From a652bfe9f0334f42dd65bc35a922f869e7e8b0fd Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 7 May 2024 14:01:00 -0400 Subject: [PATCH 001/216] Fix an error related to an easter egg, plus some warnings. --- assets | 2 +- source/funkin/play/GameOverSubState.hx | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/assets b/assets index fe52d20de7..ff24bb59b5 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit fe52d20de7025d90cadb429dbdedf6d986727088 +Subproject commit ff24bb59b5382677277ae427a164ea4764409f5c diff --git a/source/funkin/play/GameOverSubState.hx b/source/funkin/play/GameOverSubState.hx index e7b128385a..c3abbcf3e2 100644 --- a/source/funkin/play/GameOverSubState.hx +++ b/source/funkin/play/GameOverSubState.hx @@ -83,6 +83,8 @@ class GameOverSubState extends MusicBeatSubState var isChartingMode:Bool = false; + var mustNotExit:Bool = false; + var transparent:Bool; static final CAMERA_ZOOM_DURATION:Float = 0.5; @@ -240,7 +242,7 @@ class GameOverSubState extends MusicBeatSubState } // KEYBOARD ONLY: Return to the menu when pressing the assigned key. - if (controls.BACK) + if (controls.BACK && !mustNotExit) { blueballed = false; PlayState.instance.deathCounter = 0; From 7ff37ae0c22f8fa38bf4b04bad43d21cab85a35a Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 7 May 2024 14:21:22 -0400 Subject: [PATCH 002/216] Fix a conflict between a shader variable name and a function on some graphics cards. --- source/funkin/graphics/shaders/StrokeShader.hx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/funkin/graphics/shaders/StrokeShader.hx b/source/funkin/graphics/shaders/StrokeShader.hx index fd133ac0a6..d110e7de94 100644 --- a/source/funkin/graphics/shaders/StrokeShader.hx +++ b/source/funkin/graphics/shaders/StrokeShader.hx @@ -40,8 +40,8 @@ class StrokeShader extends FlxShader void main() { - vec4 sample = flixel_texture2D(bitmap, openfl_TextureCoordv); - if (sample.a == 0.) { + vec4 gay = flixel_texture2D(bitmap, openfl_TextureCoordv); + if (gay.a == 0.) { float w = size.x / openfl_TextureSize.x; float h = size.y / openfl_TextureSize.y; @@ -49,9 +49,9 @@ class StrokeShader extends FlxShader || flixel_texture2D(bitmap, vec2(openfl_TextureCoordv.x - w, openfl_TextureCoordv.y)).a != 0. || flixel_texture2D(bitmap, vec2(openfl_TextureCoordv.x, openfl_TextureCoordv.y + h)).a != 0. || flixel_texture2D(bitmap, vec2(openfl_TextureCoordv.x, openfl_TextureCoordv.y - h)).a != 0.) - sample = color; + gay = color; } - gl_FragColor = sample; + gl_FragColor = gay; } ') public function new(color:FlxColor = 0xFFFFFFFF, width:Float = 1, height:Float = 1) From 5160fd02d4c21de10f40e3b6817d3ddf405c82f4 Mon Sep 17 00:00:00 2001 From: TheGalo X <88469278+TheGaloXx@users.noreply.github.com> Date: Tue, 7 May 2024 23:17:49 -0300 Subject: [PATCH 003/216] fix window tween --- source/funkin/ui/title/TitleState.hx | 1 + 1 file changed, 1 insertion(+) diff --git a/source/funkin/ui/title/TitleState.hx b/source/funkin/ui/title/TitleState.hx index 964e0eeca1..49bef5e4a4 100644 --- a/source/funkin/ui/title/TitleState.hx +++ b/source/funkin/ui/title/TitleState.hx @@ -283,6 +283,7 @@ class TitleState extends MusicBeatState if (FlxG.keys.justPressed.Y) { + FlxTween.cancelTweensOf(FlxG.stage.window, ['x', 'y']); FlxTween.tween(FlxG.stage.window, {x: FlxG.stage.window.x + 300}, 1.4, {ease: FlxEase.quadInOut, type: PINGPONG, startDelay: 0.35}); FlxTween.tween(FlxG.stage.window, {y: FlxG.stage.window.y + 100}, 0.7, {ease: FlxEase.quadInOut, type: PINGPONG}); } From e2613fa8fb4d3ab9b7f4cf110893cbb9e25ba632 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 7 May 2024 23:45:35 -0400 Subject: [PATCH 004/216] Fix an issue with an improper version of funkVis --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index c359d7a512..a6e4467a91 100644 --- a/hmm.json +++ b/hmm.json @@ -49,7 +49,7 @@ "name": "funkin.vis", "type": "git", "dir": null, - "ref": "98c9db09f0bbfedfe67a84538a5814aaef80bdea", + "ref": "2aa654b974507ab51ab1724d2d97e75726fd7d78", "url": "https://github.com/FunkinCrew/funkVis" }, { From be0776010364fda81554a845461d71a2ad4a16a1 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 8 May 2024 00:08:44 -0400 Subject: [PATCH 005/216] Fix a crash when querying FlxG.state --- source/funkin/util/logging/CrashHandler.hx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/funkin/util/logging/CrashHandler.hx b/source/funkin/util/logging/CrashHandler.hx index 8cfa2270fa..71d1ad3942 100644 --- a/source/funkin/util/logging/CrashHandler.hx +++ b/source/funkin/util/logging/CrashHandler.hx @@ -141,7 +141,9 @@ class CrashHandler fullContents += '\n'; - fullContents += 'Flixel Current State: ${Type.getClassName(Type.getClass(FlxG.state))}\n'; + var currentState = FlxG.state != null ? Type.getClassName(Type.getClass(FlxG.state)) : 'No state loaded'; + + fullContents += 'Flixel Current State: ${currentState}\n'; fullContents += '\n'; From cfeca56634628a7cbaff085df62eafa9c193961d Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 7 May 2024 14:01:00 -0400 Subject: [PATCH 006/216] Fix an error related to an easter egg, plus some warnings. --- source/funkin/play/GameOverSubState.hx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/funkin/play/GameOverSubState.hx b/source/funkin/play/GameOverSubState.hx index e7b128385a..c3abbcf3e2 100644 --- a/source/funkin/play/GameOverSubState.hx +++ b/source/funkin/play/GameOverSubState.hx @@ -83,6 +83,8 @@ class GameOverSubState extends MusicBeatSubState var isChartingMode:Bool = false; + var mustNotExit:Bool = false; + var transparent:Bool; static final CAMERA_ZOOM_DURATION:Float = 0.5; @@ -240,7 +242,7 @@ class GameOverSubState extends MusicBeatSubState } // KEYBOARD ONLY: Return to the menu when pressing the assigned key. - if (controls.BACK) + if (controls.BACK && !mustNotExit) { blueballed = false; PlayState.instance.deathCounter = 0; From 2743a853bcaf87e0ecc908ca232ce748e12deabc Mon Sep 17 00:00:00 2001 From: Burgerballs <107233412+Burgerballs@users.noreply.github.com> Date: Wed, 8 May 2024 06:03:12 +0100 Subject: [PATCH 007/216] Fix some spaghetti on PlayAnimationSongEvent --- .../play/event/PlayAnimationSongEvent.hx | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/source/funkin/play/event/PlayAnimationSongEvent.hx b/source/funkin/play/event/PlayAnimationSongEvent.hx index 4e6669479c..4ced26b2d2 100644 --- a/source/funkin/play/event/PlayAnimationSongEvent.hx +++ b/source/funkin/play/event/PlayAnimationSongEvent.hx @@ -31,25 +31,13 @@ class PlayAnimationSongEvent extends SongEvent switch (targetName) { - case 'boyfriend': + case 'boyfriend' || 'bf' || 'player': trace('Playing animation $anim on boyfriend.'); target = PlayState.instance.currentStage.getBoyfriend(); - case 'bf': - trace('Playing animation $anim on boyfriend.'); - target = PlayState.instance.currentStage.getBoyfriend(); - case 'player': - trace('Playing animation $anim on boyfriend.'); - target = PlayState.instance.currentStage.getBoyfriend(); - case 'dad': + case 'dad' || 'opponent': trace('Playing animation $anim on dad.'); target = PlayState.instance.currentStage.getDad(); - case 'opponent': - trace('Playing animation $anim on dad.'); - target = PlayState.instance.currentStage.getDad(); - case 'girlfriend': - trace('Playing animation $anim on girlfriend.'); - target = PlayState.instance.currentStage.getGirlfriend(); - case 'gf': + case 'girlfriend' || 'gf': trace('Playing animation $anim on girlfriend.'); target = PlayState.instance.currentStage.getGirlfriend(); default: From 000e256b0e6e5d65d96f84fc7a18bfaba507d5d2 Mon Sep 17 00:00:00 2001 From: codist <50346006+ImCodist@users.noreply.github.com> Date: Wed, 8 May 2024 01:20:39 -0400 Subject: [PATCH 008/216] Fixed an issue where hold note would be invisible for a single frame. --- source/funkin/play/notes/Strumline.hx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/funkin/play/notes/Strumline.hx b/source/funkin/play/notes/Strumline.hx index 6a18f17d5b..95e0668be2 100644 --- a/source/funkin/play/notes/Strumline.hx +++ b/source/funkin/play/notes/Strumline.hx @@ -576,6 +576,8 @@ class Strumline extends FlxSpriteGroup note.holdNoteSprite.hitNote = true; note.holdNoteSprite.missedNote = false; note.holdNoteSprite.alpha = 1.0; + + note.holdNoteSprite.sustainLength = (note.holdNoteSprite.strumTime + note.holdNoteSprite.fullSustainLength) - conductorInUse.songPosition; } } From 2e74678cafbc0d44559c2eb85b6847dd8cb8e249 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 8 May 2024 01:54:48 -0400 Subject: [PATCH 009/216] Fix an issue where the Freeplay menu never displays 100% clear. --- source/funkin/ui/freeplay/FreeplayState.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 7b7543845a..5960795eac 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -733,8 +733,8 @@ class FreeplayState extends MusicBeatSubState } } - lerpScore = MathUtil.coolLerp(lerpScore, intendedScore, 0.2); - lerpCompletion = MathUtil.coolLerp(lerpCompletion, intendedCompletion, 0.9); + lerpScore = MathUtil.smoothLerp(lerpScore, intendedScore, elapsed, 0.5); + lerpCompletion = MathUtil.smoothLerp(lerpCompletion, intendedCompletion, elapsed, 0.5); if (Math.isNaN(lerpScore)) { From 4e5531744a1e7ee2023725badfabc2219e3ac4a0 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 8 May 2024 03:23:00 -0400 Subject: [PATCH 010/216] Curse you burgerballs --- source/funkin/play/event/PlayAnimationSongEvent.hx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/funkin/play/event/PlayAnimationSongEvent.hx b/source/funkin/play/event/PlayAnimationSongEvent.hx index 4ced26b2d2..57240d3994 100644 --- a/source/funkin/play/event/PlayAnimationSongEvent.hx +++ b/source/funkin/play/event/PlayAnimationSongEvent.hx @@ -31,13 +31,13 @@ class PlayAnimationSongEvent extends SongEvent switch (targetName) { - case 'boyfriend' || 'bf' || 'player': + case 'boyfriend' | 'bf' | 'player': trace('Playing animation $anim on boyfriend.'); target = PlayState.instance.currentStage.getBoyfriend(); - case 'dad' || 'opponent': + case 'dad' | 'opponent': trace('Playing animation $anim on dad.'); target = PlayState.instance.currentStage.getDad(); - case 'girlfriend' || 'gf': + case 'girlfriend' | 'gf': trace('Playing animation $anim on girlfriend.'); target = PlayState.instance.currentStage.getGirlfriend(); default: From b49fac742f0ce72386ed3dedec6efad0385de164 Mon Sep 17 00:00:00 2001 From: codist <50346006+ImCodist@users.noreply.github.com> Date: Wed, 8 May 2024 04:21:30 -0400 Subject: [PATCH 011/216] Fixed stutter once a transition to the main menu completes. --- source/funkin/ui/mainmenu/MainMenuState.hx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index 466dbbb904..7a21a6e8f5 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -139,10 +139,6 @@ class MainMenuState extends MusicBeatState resetCamStuff(); - subStateClosed.add(_ -> { - resetCamStuff(); - }); - subStateOpened.add(sub -> { if (Type.getClass(sub) == FreeplayState) { From 6fdc090eccdeab76503918b4810c42114bbbaab5 Mon Sep 17 00:00:00 2001 From: nebulazorua Date: Wed, 8 May 2024 19:53:47 +0800 Subject: [PATCH 012/216] i have accidentally done this and wiped out my chart many times --- source/funkin/play/PlayState.hx | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 44ad819c41..c5f76710e6 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -2549,12 +2549,20 @@ class PlayState extends MusicBeatSubState // Redirect to the chart editor playing the current song. if (controls.DEBUG_CHART) { - disableKeys = true; - persistentUpdate = false; - FlxG.switchState(() -> new ChartEditorState( - { - targetSongId: currentSong.id, - })); + if (isChartingMode) + { + if (FlxG.sound.music != null) FlxG.sound.music.pause(); // Don't reset song position! + PlayState.instance.close(); // This only works because PlayState is a substate! + } + else + { + disableKeys = true; + persistentUpdate = false; + FlxG.switchState(() -> new ChartEditorState( + { + targetSongId: currentSong.id, + })); + } } #end From f5143c2d7859ef51912155243b7411f1ad6d8c1d Mon Sep 17 00:00:00 2001 From: nebulazorua Date: Wed, 8 May 2024 19:56:13 +0800 Subject: [PATCH 013/216] this is better --- source/funkin/play/PlayState.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index c5f76710e6..0ba4e17ec9 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -2552,7 +2552,7 @@ class PlayState extends MusicBeatSubState if (isChartingMode) { if (FlxG.sound.music != null) FlxG.sound.music.pause(); // Don't reset song position! - PlayState.instance.close(); // This only works because PlayState is a substate! + this.close(); // This only works because PlayState is a substate! } else { From 2eaea3cdc556928cc359fec446fa656386cd135c Mon Sep 17 00:00:00 2001 From: nebulazorua Date: Wed, 8 May 2024 20:26:17 +0800 Subject: [PATCH 014/216] Apply judgements through a seperate function to applyScore Also adds more to the HitNoteScriptEvent, such as the noteDiff and also isComboBreak. noteDiff is important as it lets you create stuff like notes with reduced hitboxes (i.e mines/"hurt notes") or millisecond hit displays. isComboBreak lets you set whether the judge combo broke, so you could in theory create custom judgements in scripts now with these changes (killer reimplementation in scripts? more likely than you'd think!) --- source/funkin/modding/events/ScriptEvent.hx | 17 +++- source/funkin/play/PlayState.hx | 91 ++++++++----------- .../ui/debug/charting/ChartEditorState.hx | 2 +- 3 files changed, 55 insertions(+), 55 deletions(-) diff --git a/source/funkin/modding/events/ScriptEvent.hx b/source/funkin/modding/events/ScriptEvent.hx index 8d625290d3..ece7870fd7 100644 --- a/source/funkin/modding/events/ScriptEvent.hx +++ b/source/funkin/modding/events/ScriptEvent.hx @@ -140,16 +140,29 @@ class HitNoteScriptEvent extends NoteScriptEvent */ public var score:Int; - public function new(note:NoteSprite, healthChange:Float, score:Int, judgement:String, comboCount:Int = 0):Void + /** + * Whether the judgement caused a combo break. + */ + public var isComboBreak:Bool = false; + + /** + * The time difference when the player hit the note + */ + public var hitDiff:Float = 0; + + public function new(note:NoteSprite, healthChange:Float, score:Int, judgement:String, isComboBreak:Bool, comboCount:Int = 0, hitDiff:Float = 0):Void { super(NOTE_HIT, note, healthChange, comboCount, true); this.score = score; this.judgement = judgement; + this.isComboBreak = isComboBreak; + this.hitDiff = hitDiff; } public override function toString():String { - return 'HitNoteScriptEvent(note=' + note + ', comboCount=' + comboCount + ', judgement=' + judgement + ', score=' + score + ')'; + return 'HitNoteScriptEvent(note=' + note + ', comboCount=' + comboCount + ', judgement=' + judgement + ', score=' + score + ', isComboBreak=' + + isComboBreak + ', hitDiff=' + hitDiff + ')'; } } diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 0ba4e17ec9..8ba48a1b57 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -2080,7 +2080,8 @@ class PlayState extends MusicBeatSubState // Call an event to allow canceling the note hit. // NOTE: This is what handles the character animations! - var event:NoteScriptEvent = new HitNoteScriptEvent(note, 0.0, 0, 'perfect', 0); + + var event:NoteScriptEvent = new HitNoteScriptEvent(note, 0.0, 0, 'perfect', false, 0); dispatchEvent(event); // Calling event.cancelEvent() skips all the other logic! Neat! @@ -2176,7 +2177,7 @@ class PlayState extends MusicBeatSubState // Call an event to allow canceling the note hit. // NOTE: This is what handles the character animations! - var event:NoteScriptEvent = new HitNoteScriptEvent(note, 0.0, 0, 'perfect', 0); + var event:NoteScriptEvent = new HitNoteScriptEvent(note, 0.0, 0, 'perfect', false, 0); dispatchEvent(event); // Calling event.cancelEvent() skips all the other logic! Neat! @@ -2381,27 +2382,40 @@ class PlayState extends MusicBeatSubState var daRating = Scoring.judgeNote(noteDiff, PBOT1); var healthChange = 0.0; + var isComboBreak = false; switch (daRating) { case 'sick': healthChange = Constants.HEALTH_SICK_BONUS; + isComboBreak = Constants.JUDGEMENT_SICK_COMBO_BREAK; case 'good': healthChange = Constants.HEALTH_GOOD_BONUS; + isComboBreak = Constants.JUDGEMENT_GOOD_COMBO_BREAK; case 'bad': healthChange = Constants.HEALTH_BAD_BONUS; + isComboBreak = Constants.JUDGEMENT_BAD_COMBO_BREAK; case 'shit': + isComboBreak = Constants.JUDGEMENT_SHIT_COMBO_BREAK; healthChange = Constants.HEALTH_SHIT_BONUS; } // Send the note hit event. - var event:HitNoteScriptEvent = new HitNoteScriptEvent(note, healthChange, score, daRating, Highscore.tallies.combo + 1); + var event:HitNoteScriptEvent = new HitNoteScriptEvent(note, healthChange, score, daRating, isComboBreak, Highscore.tallies.combo + 1, noteDiff); dispatchEvent(event); // Calling event.cancelEvent() skips all the other logic! Neat! if (event.eventCanceled) return; + Highscore.tallies.totalNotesHit++; + // Display the hit on the strums + playerStrumline.hitNote(note, !isComboBreak); + if (daRating == 'sick') playerStrumline.playNoteSplash(note.noteData.getDirection()); + if (note.isHoldNote && note.holdNoteSprite != null) playerStrumline.playNoteHoldCover(note.holdNoteSprite); + vocals.playerVolume = 1; + // Display the combo meter and add the calculation to the score. - popUpScore(note, event.score, event.judgement, event.healthChange); + applyScore(event.score, event.judgement, event.healthChange, event.isComboBreak); + popUpScore(event.judgement); } /** @@ -2412,9 +2426,6 @@ class PlayState extends MusicBeatSubState { // If we are here, we already CALLED the onNoteMiss script hook! - health += healthChange; - songScore -= 10; - if (!isPracticeMode) { // messy copy paste rn lol @@ -2454,14 +2465,9 @@ class PlayState extends MusicBeatSubState } vocals.playerVolume = 0; - Highscore.tallies.missed++; + if (Highscore.tallies.combo != 0) if (Highscore.tallies.combo >= 10) comboPopUps.displayCombo(0); - if (Highscore.tallies.combo != 0) - { - // Break the combo. - if (Highscore.tallies.combo >= 10) comboPopUps.displayCombo(0); - Highscore.tallies.combo = 0; - } + applyScore(-10, 'miss', healthChange, true); if (playSound) { @@ -2593,46 +2599,24 @@ class PlayState extends MusicBeatSubState } /** - * Handles health, score, and rating popups when a note is hit. + * Handles applying health, score, and ratings. */ - function popUpScore(daNote:NoteSprite, score:Int, daRating:String, healthChange:Float):Void + function applyScore(score:Int, daRating:String, healthChange:Float, isComboBreak:Bool) { - if (daRating == 'miss') - { - // If daRating is 'miss', that means we made a mistake and should not continue. - FlxG.log.warn('popUpScore judged a note as a miss!'); - // TODO: Remove this. - // comboPopUps.displayRating('miss'); - return; - } - - vocals.playerVolume = 1; - - var isComboBreak = false; switch (daRating) { case 'sick': Highscore.tallies.sick += 1; - Highscore.tallies.totalNotesHit++; - isComboBreak = Constants.JUDGEMENT_SICK_COMBO_BREAK; case 'good': Highscore.tallies.good += 1; - Highscore.tallies.totalNotesHit++; - isComboBreak = Constants.JUDGEMENT_GOOD_COMBO_BREAK; case 'bad': Highscore.tallies.bad += 1; - Highscore.tallies.totalNotesHit++; - isComboBreak = Constants.JUDGEMENT_BAD_COMBO_BREAK; case 'shit': Highscore.tallies.shit += 1; - Highscore.tallies.totalNotesHit++; - isComboBreak = Constants.JUDGEMENT_SHIT_COMBO_BREAK; - default: - FlxG.log.error('Wuh? Buh? Guh? Note hit judgement was $daRating!'); + case 'miss': + Highscore.tallies.missed += 1; } - health += healthChange; - if (isComboBreak) { // Break the combo, but don't increment tallies.misses. @@ -2644,15 +2628,23 @@ class PlayState extends MusicBeatSubState Highscore.tallies.combo++; if (Highscore.tallies.combo > Highscore.tallies.maxCombo) Highscore.tallies.maxCombo = Highscore.tallies.combo; } + songScore += score; + } - playerStrumline.hitNote(daNote, !isComboBreak); - - if (daRating == 'sick') + /** + * Handles rating popups when a note is hit. + */ + function popUpScore(daRating:String, ?combo:Int):Void + { + if (daRating == 'miss') { - playerStrumline.playNoteSplash(daNote.noteData.getDirection()); + // If daRating is 'miss', that means we made a mistake and should not continue. + FlxG.log.warn('popUpScore judged a note as a miss!'); + // TODO: Remove this. + // comboPopUps.displayRating('miss'); + return; } - - songScore += score; + if (combo == null) combo = Highscore.tallies.combo; if (!isPracticeMode) { @@ -2692,12 +2684,7 @@ class PlayState extends MusicBeatSubState } } comboPopUps.displayRating(daRating); - if (Highscore.tallies.combo >= 10 || Highscore.tallies.combo == 0) comboPopUps.displayCombo(Highscore.tallies.combo); - - if (daNote.isHoldNote && daNote.holdNoteSprite != null) - { - playerStrumline.playNoteHoldCover(daNote.holdNoteSprite); - } + if (combo >= 10 || combo == 0) comboPopUps.displayCombo(combo); vocals.playerVolume = 1; } diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index b75cd8bf1f..d28ca87d59 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -6304,7 +6304,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState var tempNote:NoteSprite = new NoteSprite(NoteStyleRegistry.instance.fetchDefault()); tempNote.noteData = noteData; tempNote.scrollFactor.set(0, 0); - var event:NoteScriptEvent = new HitNoteScriptEvent(tempNote, 0.0, 0, 'perfect', 0); + var event:NoteScriptEvent = new HitNoteScriptEvent(tempNote, 0.0, 0, 'perfect', false, 0); dispatchEvent(event); // Calling event.cancelEvent() skips all the other logic! Neat! From 4b500f78e19218e33c65b693f1d928195d75efef Mon Sep 17 00:00:00 2001 From: nebulazorua Date: Wed, 8 May 2024 20:30:47 +0800 Subject: [PATCH 015/216] Revert change because i forgot to do it in a new branch oriignally lol --- source/funkin/play/PlayState.hx | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 8ba48a1b57..cdd8c7d71c 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -2555,20 +2555,12 @@ class PlayState extends MusicBeatSubState // Redirect to the chart editor playing the current song. if (controls.DEBUG_CHART) { - if (isChartingMode) - { - if (FlxG.sound.music != null) FlxG.sound.music.pause(); // Don't reset song position! - this.close(); // This only works because PlayState is a substate! - } - else - { - disableKeys = true; - persistentUpdate = false; - FlxG.switchState(() -> new ChartEditorState( - { - targetSongId: currentSong.id, - })); - } + disableKeys = true; + persistentUpdate = false; + FlxG.switchState(() -> new ChartEditorState( + { + targetSongId: currentSong.id, + })); } #end From d4f113df59d71fd20ebd49ecadc2bad3cbf4fe8c Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 7 May 2024 14:21:22 -0400 Subject: [PATCH 016/216] Fix a conflict between a shader variable name and a function on some graphics cards. --- source/funkin/graphics/shaders/StrokeShader.hx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/funkin/graphics/shaders/StrokeShader.hx b/source/funkin/graphics/shaders/StrokeShader.hx index fd133ac0a6..d110e7de94 100644 --- a/source/funkin/graphics/shaders/StrokeShader.hx +++ b/source/funkin/graphics/shaders/StrokeShader.hx @@ -40,8 +40,8 @@ class StrokeShader extends FlxShader void main() { - vec4 sample = flixel_texture2D(bitmap, openfl_TextureCoordv); - if (sample.a == 0.) { + vec4 gay = flixel_texture2D(bitmap, openfl_TextureCoordv); + if (gay.a == 0.) { float w = size.x / openfl_TextureSize.x; float h = size.y / openfl_TextureSize.y; @@ -49,9 +49,9 @@ class StrokeShader extends FlxShader || flixel_texture2D(bitmap, vec2(openfl_TextureCoordv.x - w, openfl_TextureCoordv.y)).a != 0. || flixel_texture2D(bitmap, vec2(openfl_TextureCoordv.x, openfl_TextureCoordv.y + h)).a != 0. || flixel_texture2D(bitmap, vec2(openfl_TextureCoordv.x, openfl_TextureCoordv.y - h)).a != 0.) - sample = color; + gay = color; } - gl_FragColor = sample; + gl_FragColor = gay; } ') public function new(color:FlxColor = 0xFFFFFFFF, width:Float = 1, height:Float = 1) From 4d1c2c1b8841bdf95ea6107298b3632be86334c1 Mon Sep 17 00:00:00 2001 From: MadBear422 Date: Wed, 8 May 2024 15:30:40 -0700 Subject: [PATCH 017/216] Character selection fix for chart editor. --- .../charting/dialogs/ChartEditorCharacterIconSelectorMenu.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/debug/charting/dialogs/ChartEditorCharacterIconSelectorMenu.hx b/source/funkin/ui/debug/charting/dialogs/ChartEditorCharacterIconSelectorMenu.hx index eb60cb6db2..1edbb6c004 100644 --- a/source/funkin/ui/debug/charting/dialogs/ChartEditorCharacterIconSelectorMenu.hx +++ b/source/funkin/ui/debug/charting/dialogs/ChartEditorCharacterIconSelectorMenu.hx @@ -67,7 +67,7 @@ class ChartEditorCharacterIconSelectorMenu extends ChartEditorBaseMenu var charGrid = new Grid(); charGrid.columns = 5; - charGrid.width = 100; + charGrid.width = this.width; charSelectScroll.addComponent(charGrid); var charIds:Array = CharacterDataParser.listCharacterIds(); From df5bdc7b7db18335a08dab6418c4c193973b7a45 Mon Sep 17 00:00:00 2001 From: codist <50346006+ImCodist@users.noreply.github.com> Date: Wed, 8 May 2024 04:21:30 -0400 Subject: [PATCH 018/216] Fixed stutter once a transition to the main menu completes. --- source/funkin/ui/mainmenu/MainMenuState.hx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index 466dbbb904..7a21a6e8f5 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -139,10 +139,6 @@ class MainMenuState extends MusicBeatState resetCamStuff(); - subStateClosed.add(_ -> { - resetCamStuff(); - }); - subStateOpened.add(sub -> { if (Type.getClass(sub) == FreeplayState) { From 54fbb9a29440791c2a5ac80b48ab8e0070c3a9d9 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 8 May 2024 22:45:13 -0400 Subject: [PATCH 019/216] be careful with these gitmodules, we don't want to work out of funkin.art or funkin.assets --- .gitmodules | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index be5e0aaa81..452c0089b7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "assets"] path = assets - url = https://github.com/FunkinCrew/funkin.assets + url = https://github.com/FunkinCrew/Funkin-Assets-secret [submodule "art"] path = art - url = https://github.com/FunkinCrew/funkin.art + url = https://github.com/FunkinCrew/Funkin-Art-secret From 928b3c4119abba963aec6b48cc139ba0e6e7677e Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 8 May 2024 23:29:55 -0400 Subject: [PATCH 020/216] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index ff24bb59b5..962130b224 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit ff24bb59b5382677277ae427a164ea4764409f5c +Subproject commit 962130b2243a839106607d08a11599b1857bf8b3 From 4fdc437840949f4558b82b64cc06412c952d27c5 Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 8 May 2024 23:55:19 -0400 Subject: [PATCH 021/216] Update Funkin' Debug Hotkeys.md --- docs/Funkin' Debug Hotkeys.md | 48 +++++++++++++++++------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/docs/Funkin' Debug Hotkeys.md b/docs/Funkin' Debug Hotkeys.md index c560c54222..1287d5a1bf 100644 --- a/docs/Funkin' Debug Hotkeys.md +++ b/docs/Funkin' Debug Hotkeys.md @@ -1,31 +1,31 @@ # Funkin' Debug Hotkeys -`F4` (EVERYWHERE) - Leave Current State and move to Main Menu -`F5` (EVERYWHERE) - Hot Reload Data Files +Most of this functionality is only available on debug builds of the game! -`Y` (Title Screen) - WOAH +## Any State +- `F2`: ***OVERLAY***: Enables the Flixel debug overlay, which has partial support for scripting. +- `F3`: ***SCREENSHOT***: Takes a screenshot of the game and saves it to the local `screenshots` directory. Works outside of debug builds too! +- `F4`: ***EJECT***: Forcibly switch state to the Main Menu (with no extra transition). Useful if you're stuck in a level and you need to get out! +- `F5`: ***HOT RELOAD***: Forcibly reload the game's scripts and data files, then restart the current state. If any files in the `assets` folder have been modified, the game should process the changes for you! NOTE: Known bug, this does not reset song charts or song scripts, but it should reset everything else (such as stage layout data and character animation data). +- `CTRL-SHIFT-L`: ***FORCE CRASH***: Immediately crash the game with a detailed crash log and a stack trace. -`~` (Main Menu) - Access Debug Menu +## **Play State** +- `H`: ***HIDE UI***: Makes the user interface invisible. Works in Pause Menu, great for screenshots. +- `1`: ***END SONG***: Immediately ends the song and moves to Results Screen on Freeplay, or next song on Story Mode. +- `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. -`U` (Play) - Open Stage Editor State -`H` (Play) - Show/Hide HUD -`1` (Play) - End Song -`2` (Play) - Add 10% Health -`3` (Play) - Subtract 5% Health -`7` (Play) - (NOT WORKING) Open Chart Editor -`8` (Play) - Open Animation Editor -`9` (Play) - (Easter Egg) Classic Health Icon -`PGUP`/`Fn+Up` (Play) - Skip Forward In Time -`PGDN`/`Fn+Down` (Play) - 🦃 That's right, we're going to go BACK IN TIME +## **Freeplay State** +- `F` (Freeplay Menu) - Move to Favorites +- `Q` (Freeplay Menu) - Back one category +- `E` (Freeplay Menu) - Forward one category -`F` (Freeplay Menu) - Move to Favorites -`P` (Freeplay Menu) - Switch to Pico (probably doesn't work) -`T` (Freeplay Menu) - Start typing in search bar -`Q` (Freeplay Menu) - Back one letter -`E` (Freeplay Menu) - Forward one letter +## **Title State** +- `Y` - WOAH -`Arrows` (Stage Editor) - Move Prop -`Ctrl-Z` (Stage Editor) - Undo -`Y` (Stage Editor) - Leave Stage Editor - -`H` (Pause Menu) - Hide the Pause Menu UI (good for screenshots!) +## **Main 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 2e4baa8ab2cc3cea56ba5e235541740348628cce Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 9 May 2024 00:43:33 -0400 Subject: [PATCH 022/216] Fix a null object reference caused by accessing cut assets. --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 962130b224..783f22e741 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 962130b2243a839106607d08a11599b1857bf8b3 +Subproject commit 783f22e741c85223da7f3f815b28fc4c6f240cbc From 4d5c0444c834ad16637d1912f096b733a76152e5 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 9 May 2024 00:46:21 -0400 Subject: [PATCH 023/216] Fix an issue where control binds would be duplicated and quickly multiply. --- source/funkin/input/Controls.hx | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/source/funkin/input/Controls.hx b/source/funkin/input/Controls.hx index 1983d413ba..548e4edfae 100644 --- a/source/funkin/input/Controls.hx +++ b/source/funkin/input/Controls.hx @@ -527,6 +527,14 @@ class Controls extends FlxActionSet action.inputs[i].inputID = toAdd; } hasReplaced = true; + } else if (input.device == KEYBOARD && input.inputID == toAdd) { + // This key is already bound! + if (hasReplaced) { + // Remove the duplicate keybind, don't replace. + action.inputs.remove(input); + } else { + hasReplaced = true; + } } } @@ -989,6 +997,7 @@ class Controls extends FlxActionSet for (control in Control.createAll()) { var inputs:Array = Reflect.field(data, control.getName()); + inputs = inputs.unique(); if (inputs != null) { if (inputs.length == 0) { @@ -1038,7 +1047,11 @@ class Controls extends FlxActionSet var inputs = getInputsFor(control, device); isEmpty = isEmpty && inputs.length == 0; - if (inputs.length == 0) inputs = [FlxKey.NONE]; + if (inputs.length == 0) { + inputs = [FlxKey.NONE]; + } else { + inputs = inputs.unique(); + } Reflect.setField(data, control.getName(), inputs); } From bfaa4626f88be1deb3a5af85c2939e3a351b150a Mon Sep 17 00:00:00 2001 From: codist <50346006+ImCodist@users.noreply.github.com> Date: Thu, 9 May 2024 01:10:53 -0400 Subject: [PATCH 024/216] Polish for the transition from GameOverSubState back into PlayState. --- source/funkin/play/PlayState.hx | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 44ad819c41..8903a4e638 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -826,6 +826,8 @@ class PlayState extends MusicBeatSubState resetCamera(); + var fromDeathState = isPlayerDying; + persistentUpdate = true; persistentDraw = true; @@ -863,8 +865,11 @@ class PlayState extends MusicBeatSubState if (currentStage != null) currentStage.resetStage(); - playerStrumline.vwooshNotes(); - opponentStrumline.vwooshNotes(); + if (!fromDeathState) + { + playerStrumline.vwooshNotes(); + opponentStrumline.vwooshNotes(); + } playerStrumline.clean(); opponentStrumline.clean(); @@ -1075,6 +1080,22 @@ class PlayState extends MusicBeatSubState function moveToGameOver():Void { + // Reset and update a bunch of values in advance for the transition back from the game over substate. + playerStrumline.clean(); + opponentStrumline.clean(); + + songScore = 0; + updateScoreText(); + + health = Constants.HEALTH_STARTING; + healthLerp = health; + + healthBar.value = healthLerp; + + iconP1.updatePosition(); + iconP2.updatePosition(); + + // Transition to the game over substate. var gameOverSubState = new GameOverSubState( { isChartingMode: isChartingMode, From 1b6febf01c9a7826ec65004d3d4e46780792116f Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 18 Apr 2024 20:23:03 -0400 Subject: [PATCH 025/216] initial freeplay songs loading --- Project.xml | 1 + checkstyle.json | 2 +- hmm.json | 9 +- source/funkin/Paths.hx | 20 ++++- source/funkin/audio/FunkinSound.hx | 95 ++++++++++++++++++++-- source/funkin/ui/freeplay/FreeplayState.hx | 23 +++--- 6 files changed, 126 insertions(+), 24 deletions(-) diff --git a/Project.xml b/Project.xml index fcfcfb9f35..87608bb88b 100644 --- a/Project.xml +++ b/Project.xml @@ -126,6 +126,7 @@ + diff --git a/checkstyle.json b/checkstyle.json index dc89409da9..41f0a79986 100644 --- a/checkstyle.json +++ b/checkstyle.json @@ -79,7 +79,7 @@ { "props": { "ignoreExtern": true, - "format": "^[a-z][A-Z][A-Z0-9]*(_[A-Z0-9_]+)*$", + "format": "^[a-zA-Z0-9]+(?:_[a-zA-Z0-9]+)*$", "tokens": ["INLINE", "NOTINLINE"] }, "type": "ConstantName" diff --git a/hmm.json b/hmm.json index a6e4467a91..6b119c52fb 100644 --- a/hmm.json +++ b/hmm.json @@ -1,5 +1,12 @@ { "dependencies": [ + { + "name": "FlxPartialSound", + "type": "git", + "dir": null, + "ref": "main", + "url": "https://github.com/FunkinCrew/FlxPartialSound.git" + }, { "name": "discord_rpc", "type": "git", @@ -171,4 +178,4 @@ "url": "https://github.com/FunkinCrew/thx.semver" } ] -} +} \ No newline at end of file diff --git a/source/funkin/Paths.hx b/source/funkin/Paths.hx index 54a4b7acfa..b0a97c4faf 100644 --- a/source/funkin/Paths.hx +++ b/source/funkin/Paths.hx @@ -123,9 +123,17 @@ class Paths return 'songs:assets/songs/${song.toLowerCase()}/Voices$suffix.${Constants.EXT_SOUND}'; } - public static function inst(song:String, ?suffix:String = ''):String + /** + * Gets the path to an `Inst.mp3/ogg` song instrumental from songs:assets/songs/`song`/ + * @param song name of the song to get instrumental for + * @param suffix any suffix to add to end of song name, used for `-erect` variants usually + * @param withExtension if it should return with the audio file extension `.mp3` or `.ogg`. + * @return String + */ + public static function inst(song:String, ?suffix:String = '', ?withExtension:Bool = true):String { - return 'songs:assets/songs/${song.toLowerCase()}/Inst$suffix.${Constants.EXT_SOUND}'; + var ext:String = withExtension ? '.${Constants.EXT_SOUND}' : ''; + return 'songs:assets/songs/${song.toLowerCase()}/Inst$suffix$ext'; } public static function image(key:String, ?library:String):String @@ -153,3 +161,11 @@ class Paths return FlxAtlasFrames.fromSpriteSheetPacker(image(key, library), file('images/$key.txt', library)); } } + +enum abstract PathsFunction(String) +{ + var MUSIC; + var INST; + var VOICES; + var SOUND; +} diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index df05cc3ef6..728a06a325 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -11,7 +11,11 @@ import funkin.audio.waveform.WaveformDataParser; import funkin.data.song.SongData.SongMusicData; import funkin.data.song.SongRegistry; import funkin.util.tools.ICloneable; +import funkin.util.flixel.sound.FlxPartialSound; +import funkin.Paths.PathsFunction; import openfl.Assets; +import lime.app.Future; +import lime.app.Promise; import openfl.media.SoundMixer; #if (openfl >= "8.0.0") import openfl.utils.AssetType; @@ -342,20 +346,52 @@ class FunkinSound extends FlxSound implements ICloneable FlxG.log.warn('Tried and failed to find music metadata for $key'); } } + var pathsFunction = params.pathsFunction ?? MUSIC; + var pathToUse = switch (pathsFunction) + { + case MUSIC: Paths.music('$key/$key'); + case INST: Paths.inst('$key'); + default: Paths.music('$key/$key'); + } - var music = FunkinSound.load(Paths.music('$key/$key'), params?.startingVolume ?? 1.0, params.loop ?? true, false, true); - if (music != null) + var shouldLoadPartial = params.partialParams?.loadPartial ?? false; + + if (shouldLoadPartial) { - FlxG.sound.music = music; + var music = FunkinSound.loadPartial(pathToUse, params.partialParams?.start ?? 0, params.partialParams?.end ?? 1, params?.startingVolume ?? 1.0, + params.loop ?? true, false, true); - // Prevent repeat update() and onFocus() calls. - FlxG.sound.list.remove(FlxG.sound.music); + if (music != null) + { + music.onComplete(function(partialMusic:Null) { + @:nullSafety(Off) + FlxG.sound.music = partialMusic; + FlxG.sound.list.remove(FlxG.sound.music); + }); - return true; + return true; + } + else + { + return false; + } } else { - return false; + var music = FunkinSound.load(pathToUse, params?.startingVolume ?? 1.0, params.loop ?? true, false, true); + if (music != null) + { + FlxG.sound.music = music; + + // Prevent repeat update() and onFocus() calls. + FlxG.sound.list.remove(FlxG.sound.music); + + return true; + } + else + { + return false; + } } } @@ -415,6 +451,36 @@ class FunkinSound extends FlxSound implements ICloneable return sound; } + /** + * Will load a section of a sound file, useful for Freeplay where we don't want to load all the bytes of a song + * @param path The path to the sound file + * @param start The start time of the sound file + * @param end The end time of the sound file + * @param volume Volume to start at + * @param looped Whether the sound file should loop + * @param autoDestroy Whether the sound file should be destroyed after it finishes playing + * @param autoPlay Whether the sound file should play immediately + * @return A FunkinSound object + */ + public static function loadPartial(path:String, start:Float = 0, end:Float = 1, volume:Float = 1.0, looped:Bool = false, autoDestroy:Bool = false, + autoPlay:Bool = true, ?onComplete:Void->Void, ?onLoad:Void->Void):Future> + { + var promise:lime.app.Promise> = new lime.app.Promise>(); + + // split the path and get only after first : + // we are bypassing the openfl/lime asset library fuss + path = Paths.stripLibrary(path); + + var soundRequest = FlxPartialSound.partialLoadFromFile(path, start, end); + + soundRequest.onComplete(function(partialSound) { + var snd = FunkinSound.load(partialSound, volume, looped, autoDestroy, autoPlay, onComplete, onLoad); + promise.complete(snd); + }); + + return promise.future; + } + @:nullSafety(Off) public override function destroy():Void { @@ -498,4 +564,19 @@ typedef FunkinSoundPlayMusicParams = * @default `true` */ var ?mapTimeChanges:Bool; + + /** + * Which Paths function to use to load a song + * @default `MUSIC` + */ + var ?pathsFunction:PathsFunction; + + var ?partialParams:PartialSoundParams; +} + +typedef PartialSoundParams = +{ + var loadPartial:Bool; + var start:Float; + var end:Float; } diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 7b7543845a..c290e65534 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1244,22 +1244,19 @@ class FreeplayState extends MusicBeatSubState else { // TODO: Stream the instrumental of the selected song? - var didReplace:Bool = FunkinSound.playMusic('freakyMenu', + FunkinSound.playMusic(daSongCapsule.songData.songId, { - startingVolume: 0.0, + startingVolume: 0.5, overrideExisting: true, - restartTrack: false + restartTrack: false, + pathsFunction: INST, + partialParams: + { + loadPartial: true, + start: 0, + end: 0.1 + } }); - if (didReplace) - { - FunkinSound.playMusic('freakyMenu', - { - startingVolume: 0.0, - overrideExisting: true, - restartTrack: false - }); - FlxG.sound.music.fadeIn(2, 0, 0.8); - } } grpCapsules.members[curSelected].selected = true; } From f2a06ad37b79c76566ab62f8244a84ac864155a0 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 9 May 2024 01:56:52 -0400 Subject: [PATCH 026/216] fading in and erect track loading --- source/funkin/audio/FunkinSound.hx | 14 ++++++++++++-- source/funkin/ui/freeplay/FreeplayState.hx | 9 +++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index 728a06a325..5a49e29eea 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -347,10 +347,11 @@ class FunkinSound extends FlxSound implements ICloneable } } var pathsFunction = params.pathsFunction ?? MUSIC; + var suffix = params.suffix ?? ''; var pathToUse = switch (pathsFunction) { case MUSIC: Paths.music('$key/$key'); - case INST: Paths.inst('$key'); + case INST: Paths.inst('$key', suffix); default: Paths.music('$key/$key'); } @@ -359,7 +360,7 @@ class FunkinSound extends FlxSound implements ICloneable if (shouldLoadPartial) { var music = FunkinSound.loadPartial(pathToUse, params.partialParams?.start ?? 0, params.partialParams?.end ?? 1, params?.startingVolume ?? 1.0, - params.loop ?? true, false, true); + params.loop ?? true, false, true, params.onComplete, params.onLoad); if (music != null) { @@ -541,6 +542,12 @@ typedef FunkinSoundPlayMusicParams = */ var ?startingVolume:Float; + /** + * The suffix of the music file to play. Usually for "-erect" tracks when loading an INST file + * @default `` + */ + var ?suffix:String; + /** * Whether to override music if a different track is already playing. * @default `false` @@ -572,6 +579,9 @@ typedef FunkinSoundPlayMusicParams = var ?pathsFunction:PathsFunction; var ?partialParams:PartialSoundParams; + + var ?onComplete:Void->Void; + var ?onLoad:Void->Void; } typedef PartialSoundParams = diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index c290e65534..d0183bf8e2 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1243,19 +1243,24 @@ class FreeplayState extends MusicBeatSubState } else { + var potentiallyErect:String = (currentDifficulty == "erect") || (currentDifficulty == "nightmare") ? "-erect" : ""; // TODO: Stream the instrumental of the selected song? FunkinSound.playMusic(daSongCapsule.songData.songId, { - startingVolume: 0.5, + startingVolume: 0.0, overrideExisting: true, restartTrack: false, pathsFunction: INST, + suffix: potentiallyErect, partialParams: { loadPartial: true, start: 0, end: 0.1 - } + }, + onLoad: function() { + FlxG.sound.music.fadeIn(2, 0, 0.4); + } }); } grpCapsules.members[curSelected].selected = true; From 985aa1f2a1d31c80c9887f62e35529d5a876ffc7 Mon Sep 17 00:00:00 2001 From: I Gede Hari Kresna Wiyasa Date: Thu, 9 May 2024 15:53:55 +0800 Subject: [PATCH 027/216] Added a fix guide for those with poor internet connection --- docs/COMPILING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index 7278e027c2..c5096c2f61 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -5,6 +5,7 @@ 1. Cloning the Repository: Make sure when you clone, you clone the submodules to get the assets repo: - `git clone --recurse-submodules https://github.com/FunkinCrew/funkin.git` - If you accidentally cloned without the `assets` submodule (aka didn't follow the step above), you can run `git submodule update --init --recursive` to get the assets in a foolproof way. + - During the cloning process, you may experience an error along the lines of `error: RPC failed; curl 92 HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR (err 1)` due to poor connectivity. A common fix is to run ` git config --global http.postBuffer 4096M`. 2. Install `hmm` (run `haxelib --global install hmm` and then `haxelib --global run hmm setup`) 3. Install all haxelibs of the current branch by running `hmm install` 4. Setup lime: `haxelib run lime setup` From edfde606a145e42af36eacbea826a17b663ffd90 Mon Sep 17 00:00:00 2001 From: Burgerballs <107233412+Burgerballs@users.noreply.github.com> Date: Thu, 9 May 2024 17:51:03 +0100 Subject: [PATCH 028/216] magical machine of death --- source/funkin/play/PlayState.hx | 48 +++++- .../play/event/AdditiveScrollSpeedEvent.hx | 138 ++++++++++++++++++ source/funkin/play/notes/Strumline.hx | 17 ++- source/funkin/play/notes/SustainTrail.hx | 31 +++- .../components/ChartEditorHoldNoteSprite.hx | 4 +- 5 files changed, 227 insertions(+), 11 deletions(-) create mode 100644 source/funkin/play/event/AdditiveScrollSpeedEvent.hx diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 0ba4e17ec9..0b76ec6ee2 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -236,6 +236,11 @@ class PlayState extends MusicBeatSubState */ public var cameraZoomTween:FlxTween; + /** + * An FlxTween that changes the additive speed to the desired amount. + */ + public var additiveScrollSpeedTween:FlxTween; + /** * The camera follow point from the last stage. * Used to persist the position of the `cameraFollowPosition` between levels. @@ -1179,6 +1184,11 @@ class PlayState extends MusicBeatSubState cameraZoomTween.active = false; cameraTweensPausedBySubState.add(cameraZoomTween); } + if (additiveScrollSpeedTween != null && additiveScrollSpeedTween.active) + { + additiveScrollSpeedTween.active = false; + cameraTweensPausedBySubState.add(additiveScrollSpeedTween); + } // Pause the countdown. Countdown.pauseCountdown(); @@ -3023,8 +3033,9 @@ class PlayState extends MusicBeatSubState // Stop camera zooming on beat. cameraZoomRate = 0; - // Cancel camera tweening if it's active. + // Cancel camera and scroll tweening if it's active. cancelAllCameraTweens(); + cancelAdditiveScrollSpeedTween(); // If the opponent is GF, zoom in on the opponent. // Else, if there is no GF, zoom in on BF. @@ -3244,6 +3255,41 @@ class PlayState extends MusicBeatSubState cancelCameraZoomTween(); } + /** + * The magical function that shall tween the additive scroll speed. + */ + public function tweenAdditiveScrollSpeed(?speed:Float, ?duration:Float, ?ease:NullFloat>):Void + { + // Cancel the current tween if it's active. + cancelAdditiveScrollSpeedTween(); + var strumLineTargets:Array = [ + playerStrumline.scrollSpeedAdditive + speed, + opponentStrumline.scrollSpeedAdditive + speed + ]; + + if (duration == 0) + { + playerStrumline.scrollSpeedAdditive = strumLineTargets[0]; + opponentStrumline.scrollSpeedAdditive = strumLineTargets[1]; + } + else + { + additiveScrollSpeedTween = FlxTween.tween(this, + { + "playerStrumline.scrollSpeedAdditive": strumLineTargets[0], + "opponentStrumline.scrollSpeedAdditive": strumLineTargets[1] + }, duration, {ease: ease}); + } + } + + public function cancelAdditiveScrollSpeedTween() + { + if (additiveScrollSpeedTween != null) + { + additiveScrollSpeedTween.cancel(); + } + } + #if (debug || FORCE_DEBUG_VERSION) /** * Jumps forward or backward a number of sections in the song. diff --git a/source/funkin/play/event/AdditiveScrollSpeedEvent.hx b/source/funkin/play/event/AdditiveScrollSpeedEvent.hx new file mode 100644 index 0000000000..f66f3b2571 --- /dev/null +++ b/source/funkin/play/event/AdditiveScrollSpeedEvent.hx @@ -0,0 +1,138 @@ +package funkin.play.event; + +import flixel.tweens.FlxTween; +import flixel.FlxCamera; +import flixel.tweens.FlxEase; +// Data from the chart +import funkin.data.song.SongData; +import funkin.data.song.SongData.SongEventData; +// Data from the event schema +import funkin.play.event.SongEvent; +import funkin.data.event.SongEventSchema; +import funkin.data.event.SongEventSchema.SongEventFieldType; + +/** + * This class represents a handler for scroll speed events. + * + * Example: Scroll speed change of both strums from 1x to 1.3x: + * ``` + * { + * 'e': 'AdditiveScrollSpeed', + * "v": { + * "scroll": "0.3", + * "duration": "4", + * "ease": "linear" + * } + * } + * ``` + */ +class AdditiveScrollSpeedEvent extends SongEvent +{ + public function new() + { + super('AdditiveScrollSpeed'); + } + + static final DEFAULT_SCROLL:Float = 0; + static final DEFAULT_DURATION:Float = 4.0; + static final DEFAULT_EASE:String = 'linear'; + + public override function handleEvent(data:SongEventData):Void + { + // Does nothing if there is no PlayState camera or stage. + if (PlayState.instance == null || PlayState.instance.currentStage == null) return; + + var scroll:Float = data.getFloat('scroll') ?? DEFAULT_SCROLL; + + var duration:Float = data.getFloat('duration') ?? DEFAULT_DURATION; + + var ease:String = data.getString('ease') ?? DEFAULT_EASE; + + // If it's a string, check the value. + switch (ease) + { + case 'INSTANT': + PlayState.instance.tweenAdditiveScrollSpeed(scroll, 0); + default: + var durSeconds = Conductor.instance.stepLengthMs * duration / 1000; + var easeFunction:NullFloat> = Reflect.field(FlxEase, ease); + if (easeFunction == null) + { + trace('Invalid ease function: $ease'); + return; + } + + PlayState.instance.tweenAdditiveScrollSpeed(scroll, durSeconds, easeFunction); + } + } + + public override function getTitle():String + { + return 'Additive Scroll Speed'; + } + + /** + * ``` + * { + * 'scroll': FLOAT, // Target additive scroll level. + * 'duration': FLOAT, // Duration in steps. + * 'ease': ENUM, // Easing function. + * } + * @return SongEventSchema + */ + public override function getEventSchema():SongEventSchema + { + return new SongEventSchema([ + { + name: 'scroll', + title: 'Additive Scroll Amount', + defaultValue: 0.0, + step: 0.1, + type: SongEventFieldType.FLOAT, + units: 'x' + }, + { + name: 'duration', + title: 'Duration', + defaultValue: 4.0, + step: 0.5, + type: SongEventFieldType.FLOAT, + units: 'steps' + }, + { + name: 'ease', + title: 'Easing Type', + defaultValue: 'linear', + type: SongEventFieldType.ENUM, + keys: [ + 'Linear' => 'linear', + 'Instant' => 'INSTANT', + 'Sine In' => 'sineIn', + 'Sine Out' => 'sineOut', + 'Sine In/Out' => 'sineInOut', + 'Quad In' => 'quadIn', + 'Quad Out' => 'quadOut', + 'Quad In/Out' => 'quadInOut', + 'Cube In' => 'cubeIn', + 'Cube Out' => 'cubeOut', + 'Cube In/Out' => 'cubeInOut', + 'Quart In' => 'quartIn', + 'Quart Out' => 'quartOut', + 'Quart In/Out' => 'quartInOut', + 'Quint In' => 'quintIn', + 'Quint Out' => 'quintOut', + 'Quint In/Out' => 'quintInOut', + 'Expo In' => 'expoIn', + 'Expo Out' => 'expoOut', + 'Expo In/Out' => 'expoInOut', + 'Smooth Step In' => 'smoothStepIn', + 'Smooth Step Out' => 'smoothStepOut', + 'Smooth Step In/Out' => 'smoothStepInOut', + 'Elastic In' => 'elasticIn', + 'Elastic Out' => 'elasticOut', + 'Elastic In/Out' => 'elasticInOut' + ] + } + ]); + } +} diff --git a/source/funkin/play/notes/Strumline.hx b/source/funkin/play/notes/Strumline.hx index 95e0668be2..bd0c8a1be8 100644 --- a/source/funkin/play/notes/Strumline.hx +++ b/source/funkin/play/notes/Strumline.hx @@ -52,6 +52,15 @@ class Strumline extends FlxSpriteGroup */ public var conductorInUse(get, set):Conductor; + // Used in-game to control the scroll speed within a song, for example if a song has an additive scroll speed of 1 and the base scroll speed is 1, it will be 2 - burgerballs + public var scrollSpeedAdditive:Float = 0; + public var scrollSpeed(get, never):Float; + + function get_scrollSpeed():Float + { + return (PlayState.instance?.currentChart?.scrollSpeed ?? 1.0) + scrollSpeedAdditive; + } + var _conductorInUse:Null; function get_conductorInUse():Conductor @@ -208,6 +217,11 @@ class Strumline extends FlxSpriteGroup return null; } + public function resetScrollSpeed():Void + { + scrollSpeedAdditive = 0; + } + public function getHoldNoteSprite(noteData:SongNoteData):SustainTrail { if (noteData == null || ((noteData.length ?? 0.0) <= 0.0)) return null; @@ -283,7 +297,6 @@ class Strumline extends FlxSpriteGroup // var vwoosh:Float = (strumTime < Conductor.songPosition) && vwoosh ? 2.0 : 1.0; // ^^^ commented this out... do NOT make it move faster as it moves offscreen! var vwoosh:Float = 1.0; - var scrollSpeed:Float = PlayState.instance?.currentChart?.scrollSpeed ?? 1.0; return Constants.PIXELS_PER_MS * (conductorInUse.songPosition - strumTime - Conductor.instance.inputOffset) * scrollSpeed * vwoosh * (Preferences.downscroll ? 1 : -1); @@ -539,6 +552,7 @@ class Strumline extends FlxSpriteGroup { playStatic(dir); } + scrollSpeedAdditive = 0; } public function applyNoteData(data:Array):Void @@ -705,6 +719,7 @@ class Strumline extends FlxSpriteGroup if (holdNoteSprite != null) { + holdNoteSprite.parentStrumline = this; holdNoteSprite.noteData = note; holdNoteSprite.strumTime = note.time; holdNoteSprite.noteDirection = note.getDirection(); diff --git a/source/funkin/play/notes/SustainTrail.hx b/source/funkin/play/notes/SustainTrail.hx index 056a6a5a99..b358d7f033 100644 --- a/source/funkin/play/notes/SustainTrail.hx +++ b/source/funkin/play/notes/SustainTrail.hx @@ -32,6 +32,7 @@ class SustainTrail extends FlxSprite public var sustainLength(default, set):Float = 0; // millis public var fullSustainLength:Float = 0; public var noteData:Null; + public var parentStrumline:Strumline; public var cover:NoteHoldCover = null; @@ -119,7 +120,7 @@ class SustainTrail extends FlxSprite // CALCULATE SIZE graphicWidth = graphic.width / 8 * zoom; // amount of notes * 2 - graphicHeight = sustainHeight(sustainLength, getScrollSpeed()); + graphicHeight = sustainHeight(sustainLength, parentStrumline?.scrollSpeed ?? 1.0); // instead of scrollSpeed, PlayState.SONG.speed flipY = Preferences.downscroll; @@ -135,9 +136,21 @@ class SustainTrail extends FlxSprite this.active = true; // This NEEDS to be true for the note to be drawn! } - function getScrollSpeed():Float + function getBaseScrollSpeed() { - return PlayState?.instance?.currentChart?.scrollSpeed ?? 1.0; + return (PlayState.instance?.currentChart?.scrollSpeed ?? 1.0); + } + + var previousScrollSpeed:Float = 1; + + override function update(elapsed) + { + super.update(elapsed); + if (previousScrollSpeed != (parentStrumline?.scrollSpeed ?? 1.0)) + { + triggerRedraw(); + } + previousScrollSpeed = parentStrumline?.scrollSpeed ?? 1.0; } /** @@ -155,12 +168,16 @@ class SustainTrail extends FlxSprite if (s < 0.0) s = 0.0; if (sustainLength == s) return s; - - graphicHeight = sustainHeight(s, getScrollSpeed()); this.sustainLength = s; + triggerRedraw(); + return this.sustainLength; + } + + function triggerRedraw() + { + graphicHeight = sustainHeight(sustainLength, parentStrumline?.scrollSpeed ?? 1.0); updateClipping(); updateHitbox(); - return this.sustainLength; } public override function updateHitbox():Void @@ -178,7 +195,7 @@ class SustainTrail extends FlxSprite */ public function updateClipping(songTime:Float = 0):Void { - var clipHeight:Float = FlxMath.bound(sustainHeight(sustainLength - (songTime - strumTime), getScrollSpeed()), 0, graphicHeight); + var clipHeight:Float = FlxMath.bound(sustainHeight(sustainLength - (songTime - strumTime), parentStrumline?.scrollSpeed ?? 1.0), 0, graphicHeight); if (clipHeight <= 0.1) { visible = false; diff --git a/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx b/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx index aeb6dd0e4a..663f2bbf47 100644 --- a/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx +++ b/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx @@ -58,11 +58,11 @@ class ChartEditorHoldNoteSprite extends SustainTrail { if (lerp) { - sustainLength = FlxMath.lerp(sustainLength, h / (getScrollSpeed() * Constants.PIXELS_PER_MS), 0.25); + sustainLength = FlxMath.lerp(sustainLength, h / (getBaseScrollSpeed() * Constants.PIXELS_PER_MS), 0.25); } else { - sustainLength = h / (getScrollSpeed() * Constants.PIXELS_PER_MS); + sustainLength = h / (getBaseScrollSpeed() * Constants.PIXELS_PER_MS); } fullSustainLength = sustainLength; From e5ee6efdf4cf052c33333ecb937617c231bd19e8 Mon Sep 17 00:00:00 2001 From: Burgerballs <107233412+Burgerballs@users.noreply.github.com> Date: Thu, 9 May 2024 20:01:26 +0100 Subject: [PATCH 029/216] redundancy is bad!!!! --- source/funkin/play/notes/SustainTrail.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/play/notes/SustainTrail.hx b/source/funkin/play/notes/SustainTrail.hx index b358d7f033..9155c9b0a7 100644 --- a/source/funkin/play/notes/SustainTrail.hx +++ b/source/funkin/play/notes/SustainTrail.hx @@ -168,6 +168,7 @@ class SustainTrail extends FlxSprite if (s < 0.0) s = 0.0; if (sustainLength == s) return s; + graphicHeight = sustainHeight(s, parentStrumline?.scrollSpeed ?? 1.0); this.sustainLength = s; triggerRedraw(); return this.sustainLength; @@ -175,7 +176,6 @@ class SustainTrail extends FlxSprite function triggerRedraw() { - graphicHeight = sustainHeight(sustainLength, parentStrumline?.scrollSpeed ?? 1.0); updateClipping(); updateHitbox(); } From eeb017b300a0d94cae53368fa8fe3830c8bb619e Mon Sep 17 00:00:00 2001 From: I Gede Hari Kresna Wiyasa Date: Fri, 10 May 2024 10:07:03 +0800 Subject: [PATCH 030/216] moved to Troubleshooting category --- docs/COMPILING.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index c5096c2f61..07df6367f4 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -5,7 +5,6 @@ 1. Cloning the Repository: Make sure when you clone, you clone the submodules to get the assets repo: - `git clone --recurse-submodules https://github.com/FunkinCrew/funkin.git` - If you accidentally cloned without the `assets` submodule (aka didn't follow the step above), you can run `git submodule update --init --recursive` to get the assets in a foolproof way. - - During the cloning process, you may experience an error along the lines of `error: RPC failed; curl 92 HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR (err 1)` due to poor connectivity. A common fix is to run ` git config --global http.postBuffer 4096M`. 2. Install `hmm` (run `haxelib --global install hmm` and then `haxelib --global run hmm setup`) 3. Install all haxelibs of the current branch by running `hmm install` 4. Setup lime: `haxelib run lime setup` @@ -19,3 +18,7 @@ - HTML5: Compiles without any extra setup 6. If you are targeting for native, you may need to run `lime rebuild PLATFORM` and `lime rebuild PLATFORM -debug` 7. `lime test PLATFORM` ! Add `-debug` to enable several debug features such as time travel (`PgUp`/`PgDn` in Play State). + +# Troubleshooting + +- During the cloning process, you may experience an error along the lines of `error: RPC failed; curl 92 HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR (err 1)` due to poor connectivity. A common fix is to run ` git config --global http.postBuffer 4096M`. From 6fc5e8cc2f7e5c9855be1950a75be6b0c4c15c05 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 9 May 2024 22:36:39 -0400 Subject: [PATCH 031/216] Fixed up some metadata --- example_mods/introMod/_polymod_meta.json | 2 +- example_mods/testing123/_polymod_meta.json | 2 +- tests/unit/assets/shared/images/arrows.png | Bin 4806 -> 0 bytes tests/unit/assets/shared/images/arrows.xml | 27 --------------------- 4 files changed, 2 insertions(+), 29 deletions(-) delete mode 100644 tests/unit/assets/shared/images/arrows.png delete mode 100644 tests/unit/assets/shared/images/arrows.xml diff --git a/example_mods/introMod/_polymod_meta.json b/example_mods/introMod/_polymod_meta.json index e0b03f1cd3..4dc0cd8044 100644 --- a/example_mods/introMod/_polymod_meta.json +++ b/example_mods/introMod/_polymod_meta.json @@ -3,7 +3,7 @@ "description": "An introductory mod.", "contributors": [ { - "name": "MasterEric" + "name": "EliteMasterEric" } ], "api_version": "0.1.0", diff --git a/example_mods/testing123/_polymod_meta.json b/example_mods/testing123/_polymod_meta.json index 4c0f177f9b..0a2ed042c6 100644 --- a/example_mods/testing123/_polymod_meta.json +++ b/example_mods/testing123/_polymod_meta.json @@ -3,7 +3,7 @@ "description": "Newgrounds? More like OLDGROUNDS lol.", "contributors": [ { - "name": "MasterEric" + "name": "EliteMasterEric" } ], "api_version": "0.1.0", diff --git a/tests/unit/assets/shared/images/arrows.png b/tests/unit/assets/shared/images/arrows.png deleted file mode 100644 index a443684327b409e3297d9456cb28afddd889b499..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4806 zcmai2XEYp6yj`pygdov-7k%|!cGXp)6MuaLK|-P>EP||(5G_IU5sY@60Hmk>6#_e#O;P}WCQuimZWfrip8@wZoBrMxN~^)i^X@p2BQX*PrgnR4 zB`_5RX(P^C<+|v4=n}&Oq;pdb3KA044U4U`06wI5QmZ+_)Z1EZ%Hw02Y^tV11u68 zJ2jL>z*K3A!K|AAY9;ySFApP`fNCAt%76>#jpNA`+3`t0;OWgJ2Y%4{3cs4xp9K-X zuk;WPYl|@U`Mev<*fjuFg{H|RxdFzZ(tg_Rs1mR4p3oBo<9BP*w@RjoxDNvHqD)e4 ztURd&;4}cu&0>c1qz7uzQ{<<*-#NJ%1Sf8b2-=4I;YtdehK2P|Jv|g#vP6cxQ9Ih_ z{VR}zOPayta1izIO2I=#USlH(^S1zAUjxAAiRu*jH zCxCb)me;|vmA7-2>pFMT+%!IvbDwODcJQRYbFGGc^ zvkBh)&`1%|@PdkAaWYi%RH0^)6Eo+(T~gk`>;J}$iXP;8L`~2xiS79LUBo42o0kEOhm~wnZWboa@C6=Xu^((8{it zr_`G#e0=cJZxcP838zUT=_ncdWL1-)f*^;y4m@YK*zT&ad(R{d0Z7y60v6 zrRyc}q1A%(sqQXe=gtqNnTM4`4$4MRc6oV{4?4GHS7gfXvW4~pzVdEsd1$Cfuv7y? zP`m?^tW9bzH_~jOMbe_iRfV__Y}^Nc)%A8G>r6}X&N2@Eo*s(N<&46X#O{_U&rCkQ z{MDpKX3Z(#i(qQAFMYBpRB$fD3wZ~56l*pWe%Gw6Olm0nZh_svUBv6$srLaw)Bm{& znlnl~V-w)ikJ=j<7TP9IBEImfm_ZR-4VUZj1TB9w6t@#;&Uf#diLn6rk{Z)C^^v&6-p0DR z^o((zocBd_Gszpl9a`J307h3M4gn7XmGTDeYcwx=eJc;7q`O{oiAc$dTKnEqnzil` zdM2eb&!2F=R2Ke%@UseG_8Ib@?oL`iKDG-wdcG1#9Qw0{hOn^^5}wCs2m?%oI6hz{ zgF2EKr56swk`rJsA5gmqqfT{ji$98)R`xEl|c0K5^zGqE6 zhL;VbcI!OC+F?e*E~)jveC8@jUso~z2_x-S7(YN#5P#B=;`l_-Y>aLBs=> z?(F!MJQzBxUv5QaxGP_QO??*hp>ib4W?wmHTYi>W*qb@?=v-Wx$df=(jb2F!Ii z^hQ?)w04-c)zXlphQ=7s>X3+(PXl-FX9|%YI&z z*yl79kRE>rf0ov!Q$i#Bv*00+U{)+>8TC-CyDA;o-fqFIQN@wxL-> zzkeg2IlF)SK{@{Co`GNEbfYkuCA|_bFdgWuhKeQFU#I~3E4QNl%cE>FdDyw% zfdcLNx50w9CVVSb~ zfJ|kRk^kBy zF=rh1f}TuYBl1Jk*03xJ520y_Q8mC!ex(;~R8Tn8GdEeH7(=Nr{I8mog9?`_T4v_d z=ItzYGTKvv)X;y%t%4jSz*hMp9lS(hgdG6aj}YIACP9sIuvU#HC%_Umma*H@Njv;pJcQO!d0o~nKg>4hVz9969g z6+=2ZPiM&KZZ~;SWvX~;ugM}m;IvoVp$JOOz3%XibPXKlWQE{uGiMeJM zsY9xszm^hj^MkTLC;|M+WwEqRORGvL4~@-z!sj9%IMJF!SICcA@{a_v-+vAEK(4z- zrBNb;KmAwobwlIZSA!~AMOM_cBBA%iafoFobg$4J%JGHEaXwIO;~`WYB=UB*78&5iv%wd@6!p1}A6O zOM1`a@@`i}p9Te+)N6t(A+qD%717s;vdP&Kp9s+Tau!|>9a(8YG*tmy3$}c}5!wGD zVlJTlE}@Y4#zi4t|Y>qsc*-Fc#o!5Ay zu#GxIN~s86Fs~{;VoqiFtBFo8XS)@Ubl(#&>0cpspf*=j7jZ8;feaQtkJq>Ci)AjP zV5ap*GWl!Z)#-C=w30FMDexb!|FJ@>ci=Iv#0ft)o-i5+eLjVnx+D}C1m>q>_Sd95 zxmqZ_*ihdSo1y=WRO^mgOuGIdUafyG8o0yq1X&d>dyIN!cSO097tbb~l1Vw$`MY-v zO#^#+T9`h1qsPnt2r*r1Mm{~V>9E{}jG_~KhQ7S*p^!RYZE*R?l4gDf$}u+XYHj;0}w=Io=ifu619 zXA_&;l*tjY&RDNU#d@V4gO)GLQfkrC{#G$gypKBQ{0ycucspiFn$Yqg0vU7mrDC!I zXJ~1t`^C1s`FzjK;PZ2<{15GtZ&aS1c-7kk@+)^=w!l}m9v24kXXKE%kIz)di!^6n z>6hCgx8-^iI8 zFZi9ps4vHt9Xeo-9rZhe@Z+jvalVO z!sJ1MK)$U(MW$gz7gd4B-KD;nNxOR+t9pU2UjUsQe zN5aA!Z~YP2S934`MV8YuJ)i?(=GKcR;5KK!82sZU@S>+yI?bASp-2SRAPouT22c(^ zDmXYfWZ7mS?EJM~h=nnpu-%YTHl#^YJLhO@^GowM@ijM7szQv6PvmvZHIyg%O zVuds4rignBEoTS}SWg07v@JeZh7GBDQR%FpVdX;K+*?vCz8=Iis80q!e~XrfI9M=l z%{DxCYZFpALGM>I-B^~Kj8sPi^pfvZv~*pu^u^7F|6z4ol0qMapSP{}rz>S=GQ5zQ zU#eZKOfPcA^Bj%m`StAsfNesX4R!4<1bVLR~_cC<*;g?2zg5f8pAFLamqR9I)&gq+N)=1*e5&>)!NV53s zuvyF3i_7F~(3h9~=74hpgWMqp%(}H{bJj;02K(TjSHE6v`v_ye4Iikc*U}sGq=lg0 z4-qCB7CQPiMNe5x%hdl4RygaC8FL&-^VU@~J4}&VcO^_Vm7B0%wV2E@ z32zQcMwlC}RO*pVI>vx5M=nsi<71>}+8=1>T9fVO+3%LYU0gyvTDV)2Z5s$d&T$l8 z>{Wz)TjoOl%=ffPfzvKH z+dbk18I=8{<0;H$G8P%Y4Od!LkVn@l^9l=70X_3`e8t=*K}+-=oim^#7xM1+TO; zz3S2HnZ=votfeo!V&b<*V_u#}9xxwo@4fK3A)uzP0T071yG@-N1i;wnmfZ3|mdLMl zDAFg#r*#Oa20Z|+;Ji}hN5zF^m<=qN_8L8kcK%-noqT)enY>N^z5Wyn{KphPSJMzu Iso@a*KZ!k4q5uE@ diff --git a/tests/unit/assets/shared/images/arrows.xml b/tests/unit/assets/shared/images/arrows.xml deleted file mode 100644 index 96a73a3888..0000000000 --- a/tests/unit/assets/shared/images/arrows.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - From a243b167b2b1a76c70a7b68296d7e27f4410cff4 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 9 May 2024 22:37:01 -0400 Subject: [PATCH 032/216] Fix up more credits --- source/funkin/play/components/HealthIcon.hx | 2 +- source/funkin/ui/debug/charting/ChartEditorState.hx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/play/components/HealthIcon.hx b/source/funkin/play/components/HealthIcon.hx index 957daa43c9..2d7099e8ac 100644 --- a/source/funkin/play/components/HealthIcon.hx +++ b/source/funkin/play/components/HealthIcon.hx @@ -24,7 +24,7 @@ import funkin.util.MathUtil; * - i.e. `PlayState.instance.iconP1.playAnimation("losing")` * - Scripts can also utilize all functionality that a normal FlxSprite would have access to, such as adding supplimental animations. * - i.e. `PlayState.instance.iconP1.animation.addByPrefix("jumpscare", "jumpscare", 24, false);` - * @author MasterEric + * @author EliteMasterEric */ @:nullSafety class HealthIcon extends FunkinSprite diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index b75cd8bf1f..a313981f45 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -137,7 +137,7 @@ using Lambda; * * Some functionality is split into handler classes to help maintain my sanity. * - * @author MasterEric + * @author EliteMasterEric */ // @:nullSafety From 5d5cf740204ac0b57712483a5e2a9fb0491b6eba Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 9 May 2024 22:37:21 -0400 Subject: [PATCH 033/216] Reimplement rank-based results animations. --- README.md | 2 +- assets | 2 +- source/funkin/play/ResultState.hx | 332 +++++++++++++++++++++--------- source/funkin/util/Constants.hx | 11 + 4 files changed, 245 insertions(+), 102 deletions(-) diff --git a/README.md b/README.md index 39c098af5e..5728a6cb37 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Please check out our [Contributor's guide](./CONTRIBUTORS.md) on how you can act ## Programming - [ninjamuffin99](https://twitter.com/ninja_muffin99) - Lead Programmer -- [MasterEric](https://twitter.com/EliteMasterEric) - Programmer +- [EliteMasterEric](https://twitter.com/EliteMasterEric) - Programmer - [MtH](https://twitter.com/emmnyaa) - Charting and Additional Programming - [GeoKureli](https://twitter.com/Geokureli/) - Additional Programming - Our contributors on GitHub diff --git a/assets b/assets index fe52d20de7..6115eb6837 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit fe52d20de7025d90cadb429dbdedf6d986727088 +Subproject commit 6115eb6837e97b8b3ad82f3ccd2a49a4383ed35b diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index 56dd1e80fc..7f8bdd77ab 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -26,6 +26,7 @@ import funkin.play.components.TallyCounter; /** * The state for the results screen after a song or week is finished. */ +@:nullSafety class ResultState extends MusicBeatSubState { final params:ResultsStateParams; @@ -42,91 +43,45 @@ class ResultState extends MusicBeatSubState super(); this.params = params; + + resultsVariation = calculateVariation(params); + + var fontLetters:String = "AaBbCcDdEeFfGgHhiIJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz:1234567890"; + songName = new FlxBitmapText(FlxBitmapFont.fromMonospace(Paths.image("resultScreen/tardlingSpritesheet"), fontLetters, FlxPoint.get(49, 62))); + songName.text = params.title; + songName.letterSpacing = -15; + songName.angle = -4.4; + songName.zIndex = 1000; + + difficulty = new FlxSprite(555); + difficulty.zIndex = 1000; } override function create():Void { - /* - if (params.scoreData.sick == params.scoreData.totalNotesHit - && params.scoreData.maxCombo == params.scoreData.totalNotesHit) resultsVariation = PERFECT; - else if (params.scoreData.missed + params.scoreData.bad + params.scoreData.shit >= params.scoreData.totalNotes * 0.50) - resultsVariation = SHIT; // if more than half of your song was missed, bad, or shit notes, you get shit ending! - else - resultsVariation = NORMAL; - */ - resultsVariation = NORMAL; - - FunkinSound.playMusic('results$resultsVariation', + FunkinSound.playMusic(resultsVariation.getMusicPath(), { startingVolume: 1.0, overrideExisting: true, restartTrack: true, - loop: resultsVariation != SHIT + loop: resultsVariation.shouldMusicLoop() }); // Reset the camera zoom on the results screen. FlxG.camera.zoom = 1.0; - // TEMP-ish, just used to sorta "cache" the 3000x3000 image! - var cacheBullShit:FlxSprite = new FlxSprite().loadGraphic(Paths.image("resultScreen/soundSystem")); - add(cacheBullShit); - - var dumb:FlxSprite = new FlxSprite().loadGraphic(Paths.image("resultScreen/scorePopin")); - add(dumb); - var bg:FlxSprite = FlxGradient.createGradientFlxSprite(FlxG.width, FlxG.height, [0xFFFECC5C, 0xFFFDC05C], 90); bg.scrollFactor.set(); + bg.zIndex = 10; add(bg); var bgFlash:FlxSprite = FlxGradient.createGradientFlxSprite(FlxG.width, FlxG.height, [0xFFFFEB69, 0xFFFFE66A], 90); bgFlash.scrollFactor.set(); bgFlash.visible = false; + bg.zIndex = 20; add(bgFlash); - // var bfGfExcellent:FlxAtlasSprite = new FlxAtlasSprite(380, -170, Paths.animateAtlas("resultScreen/resultsBoyfriendExcellent", "shared")); - // bfGfExcellent.visible = false; - // add(bfGfExcellent); - // - // var bfPerfect:FlxAtlasSprite = new FlxAtlasSprite(370, -180, Paths.animateAtlas("resultScreen/resultsBoyfriendPerfect", "shared")); - // bfPerfect.visible = false; - // add(bfPerfect); - // - // var bfSHIT:FlxAtlasSprite = new FlxAtlasSprite(0, 20, Paths.animateAtlas("resultScreen/resultsBoyfriendSHIT", "shared")); - // bfSHIT.visible = false; - // add(bfSHIT); - // - // bfGfExcellent.anim.onComplete = () -> { - // bfGfExcellent.anim.curFrame = 28; - // bfGfExcellent.anim.play(); // unpauses this anim, since it's on PlayOnce! - // }; - // - // bfPerfect.anim.onComplete = () -> { - // bfPerfect.anim.curFrame = 136; - // bfPerfect.anim.play(); // unpauses this anim, since it's on PlayOnce! - // }; - // - // bfSHIT.anim.onComplete = () -> { - // bfSHIT.anim.curFrame = 150; - // bfSHIT.anim.play(); // unpauses this anim, since it's on PlayOnce! - // }; - - var gf:FlxSprite = FunkinSprite.createSparrow(625, 325, 'resultScreen/resultGirlfriendGOOD'); - gf.animation.addByPrefix("clap", "Girlfriend Good Anim", 24, false); - gf.visible = false; - gf.animation.finishCallback = _ -> { - gf.animation.play('clap', true, false, 9); - }; - add(gf); - - var boyfriend:FlxSprite = FunkinSprite.createSparrow(640, -200, 'resultScreen/resultBoyfriendGOOD'); - boyfriend.animation.addByPrefix("fall", "Boyfriend Good Anim0", 24, false); - boyfriend.visible = false; - boyfriend.animation.finishCallback = function(_) { - boyfriend.animation.play('fall', true, false, 14); - }; - - add(boyfriend); - + // The sound system which falls into place behind the score text. Plays every time! var soundSystem:FlxSprite = FunkinSprite.createSparrow(-15, -180, 'resultScreen/soundSystem'); soundSystem.animation.addByPrefix("idle", "sound system", 24, false); soundSystem.visible = false; @@ -134,9 +89,66 @@ class ResultState extends MusicBeatSubState soundSystem.animation.play("idle"); soundSystem.visible = true; }); + soundSystem.zIndex = 1100; add(soundSystem); - difficulty = new FlxSprite(555); + var bfPerfect:Null = null; + var bfExcellent:Null = null; + var bfGood:Null = null; + var gfGood:Null = null; + var bfShit:Null = null; + + switch (resultsVariation) + { + case PERFECT | PERFECT_GOLD | PERFECT_PLATINUM: + bfPerfect = new FlxAtlasSprite(370, -180, Paths.animateAtlas("resultScreen/results-bf/resultsPERFECT", "shared")); + bfPerfect.visible = false; + bfPerfect.zIndex = 500; + add(bfPerfect); + + bfPerfect.anim.onComplete = () -> { + bfPerfect.anim.curFrame = 136; + bfPerfect.anim.play(); // unpauses this anim, since it's on PlayOnce! + }; + + case EXCELLENT: + bfExcellent = new FlxAtlasSprite(380, -170, Paths.animateAtlas("resultScreen/results-bf/resultsEXCELLENT", "shared")); + bfExcellent.visible = false; + bfExcellent.zIndex = 500; + add(bfExcellent); + + bfExcellent.onAnimationFinish.add((animName) -> { + bfExcellent.playAnimation('Loop Start'); + }); + + case GOOD | GREAT: + gfGood = FunkinSprite.createSparrow(625, 325, 'resultScreen/results-bf/resultsGOOD/resultGirlfriendGOOD'); + gfGood.animation.addByPrefix("clap", "Girlfriend Good Anim", 24, false); + gfGood.visible = false; + gfGood.zIndex = 500; + gfGood.animation.finishCallback = _ -> { + gfGood.animation.play('clap', true, false, 9); + }; + add(gfGood); + + bfGood = FunkinSprite.createSparrow(640, -200, 'resultScreen/results-bf/resultsGOOD/resultBoyfriendGOOD'); + bfGood.animation.addByPrefix("fall", "Boyfriend Good Anim0", 24, false); + bfGood.visible = false; + bfGood.zIndex = 501; + bfGood.animation.finishCallback = function(_) { + bfGood.animation.play('fall', true, false, 14); + }; + add(bfGood); + + case SHIT: + bfShit = new FlxAtlasSprite(0, 20, Paths.animateAtlas("resultScreen/results-bf/resultsSHIT", "shared")); + bfShit.visible = false; + bfShit.zIndex = 500; + add(bfShit); + bfShit.onAnimationFinish.add((animName) -> { + bfShit.playAnimation('Loop Start'); + }); + } var diffSpr:String = switch (PlayState.instance.currentDifficulty) { @@ -157,11 +169,6 @@ class ResultState extends MusicBeatSubState difficulty.loadGraphic(Paths.image("resultScreen/" + diffSpr)); add(difficulty); - var fontLetters:String = "AaBbCcDdEeFfGgHhiIJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz:1234567890"; - songName = new FlxBitmapText(FlxBitmapFont.fromMonospace(Paths.image("resultScreen/tardlingSpritesheet"), fontLetters, FlxPoint.get(49, 62))); - songName.text = params.title; - songName.letterSpacing = -15; - songName.angle = -4.4; add(songName); var angleRad = songName.angle * Math.PI / 180; @@ -179,21 +186,25 @@ class ResultState extends MusicBeatSubState var blackTopBar:FlxSprite = new FlxSprite().loadGraphic(Paths.image("resultScreen/topBarBlack")); blackTopBar.y = -blackTopBar.height; FlxTween.tween(blackTopBar, {y: 0}, 0.4, {ease: FlxEase.quartOut, startDelay: 0.5}); + blackTopBar.zIndex = 1010; add(blackTopBar); var resultsAnim:FunkinSprite = FunkinSprite.createSparrow(-200, -10, "resultScreen/results"); resultsAnim.animation.addByPrefix("result", "results instance 1", 24, false); resultsAnim.animation.play("result"); + resultsAnim.zIndex = 1200; add(resultsAnim); var ratingsPopin:FunkinSprite = FunkinSprite.createSparrow(-150, 120, "resultScreen/ratingsPopin"); ratingsPopin.animation.addByPrefix("idle", "Categories", 24, false); ratingsPopin.visible = false; + ratingsPopin.zIndex = 1200; add(ratingsPopin); var scorePopin:FunkinSprite = FunkinSprite.createSparrow(-180, 520, "resultScreen/scorePopin"); scorePopin.animation.addByPrefix("score", "tally score", 24, false); scorePopin.visible = false; + scorePopin.zIndex = 1200; add(scorePopin); var highscoreNew:FlxSprite = new FlxSprite(310, 570); @@ -202,11 +213,13 @@ class ResultState extends MusicBeatSubState highscoreNew.visible = false; highscoreNew.setGraphicSize(Std.int(highscoreNew.width * 0.8)); highscoreNew.updateHitbox(); + highscoreNew.zIndex = 1200; add(highscoreNew); var hStuf:Int = 50; var ratingGrp:FlxTypedGroup = new FlxTypedGroup(); + ratingGrp.zIndex = 1200; add(ratingGrp); /** @@ -238,6 +251,7 @@ class ResultState extends MusicBeatSubState var score:ResultScore = new ResultScore(35, 305, 10, params.scoreData.score); score.visible = false; + score.zIndex = 1200; add(score); for (ind => rating in ratingGrp.members) @@ -275,40 +289,72 @@ class ResultState extends MusicBeatSubState switch (resultsVariation) { - // case SHIT: - // bfSHIT.visible = true; - // bfSHIT.playAnimation(""); - - case NORMAL: - boyfriend.animation.play('fall'); - boyfriend.visible = true; - - new FlxTimer().start((1 / 24) * 12, _ -> { - bgFlash.visible = true; - FlxTween.tween(bgFlash, {alpha: 0}, 0.4); - new FlxTimer().start((1 / 24) * 2, _ -> - { - // bgFlash.alpha = 0.5; - - // bgFlash.visible = false; - }); - }); - - new FlxTimer().start((1 / 24) * 22, _ -> { - // plays about 22 frames (at 24fps timing) after bf spawns in - gf.animation.play('clap', true); - gf.visible = true; - }); - // case PERFECT: - // bfPerfect.visible = true; - // bfPerfect.playAnimation(""); - - // bfGfExcellent.visible = true; - // bfGfExcellent.playAnimation(""); + case PERFECT | PERFECT_GOLD | PERFECT_PLATINUM: + if (bfPerfect == null) + { + trace("Could not build PERFECT animation!"); + } + else + { + bfPerfect.visible = true; + bfPerfect.playAnimation(''); + } + + case EXCELLENT: + if (bfExcellent == null) + { + trace("Could not build EXCELLENT animation!"); + } + else + { + bfExcellent.visible = true; + bfExcellent.playAnimation('Intro'); + } + + case SHIT: + if (bfShit == null) + { + trace("Could not build SHIT animation!"); + } + else + { + bfShit.visible = true; + bfShit.playAnimation('Intro'); + } + + case GREAT | GOOD: + if (bfGood == null || gfGood == null) + { + trace("Could not build GOOD animation!"); + } + else + { + bfGood.animation.play('fall'); + bfGood.visible = true; + + new FlxTimer().start((1 / 24) * 12, _ -> { + bgFlash.visible = true; + FlxTween.tween(bgFlash, {alpha: 0}, 0.4); + new FlxTimer().start((1 / 24) * 2, _ -> + { + // bgFlash.alpha = 0.5; + + // bgFlash.visible = false; + }); + }); + + new FlxTimer().start((1 / 24) * 22, _ -> { + // plays about 22 frames (at 24fps timing) after bf spawns in + gfGood.animation.play('clap', true); + gfGood.visible = true; + }); + } default: } }); + refresh(); + super.create(); } @@ -401,14 +447,100 @@ class ResultState extends MusicBeatSubState super.update(elapsed); } + + public static function calculateVariation(params:ResultsStateParams):ResultVariations + { + // Perfect (Platinum) is a Sick Full Clear + var isPerfectPlat = (params.scoreData.tallies.sick + params.scoreData.tallies.good) == params.scoreData.tallies.totalNotes + && params.scoreData.tallies.sick / params.scoreData.tallies.totalNotes >= Constants.RANK_PERFECT_PLAT_THRESHOLD; + if (isPerfectPlat) return ResultVariations.PERFECT_PLATINUM; + + // Perfect (Gold) is an 85% Sick Full Clear + var isPerfectGold = (params.scoreData.tallies.sick + params.scoreData.tallies.good) == params.scoreData.tallies.totalNotes + && params.scoreData.tallies.sick / params.scoreData.tallies.totalNotes >= Constants.RANK_PERFECT_GOLD_THRESHOLD; + if (isPerfectGold) return ResultVariations.PERFECT_GOLD; + + // Else, use the standard grades + + // Clear % (including bad and shit). 1.00 is a full clear but not a full combo + var clear = (params.scoreData.tallies.totalNotesHit) / params.scoreData.tallies.totalNotes; + + if (clear == Constants.RANK_PERFECT_THRESHOLD) + { + return ResultVariations.PERFECT; + } + else if (clear >= Constants.RANK_EXCELLENT_THRESHOLD) + { + return ResultVariations.EXCELLENT; + } + else if (clear >= Constants.RANK_GREAT_THRESHOLD) + { + return ResultVariations.GREAT; + } + else if (clear >= Constants.RANK_GOOD_THRESHOLD) + { + return ResultVariations.GOOD; + } + else + { + return ResultVariations.SHIT; + } + } } enum abstract ResultVariations(String) { + var PERFECT_PLATINUM; + var PERFECT_GOLD; var PERFECT; var EXCELLENT; - var NORMAL; + var GREAT; + var GOOD; var SHIT; + + public function getMusicPath():String + { + switch (abstract) + { + case PERFECT_PLATINUM: + return 'resultsPERFECT'; + case PERFECT_GOLD: + return 'resultsPERFECT'; + case PERFECT: + return 'resultsPERFECT'; + case EXCELLENT: + return 'resultsNORMAL'; + case GREAT: + return 'resultsNORMAL'; + case GOOD: + return 'resultsNORMAL'; + case SHIT: + return 'resultsSHIT'; + } + } + + public function shouldMusicLoop():Bool + { + switch (abstract) + { + case PERFECT_PLATINUM: + return true; + case PERFECT_GOLD: + return true; + case PERFECT: + return true; + case EXCELLENT: + return true; + case GREAT: + return true; + case GOOD: + return true; + case SHIT: + return false; + default: + return false; + } + } } typedef ResultsStateParams = diff --git a/source/funkin/util/Constants.hx b/source/funkin/util/Constants.hx index c50f17697b..2f3b570b3b 100644 --- a/source/funkin/util/Constants.hx +++ b/source/funkin/util/Constants.hx @@ -455,6 +455,17 @@ class Constants public static final JUDGEMENT_BAD_COMBO_BREAK:Bool = true; public static final JUDGEMENT_SHIT_COMBO_BREAK:Bool = true; + // % Sick + public static final RANK_PERFECT_PLAT_THRESHOLD:Float = 1.0; // % Sick + public static final RANK_PERFECT_GOLD_THRESHOLD:Float = 0.85; // % Sick + + // % Hit + public static final RANK_PERFECT_THRESHOLD:Float = 1.00; + public static final RANK_EXCELLENT_THRESHOLD:Float = 0.90; + public static final RANK_GREAT_THRESHOLD:Float = 0.75; + public static final RANK_GOOD_THRESHOLD:Float = 0.60; + + // public static final RANK_SHIT_THRESHOLD:Float = 0.00; /** * FILE EXTENSIONS */ From 98cf37b642292fcd7eb8a5913db5c7e08a43b82a Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 9 May 2024 22:38:01 -0400 Subject: [PATCH 034/216] Update assets to add music. --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 6115eb6837..7df2e55273 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 6115eb6837e97b8b3ad82f3ccd2a49a4383ed35b +Subproject commit 7df2e552738f8f2278538513a7495cb96d5ed118 From a5700b37e10e35f6fc338b646951903887c221a6 Mon Sep 17 00:00:00 2001 From: Burgerballs <107233412+Burgerballs@users.noreply.github.com> Date: Fri, 10 May 2024 21:23:35 +0100 Subject: [PATCH 035/216] awesome shit (see desc) No longer Additive, it just sets the scroll speed Now you can set it to either strumline --- source/funkin/play/PlayState.hx | 60 ++++++++++--------- ...crollSpeedEvent.hx => ScrollSpeedEvent.hx} | 51 ++++++++++++---- source/funkin/play/notes/Strumline.hx | 17 ++---- 3 files changed, 77 insertions(+), 51 deletions(-) rename source/funkin/play/event/{AdditiveScrollSpeedEvent.hx => ScrollSpeedEvent.hx} (69%) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 0b76ec6ee2..b4c733ee3e 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -239,7 +239,7 @@ class PlayState extends MusicBeatSubState /** * An FlxTween that changes the additive speed to the desired amount. */ - public var additiveScrollSpeedTween:FlxTween; + public var scrollSpeedTweens:Array = []; /** * The camera follow point from the last stage. @@ -1184,10 +1184,14 @@ class PlayState extends MusicBeatSubState cameraZoomTween.active = false; cameraTweensPausedBySubState.add(cameraZoomTween); } - if (additiveScrollSpeedTween != null && additiveScrollSpeedTween.active) + + for (tween in scrollSpeedTweens) { - additiveScrollSpeedTween.active = false; - cameraTweensPausedBySubState.add(additiveScrollSpeedTween); + if (tween != null && tween.active) + { + tween.active = false; + cameraTweensPausedBySubState.add(tween); + } } // Pause the countdown. @@ -3035,7 +3039,7 @@ class PlayState extends MusicBeatSubState // Cancel camera and scroll tweening if it's active. cancelAllCameraTweens(); - cancelAdditiveScrollSpeedTween(); + cancelScrollSpeedTweens(); // If the opponent is GF, zoom in on the opponent. // Else, if there is no GF, zoom in on BF. @@ -3256,37 +3260,39 @@ class PlayState extends MusicBeatSubState } /** - * The magical function that shall tween the additive scroll speed. + * The magical function that shall tween the scroll speed. */ - public function tweenAdditiveScrollSpeed(?speed:Float, ?duration:Float, ?ease:NullFloat>):Void + public function tweenScrollSpeed(?speed:Float, ?duration:Float, ?ease:NullFloat>, strumlines:Array):Void { // Cancel the current tween if it's active. - cancelAdditiveScrollSpeedTween(); - var strumLineTargets:Array = [ - playerStrumline.scrollSpeedAdditive + speed, - opponentStrumline.scrollSpeedAdditive + speed - ]; - - if (duration == 0) + cancelScrollSpeedTweens(); + for (i in strumlines) { - playerStrumline.scrollSpeedAdditive = strumLineTargets[0]; - opponentStrumline.scrollSpeedAdditive = strumLineTargets[1]; - } - else - { - additiveScrollSpeedTween = FlxTween.tween(this, - { - "playerStrumline.scrollSpeedAdditive": strumLineTargets[0], - "opponentStrumline.scrollSpeedAdditive": strumLineTargets[1] - }, duration, {ease: ease}); + var value:Float = speed; + var strum:Strumline = Reflect.getProperty(this, i); + + if (duration == 0) + { + strum.scrollSpeed = value; + } + else + { + scrollSpeedTweens.push(FlxTween.tween(strum, + { + 'scrollSpeed': value + }, duration, {ease: ease})); + } } } - public function cancelAdditiveScrollSpeedTween() + public function cancelScrollSpeedTweens() { - if (additiveScrollSpeedTween != null) + for (tween in scrollSpeedTweens) { - additiveScrollSpeedTween.cancel(); + if (tween != null) + { + tween.cancel(); + } } } diff --git a/source/funkin/play/event/AdditiveScrollSpeedEvent.hx b/source/funkin/play/event/ScrollSpeedEvent.hx similarity index 69% rename from source/funkin/play/event/AdditiveScrollSpeedEvent.hx rename to source/funkin/play/event/ScrollSpeedEvent.hx index f66f3b2571..22da45b0cb 100644 --- a/source/funkin/play/event/AdditiveScrollSpeedEvent.hx +++ b/source/funkin/play/event/ScrollSpeedEvent.hx @@ -17,30 +17,31 @@ import funkin.data.event.SongEventSchema.SongEventFieldType; * Example: Scroll speed change of both strums from 1x to 1.3x: * ``` * { - * 'e': 'AdditiveScrollSpeed', + * 'e': 'ScrollSpeed', * "v": { - * "scroll": "0.3", + * "scroll": "1.3", * "duration": "4", * "ease": "linear" * } * } * ``` */ -class AdditiveScrollSpeedEvent extends SongEvent +class ScrollSpeedEvent extends SongEvent { public function new() { - super('AdditiveScrollSpeed'); + super('ScrollSpeed'); } - static final DEFAULT_SCROLL:Float = 0; + static final DEFAULT_SCROLL:Float = 1; static final DEFAULT_DURATION:Float = 4.0; static final DEFAULT_EASE:String = 'linear'; + static final DEFAULT_STRUMLINE:String = 'both'; // my special little trick public override function handleEvent(data:SongEventData):Void { - // Does nothing if there is no PlayState camera or stage. - if (PlayState.instance == null || PlayState.instance.currentStage == null) return; + // Does nothing if there is no PlayState. + if (PlayState.instance == null) return; var scroll:Float = data.getFloat('scroll') ?? DEFAULT_SCROLL; @@ -48,11 +49,28 @@ class AdditiveScrollSpeedEvent extends SongEvent var ease:String = data.getString('ease') ?? DEFAULT_EASE; + var strumline:String = data.getString('strumline') ?? DEFAULT_STRUMLINE; + + var strumlineNames:Array = []; + + if (scroll == 0) + { + // if the parameter is set to 0, reset the scroll speed to normal. + scroll = PlayState.instance?.currentChart?.scrollSpeed ?? 1.0; + } + + switch (strumline) + { + case 'both': + strumlineNames = ['playerStrumline', 'opponentStrumline']; + default: + strumlineNames = [strumline + 'Strumline']; + } // If it's a string, check the value. switch (ease) { case 'INSTANT': - PlayState.instance.tweenAdditiveScrollSpeed(scroll, 0); + PlayState.instance.tweenScrollSpeed(scroll, 0, null, strumlineNames); default: var durSeconds = Conductor.instance.stepLengthMs * duration / 1000; var easeFunction:NullFloat> = Reflect.field(FlxEase, ease); @@ -62,19 +80,19 @@ class AdditiveScrollSpeedEvent extends SongEvent return; } - PlayState.instance.tweenAdditiveScrollSpeed(scroll, durSeconds, easeFunction); + PlayState.instance.tweenScrollSpeed(scroll, durSeconds, easeFunction, strumlineNames); } } public override function getTitle():String { - return 'Additive Scroll Speed'; + return 'Scroll Speed'; } /** * ``` * { - * 'scroll': FLOAT, // Target additive scroll level. + * 'scroll': FLOAT, // Target scroll level. * 'duration': FLOAT, // Duration in steps. * 'ease': ENUM, // Easing function. * } @@ -85,7 +103,7 @@ class AdditiveScrollSpeedEvent extends SongEvent return new SongEventSchema([ { name: 'scroll', - title: 'Additive Scroll Amount', + title: 'Scroll Amount', defaultValue: 0.0, step: 0.1, type: SongEventFieldType.FLOAT, @@ -106,7 +124,7 @@ class AdditiveScrollSpeedEvent extends SongEvent type: SongEventFieldType.ENUM, keys: [ 'Linear' => 'linear', - 'Instant' => 'INSTANT', + 'Instant (Ignores Duration)' => 'INSTANT', 'Sine In' => 'sineIn', 'Sine Out' => 'sineOut', 'Sine In/Out' => 'sineInOut', @@ -132,6 +150,13 @@ class AdditiveScrollSpeedEvent extends SongEvent 'Elastic Out' => 'elasticOut', 'Elastic In/Out' => 'elasticInOut' ] + }, + { + name: 'strumline', + title: 'Target Strumline', + defaultValue: 'both', + type: SongEventFieldType.ENUM, + keys: ['Both' => 'both', 'Player' => 'player', 'Opponent' => 'opponent'] } ]); } diff --git a/source/funkin/play/notes/Strumline.hx b/source/funkin/play/notes/Strumline.hx index bd0c8a1be8..dbc8569c58 100644 --- a/source/funkin/play/notes/Strumline.hx +++ b/source/funkin/play/notes/Strumline.hx @@ -52,13 +52,12 @@ class Strumline extends FlxSpriteGroup */ public var conductorInUse(get, set):Conductor; - // Used in-game to control the scroll speed within a song, for example if a song has an additive scroll speed of 1 and the base scroll speed is 1, it will be 2 - burgerballs - public var scrollSpeedAdditive:Float = 0; - public var scrollSpeed(get, never):Float; + // Used in-game to control the scroll speed within a song + public var scrollSpeed:Float = 1.0; - function get_scrollSpeed():Float + public function resetScrollSpeed():Void { - return (PlayState.instance?.currentChart?.scrollSpeed ?? 1.0) + scrollSpeedAdditive; + scrollSpeed = PlayState.instance?.currentChart?.scrollSpeed ?? 1.0; } var _conductorInUse:Null; @@ -143,6 +142,7 @@ class Strumline extends FlxSpriteGroup this.refresh(); this.onNoteIncoming = new FlxTypedSignalVoid>(); + resetScrollSpeed(); for (i in 0...KEY_COUNT) { @@ -217,11 +217,6 @@ class Strumline extends FlxSpriteGroup return null; } - public function resetScrollSpeed():Void - { - scrollSpeedAdditive = 0; - } - public function getHoldNoteSprite(noteData:SongNoteData):SustainTrail { if (noteData == null || ((noteData.length ?? 0.0) <= 0.0)) return null; @@ -552,7 +547,7 @@ class Strumline extends FlxSpriteGroup { playStatic(dir); } - scrollSpeedAdditive = 0; + resetScrollSpeed(); } public function applyNoteData(data:Array):Void From 5fd2ea0bcf0c60ed4ea654b34485df86c34a88fc Mon Sep 17 00:00:00 2001 From: Burgerballs <107233412+Burgerballs@users.noreply.github.com> Date: Fri, 10 May 2024 21:37:46 +0100 Subject: [PATCH 036/216] optimization of the cleary boy (: --- source/funkin/play/PlayState.hx | 1 + 1 file changed, 1 insertion(+) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index b4c733ee3e..4ce778fc1c 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -3294,6 +3294,7 @@ class PlayState extends MusicBeatSubState tween.cancel(); } } + scrollSpeedTweens = []; } #if (debug || FORCE_DEBUG_VERSION) From 83c3ff478c27bdc096e7dfcea190753df97526b5 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 10 May 2024 22:09:09 -0400 Subject: [PATCH 037/216] Added Clear % tally to results. --- assets | 2 +- source/funkin/play/ResultState.hx | 371 +++++++++++++++++++++--------- 2 files changed, 261 insertions(+), 112 deletions(-) diff --git a/assets b/assets index 7df2e55273..927578f482 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 7df2e552738f8f2278538513a7495cb96d5ed118 +Subproject commit 927578f482b23dc4511fd8203560d631442d91a8 diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index 7f8bdd77ab..df3134b9d5 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -12,6 +12,8 @@ import funkin.ui.MusicBeatSubState; import flixel.math.FlxRect; import flixel.text.FlxBitmapText; import funkin.ui.freeplay.FreeplayScore; +import flixel.text.FlxText; +import flixel.util.FlxColor; import flixel.tweens.FlxEase; import funkin.ui.freeplay.FreeplayState; import flixel.tweens.FlxTween; @@ -31,12 +33,27 @@ class ResultState extends MusicBeatSubState { final params:ResultsStateParams; - var resultsVariation:ResultVariations; - var songName:FlxBitmapText; - var difficulty:FlxSprite; + final rank:ResultRank; + final songName:FlxBitmapText; + final difficulty:FlxSprite; - var maskShaderSongName:LeftMaskShader = new LeftMaskShader(); - var maskShaderDifficulty:LeftMaskShader = new LeftMaskShader(); + final maskShaderSongName:LeftMaskShader = new LeftMaskShader(); + final maskShaderDifficulty:LeftMaskShader = new LeftMaskShader(); + + final resultsAnim:FunkinSprite; + final ratingsPopin:FunkinSprite; + final scorePopin:FunkinSprite; + + final bgFlash:FlxSprite; + + final highscoreNew:FlxSprite; + final score:ResultScore; + + var bfPerfect:Null = null; + var bfExcellent:Null = null; + var bfGood:Null = null; + var gfGood:Null = null; + var bfShit:Null = null; public function new(params:ResultsStateParams) { @@ -44,7 +61,11 @@ class ResultState extends MusicBeatSubState this.params = params; - resultsVariation = calculateVariation(params); + rank = calculateRank(params); + // rank = SHIT; + + // We build a lot of this stuff in the constructor, then place it in create(). + // This prevents having to do `null` checks everywhere. var fontLetters:String = "AaBbCcDdEeFfGgHhiIJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz:1234567890"; songName = new FlxBitmapText(FlxBitmapFont.fromMonospace(Paths.image("resultScreen/tardlingSpritesheet"), fontLetters, FlxPoint.get(49, 62))); @@ -55,18 +76,22 @@ class ResultState extends MusicBeatSubState difficulty = new FlxSprite(555); difficulty.zIndex = 1000; + + bgFlash = FlxGradient.createGradientFlxSprite(FlxG.width, FlxG.height, [0xFFFFEB69, 0xFFFFE66A], 90); + + resultsAnim = FunkinSprite.createSparrow(-200, -10, "resultScreen/results"); + + ratingsPopin = FunkinSprite.createSparrow(-150, 120, "resultScreen/ratingsPopin"); + + scorePopin = FunkinSprite.createSparrow(-180, 520, "resultScreen/scorePopin"); + + highscoreNew = new FlxSprite(310, 570); + + score = new ResultScore(35, 305, 10, params.scoreData.score); } override function create():Void { - FunkinSound.playMusic(resultsVariation.getMusicPath(), - { - startingVolume: 1.0, - overrideExisting: true, - restartTrack: true, - loop: resultsVariation.shouldMusicLoop() - }); - // Reset the camera zoom on the results screen. FlxG.camera.zoom = 1.0; @@ -75,10 +100,9 @@ class ResultState extends MusicBeatSubState bg.zIndex = 10; add(bg); - var bgFlash:FlxSprite = FlxGradient.createGradientFlxSprite(FlxG.width, FlxG.height, [0xFFFFEB69, 0xFFFFE66A], 90); bgFlash.scrollFactor.set(); bgFlash.visible = false; - bg.zIndex = 20; + bgFlash.zIndex = 20; add(bgFlash); // The sound system which falls into place behind the score text. Plays every time! @@ -92,13 +116,7 @@ class ResultState extends MusicBeatSubState soundSystem.zIndex = 1100; add(soundSystem); - var bfPerfect:Null = null; - var bfExcellent:Null = null; - var bfGood:Null = null; - var gfGood:Null = null; - var bfShit:Null = null; - - switch (resultsVariation) + switch (rank) { case PERFECT | PERFECT_GOLD | PERFECT_PLATINUM: bfPerfect = new FlxAtlasSprite(370, -180, Paths.animateAtlas("resultScreen/results-bf/resultsPERFECT", "shared")); @@ -107,8 +125,11 @@ class ResultState extends MusicBeatSubState add(bfPerfect); bfPerfect.anim.onComplete = () -> { - bfPerfect.anim.curFrame = 136; - bfPerfect.anim.play(); // unpauses this anim, since it's on PlayOnce! + if (bfPerfect != null) + { + bfPerfect.anim.curFrame = 137; + bfPerfect.anim.play(); // unpauses this anim, since it's on PlayOnce! + } }; case EXCELLENT: @@ -118,7 +139,10 @@ class ResultState extends MusicBeatSubState add(bfExcellent); bfExcellent.onAnimationFinish.add((animName) -> { - bfExcellent.playAnimation('Loop Start'); + if (bfExcellent != null) + { + bfExcellent.playAnimation('Loop Start'); + } }); case GOOD | GREAT: @@ -127,7 +151,10 @@ class ResultState extends MusicBeatSubState gfGood.visible = false; gfGood.zIndex = 500; gfGood.animation.finishCallback = _ -> { - gfGood.animation.play('clap', true, false, 9); + if (gfGood != null) + { + gfGood.animation.play('clap', true, false, 9); + } }; add(gfGood); @@ -136,7 +163,10 @@ class ResultState extends MusicBeatSubState bfGood.visible = false; bfGood.zIndex = 501; bfGood.animation.finishCallback = function(_) { - bfGood.animation.play('fall', true, false, 14); + if (bfGood != null) + { + bfGood.animation.play('fall', true, false, 14); + } }; add(bfGood); @@ -146,7 +176,10 @@ class ResultState extends MusicBeatSubState bfShit.zIndex = 500; add(bfShit); bfShit.onAnimationFinish.add((animName) -> { - bfShit.playAnimation('Loop Start'); + if (bfShit != null) + { + bfShit.playAnimation('Loop Start'); + } }); } @@ -189,25 +222,21 @@ class ResultState extends MusicBeatSubState blackTopBar.zIndex = 1010; add(blackTopBar); - var resultsAnim:FunkinSprite = FunkinSprite.createSparrow(-200, -10, "resultScreen/results"); resultsAnim.animation.addByPrefix("result", "results instance 1", 24, false); resultsAnim.animation.play("result"); resultsAnim.zIndex = 1200; add(resultsAnim); - var ratingsPopin:FunkinSprite = FunkinSprite.createSparrow(-150, 120, "resultScreen/ratingsPopin"); ratingsPopin.animation.addByPrefix("idle", "Categories", 24, false); ratingsPopin.visible = false; ratingsPopin.zIndex = 1200; add(ratingsPopin); - var scorePopin:FunkinSprite = FunkinSprite.createSparrow(-180, 520, "resultScreen/scorePopin"); scorePopin.animation.addByPrefix("score", "tally score", 24, false); scorePopin.visible = false; scorePopin.zIndex = 1200; add(scorePopin); - var highscoreNew:FlxSprite = new FlxSprite(310, 570); highscoreNew.frames = Paths.getSparrowAtlas("resultScreen/highscoreNew"); highscoreNew.animation.addByPrefix("new", "NEW HIGHSCORE", 24); highscoreNew.visible = false; @@ -249,7 +278,6 @@ class ResultState extends MusicBeatSubState var tallyMissed:TallyCounter = new TallyCounter(260, (hStuf * 9) + extraYOffset, params.scoreData.tallies.missed, 0xFFC68AE6); ratingGrp.add(tallyMissed); - var score:ResultScore = new ResultScore(35, 305, 10, params.scoreData.score); score.visible = false; score.zIndex = 1200; add(score); @@ -263,7 +291,68 @@ class ResultState extends MusicBeatSubState }); } - new FlxTimer().start(0.5, _ -> { + startRankTallySequence(); + + refresh(); + + super.create(); + } + + var rankTallyTimer:Null = null; + var clearPercentTarget:Int = 100; + var clearPercentLerp:Int = 0; + + function startRankTallySequence():Void + { + clearPercentTarget = Math.floor((params.scoreData.tallies.totalNotesHit) / params.scoreData.tallies.totalNotes * 100); + // clearPercentTarget = 97; + + var clearPercentText = new FlxText(FlxG.width / 2, FlxG.height / 2, 0, 'CLEAR: ${clearPercentLerp}%'); + clearPercentText.setFormat(Paths.font('vcr.ttf'), 64, FlxColor.BLACK, FlxTextAlign.RIGHT); + clearPercentText.zIndex = 1000; + add(clearPercentText); + + rankTallyTimer = new FlxTimer().start(1 / 24, _ -> { + // Tick up. + if (clearPercentLerp < clearPercentTarget) + { + clearPercentLerp++; + + clearPercentText.text = 'CLEAR: ${clearPercentLerp}%'; + FunkinSound.playOnce(Paths.sound('scrollMenu')); + } + + // Don't overshoot. + if (clearPercentLerp > clearPercentTarget) + { + clearPercentLerp = clearPercentTarget; + } + + if (clearPercentLerp == clearPercentTarget) + { + if (rankTallyTimer != null) + { + rankTallyTimer.destroy(); + rankTallyTimer = null; + } + + // Play confirm sound. + FunkinSound.playOnce(Paths.sound('confirmMenu')); + + new FlxTimer().start(1.0, _ -> { + remove(clearPercentText); + + afterRankTallySequence(); + }); + } + }, 0); // 0 = Loop until stopped + + if (ratingsPopin == null) + { + trace("Could not build ratingsPopin!"); + } + else + { ratingsPopin.animation.play("idle"); ratingsPopin.visible = true; @@ -286,76 +375,139 @@ class ResultState extends MusicBeatSubState highscoreNew.visible = false; } }; + } - switch (resultsVariation) + refresh(); + } + + function afterRankTallySequence():Void + { + FunkinSound.playMusic(rank.getMusicPath(), { - case PERFECT | PERFECT_GOLD | PERFECT_PLATINUM: - if (bfPerfect == null) - { - trace("Could not build PERFECT animation!"); - } - else - { - bfPerfect.visible = true; - bfPerfect.playAnimation(''); - } + startingVolume: 1.0, + overrideExisting: true, + restartTrack: true, + loop: rank.shouldMusicLoop() + }); - case EXCELLENT: - if (bfExcellent == null) - { - trace("Could not build EXCELLENT animation!"); - } - else + FlxG.sound.music.onComplete = () -> { + if (rank == SHIT) + { + FunkinSound.playMusic('bluu', { - bfExcellent.visible = true; - bfExcellent.playAnimation('Intro'); - } + startingVolume: 0.0, + overrideExisting: true, + restartTrack: true, + loop: true + }); + FlxG.sound.music.fadeIn(10.0, 0.0, 1.0); + } + } - case SHIT: - if (bfShit == null) - { - trace("Could not build SHIT animation!"); - } - else - { - bfShit.visible = true; - bfShit.playAnimation('Intro'); - } + switch (rank) + { + case PERFECT | PERFECT_GOLD | PERFECT_PLATINUM: + if (bfPerfect == null) + { + trace("Could not build PERFECT animation!"); + } + else + { + bfPerfect.visible = true; + bfPerfect.playAnimation(''); + + new FlxTimer().start((1 / 24) * 12, _ -> { + bgFlash.visible = true; + FlxTween.tween(bgFlash, {alpha: 0}, 0.4); + new FlxTimer().start((1 / 24) * 2, _ -> + { + // bgFlash.alpha = 0.5; + + // bgFlash.visible = false; + }); + }); + } - case GREAT | GOOD: - if (bfGood == null || gfGood == null) - { - trace("Could not build GOOD animation!"); - } - else - { - bfGood.animation.play('fall'); - bfGood.visible = true; - - new FlxTimer().start((1 / 24) * 12, _ -> { - bgFlash.visible = true; - FlxTween.tween(bgFlash, {alpha: 0}, 0.4); - new FlxTimer().start((1 / 24) * 2, _ -> - { - // bgFlash.alpha = 0.5; - - // bgFlash.visible = false; - }); - }); - - new FlxTimer().start((1 / 24) * 22, _ -> { - // plays about 22 frames (at 24fps timing) after bf spawns in - gfGood.animation.play('clap', true); - gfGood.visible = true; - }); - } - default: - } - }); + case EXCELLENT: + if (bfExcellent == null) + { + trace("Could not build EXCELLENT animation!"); + } + else + { + bfExcellent.visible = true; + bfExcellent.playAnimation('Intro'); + + new FlxTimer().start((1 / 24) * 12, _ -> { + bgFlash.visible = true; + FlxTween.tween(bgFlash, {alpha: 0}, 0.4); + new FlxTimer().start((1 / 24) * 2, _ -> + { + // bgFlash.alpha = 0.5; + + // bgFlash.visible = false; + }); + }); + } - refresh(); + case SHIT: + if (bfShit == null) + { + trace("Could not build SHIT animation!"); + } + else + { + bfShit.visible = true; + bfShit.playAnimation('Intro'); + + new FlxTimer().start((1 / 24) * 12, _ -> { + bgFlash.visible = true; + FlxTween.tween(bgFlash, {alpha: 0}, 0.4); + new FlxTimer().start((1 / 24) * 2, _ -> + { + // bgFlash.alpha = 0.5; + + // bgFlash.visible = false; + }); + }); + } - super.create(); + case GREAT | GOOD: + if (bfGood == null) + { + trace("Could not build GOOD animation!"); + } + else + { + bfGood.animation.play('fall'); + bfGood.visible = true; + + new FlxTimer().start((1 / 24) * 12, _ -> { + bgFlash.visible = true; + FlxTween.tween(bgFlash, {alpha: 0}, 0.4); + new FlxTimer().start((1 / 24) * 2, _ -> + { + // bgFlash.alpha = 0.5; + + // bgFlash.visible = false; + }); + }); + + new FlxTimer().start((1 / 24) * 22, _ -> { + // plays about 22 frames (at 24fps timing) after bf spawns in + if (gfGood != null) + { + gfGood.animation.play('clap', true); + gfGood.visible = true; + } + else + { + trace("Could not build GOOD animation!"); + } + }); + } + default: + } } function timerThenSongName():Void @@ -391,11 +543,8 @@ class ResultState extends MusicBeatSubState { super.draw(); - if (songName != null) - { - songName.clipRect = FlxRect.get(Math.max(0, 540 - songName.x), 0, FlxG.width, songName.height); - // PROBABLY SHOULD FIX MEMORY FREE OR WHATEVER THE PUT() FUNCTION DOES !!!! FEELS LIKE IT STUTTERS!!! - } + songName.clipRect = FlxRect.get(Math.max(0, 540 - songName.x), 0, FlxG.width, songName.height); + // PROBABLY SHOULD FIX MEMORY FREE OR WHATEVER THE PUT() FUNCTION DOES !!!! FEELS LIKE IT STUTTERS!!! // if (songName != null && songName.frame != null) // maskShaderSongName.frameUV = songName.frame.uv; @@ -448,17 +597,17 @@ class ResultState extends MusicBeatSubState super.update(elapsed); } - public static function calculateVariation(params:ResultsStateParams):ResultVariations + public static function calculateRank(params:ResultsStateParams):ResultRank { // Perfect (Platinum) is a Sick Full Clear var isPerfectPlat = (params.scoreData.tallies.sick + params.scoreData.tallies.good) == params.scoreData.tallies.totalNotes && params.scoreData.tallies.sick / params.scoreData.tallies.totalNotes >= Constants.RANK_PERFECT_PLAT_THRESHOLD; - if (isPerfectPlat) return ResultVariations.PERFECT_PLATINUM; + if (isPerfectPlat) return ResultRank.PERFECT_PLATINUM; // Perfect (Gold) is an 85% Sick Full Clear var isPerfectGold = (params.scoreData.tallies.sick + params.scoreData.tallies.good) == params.scoreData.tallies.totalNotes && params.scoreData.tallies.sick / params.scoreData.tallies.totalNotes >= Constants.RANK_PERFECT_GOLD_THRESHOLD; - if (isPerfectGold) return ResultVariations.PERFECT_GOLD; + if (isPerfectGold) return ResultRank.PERFECT_GOLD; // Else, use the standard grades @@ -467,28 +616,28 @@ class ResultState extends MusicBeatSubState if (clear == Constants.RANK_PERFECT_THRESHOLD) { - return ResultVariations.PERFECT; + return ResultRank.PERFECT; } else if (clear >= Constants.RANK_EXCELLENT_THRESHOLD) { - return ResultVariations.EXCELLENT; + return ResultRank.EXCELLENT; } else if (clear >= Constants.RANK_GREAT_THRESHOLD) { - return ResultVariations.GREAT; + return ResultRank.GREAT; } else if (clear >= Constants.RANK_GOOD_THRESHOLD) { - return ResultVariations.GOOD; + return ResultRank.GOOD; } else { - return ResultVariations.SHIT; + return ResultRank.SHIT; } } } -enum abstract ResultVariations(String) +enum abstract ResultRank(String) { var PERFECT_PLATINUM; var PERFECT_GOLD; From 6c2d18c72c7350ccefc4d9b15577c6092d663bed Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 11 May 2024 01:05:51 -0400 Subject: [PATCH 038/216] Resurrected difficulty stars, fixed flame animation, fixed Random showing an album. --- assets | 2 +- source/funkin/play/song/Song.hx | 21 ++++ source/funkin/ui/freeplay/AlbumRoll.hx | 44 ++++---- source/funkin/ui/freeplay/DifficultyStars.hx | 106 +++++++++++++++++++ source/funkin/ui/freeplay/FreeplayFlames.hx | 21 +++- source/funkin/ui/freeplay/FreeplayState.hx | 23 ++-- source/funkin/ui/freeplay/SongMenuItem.hx | 2 +- 7 files changed, 183 insertions(+), 36 deletions(-) create mode 100644 source/funkin/ui/freeplay/DifficultyStars.hx diff --git a/assets b/assets index 927578f482..fd112e293e 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 e71ae3213e..23d8d21986 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 + { + 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 35facf131f..50f4a432c8 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; 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 0000000000..51526bcbec --- /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 c20d858989..f6b6f5c3d4 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 = []; + 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 7b7543845a..2390682889 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; - 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 = 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 = null; public var currentDifficulty(default, set):String = Constants.DEFAULT_DIFFICULTY; - public var displayedVariations(default, null):Array = [Constants.DEFAULT_VARIATION]; + + var displayedVariations:Array = [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 f6d85e56e2..cf9b524827 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(); } From c0485fd1a23f0f683b79935245bc89af18d15e4a Mon Sep 17 00:00:00 2001 From: gamerbross Date: Sat, 11 May 2024 20:11:51 +0200 Subject: [PATCH 039/216] Fix Freeplay Crash when song is invalid --- source/funkin/ui/freeplay/FreeplayState.hx | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 7b7543845a..a359010d34 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -29,6 +29,7 @@ import funkin.graphics.shaders.StrokeShader; import funkin.input.Controls; import funkin.play.PlayStatePlaylist; import funkin.play.song.Song; +import funkin.ui.story.Level; import funkin.save.Save; import funkin.save.Save.SaveScoreData; import funkin.ui.AtlasText; @@ -191,10 +192,24 @@ class FreeplayState extends MusicBeatSubState // programmatically adds the songs via LevelRegistry and SongRegistry for (levelId in LevelRegistry.instance.listSortedLevelIds()) { - for (songId in LevelRegistry.instance.parseEntryData(levelId).songs) + var level:Level = LevelRegistry.instance.fetchEntry(levelId); + + if (level == null) + { + trace('[WARN] Could not find level with id (${levelId})'); + continue; + } + + for (songId in level.getSongs()) { var song:Song = SongRegistry.instance.fetchEntry(songId); + if (song == null) + { + trace('[WARN] Could not find song with id (${songId})'); + continue; + } + // Only display songs which actually have available charts for the current character. var availableDifficultiesForSong:Array = song.listDifficulties(displayedVariations, false); if (availableDifficultiesForSong.length == 0) continue; From 4f8a0dbebfdafb37955177d316e82dd26543dd39 Mon Sep 17 00:00:00 2001 From: JugieNoob Date: Sun, 12 May 2024 01:35:04 +0200 Subject: [PATCH 040/216] Fixed Freeplay Scrolling Issue --- source/funkin/ui/freeplay/FreeplayState.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 7b7543845a..b0d435274e 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -892,7 +892,7 @@ class FreeplayState extends MusicBeatSubState if (FlxG.mouse.wheel != 0) { dj.resetAFKTimer(); - changeSelection(-Math.round(FlxG.mouse.wheel / 4)); + changeSelection(-Math.round(FlxG.mouse.wheel)); } if (controls.UI_LEFT_P && !FlxG.keys.pressed.CONTROL) From 9d8c6365857d3d7ca99fffa1cc7dcd0cbf782c70 Mon Sep 17 00:00:00 2001 From: gamerbross Date: Sun, 12 May 2024 02:21:39 +0200 Subject: [PATCH 041/216] Add running without compiling VSCode --- .vscode/launch.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.vscode/launch.json b/.vscode/launch.json index 74f72b8261..b8fdb64d12 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -7,6 +7,13 @@ "type": "lime", "request": "launch" }, + { + // Launch in native/CPP on Windows/OSX/Linux (without compiling) + "name": "Debug", + "type": "lime", + "request": "launch", + "preLaunchTask": null + }, { // Launch in browser "name": "HTML5 Debug", From b22f09d4daf8784fdf46fec564abac21e20ede3e Mon Sep 17 00:00:00 2001 From: JugieNoob Date: Sun, 12 May 2024 02:21:59 +0200 Subject: [PATCH 042/216] Fixed Scrolling on HTML5 Platforms --- source/funkin/ui/freeplay/FreeplayState.hx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index b0d435274e..d4a89531c3 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -889,11 +889,24 @@ class FreeplayState extends MusicBeatSubState spamTimer = 0; } + #if !html5 if (FlxG.mouse.wheel != 0) { dj.resetAFKTimer(); changeSelection(-Math.round(FlxG.mouse.wheel)); } + #else + if (FlxG.mouse.wheel < 0) + { + dj.resetAFKTimer(); + changeSelection(-Math.round(FlxG.mouse.wheel / 4)); + } + else if (FlxG.mouse.wheel > 0) + { + dj.resetAFKTimer(); + changeSelection(-Math.round(FlxG.mouse.wheel / 8)); + } + #end if (controls.UI_LEFT_P && !FlxG.keys.pressed.CONTROL) { From 090e4fc6e886093267f612dbe9a1674d4e68518d Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Sun, 12 May 2024 02:42:02 +0200 Subject: [PATCH 043/216] Fixed doing actions when exiting Freeplay menu --- source/funkin/ui/freeplay/FreeplayState.hx | 1 + 1 file changed, 1 insertion(+) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 7b7543845a..52fc321969 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -910,6 +910,7 @@ class FreeplayState extends MusicBeatSubState if (controls.BACK) { + busy = true; FlxTween.globalManager.clear(); FlxTimer.globalManager.clear(); dj.onIntroDone.removeAll(); From 1f8954acad10d0c38ffa83ea736a2a31d596685d Mon Sep 17 00:00:00 2001 From: Noobz4Life Date: Sat, 11 May 2024 21:47:28 -0400 Subject: [PATCH 044/216] bump hxcodec version (fixes linux compilation) --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index a6e4467a91..b9986547af 100644 --- a/hmm.json +++ b/hmm.json @@ -80,7 +80,7 @@ "name": "hxCodec", "type": "git", "dir": null, - "ref": "c0c7f2680cc190c932a549c2e2fdd9b0ba2bd10e", + "ref": "2aa654b974507ab51ab1724d2d97e75726fd7d78", "url": "https://github.com/FunkinCrew/hxCodec" }, { From 42e69c1f73c088b387876d422ac943c126db7986 Mon Sep 17 00:00:00 2001 From: Noobz4Life Date: Sun, 12 May 2024 18:51:21 -0400 Subject: [PATCH 045/216] bump hxcodec version --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index b9986547af..288aa80b8b 100644 --- a/hmm.json +++ b/hmm.json @@ -80,7 +80,7 @@ "name": "hxCodec", "type": "git", "dir": null, - "ref": "2aa654b974507ab51ab1724d2d97e75726fd7d78", + "ref": "61b98a7a353b7f529a8fec84ed9afc919a2dffdd", "url": "https://github.com/FunkinCrew/hxCodec" }, { From b22dd4d7d44bdd9fda401ac50727e1cf6aae2c28 Mon Sep 17 00:00:00 2001 From: MaybeMaru <97055307+MaybeMaru@users.noreply.github.com> Date: Mon, 13 May 2024 02:18:57 +0200 Subject: [PATCH 046/216] Update Strumline.hx --- source/funkin/play/notes/Strumline.hx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/funkin/play/notes/Strumline.hx b/source/funkin/play/notes/Strumline.hx index 95e0668be2..b520f7b703 100644 --- a/source/funkin/play/notes/Strumline.hx +++ b/source/funkin/play/notes/Strumline.hx @@ -406,7 +406,7 @@ class Strumline extends FlxSpriteGroup if (Preferences.downscroll) { - holdNote.y = this.y + calculateNoteYPos(holdNote.strumTime, vwoosh) - holdNote.height + STRUMLINE_SIZE / 2; + holdNote.y = this.y - INITIAL_OFFSET + calculateNoteYPos(holdNote.strumTime, vwoosh) - holdNote.height + STRUMLINE_SIZE / 2; } else { @@ -435,7 +435,7 @@ class Strumline extends FlxSpriteGroup if (Preferences.downscroll) { - holdNote.y = this.y - holdNote.height + STRUMLINE_SIZE / 2; + holdNote.y = this.y - holdNote.height - INITIAL_OFFSET + STRUMLINE_SIZE / 2; // + STRUMLINE_SIZE / 2; } else { @@ -450,7 +450,7 @@ class Strumline extends FlxSpriteGroup if (Preferences.downscroll) { - holdNote.y = this.y + calculateNoteYPos(holdNote.strumTime, vwoosh) - holdNote.height + STRUMLINE_SIZE / 2; + holdNote.y = this.y - INITIAL_OFFSET + calculateNoteYPos(holdNote.strumTime, vwoosh) - holdNote.height + STRUMLINE_SIZE / 2; } else { From c270f61cac9b6fc5acca79206f7ccf5732d63dea Mon Sep 17 00:00:00 2001 From: MaybeMaru <97055307+MaybeMaru@users.noreply.github.com> Date: Mon, 13 May 2024 02:21:43 +0200 Subject: [PATCH 047/216] Update Strumline.hx --- source/funkin/play/notes/Strumline.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/play/notes/Strumline.hx b/source/funkin/play/notes/Strumline.hx index b520f7b703..a7a051a665 100644 --- a/source/funkin/play/notes/Strumline.hx +++ b/source/funkin/play/notes/Strumline.hx @@ -435,7 +435,7 @@ class Strumline extends FlxSpriteGroup if (Preferences.downscroll) { - holdNote.y = this.y - holdNote.height - INITIAL_OFFSET + STRUMLINE_SIZE / 2; // + STRUMLINE_SIZE / 2; + holdNote.y = this.y - holdNote.height - INITIAL_OFFSET + STRUMLINE_SIZE / 2; } else { From 0322a8388262ec8cda1eda8b69ceccd57652b6ef Mon Sep 17 00:00:00 2001 From: NotHyper-474 Date: Sun, 12 May 2024 23:16:12 -0300 Subject: [PATCH 048/216] Fix "Invalid argument '&'" error --- source/funkin/util/WindowUtil.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/util/WindowUtil.hx b/source/funkin/util/WindowUtil.hx index 763d84853e..9930d688c3 100644 --- a/source/funkin/util/WindowUtil.hx +++ b/source/funkin/util/WindowUtil.hx @@ -24,7 +24,7 @@ class WindowUtil { #if CAN_OPEN_LINKS #if linux - Sys.command('/usr/bin/xdg-open', [targetUrl, '&']); + Sys.command('/usr/bin/xdg-open ' + targetUrl + ' &'); #else // This should work on Windows and HTML5. FlxG.openURL(targetUrl); From 7df41ebc56d1dc712564702d9ff0dfe87e2c7009 Mon Sep 17 00:00:00 2001 From: richTrash21 Date: Mon, 13 May 2024 21:35:26 +0400 Subject: [PATCH 049/216] minor optimization --- source/funkin/play/character/BaseCharacter.hx | 43 ++++++++----------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/source/funkin/play/character/BaseCharacter.hx b/source/funkin/play/character/BaseCharacter.hx index 2796f8123b..4ef86c6a9f 100644 --- a/source/funkin/play/character/BaseCharacter.hx +++ b/source/funkin/play/character/BaseCharacter.hx @@ -420,7 +420,8 @@ class BaseCharacter extends Bopper { if (isSinging()) return; - if (['hey', 'cheer'].contains(getCurrentAnimation()) && !isAnimationFinished()) return; + var currentAnimation:String = getCurrentAnimation(); + if ((currentAnimation == 'hey' || currentAnimation == 'cheer') && !isAnimationFinished()) return; } // Prevent dancing while another animation is playing. @@ -441,19 +442,15 @@ class BaseCharacter extends Bopper switch (player) { case 1: - return [ - PlayerSettings.player1.controls.NOTE_LEFT_P, - PlayerSettings.player1.controls.NOTE_DOWN_P, - PlayerSettings.player1.controls.NOTE_UP_P, - PlayerSettings.player1.controls.NOTE_RIGHT_P, - ].contains(true); + return PlayerSettings.player1.controls.NOTE_LEFT_P + || PlayerSettings.player1.controls.NOTE_DOWN_P + || PlayerSettings.player1.controls.NOTE_UP_P + || PlayerSettings.player1.controls.NOTE_RIGHT_P; case 2: - return [ - PlayerSettings.player2.controls.NOTE_LEFT_P, - PlayerSettings.player2.controls.NOTE_DOWN_P, - PlayerSettings.player2.controls.NOTE_UP_P, - PlayerSettings.player2.controls.NOTE_RIGHT_P, - ].contains(true); + return PlayerSettings.player2.controls.NOTE_LEFT_P + || PlayerSettings.player2.controls.NOTE_DOWN_P + || PlayerSettings.player2.controls.NOTE_UP_P + || PlayerSettings.player2.controls.NOTE_RIGHT_P; } return false; } @@ -469,19 +466,15 @@ class BaseCharacter extends Bopper switch (player) { case 1: - return [ - PlayerSettings.player1.controls.NOTE_LEFT, - PlayerSettings.player1.controls.NOTE_DOWN, - PlayerSettings.player1.controls.NOTE_UP, - PlayerSettings.player1.controls.NOTE_RIGHT, - ].contains(true); + return PlayerSettings.player1.controls.NOTE_LEFT + || PlayerSettings.player1.controls.NOTE_DOWN + || PlayerSettings.player1.controls.NOTE_UP + || PlayerSettings.player1.controls.NOTE_RIGHT; case 2: - return [ - PlayerSettings.player2.controls.NOTE_LEFT, - PlayerSettings.player2.controls.NOTE_DOWN, - PlayerSettings.player2.controls.NOTE_UP, - PlayerSettings.player2.controls.NOTE_RIGHT, - ].contains(true); + return PlayerSettings.player2.controls.NOTE_LEFT + || PlayerSettings.player2.controls.NOTE_DOWN + || PlayerSettings.player2.controls.NOTE_UP + || PlayerSettings.player2.controls.NOTE_RIGHT; } return false; } From 24933f5bb9bc725b90b95db6a4b2782f0f71b9d5 Mon Sep 17 00:00:00 2001 From: Hyper_ Date: Mon, 13 May 2024 17:16:49 -0300 Subject: [PATCH 050/216] Replace concatenation with string interpolation --- source/funkin/util/WindowUtil.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/util/WindowUtil.hx b/source/funkin/util/WindowUtil.hx index 9930d688c3..07f6bc13ad 100644 --- a/source/funkin/util/WindowUtil.hx +++ b/source/funkin/util/WindowUtil.hx @@ -24,7 +24,7 @@ class WindowUtil { #if CAN_OPEN_LINKS #if linux - Sys.command('/usr/bin/xdg-open ' + targetUrl + ' &'); + Sys.command('/usr/bin/xdg-open $targetUrl &'); #else // This should work on Windows and HTML5. FlxG.openURL(targetUrl); From c5caa0331e4f167d632065e2a265b96def506bd9 Mon Sep 17 00:00:00 2001 From: MaybeMaru <97055307+MaybeMaru@users.noreply.github.com> Date: Mon, 13 May 2024 22:17:47 +0200 Subject: [PATCH 051/216] Update Strumline.hx --- source/funkin/play/notes/Strumline.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/play/notes/Strumline.hx b/source/funkin/play/notes/Strumline.hx index a7a051a665..07d4ab69b0 100644 --- a/source/funkin/play/notes/Strumline.hx +++ b/source/funkin/play/notes/Strumline.hx @@ -435,7 +435,7 @@ class Strumline extends FlxSpriteGroup if (Preferences.downscroll) { - holdNote.y = this.y - holdNote.height - INITIAL_OFFSET + STRUMLINE_SIZE / 2; + holdNote.y = this.y - INITIAL_OFFSET - holdNote.height + STRUMLINE_SIZE / 2; } else { From 4e935b47c66112239ac2c1ddf660ff9cfe08ee79 Mon Sep 17 00:00:00 2001 From: lemz Date: Tue, 14 May 2024 00:04:45 +0200 Subject: [PATCH 052/216] Update LoadingState.hx --- source/funkin/ui/transition/LoadingState.hx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/funkin/ui/transition/LoadingState.hx b/source/funkin/ui/transition/LoadingState.hx index 28533e35ba..9ac34465cf 100644 --- a/source/funkin/ui/transition/LoadingState.hx +++ b/source/funkin/ui/transition/LoadingState.hx @@ -162,7 +162,8 @@ class LoadingState extends MusicBeatSubState { targetShit = FlxMath.remapToRange(callbacks.numRemaining / callbacks.length, 1, 0, 0, 1); - loadBar.scale.x = FlxMath.lerp(loadBar.scale.x, targetShit, 0.50); + loadBar.setGraphicSize(Std.int(FlxG.width * targetShit), loadBar.height); + loadBar.updateHitbox(); FlxG.watch.addQuick('percentage?', callbacks.numRemaining / callbacks.length); } From 3810662f9fd55400be6d96808256b3c5e94be4ab Mon Sep 17 00:00:00 2001 From: rich <87835336+richTrash21@users.noreply.github.com> Date: Tue, 14 May 2024 04:20:23 +0400 Subject: [PATCH 053/216] freeplay optimization --- source/funkin/ui/freeplay/FreeplayState.hx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 7b7543845a..bdaa87ede3 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -527,6 +527,9 @@ class FreeplayState extends MusicBeatSubState orangeBackShit.visible = true; alsoOrangeLOL.visible = true; grpTxtScrolls.visible = true; + + // render optimisation + _parentState.persistentDraw = false; }); generateSongList(null, false); @@ -985,6 +988,8 @@ class FreeplayState extends MusicBeatSubState { clearDaCache(daSong.songName); } + // remove and destroy freeplay camera + FlxG.cameras.remove(FlxG.cameras.list[FlxG.cameras.list.length - 1]); } function changeDiff(change:Int = 0, force:Bool = false):Void From 59e409f8e65387a6000710046670c6d8262ad203 Mon Sep 17 00:00:00 2001 From: rich <87835336+richTrash21@users.noreply.github.com> Date: Tue, 14 May 2024 04:30:36 +0400 Subject: [PATCH 054/216] ensure that only freeplay camera gets destroyed --- source/funkin/ui/freeplay/FreeplayState.hx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index bdaa87ede3..0a2674c8ad 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -131,6 +131,7 @@ class FreeplayState extends MusicBeatSubState var exitMovers:ExitMoverData = new Map(); var stickerSubState:StickerSubState; + var funnyCam:FunkinCamera; public static var rememberedDifficulty:Null = Constants.DEFAULT_DIFFICULTY; public static var rememberedSongId:Null = 'tutorial'; @@ -535,7 +536,7 @@ class FreeplayState extends MusicBeatSubState generateSongList(null, false); // dedicated camera for the state so we don't need to fuk around with camera scrolls from the mainmenu / elsewhere - var funnyCam:FunkinCamera = new FunkinCamera('freeplayFunny', 0, 0, FlxG.width, FlxG.height); + funnyCam = new FunkinCamera('freeplayFunny', 0, 0, FlxG.width, FlxG.height); funnyCam.bgColor = FlxColor.TRANSPARENT; FlxG.cameras.add(funnyCam, false); @@ -989,7 +990,7 @@ class FreeplayState extends MusicBeatSubState clearDaCache(daSong.songName); } // remove and destroy freeplay camera - FlxG.cameras.remove(FlxG.cameras.list[FlxG.cameras.list.length - 1]); + FlxG.cameras.remove(funnyCam); } function changeDiff(change:Int = 0, force:Bool = false):Void From 259df760bc8d4eb3131b06d106b1ebee0493a7d3 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 13 May 2024 21:06:41 -0400 Subject: [PATCH 055/216] re-add lerp to load screen --- source/funkin/ui/transition/LoadingState.hx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/funkin/ui/transition/LoadingState.hx b/source/funkin/ui/transition/LoadingState.hx index 9ac34465cf..95c378b24d 100644 --- a/source/funkin/ui/transition/LoadingState.hx +++ b/source/funkin/ui/transition/LoadingState.hx @@ -162,7 +162,8 @@ class LoadingState extends MusicBeatSubState { targetShit = FlxMath.remapToRange(callbacks.numRemaining / callbacks.length, 1, 0, 0, 1); - loadBar.setGraphicSize(Std.int(FlxG.width * targetShit), loadBar.height); + var lerpWidth:Int = Std.int(FlxMath.lerp(loadBar.width, FlxG.width * targetShit, 0.2)); + loadBar.setGraphicSize(lerpWidth, loadBar.height); loadBar.updateHitbox(); FlxG.watch.addQuick('percentage?', callbacks.numRemaining / callbacks.length); } From be5756410000a98875f467507b2cf8fdcd83d288 Mon Sep 17 00:00:00 2001 From: TechnikTil <89487150+TechnikTil@users.noreply.github.com> Date: Tue, 14 May 2024 12:32:50 -0600 Subject: [PATCH 056/216] ludum dare 47 typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 62794b9240..4c6fd9e843 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Friday Night Funkin' -Friday Night Funkin' is a rhythm game. Built using HaxeFlixel for Ludem Dare 47. +Friday Night Funkin' is a rhythm game. Built using HaxeFlixel for Ludum Dare 47. This game was made with love to Newgrounds and it's community. Extra love to Tom Fulp. From 2434f6438146b5bfbb224c6a6c98cf8d932ecdc1 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 14 May 2024 21:21:47 -0400 Subject: [PATCH 057/216] web fix for scroll --- assets | 2 +- source/funkin/ui/freeplay/FreeplayState.hx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/assets b/assets index 783f22e741..962130b224 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 783f22e741c85223da7f3f815b28fc4c6f240cbc +Subproject commit 962130b2243a839106607d08a11599b1857bf8b3 diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index a3726e0252..1c7926f62e 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -899,7 +899,7 @@ class FreeplayState extends MusicBeatSubState if (FlxG.mouse.wheel < 0) { dj.resetAFKTimer(); - changeSelection(-Math.round(FlxG.mouse.wheel / 4)); + changeSelection(-Math.round(FlxG.mouse.wheel / 8)); } else if (FlxG.mouse.wheel > 0) { From 41686dce9e739783dfb98025b44427d12079a2be Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 14 May 2024 21:22:17 -0400 Subject: [PATCH 058/216] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 962130b224..783f22e741 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 962130b2243a839106607d08a11599b1857bf8b3 +Subproject commit 783f22e741c85223da7f3f815b28fc4c6f240cbc From ac06c2357735f90825586ccccd02a555d76e26ec Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 14 May 2024 21:41:42 -0400 Subject: [PATCH 059/216] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 783f22e741..962130b224 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 783f22e741c85223da7f3f815b28fc4c6f240cbc +Subproject commit 962130b2243a839106607d08a11599b1857bf8b3 From 4e6d980447cacc5cda32d74320b833593cb8e045 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 14 May 2024 22:10:13 -0400 Subject: [PATCH 060/216] 0.3.3 changelog --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7f8300476..2f0a0dcffc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,20 @@ All notable changes will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.3.3] - 2024-05-14 +### Changed +- Cleaned up some code in `PlayAnimationSongEvent.hx` (thanks BurgerBalls!) +### Fixed +- Fix Web Loading Bar (thanks lemz1!) +- Don't allow any more inputs when exiting freeplay (thanks gamerbros!) +- Fixed using mouse wheel to scroll on freeplay (thanks JugieNoob!) +- Fixed the reset's of the health icons, score, and notes when re-entering gameplay from gameover (thanks ImCodist!) +- Fixed the chart editor character selector's hitbox width (thanks MadBear422!) +- Fixed camera stutter once a wipe transition to the Main Menu completes (thanks ImCodist!) +- Fixed an issue where hold note would be invisible for a single frame (thanks ImCodist!) +- Fix tween accumulation on title screen when pressing Y multiple times (thanks TheGaloXx!) +- Fix for a game over easter egg so you don't accidentally exit it when viewing + ## [0.3.2] - 2024-05-03 ### Added - Added `,` and `.` keybinds to the Chart Editor. These place Focus Camera events at the playhead, for the opponent and player respectively. From 1a8706b0315ca0728536080cff49934a27e4861b Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 14 May 2024 22:11:57 -0400 Subject: [PATCH 061/216] project.xml version bump --- Project.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.xml b/Project.xml index fcfcfb9f35..24cdac2700 100644 --- a/Project.xml +++ b/Project.xml @@ -1,7 +1,7 @@ - + From e724373563564b7c68d3c8dbff4db48985b36b44 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 14 May 2024 22:16:57 -0400 Subject: [PATCH 062/216] more changeloggy --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f0a0dcffc..a852ca82d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed an issue where hold note would be invisible for a single frame (thanks ImCodist!) - Fix tween accumulation on title screen when pressing Y multiple times (thanks TheGaloXx!) - Fix for a game over easter egg so you don't accidentally exit it when viewing +- Fix a crash when querying FlxG.state in the crash handler +- Fix an issue where the Freeplay menu never displays 100% clear +- Chart debug key now properly returns you to the previous chart editor session if you were playtesting a chart (thanks nebulazorua!) +- Hopefully fixed Freeplay crashes on AMD gpu's ## [0.3.2] - 2024-05-03 ### Added From 28bee8397e4ee18bcc75e775ebec4e4bd20db151 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 14 May 2024 23:19:02 -0400 Subject: [PATCH 063/216] git submodules trolled --- .gitmodules | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 452c0089b7..be5e0aaa81 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "assets"] path = assets - url = https://github.com/FunkinCrew/Funkin-Assets-secret + url = https://github.com/FunkinCrew/funkin.assets [submodule "art"] path = art - url = https://github.com/FunkinCrew/Funkin-Art-secret + url = https://github.com/FunkinCrew/funkin.art From f21cff86be0d2ef57713d4fa8a09e2634d22e54a Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 14 May 2024 23:29:09 -0400 Subject: [PATCH 064/216] asset submod grr... --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 962130b224..783f22e741 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 962130b2243a839106607d08a11599b1857bf8b3 +Subproject commit 783f22e741c85223da7f3f815b28fc4c6f240cbc From e462b04b59e564ec5c10c1cd495484178736fcbf Mon Sep 17 00:00:00 2001 From: nebulazorua Date: Wed, 15 May 2024 20:46:08 +0800 Subject: [PATCH 065/216] does notesplash --- source/funkin/modding/events/ScriptEvent.hx | 13 ++++++++++--- source/funkin/play/PlayState.hx | 5 +++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/source/funkin/modding/events/ScriptEvent.hx b/source/funkin/modding/events/ScriptEvent.hx index ece7870fd7..dd55de23b0 100644 --- a/source/funkin/modding/events/ScriptEvent.hx +++ b/source/funkin/modding/events/ScriptEvent.hx @@ -141,7 +141,7 @@ class HitNoteScriptEvent extends NoteScriptEvent public var score:Int; /** - * Whether the judgement caused a combo break. + * If the hit causes a combo break. */ public var isComboBreak:Bool = false; @@ -150,19 +150,26 @@ class HitNoteScriptEvent extends NoteScriptEvent */ public var hitDiff:Float = 0; - public function new(note:NoteSprite, healthChange:Float, score:Int, judgement:String, isComboBreak:Bool, comboCount:Int = 0, hitDiff:Float = 0):Void + /** + * If the hit causes a notesplash + */ + public var doesNotesplash:Bool = false; + + public function new(note:NoteSprite, healthChange:Float, score:Int, judgement:String, isComboBreak:Bool, comboCount:Int = 0, hitDiff:Float = 0, + doesNotesplash:Bool = false):Void { super(NOTE_HIT, note, healthChange, comboCount, true); this.score = score; this.judgement = judgement; this.isComboBreak = isComboBreak; + this.doesNotesplash = doesNotesplash; this.hitDiff = hitDiff; } public override function toString():String { return 'HitNoteScriptEvent(note=' + note + ', comboCount=' + comboCount + ', judgement=' + judgement + ', score=' + score + ', isComboBreak=' - + isComboBreak + ', hitDiff=' + hitDiff + ')'; + + isComboBreak + ', hitDiff=' + hitDiff + ', doesNotesplash=' + doesNotesplash + ')'; } } diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index cdd8c7d71c..f563c8d2e7 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -2400,7 +2400,8 @@ class PlayState extends MusicBeatSubState } // Send the note hit event. - var event:HitNoteScriptEvent = new HitNoteScriptEvent(note, healthChange, score, daRating, isComboBreak, Highscore.tallies.combo + 1, noteDiff); + var event:HitNoteScriptEvent = new HitNoteScriptEvent(note, healthChange, score, daRating, isComboBreak, Highscore.tallies.combo + 1, noteDiff, + daRating == 'sick'); dispatchEvent(event); // Calling event.cancelEvent() skips all the other logic! Neat! @@ -2409,7 +2410,7 @@ class PlayState extends MusicBeatSubState Highscore.tallies.totalNotesHit++; // Display the hit on the strums playerStrumline.hitNote(note, !isComboBreak); - if (daRating == 'sick') playerStrumline.playNoteSplash(note.noteData.getDirection()); + if (event.doesNotesplash) playerStrumline.playNoteSplash(note.noteData.getDirection()); if (note.isHoldNote && note.holdNoteSprite != null) playerStrumline.playNoteHoldCover(note.holdNoteSprite); vocals.playerVolume = 1; From 96de434d75d459ebeb13fdfc1aba7adf57b9d705 Mon Sep 17 00:00:00 2001 From: Burgerballs <107233412+Burgerballs@users.noreply.github.com> Date: Wed, 15 May 2024 17:17:09 +0100 Subject: [PATCH 066/216] multiplicative added!! + sum tween fixes --- source/funkin/play/PlayState.hx | 16 ++++++++++++++++ source/funkin/play/event/ScrollSpeedEvent.hx | 19 ++++++++++++++----- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 4ce778fc1c..d63854d3f3 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -3259,6 +3259,8 @@ class PlayState extends MusicBeatSubState cancelCameraZoomTween(); } + var prevScrollTargets:Array = []; // used to snap scroll speed when things go unruely + /** * The magical function that shall tween the scroll speed. */ @@ -3266,6 +3268,18 @@ class PlayState extends MusicBeatSubState { // Cancel the current tween if it's active. cancelScrollSpeedTweens(); + + // Snap to previous event value to prevent the tween breaking when another event cancels the previous tween. + for (i in prevScrollTargets) + { + var value:Float = i[1]; + var strum:Strumline = Reflect.getProperty(this, i[0]); + strum.scrollSpeed = value; + } + + // for next event, clean array. + prevScrollTargets = []; + for (i in strumlines) { var value:Float = speed; @@ -3282,6 +3296,8 @@ class PlayState extends MusicBeatSubState 'scrollSpeed': value }, duration, {ease: ease})); } + // make sure charts dont break if the charter is dumb and stupid + prevScrollTargets.push([value, i]); } } diff --git a/source/funkin/play/event/ScrollSpeedEvent.hx b/source/funkin/play/event/ScrollSpeedEvent.hx index 22da45b0cb..9abd4be90a 100644 --- a/source/funkin/play/event/ScrollSpeedEvent.hx +++ b/source/funkin/play/event/ScrollSpeedEvent.hx @@ -36,6 +36,7 @@ class ScrollSpeedEvent extends SongEvent static final DEFAULT_SCROLL:Float = 1; static final DEFAULT_DURATION:Float = 4.0; static final DEFAULT_EASE:String = 'linear'; + static final DEFAULT_ABSOLUTE:Bool = false; static final DEFAULT_STRUMLINE:String = 'both'; // my special little trick public override function handleEvent(data:SongEventData):Void @@ -51,12 +52,14 @@ class ScrollSpeedEvent extends SongEvent var strumline:String = data.getString('strumline') ?? DEFAULT_STRUMLINE; + var absolute:Bool = data.getBool('absolute') ?? DEFAULT_ABSOLUTE; + var strumlineNames:Array = []; - if (scroll == 0) + if (!absolute) { - // if the parameter is set to 0, reset the scroll speed to normal. - scroll = PlayState.instance?.currentChart?.scrollSpeed ?? 1.0; + // If absolute is set to false, do the awesome multiplicative thing + scroll = scroll * (PlayState.instance?.currentChart?.scrollSpeed ?? 1.0); } switch (strumline) @@ -103,8 +106,8 @@ class ScrollSpeedEvent extends SongEvent return new SongEventSchema([ { name: 'scroll', - title: 'Scroll Amount', - defaultValue: 0.0, + title: 'Target Value', + defaultValue: 1.0, step: 0.1, type: SongEventFieldType.FLOAT, units: 'x' @@ -157,6 +160,12 @@ class ScrollSpeedEvent extends SongEvent defaultValue: 'both', type: SongEventFieldType.ENUM, keys: ['Both' => 'both', 'Player' => 'player', 'Opponent' => 'opponent'] + }, + { + name: 'absolute', + title: 'Absolute', + defaultValue: false, + type: SongEventFieldType.BOOL, } ]); } From eaf998adf71a0e9060f6604dd23e070f3036d8f4 Mon Sep 17 00:00:00 2001 From: Burgerballs <107233412+Burgerballs@users.noreply.github.com> Date: Wed, 15 May 2024 17:24:04 +0100 Subject: [PATCH 067/216] curse burgerballs --- source/funkin/play/PlayState.hx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index d63854d3f3..176f3817c2 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -827,6 +827,8 @@ class PlayState extends MusicBeatSubState { if (!assertChartExists()) return; + prevScrollTargets = []; + dispatchEvent(new ScriptEvent(SONG_RETRY)); resetCamera(); @@ -3272,8 +3274,8 @@ class PlayState extends MusicBeatSubState // Snap to previous event value to prevent the tween breaking when another event cancels the previous tween. for (i in prevScrollTargets) { - var value:Float = i[1]; - var strum:Strumline = Reflect.getProperty(this, i[0]); + var value:Float = i[0]; + var strum:Strumline = Reflect.getProperty(this, i[1]); strum.scrollSpeed = value; } From 21333ee8dc5a65600e5b886f608bd76de8967233 Mon Sep 17 00:00:00 2001 From: Burgerballs <107233412+Burgerballs@users.noreply.github.com> Date: Wed, 15 May 2024 17:26:03 +0100 Subject: [PATCH 068/216] burgerbugs require burgerfixes --- source/funkin/play/notes/SustainTrail.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/play/notes/SustainTrail.hx b/source/funkin/play/notes/SustainTrail.hx index 9155c9b0a7..b358d7f033 100644 --- a/source/funkin/play/notes/SustainTrail.hx +++ b/source/funkin/play/notes/SustainTrail.hx @@ -168,7 +168,6 @@ class SustainTrail extends FlxSprite if (s < 0.0) s = 0.0; if (sustainLength == s) return s; - graphicHeight = sustainHeight(s, parentStrumline?.scrollSpeed ?? 1.0); this.sustainLength = s; triggerRedraw(); return this.sustainLength; @@ -176,6 +175,7 @@ class SustainTrail extends FlxSprite function triggerRedraw() { + graphicHeight = sustainHeight(sustainLength, parentStrumline?.scrollSpeed ?? 1.0); updateClipping(); updateHitbox(); } From f1a0692c51335f7d5ccf4236b3775f55fef7cd86 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Wed, 15 May 2024 22:50:34 +0200 Subject: [PATCH 069/216] Fix ChartingState GameOver Crashes --- source/funkin/play/GameOverSubState.hx | 3 +++ source/funkin/play/PlayState.hx | 7 +++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/source/funkin/play/GameOverSubState.hx b/source/funkin/play/GameOverSubState.hx index c3abbcf3e2..4d50d75cc4 100644 --- a/source/funkin/play/GameOverSubState.hx +++ b/source/funkin/play/GameOverSubState.hx @@ -162,6 +162,8 @@ class GameOverSubState extends MusicBeatSubState @:nullSafety(Off) function setCameraTarget():Void { + if (PlayState.instance.isMinimalMode || boyfriend == null) return; + // Assign a camera follow point to the boyfriend's position. cameraFollowPoint = new FlxObject(PlayState.instance.cameraFollowPoint.x, PlayState.instance.cameraFollowPoint.y, 1, 1); cameraFollowPoint.x = boyfriend.getGraphicMidpoint().x; @@ -254,6 +256,7 @@ class GameOverSubState extends MusicBeatSubState this.close(); if (FlxG.sound.music != null) FlxG.sound.music.pause(); // Don't reset song position! PlayState.instance.close(); // This only works because PlayState is a substate! + return; } else if (PlayStatePlaylist.isStoryMode) { diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index a9ca09ce84..43dd485cf9 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1092,8 +1092,11 @@ class PlayState extends MusicBeatSubState healthBar.value = healthLerp; - iconP1.updatePosition(); - iconP2.updatePosition(); + if (!isMinimalMode) + { + iconP1.updatePosition(); + iconP2.updatePosition(); + } // Transition to the game over substate. var gameOverSubState = new GameOverSubState( From b10872e8e89b7e9ab404c57a26a7d8646b1921b9 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Fri, 17 May 2024 23:51:07 +0200 Subject: [PATCH 070/216] Fix TitleState late start + enter spam crash --- source/funkin/ui/title/TitleState.hx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/source/funkin/ui/title/TitleState.hx b/source/funkin/ui/title/TitleState.hx index 49bef5e4a4..c9b3619e93 100644 --- a/source/funkin/ui/title/TitleState.hx +++ b/source/funkin/ui/title/TitleState.hx @@ -67,9 +67,11 @@ class TitleState extends MusicBeatState // DEBUG BULLSHIT // netConnection.addEventListener(MouseEvent.MOUSE_DOWN, overlay_onMouseDown); - new FlxTimer().start(1, function(tmr:FlxTimer) { + if (!initialized) new FlxTimer().start(1, function(tmr:FlxTimer) { startIntro(); }); + else + startIntro(); } function client_onMetaData(metaData:Dynamic) @@ -118,7 +120,7 @@ class TitleState extends MusicBeatState function startIntro():Void { - playMenuMusic(); + if (!initialized || FlxG.sound.music == null) playMenuMusic(); persistentUpdate = true; @@ -231,7 +233,7 @@ class TitleState extends MusicBeatState overrideExisting: true, restartTrack: true }); - // Fade from 0.0 to 0.7 over 4 seconds + // Fade from 0.0 to 1 over 4 seconds if (shouldFadeIn) FlxG.sound.music.fadeIn(4.0, 0.0, 1.0); } From 85b9de1de937b29863e3a3ff92542b1218cf99e4 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Fri, 17 May 2024 23:53:43 +0200 Subject: [PATCH 071/216] Allow Volume Keys while watching Toy Commercial (AttractState) --- source/funkin/ui/title/AttractState.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/title/AttractState.hx b/source/funkin/ui/title/AttractState.hx index 3ecb756dfa..c5a3d05048 100644 --- a/source/funkin/ui/title/AttractState.hx +++ b/source/funkin/ui/title/AttractState.hx @@ -89,7 +89,7 @@ class AttractState extends MusicBeatState super.update(elapsed); // If the user presses any button, skip the video. - if (FlxG.keys.justPressed.ANY) + if (FlxG.keys.justPressed.ANY && !controls.VOLUME_MUTE && !controls.VOLUME_UP && !controls.VOLUME_DOWN) { onAttractEnd(); } From b6b93bb0c6686b3a89100c3b625dfd912380cda6 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 17 May 2024 20:26:34 -0400 Subject: [PATCH 072/216] Added clear percent, rank name, and background text. --- .vscode/launch.json | 9 +- .vscode/settings.json | 5 + assets | 2 +- source/funkin/InitState.hx | 24 ++ source/funkin/play/PlayState.hx | 18 +- source/funkin/play/ResultState.hx | 288 ++++++++++-------- .../play/components/ClearPercentCounter.hx | 96 ++++++ source/funkin/save/Save.hx | 8 +- .../funkin/save/migrator/SaveDataMigrator.hx | 15 +- source/funkin/ui/freeplay/FreeplayState.hx | 4 +- source/funkin/ui/mainmenu/MainMenuState.hx | 3 +- 11 files changed, 311 insertions(+), 161 deletions(-) create mode 100644 source/funkin/play/components/ClearPercentCounter.hx diff --git a/.vscode/launch.json b/.vscode/launch.json index 74f72b8261..6dc1dc0082 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -3,10 +3,17 @@ "configurations": [ { // Launch in native/CPP on Windows/OSX/Linux - "name": "Lime", + "name": "Lime Build+Debug", "type": "lime", "request": "launch" }, + { + // Launch in native/CPP on Windows/OSX/Linux + "name": "Lime Debug (No Build)", + "type": "lime", + "request": "launch", + "preLaunchTask": null + }, { // Launch in browser "name": "HTML5 Debug", diff --git a/.vscode/settings.json b/.vscode/settings.json index a8a67245b2..26fe0b0427 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -155,6 +155,11 @@ "target": "hl", "args": ["-debug", "-DDIALOGUE"] }, + { + "label": "Windows / Debug (Results Screen Test)", + "target": "windows", + "args": ["-debug", "-DRESULTS"] + }, { "label": "Windows / Debug (Straight to Chart Editor)", "target": "windows", diff --git a/assets b/assets index fd112e293e..ce7dabffbe 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit fd112e293ee0f823ee98d5b8bd8a85e934f772f6 +Subproject commit ce7dabffbebc154c9dda1f01e92dbef83e3405ab diff --git a/source/funkin/InitState.hx b/source/funkin/InitState.hx index 00d34fadba..6a52eaf5d8 100644 --- a/source/funkin/InitState.hx +++ b/source/funkin/InitState.hx @@ -214,6 +214,30 @@ class InitState extends FlxState #elseif STAGEBUILD // -DSTAGEBUILD FlxG.switchState(() -> new funkin.ui.debug.stage.StageBuilderState()); + #elseif RESULTS + // -DRESULTS + FlxG.switchState(() -> new funkin.play.ResultState( + { + storyMode: false, + title: "CUM SONG", + isNewHighscore: true, + scoreData: + { + score: 1_234_567, + tallies: + { + sick: 130, + good: 69, + bad: 69, + shit: 69, + missed: 69, + combo: 69, + maxCombo: 69, + totalNotesHit: 140, + totalNotes: 2000, + } + }, + })); #elseif ANIMDEBUG // -DANIMDEBUG FlxG.switchState(() -> new funkin.ui.debug.anim.DebugBoundingState()); diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 44ad819c41..3e1d4cac8d 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -2777,6 +2777,7 @@ class PlayState extends MusicBeatSubState deathCounter = 0; var isNewHighscore = false; + var prevScoreData:Null = Save.instance.getSongScore(currentSong.id, currentDifficulty); if (currentSong != null && currentSong.validScore) { @@ -2796,7 +2797,6 @@ class PlayState extends MusicBeatSubState totalNotesHit: Highscore.tallies.totalNotesHit, totalNotes: Highscore.tallies.totalNotes, }, - accuracy: Highscore.tallies.totalNotesHit / Highscore.tallies.totalNotes, }; // adds current song data into the tallies for the level (story levels) @@ -2833,7 +2833,7 @@ class PlayState extends MusicBeatSubState score: PlayStatePlaylist.campaignScore, tallies: { - // TODO: Sum up the values for the whole level! + // TODO: Sum up the values for the whole week! sick: 0, good: 0, bad: 0, @@ -2844,7 +2844,6 @@ class PlayState extends MusicBeatSubState totalNotesHit: 0, totalNotes: 0, }, - accuracy: Highscore.tallies.totalNotesHit / Highscore.tallies.totalNotes, }; if (Save.instance.isLevelHighScore(PlayStatePlaylist.campaignId, PlayStatePlaylist.campaignDifficulty, data)) @@ -2930,11 +2929,11 @@ class PlayState extends MusicBeatSubState { if (rightGoddamnNow) { - moveToResultsScreen(isNewHighscore); + moveToResultsScreen(isNewHighscore, prevScoreData); } else { - zoomIntoResultsScreen(isNewHighscore); + zoomIntoResultsScreen(isNewHighscore, prevScoreData); } } } @@ -3008,7 +3007,7 @@ class PlayState extends MusicBeatSubState /** * Play the camera zoom animation and then move to the results screen once it's done. */ - function zoomIntoResultsScreen(isNewHighscore:Bool):Void + function zoomIntoResultsScreen(isNewHighscore:Bool, ?prevScoreData:SaveScoreData):Void { trace('WENT TO RESULTS SCREEN!'); @@ -3048,7 +3047,7 @@ class PlayState extends MusicBeatSubState FlxTween.tween(camHUD, {alpha: 0}, 0.6, { onComplete: function(_) { - moveToResultsScreen(isNewHighscore); + moveToResultsScreen(isNewHighscore, prevScoreData); } }); @@ -3081,7 +3080,7 @@ class PlayState extends MusicBeatSubState /** * Move to the results screen right goddamn now. */ - function moveToResultsScreen(isNewHighscore:Bool):Void + function moveToResultsScreen(isNewHighscore:Bool, ?prevScoreData:SaveScoreData):Void { persistentUpdate = false; vocals.stop(); @@ -3093,6 +3092,8 @@ class PlayState extends MusicBeatSubState { storyMode: PlayStatePlaylist.isStoryMode, title: PlayStatePlaylist.isStoryMode ? ('${PlayStatePlaylist.campaignTitle}') : ('${currentChart.songName} by ${currentChart.songArtist}'), + prevScoreData: prevScoreData, + difficultyId: currentDifficulty, scoreData: { score: PlayStatePlaylist.isStoryMode ? PlayStatePlaylist.campaignScore : songScore, @@ -3108,7 +3109,6 @@ class PlayState extends MusicBeatSubState totalNotesHit: talliesToUse.totalNotesHit, totalNotes: talliesToUse.totalNotes, }, - accuracy: Highscore.tallies.totalNotesHit / Highscore.tallies.totalNotes, }, isNewHighscore: isNewHighscore }); diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index df3134b9d5..d038b77854 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -24,6 +24,7 @@ import funkin.save.Save; import funkin.save.Save.SaveScoreData; import funkin.graphics.shaders.LeftMaskShader; import funkin.play.components.TallyCounter; +import funkin.play.components.ClearPercentCounter; /** * The state for the results screen after a song or week is finished. @@ -109,7 +110,7 @@ class ResultState extends MusicBeatSubState var soundSystem:FlxSprite = FunkinSprite.createSparrow(-15, -180, 'resultScreen/soundSystem'); soundSystem.animation.addByPrefix("idle", "sound system", 24, false); soundSystem.visible = false; - new FlxTimer().start(0.4, _ -> { + new FlxTimer().start(0.3, _ -> { soundSystem.animation.play("idle"); soundSystem.visible = true; }); @@ -118,7 +119,7 @@ class ResultState extends MusicBeatSubState switch (rank) { - case PERFECT | PERFECT_GOLD | PERFECT_PLATINUM: + case PERFECT | PERFECT_GOLD: bfPerfect = new FlxAtlasSprite(370, -180, Paths.animateAtlas("resultScreen/results-bf/resultsPERFECT", "shared")); bfPerfect.visible = false; bfPerfect.zIndex = 500; @@ -183,22 +184,7 @@ class ResultState extends MusicBeatSubState }); } - var diffSpr:String = switch (PlayState.instance.currentDifficulty) - { - case 'easy': - 'difEasy'; - case 'normal': - 'difNormal'; - case 'hard': - 'difHard'; - case 'erect': - 'difErect'; - case 'nightmare': - 'difNightmare'; - case _: - 'difNormal'; - } - + var diffSpr:String = 'dif${params?.difficultyId ?? 'Normal'}'; difficulty.loadGraphic(Paths.image("resultScreen/" + diffSpr)); add(difficulty); @@ -208,7 +194,7 @@ class ResultState extends MusicBeatSubState speedOfTween.x = -1.0 * Math.cos(angleRad); speedOfTween.y = -1.0 * Math.sin(angleRad); - timerThenSongName(); + timerThenSongName(1.0); songName.shader = maskShaderSongName; difficulty.shader = maskShaderDifficulty; @@ -218,24 +204,40 @@ class ResultState extends MusicBeatSubState var blackTopBar:FlxSprite = new FlxSprite().loadGraphic(Paths.image("resultScreen/topBarBlack")); blackTopBar.y = -blackTopBar.height; - FlxTween.tween(blackTopBar, {y: 0}, 0.4, {ease: FlxEase.quartOut, startDelay: 0.5}); + FlxTween.tween(blackTopBar, {y: 0}, 0.4, {ease: FlxEase.quartOut}); blackTopBar.zIndex = 1010; add(blackTopBar); resultsAnim.animation.addByPrefix("result", "results instance 1", 24, false); - resultsAnim.animation.play("result"); + resultsAnim.visible = false; resultsAnim.zIndex = 1200; add(resultsAnim); + new FlxTimer().start(0.3, _ -> { + resultsAnim.visible = true; + resultsAnim.animation.play("result"); + }); ratingsPopin.animation.addByPrefix("idle", "Categories", 24, false); ratingsPopin.visible = false; ratingsPopin.zIndex = 1200; add(ratingsPopin); + new FlxTimer().start(1.0, _ -> { + ratingsPopin.visible = true; + ratingsPopin.animation.play("idle"); + }); scorePopin.animation.addByPrefix("score", "tally score", 24, false); scorePopin.visible = false; scorePopin.zIndex = 1200; add(scorePopin); + new FlxTimer().start(1.0, _ -> { + scorePopin.visible = true; + scorePopin.animation.play("score"); + scorePopin.animation.finishCallback = anim -> { + score.visible = true; + score.animateNumbers(); + }; + }); highscoreNew.frames = Paths.getSparrowAtlas("resultScreen/highscoreNew"); highscoreNew.animation.addByPrefix("new", "NEW HIGHSCORE", 24); @@ -285,13 +287,26 @@ class ResultState extends MusicBeatSubState for (ind => rating in ratingGrp.members) { rating.visible = false; - new FlxTimer().start((0.3 * ind) + 0.55, _ -> { + new FlxTimer().start((0.3 * ind) + 1.20, _ -> { rating.visible = true; FlxTween.tween(rating, {curNumber: rating.neededNumber}, 0.5, {ease: FlxEase.quartOut}); }); } - startRankTallySequence(); + ratingsPopin.animation.finishCallback = anim -> { + startRankTallySequence(); + + if (params.isNewHighscore ?? false) + { + highscoreNew.visible = true; + highscoreNew.animation.play("new"); + FlxTween.tween(highscoreNew, {y: highscoreNew.y + 10}, 0.8, {ease: FlxEase.quartOut}); + } + else + { + highscoreNew.visible = false; + } + }; refresh(); @@ -304,48 +319,43 @@ class ResultState extends MusicBeatSubState function startRankTallySequence():Void { - clearPercentTarget = Math.floor((params.scoreData.tallies.totalNotesHit) / params.scoreData.tallies.totalNotes * 100); - // clearPercentTarget = 97; + clearPercentTarget = Math.floor((params.scoreData.tallies.sick + params.scoreData.tallies.good) / params.scoreData.tallies.totalNotes * 100); + clearPercentTarget = 100; - var clearPercentText = new FlxText(FlxG.width / 2, FlxG.height / 2, 0, 'CLEAR: ${clearPercentLerp}%'); - clearPercentText.setFormat(Paths.font('vcr.ttf'), 64, FlxColor.BLACK, FlxTextAlign.RIGHT); - clearPercentText.zIndex = 1000; - add(clearPercentText); + clearPercentLerp = Std.int(Math.max(0, clearPercentTarget - 36)); - rankTallyTimer = new FlxTimer().start(1 / 24, _ -> { - // Tick up. - if (clearPercentLerp < clearPercentTarget) + var clearPercentCounter:ClearPercentCounter = new ClearPercentCounter(FlxG.width / 2 + 300, FlxG.height / 2 - 100, clearPercentTarget); + clearPercentCounter.curNumber = clearPercentLerp; + FlxTween.tween(clearPercentCounter, {curNumber: clearPercentTarget}, 1.5, { - clearPercentLerp++; - - clearPercentText.text = 'CLEAR: ${clearPercentLerp}%'; - FunkinSound.playOnce(Paths.sound('scrollMenu')); - } - - // Don't overshoot. - if (clearPercentLerp > clearPercentTarget) - { - clearPercentLerp = clearPercentTarget; - } + ease: FlxEase.quartOut, + onUpdate: _ -> { + // Only play the tick sound if the number increased. + if (clearPercentLerp != clearPercentCounter.curNumber) + { + clearPercentLerp = clearPercentCounter.curNumber; + FunkinSound.playOnce(Paths.sound('scrollMenu')); + } + }, + onComplete: _ -> { + // Play confirm sound. + FunkinSound.playOnce(Paths.sound('confirmMenu')); - if (clearPercentLerp == clearPercentTarget) - { - if (rankTallyTimer != null) - { - rankTallyTimer.destroy(); - rankTallyTimer = null; - } + // Flash background. + bgFlash.visible = true; + FlxTween.tween(bgFlash, {alpha: 0}, 0.4); - // Play confirm sound. - FunkinSound.playOnce(Paths.sound('confirmMenu')); + displayRankText(); - new FlxTimer().start(1.0, _ -> { - remove(clearPercentText); + new FlxTimer().start(2.0, _ -> { + // remove(clearPercentCounter); - afterRankTallySequence(); - }); - } - }, 0); // 0 = Loop until stopped + afterRankTallySequence(); + }); + } + }); + clearPercentCounter.zIndex = 450; + add(clearPercentCounter); if (ratingsPopin == null) { @@ -353,18 +363,15 @@ class ResultState extends MusicBeatSubState } else { - ratingsPopin.animation.play("idle"); - ratingsPopin.visible = true; + // ratingsPopin.animation.play("idle"); + // ratingsPopin.visible = true; ratingsPopin.animation.finishCallback = anim -> { - scorePopin.animation.play("score"); - scorePopin.animation.finishCallback = anim -> { - score.visible = true; - score.animateNumbers(); - }; - scorePopin.visible = true; + // scorePopin.animation.play("score"); + + // scorePopin.visible = true; - if (params.isNewHighscore) + if (params.isNewHighscore ?? false) { highscoreNew.visible = true; highscoreNew.animation.play("new"); @@ -380,6 +387,23 @@ class ResultState extends MusicBeatSubState refresh(); } + function displayRankText():Void + { + var rankTextVert:FunkinSprite = FunkinSprite.create(FlxG.width - 64, 100, rank.getVerTextAsset()); + rankTextVert.zIndex = 2000; + add(rankTextVert); + + for (i in 0...10) + { + var rankTextBack:FunkinSprite = FunkinSprite.create(FlxG.width / 2 - 80, 50, rank.getHorTextAsset()); + rankTextBack.y += (rankTextBack.height * i / 2) + 10; + rankTextBack.zIndex = 100; + add(rankTextBack); + } + + refresh(); + } + function afterRankTallySequence():Void { FunkinSound.playMusic(rank.getMusicPath(), @@ -406,7 +430,7 @@ class ResultState extends MusicBeatSubState switch (rank) { - case PERFECT | PERFECT_GOLD | PERFECT_PLATINUM: + case PERFECT | PERFECT_GOLD: if (bfPerfect == null) { trace("Could not build PERFECT animation!"); @@ -415,17 +439,6 @@ class ResultState extends MusicBeatSubState { bfPerfect.visible = true; bfPerfect.playAnimation(''); - - new FlxTimer().start((1 / 24) * 12, _ -> { - bgFlash.visible = true; - FlxTween.tween(bgFlash, {alpha: 0}, 0.4); - new FlxTimer().start((1 / 24) * 2, _ -> - { - // bgFlash.alpha = 0.5; - - // bgFlash.visible = false; - }); - }); } case EXCELLENT: @@ -437,17 +450,6 @@ class ResultState extends MusicBeatSubState { bfExcellent.visible = true; bfExcellent.playAnimation('Intro'); - - new FlxTimer().start((1 / 24) * 12, _ -> { - bgFlash.visible = true; - FlxTween.tween(bgFlash, {alpha: 0}, 0.4); - new FlxTimer().start((1 / 24) * 2, _ -> - { - // bgFlash.alpha = 0.5; - - // bgFlash.visible = false; - }); - }); } case SHIT: @@ -459,17 +461,6 @@ class ResultState extends MusicBeatSubState { bfShit.visible = true; bfShit.playAnimation('Intro'); - - new FlxTimer().start((1 / 24) * 12, _ -> { - bgFlash.visible = true; - FlxTween.tween(bgFlash, {alpha: 0}, 0.4); - new FlxTimer().start((1 / 24) * 2, _ -> - { - // bgFlash.alpha = 0.5; - - // bgFlash.visible = false; - }); - }); } case GREAT | GOOD: @@ -482,17 +473,6 @@ class ResultState extends MusicBeatSubState bfGood.animation.play('fall'); bfGood.visible = true; - new FlxTimer().start((1 / 24) * 12, _ -> { - bgFlash.visible = true; - FlxTween.tween(bgFlash, {alpha: 0}, 0.4); - new FlxTimer().start((1 / 24) * 2, _ -> - { - // bgFlash.alpha = 0.5; - - // bgFlash.visible = false; - }); - }); - new FlxTimer().start((1 / 24) * 22, _ -> { // plays about 22 frames (at 24fps timing) after bf spawns in if (gfGood != null) @@ -510,7 +490,7 @@ class ResultState extends MusicBeatSubState } } - function timerThenSongName():Void + function timerThenSongName(timerLength:Float = 3.0):Void { movingSongStuff = false; @@ -526,7 +506,7 @@ class ResultState extends MusicBeatSubState FlxTween.tween(songName, {y: diffYTween - 35 - fuckedupnumber}, 0.5, {ease: FlxEase.expoOut, startDelay: 0.9}); songName.x = (difficulty.x + difficulty.width) + 20; - new FlxTimer().start(3, _ -> { + new FlxTimer().start(timerLength, _ -> { var tempSpeed = FlxPoint.get(speedOfTween.x, speedOfTween.y); speedOfTween.set(0, 0); @@ -600,33 +580,29 @@ class ResultState extends MusicBeatSubState public static function calculateRank(params:ResultsStateParams):ResultRank { // Perfect (Platinum) is a Sick Full Clear - var isPerfectPlat = (params.scoreData.tallies.sick + params.scoreData.tallies.good) == params.scoreData.tallies.totalNotes - && params.scoreData.tallies.sick / params.scoreData.tallies.totalNotes >= Constants.RANK_PERFECT_PLAT_THRESHOLD; - if (isPerfectPlat) return ResultRank.PERFECT_PLATINUM; - - // Perfect (Gold) is an 85% Sick Full Clear - var isPerfectGold = (params.scoreData.tallies.sick + params.scoreData.tallies.good) == params.scoreData.tallies.totalNotes - && params.scoreData.tallies.sick / params.scoreData.tallies.totalNotes >= Constants.RANK_PERFECT_GOLD_THRESHOLD; + var isPerfectGold = params.scoreData.tallies.sick == params.scoreData.tallies.totalNotes; if (isPerfectGold) return ResultRank.PERFECT_GOLD; // Else, use the standard grades + // Grade % (only good and sick), 1.00 is a full combo + var grade = (params.scoreData.tallies.sick + params.scoreData.tallies.good) / params.scoreData.tallies.totalNotes; // Clear % (including bad and shit). 1.00 is a full clear but not a full combo var clear = (params.scoreData.tallies.totalNotesHit) / params.scoreData.tallies.totalNotes; - if (clear == Constants.RANK_PERFECT_THRESHOLD) + if (grade == Constants.RANK_PERFECT_THRESHOLD) { return ResultRank.PERFECT; } - else if (clear >= Constants.RANK_EXCELLENT_THRESHOLD) + else if (grade >= Constants.RANK_EXCELLENT_THRESHOLD) { return ResultRank.EXCELLENT; } - else if (clear >= Constants.RANK_GREAT_THRESHOLD) + else if (grade >= Constants.RANK_GREAT_THRESHOLD) { return ResultRank.GREAT; } - else if (clear >= Constants.RANK_GOOD_THRESHOLD) + else if (grade >= Constants.RANK_GOOD_THRESHOLD) { return ResultRank.GOOD; } @@ -639,7 +615,6 @@ class ResultState extends MusicBeatSubState enum abstract ResultRank(String) { - var PERFECT_PLATINUM; var PERFECT_GOLD; var PERFECT; var EXCELLENT; @@ -651,8 +626,6 @@ enum abstract ResultRank(String) { switch (abstract) { - case PERFECT_PLATINUM: - return 'resultsPERFECT'; case PERFECT_GOLD: return 'resultsPERFECT'; case PERFECT: @@ -665,6 +638,8 @@ enum abstract ResultRank(String) return 'resultsNORMAL'; case SHIT: return 'resultsSHIT'; + default: + return 'resultsNORMAL'; } } @@ -672,8 +647,6 @@ enum abstract ResultRank(String) { switch (abstract) { - case PERFECT_PLATINUM: - return true; case PERFECT_GOLD: return true; case PERFECT: @@ -690,6 +663,48 @@ enum abstract ResultRank(String) return false; } } + + public function getHorTextAsset() + { + switch (abstract) + { + case PERFECT_GOLD: + return 'resultScreen/rankText/rankScrollPERFECT'; + case PERFECT: + return 'resultScreen/rankText/rankScrollPERFECT'; + case EXCELLENT: + return 'resultScreen/rankText/rankScrollEXCELLENT'; + case GREAT: + return 'resultScreen/rankText/rankScrollGREAT'; + case GOOD: + return 'resultScreen/rankText/rankScrollGOOD'; + case SHIT: + return 'resultScreen/rankText/rankScrollLOSS'; + default: + return 'resultScreen/rankText/rankScrollGOOD'; + } + } + + public function getVerTextAsset() + { + switch (abstract) + { + case PERFECT_GOLD: + return 'resultScreen/rankText/rankTextPERFECT'; + case PERFECT: + return 'resultScreen/rankText/rankTextPERFECT'; + case EXCELLENT: + return 'resultScreen/rankText/rankTextEXCELLENT'; + case GREAT: + return 'resultScreen/rankText/rankTextGREAT'; + case GOOD: + return 'resultScreen/rankText/rankTextGOOD'; + case SHIT: + return 'resultScreen/rankText/rankTextLOSS'; + default: + return 'resultScreen/rankText/rankTextGOOD'; + } + } } typedef ResultsStateParams = @@ -707,10 +722,21 @@ typedef ResultsStateParams = /** * Whether the displayed score is a new highscore */ - var isNewHighscore:Bool; + var ?isNewHighscore:Bool; + + /** + * The difficulty ID of the song/week we just played. + * @default Normal + */ + var ?difficultyId:String; /** * The score, accuracy, and judgements. */ var scoreData:SaveScoreData; + + /** + * The previous score data, used for rank comparision. + */ + var ?prevScoreData:SaveScoreData; }; diff --git a/source/funkin/play/components/ClearPercentCounter.hx b/source/funkin/play/components/ClearPercentCounter.hx new file mode 100644 index 0000000000..4c03ec3a90 --- /dev/null +++ b/source/funkin/play/components/ClearPercentCounter.hx @@ -0,0 +1,96 @@ +package funkin.play.components; + +import funkin.graphics.FunkinSprite; +import flixel.FlxSprite; +import flixel.group.FlxGroup.FlxTypedGroup; +import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup; +import flixel.math.FlxMath; +import flixel.tweens.FlxEase; +import flixel.tweens.FlxTween; +import flixel.text.FlxText.FlxTextAlign; +import funkin.util.MathUtil; + +/** + * Numerical counters used to display the clear percent. + */ +class ClearPercentCounter extends FlxTypedSpriteGroup +{ + public var curNumber:Int = 0; + public var neededNumber:Int = 0; + + public function new(x:Float, y:Float, neededNumber:Int = 0) + { + super(x, y); + + this.neededNumber = neededNumber; + + var clearPercentText:FunkinSprite = FunkinSprite.create(0, 0, 'resultScreen/clearPercent/clearPercentText'); + add(clearPercentText); + + if (curNumber == neededNumber) drawNumbers(); + } + + var tmr:Float = 0; + + override function update(elapsed:Float) + { + super.update(elapsed); + + if (curNumber < neededNumber) drawNumbers(); + } + + function drawNumbers() + { + var seperatedScore:Array = []; + var tempCombo:Int = Math.round(curNumber); + + var fullNumberDigits:Int = Std.int(Math.max(1, Math.ceil(MathUtil.logBase(10, neededNumber)))); + + while (tempCombo != 0) + { + seperatedScore.push(tempCombo % 10); + tempCombo = Math.floor(tempCombo / 10); + } + + if (seperatedScore.length == 0) seperatedScore.push(0); + + seperatedScore.reverse(); + + for (ind => num in seperatedScore) + { + var digitIndex = ind + 1; + if (digitIndex >= members.length) + { + var xPos = (digitIndex - 1) * (72 * this.scale.x); + var yPos = 72; + // Three digits = LRL so two different numbers aren't adjacent to each other. + var variant:Bool = (fullNumberDigits % 2 != 0) ? (digitIndex % 2 == 0) : (digitIndex % 2 == 1); + var numb:ClearPercentNumber = new ClearPercentNumber(xPos, yPos, num); + numb.scale.set(this.scale.x, this.scale.y); + add(numb); + } + else + { + members[digitIndex].animation.play(Std.string(num)); + } + } + } +} + +class ClearPercentNumber extends FlxSprite +{ + public function new(x:Float, y:Float, digit:Int, variant:Bool = false) + { + super(x, y); + + frames = Paths.getSparrowAtlas('resultScreen/clearPercent/clearPercentNumber${variant ? 'Right' : 'Left'}'); + + for (i in 0...10) + { + animation.addByPrefix('$i', 'number $i 0', 24, false); + } + + animation.play('$digit'); + updateHitbox(); + } +} diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx index acbe59edda..08614e307b 100644 --- a/source/funkin/save/Save.hx +++ b/source/funkin/save/Save.hx @@ -53,7 +53,8 @@ class Save public function new(?data:RawSaveData) { if (data == null) this.data = Save.getDefault(); - else this.data = data; + else + this.data = data; } public static function getDefault():RawSaveData @@ -809,11 +810,6 @@ typedef SaveScoreData = * The count of each judgement hit. */ var tallies:SaveScoreTallyData; - - /** - * The accuracy percentage. - */ - var accuracy:Float; } typedef SaveScoreTallyData = diff --git a/source/funkin/save/migrator/SaveDataMigrator.hx b/source/funkin/save/migrator/SaveDataMigrator.hx index 3ed59e7268..9e308cb10e 100644 --- a/source/funkin/save/migrator/SaveDataMigrator.hx +++ b/source/funkin/save/migrator/SaveDataMigrator.hx @@ -118,7 +118,7 @@ class SaveDataMigrator var scoreDataEasy:SaveScoreData = { score: inputSaveData.songScores.get('${levelId}-easy') ?? 0, - accuracy: inputSaveData.songCompletion.get('${levelId}-easy') ?? 0.0, + // accuracy: inputSaveData.songCompletion.get('${levelId}-easy') ?? 0.0, tallies: { sick: 0, @@ -137,7 +137,7 @@ class SaveDataMigrator var scoreDataNormal:SaveScoreData = { score: inputSaveData.songScores.get('${levelId}') ?? 0, - accuracy: inputSaveData.songCompletion.get('${levelId}') ?? 0.0, + // accuracy: inputSaveData.songCompletion.get('${levelId}') ?? 0.0, tallies: { sick: 0, @@ -156,7 +156,7 @@ class SaveDataMigrator var scoreDataHard:SaveScoreData = { score: inputSaveData.songScores.get('${levelId}-hard') ?? 0, - accuracy: inputSaveData.songCompletion.get('${levelId}-hard') ?? 0.0, + // accuracy: inputSaveData.songCompletion.get('${levelId}-hard') ?? 0.0, tallies: { sick: 0, @@ -178,7 +178,6 @@ class SaveDataMigrator var scoreDataEasy:SaveScoreData = { score: 0, - accuracy: 0, tallies: { sick: 0, @@ -196,14 +195,13 @@ class SaveDataMigrator for (songId in songIds) { scoreDataEasy.score = Std.int(Math.max(scoreDataEasy.score, inputSaveData.songScores.get('${songId}-easy') ?? 0)); - scoreDataEasy.accuracy = Math.max(scoreDataEasy.accuracy, inputSaveData.songCompletion.get('${songId}-easy') ?? 0.0); + // scoreDataEasy.accuracy = Math.max(scoreDataEasy.accuracy, inputSaveData.songCompletion.get('${songId}-easy') ?? 0.0); } result.setSongScore(songIds[0], 'easy', scoreDataEasy); var scoreDataNormal:SaveScoreData = { score: 0, - accuracy: 0, tallies: { sick: 0, @@ -221,14 +219,13 @@ class SaveDataMigrator for (songId in songIds) { scoreDataNormal.score = Std.int(Math.max(scoreDataNormal.score, inputSaveData.songScores.get('${songId}') ?? 0)); - scoreDataNormal.accuracy = Math.max(scoreDataNormal.accuracy, inputSaveData.songCompletion.get('${songId}') ?? 0.0); + // scoreDataNormal.accuracy = Math.max(scoreDataNormal.accuracy, inputSaveData.songCompletion.get('${songId}') ?? 0.0); } result.setSongScore(songIds[0], 'normal', scoreDataNormal); var scoreDataHard:SaveScoreData = { score: 0, - accuracy: 0, tallies: { sick: 0, @@ -246,7 +243,7 @@ class SaveDataMigrator for (songId in songIds) { scoreDataHard.score = Std.int(Math.max(scoreDataHard.score, inputSaveData.songScores.get('${songId}-hard') ?? 0)); - scoreDataHard.accuracy = Math.max(scoreDataHard.accuracy, inputSaveData.songCompletion.get('${songId}-hard') ?? 0.0); + // scoreDataHard.accuracy = Math.max(scoreDataHard.accuracy, inputSaveData.songCompletion.get('${songId}-hard') ?? 0.0); } result.setSongScore(songIds[0], 'hard', scoreDataHard); } diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 2390682889..dbf223dc83 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -998,7 +998,7 @@ class FreeplayState extends MusicBeatSubState { var songScore:SaveScoreData = Save.instance.getSongScore(grpCapsules.members[curSelected].songData.songId, currentDifficulty); intendedScore = songScore?.score ?? 0; - intendedCompletion = songScore?.accuracy ?? 0.0; + intendedCompletion = songScore == null ? 0.0 : ((songScore.tallies.sick + songScore.tallies.good) / songScore.tallies.totalNotes); rememberedDifficulty = currentDifficulty; } else @@ -1196,7 +1196,7 @@ class FreeplayState extends MusicBeatSubState { var songScore:SaveScoreData = Save.instance.getSongScore(daSongCapsule.songData.songId, currentDifficulty); intendedScore = songScore?.score ?? 0; - intendedCompletion = songScore?.accuracy ?? 0.0; + intendedCompletion = songScore == null ? 0.0 : ((songScore.tallies.sick + songScore.tallies.good) / songScore.tallies.totalNotes); diffIdsCurrent = daSongCapsule.songData.songDifficulties; rememberedSongId = daSongCapsule.songData.songId; changeDiff(); diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index 466dbbb904..fcff41dfdf 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -355,8 +355,7 @@ class MainMenuState extends MusicBeatState maxCombo: 0, totalNotesHit: 0, totalNotes: 0, - }, - accuracy: 0, + } }); } #end From 6b42da09026d4c50eecff357cc2557c3f0ff9312 Mon Sep 17 00:00:00 2001 From: SanicBTW <58010536+SanicBTW@users.noreply.github.com> Date: Sat, 18 May 2024 09:04:27 +0200 Subject: [PATCH 073/216] Keep the consistency in Conductor --- source/funkin/Conductor.hx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/funkin/Conductor.hx b/source/funkin/Conductor.hx index 0d63cb6cce..e73b2860c7 100644 --- a/source/funkin/Conductor.hx +++ b/source/funkin/Conductor.hx @@ -430,7 +430,7 @@ class Conductor else if (currentTimeChange != null && this.songPosition > 0.0) { // roundDecimal prevents representing 8 as 7.9999999 - this.currentStepTime = FlxMath.roundDecimal((currentTimeChange.beatTime * 4) + (this.songPosition - currentTimeChange.timeStamp) / stepLengthMs, 6); + this.currentStepTime = FlxMath.roundDecimal((currentTimeChange.beatTime * Constants.STEPS_PER_BEAT) + (this.songPosition - currentTimeChange.timeStamp) / stepLengthMs, 6); this.currentBeatTime = currentStepTime / Constants.STEPS_PER_BEAT; this.currentMeasureTime = currentStepTime / stepsPerMeasure; this.currentStep = Math.floor(currentStepTime); @@ -564,7 +564,7 @@ class Conductor if (ms >= timeChange.timeStamp) { lastTimeChange = timeChange; - resultStep = lastTimeChange.beatTime * 4; + resultStep = lastTimeChange.beatTime * Constants.STEPS_PER_BEAT; } else { @@ -600,7 +600,7 @@ class Conductor var lastTimeChange:SongTimeChange = timeChanges[0]; for (timeChange in timeChanges) { - if (stepTime >= timeChange.beatTime * 4) + if (stepTime >= timeChange.beatTime * Constants.STEPS_PER_BEAT) { lastTimeChange = timeChange; resultMs = lastTimeChange.timeStamp; @@ -613,7 +613,7 @@ class Conductor } var lastStepLengthMs:Float = ((Constants.SECS_PER_MIN / lastTimeChange.bpm) * Constants.MS_PER_SEC) / timeSignatureNumerator; - resultMs += (stepTime - lastTimeChange.beatTime * 4) * lastStepLengthMs; + resultMs += (stepTime - lastTimeChange.beatTime * Constants.STEPS_PER_BEAT) * lastStepLengthMs; return resultMs; } From a73d65757cafa8b6eed97dd45ab5c1b1e28b6684 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Sun, 19 May 2024 00:23:51 +0200 Subject: [PATCH 074/216] Fix Options Menu not enabled in transIn --- source/funkin/ui/options/OptionsState.hx | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/source/funkin/ui/options/OptionsState.hx b/source/funkin/ui/options/OptionsState.hx index 81331b266f..e7950f0bd1 100644 --- a/source/funkin/ui/options/OptionsState.hx +++ b/source/funkin/ui/options/OptionsState.hx @@ -25,6 +25,8 @@ class OptionsState extends MusicBeatState override function create():Void { + persistentUpdate = true; + var menuBG = new FlxSprite().loadGraphic(Paths.image('menuBG')); var hsv = new HSVShader(); hsv.hue = -0.6; @@ -55,8 +57,6 @@ class OptionsState extends MusicBeatState setPage(Controls); } - // disable for intro transition - currentPage.enabled = false; super.create(); } @@ -86,13 +86,6 @@ class OptionsState extends MusicBeatState } } - override function finishTransIn() - { - super.finishTransIn(); - - currentPage.enabled = true; - } - function switchPage(name:PageName) { // TODO: Animate this transition? From bc1c15e91cdac75f7402840dbaf06811b8d44153 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Sun, 19 May 2024 00:29:46 +0200 Subject: [PATCH 075/216] Add Remember Selection to MainMenuState --- source/funkin/ui/mainmenu/MainMenuState.hx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index 7a21a6e8f5..558a348345 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -42,6 +42,8 @@ class MainMenuState extends MusicBeatState var magenta:FlxSprite; var camFollow:FlxObject; + static var rememberedSelectedIndex:Int = 0; + override function create():Void { #if discord_rpc @@ -137,6 +139,8 @@ class MainMenuState extends MusicBeatState menuItem.scrollFactor.y = 0.4; } + menuItems.selectItem(rememberedSelectedIndex); + resetCamStuff(); subStateOpened.add(sub -> { @@ -285,6 +289,8 @@ class MainMenuState extends MusicBeatState function startExitState(state:NextState):Void { menuItems.enabled = false; // disable for exit + rememberedSelectedIndex = menuItems.selectedIndex; + var duration = 0.4; menuItems.forEach(function(item) { if (menuItems.selectedIndex != item.ID) From e0867643d04dd5624d0684fe8eca0fd7fd2efab9 Mon Sep 17 00:00:00 2001 From: lemz Date: Sun, 19 May 2024 01:39:30 +0200 Subject: [PATCH 076/216] fix the setgraphicsize stuff --- source/funkin/ui/transition/LoadingState.hx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/source/funkin/ui/transition/LoadingState.hx b/source/funkin/ui/transition/LoadingState.hx index 95c378b24d..bc26ad97a1 100644 --- a/source/funkin/ui/transition/LoadingState.hx +++ b/source/funkin/ui/transition/LoadingState.hx @@ -57,8 +57,7 @@ class LoadingState extends MusicBeatSubState funkay.scrollFactor.set(); funkay.screenCenter(); - loadBar = new FunkinSprite(0, FlxG.height - 20).makeSolidColor(FlxG.width, 10, 0xFFff16d2); - loadBar.screenCenter(X); + loadBar = new FunkinSprite(0, FlxG.height - 20).makeSolidColor(0, 10, 0xFFff16d2); add(loadBar); initSongsManifest().onComplete(function(lib) { @@ -163,8 +162,15 @@ class LoadingState extends MusicBeatSubState targetShit = FlxMath.remapToRange(callbacks.numRemaining / callbacks.length, 1, 0, 0, 1); var lerpWidth:Int = Std.int(FlxMath.lerp(loadBar.width, FlxG.width * targetShit, 0.2)); - loadBar.setGraphicSize(lerpWidth, loadBar.height); - loadBar.updateHitbox(); + // this if-check prevents the setGraphicSize function + // from setting the width of the loadBar to the height of the loadBar + // this is a behaviour that is implemented in the setGraphicSize function + // if the width parameter is equal to 0 + if (lerpWidth > 0) + { + loadBar.setGraphicSize(lerpWidth, loadBar.height); + loadBar.updateHitbox(); + } FlxG.watch.addQuick('percentage?', callbacks.numRemaining / callbacks.length); } From faf7a0643cd83bbf99ac99e302c6aaf2bcdebd30 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sun, 19 May 2024 01:47:36 -0400 Subject: [PATCH 077/216] Tinkered with ghost tapping some, leaving it off for now tho. --- source/funkin/play/PlayState.hx | 24 ++++++++++++++---------- source/funkin/play/notes/Strumline.hx | 14 ++++++++++++++ 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 44ad819c41..5b95c467c4 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -2298,8 +2298,6 @@ class PlayState extends MusicBeatSubState var notesInRange:Array = playerStrumline.getNotesMayHit(); var holdNotesInRange:Array = playerStrumline.getHoldNotesHitOrMissed(); - // If there are notes in range, pressing a key will cause a ghost miss. - var notesByDirection:Array> = [[], [], [], []]; for (note in notesInRange) @@ -2321,17 +2319,27 @@ class PlayState extends MusicBeatSubState // Play the strumline animation. playerStrumline.playPress(input.noteDirection); + trace('PENALTY Score: ${songScore}'); } - else if (Constants.GHOST_TAPPING && (holdNotesInRange.length + notesInRange.length > 0) && notesInDirection.length == 0) + else if (Constants.GHOST_TAPPING && (!playerStrumline.mayGhostTap()) && notesInDirection.length == 0) { - // Pressed a wrong key with no notes nearby AND with notes in a different direction available. + // Pressed a wrong key with notes visible on-screen. // Perform a ghost miss (anti-spam). ghostNoteMiss(input.noteDirection, notesInRange.length > 0); // Play the strumline animation. playerStrumline.playPress(input.noteDirection); + trace('PENALTY Score: ${songScore}'); + } + else if (notesInDirection.length == 0) + { + // Press a key with no penalty. + + // Play the strumline animation. + playerStrumline.playPress(input.noteDirection); + trace('NO PENALTY Score: ${songScore}'); } - else if (notesInDirection.length > 0) + else { // Choose the first note, deprioritizing low priority notes. var targetNote:Null = notesInDirection.find((note) -> !note.lowPriority); @@ -2341,17 +2349,13 @@ class PlayState extends MusicBeatSubState // Judge and hit the note. trace('Hit note! ${targetNote.noteData}'); goodNoteHit(targetNote, input); + trace('Score: ${songScore}'); notesInDirection.remove(targetNote); // Play the strumline animation. playerStrumline.playConfirm(input.noteDirection); } - else - { - // Play the strumline animation. - playerStrumline.playPress(input.noteDirection); - } } while (inputReleaseQueue.length > 0) diff --git a/source/funkin/play/notes/Strumline.hx b/source/funkin/play/notes/Strumline.hx index 6a18f17d5b..220b6723c5 100644 --- a/source/funkin/play/notes/Strumline.hx +++ b/source/funkin/play/notes/Strumline.hx @@ -171,6 +171,20 @@ class Strumline extends FlxSpriteGroup updateNotes(); } + /** + * Returns `true` if no notes are in range of the strumline and the player can spam without penalty. + */ + public function mayGhostTap():Bool + { + // TODO: Refine this. Only querying "can be hit" is too tight but "is being rendered" is too loose. + // Also, if you just hit a note, there should be a (short) period where this is off so you can't spam. + + // If there are any notes on screen, we can't ghost tap. + return notes.members.filter(function(note:NoteSprite) { + return note != null && note.alive && !note.hasBeenHit; + }).length == 0; + } + /** * Return notes that are within `Constants.HIT_WINDOW` ms of the strumline. * @return An array of `NoteSprite` objects. From 228ac66cc2e9966c0eae1f4bc050477ff9cba93f Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sun, 19 May 2024 01:48:51 -0400 Subject: [PATCH 078/216] Credit the song's charter in the pause menu. --- assets | 2 +- source/funkin/data/song/SongData.hx | 3 + source/funkin/data/song/SongRegistry.hx | 2 +- .../data/song/importer/FNFLegacyImporter.hx | 2 +- source/funkin/play/PauseSubState.hx | 89 +++++++++++++++++-- source/funkin/play/song/Song.hx | 15 ++++ .../ui/debug/charting/ChartEditorState.hx | 2 +- .../toolboxes/ChartEditorMetadataToolbox.hx | 16 ++++ source/funkin/util/Constants.hx | 5 ++ 9 files changed, 127 insertions(+), 9 deletions(-) diff --git a/assets b/assets index fd112e293e..778e16705b 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit fd112e293ee0f823ee98d5b8bd8a85e934f772f6 +Subproject commit 778e16705b30af85087f627594c22f4b5ba6141a diff --git a/source/funkin/data/song/SongData.hx b/source/funkin/data/song/SongData.hx index 26380947af..bd25139a79 100644 --- a/source/funkin/data/song/SongData.hx +++ b/source/funkin/data/song/SongData.hx @@ -30,6 +30,9 @@ class SongMetadata implements ICloneable @:default("Unknown") public var artist:String; + @:optional + public var charter:Null = null; + @:optional @:default(96) public var divisions:Null; // Optional field diff --git a/source/funkin/data/song/SongRegistry.hx b/source/funkin/data/song/SongRegistry.hx index 277dcd9e1f..a3305c4ecc 100644 --- a/source/funkin/data/song/SongRegistry.hx +++ b/source/funkin/data/song/SongRegistry.hx @@ -20,7 +20,7 @@ class SongRegistry extends BaseRegistry * Handle breaking changes by incrementing this value * and adding migration to the `migrateStageData()` function. */ - public static final SONG_METADATA_VERSION:thx.semver.Version = "2.2.2"; + public static final SONG_METADATA_VERSION:thx.semver.Version = "2.2.3"; public static final SONG_METADATA_VERSION_RULE:thx.semver.VersionRule = "2.2.x"; diff --git a/source/funkin/data/song/importer/FNFLegacyImporter.hx b/source/funkin/data/song/importer/FNFLegacyImporter.hx index ab2abda8e1..fdfac7f726 100644 --- a/source/funkin/data/song/importer/FNFLegacyImporter.hx +++ b/source/funkin/data/song/importer/FNFLegacyImporter.hx @@ -36,7 +36,7 @@ class FNFLegacyImporter { trace('Migrating song metadata from FNF Legacy.'); - var songMetadata:SongMetadata = new SongMetadata('Import', 'Kawai Sprite', 'default'); + var songMetadata:SongMetadata = new SongMetadata('Import', Constants.DEFAULT_ARTIST, 'default'); var hadError:Bool = false; diff --git a/source/funkin/play/PauseSubState.hx b/source/funkin/play/PauseSubState.hx index fb9d9b4e29..c345871a9a 100644 --- a/source/funkin/play/PauseSubState.hx +++ b/source/funkin/play/PauseSubState.hx @@ -101,6 +101,10 @@ class PauseSubState extends MusicBeatSubState */ static final MUSIC_FINAL_VOLUME:Float = 0.75; + static final CHARTER_FADE_DELAY:Float = 15.0; + + static final CHARTER_FADE_DURATION:Float = 0.75; + /** * Defines which pause music to use. */ @@ -163,6 +167,12 @@ class PauseSubState extends MusicBeatSubState */ var metadataDeaths:FlxText; + /** + * A text object which displays the current song's artist. + * Fades to the charter after a period before fading back. + */ + var metadataArtist:FlxText; + /** * The actual text objects for the menu entries. */ @@ -203,6 +213,8 @@ class PauseSubState extends MusicBeatSubState regenerateMenu(); transitionIn(); + + startCharterTimer(); } /** @@ -222,6 +234,8 @@ class PauseSubState extends MusicBeatSubState public override function destroy():Void { super.destroy(); + charterFadeTween.destroy(); + charterFadeTween = null; pauseMusic.stop(); } @@ -270,16 +284,25 @@ class PauseSubState extends MusicBeatSubState metadata.scrollFactor.set(0, 0); add(metadata); - var metadataSong:FlxText = new FlxText(20, 15, FlxG.width - 40, 'Song Name - Artist'); + var metadataSong:FlxText = new FlxText(20, 15, FlxG.width - 40, 'Song Name'); metadataSong.setFormat(Paths.font('vcr.ttf'), 32, FlxColor.WHITE, FlxTextAlign.RIGHT); if (PlayState.instance?.currentChart != null) { - metadataSong.text = '${PlayState.instance.currentChart.songName} - ${PlayState.instance.currentChart.songArtist}'; + metadataSong.text = '${PlayState.instance.currentChart.songName}'; } metadataSong.scrollFactor.set(0, 0); metadata.add(metadataSong); - var metadataDifficulty:FlxText = new FlxText(20, 15 + 32, FlxG.width - 40, 'Difficulty: '); + metadataArtist = new FlxText(20, metadataSong.y + 32, FlxG.width - 40, 'Artist: ${Constants.DEFAULT_ARTIST}'); + metadataArtist.setFormat(Paths.font('vcr.ttf'), 32, FlxColor.WHITE, FlxTextAlign.RIGHT); + if (PlayState.instance?.currentChart != null) + { + metadataArtist.text = 'Artist: ${PlayState.instance.currentChart.songArtist}'; + } + metadataArtist.scrollFactor.set(0, 0); + metadata.add(metadataArtist); + + var metadataDifficulty:FlxText = new FlxText(20, metadataArtist.y + 32, FlxG.width - 40, 'Difficulty: '); metadataDifficulty.setFormat(Paths.font('vcr.ttf'), 32, FlxColor.WHITE, FlxTextAlign.RIGHT); if (PlayState.instance?.currentDifficulty != null) { @@ -288,12 +311,12 @@ class PauseSubState extends MusicBeatSubState metadataDifficulty.scrollFactor.set(0, 0); metadata.add(metadataDifficulty); - metadataDeaths = new FlxText(20, 15 + 64, FlxG.width - 40, '${PlayState.instance?.deathCounter} Blue Balls'); + metadataDeaths = new FlxText(20, metadataDifficulty.y + 32, FlxG.width - 40, '${PlayState.instance?.deathCounter} Blue Balls'); metadataDeaths.setFormat(Paths.font('vcr.ttf'), 32, FlxColor.WHITE, FlxTextAlign.RIGHT); metadataDeaths.scrollFactor.set(0, 0); metadata.add(metadataDeaths); - metadataPractice = new FlxText(20, 15 + 96, FlxG.width - 40, 'PRACTICE MODE'); + metadataPractice = new FlxText(20, metadataDeaths.y + 32, FlxG.width - 40, 'PRACTICE MODE'); metadataPractice.setFormat(Paths.font('vcr.ttf'), 32, FlxColor.WHITE, FlxTextAlign.RIGHT); metadataPractice.visible = PlayState.instance?.isPracticeMode ?? false; metadataPractice.scrollFactor.set(0, 0); @@ -302,6 +325,62 @@ class PauseSubState extends MusicBeatSubState updateMetadataText(); } + var charterFadeTween:Null = null; + + function startCharterTimer():Void + { + charterFadeTween = FlxTween.tween(metadataArtist, {alpha: 0.0}, CHARTER_FADE_DURATION, + { + startDelay: CHARTER_FADE_DELAY, + ease: FlxEase.quartOut, + onComplete: (_) -> { + if (PlayState.instance?.currentChart != null) + { + metadataArtist.text = 'Charter: ${PlayState.instance.currentChart.charter ?? 'Unknown'}'; + } + else + { + metadataArtist.text = 'Charter: ${Constants.DEFAULT_CHARTER}'; + } + + FlxTween.tween(metadataArtist, {alpha: 1.0}, CHARTER_FADE_DURATION, + { + ease: FlxEase.quartOut, + onComplete: (_) -> { + startArtistTimer(); + } + }); + } + }); + } + + function startArtistTimer():Void + { + charterFadeTween = FlxTween.tween(metadataArtist, {alpha: 0.0}, CHARTER_FADE_DURATION, + { + startDelay: CHARTER_FADE_DELAY, + ease: FlxEase.quartOut, + onComplete: (_) -> { + if (PlayState.instance?.currentChart != null) + { + metadataArtist.text = 'Artist: ${PlayState.instance.currentChart.songArtist}'; + } + else + { + metadataArtist.text = 'Artist: ${Constants.DEFAULT_ARTIST}'; + } + + FlxTween.tween(metadataArtist, {alpha: 1.0}, CHARTER_FADE_DURATION, + { + ease: FlxEase.quartOut, + onComplete: (_) -> { + startCharterTimer(); + } + }); + } + }); + } + /** * Perform additional animations to transition the pause menu in when it is first displayed. */ diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx index 23d8d21986..5da78e9dfc 100644 --- a/source/funkin/play/song/Song.hx +++ b/source/funkin/play/song/Song.hx @@ -120,6 +120,18 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry 0) return _metadata.get(Constants.DEFAULT_VARIATION)?.charter ?? 'Unknown'; + return Constants.DEFAULT_CHARTER; + } + /** * @param id The ID of the song to load. * @param ignoreErrors If false, an exception will be thrown if the song data could not be loaded. @@ -270,6 +282,7 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry = null; public var looped:Bool = false; diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index a313981f45..980f5db4f3 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -1270,7 +1270,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState var result:Null = songMetadata.get(selectedVariation); if (result == null) { - result = new SongMetadata('DadBattle', 'Kawai Sprite', selectedVariation); + result = new SongMetadata('Default Song Name', Constants.DEFAULT_ARTIST, selectedVariation); songMetadata.set(selectedVariation, result); } return result; diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx index f85307c64f..80a421d806 100644 --- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx @@ -29,6 +29,7 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox { var inputSongName:TextField; var inputSongArtist:TextField; + var inputSongCharter:TextField; var inputStage:DropDown; var inputNoteStyle:DropDown; var buttonCharacterPlayer:Button; @@ -89,6 +90,20 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox } }; + inputSongCharter.onChange = function(event:UIEvent) { + var valid:Bool = event.target.text != null && event.target.text != ''; + + if (valid) + { + inputSongCharter.removeClass('invalid-value'); + chartEditorState.currentSongMetadata.charter = event.target.text; + } + else + { + chartEditorState.currentSongMetadata.charter = null; + } + }; + inputStage.onChange = function(event:UIEvent) { var valid:Bool = event.data != null && event.data.id != null; @@ -176,6 +191,7 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox inputSongName.value = chartEditorState.currentSongMetadata.songName; inputSongArtist.value = chartEditorState.currentSongMetadata.artist; + inputSongCharter.value = chartEditorState.currentSongMetadata.charter; inputStage.value = chartEditorState.currentSongMetadata.playData.stage; inputNoteStyle.value = chartEditorState.currentSongMetadata.playData.noteStyle; inputBPM.value = chartEditorState.currentSongMetadata.timeChanges[0].bpm; diff --git a/source/funkin/util/Constants.hx b/source/funkin/util/Constants.hx index 2f3b570b3b..4e706c612e 100644 --- a/source/funkin/util/Constants.hx +++ b/source/funkin/util/Constants.hx @@ -248,6 +248,11 @@ class Constants */ public static final DEFAULT_ARTIST:String = 'Unknown'; + /** + * The default charter for songs. + */ + public static final DEFAULT_CHARTER:String = 'Unknown'; + /** * The default note style for songs. */ From 13595fca700d99c0a472687b20b1ba6170eec58f Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sun, 19 May 2024 01:49:06 -0400 Subject: [PATCH 079/216] Changelog entry for chart metadata --- source/funkin/data/song/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/funkin/data/song/CHANGELOG.md b/source/funkin/data/song/CHANGELOG.md index 3cd3af0700..4f1c66adec 100644 --- a/source/funkin/data/song/CHANGELOG.md +++ b/source/funkin/data/song/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.2.3] +### Added +- Added `charter` field to denote authorship of a chart. + ## [2.2.2] ### Added - Added `playData.previewStart` and `playData.previewEnd` fields to specify when in the song should the song's audio should be played as a preview in Freeplay. From dcfc51cdcd53cd52b1b5ee34f0df6778afa1f2b9 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Mon, 20 May 2024 01:37:35 +0200 Subject: [PATCH 080/216] Fix Charting Sustain Trails Inverted --- .../ui/debug/charting/components/ChartEditorHoldNoteSprite.hx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx b/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx index aeb6dd0e4a..7c20358a4c 100644 --- a/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx +++ b/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx @@ -36,6 +36,8 @@ class ChartEditorHoldNoteSprite extends SustainTrail zoom *= 0.7; zoom *= ChartEditorState.GRID_SIZE / Strumline.STRUMLINE_SIZE; + flipY = false; + setup(); } From 9a18e3fde6ee779ca391dece4a0d94e79f584501 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Mon, 20 May 2024 01:38:52 +0200 Subject: [PATCH 081/216] Fix Charting Dragging Sustain Trails --- source/funkin/ui/debug/charting/ChartEditorState.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index b75cd8bf1f..d426abaafd 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -4566,8 +4566,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState } gridGhostHoldNote.visible = true; - gridGhostHoldNote.noteData = gridGhostNote.noteData; - gridGhostHoldNote.noteDirection = gridGhostNote.noteData.getDirection(); + gridGhostHoldNote.noteData = currentPlaceNoteData; + gridGhostHoldNote.noteDirection = currentPlaceNoteData.getDirection(); gridGhostHoldNote.setHeightDirectly(dragLengthPixels, true); gridGhostHoldNote.updateHoldNotePosition(renderedHoldNotes); From 9968c8eabcd6ee6b805abee3a3dbd9c82695fc89 Mon Sep 17 00:00:00 2001 From: etvx86 <64978924+EnterTheVoid-x86@users.noreply.github.com> Date: Mon, 20 May 2024 10:42:17 -0400 Subject: [PATCH 082/216] Fix some trace typos --- source/funkin/play/PlayState.hx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index a9ca09ce84..88fea72ac8 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -772,19 +772,19 @@ class PlayState extends MusicBeatSubState var message:String = 'There was a critical error. Click OK to return to the main menu.'; if (currentSong == null) { - message = 'The was a critical error loading this song\'s chart. Click OK to return to the main menu.'; + message = 'There was a critical error loading this song\'s chart. Click OK to return to the main menu.'; } else if (currentDifficulty == null) { - message = 'The was a critical error selecting a difficulty for this song. Click OK to return to the main menu.'; + message = 'There was a critical error selecting a difficulty for this song. Click OK to return to the main menu.'; } else if (currentChart == null) { - message = 'The was a critical error retrieving data for this song on "$currentDifficulty" difficulty with variation "$currentVariation". Click OK to return to the main menu.'; + message = 'There was a critical error retrieving data for this song on "$currentDifficulty" difficulty with variation "$currentVariation". Click OK to return to the main menu.'; } else if (currentChart.notes == null) { - message = 'The was a critical error retrieving note data for this song on "$currentDifficulty" difficulty with variation "$currentVariation". Click OK to return to the main menu.'; + message = 'There was a critical error retrieving note data for this song on "$currentDifficulty" difficulty with variation "$currentVariation". Click OK to return to the main menu.'; } // Display a popup. This blocks the application until the user clicks OK. From 1050176b274014a17b7714ef75a26c8a8684cb46 Mon Sep 17 00:00:00 2001 From: richTrash21 Date: Mon, 20 May 2024 23:52:48 +0400 Subject: [PATCH 083/216] main menu camera fix --- source/funkin/ui/debug/DebugMenuSubState.hx | 1 - source/funkin/ui/mainmenu/MainMenuState.hx | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/source/funkin/ui/debug/DebugMenuSubState.hx b/source/funkin/ui/debug/DebugMenuSubState.hx index 6d6e73e809..f8b1be9d2d 100644 --- a/source/funkin/ui/debug/DebugMenuSubState.hx +++ b/source/funkin/ui/debug/DebugMenuSubState.hx @@ -62,7 +62,6 @@ class DebugMenuSubState extends MusicBeatSubState #if sys createItem("OPEN CRASH LOG FOLDER", openLogFolder); #end - FlxG.camera.focusOn(new FlxPoint(camFocusPoint.x, camFocusPoint.y)); FlxG.camera.focusOn(new FlxPoint(camFocusPoint.x, camFocusPoint.y + 500)); } diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index 7a21a6e8f5..9af4e299fd 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -49,6 +49,8 @@ class MainMenuState extends MusicBeatState DiscordClient.changePresence("In the Menus", null); #end + FlxG.cameras.reset(new FunkinCamera('mainMenu')); + transIn = FlxTransitionableState.defaultTransIn; transOut = FlxTransitionableState.defaultTransOut; @@ -170,7 +172,6 @@ class MainMenuState extends MusicBeatState function resetCamStuff():Void { - FlxG.cameras.reset(new FunkinCamera('mainMenu')); FlxG.camera.follow(camFollow, null, 0.06); FlxG.camera.snapToTarget(); } @@ -329,6 +330,8 @@ class MainMenuState extends MusicBeatState persistentUpdate = false; FlxG.state.openSubState(new DebugMenuSubState()); + // reset camera when debug menu is closed + subStateClosed.addOnce(_ -> resetCamStuff()); } #end From f3868c2ee8d9dcf9488c349d8509545f0113f010 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 21 May 2024 02:23:21 -0400 Subject: [PATCH 084/216] An attempt at an HTML5 save data fix --- hmm.json | 2 +- source/funkin/save/Save.hx | 6 ++-- .../funkin/save/migrator/SaveDataMigrator.hx | 7 ++-- source/funkin/util/StructureUtil.hx | 32 ++++++++++++++++--- source/funkin/util/VersionUtil.hx | 19 +++++++++++ 5 files changed, 55 insertions(+), 11 deletions(-) diff --git a/hmm.json b/hmm.json index c359d7a512..1fe5a923d6 100644 --- a/hmm.json +++ b/hmm.json @@ -153,7 +153,7 @@ "name": "polymod", "type": "git", "dir": null, - "ref": "8553b800965f225bb14c7ab8f04bfa9cdec362ac", + "ref": "bfbe30d81601b3543d80dce580108ad6b7e182c7", "url": "https://github.com/larsiusprime/polymod" }, { diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx index acbe59edda..dbba4a4c46 100644 --- a/source/funkin/save/Save.hx +++ b/source/funkin/save/Save.hx @@ -53,7 +53,8 @@ class Save public function new(?data:RawSaveData) { if (data == null) this.data = Save.getDefault(); - else this.data = data; + else + this.data = data; } public static function getDefault():RawSaveData @@ -714,6 +715,7 @@ class Save /** * An anonymous structure containingg all the user's save data. + * Isn't stored with JSON, stored with some sort of Haxe built-in serialization? */ typedef RawSaveData = { @@ -724,8 +726,6 @@ typedef RawSaveData = /** * A semantic versioning string for the save data format. */ - @:jcustomparse(funkin.data.DataParse.semverVersion) - @:jcustomwrite(funkin.data.DataWrite.semverVersion) var version:Version; var api:SaveApiData; diff --git a/source/funkin/save/migrator/SaveDataMigrator.hx b/source/funkin/save/migrator/SaveDataMigrator.hx index 3ed59e7268..7f597b4ec9 100644 --- a/source/funkin/save/migrator/SaveDataMigrator.hx +++ b/source/funkin/save/migrator/SaveDataMigrator.hx @@ -24,6 +24,8 @@ class SaveDataMigrator } else { + // Sometimes the Haxe serializer has issues with the version so we fix it here. + version = VersionUtil.repairVersion(version); if (VersionUtil.validateVersion(version, Save.SAVE_DATA_VERSION_RULE)) { // Simply import the structured data. @@ -32,8 +34,9 @@ class SaveDataMigrator } else { - trace('[SAVE] Invalid save data version! Returning blank data.'); - trace(inputData); + var message:String = 'Error migrating save data, expected ${Save.SAVE_DATA_VERSION}.'; + lime.app.Application.current.window.alert(message, "Save Data Failure"); + trace('[SAVE] ' + message); return new Save(Save.getDefault()); } } diff --git a/source/funkin/util/StructureUtil.hx b/source/funkin/util/StructureUtil.hx index 2f0c3818a2..2a6b345d36 100644 --- a/source/funkin/util/StructureUtil.hx +++ b/source/funkin/util/StructureUtil.hx @@ -44,8 +44,15 @@ class StructureUtil return Std.isOfType(a, haxe.Constraints.IMap); } - public static function isObject(a:Dynamic):Bool + /** + * Returns `true` if `a` is an anonymous structure. + * I believe this returns `false` even for class instances and arrays. + */ + public static function isStructure(a:Dynamic):Bool { + // TODO: Is there a difference? + // return Reflect.isObject(foo); + switch (Type.typeof(a)) { case TObject: @@ -55,6 +62,22 @@ class StructureUtil } } + /** + * Returns true if `a` is an array. + * + * NOTE: isObject and isInstance also return true, + * since they're objects of the Array<> class, so check this first! + */ + public static function isArray(a:Dynamic):Bool + { + return Std.is(a, Array); + } + + public static function isInstance(a:Dynamic):Bool + { + return Type.getClass(a) != null; + } + public static function isPrimitive(a:Dynamic):Bool { switch (Type.typeof(a)) @@ -89,6 +112,7 @@ class StructureUtil { if (a == null) return b; if (b == null) return null; + if (isArray(a) && isArray(b)) return b; if (isPrimitive(a) && isPrimitive(b)) return b; if (isMap(b)) { @@ -101,7 +125,6 @@ class StructureUtil return StructureUtil.toMap(a).merge(b); } } - if (!Reflect.isObject(a) || !Reflect.isObject(b)) return b; if (Std.isOfType(b, haxe.ds.StringMap)) { if (Std.isOfType(a, haxe.ds.StringMap)) @@ -113,15 +136,14 @@ class StructureUtil return StructureUtil.toMap(a).merge(b); } } + if (!isStructure(a) || !isStructure(b)) return b; var result:DynamicAccess = Reflect.copy(a); for (field in Reflect.fields(b)) { - if (Reflect.isObject(b)) + if (isStructure(b)) { - // Note that isObject also returns true for class instances, - // but we just assume that's not a problem here. result.set(field, deepMerge(Reflect.field(result, field), Reflect.field(b, field))); } else diff --git a/source/funkin/util/VersionUtil.hx b/source/funkin/util/VersionUtil.hx index 247ba19db4..8f55506627 100644 --- a/source/funkin/util/VersionUtil.hx +++ b/source/funkin/util/VersionUtil.hx @@ -32,6 +32,25 @@ class VersionUtil } } + public static function repairVersion(version:thx.semver.Version):thx.semver.Version + { + var versionData:thx.semver.Version.SemVer = version; + + if (StructureUtil.isStructure(versionData.version)) + { + // This is bad! versionData.version should be an array! + versionData.version = [versionData.version[0], versionData.version[1], versionData.version[2]]; + + var fixedVersion:thx.semver.Version = versionData; + return fixedVersion; + } + else + { + // No need for repair. + return version; + } + } + /** * Checks that a given verison number satisisfies a given version rule. * Version rule can be complex, e.g. "1.0.x" or ">=1.0.0,<1.1.0", or anything NPM supports. From 6cb58163787b6951fa6fffed01a48e444cd5b5f5 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 21 May 2024 02:49:07 -0400 Subject: [PATCH 085/216] Add freeplay favorites to the save data so they persist between sessions. --- source/funkin/input/Controls.hx | 2 +- source/funkin/save/Save.hx | 44 ++++++++++++++++++++-- source/funkin/save/changelog.md | 3 ++ source/funkin/ui/freeplay/FreeplayState.hx | 25 +++++++++++- 4 files changed, 68 insertions(+), 6 deletions(-) diff --git a/source/funkin/input/Controls.hx b/source/funkin/input/Controls.hx index 1983d413ba..cede0b6887 100644 --- a/source/funkin/input/Controls.hx +++ b/source/funkin/input/Controls.hx @@ -707,7 +707,7 @@ class Controls extends FlxActionSet case Control.VOLUME_UP: return [PLUS, NUMPADPLUS]; case Control.VOLUME_DOWN: return [MINUS, NUMPADMINUS]; case Control.VOLUME_MUTE: return [ZERO, NUMPADZERO]; - case Control.FULLSCREEN: return [FlxKey.F]; + case Control.FULLSCREEN: return [FlxKey.F11]; // We use F for other things LOL. } case Duo(true): diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx index acbe59edda..7b2d3f5114 100644 --- a/source/funkin/save/Save.hx +++ b/source/funkin/save/Save.hx @@ -14,8 +14,7 @@ import funkin.util.SerializerUtil; @:nullSafety class Save { - // Version 2.0.2 adds attributes to `optionsChartEditor`, that should return default values if they are null. - public static final SAVE_DATA_VERSION:thx.semver.Version = "2.0.3"; + public static final SAVE_DATA_VERSION:thx.semver.Version = "2.0.4"; public static final SAVE_DATA_VERSION_RULE:thx.semver.VersionRule = "2.0.x"; // We load this version's saves from a new save path, to maintain SOME level of backwards compatibility. @@ -53,7 +52,8 @@ class Save public function new(?data:RawSaveData) { if (data == null) this.data = Save.getDefault(); - else this.data = data; + else + this.data = data; } public static function getDefault():RawSaveData @@ -77,6 +77,9 @@ class Save levels: [], songs: [], }, + + favoriteSongs: [], + options: { // Reasonable defaults. @@ -554,6 +557,35 @@ class Save return false; } + public function isSongFavorited(id:String):Bool + { + if (data.favoriteSongs == null) + { + data.favoriteSongs = []; + flush(); + }; + + return data.favoriteSongs.contains(id); + } + + public function favoriteSong(id:String):Void + { + if (!isSongFavorited(id)) + { + data.favoriteSongs.push(id); + flush(); + } + } + + public function unfavoriteSong(id:String):Void + { + if (isSongFavorited(id)) + { + data.favoriteSongs.remove(id); + flush(); + } + } + public function getControls(playerId:Int, inputType:Device):Null { switch (inputType) @@ -740,6 +772,12 @@ typedef RawSaveData = */ var options:SaveDataOptions; + /** + * The user's favorited songs in the Freeplay menu, + * as a list of song IDs. + */ + var favoriteSongs:Array; + var mods:SaveDataMods; /** diff --git a/source/funkin/save/changelog.md b/source/funkin/save/changelog.md index 3fa9839d1c..7c9094f2dd 100644 --- a/source/funkin/save/changelog.md +++ b/source/funkin/save/changelog.md @@ -5,6 +5,9 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.0.4] - 2024-05-21 +### Added +- `favoriteSongs:Array` to `Save` ## [2.0.3] - 2024-01-09 ### Added diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 2390682889..911d07a568 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -699,8 +699,8 @@ class FreeplayState extends MusicBeatSubState if (targetSong != null) { var realShit:Int = curSelected; - targetSong.isFav = !targetSong.isFav; - if (targetSong.isFav) + var isFav = targetSong.toggleFavorite(); + if (isFav) { FlxTween.tween(grpCapsules.members[realShit], {angle: 360}, 0.4, { @@ -1398,11 +1398,32 @@ class FreeplaySongData this.levelId = levelId; this.songId = songId; this.song = song; + + this.isFav = Save.instance.isSongFavorited(songId); + if (displayedVariations != null) this.displayedVariations = displayedVariations; updateValues(displayedVariations); } + /** + * Toggle whether or not the song is favorited, then flush to save data. + * @return Whether or not the song is now favorited. + */ + public function toggleFavorite():Bool + { + isFav = !isFav; + if (isFav) + { + Save.instance.favoriteSong(this.songId); + } + else + { + Save.instance.unfavoriteSong(this.songId); + } + return isFav; + } + function updateValues(variations:Array):Void { this.songDifficulties = song.listDifficulties(variations, false, false); From fed6d1146c67b048f2c9b82d3b50a7dd9cd1748f Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 21 May 2024 04:02:32 -0400 Subject: [PATCH 086/216] Do some cleanup (replace several utility functions with a utility library we already depend on!) --- Project.xml | 1 + source/funkin/import.hx | 1 + source/funkin/play/song/Song.hx | 16 +- .../funkin/save/migrator/SaveDataMigrator.hx | 5 +- source/funkin/ui/story/LevelProp.hx | 5 +- source/funkin/util/StructureUtil.hx | 158 ------------------ source/funkin/util/tools/ArrayTools.hx | 66 -------- 7 files changed, 17 insertions(+), 235 deletions(-) delete mode 100644 source/funkin/util/StructureUtil.hx diff --git a/Project.xml b/Project.xml index fcfcfb9f35..b5630a46ab 100644 --- a/Project.xml +++ b/Project.xml @@ -128,6 +128,7 @@ + diff --git a/source/funkin/import.hx b/source/funkin/import.hx index 250de99cb2..c8431be33b 100644 --- a/source/funkin/import.hx +++ b/source/funkin/import.hx @@ -11,6 +11,7 @@ import flixel.system.debug.watch.Tracker; // These are great. using Lambda; using StringTools; +using thx.Arrays; using funkin.util.tools.ArraySortTools; using funkin.util.tools.ArrayTools; using funkin.util.tools.FloatTools; diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx index 23d8d21986..53408fb34d 100644 --- a/source/funkin/play/song/Song.hx +++ b/source/funkin/play/song/Song.hx @@ -439,12 +439,16 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry = difficulties.keys().array().map(function(diffId:String):Null { - var difficulty:Null = difficulties.get(diffId); - if (difficulty == null) return null; - if (variationIds.length > 0 && !variationIds.contains(difficulty.variation)) return null; - return difficulty.difficulty; - }).nonNull().unique(); + var diffFiltered:Array = difficulties.keys() + .array() + .map(function(diffId:String):Null { + var difficulty:Null = difficulties.get(diffId); + if (difficulty == null) return null; + if (variationIds.length > 0 && !variationIds.contains(difficulty.variation)) return null; + return difficulty.difficulty; + }) + .filterNull() + .distinct(); diffFiltered = diffFiltered.filter(function(diffId:String):Bool { if (showHidden) return true; diff --git a/source/funkin/save/migrator/SaveDataMigrator.hx b/source/funkin/save/migrator/SaveDataMigrator.hx index 7f597b4ec9..5398b21198 100644 --- a/source/funkin/save/migrator/SaveDataMigrator.hx +++ b/source/funkin/save/migrator/SaveDataMigrator.hx @@ -28,8 +28,9 @@ class SaveDataMigrator version = VersionUtil.repairVersion(version); if (VersionUtil.validateVersion(version, Save.SAVE_DATA_VERSION_RULE)) { - // Simply import the structured data. - var save:Save = new Save(StructureUtil.deepMerge(Save.getDefault(), inputData)); + // Import the structured data. + var saveDataWithDefaults:RawSaveData = thx.Objects.deepCombine(Save.getDefault(), inputData); + var save:Save = new Save(saveDataWithDefaults); return save; } else diff --git a/source/funkin/ui/story/LevelProp.hx b/source/funkin/ui/story/LevelProp.hx index ffc756e1cb..5a3efc36ae 100644 --- a/source/funkin/ui/story/LevelProp.hx +++ b/source/funkin/ui/story/LevelProp.hx @@ -13,11 +13,10 @@ class LevelProp extends Bopper // Only reset the prop if the asset path has changed. if (propData == null || value?.assetPath != propData?.assetPath) { - this.visible = (value != null); - this.propData = value; - danceEvery = this.propData?.danceEvery ?? 0; applyData(); } + this.visible = (value != null); + danceEvery = this.propData?.danceEvery ?? 0; return this.propData; } diff --git a/source/funkin/util/StructureUtil.hx b/source/funkin/util/StructureUtil.hx deleted file mode 100644 index 2a6b345d36..0000000000 --- a/source/funkin/util/StructureUtil.hx +++ /dev/null @@ -1,158 +0,0 @@ -package funkin.util; - -import funkin.util.tools.MapTools; -import haxe.DynamicAccess; - -/** - * Utilities for working with anonymous structures. - */ -class StructureUtil -{ - /** - * Merge two structures, with the second overwriting the first. - * Performs a SHALLOW clone, where child structures are not merged. - * @param a The base structure. - * @param b The new structure. - * @return The merged structure. - */ - public static function merge(a:Dynamic, b:Dynamic):Dynamic - { - var result:DynamicAccess = Reflect.copy(a); - - for (field in Reflect.fields(b)) - { - result.set(field, Reflect.field(b, field)); - } - - return result; - } - - public static function toMap(a:Dynamic):haxe.ds.Map - { - var result:haxe.ds.Map = []; - - for (field in Reflect.fields(a)) - { - result.set(field, Reflect.field(a, field)); - } - - return result; - } - - public static function isMap(a:Dynamic):Bool - { - return Std.isOfType(a, haxe.Constraints.IMap); - } - - /** - * Returns `true` if `a` is an anonymous structure. - * I believe this returns `false` even for class instances and arrays. - */ - public static function isStructure(a:Dynamic):Bool - { - // TODO: Is there a difference? - // return Reflect.isObject(foo); - - switch (Type.typeof(a)) - { - case TObject: - return true; - default: - return false; - } - } - - /** - * Returns true if `a` is an array. - * - * NOTE: isObject and isInstance also return true, - * since they're objects of the Array<> class, so check this first! - */ - public static function isArray(a:Dynamic):Bool - { - return Std.is(a, Array); - } - - public static function isInstance(a:Dynamic):Bool - { - return Type.getClass(a) != null; - } - - public static function isPrimitive(a:Dynamic):Bool - { - switch (Type.typeof(a)) - { - case TInt | TFloat | TBool: - return true; - case TClass(c): - return false; - case TEnum(e): - return false; - case TObject: - return false; - case TFunction: - return false; - case TNull: - return true; - case TUnknown: - return false; - default: - return false; - } - } - - /** - * Merge two structures, with the second overwriting the first. - * Performs a DEEP clone, where child structures are also merged recursively. - * @param a The base structure. - * @param b The new structure. - * @return The merged structure. - */ - public static function deepMerge(a:Dynamic, b:Dynamic):Dynamic - { - if (a == null) return b; - if (b == null) return null; - if (isArray(a) && isArray(b)) return b; - if (isPrimitive(a) && isPrimitive(b)) return b; - if (isMap(b)) - { - if (isMap(a)) - { - return MapTools.merge(a, b); - } - else - { - return StructureUtil.toMap(a).merge(b); - } - } - if (Std.isOfType(b, haxe.ds.StringMap)) - { - if (Std.isOfType(a, haxe.ds.StringMap)) - { - return MapTools.merge(a, b); - } - else - { - return StructureUtil.toMap(a).merge(b); - } - } - if (!isStructure(a) || !isStructure(b)) return b; - - var result:DynamicAccess = Reflect.copy(a); - - for (field in Reflect.fields(b)) - { - if (isStructure(b)) - { - result.set(field, deepMerge(Reflect.field(result, field), Reflect.field(b, field))); - } - else - { - // If we're here, b[field] is a primitive. - result.set(field, Reflect.field(b, field)); - } - } - - return result; - } -} diff --git a/source/funkin/util/tools/ArrayTools.hx b/source/funkin/util/tools/ArrayTools.hx index caf8e8aab5..0fe245e3a4 100644 --- a/source/funkin/util/tools/ArrayTools.hx +++ b/source/funkin/util/tools/ArrayTools.hx @@ -5,72 +5,6 @@ package funkin.util.tools; */ class ArrayTools { - /** - * Returns a copy of the array with all duplicate elements removed. - * @param array The array to remove duplicates from. - * @return A copy of the array with all duplicate elements removed. - */ - public static function unique(array:Array):Array - { - var result:Array = []; - for (element in array) - { - if (!result.contains(element)) - { - result.push(element); - } - } - return result; - } - - /** - * Returns a copy of the array with all `null` elements removed. - * @param array The array to remove `null` elements from. - * @return A copy of the array with all `null` elements removed. - */ - public static function nonNull(array:Array>):Array - { - var result:Array = []; - for (element in array) - { - if (element != null) - { - result.push(element); - } - } - return result; - } - - /** - * Return the first element of the array that satisfies the predicate, or null if none do. - * @param input The array to search - * @param predicate The predicate to call - * @return The result - */ - public static function find(input:Array, predicate:T->Bool):Null - { - for (element in input) - { - if (predicate(element)) return element; - } - return null; - } - - /** - * Return the index of the first element of the array that satisfies the predicate, or `-1` if none do. - * @param input The array to search - * @param predicate The predicate to call - * @return The index of the result - */ - public static function findIndex(input:Array, predicate:T->Bool):Int - { - for (index in 0...input.length) - { - if (predicate(input[index])) return index; - } - return -1; - } - /* * Push an element to the array if it is not already present. * @param input The array to push to From 6d3b58cecdb3b3881e261a3137518926835fd7a5 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 21 May 2024 04:02:53 -0400 Subject: [PATCH 087/216] Fix some additional compiling issues. --- source/funkin/save/migrator/SaveDataMigrator.hx | 3 +-- source/funkin/util/VersionUtil.hx | 2 +- source/funkin/util/macro/InlineMacro.hx | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/source/funkin/save/migrator/SaveDataMigrator.hx b/source/funkin/save/migrator/SaveDataMigrator.hx index 5398b21198..650666c5c4 100644 --- a/source/funkin/save/migrator/SaveDataMigrator.hx +++ b/source/funkin/save/migrator/SaveDataMigrator.hx @@ -3,7 +3,6 @@ package funkin.save.migrator; import funkin.save.Save; import funkin.save.migrator.RawSaveData_v1_0_0; import thx.semver.Version; -import funkin.util.StructureUtil; import funkin.util.VersionUtil; @:nullSafety @@ -29,7 +28,7 @@ class SaveDataMigrator if (VersionUtil.validateVersion(version, Save.SAVE_DATA_VERSION_RULE)) { // Import the structured data. - var saveDataWithDefaults:RawSaveData = thx.Objects.deepCombine(Save.getDefault(), inputData); + var saveDataWithDefaults:RawSaveData = cast thx.Objects.deepCombine(Save.getDefault(), inputData); var save:Save = new Save(saveDataWithDefaults); return save; } diff --git a/source/funkin/util/VersionUtil.hx b/source/funkin/util/VersionUtil.hx index 8f55506627..18d7eafa66 100644 --- a/source/funkin/util/VersionUtil.hx +++ b/source/funkin/util/VersionUtil.hx @@ -36,7 +36,7 @@ class VersionUtil { var versionData:thx.semver.Version.SemVer = version; - if (StructureUtil.isStructure(versionData.version)) + if (thx.Types.isAnonymousObject(versionData.version)) { // This is bad! versionData.version should be an array! versionData.version = [versionData.version[0], versionData.version[1], versionData.version[2]]; diff --git a/source/funkin/util/macro/InlineMacro.hx b/source/funkin/util/macro/InlineMacro.hx index b0e7ed1847..c402574098 100644 --- a/source/funkin/util/macro/InlineMacro.hx +++ b/source/funkin/util/macro/InlineMacro.hx @@ -23,7 +23,7 @@ class InlineMacro var fields:Array = haxe.macro.Context.getBuildFields(); // Find the field with the given name. - var targetField:Null = fields.find(function(f) return f.name == field + var targetField:Null = thx.Arrays.find(fields, function(f) return f.name == field && (MacroUtil.isFieldStatic(f) == isStatic)); // If the field was not found, throw an error. From 4e47bfe68b056656c24355c2ff90042db3a62744 Mon Sep 17 00:00:00 2001 From: Keoiki <55053690+Keoiki@users.noreply.github.com> Date: Tue, 21 May 2024 23:52:40 +0300 Subject: [PATCH 088/216] Fix Note Styles in PlayState & Chart Editor --- source/funkin/play/PlayState.hx | 7 +------ .../debug/charting/toolboxes/ChartEditorMetadataToolbox.hx | 2 ++ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 43dd485cf9..dc07e19103 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1730,12 +1730,7 @@ class PlayState extends MusicBeatSubState */ function initStrumlines():Void { - var noteStyleId:String = switch (currentStageId) - { - case 'school': 'pixel'; - case 'schoolEvil': 'pixel'; - default: Constants.DEFAULT_NOTE_STYLE; - } + var noteStyleId:String = currentChart.noteStyle; var noteStyle:NoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyleId); if (noteStyle == null) noteStyle = NoteStyleRegistry.instance.fetchDefault(); diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx index f85307c64f..98e263aaf9 100644 --- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx @@ -104,6 +104,8 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox if (event.data?.id == null) return; chartEditorState.currentSongNoteStyle = event.data.id; }; + var startingValueNoteStyle = ChartEditorDropdowns.populateDropdownWithNoteStyles(inputNoteStyle, chartEditorState.currentSongMetadata.playData.noteStyle); + inputNoteStyle.value = startingValueNoteStyle; inputBPM.onChange = function(event:UIEvent) { if (event.value == null || event.value <= 0) return; From f17f6393041a54e4b15418059f6a9ff9dc2a39cb Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 22 May 2024 01:07:20 -0400 Subject: [PATCH 089/216] Finish implementing smaller numbers. --- assets | 2 +- source/funkin/InitState.hx | 4 +- source/funkin/play/ResultState.hx | 75 ++++++++++++++++--- .../play/components/ClearPercentCounter.hx | 73 ++++++++++++++---- 4 files changed, 124 insertions(+), 30 deletions(-) diff --git a/assets b/assets index ce7dabffbe..b6d930109e 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit ce7dabffbebc154c9dda1f01e92dbef83e3405ab +Subproject commit b6d930109eb69cfd368145e893d81ac1e97ed004 diff --git a/source/funkin/InitState.hx b/source/funkin/InitState.hx index 6a52eaf5d8..d17554d11e 100644 --- a/source/funkin/InitState.hx +++ b/source/funkin/InitState.hx @@ -227,14 +227,14 @@ class InitState extends FlxState tallies: { sick: 130, - good: 69, + good: 70, bad: 69, shit: 69, missed: 69, combo: 69, maxCombo: 69, totalNotesHit: 140, - totalNotes: 2000, + totalNotes: 200 // 0, } }, })); diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index d038b77854..fdcd0cc397 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -37,6 +37,7 @@ class ResultState extends MusicBeatSubState final rank:ResultRank; final songName:FlxBitmapText; final difficulty:FlxSprite; + final clearPercentSmall:ClearPercentCounter; final maskShaderSongName:LeftMaskShader = new LeftMaskShader(); final maskShaderDifficulty:LeftMaskShader = new LeftMaskShader(); @@ -78,6 +79,10 @@ class ResultState extends MusicBeatSubState difficulty = new FlxSprite(555); difficulty.zIndex = 1000; + clearPercentSmall = new ClearPercentCounter(FlxG.width / 2 + 300, FlxG.height / 2 - 100, 100, true); + clearPercentSmall.zIndex = 1000; + clearPercentSmall.visible = false; + bgFlash = FlxGradient.createGradientFlxSprite(FlxG.width, FlxG.height, [0xFFFFEB69, 0xFFFFE66A], 90); resultsAnim = FunkinSprite.createSparrow(-200, -10, "resultScreen/results"); @@ -194,7 +199,7 @@ class ResultState extends MusicBeatSubState speedOfTween.x = -1.0 * Math.cos(angleRad); speedOfTween.y = -1.0 * Math.sin(angleRad); - timerThenSongName(1.0); + timerThenSongName(1.0, false); songName.shader = maskShaderSongName; difficulty.shader = maskShaderDifficulty; @@ -319,13 +324,15 @@ class ResultState extends MusicBeatSubState function startRankTallySequence():Void { - clearPercentTarget = Math.floor((params.scoreData.tallies.sick + params.scoreData.tallies.good) / params.scoreData.tallies.totalNotes * 100); - clearPercentTarget = 100; + var clearPercentFloat = (params.scoreData.tallies.sick + params.scoreData.tallies.good) / params.scoreData.tallies.totalNotes * 100; + clearPercentTarget = Math.floor(clearPercentFloat); + // Prevent off-by-one errors. clearPercentLerp = Std.int(Math.max(0, clearPercentTarget - 36)); - var clearPercentCounter:ClearPercentCounter = new ClearPercentCounter(FlxG.width / 2 + 300, FlxG.height / 2 - 100, clearPercentTarget); - clearPercentCounter.curNumber = clearPercentLerp; + trace('Clear percent target: ' + clearPercentFloat + ', round: ' + clearPercentTarget); + + var clearPercentCounter:ClearPercentCounter = new ClearPercentCounter(FlxG.width / 2 + 300, FlxG.height / 2 - 100, clearPercentLerp); FlxTween.tween(clearPercentCounter, {curNumber: clearPercentTarget}, 1.5, { ease: FlxEase.quartOut, @@ -345,10 +352,25 @@ class ResultState extends MusicBeatSubState bgFlash.visible = true; FlxTween.tween(bgFlash, {alpha: 0}, 0.4); + // Just to be sure that the lerp didn't mess things up. + clearPercentCounter.curNumber = clearPercentTarget; + + clearPercentCounter.flash(true); + new FlxTimer().start(0.4, _ -> { + clearPercentCounter.flash(false); + }); + displayRankText(); new FlxTimer().start(2.0, _ -> { - // remove(clearPercentCounter); + FlxTween.tween(clearPercentCounter, {alpha: 0}, 0.5, + { + startDelay: 0.5, + ease: FlxEase.quartOut, + onComplete: _ -> { + remove(clearPercentCounter); + } + }); afterRankTallySequence(); }); @@ -406,6 +428,8 @@ class ResultState extends MusicBeatSubState function afterRankTallySequence():Void { + showSmallClearPercent(); + FunkinSound.playMusic(rank.getMusicPath(), { startingVolume: 1.0, @@ -490,7 +514,7 @@ class ResultState extends MusicBeatSubState } } - function timerThenSongName(timerLength:Float = 3.0):Void + function timerThenSongName(timerLength:Float = 3.0, autoScroll:Bool = true):Void { movingSongStuff = false; @@ -501,10 +525,17 @@ class ResultState extends MusicBeatSubState difficulty.y = -difficulty.height; FlxTween.tween(difficulty, {y: diffYTween}, 0.5, {ease: FlxEase.expoOut, startDelay: 0.8}); + if (clearPercentSmall != null) + { + clearPercentSmall.x = (difficulty.x + difficulty.width) + 60; + clearPercentSmall.y = -clearPercentSmall.height; + FlxTween.tween(clearPercentSmall, {y: 122 - 5}, 0.5, {ease: FlxEase.expoOut, startDelay: 0.8}); + } + songName.y = -songName.height; var fuckedupnumber = (10) * (songName.text.length / 15); - FlxTween.tween(songName, {y: diffYTween - 35 - fuckedupnumber}, 0.5, {ease: FlxEase.expoOut, startDelay: 0.9}); - songName.x = (difficulty.x + difficulty.width) + 20; + FlxTween.tween(songName, {y: diffYTween - 25 - fuckedupnumber}, 0.5, {ease: FlxEase.expoOut, startDelay: 0.9}); + songName.x = clearPercentSmall.x + clearPercentSmall.width - 30; new FlxTimer().start(timerLength, _ -> { var tempSpeed = FlxPoint.get(speedOfTween.x, speedOfTween.y); @@ -512,10 +543,29 @@ class ResultState extends MusicBeatSubState speedOfTween.set(0, 0); FlxTween.tween(speedOfTween, {x: tempSpeed.x, y: tempSpeed.y}, 0.7, {ease: FlxEase.quadIn}); - movingSongStuff = true; + movingSongStuff = (autoScroll); }); } + function showSmallClearPercent():Void + { + if (clearPercentSmall != null) + { + add(clearPercentSmall); + clearPercentSmall.visible = true; + clearPercentSmall.flash(true); + new FlxTimer().start(0.4, _ -> { + clearPercentSmall.flash(false); + }); + + clearPercentSmall.curNumber = clearPercentTarget; + clearPercentSmall.zIndex = 1000; + refresh(); + } + + movingSongStuff = true; + } + var movingSongStuff:Bool = false; var speedOfTween:FlxPoint = FlxPoint.get(-1, 1); @@ -523,7 +573,8 @@ class ResultState extends MusicBeatSubState { super.draw(); - songName.clipRect = FlxRect.get(Math.max(0, 540 - songName.x), 0, FlxG.width, songName.height); + songName.clipRect = FlxRect.get(Math.max(0, 520 - songName.x), 0, FlxG.width, songName.height); + // PROBABLY SHOULD FIX MEMORY FREE OR WHATEVER THE PUT() FUNCTION DOES !!!! FEELS LIKE IT STUTTERS!!! // if (songName != null && songName.frame != null) @@ -539,8 +590,10 @@ class ResultState extends MusicBeatSubState { songName.x += speedOfTween.x; difficulty.x += speedOfTween.x; + clearPercentSmall.x += speedOfTween.x; songName.y += speedOfTween.y; difficulty.y += speedOfTween.y; + clearPercentSmall.y += speedOfTween.y; if (songName.x + songName.width < 100) { diff --git a/source/funkin/play/components/ClearPercentCounter.hx b/source/funkin/play/components/ClearPercentCounter.hx index 4c03ec3a90..d296b0b0b1 100644 --- a/source/funkin/play/components/ClearPercentCounter.hx +++ b/source/funkin/play/components/ClearPercentCounter.hx @@ -1,6 +1,7 @@ package funkin.play.components; import funkin.graphics.FunkinSprite; +import funkin.graphics.shaders.PureColor; import flixel.FlxSprite; import flixel.group.FlxGroup.FlxTypedGroup; import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup; @@ -9,25 +10,54 @@ import flixel.tweens.FlxEase; import flixel.tweens.FlxTween; import flixel.text.FlxText.FlxTextAlign; import funkin.util.MathUtil; +import flixel.util.FlxColor; /** * Numerical counters used to display the clear percent. */ class ClearPercentCounter extends FlxTypedSpriteGroup { - public var curNumber:Int = 0; - public var neededNumber:Int = 0; + public var curNumber(default, set):Int = 0; - public function new(x:Float, y:Float, neededNumber:Int = 0) + var numberChanged:Bool = false; + + function set_curNumber(val:Int):Int + { + numberChanged = true; + return curNumber = val; + } + + var small:Bool = false; + var flashShader:PureColor; + + public function new(x:Float, y:Float, startingNumber:Int = 0, small:Bool = false) { super(x, y); - this.neededNumber = neededNumber; + flashShader = new PureColor(FlxColor.WHITE); + flashShader.colorSet = true; + + curNumber = startingNumber; - var clearPercentText:FunkinSprite = FunkinSprite.create(0, 0, 'resultScreen/clearPercent/clearPercentText'); + this.small = small; + + var clearPercentText:FunkinSprite = FunkinSprite.create(0, 0, 'resultScreen/clearPercent/clearPercentText${small ? 'Small' : ''}'); + clearPercentText.x = small ? 40 : 0; add(clearPercentText); - if (curNumber == neededNumber) drawNumbers(); + drawNumbers(); + } + + /** + * Make the counter flash turn white or stop being all white. + * @param enabled Whether the counter should be white. + */ + public function flash(enabled:Bool):Void + { + for (member in members) + { + member.shader = enabled ? flashShader : null; + } } var tmr:Float = 0; @@ -36,7 +66,7 @@ class ClearPercentCounter extends FlxTypedSpriteGroup { super.update(elapsed); - if (curNumber < neededNumber) drawNumbers(); + if (numberChanged) drawNumbers(); } function drawNumbers() @@ -44,8 +74,6 @@ class ClearPercentCounter extends FlxTypedSpriteGroup var seperatedScore:Array = []; var tempCombo:Int = Math.round(curNumber); - var fullNumberDigits:Int = Std.int(Math.max(1, Math.ceil(MathUtil.logBase(10, neededNumber)))); - while (tempCombo != 0) { seperatedScore.push(tempCombo % 10); @@ -59,19 +87,32 @@ class ClearPercentCounter extends FlxTypedSpriteGroup for (ind => num in seperatedScore) { var digitIndex = ind + 1; + // If there's only one digit, move it to the right + // If there's three digits, move them all to the left + var digitOffset = (seperatedScore.length == 1) ? 1 : (seperatedScore.length == 3) ? -1 : 0; + var digitSize = small ? 32 : 72; + var digitHeightOffset = small ? -4 : 0; + + var xPos = (digitIndex - 1 + digitOffset) * (digitSize * this.scale.x); + xPos += small ? -24 : 0; + var yPos = (digitIndex - 1 + digitOffset) * (digitHeightOffset * this.scale.y); + yPos += small ? 0 : 72; + if (digitIndex >= members.length) { - var xPos = (digitIndex - 1) * (72 * this.scale.x); - var yPos = 72; - // Three digits = LRL so two different numbers aren't adjacent to each other. - var variant:Bool = (fullNumberDigits % 2 != 0) ? (digitIndex % 2 == 0) : (digitIndex % 2 == 1); - var numb:ClearPercentNumber = new ClearPercentNumber(xPos, yPos, num); + // Three digits = LLR because the 1 and 0 won't be the same anyway. + var variant:Bool = (seperatedScore.length == 3) ? (digitIndex >= 2) : (digitIndex >= 1); + // var variant:Bool = (seperatedScore.length % 2 != 0) ? (digitIndex % 2 == 0) : (digitIndex % 2 == 1); + var numb:ClearPercentNumber = new ClearPercentNumber(xPos, yPos, num, variant, this.small); numb.scale.set(this.scale.x, this.scale.y); add(numb); } else { members[digitIndex].animation.play(Std.string(num)); + // Reset the position of the number + members[digitIndex].x = xPos + this.x; + members[digitIndex].y = yPos + this.y; } } } @@ -79,11 +120,11 @@ class ClearPercentCounter extends FlxTypedSpriteGroup class ClearPercentNumber extends FlxSprite { - public function new(x:Float, y:Float, digit:Int, variant:Bool = false) + public function new(x:Float, y:Float, digit:Int, variant:Bool, small:Bool) { super(x, y); - frames = Paths.getSparrowAtlas('resultScreen/clearPercent/clearPercentNumber${variant ? 'Right' : 'Left'}'); + frames = Paths.getSparrowAtlas('resultScreen/clearPercent/clearPercentNumber${small ? 'Small' : variant ? 'Right' : 'Left'}'); for (i in 0...10) { From d84e832c6c9152abab106290dab72e5792fc6808 Mon Sep 17 00:00:00 2001 From: sector-a <82838084+sector-a@users.noreply.github.com> Date: Wed, 22 May 2024 12:57:57 +0300 Subject: [PATCH 090/216] Make texts update on difficulty change in Story Menu --- source/funkin/ui/story/StoryMenuState.hx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx index 0c22145294..820ac2ad14 100644 --- a/source/funkin/ui/story/StoryMenuState.hx +++ b/source/funkin/ui/story/StoryMenuState.hx @@ -466,6 +466,9 @@ class StoryMenuState extends MusicBeatState // Disable the funny music thing for now. // funnyMusicThing(); } + + updateText(); + refresh(); } final FADE_OUT_TIME:Float = 1.5; From 9afc314a0d20f29d69beba70d91d23cc37922660 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 22 May 2024 15:20:53 -0400 Subject: [PATCH 091/216] Fix an issue with git modules --- .gitmodules | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index be5e0aaa81..2d5c11067d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,5 @@ [submodule "assets"] path = assets - url = https://github.com/FunkinCrew/funkin.assets -[submodule "art"] + url = https://github.com/FunkinCrew/Funkin-Assets-secret path = art - url = https://github.com/FunkinCrew/funkin.art + url = https://github.com/FunkinCrew/Funkin-Art-secret From 5e130eeffcecf2746b222930f2d801faed5a4c64 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Thu, 23 May 2024 18:18:37 +0200 Subject: [PATCH 092/216] Add Winning support to Legacy Health Icons --- source/funkin/play/components/HealthIcon.hx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/funkin/play/components/HealthIcon.hx b/source/funkin/play/components/HealthIcon.hx index 957daa43c9..ded00f3783 100644 --- a/source/funkin/play/components/HealthIcon.hx +++ b/source/funkin/play/components/HealthIcon.hx @@ -373,6 +373,10 @@ class HealthIcon extends FunkinSprite // Don't flip BF's icon here! That's done later. this.animation.add(Idle, [0], 0, false, false); this.animation.add(Losing, [1], 0, false, false); + if (animation.numFrames >= 3) + { + this.animation.add(Winning, [2], 0, false, false); + } } function correctCharacterId(charId:Null):String From 1c352e4e114ed997f842d638ad0483b5a5554cae Mon Sep 17 00:00:00 2001 From: richTrash21 Date: Thu, 23 May 2024 21:50:11 +0400 Subject: [PATCH 093/216] simplify freeplay camera --- source/funkin/ui/freeplay/FreeplayState.hx | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 2f8231bb0f..2dea923529 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -156,6 +156,12 @@ class FreeplayState extends MusicBeatSubState FlxTransitionableState.skipNextTransIn = true; + // dedicated camera for the state so we don't need to fuk around with camera scrolls from the mainmenu / elsewhere + funnyCam = new FunkinCamera('freeplayFunny', 0, 0, FlxG.width, FlxG.height); + funnyCam.bgColor = FlxColor.TRANSPARENT; + FlxG.cameras.add(funnyCam, false); + this.cameras = [funnyCam]; + if (stickerSubState != null) { this.persistentUpdate = true; @@ -534,15 +540,6 @@ class FreeplayState extends MusicBeatSubState }); generateSongList(null, false); - - // dedicated camera for the state so we don't need to fuk around with camera scrolls from the mainmenu / elsewhere - funnyCam = new FunkinCamera('freeplayFunny', 0, 0, FlxG.width, FlxG.height); - funnyCam.bgColor = FlxColor.TRANSPARENT; - FlxG.cameras.add(funnyCam, false); - - forEach(function(bs) { - bs.cameras = [funnyCam]; - }); } var currentFilter:SongFilter = null; From 4ca30a571d46607c7fa3454bd00c7e16977eb10f Mon Sep 17 00:00:00 2001 From: richTrash21 Date: Thu, 23 May 2024 21:52:28 +0400 Subject: [PATCH 094/216] safety --- source/funkin/ui/freeplay/FreeplayState.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 2dea923529..4d1ad70194 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -536,7 +536,7 @@ class FreeplayState extends MusicBeatSubState grpTxtScrolls.visible = true; // render optimisation - _parentState.persistentDraw = false; + if (_parentState != null) _parentState.persistentDraw = false; }); generateSongList(null, false); From 28bf46022aa41bb0eeebcc32ae0fee88c9696884 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 23 May 2024 14:37:50 -0400 Subject: [PATCH 095/216] add simple PR auto labelling action --- .github/labeler.yml | 12 ++++++++++++ .github/workflows/labeler.yml | 14 ++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 .github/labeler.yml create mode 100644 .github/workflows/labeler.yml diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 0000000000..e8e4908652 --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,12 @@ +# Add Documentation tag to PR's changing markdown files, or anyhting in the docs folder +Documentation: +- changed-files: + - any-glob-to-any-file: + - any-glob-to-any-file: + - docs/* + - '**/*.md' + +# Adds Haxe tag to PR's changing haxe code files +Haxe: +- changed-files: + - any-glob-to-any-file: '**/*.hx' diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml new file mode 100644 index 0000000000..195b22b7c0 --- /dev/null +++ b/.github/workflows/labeler.yml @@ -0,0 +1,14 @@ +name: "Pull Request Labeler" +on: +- pull_request + +jobs: + labeler: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + - uses: actions/labeler@v5 + with: + sync-labels: true From 5d866cb1867c1675d370cd06f805e08a9e307ea7 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 23 May 2024 14:53:25 -0400 Subject: [PATCH 096/216] pr target --- .github/workflows/labeler.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 195b22b7c0..0bcc420d34 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -1,6 +1,6 @@ name: "Pull Request Labeler" on: -- pull_request +- pull_request_target jobs: labeler: From a2ee359e466746646c278d0adbef0c1fd08d21c1 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 23 May 2024 16:31:18 -0400 Subject: [PATCH 097/216] fix for songs overlapping each other on desktop --- source/funkin/audio/FunkinSound.hx | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index 5a49e29eea..aaddda9dcb 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -364,10 +364,20 @@ class FunkinSound extends FlxSound implements ICloneable if (music != null) { + for (future in partialQueue) + { + future = cast Future.withError("Music was overridden by another partial load"); + } + partialQueue = []; + partialQueue.push(music); + + @:nullSafety(Off) music.onComplete(function(partialMusic:Null) { - @:nullSafety(Off) - FlxG.sound.music = partialMusic; - FlxG.sound.list.remove(FlxG.sound.music); + if (partialQueue.pop() == music) + { + FlxG.sound.music = partialMusic; + FlxG.sound.list.remove(FlxG.sound.music); + } }); return true; @@ -396,6 +406,8 @@ class FunkinSound extends FlxSound implements ICloneable } } + static var partialQueue:Array>> = []; + /** * Creates a new `FunkinSound` object synchronously. * @@ -461,6 +473,8 @@ class FunkinSound extends FlxSound implements ICloneable * @param looped Whether the sound file should loop * @param autoDestroy Whether the sound file should be destroyed after it finishes playing * @param autoPlay Whether the sound file should play immediately + * @param onComplete Callback when the sound finishes playing + * @param onLoad Callback when the sound finishes loading * @return A FunkinSound object */ public static function loadPartial(path:String, start:Float = 0, end:Float = 1, volume:Float = 1.0, looped:Bool = false, autoDestroy:Bool = false, From 44880fa5697ddf16a62211cd4089d63371acaf46 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 24 May 2024 00:06:26 -0400 Subject: [PATCH 098/216] Implement placeholder GREAT animation --- source/funkin/InitState.hx | 2 +- source/funkin/play/ResultState.hx | 29 +++++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/source/funkin/InitState.hx b/source/funkin/InitState.hx index d17554d11e..a945c10c54 100644 --- a/source/funkin/InitState.hx +++ b/source/funkin/InitState.hx @@ -227,7 +227,7 @@ class InitState extends FlxState tallies: { sick: 130, - good: 70, + good: 25, bad: 69, shit: 69, missed: 69, diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index fdcd0cc397..ee7c8eade5 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -53,6 +53,7 @@ class ResultState extends MusicBeatSubState var bfPerfect:Null = null; var bfExcellent:Null = null; + var bfGreat:Null = null; var bfGood:Null = null; var gfGood:Null = null; var bfShit:Null = null; @@ -151,7 +152,20 @@ class ResultState extends MusicBeatSubState } }); - case GOOD | GREAT: + case GREAT: + bfGreat = new FlxAtlasSprite(640, 200, Paths.animateAtlas("resultScreen/results-bf/resultsGREAT", "shared")); + bfGreat.visible = false; + bfGreat.zIndex = 500; + add(bfGreat); + + bfGreat.onAnimationFinish.add((animName) -> { + if (bfGreat != null) + { + bfGreat.playAnimation('Loop Start'); + } + }); + + case GOOD: gfGood = FunkinSprite.createSparrow(625, 325, 'resultScreen/results-bf/resultsGOOD/resultGirlfriendGOOD'); gfGood.animation.addByPrefix("clap", "Girlfriend Good Anim", 24, false); gfGood.visible = false; @@ -476,6 +490,17 @@ class ResultState extends MusicBeatSubState bfExcellent.playAnimation('Intro'); } + case GREAT: + if (bfGreat == null) + { + trace("Could not build GREAT animation!"); + } + else + { + bfGreat.visible = true; + bfGreat.playAnimation('Intro'); + } + case SHIT: if (bfShit == null) { @@ -487,7 +512,7 @@ class ResultState extends MusicBeatSubState bfShit.playAnimation('Intro'); } - case GREAT | GOOD: + case GOOD: if (bfGood == null) { trace("Could not build GOOD animation!"); From 2db99b3cb41bef826bd3a286ac0d942476dc5eee Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 24 May 2024 00:06:52 -0400 Subject: [PATCH 099/216] Update submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index b6d930109e..2a57e34061 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit b6d930109eb69cfd368145e893d81ac1e97ed004 +Subproject commit 2a57e34061f6034236663851332319c5dedab259 From 0e920237940d894ffb9be77f67f4d73a8463d1f3 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 24 May 2024 00:21:45 -0400 Subject: [PATCH 100/216] Add credits for all charts + tweak charts for Guns, Lit Up, Winter Horrorland --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 778e16705b..826be3bf1e 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 778e16705b30af85087f627594c22f4b5ba6141a +Subproject commit 826be3bf1e635e6b61c8c11bd3ece51f8a2b3061 From 62e04b3372fe1b9f7256585a23ed38a5b51db98f Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 24 May 2024 13:24:11 -0400 Subject: [PATCH 101/216] Update Changelog --- CHANGELOG.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7f8300476..10bbfe5f7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,46 @@ All notable changes will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.4.0] - 2024-05-?? +### Added +- 2 new Erect remixes, Eggnog and Satin Panties. Check them out from +- Improvements to the Freeplay screen, with song difficulty ratings and player rank displays. +- Reworked the Results screen, with additional animations and audio based on your performance. +- Added a Charter field to the chart format, to allow for crediting the creator of a level's chart. + - You can see who charted a song from the Pause menu. +### Changed +- Tweaked the charts for several songs: + - Winter Horrorland + - Stress + - Lit Up +- Custom note styles are now properly supported for songs; add new notestyles via JSON, then select it for use from the Chart Editor Metadata toolbox. (thanks Keoiki!) +- Health icons now support a Winning frame without requiring a spritesheet, simply include a third frame in the icon file. (thanks gamerbross!) + - Remember that for more complex behaviors such as animations or transitions, you should use an XML file to define each frame. +### Fixed +- Fixed a bug where pressing the volume keys would stop the Toy commercial (thanks gamerbross!) +- Fixed a bug where the Chart Editor would crash when losing (thanks gamerbross!) +- Made improvements to compiling documentation (thanks gedehari!) +- Fixed a crash on Linux caused by an old version of hxCodec (thanks Noobz4Life!) +- Optimized animation handling for characters (thanks richTrash21!) + +## [0.3.3] - 2024-05-14 +### Changed +- Cleaned up some code in `PlayAnimationSongEvent.hx` (thanks BurgerBalls!) +### Fixed +- Fix Web Loading Bar (thanks lemz1!) +- Don't allow any more inputs when exiting freeplay (thanks gamerbros!) +- Fixed using mouse wheel to scroll on freeplay (thanks JugieNoob!) +- Fixed the reset's of the health icons, score, and notes when re-entering gameplay from gameover (thanks ImCodist!) +- Fixed the chart editor character selector's hitbox width (thanks MadBear422!) +- Fixed camera stutter once a wipe transition to the Main Menu completes (thanks ImCodist!) +- Fixed an issue where hold note would be invisible for a single frame (thanks ImCodist!) +- Fix tween accumulation on title screen when pressing Y multiple times (thanks TheGaloXx!) +- Fix for a game over easter egg so you don't accidentally exit it when viewing +- Fix a crash when querying FlxG.state in the crash handler +- Fix an issue where the Freeplay menu never displays 100% clear +- Chart debug key now properly returns you to the previous chart editor session if you were playtesting a chart (thanks nebulazorua!) +- Hopefully fixed Freeplay crashes on AMD gpu's + ## [0.3.2] - 2024-05-03 ### Added - Added `,` and `.` keybinds to the Chart Editor. These place Focus Camera events at the playhead, for the opponent and player respectively. From c8930b598025f6f9faff795aeb3280ae3480c6b6 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 24 May 2024 13:45:37 -0400 Subject: [PATCH 102/216] Attempt to repair local submodules --- .gitmodules | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitmodules b/.gitmodules index 2d5c11067d..452c0089b7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,5 +1,6 @@ [submodule "assets"] path = assets url = https://github.com/FunkinCrew/Funkin-Assets-secret +[submodule "art"] path = art url = https://github.com/FunkinCrew/Funkin-Art-secret From 98505e58eca59a084bdd5fc98765ee53aca7c926 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 24 May 2024 14:04:55 -0400 Subject: [PATCH 103/216] Take two at fixing submodules --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 66572f85d8..52e007f5b6 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 66572f85d826ce2ec1d45468c12733b161237ffa +Subproject commit 52e007f5b682ee7b9d252edba78a88780510d32b From 85bfd00bade0d7413b578d7152afa6cc8f93f1d6 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 24 May 2024 16:38:35 -0400 Subject: [PATCH 104/216] desktop vis testing --- Project.xml | 1 + hmm.json | 9 ++++++++- source/funkin/audio/visualize/ABotVis.hx | 8 +++----- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Project.xml b/Project.xml index 24cdac2700..03e87e2d87 100644 --- a/Project.xml +++ b/Project.xml @@ -125,6 +125,7 @@ + diff --git a/hmm.json b/hmm.json index 288aa80b8b..a1998f515d 100644 --- a/hmm.json +++ b/hmm.json @@ -49,9 +49,16 @@ "name": "funkin.vis", "type": "git", "dir": null, - "ref": "2aa654b974507ab51ab1724d2d97e75726fd7d78", + "ref": "c6a1e24d48646849ea63563ca45561512c953779", "url": "https://github.com/FunkinCrew/funkVis" }, + { + "name": "grig.audio", + "type": "git", + "dir": "src", + "ref": "cbf91e2180fd2e374924fe74844086aab7891666", + "url": "https://gitlab.com/haxe-grig/grig.audio.git" + }, { "name": "hamcrest", "type": "haxelib", diff --git a/source/funkin/audio/visualize/ABotVis.hx b/source/funkin/audio/visualize/ABotVis.hx index ca77dd58aa..15596318c3 100644 --- a/source/funkin/audio/visualize/ABotVis.hx +++ b/source/funkin/audio/visualize/ABotVis.hx @@ -58,8 +58,8 @@ class ABotVis extends FlxTypedSpriteGroup public function initAnalyzer() { @:privateAccess - analyzer = new SpectralAnalyzer(7, new LimeAudioClip(cast snd._channel.__source), 0.01, 30); - analyzer.maxDb = -35; + analyzer = new SpectralAnalyzer(snd._channel.__source, 7, 0.01, 30); + // analyzer.maxDb = -35; // analyzer.fftN = 2048; } @@ -83,9 +83,7 @@ class ABotVis extends FlxTypedSpriteGroup override function draw() { - #if web if (analyzer != null) drawFFT(); - #end super.draw(); } @@ -94,7 +92,7 @@ class ABotVis extends FlxTypedSpriteGroup */ function drawFFT():Void { - var levels = analyzer.getLevels(false); + var levels = analyzer.getLevels(); for (i in 0...min(group.members.length, levels.length)) { From dd3e241f0c08ae5239ba081c1022acc96e993abe Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 24 May 2024 16:44:12 -0400 Subject: [PATCH 105/216] Fix some merge conflicts --- source/funkin/input/Controls.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/input/Controls.hx b/source/funkin/input/Controls.hx index 31551dec94..345791eefe 100644 --- a/source/funkin/input/Controls.hx +++ b/source/funkin/input/Controls.hx @@ -997,7 +997,7 @@ class Controls extends FlxActionSet for (control in Control.createAll()) { var inputs:Array = Reflect.field(data, control.getName()); - inputs = inputs.unique(); + inputs = inputs.distinct(); if (inputs != null) { if (inputs.length == 0) { @@ -1050,7 +1050,7 @@ class Controls extends FlxActionSet if (inputs.length == 0) { inputs = [FlxKey.NONE]; } else { - inputs = inputs.unique(); + inputs = inputs.distinct(); } Reflect.setField(data, control.getName(), inputs); From 07959d3e88898048cc1037a43310c20223cf18b1 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Sat, 25 May 2024 01:08:17 +0200 Subject: [PATCH 106/216] Fix Unscripted Stage Log Trace --- source/funkin/data/BaseRegistry.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/data/BaseRegistry.hx b/source/funkin/data/BaseRegistry.hx index 118516bec3..2df3a87dae 100644 --- a/source/funkin/data/BaseRegistry.hx +++ b/source/funkin/data/BaseRegistry.hx @@ -117,7 +117,7 @@ abstract class BaseRegistry & Constructible Date: Sat, 25 May 2024 01:21:37 +0200 Subject: [PATCH 107/216] Fix Legacy Chart Importer wrong instrumental --- source/funkin/data/song/importer/FNFLegacyImporter.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/data/song/importer/FNFLegacyImporter.hx b/source/funkin/data/song/importer/FNFLegacyImporter.hx index ab2abda8e1..87f3f81367 100644 --- a/source/funkin/data/song/importer/FNFLegacyImporter.hx +++ b/source/funkin/data/song/importer/FNFLegacyImporter.hx @@ -65,7 +65,7 @@ class FNFLegacyImporter songMetadata.timeChanges = rebuildTimeChanges(songData); - songMetadata.playData.characters = new SongCharacterData(songData?.song?.player1 ?? 'bf', 'gf', songData?.song?.player2 ?? 'dad', 'mom'); + songMetadata.playData.characters = new SongCharacterData(songData?.song?.player1 ?? 'bf', 'gf', songData?.song?.player2 ?? 'dad'); return songMetadata; } From cb2f4b0f06f66a343edb6efe33f44d21d66dbc8c Mon Sep 17 00:00:00 2001 From: PurSnake <56314743+PurSnake@users.noreply.github.com> Date: Sat, 25 May 2024 21:00:10 +0300 Subject: [PATCH 108/216] [BUGFIX] Correct characters scaling bruh --- source/funkin/play/stage/Stage.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/play/stage/Stage.hx b/source/funkin/play/stage/Stage.hx index eb9eb18108..e9c99558dd 100644 --- a/source/funkin/play/stage/Stage.hx +++ b/source/funkin/play/stage/Stage.hx @@ -124,7 +124,7 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements getGirlfriend().resetCharacter(true); // Reapply the camera offsets. var stageCharData:StageDataCharacter = _data.characters.gf; - var finalScale:Float = getBoyfriend().getBaseScale() * stageCharData.scale; + var finalScale:Float = getGirlfriend().getBaseScale() * stageCharData.scale; getGirlfriend().setScale(finalScale); getGirlfriend().cameraFocusPoint.x += stageCharData.cameraOffsets[0]; getGirlfriend().cameraFocusPoint.y += stageCharData.cameraOffsets[1]; @@ -134,7 +134,7 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements getDad().resetCharacter(true); // Reapply the camera offsets. var stageCharData:StageDataCharacter = _data.characters.dad; - var finalScale:Float = getBoyfriend().getBaseScale() * stageCharData.scale; + var finalScale:Float = getDad().getBaseScale() * stageCharData.scale; getDad().setScale(finalScale); getDad().cameraFocusPoint.x += stageCharData.cameraOffsets[0]; getDad().cameraFocusPoint.y += stageCharData.cameraOffsets[1]; From 6c0d998edd02f39863b840e5557fdb8375d367b5 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 28 May 2024 01:18:18 -0400 Subject: [PATCH 109/216] update funkVis in hmm --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index a1998f515d..e364e405fe 100644 --- a/hmm.json +++ b/hmm.json @@ -49,7 +49,7 @@ "name": "funkin.vis", "type": "git", "dir": null, - "ref": "c6a1e24d48646849ea63563ca45561512c953779", + "ref": "38261833590773cb1de34ac5d11e0825696fc340", "url": "https://github.com/FunkinCrew/funkVis" }, { From 004ed32fad81f096a925b3e3068e55e27fd33a3d Mon Sep 17 00:00:00 2001 From: Axuko Date: Mon, 27 May 2024 22:34:28 -0700 Subject: [PATCH 110/216] Remove alot of unused imoprts --- source/funkin/api/newgrounds/NGUnsafe.hx | 4 ---- source/funkin/api/newgrounds/NGio.hx | 8 -------- source/funkin/audio/FunkinSound.hx | 3 +-- source/funkin/audio/VoicesGroup.hx | 2 -- source/funkin/audio/visualize/ABotVis.hx | 4 ---- source/funkin/audio/visualize/PolygonVisGroup.hx | 1 - source/funkin/audio/visualize/SpectogramSprite.hx | 12 ------------ source/funkin/audio/visualize/VisShit.hx | 5 ----- source/funkin/audio/visualize/dsp/FFT.hx | 2 -- source/funkin/audio/waveform/WaveformData.hx | 2 -- source/funkin/audio/waveform/WaveformSprite.hx | 2 -- .../data/dialogue/conversation/ConversationData.hx | 2 -- .../dialogue/conversation/ConversationRegistry.hx | 1 - 13 files changed, 1 insertion(+), 47 deletions(-) diff --git a/source/funkin/api/newgrounds/NGUnsafe.hx b/source/funkin/api/newgrounds/NGUnsafe.hx index 9616dfe187..77e44bd1d4 100644 --- a/source/funkin/api/newgrounds/NGUnsafe.hx +++ b/source/funkin/api/newgrounds/NGUnsafe.hx @@ -1,9 +1,5 @@ package funkin.api.newgrounds; -import flixel.util.FlxSignal; -import flixel.util.FlxTimer; -import lime.app.Application; -import openfl.display.Stage; #if newgrounds import io.newgrounds.NG; import io.newgrounds.NGLite; diff --git a/source/funkin/api/newgrounds/NGio.hx b/source/funkin/api/newgrounds/NGio.hx index c1f8ad3ba4..3f5fc078ac 100644 --- a/source/funkin/api/newgrounds/NGio.hx +++ b/source/funkin/api/newgrounds/NGio.hx @@ -2,19 +2,11 @@ package funkin.api.newgrounds; #if newgrounds import flixel.util.FlxSignal; -import flixel.util.FlxTimer; import io.newgrounds.NG; import io.newgrounds.NGLite; -import io.newgrounds.components.ScoreBoardComponent.Period; import io.newgrounds.objects.Error; -import io.newgrounds.objects.Medal; import io.newgrounds.objects.Score; -import io.newgrounds.objects.ScoreBoard; -import io.newgrounds.objects.events.Response; -import io.newgrounds.objects.events.Result.GetCurrentVersionResult; -import io.newgrounds.objects.events.Result.GetVersionResult; import lime.app.Application; -import openfl.display.Stage; #end /** diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index df05cc3ef6..939b17f28c 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -11,10 +11,9 @@ import funkin.audio.waveform.WaveformDataParser; import funkin.data.song.SongData.SongMusicData; import funkin.data.song.SongRegistry; import funkin.util.tools.ICloneable; -import openfl.Assets; import openfl.media.SoundMixer; + #if (openfl >= "8.0.0") -import openfl.utils.AssetType; #end /** diff --git a/source/funkin/audio/VoicesGroup.hx b/source/funkin/audio/VoicesGroup.hx index 5037ee1d0c..9a1e0e0c17 100644 --- a/source/funkin/audio/VoicesGroup.hx +++ b/source/funkin/audio/VoicesGroup.hx @@ -1,9 +1,7 @@ package funkin.audio; -import funkin.audio.FunkinSound; import flixel.group.FlxGroup.FlxTypedGroup; import funkin.audio.waveform.WaveformData; -import funkin.audio.waveform.WaveformDataParser; class VoicesGroup extends SoundGroup { diff --git a/source/funkin/audio/visualize/ABotVis.hx b/source/funkin/audio/visualize/ABotVis.hx index ca77dd58aa..b94f20b38a 100644 --- a/source/funkin/audio/visualize/ABotVis.hx +++ b/source/funkin/audio/visualize/ABotVis.hx @@ -1,13 +1,9 @@ package funkin.audio.visualize; -import funkin.audio.visualize.dsp.FFT; import flixel.FlxSprite; -import flixel.addons.plugin.taskManager.FlxTask; import flixel.graphics.frames.FlxAtlasFrames; import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup; -import flixel.math.FlxMath; import flixel.sound.FlxSound; -import funkin.util.MathUtil; import funkin.vis.dsp.SpectralAnalyzer; import funkin.vis.audioclip.frontends.LimeAudioClip; diff --git a/source/funkin/audio/visualize/PolygonVisGroup.hx b/source/funkin/audio/visualize/PolygonVisGroup.hx index cc68f4ae08..bff8457965 100644 --- a/source/funkin/audio/visualize/PolygonVisGroup.hx +++ b/source/funkin/audio/visualize/PolygonVisGroup.hx @@ -1,6 +1,5 @@ package funkin.audio.visualize; -import funkin.audio.visualize.PolygonSpectogram; import flixel.group.FlxGroup.FlxTypedGroup; import flixel.sound.FlxSound; diff --git a/source/funkin/audio/visualize/SpectogramSprite.hx b/source/funkin/audio/visualize/SpectogramSprite.hx index 636c0726a6..615e80d956 100644 --- a/source/funkin/audio/visualize/SpectogramSprite.hx +++ b/source/funkin/audio/visualize/SpectogramSprite.hx @@ -8,8 +8,6 @@ import flixel.sound.FlxSound; import flixel.util.FlxColor; import funkin.audio.visualize.PolygonSpectogram.VISTYPE; import funkin.audio.visualize.VisShit.CurAudioInfo; -import funkin.audio.visualize.dsp.FFT; -import lime.system.ThreadPool; import lime.utils.Int16Array; using Lambda; @@ -38,8 +36,6 @@ class SpectogramSprite extends FlxTypedSpriteGroup lengthOfShit = amnt; regenLineShit(); - - // makeGraphic(200, 200, FlxColor.BLACK); } public function regenLineShit():Void @@ -89,8 +85,6 @@ class SpectogramSprite extends FlxTypedSpriteGroup { checkAndSetBuffer(); - // vis.checkAndSetBuffer(); - if (setBuffer) { var samplesToGen:Int = Std.int(sampleRate * seconds); @@ -191,7 +185,6 @@ class SpectogramSprite extends FlxTypedSpriteGroup // a value between 10hz and 100Khz var hzPicker:Float = Math.pow(10, powedShit); - // var sampleApprox:Int = Std.int(FlxMath.remapToRange(i, 0, group.members.length, startingSample, startingSample + samplesToGen)); var remappedFreq:Int = Std.int(FlxMath.remapToRange(hzPicker, 0, 10000, 0, freqShit[0].length - 1)); group.members[i].x = prevLine.x; @@ -211,8 +204,6 @@ class SpectogramSprite extends FlxTypedSpriteGroup var line = FlxPoint.get(prevLine.x - group.members[i].x, prevLine.y - group.members[i].y); // dont draw a line until i figure out a nicer way to view da spikes and shit idk lol! - // group.members[i].setGraphicSize(Std.int(Math.max(line.length, 1)), Std.int(1)); - // group.members[i].angle = line.degrees; } } } @@ -261,9 +252,6 @@ class SpectogramSprite extends FlxTypedSpriteGroup group.members[Std.int(remappedSample)].x = prevLine.x; group.members[Std.int(remappedSample)].y = prevLine.y; - // group.members[0].y = prevLine.y; - - // FlxSpriteUtil.drawLine(this, prevLine.x, prevLine.y, width * remappedSample, left * height / 2 + height / 2); prevLine.x = (curAud.balanced * swagheight / 2 + swagheight / 2) + x; prevLine.y = (Std.int(remappedSample) / lengthOfShit * daHeight) + y; diff --git a/source/funkin/audio/visualize/VisShit.hx b/source/funkin/audio/visualize/VisShit.hx index 204ced1e1a..ba235fe890 100644 --- a/source/funkin/audio/visualize/VisShit.hx +++ b/source/funkin/audio/visualize/VisShit.hx @@ -3,7 +3,6 @@ package funkin.audio.visualize; import flixel.math.FlxMath; import flixel.sound.FlxSound; import funkin.audio.visualize.dsp.FFT; -import lime.system.ThreadPool; import lime.utils.Int16Array; import funkin.util.MathUtil; @@ -73,9 +72,6 @@ class VisShit freqOutput.push([]); - // if (FlxG.keys.justPressed.M) - // trace(FFT.rfft(chunk).map(z -> z.scale(1 / fs).magnitude)); - // find spectral peaks and their instantaneous frequencies for (k => s in freqs) { @@ -91,7 +87,6 @@ class VisShit if (freq < maxFreq) freqOutput[indexOfArray].push(power); // } - // haxe.Log.trace("", null); indexOfArray++; // move to next (overlapping) chunk diff --git a/source/funkin/audio/visualize/dsp/FFT.hx b/source/funkin/audio/visualize/dsp/FFT.hx index dc75acb814..40ee9cb8c3 100644 --- a/source/funkin/audio/visualize/dsp/FFT.hx +++ b/source/funkin/audio/visualize/dsp/FFT.hx @@ -1,7 +1,5 @@ package funkin.audio.visualize.dsp; -import funkin.audio.visualize.dsp.Complex; - using funkin.audio.visualize.dsp.OffsetArray; using funkin.audio.visualize.dsp.Signal; diff --git a/source/funkin/audio/waveform/WaveformData.hx b/source/funkin/audio/waveform/WaveformData.hx index 1f649b4728..a939f91bf9 100644 --- a/source/funkin/audio/waveform/WaveformData.hx +++ b/source/funkin/audio/waveform/WaveformData.hx @@ -1,7 +1,5 @@ package funkin.audio.waveform; -import funkin.util.MathUtil; - @:nullSafety class WaveformData { diff --git a/source/funkin/audio/waveform/WaveformSprite.hx b/source/funkin/audio/waveform/WaveformSprite.hx index 32ced2fbd3..8eaba8117d 100644 --- a/source/funkin/audio/waveform/WaveformSprite.hx +++ b/source/funkin/audio/waveform/WaveformSprite.hx @@ -1,7 +1,5 @@ package funkin.audio.waveform; -import funkin.audio.waveform.WaveformData; -import funkin.audio.waveform.WaveformDataParser; import funkin.graphics.rendering.MeshRender; import flixel.util.FlxColor; diff --git a/source/funkin/data/dialogue/conversation/ConversationData.hx b/source/funkin/data/dialogue/conversation/ConversationData.hx index 30e3f451be..6505198367 100644 --- a/source/funkin/data/dialogue/conversation/ConversationData.hx +++ b/source/funkin/data/dialogue/conversation/ConversationData.hx @@ -1,7 +1,5 @@ package funkin.data.dialogue.conversation; -import funkin.data.animation.AnimationData; - /** * A type definition for the data for a specific conversation. * It includes things like what dialogue boxes to use, what text to display, and what animations to play. diff --git a/source/funkin/data/dialogue/conversation/ConversationRegistry.hx b/source/funkin/data/dialogue/conversation/ConversationRegistry.hx index ca072897fd..fad1e43adc 100644 --- a/source/funkin/data/dialogue/conversation/ConversationRegistry.hx +++ b/source/funkin/data/dialogue/conversation/ConversationRegistry.hx @@ -1,7 +1,6 @@ package funkin.data.dialogue.conversation; import funkin.play.cutscene.dialogue.Conversation; -import funkin.data.dialogue.conversation.ConversationData; import funkin.play.cutscene.dialogue.ScriptedConversation; class ConversationRegistry extends BaseRegistry From 9a47666fc7f5e51dc3b58df2023ec63d6a61202f Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 28 May 2024 01:37:30 -0400 Subject: [PATCH 111/216] Fix a merge issue. --- source/funkin/input/Controls.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/input/Controls.hx b/source/funkin/input/Controls.hx index 31551dec94..345791eefe 100644 --- a/source/funkin/input/Controls.hx +++ b/source/funkin/input/Controls.hx @@ -997,7 +997,7 @@ class Controls extends FlxActionSet for (control in Control.createAll()) { var inputs:Array = Reflect.field(data, control.getName()); - inputs = inputs.unique(); + inputs = inputs.distinct(); if (inputs != null) { if (inputs.length == 0) { @@ -1050,7 +1050,7 @@ class Controls extends FlxActionSet if (inputs.length == 0) { inputs = [FlxKey.NONE]; } else { - inputs = inputs.unique(); + inputs = inputs.distinct(); } Reflect.setField(data, control.getName(), inputs); From d4b2e9496382ef967d425d7fe92ca4a816dafe04 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 28 May 2024 02:17:55 -0400 Subject: [PATCH 112/216] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 8a8239cb50..371cce1fdc 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 8a8239cb50b5277fb0cfce041b3d8a9dfc780c35 +Subproject commit 371cce1fdc44914ddc3a5327e996cece4e676715 From cf61b9ef90810451c1a186c0388325f4d012bb9a Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Tue, 28 May 2024 14:51:16 +0200 Subject: [PATCH 113/216] Add toString to Stage + Revert "Fix Unscripted Stage Log Trace" --- source/funkin/data/BaseRegistry.hx | 2 +- source/funkin/play/stage/Stage.hx | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/source/funkin/data/BaseRegistry.hx b/source/funkin/data/BaseRegistry.hx index 2df3a87dae..118516bec3 100644 --- a/source/funkin/data/BaseRegistry.hx +++ b/source/funkin/data/BaseRegistry.hx @@ -117,7 +117,7 @@ abstract class BaseRegistry & Constructible { return StageRegistry.instance.parseEntryDataWithMigration(id, StageRegistry.instance.fetchEntryVersion(id)); From 1ae30283a3a0d2a3bafb6d4da84d906764e80ed6 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 28 May 2024 15:34:09 -0400 Subject: [PATCH 114/216] re add the xmlns schema stuff --- Project.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Project.xml b/Project.xml index 24cdac2700..dce45546fb 100644 --- a/Project.xml +++ b/Project.xml @@ -1,5 +1,6 @@ - + @@ -14,6 +15,7 @@ + < @@ -28,7 +30,7 @@ - + From 01b6a11ddbbacc034f73b61451b78587b3536b7d Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 28 May 2024 22:57:01 -0400 Subject: [PATCH 115/216] flxpartialsound lock to current version --- hmm.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hmm.json b/hmm.json index 6b119c52fb..5260d5229f 100644 --- a/hmm.json +++ b/hmm.json @@ -4,7 +4,7 @@ "name": "FlxPartialSound", "type": "git", "dir": null, - "ref": "main", + "ref": "8bb8ed50f520d9cd64a65414b119b8718924b93a", "url": "https://github.com/FunkinCrew/FlxPartialSound.git" }, { @@ -178,4 +178,4 @@ "url": "https://github.com/FunkinCrew/thx.semver" } ] -} \ No newline at end of file +} From 2d300039ae42988c570af0f36225c1732a4fb09c Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 28 May 2024 23:53:50 -0400 Subject: [PATCH 116/216] promises + error out partial sounds that attempt to load multiple times --- source/funkin/audio/FunkinSound.hx | 32 +++++++++++++++++------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index aaddda9dcb..39a26aac1b 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -360,24 +360,24 @@ class FunkinSound extends FlxSound implements ICloneable if (shouldLoadPartial) { var music = FunkinSound.loadPartial(pathToUse, params.partialParams?.start ?? 0, params.partialParams?.end ?? 1, params?.startingVolume ?? 1.0, - params.loop ?? true, false, true, params.onComplete, params.onLoad); + params.loop ?? true, false, false, params.onComplete); if (music != null) { - for (future in partialQueue) + while (partialQueue.length > 0) { - future = cast Future.withError("Music was overridden by another partial load"); + @:nullSafety(Off) + partialQueue.pop().error("Cancel loading partial sound"); } - partialQueue = []; + partialQueue.push(music); @:nullSafety(Off) - music.onComplete(function(partialMusic:Null) { - if (partialQueue.pop() == music) - { - FlxG.sound.music = partialMusic; - FlxG.sound.list.remove(FlxG.sound.music); - } + music.future.onComplete(function(partialMusic:Null) { + FlxG.sound.music = partialMusic; + FlxG.sound.list.remove(FlxG.sound.music); + + if (params.onLoad != null) params.onLoad(); }); return true; @@ -406,7 +406,7 @@ class FunkinSound extends FlxSound implements ICloneable } } - static var partialQueue:Array>> = []; + static var partialQueue:Array>> = []; /** * Creates a new `FunkinSound` object synchronously. @@ -478,7 +478,7 @@ class FunkinSound extends FlxSound implements ICloneable * @return A FunkinSound object */ public static function loadPartial(path:String, start:Float = 0, end:Float = 1, volume:Float = 1.0, looped:Bool = false, autoDestroy:Bool = false, - autoPlay:Bool = true, ?onComplete:Void->Void, ?onLoad:Void->Void):Future> + autoPlay:Bool = true, ?onComplete:Void->Void, ?onLoad:Void->Void):Promise> { var promise:lime.app.Promise> = new lime.app.Promise>(); @@ -488,12 +488,16 @@ class FunkinSound extends FlxSound implements ICloneable var soundRequest = FlxPartialSound.partialLoadFromFile(path, start, end); - soundRequest.onComplete(function(partialSound) { + promise.future.onError(function(e) { + soundRequest.error("Sound loading was errored or cancelled"); + }); + + soundRequest.future.onComplete(function(partialSound) { var snd = FunkinSound.load(partialSound, volume, looped, autoDestroy, autoPlay, onComplete, onLoad); promise.complete(snd); }); - return promise.future; + return promise; } @:nullSafety(Off) From 1f64c7fcc9757004925fdb641f5b9f19be248e5f Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 28 May 2024 23:54:23 -0400 Subject: [PATCH 117/216] update hmm flxpartialsound --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index 5260d5229f..91d2f08bb3 100644 --- a/hmm.json +++ b/hmm.json @@ -4,7 +4,7 @@ "name": "FlxPartialSound", "type": "git", "dir": null, - "ref": "8bb8ed50f520d9cd64a65414b119b8718924b93a", + "ref": "44aa7eb", "url": "https://github.com/FunkinCrew/FlxPartialSound.git" }, { From d97d77566e1e30800bb3c5f8ba973af38a8ded0b Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 29 May 2024 00:53:32 -0400 Subject: [PATCH 118/216] Make song score lerp faster --- source/funkin/ui/story/StoryMenuState.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx index 820ac2ad14..c1a001e5de 100644 --- a/source/funkin/ui/story/StoryMenuState.hx +++ b/source/funkin/ui/story/StoryMenuState.hx @@ -306,7 +306,7 @@ class StoryMenuState extends MusicBeatState { Conductor.instance.update(); - highScoreLerp = Std.int(MathUtil.smoothLerp(highScoreLerp, highScore, elapsed, 0.5)); + highScoreLerp = Std.int(MathUtil.smoothLerp(highScoreLerp, highScore, elapsed, 0.25)); scoreText.text = 'LEVEL SCORE: ${Math.round(highScoreLerp)}'; From ee4be810622f896fb1ff12e9f9ad03889e85f455 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 29 May 2024 15:16:31 -0300 Subject: [PATCH 119/216] Now Preloader resets CWD --- source/funkin/ui/transition/preload/FunkinPreloader.hx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/funkin/ui/transition/preload/FunkinPreloader.hx b/source/funkin/ui/transition/preload/FunkinPreloader.hx index b71af2b3b3..9d25695884 100644 --- a/source/funkin/ui/transition/preload/FunkinPreloader.hx +++ b/source/funkin/ui/transition/preload/FunkinPreloader.hx @@ -136,6 +136,8 @@ class FunkinPreloader extends FlxBasePreloader // We can't even call trace() yet, until Flixel loads. trace('Initializing custom preloader...'); + funkin.util.CLIUtil.resetWorkingDir(); + this.siteLockTitleText = Constants.SITE_LOCK_TITLE; this.siteLockBodyText = Constants.SITE_LOCK_DESC; } From fb752ddd7860248c208fc612a4630f4be2bcee1c Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 29 May 2024 17:05:20 -0400 Subject: [PATCH 120/216] remove random < in project.xml lol --- Project.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/Project.xml b/Project.xml index 16e4b9854b..fcd29a25e4 100644 --- a/Project.xml +++ b/Project.xml @@ -15,7 +15,6 @@ xsi:schemaLocation="http://lime.openfl.org/project/1.0.4 http://lime.openfl.org/ - < From 8d7591a796f9c0c392eb66c8e494d5f9a7a5e36a Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 29 May 2024 21:43:54 -0400 Subject: [PATCH 121/216] Fix an issue where Story Menu props wouldn't render. --- source/funkin/ui/story/LevelProp.hx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/source/funkin/ui/story/LevelProp.hx b/source/funkin/ui/story/LevelProp.hx index 5a3efc36ae..0547404a1a 100644 --- a/source/funkin/ui/story/LevelProp.hx +++ b/source/funkin/ui/story/LevelProp.hx @@ -11,12 +11,15 @@ class LevelProp extends Bopper function set_propData(value:LevelPropData):LevelPropData { // Only reset the prop if the asset path has changed. - if (propData == null || value?.assetPath != propData?.assetPath) + if (propData == null || !(thx.Dynamics.equals(value, propData))) { + this.propData = value; + + this.visible = this.propData != null; + danceEvery = this.propData?.danceEvery ?? 0; + applyData(); } - this.visible = (value != null); - danceEvery = this.propData?.danceEvery ?? 0; return this.propData; } From 174c595837a63fef473ad191576e51862c240cc0 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 29 May 2024 22:49:57 -0400 Subject: [PATCH 122/216] Fix crash caused by improperly canceling a tween --- source/funkin/play/PauseSubState.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/play/PauseSubState.hx b/source/funkin/play/PauseSubState.hx index c345871a9a..8c45fac650 100644 --- a/source/funkin/play/PauseSubState.hx +++ b/source/funkin/play/PauseSubState.hx @@ -234,7 +234,7 @@ class PauseSubState extends MusicBeatSubState public override function destroy():Void { super.destroy(); - charterFadeTween.destroy(); + charterFadeTween.cancel(); charterFadeTween = null; pauseMusic.stop(); } From 6572d13a7f3212a047b2cb2266edf6938ddd7e2f Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 29 May 2024 23:21:32 -0400 Subject: [PATCH 123/216] Improve documentation a bit. --- source/funkin/play/event/ScrollSpeedEvent.hx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/funkin/play/event/ScrollSpeedEvent.hx b/source/funkin/play/event/ScrollSpeedEvent.hx index 9abd4be90a..c752d2f6d1 100644 --- a/source/funkin/play/event/ScrollSpeedEvent.hx +++ b/source/funkin/play/event/ScrollSpeedEvent.hx @@ -21,7 +21,9 @@ import funkin.data.event.SongEventSchema.SongEventFieldType; * "v": { * "scroll": "1.3", * "duration": "4", - * "ease": "linear" + * "ease": "linear", + * "strumline": "both", + * "absolute": false * } * } * ``` @@ -98,6 +100,8 @@ class ScrollSpeedEvent extends SongEvent * 'scroll': FLOAT, // Target scroll level. * 'duration': FLOAT, // Duration in steps. * 'ease': ENUM, // Easing function. + * 'strumline': ENUM, // Which strumline to change + * 'absolute': BOOL, // True to set the scroll speed to the target level, false to set the scroll speed to (target level x base scroll speed) * } * @return SongEventSchema */ From 68e9937b43994f7fb1b21347bad3cd02ef195815 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Thu, 30 May 2024 04:33:26 +0100 Subject: [PATCH 124/216] interval shake class --- source/funkin/effects/IntervalShake.hx | 240 +++++++++++++++++++++++++ 1 file changed, 240 insertions(+) create mode 100644 source/funkin/effects/IntervalShake.hx diff --git a/source/funkin/effects/IntervalShake.hx b/source/funkin/effects/IntervalShake.hx new file mode 100644 index 0000000000..545739cc33 --- /dev/null +++ b/source/funkin/effects/IntervalShake.hx @@ -0,0 +1,240 @@ +package funkin.effects; + +import flixel.FlxObject; +import flixel.util.FlxDestroyUtil.IFlxDestroyable; +import flixel.util.FlxPool; +import flixel.util.FlxTimer; +import flixel.math.FlxPoint; +import flixel.util.FlxAxes; +import flixel.tweens.FlxEase.EaseFunction; +import flixel.math.FlxMath; + +/** + * pretty much a copy of FlxFlicker geared towards making sprites + * shake around at a set interval and slow down over time. + */ +class IntervalShake implements IFlxDestroyable +{ + static var _pool:FlxPool = new FlxPool(IntervalShake.new); + + /** + * Internal map for looking up which objects are currently shaking and getting their shake data. + */ + static var _boundObjects:Map = new Map(); + + /** + * An effect that shakes the sprite on a set interval and a starting intensity that goes down over time. + * + * @param Object The object to shake. + * @param Duration How long to shake for (in seconds). `0` means "forever". + * @param Interval In what interval to update the shake position. Set to `FlxG.elapsed` if `<= 0`! + * @param StartIntensity The starting intensity of the shake. + * @param EndIntensity The ending intensity of the shake. + * @param Ease Control the easing of the intensity over the shake. + * @param CompletionCallback Callback on shake completion + * @param ProgressCallback Callback on each shake interval + * @return The `IntervalShake` object. `IntervalShake`s are pooled internally, so beware of storing references. + */ + public static function shake(Object:FlxObject, Duration:Float = 1, Interval:Float = 0.04, StartIntensity:Float = 0, EndIntensity:Float = 0, + Ease:EaseFunction, ?CompletionCallback:IntervalShake->Void, ?ProgressCallback:IntervalShake->Void):IntervalShake + { + if (isShaking(Object)) + { + // if (ForceRestart) + // { + // stopShaking(Object); + // } + // else + // { + // Ignore this call if object is already flickering. + return _boundObjects[Object]; + // } + } + + if (Interval <= 0) + { + Interval = FlxG.elapsed; + } + + var shake:IntervalShake = _pool.get(); + shake.start(Object, Duration, Interval, StartIntensity, EndIntensity, Ease, CompletionCallback, ProgressCallback); + return _boundObjects[Object] = shake; + } + + /** + * Returns whether the object is shaking or not. + * + * @param Object The object to test. + */ + public static function isShaking(Object:FlxObject):Bool + { + return _boundObjects.exists(Object); + } + + /** + * Stops shaking the object. + * + * @param Object The object to stop shaking. + */ + public static function stopShaking(Object:FlxObject):Void + { + var boundShake:IntervalShake = _boundObjects[Object]; + if (boundShake != null) + { + boundShake.stop(); + } + } + + /** + * The shaking object. + */ + public var object(default, null):FlxObject; + + /** + * The shaking timer. You can check how many seconds has passed since shaking started etc. + */ + public var timer(default, null):FlxTimer; + + /** + * The starting intensity of the shake. + */ + public var startIntensity(default, null):Float; + + /** + * The ending intensity of the shake. + */ + public var endIntensity(default, null):Float; + + /** + * How long to shake for (in seconds). `0` means "forever". + */ + public var duration(default, null):Float; + + /** + * The interval of the shake. + */ + public var interval(default, null):Float; + + /** + * Defines on what axes to `shake()`. Default value is `XY` / both. + */ + public var axes(default, null):FlxAxes; + + /** + * Defines the initial position of the object at the beginning of the shake effect. + */ + public var initialOffset(default, null):FlxPoint; + + /** + * The callback that will be triggered after the shake has completed. + */ + public var completionCallback(default, null):IntervalShake->Void; + + /** + * The callback that will be triggered every time the object shakes. + */ + public var progressCallback(default, null):IntervalShake->Void; + + /** + * The easing of the intensity over the shake. + */ + public var ease(default, null):EaseFunction; + + /** + * Nullifies the references to prepare object for reuse and avoid memory leaks. + */ + public function destroy():Void + { + object = null; + timer = null; + ease = null; + completionCallback = null; + progressCallback = null; + } + + /** + * Starts shaking behavior. + */ + function start(Object:FlxObject, Duration:Float = 1, Interval:Float = 0.04, StartIntensity:Float = 0, EndIntensity:Float = 0, Ease:EaseFunction, + ?CompletionCallback:IntervalShake->Void, ?ProgressCallback:IntervalShake->Void):Void + { + object = Object; + duration = Duration; + interval = Interval; + completionCallback = CompletionCallback; + startIntensity = StartIntensity; + endIntensity = EndIntensity; + initialOffset = new FlxPoint(Object.x, Object.y); + ease = Ease; + axes = FlxAxes.XY; + _secondsSinceStart = 0; + timer = new FlxTimer().start(interval, shakeProgress, Std.int(duration / interval)); + } + + /** + * Prematurely ends shaking. + */ + public function stop():Void + { + timer.cancel(); + // object.visible = true; + object.x = initialOffset.x; + object.y = initialOffset.y; + release(); + } + + /** + * Unbinds the object from shaking and releases it into pool for reuse. + */ + function release():Void + { + _boundObjects.remove(object); + _pool.put(this); + } + + public var _secondsSinceStart(default, null):Float = 0; + + public var scale(default, null):Float = 0; + + /** + * Just a helper function for shake() to update object's position. + */ + function shakeProgress(timer:FlxTimer):Void + { + _secondsSinceStart += interval; + scale = _secondsSinceStart / duration; + if (ease != null) + { + scale = 1 - ease(scale); + // trace(scale); + } + + var curIntensity:Float = 0; + curIntensity = FlxMath.lerp(endIntensity, startIntensity, scale); + + if (axes.x) object.x = initialOffset.x + FlxG.random.float((-curIntensity) * object.width, (curIntensity) * object.width); + if (axes.y) object.y = initialOffset.y + FlxG.random.float((-curIntensity) * object.width, (curIntensity) * object.width); + + // object.visible = !object.visible; + + if (progressCallback != null) progressCallback(this); + + if (timer.loops > 0 && timer.loopsLeft == 0) + { + object.x = initialOffset.x; + object.y = initialOffset.y; + if (completionCallback != null) + { + completionCallback(this); + } + + if (this.timer == timer) release(); + } + } + + /** + * Internal constructor. Use static methods. + */ + @:keep + function new() {} +} From e7079452fb4e54cc26d8c1cd132d70d0103a5d37 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Thu, 30 May 2024 04:34:00 +0100 Subject: [PATCH 125/216] freeplay visual changes + base rank visuals --- source/funkin/ui/freeplay/CapsuleText.hx | 135 +++++++ source/funkin/ui/freeplay/DJBoyfriend.hx | 35 ++ source/funkin/ui/freeplay/FreeplayState.hx | 396 +++++++++++++++++- source/funkin/ui/freeplay/SongMenuItem.hx | 450 ++++++++++++++++++++- 4 files changed, 992 insertions(+), 24 deletions(-) diff --git a/source/funkin/ui/freeplay/CapsuleText.hx b/source/funkin/ui/freeplay/CapsuleText.hx index 3a520e0152..c3fd51d1fd 100644 --- a/source/funkin/ui/freeplay/CapsuleText.hx +++ b/source/funkin/ui/freeplay/CapsuleText.hx @@ -4,6 +4,12 @@ import openfl.filters.BitmapFilterQuality; import flixel.text.FlxText; import flixel.group.FlxSpriteGroup; import funkin.graphics.shaders.GaussianBlurShader; +import funkin.graphics.shaders.LeftMaskShader; +import flixel.math.FlxRect; +import flixel.tweens.FlxEase; +import flixel.util.FlxTimer; +import flixel.tweens.FlxTween; +import openfl.display.BlendMode; class CapsuleText extends FlxSpriteGroup { @@ -13,6 +19,15 @@ class CapsuleText extends FlxSpriteGroup public var text(default, set):String; + var maskShaderSongName:LeftMaskShader = new LeftMaskShader(); + + public var clipWidth(default, set):Int = 255; + + public var tooLong:Bool = false; + + // 255, 27 normal + // 220, 27 favourited + public function new(x:Float, y:Float, songTitle:String, size:Float) { super(x, y); @@ -36,6 +51,30 @@ class CapsuleText extends FlxSpriteGroup return text; } + // ???? none + // 255, 27 normal + // 220, 27 favourited + + function set_clipWidth(value:Int):Int + { + resetText(); + if (whiteText.width > value) + { + tooLong = true; + + blurredText.clipRect = new FlxRect(0, 0, value, blurredText.height); + whiteText.clipRect = new FlxRect(0, 0, value, whiteText.height); + } + else + { + tooLong = false; + + blurredText.clipRect = null; + whiteText.clipRect = null; + } + return clipWidth = value; + } + function set_text(value:String):String { if (value == null) return value; @@ -51,6 +90,102 @@ class CapsuleText extends FlxSpriteGroup new openfl.filters.GlowFilter(0x00ccff, 1, 5, 5, 210, BitmapFilterQuality.MEDIUM), // new openfl.filters.BlurFilter(5, 5, BitmapFilterQuality.LOW) ]; + return text = value; } + + var moveTimer:FlxTimer = new FlxTimer(); + var moveTween:FlxTween; + + public function initMove():Void + { + moveTimer.start(0.6, (timer) -> { + moveTextRight(); + }); + } + + function moveTextRight():Void + { + var distToMove:Float = whiteText.width - clipWidth; + moveTween = FlxTween.tween(whiteText.offset, {x: distToMove}, 2, + { + onUpdate: function(_) { + whiteText.clipRect = new FlxRect(whiteText.offset.x, 0, clipWidth, whiteText.height); + blurredText.offset = whiteText.offset; + blurredText.clipRect = new FlxRect(whiteText.offset.x, 0, clipWidth, blurredText.height); + }, + onComplete: function(_) { + moveTimer.start(0.3, (timer) -> { + moveTextLeft(); + }); + }, + ease: FlxEase.sineInOut + }); + } + + function moveTextLeft():Void + { + moveTween = FlxTween.tween(whiteText.offset, {x: 0}, 2, + { + onUpdate: function(_) { + whiteText.clipRect = new FlxRect(whiteText.offset.x, 0, clipWidth, whiteText.height); + blurredText.offset = whiteText.offset; + blurredText.clipRect = new FlxRect(whiteText.offset.x, 0, clipWidth, blurredText.height); + }, + onComplete: function(_) { + moveTimer.start(0.3, (timer) -> { + moveTextRight(); + }); + }, + ease: FlxEase.sineInOut + }); + } + + public function resetText():Void + { + if (moveTween != null) moveTween.cancel(); + if (moveTimer != null) moveTimer.cancel(); + whiteText.offset.x = 0; + whiteText.clipRect = new FlxRect(whiteText.offset.x, 0, clipWidth, whiteText.height); + blurredText.clipRect = new FlxRect(whiteText.offset.x, 0, clipWidth, whiteText.height); + } + + var flickerState:Bool = false; + var flickerTimer:FlxTimer; + + public function flickerText():Void + { + resetText(); + flickerTimer = new FlxTimer().start(1 / 24, flickerProgress, 19); + } + + function flickerProgress(timer:FlxTimer):Void + { + if (flickerState == true) + { + whiteText.blend = BlendMode.ADD; + blurredText.blend = BlendMode.ADD; + blurredText.color = 0xFFFFFFFF; + whiteText.color = 0xFFFFFFFF; + whiteText.textField.filters = [ + new openfl.filters.GlowFilter(0xFFFFFF, 1, 5, 5, 210, BitmapFilterQuality.MEDIUM), + // new openfl.filters.BlurFilter(5, 5, BitmapFilterQuality.LOW) + ]; + } + else + { + blurredText.color = 0xFF00aadd; + whiteText.color = 0xFFDDDDDD; + whiteText.textField.filters = [ + new openfl.filters.GlowFilter(0xDDDDDD, 1, 5, 5, 210, BitmapFilterQuality.MEDIUM), + // new openfl.filters.BlurFilter(5, 5, BitmapFilterQuality.LOW) + ]; + } + flickerState = !flickerState; + } + + override function update(elapsed:Float):Void + { + super.update(elapsed); + } } diff --git a/source/funkin/ui/freeplay/DJBoyfriend.hx b/source/funkin/ui/freeplay/DJBoyfriend.hx index 5f1144fabe..248526aaf6 100644 --- a/source/funkin/ui/freeplay/DJBoyfriend.hx +++ b/source/funkin/ui/freeplay/DJBoyfriend.hx @@ -82,6 +82,8 @@ class DJBoyfriend extends FlxAtlasSprite return anims; } + var lowPumpLoopPoint:Int = 4; + public override function update(elapsed:Float):Void { super.update(elapsed); @@ -114,6 +116,14 @@ class DJBoyfriend extends FlxAtlasSprite case Confirm: if (getCurrentAnimation() != 'Boyfriend DJ confirm') playFlashAnimation('Boyfriend DJ confirm', false); timeSinceSpook = 0; + case PumpIntro: + if (getCurrentAnimation() != 'Boyfriend DJ fist pump') playFlashAnimation('Boyfriend DJ fist pump', false); + if (getCurrentAnimation() == 'Boyfriend DJ fist pump' && anim.curFrame >= 4) + { + anim.play("Boyfriend DJ fist pump", true, false, 0); + } + case FistPump: + case Spook: if (getCurrentAnimation() != 'bf dj afk') { @@ -174,6 +184,12 @@ class DJBoyfriend extends FlxAtlasSprite currentState = Idle; case "Boyfriend DJ confirm": + case "Boyfriend DJ fist pump": + currentState = Idle; + + case "Boyfriend DJ loss reaction 1": + currentState = Idle; + case "Boyfriend DJ watchin tv OG": var frame:Int = FlxG.random.bool(33) ? 112 : 166; @@ -275,6 +291,23 @@ class DJBoyfriend extends FlxAtlasSprite currentState = Confirm; } + public function fistPump():Void + { + currentState = PumpIntro; + } + + public function pumpFist():Void + { + currentState = FistPump; + anim.play("Boyfriend DJ fist pump", true, false, 4); + } + + public function pumpFistBad():Void + { + currentState = FistPump; + anim.play("Boyfriend DJ loss reaction 1", true, false, 4); + } + public inline function addOffset(name:String, x:Float = 0, y:Float = 0) { animOffsets[name] = [x, y]; @@ -331,6 +364,8 @@ enum DJBoyfriendState Intro; Idle; Confirm; + PumpIntro; + FistPump; Spook; TV; } diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 7b7543845a..a665f07565 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1,5 +1,6 @@ package funkin.ui.freeplay; +import funkin.graphics.adobeanimate.FlxAtlasSprite; import flixel.addons.transition.FlxTransitionableState; import flixel.addons.ui.FlxInputText; import flixel.FlxCamera; @@ -10,6 +11,7 @@ import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup; import flixel.input.touch.FlxTouch; import flixel.math.FlxAngle; import flixel.math.FlxPoint; +import openfl.display.BlendMode; import flixel.system.debug.watch.Tracker.TrackerProfile; import flixel.text.FlxText; import flixel.tweens.FlxEase; @@ -38,6 +40,8 @@ import funkin.ui.transition.LoadingState; import funkin.ui.transition.StickerSubState; import funkin.util.MathUtil; import lime.utils.Assets; +import flixel.tweens.misc.ShakeTween; +import funkin.effects.IntervalShake; /** * Parameters used to initialize the FreeplayState. @@ -135,6 +139,29 @@ class FreeplayState extends MusicBeatSubState public static var rememberedDifficulty:Null = Constants.DEFAULT_DIFFICULTY; public static var rememberedSongId:Null = 'tutorial'; + var funnyCam:FunkinCamera; + var rankCamera:FunkinCamera; + var rankBg:FunkinSprite; + var rankVignette:FlxSprite; + + var backingTextYeah:FlxAtlasSprite; + var orangeBackShit:FunkinSprite; + var alsoOrangeLOL:FunkinSprite; + var pinkBack:FunkinSprite; + var confirmGlow:FlxSprite; + var confirmGlow2:FlxSprite; + var confirmTextGlow:FlxSprite; + + var moreWays:BGScrollingText; + var funnyScroll:BGScrollingText; + var txtNuts:BGScrollingText; + var funnyScroll2:BGScrollingText; + var moreWays2:BGScrollingText; + var funnyScroll3:BGScrollingText; + + var bgDad:FlxSprite; + var cardGlow:FlxSprite; + public function new(?params:FreeplayStateParams, ?stickers:StickerSubState) { currentCharacter = params?.character ?? Constants.DEFAULT_CHARACTER; @@ -216,17 +243,17 @@ class FreeplayState extends MusicBeatSubState trace(FlxG.camera.initialZoom); trace(FlxCamera.defaultZoom); - var pinkBack:FunkinSprite = FunkinSprite.create('freeplay/pinkBack'); + pinkBack = FunkinSprite.create('freeplay/pinkBack'); pinkBack.color = 0xFFFFD4E9; // sets it to pink! pinkBack.x -= pinkBack.width; FlxTween.tween(pinkBack, {x: 0}, 0.6, {ease: FlxEase.quartOut}); add(pinkBack); - var orangeBackShit:FunkinSprite = new FunkinSprite(84, 440).makeSolidColor(Std.int(pinkBack.width), 75, 0xFFFEDA00); + orangeBackShit = new FunkinSprite(84, 440).makeSolidColor(Std.int(pinkBack.width), 75, 0xFFFEDA00); add(orangeBackShit); - var alsoOrangeLOL:FunkinSprite = new FunkinSprite(0, orangeBackShit.y).makeSolidColor(100, Std.int(orangeBackShit.height), 0xFFFFD400); + alsoOrangeLOL = new FunkinSprite(0, orangeBackShit.y).makeSolidColor(100, Std.int(orangeBackShit.height), 0xFFFFD400); add(alsoOrangeLOL); exitMovers.set([pinkBack, orangeBackShit, alsoOrangeLOL], @@ -241,13 +268,30 @@ class FreeplayState extends MusicBeatSubState orangeBackShit.visible = false; alsoOrangeLOL.visible = false; + confirmTextGlow = new FlxSprite(-8, 115).loadGraphic(Paths.image('freeplay/glowingText')); + confirmTextGlow.blend = BlendMode.ADD; + confirmTextGlow.visible = false; + + confirmGlow = new FlxSprite(-30, 240).loadGraphic(Paths.image('freeplay/confirmGlow')); + confirmGlow.blend = BlendMode.ADD; + + confirmGlow2 = new FlxSprite(confirmGlow.x, confirmGlow.y).loadGraphic(Paths.image('freeplay/confirmGlow2')); + + confirmGlow.visible = false; + confirmGlow2.visible = false; + + add(confirmGlow2); + add(confirmGlow); + + add(confirmTextGlow); + var grpTxtScrolls:FlxGroup = new FlxGroup(); add(grpTxtScrolls); grpTxtScrolls.visible = false; FlxG.debugger.addTrackerProfile(new TrackerProfile(BGScrollingText, ['x', 'y', 'speed', 'size'])); - var moreWays:BGScrollingText = new BGScrollingText(0, 160, 'HOT BLOODED IN MORE WAYS THAN ONE', FlxG.width, true, 43); + moreWays = new BGScrollingText(0, 160, 'HOT BLOODED IN MORE WAYS THAN ONE', FlxG.width, true, 43); moreWays.funnyColor = 0xFFFFF383; moreWays.speed = 6.8; grpTxtScrolls.add(moreWays); @@ -258,7 +302,7 @@ class FreeplayState extends MusicBeatSubState speed: 0.4, }); - var funnyScroll:BGScrollingText = new BGScrollingText(0, 220, 'BOYFRIEND', FlxG.width / 2, false, 60); + funnyScroll = new BGScrollingText(0, 220, 'BOYFRIEND', FlxG.width / 2, false, 60); funnyScroll.funnyColor = 0xFFFF9963; funnyScroll.speed = -3.8; grpTxtScrolls.add(funnyScroll); @@ -271,7 +315,7 @@ class FreeplayState extends MusicBeatSubState wait: 0 }); - var txtNuts:BGScrollingText = new BGScrollingText(0, 285, 'PROTECT YO NUTS', FlxG.width / 2, true, 43); + txtNuts = new BGScrollingText(0, 285, 'PROTECT YO NUTS', FlxG.width / 2, true, 43); txtNuts.speed = 3.5; grpTxtScrolls.add(txtNuts); exitMovers.set([txtNuts], @@ -280,7 +324,7 @@ class FreeplayState extends MusicBeatSubState speed: 0.4, }); - var funnyScroll2:BGScrollingText = new BGScrollingText(0, 335, 'BOYFRIEND', FlxG.width / 2, false, 60); + funnyScroll2 = new BGScrollingText(0, 335, 'BOYFRIEND', FlxG.width / 2, false, 60); funnyScroll2.funnyColor = 0xFFFF9963; funnyScroll2.speed = -3.8; grpTxtScrolls.add(funnyScroll2); @@ -291,7 +335,7 @@ class FreeplayState extends MusicBeatSubState speed: 0.5, }); - var moreWays2:BGScrollingText = new BGScrollingText(0, 397, 'HOT BLOODED IN MORE WAYS THAN ONE', FlxG.width, true, 43); + moreWays2 = new BGScrollingText(0, 397, 'HOT BLOODED IN MORE WAYS THAN ONE', FlxG.width, true, 43); moreWays2.funnyColor = 0xFFFFF383; moreWays2.speed = 6.8; grpTxtScrolls.add(moreWays2); @@ -302,7 +346,7 @@ class FreeplayState extends MusicBeatSubState speed: 0.4 }); - var funnyScroll3:BGScrollingText = new BGScrollingText(0, orangeBackShit.y + 10, 'BOYFRIEND', FlxG.width / 2, 60); + funnyScroll3 = new BGScrollingText(0, orangeBackShit.y + 10, 'BOYFRIEND', FlxG.width / 2, 60); funnyScroll3.funnyColor = 0xFFFEA400; funnyScroll3.speed = -3.8; grpTxtScrolls.add(funnyScroll3); @@ -313,6 +357,24 @@ class FreeplayState extends MusicBeatSubState speed: 0.3 }); + backingTextYeah = new FlxAtlasSprite(640, 370, Paths.animateAtlas("freeplay/backing-text-yeah"), + { + FrameRate: 24.0, + Reversed: false, + // ?OnComplete:Void -> Void, + ShowPivot: false, + Antialiasing: true, + ScrollFactor: new FlxPoint(1, 1), + }); + + add(backingTextYeah); + + cardGlow = new FlxSprite(-30, -30).loadGraphic(Paths.image('freeplay/cardGlow')); + cardGlow.blend = BlendMode.ADD; + cardGlow.visible = false; + + add(cardGlow); + dj = new DJBoyfriend(640, 366); exitMovers.set([dj], { @@ -325,7 +387,7 @@ class FreeplayState extends MusicBeatSubState add(dj); - var bgDad:FlxSprite = new FlxSprite(pinkBack.width * 0.75, 0).loadGraphic(Paths.image('freeplay/freeplayBGdad')); + bgDad = new FlxSprite(pinkBack.width * 0.75, 0).loadGraphic(Paths.image('freeplay/freeplayBGdad')); bgDad.setGraphicSize(0, FlxG.height); bgDad.updateHitbox(); bgDad.shader = new AngleMask(); @@ -342,10 +404,14 @@ class FreeplayState extends MusicBeatSubState }); add(bgDad); - FlxTween.tween(blackOverlayBullshitLOLXD, {x: pinkBack.width * 0.75}, 0.7, {ease: FlxEase.quintOut}); + FlxTween.tween(blackOverlayBullshitLOLXD, {x: pinkBack.width * 0.76}, 0.7, {ease: FlxEase.quintOut}); blackOverlayBullshitLOLXD.shader = bgDad.shader; + rankBg = new FunkinSprite(0, 0); + rankBg.makeSolidColor(FlxG.width, FlxG.height, 0xD3000000); + add(rankBg); + grpSongs = new FlxTypedGroup(); add(grpSongs); @@ -527,18 +593,35 @@ class FreeplayState extends MusicBeatSubState orangeBackShit.visible = true; alsoOrangeLOL.visible = true; grpTxtScrolls.visible = true; + + cardGlow.visible = true; + FlxTween.tween(cardGlow, {alpha: 0, "scale.x": 1.2, "scale.y": 1.2}, 0.45, {ease: FlxEase.sineOut}); }); generateSongList(null, false); // dedicated camera for the state so we don't need to fuk around with camera scrolls from the mainmenu / elsewhere - var funnyCam:FunkinCamera = new FunkinCamera('freeplayFunny', 0, 0, FlxG.width, FlxG.height); + funnyCam = new FunkinCamera('freeplayFunny', 0, 0, FlxG.width, FlxG.height); funnyCam.bgColor = FlxColor.TRANSPARENT; FlxG.cameras.add(funnyCam, false); + rankVignette = new FlxSprite(0, 0).loadGraphic(Paths.image('freeplay/rankVignette')); + rankVignette.scale.set(2, 2); + rankVignette.updateHitbox(); + rankVignette.blend = BlendMode.ADD; + // rankVignette.cameras = [rankCamera]; + add(rankVignette); + rankVignette.alpha = 0; + forEach(function(bs) { bs.cameras = [funnyCam]; }); + + rankCamera = new FunkinCamera('rankCamera', 0, 0, FlxG.width, FlxG.height); + rankCamera.bgColor = FlxColor.TRANSPARENT; + FlxG.cameras.add(rankCamera, false); + rankBg.cameras = [rankCamera]; + rankBg.alpha = 0; } var currentFilter:SongFilter = null; @@ -585,6 +668,7 @@ class FreeplayState extends MusicBeatSubState for (cap in grpCapsules.members) { + cap.songText.resetText(); cap.kill(); } @@ -602,9 +686,11 @@ class FreeplayState extends MusicBeatSubState }; randomCapsule.y = randomCapsule.intendedY(0) + 10; randomCapsule.targetPos.x = randomCapsule.x; - randomCapsule.alpha = 0.5; + randomCapsule.alpha = 0; randomCapsule.songText.visible = false; randomCapsule.favIcon.visible = false; + randomCapsule.ranking.visible = false; + randomCapsule.blurredRanking.visible = false; randomCapsule.initJumpIn(0, force); randomCapsule.hsvShader = hsvShader; grpCapsules.add(randomCapsule); @@ -627,8 +713,12 @@ class FreeplayState extends MusicBeatSubState funnyMenu.favIcon.visible = tempSongs[i].isFav; funnyMenu.hsvShader = hsvShader; + funnyMenu.newText.animation.curAnim.curFrame = 45 - ((i * 4) % 45); + funnyMenu.forcePosition(); + funnyMenu.checkClip(); + grpCapsules.add(funnyMenu); } @@ -682,6 +772,210 @@ class FreeplayState extends MusicBeatSubState return songsToFilter; } + function rankAnimStart() + { + dj.fistPump(); + // rankCamera.fade(FlxColor.BLACK, 0.5, true); + rankCamera.fade(0xFF000000, 0.5, true, null, true); + FlxG.sound.music.volume = 0; + rankBg.alpha = 1; + + originalPos.x = grpCapsules.members[curSelected].x; + originalPos.y = grpCapsules.members[curSelected].y; + + grpCapsules.members[curSelected].ranking.alpha = 0; + grpCapsules.members[curSelected].blurredRanking.alpha = 0; + + rankCamera.zoom = 1.85; + FlxTween.tween(rankCamera, {"zoom": 1.8}, 0.6, {ease: FlxEase.sineIn}); + + funnyCam.zoom = 1.15; + FlxTween.tween(funnyCam, {"zoom": 1.1}, 0.6, {ease: FlxEase.sineIn}); + + grpCapsules.members[curSelected].cameras = [rankCamera]; + grpCapsules.members[curSelected].targetPos.set((FlxG.width / 2) - (grpCapsules.members[curSelected].width / 2), + (FlxG.height / 2) - (grpCapsules.members[curSelected].height / 2)); + + new FlxTimer().start(0.5, _ -> { + grpCapsules.members[curSelected].doLerp = false; + rankDisplayNew(); + }); + } + + function rankDisplayNew() + { + grpCapsules.members[curSelected].ranking.alpha = 1; + grpCapsules.members[curSelected].blurredRanking.alpha = 1; + + grpCapsules.members[curSelected].ranking.scale.set(20, 20); + grpCapsules.members[curSelected].blurredRanking.scale.set(20, 20); + // var tempr:Int = FlxG.random.int(0, 4); + + // grpCapsules.members[curSelected].ranking.rank = tempr; + grpCapsules.members[curSelected].ranking.animation.play(grpCapsules.members[curSelected].ranking.animation.curAnim.name, true); + FlxTween.tween(grpCapsules.members[curSelected].ranking, {"scale.x": 1, "scale.y": 1}, 0.1); + + grpCapsules.members[curSelected].blurredRanking.animation.play(grpCapsules.members[curSelected].blurredRanking.animation.curAnim.name, true); + FlxTween.tween(grpCapsules.members[curSelected].blurredRanking, {"scale.x": 1, "scale.y": 1}, 0.1); + + new FlxTimer().start(0.1, _ -> { + trace(grpCapsules.members[curSelected].ranking.rank); + switch (grpCapsules.members[curSelected].tempr) + { + case 0: + FunkinSound.playOnce(Paths.sound('ranks/rankinbad')); + case 4: + FunkinSound.playOnce(Paths.sound('ranks/rankinperfect')); + case 5: + FunkinSound.playOnce(Paths.sound('ranks/rankinperfect')); + default: + FunkinSound.playOnce(Paths.sound('ranks/rankinnormal')); + } + rankCamera.zoom = 1.3; + // FlxTween.tween(rankCamera, {"zoom": 1.4}, 0.3, {ease: FlxEase.elasticOut}); + + FlxTween.tween(rankCamera, {"zoom": 1.5}, 0.3, {ease: FlxEase.backInOut}); + + grpCapsules.members[curSelected].x -= 10; + grpCapsules.members[curSelected].y -= 20; + + FlxTween.tween(funnyCam, {"zoom": 1.05}, 0.3, {ease: FlxEase.elasticOut}); + + grpCapsules.members[curSelected].capsule.angle = -3; + FlxTween.tween(grpCapsules.members[curSelected].capsule, {angle: 0}, 0.5, {ease: FlxEase.backOut}); + + IntervalShake.shake(grpCapsules.members[curSelected].capsule, 0.3, 1 / 30, 0.1, 0, FlxEase.quadOut); + }); + + new FlxTimer().start(0.4, _ -> { + FlxTween.tween(funnyCam, {"zoom": 1}, 0.8, {ease: FlxEase.sineIn}); + FlxTween.tween(rankCamera, {"zoom": 1.2}, 0.8, {ease: FlxEase.backIn}); + // IntervalShake.shake(grpCapsules.members[curSelected], 0.8 + 0.5, 1 / 24, 0, 2, FlxEase.quadIn); + FlxTween.tween(grpCapsules.members[curSelected], {x: originalPos.x - 7, y: originalPos.y - 80}, 0.8 + 0.5, {ease: FlxEase.quartIn}); + }); + + new FlxTimer().start(0.6, _ -> { + rankAnimSlam(); + // IntervalShake.shake(grpCapsules.members[curSelected].capsule, 0.3, 1 / 30, 0, 0.3, FlxEase.quartIn); + }); + } + + function rankAnimSlam() + { + // FlxTween.tween(rankCamera, {"zoom": 1.9}, 0.5, {ease: FlxEase.backOut}); + FlxTween.tween(rankBg, {alpha: 0}, 0.5, {ease: FlxEase.expoIn}); + + // FlxTween.tween(grpCapsules.members[curSelected], {angle: 5}, 0.5, {ease: FlxEase.backIn}); + + switch (grpCapsules.members[curSelected].tempr) + { + case 0: + FunkinSound.playOnce(Paths.sound('ranks/loss')); + case 1: + FunkinSound.playOnce(Paths.sound('ranks/good')); + case 2: + FunkinSound.playOnce(Paths.sound('ranks/great')); + case 3: + FunkinSound.playOnce(Paths.sound('ranks/excellent')); + case 4: + FunkinSound.playOnce(Paths.sound('ranks/perfect')); + case 5: + FunkinSound.playOnce(Paths.sound('ranks/perfect')); + default: + FunkinSound.playOnce(Paths.sound('ranks/loss')); + } + + FlxTween.tween(grpCapsules.members[curSelected], {"targetPos.x": originalPos.x, "targetPos.y": originalPos.y}, 0.5, {ease: FlxEase.expoOut}); + new FlxTimer().start(0.5, _ -> { + funnyCam.shake(0.0045, 0.35); + + if (grpCapsules.members[curSelected].tempr == 0) + { + dj.pumpFistBad(); + } + else + { + dj.pumpFist(); + } + + rankCamera.zoom = 0.8; + funnyCam.zoom = 0.8; + FlxTween.tween(rankCamera, {"zoom": 1}, 1, {ease: FlxEase.elasticOut}); + FlxTween.tween(funnyCam, {"zoom": 1}, 0.8, {ease: FlxEase.elasticOut}); + + for (index => capsule in grpCapsules.members) + { + var distFromSelected:Float = Math.abs(index - curSelected) - 1; + + if (distFromSelected < 5) + { + if (index == curSelected) + { + FlxTween.cancelTweensOf(capsule); + // capsule.targetPos.x += 50; + capsule.fadeAnim(); + + rankVignette.color = capsule.getTrailColor(); + rankVignette.alpha = 1; + FlxTween.tween(rankVignette, {alpha: 0}, 0.6, {ease: FlxEase.expoOut}); + + capsule.doLerp = false; + capsule.setPosition(originalPos.x, originalPos.y); + IntervalShake.shake(capsule, 0.6, 1 / 24, 0.12, 0, FlxEase.quadOut, function(_) { + capsule.doLerp = true; + capsule.cameras = [funnyCam]; + }, null); + + // FlxTween.tween(capsule, {"targetPos.x": capsule.targetPos.x - 50}, 0.6, + // { + // ease: FlxEase.backInOut, + // onComplete: function(_) { + // capsule.cameras = [funnyCam]; + // } + // }); + FlxTween.tween(capsule, {angle: 0}, 0.5, {ease: FlxEase.backOut}); + } + if (index > curSelected) + { + // capsule.color = FlxColor.RED; + new FlxTimer().start(distFromSelected / 20, _ -> { + capsule.doLerp = false; + + capsule.capsule.angle = FlxG.random.float(-10 + (distFromSelected * 2), 10 - (distFromSelected * 2)); + FlxTween.tween(capsule.capsule, {angle: 0}, 0.5, {ease: FlxEase.backOut}); + + IntervalShake.shake(capsule, 0.6, 1 / 24, 0.12 / (distFromSelected + 1), 0, FlxEase.quadOut, function(_) { + capsule.doLerp = true; + }); + }); + } + + if (index < curSelected) + { + // capsule.color = FlxColor.BLUE; + new FlxTimer().start(distFromSelected / 20, _ -> { + capsule.doLerp = false; + + capsule.capsule.angle = FlxG.random.float(-10 + (distFromSelected * 2), 10 - (distFromSelected * 2)); + FlxTween.tween(capsule.capsule, {angle: 0}, 0.5, {ease: FlxEase.backOut}); + + IntervalShake.shake(capsule, 0.6, 1 / 24, 0.12 / (distFromSelected + 1), 0, FlxEase.quadOut, function(_) { + capsule.doLerp = true; + }); + }); + } + } + + index += 1; + } + }); + + new FlxTimer().start(2, _ -> { + // dj.fistPump(); + FlxG.sound.music.fadeIn(4.0, 0.0, 1.0); + }); + } + var touchY:Float = 0; var touchX:Float = 0; var dxTouch:Float = 0; @@ -698,10 +992,48 @@ class FreeplayState extends MusicBeatSubState var busy:Bool = false; // Set to true once the user has pressed enter to select a song. + var originalPos:FlxPoint = new FlxPoint(); + override function update(elapsed:Float):Void { super.update(elapsed); + if (FlxG.keys.justPressed.T) + { + rankAnimStart(); + } + + if (FlxG.keys.justPressed.H) + { + rankDisplayNew(); + } + + if (FlxG.keys.justPressed.G) + { + rankAnimSlam(); + } + + if (FlxG.keys.justPressed.I) + { + confirmTextGlow.y -= 1; + trace(confirmTextGlow.x, confirmTextGlow.y); + } + if (FlxG.keys.justPressed.J) + { + confirmTextGlow.x -= 1; + trace(confirmTextGlow.x, confirmTextGlow.y); + } + if (FlxG.keys.justPressed.L) + { + confirmTextGlow.x += 1; + trace(confirmTextGlow.x, confirmTextGlow.y); + } + if (FlxG.keys.justPressed.K) + { + confirmTextGlow.y += 1; + trace(confirmTextGlow.x, confirmTextGlow.y); + } + if (FlxG.keys.justPressed.F) { var targetSong = grpCapsules.members[curSelected]?.songData; @@ -1145,6 +1477,42 @@ class FreeplayState extends MusicBeatSubState FunkinSound.playOnce(Paths.sound('confirmMenu')); dj.confirm(); + grpCapsules.members[curSelected].songText.flickerText(); + + // FlxTween.color(bgDad, 0.33, 0xFFFFFFFF, 0xFF555555, {ease: FlxEase.quadOut}); + FlxTween.color(pinkBack, 0.33, 0xFFFFD0D5, 0xFF171831, {ease: FlxEase.quadOut}); + orangeBackShit.visible = false; + alsoOrangeLOL.visible = false; + + confirmGlow.visible = true; + confirmGlow2.visible = true; + + backingTextYeah.anim.play("BF back card confirm raw", false, false, 0); + confirmGlow2.alpha = 0; + confirmGlow.alpha = 0; + + FlxTween.tween(confirmGlow2, {alpha: 0.5}, 0.33, + { + ease: FlxEase.quadOut, + onComplete: function(_) { + confirmGlow2.alpha = 0.6; + confirmGlow.alpha = 1; + confirmTextGlow.visible = true; + confirmTextGlow.alpha = 1; + FlxTween.tween(confirmTextGlow, {alpha: 0.4}, 0.5); + FlxTween.tween(confirmGlow, {alpha: 0}, 0.5); + } + }); + + // confirmGlow + + moreWays.visible = false; + funnyScroll.visible = false; + txtNuts.visible = false; + funnyScroll2.visible = false; + moreWays2.visible = false; + funnyScroll3.visible = false; + new FlxTimer().start(1, function(tmr:FlxTimer) { Paths.setCurrentLevel(cap.songData.levelId); LoadingState.loadPlayState( @@ -1383,6 +1751,7 @@ class FreeplaySongData public var songName(default, null):String = ''; public var songCharacter(default, null):String = ''; + public var songStartingBpm(default, null):Float = 0; public var songRating(default, null):Int = 0; public var albumId(default, null):Null = null; @@ -1415,6 +1784,7 @@ class FreeplaySongData var songDifficulty:SongDifficulty = song.getDifficulty(currentDifficulty, variations); if (songDifficulty == null) return; + this.songStartingBpm = songDifficulty.getStartingBPM(); 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 f6d85e56e2..0f72199ba0 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -14,6 +14,13 @@ import flixel.text.FlxText; import flixel.util.FlxTimer; import funkin.util.MathUtil; import funkin.graphics.shaders.Grayscale; +import funkin.graphics.shaders.GaussianBlurShader; +import openfl.display.BlendMode; +import funkin.graphics.FunkinSprite; +import flixel.tweens.FlxEase; +import flixel.tweens.FlxTween; +import flixel.addons.effects.FlxTrail; +import flixel.util.FlxColor; class SongMenuItem extends FlxSpriteGroup { @@ -31,9 +38,10 @@ class SongMenuItem extends FlxSpriteGroup public var songText:CapsuleText; public var favIcon:FlxSprite; - public var ranking:FlxSprite; + public var ranking:FreeplayRank; + public var blurredRanking:FreeplayRank; - var ranks:Array = ["fail", "average", "great", "excellent", "perfect"]; + var ranks:Array = ["fail", "average", "great", "excellent", "perfect", "perfectsick"]; public var targetPos:FlxPoint = new FlxPoint(); public var doLerp:Bool = false; @@ -47,6 +55,22 @@ class SongMenuItem extends FlxSpriteGroup public var hsvShader(default, set):HSVShader; // var diffRatingSprite:FlxSprite; + public var bpmText:FlxSprite; + public var difficultyText:FlxSprite; + public var weekType:FlxSprite; + + public var newText:FlxSprite; + + // public var weekType:FlxSprite; + public var bigNumbers:Array = []; + + public var smallNumbers:Array = []; + + public var weekNumbers:Array = []; + + var impactThing:FunkinSprite; + + public var tempr:Int; public function new(x:Float, y:Float) { @@ -59,12 +83,64 @@ class SongMenuItem extends FlxSpriteGroup // capsule.animation add(capsule); + bpmText = new FlxSprite(144, 87).loadGraphic(Paths.image('freeplay/freeplayCapsule/bpmtext')); + bpmText.setGraphicSize(Std.int(bpmText.width * 0.9)); + add(bpmText); + + difficultyText = new FlxSprite(414, 87).loadGraphic(Paths.image('freeplay/freeplayCapsule/difficultytext')); + difficultyText.setGraphicSize(Std.int(difficultyText.width * 0.9)); + add(difficultyText); + + weekType = new FlxSprite(291, 87); + weekType.frames = Paths.getSparrowAtlas('freeplay/freeplayCapsule/weektypes'); + + weekType.animation.addByPrefix('WEEK', 'WEEK text instance 1', 24, false); + weekType.animation.addByPrefix('WEEKEND', 'WEEKEND text instance 1', 24, false); + + weekType.setGraphicSize(Std.int(weekType.width * 0.9)); + add(weekType); + + newText = new FlxSprite(454, 9); + newText.frames = Paths.getSparrowAtlas('freeplay/freeplayCapsule/new'); + newText.animation.addByPrefix('newAnim', 'NEW notif', 24, true); + newText.animation.play('newAnim', true); + newText.setGraphicSize(Std.int(newText.width * 0.9)); + + newText.visible = false; + + add(newText); + + // var debugNumber2:CapsuleNumber = new CapsuleNumber(0, 0, true, 2); + // add(debugNumber2); + + for (i in 0...2) + { + var bigNumber:CapsuleNumber = new CapsuleNumber(466 + (i * 30), 32, true, 0); + add(bigNumber); + + bigNumbers.push(bigNumber); + } + + for (i in 0...3) + { + var smallNumber:CapsuleNumber = new CapsuleNumber(185 + (i * 11), 88.5, false, 0); + add(smallNumber); + + smallNumbers.push(smallNumber); + } + // doesn't get added, simply is here to help with visibility of things for the pop in! grpHide = new FlxGroup(); var rank:String = FlxG.random.getObject(ranks); - ranking = new FlxSprite(capsule.width * 0.84, 30); + tempr = FlxG.random.int(0, 5); + ranking = new FreeplayRank(420, 41, tempr); + add(ranking); + + blurredRanking = new FreeplayRank(ranking.x, ranking.y, tempr); + blurredRanking.shader = new GaussianBlurShader(1); + add(blurredRanking); // ranking.loadGraphic(Paths.image('freeplay/ranks/' + rank)); // ranking.scale.x = ranking.scale.y = realScaled; // ranking.alpha = 0.75; @@ -73,11 +149,11 @@ class SongMenuItem extends FlxSpriteGroup // add(ranking); // grpHide.add(ranking); - switch (rank) - { - case 'perfect': - ranking.x -= 10; - } + // switch (rank) + // { + // case 'perfect': + // ranking.x -= 10; + // } grayscaleShader = new Grayscale(1); @@ -93,7 +169,7 @@ class SongMenuItem extends FlxSpriteGroup grpHide.add(songText); // TODO: Use value from metadata instead of random. - updateDifficultyRating(FlxG.random.int(0, 15)); + updateDifficultyRating(FlxG.random.int(0, 20)); pixelIcon = new FlxSprite(160, 35); @@ -103,21 +179,216 @@ class SongMenuItem extends FlxSpriteGroup add(pixelIcon); grpHide.add(pixelIcon); - favIcon = new FlxSprite(400, 40); + favIcon = new FlxSprite(380, 40); favIcon.frames = Paths.getSparrowAtlas('freeplay/favHeart'); favIcon.animation.addByPrefix('fav', 'favorite heart', 24, false); favIcon.animation.play('fav'); favIcon.setGraphicSize(50, 50); favIcon.visible = false; + favIcon.blend = BlendMode.ADD; add(favIcon); - // grpHide.add(favIcon); + + var weekNumber:CapsuleNumber = new CapsuleNumber(355, 88.5, false, 0); + add(weekNumber); + + weekNumbers.push(weekNumber); setVisibleGrp(false); } + // no way to grab weeks rn, so this needs to be done :/ + // negative values mean weekends + function checkWeek(name:String):Void + { + // trace(name); + var weekNum:Int = 0; + switch (name) + { + case 'bopeebo' | 'fresh' | 'dadbattle': + weekNum = 1; + case 'spookeez' | 'south' | 'monster': + weekNum = 2; + case 'pico' | 'philly-nice' | 'blammed': + weekNum = 3; + case "satin-panties" | 'high' | 'milf': + weekNum = 4; + case "cocoa" | 'eggnog' | 'winter-horrorland': + weekNum = 5; + case 'senpai' | 'roses' | 'thorns': + weekNum = 6; + case 'ugh' | 'guns' | 'stress': + weekNum = 7; + case 'darnell' | 'lit-up' | '2hot' | 'blazin': + weekNum = -1; + default: + weekNum = 0; + } + + weekNumbers[0].digit = Std.int(Math.abs(weekNum)); + + if (weekNum == 0) + { + weekType.visible = false; + weekNumbers[0].visible = false; + } + else + { + weekType.visible = true; + weekNumbers[0].visible = true; + } + if (weekNum > 0) + { + weekType.animation.play('WEEK', true); + } + else + { + weekType.animation.play('WEEKEND', true); + weekNumbers[0].offset.x -= 35; + } + } + + // 255, 27 normal + // 220, 27 favourited + public function checkClip():Void + { + var clipSize:Int = 290; + var clipType:Int = 0; + + if (ranking.visible == true) clipType += 1; + if (favIcon.visible == true) clipType += 1; + switch (clipType) + { + case 2: + clipSize = 220; + case 1: + clipSize = 255; + } + songText.clipWidth = clipSize; + } + + function updateBPM(newBPM:Int):Void + { + trace(newBPM); + + var shiftX:Float = 191; + var tempShift:Float = 0; + + if (Math.floor(newBPM / 100) == 1) + { + shiftX = 186; + } + + for (i in 0...smallNumbers.length) + { + smallNumbers[i].x = this.x + (shiftX + (i * 11)); + switch (i) + { + case 0: + if (newBPM < 100) + { + smallNumbers[i].digit = 0; + } + else + { + smallNumbers[i].digit = Math.floor(newBPM / 100) % 10; + } + + case 1: + if (newBPM < 10) + { + smallNumbers[i].digit = 0; + } + else + { + smallNumbers[i].digit = Math.floor(newBPM / 10) % 10; + + if (Math.floor(newBPM / 10) % 10 == 1) tempShift = -4; + } + case 2: + smallNumbers[i].digit = newBPM % 10; + default: + trace('why the fuck is this being called'); + } + smallNumbers[i].x += tempShift; + } + // diffRatingSprite.loadGraphic(Paths.image('freeplay/diffRatings/diff${ratingPadded}')); + // diffRatingSprite.visible = false; + } + + var evilTrail:FlxTrail; + + public function fadeAnim() + { + impactThing = new FunkinSprite(0, 0); + impactThing.frames = capsule.frames; + impactThing.frame = capsule.frame; + impactThing.updateHitbox(); + // impactThing.x = capsule.x; + // impactThing.y = capsule.y; + // picoFade.stamp(this, 0, 0); + impactThing.alpha = 0; + impactThing.zIndex = capsule.zIndex - 3; + add(impactThing); + FlxTween.tween(impactThing.scale, {x: 2.5, y: 2.5}, 0.5); + // FlxTween.tween(impactThing, {alpha: 0}, 0.5); + + evilTrail = new FlxTrail(impactThing, null, 15, 2, 0.01, 0.069); + evilTrail.blend = BlendMode.ADD; + evilTrail.zIndex = capsule.zIndex - 5; + FlxTween.tween(evilTrail, {alpha: 0}, 0.6, + { + ease: FlxEase.quadOut, + onComplete: function(_) { + remove(evilTrail); + } + }); + add(evilTrail); + + switch (tempr) + { + case 0: + evilTrail.color = 0xFF6044FF; + case 1: + evilTrail.color = 0xFFEF8764; + case 2: + evilTrail.color = 0xFFEAF6FF; + case 3: + evilTrail.color = 0xFFFDCB42; + case 4: + evilTrail.color = 0xFFFF58B4; + case 5: + evilTrail.color = 0xFFFFB619; + } + } + + public function getTrailColor():FlxColor + { + return evilTrail.color; + } + function updateDifficultyRating(newRating:Int):Void { var ratingPadded:String = newRating < 10 ? '0$newRating' : '$newRating'; + + for (i in 0...bigNumbers.length) + { + switch (i) + { + case 0: + if (newRating > 10) + { + bigNumbers[i].digit = 0; + } + else + { + bigNumbers[i].digit = Math.floor(newRating / 10); + } + case 1: + bigNumbers[i].digit = newRating % 10; + default: + trace('why the fuck is this being called'); + } + } // diffRatingSprite.loadGraphic(Paths.image('freeplay/diffRatings/diff${ratingPadded}')); // diffRatingSprite.visible = false; } @@ -169,8 +440,11 @@ class SongMenuItem extends FlxSpriteGroup // Update capsule character. if (songData?.songCharacter != null) setCharacter(songData.songCharacter); updateDifficultyRating(songData?.songRating ?? 0); + updateBPM(Std.int(songData?.songStartingBpm) ?? 0); // Update opacity, offsets, etc. updateSelected(); + + checkWeek(songData?.songId); } /** @@ -289,6 +563,28 @@ class SongMenuItem extends FlxSpriteGroup override function update(elapsed:Float):Void { + if (impactThing != null) impactThing.angle = capsule.angle; + + // if (FlxG.keys.justPressed.I) + // { + // newText.y -= 1; + // trace(this.x - newText.x, this.y - newText.y); + // } + // if (FlxG.keys.justPressed.J) + // { + // newText.x -= 1; + // trace(this.x - newText.x, this.y - newText.y); + // } + // if (FlxG.keys.justPressed.L) + // { + // newText.x += 1; + // trace(this.x - newText.x, this.y - newText.y); + // } + // if (FlxG.keys.justPressed.K) + // { + // newText.y += 1; + // trace(this.x - newText.x, this.y - newText.y); + // } if (doJumpIn) { frameInTicker += elapsed; @@ -358,5 +654,137 @@ class SongMenuItem extends FlxSpriteGroup capsule.animation.play(this.selected ? "selected" : "unselected"); ranking.alpha = this.selected ? 1 : 0.7; ranking.color = this.selected ? 0xFFFFFFFF : 0xFFAAAAAA; + + if (selected) + { + if (songText.tooLong == true) songText.initMove(); + } + else + { + if (songText.tooLong == true) songText.resetText(); + } + } +} + +class FreeplayRank extends FlxSprite +{ + public var rank(default, set):Int = 0; + + var numToRank:Array = ["LOSS", "GOOD", "GREAT", "EXCELLENT", "PERFECT", "PERFECTSICK"]; + + function set_rank(val):Int + { + animation.play(numToRank[val], true, false); + + centerOffsets(false); + + switch (val) + { + case 0: + // offset.x -= 1; + case 1: + // offset.x -= 1; + offset.y -= 8; + case 2: + // offset.x -= 1; + offset.y -= 8; + case 3: + // offset.y += 5; + case 4: + // offset.y += 5; + default: + centerOffsets(false); + } + updateHitbox(); + return val; + } + + public var baseY:Float = 0; + public var baseX:Float = 0; + + public function new(x:Float, y:Float, ?initRank:Int = 0) + { + super(x, y); + + frames = Paths.getSparrowAtlas('freeplay/rankbadges'); + + animation.addByPrefix('PERFECT', 'PERFECT rank0', 24, false); + animation.addByPrefix('EXCELLENT', 'EXCELLENT rank0', 24, false); + animation.addByPrefix('GOOD', 'GOOD rank0', 24, false); + animation.addByPrefix('PERFECTSICK', 'PERFECT rank GOLD', 24, false); + animation.addByPrefix('GREAT', 'GREAT rank0', 24, false); + animation.addByPrefix('LOSS', 'LOSS rank0', 24, false); + + blend = BlendMode.ADD; + + this.rank = initRank; + + animation.play(numToRank[initRank], true); + + // setGraphicSize(Std.int(width * 0.9)); + scale.set(0.9, 0.9); + updateHitbox(); + } +} + +class CapsuleNumber extends FlxSprite +{ + public var digit(default, set):Int = 0; + + function set_digit(val):Int + { + animation.play(numToString[val], true, false, 0); + + centerOffsets(false); + + switch (val) + { + case 1: + offset.x -= 4; + case 3: + offset.x -= 1; + + case 6: + + case 4: + // offset.y += 5; + case 9: + // offset.y += 5; + default: + centerOffsets(false); + } + return val; + } + + public var baseY:Float = 0; + public var baseX:Float = 0; + + var numToString:Array = ["ZERO", "ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE"]; + + public function new(x:Float, y:Float, big:Bool = false, ?initDigit:Int = 0) + { + super(x, y); + + if (big) + { + frames = Paths.getSparrowAtlas('freeplay/freeplayCapsule/bignumbers'); + } + else + { + frames = Paths.getSparrowAtlas('freeplay/freeplayCapsule/smallnumbers'); + } + + for (i in 0...10) + { + var stringNum:String = numToString[i]; + animation.addByPrefix(stringNum, '$stringNum', 24, false); + } + + this.digit = initDigit; + + animation.play(numToString[initDigit], true); + + setGraphicSize(Std.int(width * 0.9)); + updateHitbox(); } } From 5f9019a2a3f9283fa96684b91ce17cd8e1ff5b23 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Thu, 30 May 2024 04:35:05 +0100 Subject: [PATCH 126/216] update assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index fe52d20de7..dabdf9b1d3 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit fe52d20de7025d90cadb429dbdedf6d986727088 +Subproject commit dabdf9b1d361afa0f65c87b9c0f12cf90b0eebdf From b7a828e7d89756a20c7415876446ddda2c1cbd84 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 30 May 2024 05:25:51 -0400 Subject: [PATCH 127/216] Make Freeplay use correct ranks, play the slam animation after Results, new Results music --- assets | 2 +- source/funkin/InitState.hx | 4 +- source/funkin/play/PlayState.hx | 3 +- source/funkin/play/ResultState.hx | 226 ++++++--------------- source/funkin/play/scoring/Scoring.hx | 176 ++++++++++++++++ source/funkin/save/Save.hx | 13 +- source/funkin/ui/freeplay/FreeplayState.hx | 107 +++++++--- source/funkin/ui/freeplay/SongMenuItem.hx | 97 +++++---- 8 files changed, 388 insertions(+), 240 deletions(-) diff --git a/assets b/assets index 8fea0bf1fe..2719d3fc1d 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 8fea0bf1fe07b6dd0efb8ecf46dc8091b0177007 +Subproject commit 2719d3fc1d8f5d0cbafae8d27141d6c471148482 diff --git a/source/funkin/InitState.hx b/source/funkin/InitState.hx index a945c10c54..d0009f95b7 100644 --- a/source/funkin/InitState.hx +++ b/source/funkin/InitState.hx @@ -220,6 +220,8 @@ class InitState extends FlxState { storyMode: false, title: "CUM SONG", + songId: "cum", + difficultyId: "hard", isNewHighscore: true, scoreData: { @@ -227,7 +229,7 @@ class InitState extends FlxState tallies: { sick: 130, - good: 25, + good: 70, bad: 69, shit: 69, missed: 69, diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index a95166e219..e69a50b00d 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -3123,9 +3123,10 @@ class PlayState extends MusicBeatSubState var res:ResultState = new ResultState( { storyMode: PlayStatePlaylist.isStoryMode, + songId: currentChart.song.id, + difficultyId: currentDifficulty, title: PlayStatePlaylist.isStoryMode ? ('${PlayStatePlaylist.campaignTitle}') : ('${currentChart.songName} by ${currentChart.songArtist}'), prevScoreData: prevScoreData, - difficultyId: currentDifficulty, scoreData: { score: PlayStatePlaylist.isStoryMode ? PlayStatePlaylist.campaignScore : songScore, diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index ee7c8eade5..79880038df 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -21,6 +21,7 @@ import funkin.audio.FunkinSound; import flixel.util.FlxGradient; import flixel.util.FlxTimer; import funkin.save.Save; +import funkin.play.scoring.Scoring; import funkin.save.Save.SaveScoreData; import funkin.graphics.shaders.LeftMaskShader; import funkin.play.components.TallyCounter; @@ -34,7 +35,7 @@ class ResultState extends MusicBeatSubState { final params:ResultsStateParams; - final rank:ResultRank; + final rank:ScoringRank; final songName:FlxBitmapText; final difficulty:FlxSprite; final clearPercentSmall:ClearPercentCounter; @@ -64,8 +65,7 @@ class ResultState extends MusicBeatSubState this.params = params; - rank = calculateRank(params); - // rank = SHIT; + rank = Scoring.calculateRank(params.scoreData) ?? SHIT; // We build a lot of this stuff in the constructor, then place it in create(). // This prevents having to do `null` checks everywhere. @@ -99,6 +99,8 @@ class ResultState extends MusicBeatSubState override function create():Void { + if (FlxG.sound.music != null) FlxG.sound.music.stop(); + // Reset the camera zoom on the results screen. FlxG.camera.zoom = 1.0; @@ -327,6 +329,33 @@ class ResultState extends MusicBeatSubState } }; + new FlxTimer().start(rank.getMusicDelay(), _ -> { + if (rank.hasMusicIntro()) + { + // Play the intro music. + var introMusic:String = Paths.music(rank.getMusicPath() + '/' + rank.getMusicPath() + '-intro'); + FunkinSound.load(introMusic, 1.0, false, true, true, () -> { + FunkinSound.playMusic(rank.getMusicPath(), + { + startingVolume: 1.0, + overrideExisting: true, + restartTrack: true, + loop: rank.shouldMusicLoop() + }); + }); + } + else + { + FunkinSound.playMusic(rank.getMusicPath(), + { + startingVolume: 1.0, + overrideExisting: true, + restartTrack: true, + loop: rank.shouldMusicLoop() + }); + } + }); + refresh(); super.create(); @@ -376,7 +405,8 @@ class ResultState extends MusicBeatSubState displayRankText(); - new FlxTimer().start(2.0, _ -> { + // previously 2.0 seconds + new FlxTimer().start(0.25, _ -> { FlxTween.tween(clearPercentCounter, {alpha: 0}, 0.5, { startDelay: 0.5, @@ -444,28 +474,6 @@ class ResultState extends MusicBeatSubState { showSmallClearPercent(); - FunkinSound.playMusic(rank.getMusicPath(), - { - startingVolume: 1.0, - overrideExisting: true, - restartTrack: true, - loop: rank.shouldMusicLoop() - }); - - FlxG.sound.music.onComplete = () -> { - if (rank == SHIT) - { - FunkinSound.playMusic('bluu', - { - startingVolume: 0.0, - overrideExisting: true, - restartTrack: true, - loop: true - }); - FlxG.sound.music.fadeIn(10.0, 0.0, 1.0); - } - } - switch (rank) { case PERFECT | PERFECT_GOLD: @@ -478,7 +486,6 @@ class ResultState extends MusicBeatSubState bfPerfect.visible = true; bfPerfect.playAnimation(''); } - case EXCELLENT: if (bfExcellent == null) { @@ -489,7 +496,6 @@ class ResultState extends MusicBeatSubState bfExcellent.visible = true; bfExcellent.playAnimation('Intro'); } - case GREAT: if (bfGreat == null) { @@ -500,7 +506,6 @@ class ResultState extends MusicBeatSubState bfGreat.visible = true; bfGreat.playAnimation('Intro'); } - case SHIT: if (bfShit == null) { @@ -511,7 +516,6 @@ class ResultState extends MusicBeatSubState bfShit.visible = true; bfShit.playAnimation('Intro'); } - case GOOD: if (bfGood == null) { @@ -521,7 +525,6 @@ class ResultState extends MusicBeatSubState { bfGood.animation.play('fall'); bfGood.visible = true; - new FlxTimer().start((1 / 24) * 22, _ -> { // plays about 22 frames (at 24fps timing) after bf spawns in if (gfGood != null) @@ -635,154 +638,39 @@ class ResultState extends MusicBeatSubState if (controls.PAUSE) { - FlxTween.tween(FlxG.sound.music, {volume: 0}, 0.8); - FlxTween.tween(FlxG.sound.music, {pitch: 3}, 0.1, - { - onComplete: _ -> { - FlxTween.tween(FlxG.sound.music, {pitch: 0.5}, 0.4); - } - }); + if (FlxG.sound.music != null) + { + FlxTween.tween(FlxG.sound.music, {volume: 0}, 0.8); + FlxTween.tween(FlxG.sound.music, {pitch: 3}, 0.1, + { + onComplete: _ -> { + FlxTween.tween(FlxG.sound.music, {pitch: 0.5}, 0.4); + } + }); + } if (params.storyMode) { openSubState(new funkin.ui.transition.StickerSubState(null, (sticker) -> new StoryMenuState(sticker))); } else { - openSubState(new funkin.ui.transition.StickerSubState(null, (sticker) -> FreeplayState.build(null, sticker))); + openSubState(new funkin.ui.transition.StickerSubState(null, (sticker) -> FreeplayState.build( + { + { + fromResults: + { + oldRank: Scoring.calculateRank(params?.prevScoreData), + newRank: rank, + songId: params.songId, + difficultyId: params.difficultyId + } + } + }, sticker))); } } super.update(elapsed); } - - public static function calculateRank(params:ResultsStateParams):ResultRank - { - // Perfect (Platinum) is a Sick Full Clear - var isPerfectGold = params.scoreData.tallies.sick == params.scoreData.tallies.totalNotes; - if (isPerfectGold) return ResultRank.PERFECT_GOLD; - - // Else, use the standard grades - - // Grade % (only good and sick), 1.00 is a full combo - var grade = (params.scoreData.tallies.sick + params.scoreData.tallies.good) / params.scoreData.tallies.totalNotes; - // Clear % (including bad and shit). 1.00 is a full clear but not a full combo - var clear = (params.scoreData.tallies.totalNotesHit) / params.scoreData.tallies.totalNotes; - - if (grade == Constants.RANK_PERFECT_THRESHOLD) - { - return ResultRank.PERFECT; - } - else if (grade >= Constants.RANK_EXCELLENT_THRESHOLD) - { - return ResultRank.EXCELLENT; - } - else if (grade >= Constants.RANK_GREAT_THRESHOLD) - { - return ResultRank.GREAT; - } - else if (grade >= Constants.RANK_GOOD_THRESHOLD) - { - return ResultRank.GOOD; - } - else - { - return ResultRank.SHIT; - } - } -} - -enum abstract ResultRank(String) -{ - var PERFECT_GOLD; - var PERFECT; - var EXCELLENT; - var GREAT; - var GOOD; - var SHIT; - - public function getMusicPath():String - { - switch (abstract) - { - case PERFECT_GOLD: - return 'resultsPERFECT'; - case PERFECT: - return 'resultsPERFECT'; - case EXCELLENT: - return 'resultsNORMAL'; - case GREAT: - return 'resultsNORMAL'; - case GOOD: - return 'resultsNORMAL'; - case SHIT: - return 'resultsSHIT'; - default: - return 'resultsNORMAL'; - } - } - - public function shouldMusicLoop():Bool - { - switch (abstract) - { - case PERFECT_GOLD: - return true; - case PERFECT: - return true; - case EXCELLENT: - return true; - case GREAT: - return true; - case GOOD: - return true; - case SHIT: - return false; - default: - return false; - } - } - - public function getHorTextAsset() - { - switch (abstract) - { - case PERFECT_GOLD: - return 'resultScreen/rankText/rankScrollPERFECT'; - case PERFECT: - return 'resultScreen/rankText/rankScrollPERFECT'; - case EXCELLENT: - return 'resultScreen/rankText/rankScrollEXCELLENT'; - case GREAT: - return 'resultScreen/rankText/rankScrollGREAT'; - case GOOD: - return 'resultScreen/rankText/rankScrollGOOD'; - case SHIT: - return 'resultScreen/rankText/rankScrollLOSS'; - default: - return 'resultScreen/rankText/rankScrollGOOD'; - } - } - - public function getVerTextAsset() - { - switch (abstract) - { - case PERFECT_GOLD: - return 'resultScreen/rankText/rankTextPERFECT'; - case PERFECT: - return 'resultScreen/rankText/rankTextPERFECT'; - case EXCELLENT: - return 'resultScreen/rankText/rankTextEXCELLENT'; - case GREAT: - return 'resultScreen/rankText/rankTextGREAT'; - case GOOD: - return 'resultScreen/rankText/rankTextGOOD'; - case SHIT: - return 'resultScreen/rankText/rankTextLOSS'; - default: - return 'resultScreen/rankText/rankTextGOOD'; - } - } } typedef ResultsStateParams = @@ -797,6 +685,8 @@ typedef ResultsStateParams = */ var title:String; + var songId:String; + /** * Whether the displayed score is a new highscore */ diff --git a/source/funkin/play/scoring/Scoring.hx b/source/funkin/play/scoring/Scoring.hx index 744091b443..6155ec8798 100644 --- a/source/funkin/play/scoring/Scoring.hx +++ b/source/funkin/play/scoring/Scoring.hx @@ -1,5 +1,7 @@ package funkin.play.scoring; +import funkin.save.Save.SaveScoreData; + /** * Which system to use when scoring and judging notes. */ @@ -344,4 +346,178 @@ class Scoring return 'miss'; } } + + public static function calculateRank(scoreData:Null):Null + { + if (scoreData == null) return null; + + // Perfect (Platinum) is a Sick Full Clear + var isPerfectGold = scoreData.tallies.sick == scoreData.tallies.totalNotes; + if (isPerfectGold) return ScoringRank.PERFECT_GOLD; + + // Else, use the standard grades + + // Grade % (only good and sick), 1.00 is a full combo + var grade = (scoreData.tallies.sick + scoreData.tallies.good) / scoreData.tallies.totalNotes; + // Clear % (including bad and shit). 1.00 is a full clear but not a full combo + var clear = (scoreData.tallies.totalNotesHit) / scoreData.tallies.totalNotes; + + if (grade == Constants.RANK_PERFECT_THRESHOLD) + { + return ScoringRank.PERFECT; + } + else if (grade >= Constants.RANK_EXCELLENT_THRESHOLD) + { + return ScoringRank.EXCELLENT; + } + else if (grade >= Constants.RANK_GREAT_THRESHOLD) + { + return ScoringRank.GREAT; + } + else if (grade >= Constants.RANK_GOOD_THRESHOLD) + { + return ScoringRank.GOOD; + } + else + { + return ScoringRank.SHIT; + } + } +} + +enum abstract ScoringRank(String) +{ + var PERFECT_GOLD; + var PERFECT; + var EXCELLENT; + var GREAT; + var GOOD; + var SHIT; + + /** + * Delay in seconds + */ + public function getMusicDelay():Float + { + switch (abstract) + { + case PERFECT_GOLD | PERFECT: + // return 2.5; + return 5.0; + case EXCELLENT: + return 1.75; + default: + return 3.5; + } + } + + public function getMusicPath():String + { + switch (abstract) + { + case PERFECT_GOLD: + return 'resultsPERFECT'; + case PERFECT: + return 'resultsPERFECT'; + case EXCELLENT: + return 'resultsEXCELLENT'; + case GREAT: + return 'resultsNORMAL'; + case GOOD: + return 'resultsNORMAL'; + case SHIT: + return 'resultsSHIT'; + default: + return 'resultsNORMAL'; + } + } + + public function hasMusicIntro():Bool + { + switch (abstract) + { + case EXCELLENT: + return true; + case SHIT: + return true; + default: + return false; + } + } + + public function getFreeplayRankIconAsset():Null + { + switch (abstract) + { + case PERFECT_GOLD: + return 'PERFECTSICK'; + case PERFECT: + return 'PERFECT'; + case EXCELLENT: + return 'EXCELLENT'; + case GREAT: + return 'GREAT'; + case GOOD: + return 'GOOD'; + case SHIT: + return 'LOSS'; + default: + return null; + } + } + + public function shouldMusicLoop():Bool + { + switch (abstract) + { + case PERFECT_GOLD | PERFECT | EXCELLENT | GREAT | GOOD: + return true; + case SHIT: + return false; + default: + return false; + } + } + + public function getHorTextAsset() + { + switch (abstract) + { + case PERFECT_GOLD: + return 'resultScreen/rankText/rankScrollPERFECT'; + case PERFECT: + return 'resultScreen/rankText/rankScrollPERFECT'; + case EXCELLENT: + return 'resultScreen/rankText/rankScrollEXCELLENT'; + case GREAT: + return 'resultScreen/rankText/rankScrollGREAT'; + case GOOD: + return 'resultScreen/rankText/rankScrollGOOD'; + case SHIT: + return 'resultScreen/rankText/rankScrollLOSS'; + default: + return 'resultScreen/rankText/rankScrollGOOD'; + } + } + + public function getVerTextAsset() + { + switch (abstract) + { + case PERFECT_GOLD: + return 'resultScreen/rankText/rankTextPERFECT'; + case PERFECT: + return 'resultScreen/rankText/rankTextPERFECT'; + case EXCELLENT: + return 'resultScreen/rankText/rankTextEXCELLENT'; + case GREAT: + return 'resultScreen/rankText/rankTextGREAT'; + case GOOD: + return 'resultScreen/rankText/rankTextGOOD'; + case SHIT: + return 'resultScreen/rankText/rankTextLOSS'; + default: + return 'resultScreen/rankText/rankTextGOOD'; + } + } } diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx index 934d6a4aa1..7f25a8e014 100644 --- a/source/funkin/save/Save.hx +++ b/source/funkin/save/Save.hx @@ -1,15 +1,17 @@ package funkin.save; import flixel.util.FlxSave; -import funkin.save.migrator.SaveDataMigrator; -import thx.semver.Version; import funkin.input.Controls.Device; +import funkin.play.scoring.Scoring; +import funkin.play.scoring.Scoring.ScoringRank; import funkin.save.migrator.RawSaveData_v1_0_0; import funkin.save.migrator.SaveDataMigrator; +import funkin.save.migrator.SaveDataMigrator; import funkin.ui.debug.charting.ChartEditorState.ChartEditorLiveInputStyle; import funkin.ui.debug.charting.ChartEditorState.ChartEditorTheme; -import thx.semver.Version; import funkin.util.SerializerUtil; +import thx.semver.Version; +import thx.semver.Version; @:nullSafety class Save @@ -492,6 +494,11 @@ class Save return song.get(difficultyId); } + public function getSongRank(songId:String, difficultyId:String = 'normal'):Null + { + return Scoring.calculateRank(getSongScore(songId, difficultyId)); + } + /** * Apply the score the user achieved for a given song on a given difficulty. */ diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 530f28c339..904a2ca4aa 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -34,6 +34,8 @@ import funkin.play.song.Song; import funkin.save.Save; import funkin.save.Save.SaveScoreData; import funkin.ui.AtlasText; +import funkin.play.scoring.Scoring; +import funkin.play.scoring.Scoring.ScoringRank; import funkin.ui.mainmenu.MainMenuState; import funkin.ui.MusicBeatSubState; import funkin.ui.transition.LoadingState; @@ -49,6 +51,34 @@ import funkin.effects.IntervalShake; typedef FreeplayStateParams = { ?character:String, + + ?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; + + /** + * 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; }; /** @@ -160,10 +190,14 @@ class FreeplayState extends MusicBeatSubState var bgDad:FlxSprite; var cardGlow:FlxSprite; + var fromResultsParams:Null = null; + public function new(?params:FreeplayStateParams, ?stickers:StickerSubState) { currentCharacter = params?.character ?? Constants.DEFAULT_CHARACTER; + fromResultsParams = params?.fromResults; + if (stickers != null) { stickerSubState = stickers; @@ -587,6 +621,11 @@ class FreeplayState extends MusicBeatSubState cardGlow.visible = true; FlxTween.tween(cardGlow, {alpha: 0, "scale.x": 1.2, "scale.y": 1.2}, 0.45, {ease: FlxEase.sineOut}); + + if (fromResultsParams != null) + { + rankAnimStart(fromResultsParams); + } }); generateSongList(null, false); @@ -657,6 +696,12 @@ class FreeplayState extends MusicBeatSubState // If curSelected is 0, the result will be null and fall back to the rememberedSongId. rememberedSongId = grpCapsules.members[curSelected]?.songData?.songId ?? rememberedSongId; + if (fromResultsParams != null) + { + rememberedSongId = fromResultsParams.songId; + rememberedDifficulty = fromResultsParams.difficultyId; + } + for (cap in grpCapsules.members) { cap.songText.resetText(); @@ -763,8 +808,10 @@ class FreeplayState extends MusicBeatSubState return songsToFilter; } - function rankAnimStart() + function rankAnimStart(fromResults:Null):Void { + busy = true; + dj.fistPump(); // rankCamera.fade(FlxColor.BLACK, 0.5, true); rankCamera.fade(0xFF000000, 0.5, true, null, true); @@ -789,21 +836,21 @@ class FreeplayState extends MusicBeatSubState new FlxTimer().start(0.5, _ -> { grpCapsules.members[curSelected].doLerp = false; - rankDisplayNew(); + rankDisplayNew(fromResults); }); } - function rankDisplayNew() + function rankDisplayNew(fromResults:Null):Void { grpCapsules.members[curSelected].ranking.alpha = 1; grpCapsules.members[curSelected].blurredRanking.alpha = 1; grpCapsules.members[curSelected].ranking.scale.set(20, 20); grpCapsules.members[curSelected].blurredRanking.scale.set(20, 20); - // var tempr:Int = FlxG.random.int(0, 4); - // grpCapsules.members[curSelected].ranking.rank = tempr; - grpCapsules.members[curSelected].ranking.animation.play(grpCapsules.members[curSelected].ranking.animation.curAnim.name, true); + grpCapsules.members[curSelected].ranking.animation.play(fromResults.newRank.getFreeplayRankIconAsset(), true); + // grpCapsules.members[curSelected].ranking.animation.curAnim.name, true); + FlxTween.tween(grpCapsules.members[curSelected].ranking, {"scale.x": 1, "scale.y": 1}, 0.1); grpCapsules.members[curSelected].blurredRanking.animation.play(grpCapsules.members[curSelected].blurredRanking.animation.curAnim.name, true); @@ -811,13 +858,13 @@ class FreeplayState extends MusicBeatSubState new FlxTimer().start(0.1, _ -> { trace(grpCapsules.members[curSelected].ranking.rank); - switch (grpCapsules.members[curSelected].tempr) + switch (fromResultsParams?.newRank) { - case 0: + case SHIT: FunkinSound.playOnce(Paths.sound('ranks/rankinbad')); - case 4: + case PERFECT: FunkinSound.playOnce(Paths.sound('ranks/rankinperfect')); - case 5: + case PERFECT_GOLD: FunkinSound.playOnce(Paths.sound('ranks/rankinperfect')); default: FunkinSound.playOnce(Paths.sound('ranks/rankinnormal')); @@ -846,31 +893,31 @@ class FreeplayState extends MusicBeatSubState }); new FlxTimer().start(0.6, _ -> { - rankAnimSlam(); + rankAnimSlam(fromResults); // IntervalShake.shake(grpCapsules.members[curSelected].capsule, 0.3, 1 / 30, 0, 0.3, FlxEase.quartIn); }); } - function rankAnimSlam() + function rankAnimSlam(fromResultsParams:Null) { // FlxTween.tween(rankCamera, {"zoom": 1.9}, 0.5, {ease: FlxEase.backOut}); FlxTween.tween(rankBg, {alpha: 0}, 0.5, {ease: FlxEase.expoIn}); // FlxTween.tween(grpCapsules.members[curSelected], {angle: 5}, 0.5, {ease: FlxEase.backIn}); - switch (grpCapsules.members[curSelected].tempr) + switch (fromResultsParams?.newRank) { - case 0: + case SHIT: FunkinSound.playOnce(Paths.sound('ranks/loss')); - case 1: + case GOOD: FunkinSound.playOnce(Paths.sound('ranks/good')); - case 2: + case GREAT: FunkinSound.playOnce(Paths.sound('ranks/great')); - case 3: + case EXCELLENT: FunkinSound.playOnce(Paths.sound('ranks/excellent')); - case 4: + case PERFECT: FunkinSound.playOnce(Paths.sound('ranks/perfect')); - case 5: + case PERFECT_GOLD: FunkinSound.playOnce(Paths.sound('ranks/perfect')); default: FunkinSound.playOnce(Paths.sound('ranks/loss')); @@ -880,7 +927,7 @@ class FreeplayState extends MusicBeatSubState new FlxTimer().start(0.5, _ -> { funnyCam.shake(0.0045, 0.35); - if (grpCapsules.members[curSelected].tempr == 0) + if (fromResultsParams?.newRank == SHIT) { dj.pumpFistBad(); } @@ -915,6 +962,9 @@ class FreeplayState extends MusicBeatSubState IntervalShake.shake(capsule, 0.6, 1 / 24, 0.12, 0, FlxEase.quadOut, function(_) { capsule.doLerp = true; capsule.cameras = [funnyCam]; + + // NOW we can interact with the menu + busy = false; }, null); // FlxTween.tween(capsule, {"targetPos.x": capsule.targetPos.x - 50}, 0.6, @@ -981,7 +1031,10 @@ class FreeplayState extends MusicBeatSubState var spamTimer:Float = 0; var spamming:Bool = false; - var busy:Bool = false; // Set to true once the user has pressed enter to select a song. + /** + * If true, disable interaction with the interface. + */ + var busy:Bool = false; var originalPos:FlxPoint = new FlxPoint(); @@ -989,19 +1042,20 @@ class FreeplayState extends MusicBeatSubState { super.update(elapsed); + #if debug if (FlxG.keys.justPressed.T) { - rankAnimStart(); + rankAnimStart(fromResultsParams); } if (FlxG.keys.justPressed.H) { - rankDisplayNew(); + rankDisplayNew(fromResultsParams); } if (FlxG.keys.justPressed.G) { - rankAnimSlam(); + rankAnimSlam(fromResultsParams); } if (FlxG.keys.justPressed.I) @@ -1024,6 +1078,7 @@ class FreeplayState extends MusicBeatSubState confirmTextGlow.y += 1; trace(confirmTextGlow.x, confirmTextGlow.y); } + #end if (FlxG.keys.justPressed.F) { @@ -1765,6 +1820,8 @@ class FreeplaySongData public var currentDifficulty(default, set):String = Constants.DEFAULT_DIFFICULTY; + public var scoringRank:Null = null; + var displayedVariations:Array = [Constants.DEFAULT_VARIATION]; function set_currentDifficulty(value:String):String @@ -1827,6 +1884,8 @@ class FreeplaySongData { this.albumId = songDifficulty.album; } + + this.scoringRank = Save.instance.getSongRank(songId, currentDifficulty); } } diff --git a/source/funkin/ui/freeplay/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx index 536a9cfe67..ad6ea386e7 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -20,6 +20,7 @@ import funkin.graphics.FunkinSprite; import flixel.tweens.FlxEase; import flixel.tweens.FlxTween; import flixel.addons.effects.FlxTrail; +import funkin.play.scoring.Scoring.ScoringRank; import flixel.util.FlxColor; class SongMenuItem extends FlxSpriteGroup @@ -70,8 +71,6 @@ class SongMenuItem extends FlxSpriteGroup var impactThing:FunkinSprite; - public var tempr:Int; - public function new(x:Float, y:Float) { super(x, y); @@ -132,13 +131,10 @@ class SongMenuItem extends FlxSpriteGroup // doesn't get added, simply is here to help with visibility of things for the pop in! grpHide = new FlxGroup(); - var rank:String = FlxG.random.getObject(ranks); - - tempr = FlxG.random.int(0, 5); - ranking = new FreeplayRank(420, 41, tempr); + ranking = new FreeplayRank(420, 41); add(ranking); - blurredRanking = new FreeplayRank(ranking.x, ranking.y, tempr); + blurredRanking = new FreeplayRank(ranking.x, ranking.y); blurredRanking.shader = new GaussianBlurShader(1); add(blurredRanking); // ranking.loadGraphic(Paths.image('freeplay/ranks/' + rank)); @@ -344,19 +340,19 @@ class SongMenuItem extends FlxSpriteGroup }); add(evilTrail); - switch (tempr) + switch (ranking.rank) { - case 0: + case SHIT: evilTrail.color = 0xFF6044FF; - case 1: + case GOOD: evilTrail.color = 0xFFEF8764; - case 2: + case GREAT: evilTrail.color = 0xFFEAF6FF; - case 3: + case EXCELLENT: evilTrail.color = 0xFFFDCB42; - case 4: + case PERFECT: evilTrail.color = 0xFFFF58B4; - case 5: + case PERFECT_GOLD: evilTrail.color = 0xFFFFB619; } } @@ -393,6 +389,12 @@ class SongMenuItem extends FlxSpriteGroup // diffRatingSprite.visible = false; } + function updateScoringRank(newRank:Null):Void + { + this.ranking.rank = newRank; + this.blurredRanking.rank = newRank; + } + function set_hsvShader(value:HSVShader):HSVShader { this.hsvShader = value; @@ -441,6 +443,7 @@ class SongMenuItem extends FlxSpriteGroup if (songData?.songCharacter != null) setCharacter(songData.songCharacter); updateBPM(Std.int(songData?.songStartingBpm) ?? 0); updateDifficultyRating(songData?.difficultyRating ?? 0); + updateScoringRank(songData?.scoringRank); // Update opacity, offsets, etc. updateSelected(); @@ -668,41 +671,53 @@ class SongMenuItem extends FlxSpriteGroup class FreeplayRank extends FlxSprite { - public var rank(default, set):Int = 0; - - var numToRank:Array = ["LOSS", "GOOD", "GREAT", "EXCELLENT", "PERFECT", "PERFECTSICK"]; + public var rank(default, set):Null = null; - function set_rank(val):Int + function set_rank(val:Null):Null { - animation.play(numToRank[val], true, false); + rank = val; - centerOffsets(false); - - switch (val) + if (rank == null) { - case 0: - // offset.x -= 1; - case 1: - // offset.x -= 1; - offset.y -= 8; - case 2: + this.visible = false; + } + else + { + this.visible = true; + + animation.play(val.getFreeplayRankIconAsset(), true, false); + + centerOffsets(false); + + switch (val) + { + case SHIT: // offset.x -= 1; - offset.y -= 8; - case 3: - // offset.y += 5; - case 4: - // offset.y += 5; - default: - centerOffsets(false); + case GOOD: + // offset.x -= 1; + offset.y -= 8; + case GREAT: + // offset.x -= 1; + offset.y -= 8; + case EXCELLENT: + // offset.y += 5; + case PERFECT: + // offset.y += 5; + case PERFECT_GOLD: + // offset.y += 5; + default: + centerOffsets(false); + } + updateHitbox(); } - updateHitbox(); - return val; + + return rank = val; } - public var baseY:Float = 0; public var baseX:Float = 0; + public var baseY:Float = 0; - public function new(x:Float, y:Float, ?initRank:Int = 0) + public function new(x:Float, y:Float) { super(x, y); @@ -717,9 +732,7 @@ class FreeplayRank extends FlxSprite blend = BlendMode.ADD; - this.rank = initRank; - - animation.play(numToRank[initRank], true); + this.rank = null; // setGraphicSize(Std.int(width * 0.9)); scale.set(0.9, 0.9); From 7a2f3c81a1d5cbb02c376256361eadb953cc9e6d Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 30 May 2024 21:11:17 -0400 Subject: [PATCH 128/216] fix the one random slice of pixels where the bg doesnt show... lol --- source/funkin/ui/title/TitleState.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/title/TitleState.hx b/source/funkin/ui/title/TitleState.hx index c9b3619e93..c6dbcd5058 100644 --- a/source/funkin/ui/title/TitleState.hx +++ b/source/funkin/ui/title/TitleState.hx @@ -124,7 +124,7 @@ class TitleState extends MusicBeatState persistentUpdate = true; - var bg:FunkinSprite = new FunkinSprite().makeSolidColor(FlxG.width, FlxG.height, FlxColor.BLACK); + var bg:FunkinSprite = new FunkinSprite(-1).makeSolidColor(FlxG.width + 2, FlxG.height, FlxColor.BLACK); bg.screenCenter(); add(bg); From dc33da904cc51d2ce1cf08aa3af1030863ae86f3 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 30 May 2024 23:03:27 -0400 Subject: [PATCH 129/216] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 2719d3fc1d..4bc0b35f6c 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 2719d3fc1d8f5d0cbafae8d27141d6c471148482 +Subproject commit 4bc0b35f6c7aa22086b85b6a635c6f0511d277fe From 7347b66ce47570b6098085945cd561d6fe0f2154 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 30 May 2024 23:07:41 -0400 Subject: [PATCH 130/216] removes trace() that lags freeplay --- source/funkin/ui/freeplay/SongMenuItem.hx | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/funkin/ui/freeplay/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx index ad6ea386e7..75a4c07a32 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -264,8 +264,6 @@ class SongMenuItem extends FlxSpriteGroup function updateBPM(newBPM:Int):Void { - trace(newBPM); - var shiftX:Float = 191; var tempShift:Float = 0; From 40d1fd96a36bf566437d2dafdb716ffafee9e212 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 30 May 2024 23:27:00 -0400 Subject: [PATCH 131/216] art submod --- art | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/art b/art index 66572f85d8..faeba700c5 160000 --- a/art +++ b/art @@ -1 +1 @@ -Subproject commit 66572f85d826ce2ec1d45468c12733b161237ffa +Subproject commit faeba700c5526bd4fd57ccc927d875c82b9d3553 From 007ec95e8548892e70189e782081201624211827 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 30 May 2024 23:42:48 -0400 Subject: [PATCH 132/216] update difficulties --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 4bc0b35f6c..11bcd1b791 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 4bc0b35f6c7aa22086b85b6a635c6f0511d277fe +Subproject commit 11bcd1b79169df4f0aa46d72c867e960a287d28a From 0d4f3cdc334c8593fe7b1042d1c2295adf69992e Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 31 May 2024 01:42:41 -0400 Subject: [PATCH 133/216] Scrolling results text --- assets | 2 +- source/funkin/InitState.hx | 4 +-- source/funkin/play/ResultState.hx | 44 ++++++++++++++++++++++++++++--- 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/assets b/assets index 11bcd1b791..7a0d92d300 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 11bcd1b79169df4f0aa46d72c867e960a287d28a +Subproject commit 7a0d92d3007de42c452b2ea97a917d8c8d114ee7 diff --git a/source/funkin/InitState.hx b/source/funkin/InitState.hx index d0009f95b7..c7a08d714d 100644 --- a/source/funkin/InitState.hx +++ b/source/funkin/InitState.hx @@ -219,9 +219,9 @@ class InitState extends FlxState FlxG.switchState(() -> new funkin.play.ResultState( { storyMode: false, - title: "CUM SONG", + title: "Cum Song Erect by Kawai Sprite", songId: "cum", - difficultyId: "hard", + difficultyId: "nightmare", isNewHighscore: true, scoreData: { diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index 79880038df..8b8c0aea33 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -15,8 +15,10 @@ import funkin.ui.freeplay.FreeplayScore; import flixel.text.FlxText; import flixel.util.FlxColor; import flixel.tweens.FlxEase; +import funkin.graphics.FunkinCamera; import funkin.ui.freeplay.FreeplayState; import flixel.tweens.FlxTween; +import flixel.addons.display.FlxBackdrop; import funkin.audio.FunkinSound; import flixel.util.FlxGradient; import flixel.util.FlxTimer; @@ -59,6 +61,10 @@ class ResultState extends MusicBeatSubState var gfGood:Null = null; var bfShit:Null = null; + final cameraBG:FunkinCamera; + final cameraScroll:FunkinCamera; + final cameraEverything:FunkinCamera; + public function new(params:ResultsStateParams) { super(); @@ -67,6 +73,10 @@ class ResultState extends MusicBeatSubState rank = Scoring.calculateRank(params.scoreData) ?? SHIT; + cameraBG = new FunkinCamera('resultsBG', 0, 0, FlxG.width, FlxG.height); + cameraScroll = new FunkinCamera('resultsScroll', 0, 0, FlxG.width, FlxG.height); + cameraEverything = new FunkinCamera('resultsEverything', 0, 0, FlxG.width, FlxG.height); + // We build a lot of this stuff in the constructor, then place it in create(). // This prevents having to do `null` checks everywhere. @@ -101,17 +111,32 @@ class ResultState extends MusicBeatSubState { if (FlxG.sound.music != null) FlxG.sound.music.stop(); + // We need multiple cameras so we can put one at an angle. + cameraScroll.angle = -3.8; + + cameraBG.bgColor = FlxColor.MAGENTA; + cameraScroll.bgColor = FlxColor.TRANSPARENT; + cameraEverything.bgColor = FlxColor.TRANSPARENT; + + FlxG.cameras.add(cameraBG, false); + FlxG.cameras.add(cameraScroll, false); + FlxG.cameras.add(cameraEverything, false); + + FlxG.cameras.setDefaultDrawTarget(cameraEverything, true); + // Reset the camera zoom on the results screen. FlxG.camera.zoom = 1.0; var bg:FlxSprite = FlxGradient.createGradientFlxSprite(FlxG.width, FlxG.height, [0xFFFECC5C, 0xFFFDC05C], 90); bg.scrollFactor.set(); bg.zIndex = 10; + bg.cameras = [cameraBG]; add(bg); bgFlash.scrollFactor.set(); bgFlash.visible = false; bgFlash.zIndex = 20; + bgFlash.cameras = [cameraBG]; add(bgFlash); // The sound system which falls into place behind the score text. Plays every time! @@ -455,16 +480,27 @@ class ResultState extends MusicBeatSubState function displayRankText():Void { - var rankTextVert:FunkinSprite = FunkinSprite.create(FlxG.width - 64, 100, rank.getVerTextAsset()); - rankTextVert.zIndex = 2000; + var rankTextVert:FlxBackdrop = new FlxBackdrop(Paths.image(rank.getVerTextAsset()), Y, 0, 30); + rankTextVert.x = FlxG.width - 64; + rankTextVert.y = 100; + rankTextVert.zIndex = 990; add(rankTextVert); + // Scrolling. + rankTextVert.velocity.y = -50; + for (i in 0...10) { - var rankTextBack:FunkinSprite = FunkinSprite.create(FlxG.width / 2 - 80, 50, rank.getHorTextAsset()); - rankTextBack.y += (rankTextBack.height * i / 2) + 10; + var rankTextBack:FlxBackdrop = new FlxBackdrop(Paths.image(rank.getHorTextAsset()), X, 10, 0); + rankTextBack.x = FlxG.width / 2 - 320; + rankTextBack.y = 50 + (150 * i / 2) + 10; + // rankTextBack.angle = -3.8; rankTextBack.zIndex = 100; + rankTextBack.cameras = [cameraScroll]; add(rankTextBack); + + // Scrolling. + rankTextBack.velocity.x = (i % 2 == 0) ? -10.0 : 10.0; } refresh(); From 9e0a99374691f8a3018dc547a49c7c400b9245a7 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 31 May 2024 02:03:40 -0400 Subject: [PATCH 134/216] Disable song previews for mod songs rather than crashing the game --- source/funkin/audio/FunkinSound.hx | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index b94c6008c7..7663c1305c 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -377,7 +377,7 @@ class FunkinSound extends FlxSound implements ICloneable FlxG.sound.music = partialMusic; FlxG.sound.list.remove(FlxG.sound.music); - if (params.onLoad != null) params.onLoad(); + if (FlxG.sound.music != null && params.onLoad != null) params.onLoad(); }); return true; @@ -488,14 +488,21 @@ class FunkinSound extends FlxSound implements ICloneable var soundRequest = FlxPartialSound.partialLoadFromFile(path, start, end); - promise.future.onError(function(e) { - soundRequest.error("Sound loading was errored or cancelled"); - }); - - soundRequest.future.onComplete(function(partialSound) { - var snd = FunkinSound.load(partialSound, volume, looped, autoDestroy, autoPlay, onComplete, onLoad); - promise.complete(snd); - }); + if (soundRequest == null) + { + promise.complete(null); + } + else + { + promise.future.onError(function(e) { + soundRequest.error("Sound loading was errored or cancelled"); + }); + + soundRequest.future.onComplete(function(partialSound) { + var snd = FunkinSound.load(partialSound, volume, looped, autoDestroy, autoPlay, onComplete, onLoad); + promise.complete(snd); + }); + } return promise; } From 2a8cdfaffae9dca58c0957f825f491ec89bd8070 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 31 May 2024 02:30:42 -0400 Subject: [PATCH 135/216] Fix an extra crash. --- source/funkin/ui/freeplay/FreeplayState.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 192c6e3ce1..f0695e51e6 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -830,7 +830,7 @@ class FreeplayState extends MusicBeatSubState dj.fistPump(); // rankCamera.fade(FlxColor.BLACK, 0.5, true); rankCamera.fade(0xFF000000, 0.5, true, null, true); - FlxG.sound.music.volume = 0; + if (FlxG.sound.music != null) FlxG.sound.music.volume = 0; rankBg.alpha = 1; originalPos.x = grpCapsules.members[curSelected].x; From 1e65cacb0efaa92991fd2290fe6f30b58e38ba7d Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Fri, 31 May 2024 10:39:06 +0100 Subject: [PATCH 136/216] fix funkinsound compile error --- source/funkin/audio/FunkinSound.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index b94c6008c7..cf4a71189b 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -359,7 +359,7 @@ class FunkinSound extends FlxSound implements ICloneable if (shouldLoadPartial) { - var music = FunkinSound.loadPartial(pathToUse, params.partialParams?.start ?? 0, params.partialParams?.end ?? 1, params?.startingVolume ?? 1.0, + var music = FunkinSound.loadPartial(pathToUse, params.partialParams?.start ?? 0.0, params.partialParams?.end ?? 1.0, params?.startingVolume ?? 1.0, params.loop ?? true, false, false, params.onComplete); if (music != null) From 28444fd47814a4c3833310743d7d5ce1944ec9e9 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Fri, 31 May 2024 10:39:53 +0100 Subject: [PATCH 137/216] rank tweaks, favourite changes + rank anim fixes --- source/funkin/play/ResultState.hx | 61 +++++++++-- source/funkin/play/scoring/Scoring.hx | 58 ++++++++++- source/funkin/ui/credits/CreditsState.hx | 3 +- source/funkin/ui/freeplay/AlbumRoll.hx | 2 +- source/funkin/ui/freeplay/FreeplayState.hx | 112 +++++++++++++++++---- source/funkin/ui/freeplay/SongMenuItem.hx | 7 +- source/funkin/ui/mainmenu/MainMenuState.hx | 13 ++- 7 files changed, 220 insertions(+), 36 deletions(-) diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index 79880038df..1ad19b41e1 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -59,6 +59,8 @@ class ResultState extends MusicBeatSubState var gfGood:Null = null; var bfShit:Null = null; + var rankBg:FunkinSprite; + public function new(params:ResultsStateParams) { super(); @@ -95,6 +97,8 @@ class ResultState extends MusicBeatSubState highscoreNew = new FlxSprite(310, 570); score = new ResultScore(35, 305, 10, params.scoreData.score); + + rankBg = new FunkinSprite(0, 0); } override function create():Void @@ -356,6 +360,12 @@ class ResultState extends MusicBeatSubState } }); + rankBg.makeSolidColor(FlxG.width, FlxG.height, 0xFF000000); + rankBg.zIndex = 99999; + add(rankBg); + + rankBg.alpha = 0; + refresh(); super.create(); @@ -654,18 +664,47 @@ class ResultState extends MusicBeatSubState } else { - openSubState(new funkin.ui.transition.StickerSubState(null, (sticker) -> FreeplayState.build( - { + var rigged:Bool = true; + if (rank > Scoring.calculateRank(params?.prevScoreData)) + //if (rigged) + { + trace('THE RANK IS Higher.....'); + + FlxTween.tween(rankBg, {alpha: 1}, 0.5, { - fromResults: - { - oldRank: Scoring.calculateRank(params?.prevScoreData), - newRank: rank, - songId: params.songId, - difficultyId: params.difficultyId - } - } - }, sticker))); + ease: FlxEase.expoOut, + onComplete: function(_) { + FlxG.switchState(FreeplayState.build( + { + { + fromResults: + { + oldRank: Scoring.calculateRank(params?.prevScoreData), + newRank: rank, + songId: params.songId, + difficultyId: params.difficultyId + } + } + })); + } + }); + } + else + { + trace('rank is lower...... and/or equal'); + openSubState(new funkin.ui.transition.StickerSubState(null, (sticker) -> FreeplayState.build( + { + { + fromResults: + { + oldRank: null, + newRank: rank, + songId: params.songId, + difficultyId: params.difficultyId + } + } + }, sticker))); + } } } diff --git a/source/funkin/play/scoring/Scoring.hx b/source/funkin/play/scoring/Scoring.hx index 6155ec8798..f941f3f010 100644 --- a/source/funkin/play/scoring/Scoring.hx +++ b/source/funkin/play/scoring/Scoring.hx @@ -349,7 +349,7 @@ class Scoring public static function calculateRank(scoreData:Null):Null { - if (scoreData == null) return null; + if (scoreData?.tallies.totalNotes == 0 || scoreData == null) return null; // Perfect (Platinum) is a Sick Full Clear var isPerfectGold = scoreData.tallies.sick == scoreData.tallies.totalNotes; @@ -394,6 +394,62 @@ enum abstract ScoringRank(String) var GOOD; var SHIT; + @:op(A > B) static function compare(a:Null, b:Null):Bool + { + if (a != null && b == null) return true; + if (a == null || b == null) return false; + + var temp1:Int = 0; + var temp2:Int = 0; + + // temp 1 + switch (a) + { + case PERFECT_GOLD: + temp1 = 5; + case PERFECT: + temp1 = 4; + case EXCELLENT: + temp1 = 3; + case GREAT: + temp1 = 2; + case GOOD: + temp1 = 1; + case SHIT: + temp1 = 0; + default: + temp1 = -1; + } + + // temp 2 + switch (b) + { + case PERFECT_GOLD: + temp2 = 5; + case PERFECT: + temp2 = 4; + case EXCELLENT: + temp2 = 3; + case GREAT: + temp2 = 2; + case GOOD: + temp2 = 1; + case SHIT: + temp2 = 0; + default: + temp2 = -1; + } + + if (temp1 > temp2) + { + return true; + } + else + { + return false; + } + } + /** * Delay in seconds */ diff --git a/source/funkin/ui/credits/CreditsState.hx b/source/funkin/ui/credits/CreditsState.hx index 6be1fecf71..44769e9b33 100644 --- a/source/funkin/ui/credits/CreditsState.hx +++ b/source/funkin/ui/credits/CreditsState.hx @@ -4,6 +4,7 @@ import flixel.text.FlxText; import flixel.util.FlxColor; import funkin.audio.FunkinSound; import flixel.FlxSprite; +import funkin.ui.mainmenu.MainMenuState; import flixel.group.FlxSpriteGroup; /** @@ -199,7 +200,7 @@ class CreditsState extends MusicBeatState function exit():Void { - FlxG.switchState(funkin.ui.mainmenu.MainMenuState.new); + FlxG.switchState(() -> new MainMenuState()); } public override function destroy():Void diff --git a/source/funkin/ui/freeplay/AlbumRoll.hx b/source/funkin/ui/freeplay/AlbumRoll.hx index 50f4a432c8..20cd913794 100644 --- a/source/funkin/ui/freeplay/AlbumRoll.hx +++ b/source/funkin/ui/freeplay/AlbumRoll.hx @@ -131,7 +131,7 @@ class AlbumRoll extends FlxSpriteGroup if (exitMovers == null) return; - exitMovers.set([newAlbumArt], + exitMovers.set([newAlbumArt, difficultyStars], { x: FlxG.width, speed: 0.4, diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 192c6e3ce1..186c84c338 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -193,12 +193,18 @@ class FreeplayState extends MusicBeatSubState var fromResultsParams:Null = null; + var prepForNewRank:Bool = false; + public function new(?params:FreeplayStateParams, ?stickers:StickerSubState) { currentCharacter = params?.character ?? Constants.DEFAULT_CHARACTER; fromResultsParams = params?.fromResults; + if(fromResultsParams?.oldRank != null){ + prepForNewRank = true; + } + if (stickers != null) { stickerSubState = stickers; @@ -235,11 +241,14 @@ class FreeplayState extends MusicBeatSubState isDebug = true; #end - FunkinSound.playMusic('freakyMenu', + if (prepForNewRank == false) + { + FunkinSound.playMusic('freakyMenu', { overrideExisting: true, restartTrack: false }); + } // Add a null entry that represents the RANDOM option songs.push(null); @@ -637,7 +646,7 @@ class FreeplayState extends MusicBeatSubState cardGlow.visible = true; FlxTween.tween(cardGlow, {alpha: 0, "scale.x": 1.2, "scale.y": 1.2}, 0.45, {ease: FlxEase.sineOut}); - if (fromResultsParams != null) + if (prepForNewRank == true) { rankAnimStart(fromResultsParams); } @@ -667,6 +676,11 @@ class FreeplayState extends MusicBeatSubState FlxG.cameras.add(rankCamera, false); rankBg.cameras = [rankCamera]; rankBg.alpha = 0; + + if (prepForNewRank == true) + { + rankCamera.fade(0xFF000000, 0, false, null, true); + } } var currentFilter:SongFilter = null; @@ -826,6 +840,7 @@ class FreeplayState extends MusicBeatSubState function rankAnimStart(fromResults:Null):Void { busy = true; + // grpCapsules.members[curSelected].forcePosition(); dj.fistPump(); // rankCamera.fade(FlxColor.BLACK, 0.5, true); @@ -833,8 +848,14 @@ class FreeplayState extends MusicBeatSubState FlxG.sound.music.volume = 0; rankBg.alpha = 1; - originalPos.x = grpCapsules.members[curSelected].x; - originalPos.y = grpCapsules.members[curSelected].y; + grpCapsules.members[curSelected].doLerp = false; + + // originalPos.x = grpCapsules.members[curSelected].x; + // originalPos.y = grpCapsules.members[curSelected].y; + + originalPos.x = 320.488; + originalPos.y = 235.6; + trace(originalPos); grpCapsules.members[curSelected].ranking.alpha = 0; grpCapsules.members[curSelected].blurredRanking.alpha = 0; @@ -846,11 +867,13 @@ class FreeplayState extends MusicBeatSubState FlxTween.tween(funnyCam, {"zoom": 1.1}, 0.6, {ease: FlxEase.sineIn}); grpCapsules.members[curSelected].cameras = [rankCamera]; - grpCapsules.members[curSelected].targetPos.set((FlxG.width / 2) - (grpCapsules.members[curSelected].width / 2), + // grpCapsules.members[curSelected].targetPos.set((FlxG.width / 2) - (grpCapsules.members[curSelected].width / 2), + // (FlxG.height / 2) - (grpCapsules.members[curSelected].height / 2)); + + grpCapsules.members[curSelected].setPosition((FlxG.width / 2) - (grpCapsules.members[curSelected].width / 2), (FlxG.height / 2) - (grpCapsules.members[curSelected].height / 2)); new FlxTimer().start(0.5, _ -> { - grpCapsules.members[curSelected].doLerp = false; rankDisplayNew(fromResults); }); } @@ -1028,6 +1051,12 @@ class FreeplayState extends MusicBeatSubState new FlxTimer().start(2, _ -> { // dj.fistPump(); + prepForNewRank = false; + FunkinSound.playMusic('freakyMenu', + { + overrideExisting: true, + restartTrack: false + }); FlxG.sound.music.fadeIn(4.0, 0.0, 1.0); }); } @@ -1095,7 +1124,7 @@ class FreeplayState extends MusicBeatSubState } #end - if (FlxG.keys.justPressed.F) + if (FlxG.keys.justPressed.F && !busy) { var targetSong = grpCapsules.members[curSelected]?.songData; if (targetSong != null) @@ -1104,24 +1133,45 @@ class FreeplayState extends MusicBeatSubState var isFav = targetSong.toggleFavorite(); if (isFav) { - FlxTween.tween(grpCapsules.members[realShit], {angle: 360}, 0.4, + grpCapsules.members[realShit].favIcon.visible = true; + grpCapsules.members[realShit].favIcon.animation.play('fav'); + FunkinSound.playOnce(Paths.sound('fav'), 1); + 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.elasticOut, - onComplete: _ -> { - grpCapsules.members[realShit].favIcon.visible = true; - grpCapsules.members[realShit].favIcon.animation.play('fav'); + ease: FlxEase.expoIn, + startDelay: 0.1, + onComplete: function(_) { + grpCapsules.members[realShit].doLerp = true; + busy = false; } }); } else { - grpCapsules.members[realShit].favIcon.animation.play('fav', false, true); - new FlxTimer().start((1 / 24) * 14, _ -> { + grpCapsules.members[realShit].favIcon.animation.play('fav', true, true, 9); + FunkinSound.playOnce(Paths.sound('unfav'), 1); + new FlxTimer().start(0.2, _ -> { grpCapsules.members[realShit].favIcon.visible = false; }); - new FlxTimer().start((1 / 24) * 24, _ -> { - FlxTween.tween(grpCapsules.members[realShit], {angle: 0}, 0.4, {ease: FlxEase.elasticOut}); - }); + + 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, + startDelay: 0.1, + onComplete: function(_) { + grpCapsules.members[realShit].doLerp = true; + busy = false; + } + }); } } } @@ -1325,6 +1375,24 @@ class FreeplayState extends MusicBeatSubState var longestTimer:Float = 0; + // FlxTween.color(bgDad, 0.33, 0xFFFFFFFF, 0xFF555555, {ease: FlxEase.quadOut}); + FlxTween.color(pinkBack, 0.25, 0xFFFFD863, 0xFFFFD0D5, {ease: FlxEase.quadOut}); + + cardGlow.visible = true; + cardGlow.alpha = 1; + cardGlow.scale.set(1, 1); + FlxTween.tween(cardGlow, {alpha: 0, "scale.x": 1.2, "scale.y": 1.2}, 0.25, {ease: FlxEase.sineOut}); + + orangeBackShit.visible = false; + alsoOrangeLOL.visible = false; + + moreWays.visible = false; + funnyScroll.visible = false; + txtNuts.visible = false; + funnyScroll2.visible = false; + moreWays2.visible = false; + funnyScroll3.visible = false; + for (grpSpr in exitMovers.keys()) { var moveData:MoveData = exitMovers.get(grpSpr); @@ -1555,6 +1623,7 @@ class FreeplayState extends MusicBeatSubState FunkinSound.playOnce(Paths.sound('confirmMenu')); dj.confirm(); + grpCapsules.members[curSelected].forcePosition(); grpCapsules.members[curSelected].songText.flickerText(); // FlxTween.color(bgDad, 0.33, 0xFFFFFFFF, 0xFF555555, {ease: FlxEase.quadOut}); @@ -1689,6 +1758,7 @@ class FreeplayState extends MusicBeatSubState } else { + if(prepForNewRank == false){ var potentiallyErect:String = (currentDifficulty == "erect") || (currentDifficulty == "nightmare") ? "-erect" : ""; // TODO: Stream the instrumental of the selected song? FunkinSound.playMusic(daSongCapsule.songData.songId, @@ -1708,6 +1778,7 @@ class FreeplayState extends MusicBeatSubState FlxG.sound.music.fadeIn(2, 0, 0.4); } }); + } } grpCapsules.members[curSelected].selected = true; } @@ -1719,7 +1790,12 @@ class FreeplayState extends MusicBeatSubState */ public static function build(?params:FreeplayStateParams, ?stickers:StickerSubState):MusicBeatState { - var result = new MainMenuState(); + var result:MainMenuState; + if(params?.fromResults.oldRank != null){ + result = new MainMenuState(true); + }else{ + result = new MainMenuState(false); + } result.openSubState(new FreeplayState(params, stickers)); result.persistentUpdate = false; diff --git a/source/funkin/ui/freeplay/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx index ad6ea386e7..b52032bc3f 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -371,7 +371,7 @@ class SongMenuItem extends FlxSpriteGroup switch (i) { case 0: - if (newRating > 10) + if (newRating < 10) { bigNumbers[i].digit = 0; } @@ -677,7 +677,7 @@ class FreeplayRank extends FlxSprite { rank = val; - if (rank == null) + if (rank == null || val == null) { this.visible = false; } @@ -687,6 +687,8 @@ class FreeplayRank extends FlxSprite animation.play(val.getFreeplayRankIconAsset(), true, false); + trace(val.getFreeplayRankIconAsset()); + centerOffsets(false); switch (val) @@ -707,6 +709,7 @@ class FreeplayRank extends FlxSprite // offset.y += 5; default: centerOffsets(false); + this.visible = false; } updateHitbox(); } diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index 22262006ab..c504b3c3e1 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -42,6 +42,15 @@ class MainMenuState extends MusicBeatState var magenta:FlxSprite; var camFollow:FlxObject; + var overrideMusic:Bool = false; + + public function new(?_overrideMusic:Bool = false) + { + super(); + overrideMusic = _overrideMusic; + + } + override function create():Void { #if discord_rpc @@ -54,7 +63,7 @@ class MainMenuState extends MusicBeatState transIn = FlxTransitionableState.defaultTransIn; transOut = FlxTransitionableState.defaultTransOut; - playMenuMusic(); + if(overrideMusic == false) playMenuMusic(); // We want the state to always be able to begin with being able to accept inputs and show the anims of the menu items. persistentUpdate = true; @@ -163,7 +172,7 @@ class MainMenuState extends MusicBeatState function playMenuMusic():Void { - FunkinSound.playMusic('freakyMenu', + FunkinSound.playMusic('freakyMenu', { overrideExisting: true, restartTrack: false From 5d0db60810b37e3a076e3581ed2b33416ed1050c Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Fri, 31 May 2024 10:40:51 +0100 Subject: [PATCH 138/216] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 4bc0b35f6c..d64939d866 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 4bc0b35f6c7aa22086b85b6a635c6f0511d277fe +Subproject commit d64939d866c70a831b76ed78930782b66871dcc2 From d89a898e6c3d33430002896bd601ec72c6a0faba Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 31 May 2024 17:16:26 -0400 Subject: [PATCH 139/216] make songs last longer on freeplay --- source/funkin/ui/freeplay/FreeplayState.hx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 192c6e3ce1..71052a923f 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -104,6 +104,7 @@ class FreeplayState extends MusicBeatSubState /** * For the audio preview, the duration of the fade-out effect. + * */ public static final FADE_OUT_DURATION:Float = 0.25; @@ -1690,7 +1691,6 @@ class FreeplayState extends MusicBeatSubState else { var potentiallyErect:String = (currentDifficulty == "erect") || (currentDifficulty == "nightmare") ? "-erect" : ""; - // TODO: Stream the instrumental of the selected song? FunkinSound.playMusic(daSongCapsule.songData.songId, { startingVolume: 0.0, @@ -1701,8 +1701,8 @@ class FreeplayState extends MusicBeatSubState partialParams: { loadPartial: true, - start: 0, - end: 0.1 + start: 0.05, + end: 0.25 }, onLoad: function() { FlxG.sound.music.fadeIn(2, 0, 0.4); From 98eda8ef551ad533b29a5a1625ec613b78165c5e Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 31 May 2024 18:09:07 -0400 Subject: [PATCH 140/216] Give timeFormat a default value (fixes the Stress issues!) --- source/funkin/data/song/SongData.hx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/funkin/data/song/SongData.hx b/source/funkin/data/song/SongData.hx index bd25139a79..ca805e1395 100644 --- a/source/funkin/data/song/SongData.hx +++ b/source/funkin/data/song/SongData.hx @@ -56,6 +56,8 @@ class SongMetadata implements ICloneable @:default(funkin.data.song.SongRegistry.DEFAULT_GENERATEDBY) public var generatedBy:String; + @:optional + @:default(funkin.data.song.SongData.SongTimeFormat.MILLISECONDS) public var timeFormat:SongTimeFormat; public var timeChanges:Array; @@ -117,7 +119,7 @@ class SongMetadata implements ICloneable { var ignoreNullOptionals = true; var writer = new json2object.JsonWriter(ignoreNullOptionals); - // I believe @:jignored should be iggnored by the writer? + // I believe @:jignored should be ignored by the writer? // var output = this.clone(); // output.variation = null; // Not sure how to make a field optional on the reader and ignored on the writer. return writer.write(this, pretty ? ' ' : null); From 8bf26322e9a405e3eb70508711b66a606cd444a6 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 31 May 2024 18:09:30 -0400 Subject: [PATCH 141/216] Update `generatedBy` to the latest value when saving a chart. --- .../ChartEditorImportExportHandler.hx | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/source/funkin/ui/debug/charting/handlers/ChartEditorImportExportHandler.hx b/source/funkin/ui/debug/charting/handlers/ChartEditorImportExportHandler.hx index 0308cd8716..a78eeae4cd 100644 --- a/source/funkin/ui/debug/charting/handlers/ChartEditorImportExportHandler.hx +++ b/source/funkin/ui/debug/charting/handlers/ChartEditorImportExportHandler.hx @@ -384,17 +384,32 @@ class ChartEditorImportExportHandler if (variationId == '') { var variationMetadata:Null = state.songMetadata.get(variation); - if (variationMetadata != null) zipEntries.push(FileUtil.makeZIPEntry('${state.currentSongId}-metadata.json', variationMetadata.serialize())); + if (variationMetadata != null) + { + variationMetadata.generatedBy = funkin.data.song.SongRegistry.DEFAULT_GENERATEDBY; + zipEntries.push(FileUtil.makeZIPEntry('${state.currentSongId}-metadata.json', variationMetadata.serialize())); + } var variationChart:Null = state.songChartData.get(variation); - if (variationChart != null) zipEntries.push(FileUtil.makeZIPEntry('${state.currentSongId}-chart.json', variationChart.serialize())); + if (variationChart != null) + { + variationChart.generatedBy = funkin.data.song.SongRegistry.DEFAULT_GENERATEDBY; + zipEntries.push(FileUtil.makeZIPEntry('${state.currentSongId}-chart.json', variationChart.serialize())); + } } else { var variationMetadata:Null = state.songMetadata.get(variation); - if (variationMetadata != null) zipEntries.push(FileUtil.makeZIPEntry('${state.currentSongId}-metadata-$variationId.json', - variationMetadata.serialize())); + if (variationMetadata != null) + { + variationMetadata.generatedBy = funkin.data.song.SongRegistry.DEFAULT_GENERATEDBY; + zipEntries.push(FileUtil.makeZIPEntry('${state.currentSongId}-metadata-$variationId.json', variationMetadata.serialize())); + } var variationChart:Null = state.songChartData.get(variation); - if (variationChart != null) zipEntries.push(FileUtil.makeZIPEntry('${state.currentSongId}-chart-$variationId.json', variationChart.serialize())); + if (variationChart != null) + { + variationChart.generatedBy = funkin.data.song.SongRegistry.DEFAULT_GENERATEDBY; + zipEntries.push(FileUtil.makeZIPEntry('${state.currentSongId}-chart-$variationId.json', variationChart.serialize())); + } } } From 06daa9d402a81bb45b5bf214595b4d0ac794fd4c Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 31 May 2024 19:20:39 -0400 Subject: [PATCH 142/216] Increase Great threshold to 80% --- source/funkin/util/Constants.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/util/Constants.hx b/source/funkin/util/Constants.hx index 4e706c612e..1e0978839a 100644 --- a/source/funkin/util/Constants.hx +++ b/source/funkin/util/Constants.hx @@ -467,7 +467,7 @@ class Constants // % Hit public static final RANK_PERFECT_THRESHOLD:Float = 1.00; public static final RANK_EXCELLENT_THRESHOLD:Float = 0.90; - public static final RANK_GREAT_THRESHOLD:Float = 0.75; + public static final RANK_GREAT_THRESHOLD:Float = 0.80; public static final RANK_GOOD_THRESHOLD:Float = 0.60; // public static final RANK_SHIT_THRESHOLD:Float = 0.00; From 9088570b926eae749c5cc6822dbb01cd1d541f69 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 31 May 2024 19:21:21 -0400 Subject: [PATCH 143/216] Make sure JSON data uses latest version/generatedBy when writing. --- source/funkin/data/song/SongData.hx | 24 +++++++++++++++++++ .../data/song/importer/ChartManifestData.hx | 8 +++++++ source/funkin/data/stage/StageData.hx | 8 +++++++ .../funkin/ui/credits/CreditsDataHandler.hx | 2 +- .../ChartEditorImportExportHandler.hx | 4 +++- 5 files changed, 44 insertions(+), 2 deletions(-) diff --git a/source/funkin/data/song/SongData.hx b/source/funkin/data/song/SongData.hx index ca805e1395..769af8f08a 100644 --- a/source/funkin/data/song/SongData.hx +++ b/source/funkin/data/song/SongData.hx @@ -117,6 +117,9 @@ class SongMetadata implements ICloneable */ public function serialize(pretty:Bool = true):String { + // Update generatedBy and version before writing. + updateVersionToLatest(); + var ignoreNullOptionals = true; var writer = new json2object.JsonWriter(ignoreNullOptionals); // I believe @:jignored should be ignored by the writer? @@ -125,6 +128,12 @@ class SongMetadata implements ICloneable return writer.write(this, pretty ? ' ' : null); } + public function updateVersionToLatest():Void + { + this.version = SongRegistry.SONG_METADATA_VERSION; + this.generatedBy = SongRegistry.DEFAULT_GENERATEDBY; + } + /** * Produces a string representation suitable for debugging. */ @@ -373,6 +382,12 @@ class SongMusicData implements ICloneable this.variation = variation == null ? Constants.DEFAULT_VARIATION : variation; } + public function updateVersionToLatest():Void + { + this.version = SongRegistry.SONG_MUSIC_DATA_VERSION; + this.generatedBy = SongRegistry.DEFAULT_GENERATEDBY; + } + public function clone():SongMusicData { var result:SongMusicData = new SongMusicData(this.songName, this.artist, this.variation); @@ -605,11 +620,20 @@ class SongChartData implements ICloneable */ public function serialize(pretty:Bool = true):String { + // Update generatedBy and version before writing. + updateVersionToLatest(); + var ignoreNullOptionals = true; var writer = new json2object.JsonWriter(ignoreNullOptionals); return writer.write(this, pretty ? ' ' : null); } + public function updateVersionToLatest():Void + { + this.version = SongRegistry.SONG_CHART_DATA_VERSION; + this.generatedBy = SongRegistry.DEFAULT_GENERATEDBY; + } + public function clone():SongChartData { // We have to manually perform the deep clone here because Map.deepClone() doesn't work. diff --git a/source/funkin/data/song/importer/ChartManifestData.hx b/source/funkin/data/song/importer/ChartManifestData.hx index dd0d284798..04b5a1b69b 100644 --- a/source/funkin/data/song/importer/ChartManifestData.hx +++ b/source/funkin/data/song/importer/ChartManifestData.hx @@ -61,10 +61,18 @@ class ChartManifestData */ public function serialize(pretty:Bool = true):String { + // Update generatedBy and version before writing. + updateVersionToLatest(); + var writer = new json2object.JsonWriter(); return writer.write(this, pretty ? ' ' : null); } + public function updateVersionToLatest():Void + { + this.version = CHART_MANIFEST_DATA_VERSION; + } + public static function deserialize(contents:String):Null { var parser = new json2object.JsonParser(); diff --git a/source/funkin/data/stage/StageData.hx b/source/funkin/data/stage/StageData.hx index 22b883c759..bebd86d02b 100644 --- a/source/funkin/data/stage/StageData.hx +++ b/source/funkin/data/stage/StageData.hx @@ -58,9 +58,17 @@ class StageData */ public function serialize(pretty:Bool = true):String { + // Update generatedBy and version before writing. + updateVersionToLatest(); + var writer = new json2object.JsonWriter(); return writer.write(this, pretty ? ' ' : null); } + + public function updateVersionToLatest():Void + { + this.version = StageRegistry.STAGE_DATA_VERSION; + } } typedef StageDataCharacters = diff --git a/source/funkin/ui/credits/CreditsDataHandler.hx b/source/funkin/ui/credits/CreditsDataHandler.hx index 2240ec50eb..844d0f4db7 100644 --- a/source/funkin/ui/credits/CreditsDataHandler.hx +++ b/source/funkin/ui/credits/CreditsDataHandler.hx @@ -54,7 +54,7 @@ class CreditsDataHandler body: [ {line: 'ninjamuffin99'}, {line: 'PhantomArcade'}, - {line: 'KawaiSprite'}, + {line: 'Kawai Sprite'}, {line: 'evilsk8r'}, ] } diff --git a/source/funkin/ui/debug/charting/handlers/ChartEditorImportExportHandler.hx b/source/funkin/ui/debug/charting/handlers/ChartEditorImportExportHandler.hx index a78eeae4cd..e84f7ec438 100644 --- a/source/funkin/ui/debug/charting/handlers/ChartEditorImportExportHandler.hx +++ b/source/funkin/ui/debug/charting/handlers/ChartEditorImportExportHandler.hx @@ -386,12 +386,14 @@ class ChartEditorImportExportHandler var variationMetadata:Null = state.songMetadata.get(variation); if (variationMetadata != null) { + variationMetadata.version = funkin.data.song.SongRegistry.SONG_METADATA_VERSION; variationMetadata.generatedBy = funkin.data.song.SongRegistry.DEFAULT_GENERATEDBY; zipEntries.push(FileUtil.makeZIPEntry('${state.currentSongId}-metadata.json', variationMetadata.serialize())); } var variationChart:Null = state.songChartData.get(variation); if (variationChart != null) { + variationChart.version = funkin.data.song.SongRegistry.SONG_CHART_DATA_VERSION; variationChart.generatedBy = funkin.data.song.SongRegistry.DEFAULT_GENERATEDBY; zipEntries.push(FileUtil.makeZIPEntry('${state.currentSongId}-chart.json', variationChart.serialize())); } @@ -401,12 +403,12 @@ class ChartEditorImportExportHandler var variationMetadata:Null = state.songMetadata.get(variation); if (variationMetadata != null) { - variationMetadata.generatedBy = funkin.data.song.SongRegistry.DEFAULT_GENERATEDBY; zipEntries.push(FileUtil.makeZIPEntry('${state.currentSongId}-metadata-$variationId.json', variationMetadata.serialize())); } var variationChart:Null = state.songChartData.get(variation); if (variationChart != null) { + variationChart.version = funkin.data.song.SongRegistry.SONG_CHART_DATA_VERSION; variationChart.generatedBy = funkin.data.song.SongRegistry.DEFAULT_GENERATEDBY; zipEntries.push(FileUtil.makeZIPEntry('${state.currentSongId}-chart-$variationId.json', variationChart.serialize())); } From 074b1afc7659cf0923a03533994a812c9f39ef8d Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 31 May 2024 20:16:23 -0400 Subject: [PATCH 144/216] Readd a reverted freeplay bugfix --- source/funkin/audio/FunkinSound.hx | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index b94c6008c7..7663c1305c 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -377,7 +377,7 @@ class FunkinSound extends FlxSound implements ICloneable FlxG.sound.music = partialMusic; FlxG.sound.list.remove(FlxG.sound.music); - if (params.onLoad != null) params.onLoad(); + if (FlxG.sound.music != null && params.onLoad != null) params.onLoad(); }); return true; @@ -488,14 +488,21 @@ class FunkinSound extends FlxSound implements ICloneable var soundRequest = FlxPartialSound.partialLoadFromFile(path, start, end); - promise.future.onError(function(e) { - soundRequest.error("Sound loading was errored or cancelled"); - }); - - soundRequest.future.onComplete(function(partialSound) { - var snd = FunkinSound.load(partialSound, volume, looped, autoDestroy, autoPlay, onComplete, onLoad); - promise.complete(snd); - }); + if (soundRequest == null) + { + promise.complete(null); + } + else + { + promise.future.onError(function(e) { + soundRequest.error("Sound loading was errored or cancelled"); + }); + + soundRequest.future.onComplete(function(partialSound) { + var snd = FunkinSound.load(partialSound, volume, looped, autoDestroy, autoPlay, onComplete, onLoad); + promise.complete(snd); + }); + } return promise; } From e36fbfa72c79bf2ac793e1a78a80b0559c9cba64 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 31 May 2024 20:16:37 -0400 Subject: [PATCH 145/216] Update the changelog --- CHANGELOG.md | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10bbfe5f7b..f5aefb8855 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,31 +6,51 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.4.0] - 2024-05-?? ### Added -- 2 new Erect remixes, Eggnog and Satin Panties. Check them out from -- Improvements to the Freeplay screen, with song difficulty ratings and player rank displays. -- Reworked the Results screen, with additional animations and audio based on your performance. +- 2 new Erect remixes, Eggnog and Satin Panties. Check them out from the Freeplay menu! +- Major visual improvements to the Results screen, with additional animations and audio based on your performance. +- Major visual improvements to the Freeplay screen, with song difficulty ratings and player rank displays. + - Freeplay now plays a preview of songs when you hover over them. - Added a Charter field to the chart format, to allow for crediting the creator of a level's chart. - You can see who charted a song from the Pause menu. +- Added a new Scroll Speed chart event to change the note speed mid-song (thanks ) ### Changed - Tweaked the charts for several songs: + - Monster - Winter Horrorland - Stress - Lit Up + - Tutorial (increased the note speed slightly) + - Senpai (increased the note speed) + - Thorns (increased the note speed slightly) +- Favorite songs marked in Freeplay are now stored between sessions. - Custom note styles are now properly supported for songs; add new notestyles via JSON, then select it for use from the Chart Editor Metadata toolbox. (thanks Keoiki!) +- Improved logic for NoteHitScriptEvents, allowing you to view the hit diff and modify whether a note hit is a combo break (thanks nebulazorua!) - Health icons now support a Winning frame without requiring a spritesheet, simply include a third frame in the icon file. (thanks gamerbross!) - Remember that for more complex behaviors such as animations or transitions, you should use an XML file to define each frame. ### Fixed +- Fixed a bug where the game would silently fail to load saves on HTML5 +- Fixed some bugs with the props on the Story Menu not bopping properly +- Additional fixes to the Loading bar on HTML5 (thanks lemz1!) +- Fixed several bugs with the TitleState, including missing music when returning from the Main Menu (thanks gamerbross!) +- Fixed a camera bug in the Main Menu (thanks richTrash21!) +- Fixed a bug where changing difficulties in Story mode wouldn't update the score (thanks sectorA!) +- Fixed a crash in Freeplay caused by a level referencing an invalid song (thanks gamerbross!) - Fixed a bug where pressing the volume keys would stop the Toy commercial (thanks gamerbross!) -- Fixed a bug where the Chart Editor would crash when losing (thanks gamerbross!) +- Fixed a bug where the Chart Editor Playtest would crash when losing (thanks gamerbross!) +- Fixed a bug where hold notes would display improperly in the Chart Editor when downscroll was enabled for gameplay (thanks gamerbross!) +- Fixed a bug where hold notes would be positioned wrong on downscroll (thanks MaybeMaru!) +- Removed a large number of unused imports to optimize builds (thanks Ethan-makes-music!) +- Improved debug logging for unscripted stages (thanks gamerbross!) - Made improvements to compiling documentation (thanks gedehari!) - Fixed a crash on Linux caused by an old version of hxCodec (thanks Noobz4Life!) - Optimized animation handling for characters (thanks richTrash21!) +- Additional bug fixes and optimizations. ## [0.3.3] - 2024-05-14 ### Changed - Cleaned up some code in `PlayAnimationSongEvent.hx` (thanks BurgerBalls!) ### Fixed -- Fix Web Loading Bar (thanks lemz1!) +- Fixes to the Loading bar on HTML5 (thanks lemz1!) - Don't allow any more inputs when exiting freeplay (thanks gamerbros!) - Fixed using mouse wheel to scroll on freeplay (thanks JugieNoob!) - Fixed the reset's of the health icons, score, and notes when re-entering gameplay from gameover (thanks ImCodist!) @@ -38,11 +58,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed camera stutter once a wipe transition to the Main Menu completes (thanks ImCodist!) - Fixed an issue where hold note would be invisible for a single frame (thanks ImCodist!) - Fix tween accumulation on title screen when pressing Y multiple times (thanks TheGaloXx!) -- Fix for a game over easter egg so you don't accidentally exit it when viewing - Fix a crash when querying FlxG.state in the crash handler +- Fix for a game over easter egg so you don't accidentally exit it when viewing - Fix an issue where the Freeplay menu never displays 100% clear +- Fix an issue where Weekend 1 Pico attempted to retrieve a missing asset. +- Fix an issue where duplicate keybinds would be stoed, potentially causing a crash - Chart debug key now properly returns you to the previous chart editor session if you were playtesting a chart (thanks nebulazorua!) -- Hopefully fixed Freeplay crashes on AMD gpu's +- Fix a crash on Freeplay found on AMD graphics cards ## [0.3.2] - 2024-05-03 ### Added From e08cdac35bfa3c57540d90d21118797d2e244fde Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Sat, 1 Jun 2024 01:16:52 +0100 Subject: [PATCH 146/216] score number shuffling --- source/funkin/play/ResultScore.hx | 80 +++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 4 deletions(-) diff --git a/source/funkin/play/ResultScore.hx b/source/funkin/play/ResultScore.hx index d5d5a65670..23e6c8d326 100644 --- a/source/funkin/play/ResultScore.hx +++ b/source/funkin/play/ResultScore.hx @@ -2,11 +2,16 @@ package funkin.play; import flixel.FlxSprite; import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup; +import flixel.tweens.FlxTween; +import flixel.util.FlxTimer; +import flixel.tweens.FlxEase; class ResultScore extends FlxTypedSpriteGroup { public var scoreShit(default, set):Int = 0; + public var scoreStart:Int = 0; + function set_scoreShit(val):Int { if (group == null || group.members == null) return val; @@ -16,7 +21,8 @@ class ResultScore extends FlxTypedSpriteGroup while (dumbNumb > 0) { - group.members[loopNum].digit = dumbNumb % 10; + scoreStart += 1; + group.members[loopNum].finalDigit = dumbNumb % 10; // var funnyNum = group.members[loopNum]; // prevNum = group.members[loopNum + 1]; @@ -44,9 +50,15 @@ class ResultScore extends FlxTypedSpriteGroup public function animateNumbers():Void { - for (i in group.members) + for (i in group.members.length-scoreStart...group.members.length) { - i.playAnim(); + // if(i.finalDigit == 10) continue; + + new FlxTimer().start((i-1)/24, _ -> { + group.members[i].finalDelay = scoreStart - (i-1); + group.members[i].playAnim(); + group.members[i].shuffle(); + }); } } @@ -71,12 +83,26 @@ class ResultScore extends FlxTypedSpriteGroup class ScoreNum extends FlxSprite { public var digit(default, set):Int = 10; + public var finalDigit(default, set):Int = 10; + public var glow:Bool = true; + + function set_finalDigit(val):Int + { + animation.play('GONE', true, false, 0); + + return finalDigit = val; + } function set_digit(val):Int { if (val >= 0 && animation.curAnim != null && animation.curAnim.name != numToString[val]) { - animation.play(numToString[val], true, false, 0); + if(glow){ + animation.play(numToString[val], true, false, 0); + glow = false; + }else{ + animation.play(numToString[val], true, false, 4); + } updateHitbox(); switch (val) @@ -107,6 +133,10 @@ class ScoreNum extends FlxSprite animation.play(numToString[digit], true, false, 0); } + public var shuffleTimer:FlxTimer; + public var finalTween:FlxTween; + public var finalDelay:Float = 0; + public var baseY:Float = 0; public var baseX:Float = 0; @@ -114,6 +144,47 @@ class ScoreNum extends FlxSprite "ZERO", "ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE", "DISABLED" ]; + function finishShuffleTween():Void{ + + var tweenFunction = function(x) { + var digitRounded = Math.floor(x); + //if(digitRounded == finalDigit) glow = true; + digit = digitRounded; + }; + + finalTween = FlxTween.num(0.0, finalDigit, 23/24, { + ease: FlxEase.quadOut, + onComplete: function (input) { + new FlxTimer().start((finalDelay)/24, _ -> { + animation.play(animation.curAnim.name, true, false, 0); + }); + // fuck + } + }, tweenFunction); + } + + + function shuffleProgress(shuffleTimer:FlxTimer):Void + { + var tempDigit:Int = digit; + tempDigit += 1; + if(tempDigit > 9) tempDigit = 0; + if(tempDigit < 0) tempDigit = 0; + digit = tempDigit; + + if (shuffleTimer.loops > 0 && shuffleTimer.loopsLeft == 0) + { + //digit = finalDigit; + finishShuffleTween(); + } + } + + public function shuffle():Void{ + var duration:Float = 41/24; + var interval:Float = 1/24; + shuffleTimer = new FlxTimer().start(interval, shuffleProgress, Std.int(duration / interval)); + } + public function new(x:Float, y:Float) { super(x, y); @@ -130,6 +201,7 @@ class ScoreNum extends FlxSprite } animation.addByPrefix('DISABLED', 'DISABLED', 24, false); + animation.addByPrefix('GONE', 'GONE', 24, false); this.digit = 10; From 1cffc36ba8aa51b90523ff7fbe4464eca957cc29 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Sat, 1 Jun 2024 01:17:11 +0100 Subject: [PATCH 147/216] results timing redo + fixed anims for all ranks --- source/funkin/play/ResultState.hx | 278 +++++++++++++++++++++----- source/funkin/play/scoring/Scoring.hx | 70 ++++++- 2 files changed, 292 insertions(+), 56 deletions(-) diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index 8b8c0aea33..8a7332a836 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -5,6 +5,7 @@ import funkin.ui.story.StoryMenuState; import funkin.graphics.adobeanimate.FlxAtlasSprite; import flixel.FlxSprite; import funkin.graphics.FunkinSprite; +import flixel.effects.FlxFlicker; import flixel.graphics.frames.FlxBitmapFont; import flixel.group.FlxGroup.FlxTypedGroup; import flixel.math.FlxPoint; @@ -55,8 +56,10 @@ class ResultState extends MusicBeatSubState final score:ResultScore; var bfPerfect:Null = null; + var heartsPerfect:Null = null; var bfExcellent:Null = null; var bfGreat:Null = null; + var gfGreat:Null = null; var bfGood:Null = null; var gfGood:Null = null; var bfShit:Null = null; @@ -94,15 +97,15 @@ class ResultState extends MusicBeatSubState clearPercentSmall.zIndex = 1000; clearPercentSmall.visible = false; - bgFlash = FlxGradient.createGradientFlxSprite(FlxG.width, FlxG.height, [0xFFFFEB69, 0xFFFFE66A], 90); + bgFlash = FlxGradient.createGradientFlxSprite(FlxG.width, FlxG.height, [0xFFFFF1A6, 0xFFFFF1BE], 90); resultsAnim = FunkinSprite.createSparrow(-200, -10, "resultScreen/results"); - ratingsPopin = FunkinSprite.createSparrow(-150, 120, "resultScreen/ratingsPopin"); + ratingsPopin = FunkinSprite.createSparrow(-135, 135, "resultScreen/ratingsPopin"); - scorePopin = FunkinSprite.createSparrow(-180, 520, "resultScreen/scorePopin"); + scorePopin = FunkinSprite.createSparrow(-180, 515, "resultScreen/scorePopin"); - highscoreNew = new FlxSprite(310, 570); + highscoreNew = new FlxSprite(44, 557); score = new ResultScore(35, 305, 10, params.scoreData.score); } @@ -136,14 +139,14 @@ class ResultState extends MusicBeatSubState bgFlash.scrollFactor.set(); bgFlash.visible = false; bgFlash.zIndex = 20; - bgFlash.cameras = [cameraBG]; + //bgFlash.cameras = [cameraBG]; add(bgFlash); // The sound system which falls into place behind the score text. Plays every time! var soundSystem:FlxSprite = FunkinSprite.createSparrow(-15, -180, 'resultScreen/soundSystem'); soundSystem.animation.addByPrefix("idle", "sound system", 24, false); soundSystem.visible = false; - new FlxTimer().start(0.3, _ -> { + new FlxTimer().start(8/24, _ -> { soundSystem.animation.play("idle"); soundSystem.visible = true; }); @@ -153,7 +156,22 @@ class ResultState extends MusicBeatSubState switch (rank) { case PERFECT | PERFECT_GOLD: - bfPerfect = new FlxAtlasSprite(370, -180, Paths.animateAtlas("resultScreen/results-bf/resultsPERFECT", "shared")); + heartsPerfect = new FlxAtlasSprite(1342, 370, Paths.animateAtlas("resultScreen/results-bf/resultsPERFECT/hearts", "shared")); + heartsPerfect.visible = false; + heartsPerfect.zIndex = 501; + add(heartsPerfect); + + heartsPerfect.anim.onComplete = () -> { + if (heartsPerfect != null) + { + //bfPerfect.anim.curFrame = 137; + heartsPerfect.anim.curFrame = 43; + heartsPerfect.anim.play(); // unpauses this anim, since it's on PlayOnce! + } + }; + + + bfPerfect = new FlxAtlasSprite(1342, 370, Paths.animateAtlas("resultScreen/results-bf/resultsPERFECT", "shared")); bfPerfect.visible = false; bfPerfect.zIndex = 500; add(bfPerfect); @@ -161,36 +179,57 @@ class ResultState extends MusicBeatSubState bfPerfect.anim.onComplete = () -> { if (bfPerfect != null) { + //bfPerfect.anim.curFrame = 137; bfPerfect.anim.curFrame = 137; bfPerfect.anim.play(); // unpauses this anim, since it's on PlayOnce! } }; case EXCELLENT: - bfExcellent = new FlxAtlasSprite(380, -170, Paths.animateAtlas("resultScreen/results-bf/resultsEXCELLENT", "shared")); + bfExcellent = new FlxAtlasSprite(1329, 429, Paths.animateAtlas("resultScreen/results-bf/resultsEXCELLENT", "shared")); bfExcellent.visible = false; bfExcellent.zIndex = 500; add(bfExcellent); - bfExcellent.onAnimationFinish.add((animName) -> { + bfExcellent.anim.onComplete = () -> { if (bfExcellent != null) { - bfExcellent.playAnimation('Loop Start'); + bfExcellent.anim.curFrame = 28; + bfExcellent.anim.play(); // unpauses this anim, since it's on PlayOnce! } - }); + }; + case GREAT: - bfGreat = new FlxAtlasSprite(640, 200, Paths.animateAtlas("resultScreen/results-bf/resultsGREAT", "shared")); + gfGreat = new FlxAtlasSprite(802, 331, Paths.animateAtlas("resultScreen/results-bf/resultsGREAT/gf", "shared")); + gfGreat.visible = false; + gfGreat.zIndex = 499; + add(gfGreat); + + gfGreat.scale.set(0.93, 0.93); + + gfGreat.anim.onComplete = () -> { + if (gfGreat != null) + { + gfGreat.anim.curFrame = 9; + gfGreat.anim.play(); // unpauses this anim, since it's on PlayOnce! + } + }; + + bfGreat = new FlxAtlasSprite(929, 363, Paths.animateAtlas("resultScreen/results-bf/resultsGREAT/bf", "shared")); bfGreat.visible = false; bfGreat.zIndex = 500; add(bfGreat); - bfGreat.onAnimationFinish.add((animName) -> { + bfGreat.scale.set(0.93, 0.93); + + bfGreat.anim.onComplete = () -> { if (bfGreat != null) { - bfGreat.playAnimation('Loop Start'); + bfGreat.anim.curFrame = 15; + bfGreat.anim.play(); // unpauses this anim, since it's on PlayOnce! } - }); + }; case GOOD: gfGood = FunkinSprite.createSparrow(625, 325, 'resultScreen/results-bf/resultsGOOD/resultGirlfriendGOOD'); @@ -250,7 +289,7 @@ class ResultState extends MusicBeatSubState var blackTopBar:FlxSprite = new FlxSprite().loadGraphic(Paths.image("resultScreen/topBarBlack")); blackTopBar.y = -blackTopBar.height; - FlxTween.tween(blackTopBar, {y: 0}, 0.4, {ease: FlxEase.quartOut}); + FlxTween.tween(blackTopBar, {y: 0}, 7/24, {ease: FlxEase.quartOut, startDelay: 3/24}); blackTopBar.zIndex = 1010; add(blackTopBar); @@ -258,7 +297,7 @@ class ResultState extends MusicBeatSubState resultsAnim.visible = false; resultsAnim.zIndex = 1200; add(resultsAnim); - new FlxTimer().start(0.3, _ -> { + new FlxTimer().start(6/24, _ -> { resultsAnim.visible = true; resultsAnim.animation.play("result"); }); @@ -267,7 +306,7 @@ class ResultState extends MusicBeatSubState ratingsPopin.visible = false; ratingsPopin.zIndex = 1200; add(ratingsPopin); - new FlxTimer().start(1.0, _ -> { + new FlxTimer().start(21/24, _ -> { ratingsPopin.visible = true; ratingsPopin.animation.play("idle"); }); @@ -276,23 +315,49 @@ class ResultState extends MusicBeatSubState scorePopin.visible = false; scorePopin.zIndex = 1200; add(scorePopin); - new FlxTimer().start(1.0, _ -> { + new FlxTimer().start(36/24, _ -> { scorePopin.visible = true; scorePopin.animation.play("score"); scorePopin.animation.finishCallback = anim -> { - score.visible = true; - score.animateNumbers(); + }; }); + new FlxTimer().start(37/24, _ -> { + score.visible = true; + score.animateNumbers(); + startRankTallySequence(); + }); + + new FlxTimer().start(rank.getBFDelay(), _ -> { + afterRankTallySequence(); + }); + + new FlxTimer().start(rank.getFlashDelay(), _ -> { + displayRankText(); + }); + highscoreNew.frames = Paths.getSparrowAtlas("resultScreen/highscoreNew"); - highscoreNew.animation.addByPrefix("new", "NEW HIGHSCORE", 24); + highscoreNew.animation.addByPrefix("new", "highscoreAnim0", 24, false); highscoreNew.visible = false; - highscoreNew.setGraphicSize(Std.int(highscoreNew.width * 0.8)); + //highscoreNew.setGraphicSize(Std.int(highscoreNew.width * 0.8)); highscoreNew.updateHitbox(); highscoreNew.zIndex = 1200; add(highscoreNew); + new FlxTimer().start(rank.getHighscoreDelay(), _ -> { + if (params.isNewHighscore ?? false) + { + highscoreNew.visible = true; + highscoreNew.animation.play("new"); + highscoreNew.animation.finishCallback = _ -> highscoreNew.animation.play("new", true, false, 16); + } + else + { + highscoreNew.visible = false; + } + }); + var hStuf:Int = 50; var ratingGrp:FlxTypedGroup = new FlxTypedGroup(); @@ -310,7 +375,10 @@ class ResultState extends MusicBeatSubState ratingGrp.add(maxCombo); hStuf += 2; - var extraYOffset:Float = 5; + var extraYOffset:Float = 7; + + hStuf += 2; + var tallySick:TallyCounter = new TallyCounter(230, (hStuf * 5) + extraYOffset, params.scoreData.tallies.sick, 0xFF89E59E); ratingGrp.add(tallySick); @@ -339,20 +407,17 @@ class ResultState extends MusicBeatSubState }); } - ratingsPopin.animation.finishCallback = anim -> { - startRankTallySequence(); - if (params.isNewHighscore ?? false) - { - highscoreNew.visible = true; - highscoreNew.animation.play("new"); - FlxTween.tween(highscoreNew, {y: highscoreNew.y + 10}, 0.8, {ease: FlxEase.quartOut}); - } - else - { - highscoreNew.visible = false; - } - }; + // if (params.isNewHighscore ?? false) + // { + // highscoreNew.visible = true; + // highscoreNew.animation.play("new"); + // //FlxTween.tween(highscoreNew, {y: highscoreNew.y + 10}, 0.8, {ease: FlxEase.quartOut}); + // } + // else + // { + // highscoreNew.visible = false; + // } new FlxTimer().start(rank.getMusicDelay(), _ -> { if (rank.hasMusicIntro()) @@ -392,6 +457,8 @@ class ResultState extends MusicBeatSubState function startRankTallySequence():Void { + bgFlash.visible = true; + FlxTween.tween(bgFlash, {alpha: 0}, 5/24); var clearPercentFloat = (params.scoreData.tallies.sick + params.scoreData.tallies.good) / params.scoreData.tallies.totalNotes * 100; clearPercentTarget = Math.floor(clearPercentFloat); // Prevent off-by-one errors. @@ -400,8 +467,8 @@ class ResultState extends MusicBeatSubState trace('Clear percent target: ' + clearPercentFloat + ', round: ' + clearPercentTarget); - var clearPercentCounter:ClearPercentCounter = new ClearPercentCounter(FlxG.width / 2 + 300, FlxG.height / 2 - 100, clearPercentLerp); - FlxTween.tween(clearPercentCounter, {curNumber: clearPercentTarget}, 1.5, + var clearPercentCounter:ClearPercentCounter = new ClearPercentCounter(FlxG.width / 2 + 190, FlxG.height / 2 - 70, clearPercentLerp); + FlxTween.tween(clearPercentCounter, {curNumber: clearPercentTarget}, 58/24, { ease: FlxEase.quartOut, onUpdate: _ -> { @@ -416,10 +483,6 @@ class ResultState extends MusicBeatSubState // Play confirm sound. FunkinSound.playOnce(Paths.sound('confirmMenu')); - // Flash background. - bgFlash.visible = true; - FlxTween.tween(bgFlash, {alpha: 0}, 0.4); - // Just to be sure that the lerp didn't mess things up. clearPercentCounter.curNumber = clearPercentTarget; @@ -428,7 +491,7 @@ class ResultState extends MusicBeatSubState clearPercentCounter.flash(false); }); - displayRankText(); + //displayRankText(); // previously 2.0 seconds new FlxTimer().start(0.25, _ -> { @@ -441,7 +504,7 @@ class ResultState extends MusicBeatSubState } }); - afterRankTallySequence(); + //afterRankTallySequence(); }); } }); @@ -466,7 +529,6 @@ class ResultState extends MusicBeatSubState { highscoreNew.visible = true; highscoreNew.animation.play("new"); - FlxTween.tween(highscoreNew, {y: highscoreNew.y + 10}, 0.8, {ease: FlxEase.quartOut}); } else { @@ -480,27 +542,36 @@ class ResultState extends MusicBeatSubState function displayRankText():Void { + bgFlash.visible = true; + bgFlash.alpha = 1; + FlxTween.tween(bgFlash, {alpha: 0}, 14/24); + var rankTextVert:FlxBackdrop = new FlxBackdrop(Paths.image(rank.getVerTextAsset()), Y, 0, 30); - rankTextVert.x = FlxG.width - 64; + rankTextVert.x = FlxG.width - 44; rankTextVert.y = 100; rankTextVert.zIndex = 990; add(rankTextVert); + FlxFlicker.flicker(rankTextVert, 2/24 * 3, 2/24, true); + // Scrolling. - rankTextVert.velocity.y = -50; + new FlxTimer().start(30/24, _ -> { + rankTextVert.velocity.y = -80; + }); + - for (i in 0...10) + for (i in 0...12) { var rankTextBack:FlxBackdrop = new FlxBackdrop(Paths.image(rank.getHorTextAsset()), X, 10, 0); rankTextBack.x = FlxG.width / 2 - 320; - rankTextBack.y = 50 + (150 * i / 2) + 10; + rankTextBack.y = 50 + (135 * i / 2) + 10; // rankTextBack.angle = -3.8; rankTextBack.zIndex = 100; rankTextBack.cameras = [cameraScroll]; add(rankTextBack); // Scrolling. - rankTextBack.velocity.x = (i % 2 == 0) ? -10.0 : 10.0; + rankTextBack.velocity.x = (i % 2 == 0) ? -7.0 : 7.0; } refresh(); @@ -508,6 +579,7 @@ class ResultState extends MusicBeatSubState function afterRankTallySequence():Void { + showSmallClearPercent(); switch (rank) @@ -522,6 +594,17 @@ class ResultState extends MusicBeatSubState bfPerfect.visible = true; bfPerfect.playAnimation(''); } + new FlxTimer().start(106 / 24, _ -> { + if (heartsPerfect == null) + { + trace("Could not build heartsPerfect animation!"); + } + else + { + heartsPerfect.visible = true; + heartsPerfect.playAnimation(''); + } + }); case EXCELLENT: if (bfExcellent == null) { @@ -530,7 +613,7 @@ class ResultState extends MusicBeatSubState else { bfExcellent.visible = true; - bfExcellent.playAnimation('Intro'); + bfExcellent.playAnimation(''); } case GREAT: if (bfGreat == null) @@ -540,8 +623,20 @@ class ResultState extends MusicBeatSubState else { bfGreat.visible = true; - bfGreat.playAnimation('Intro'); + bfGreat.playAnimation(''); + } + + new FlxTimer().start(6 / 24, _ -> { + if (gfGreat == null) + { + trace("Could not build GREAT animation for gf!"); + } + else + { + gfGreat.visible = true; + gfGreat.playAnimation(''); } + }); case SHIT: if (bfShit == null) { @@ -627,7 +722,9 @@ class ResultState extends MusicBeatSubState refresh(); } - movingSongStuff = true; + new FlxTimer().start(2.5, _ -> { + movingSongStuff = true; + }); } var movingSongStuff:Bool = false; @@ -647,6 +744,79 @@ class ResultState extends MusicBeatSubState override function update(elapsed:Float):Void { + // if(FlxG.keys.justPressed.R){ + // FlxG.switchState(() -> new funkin.play.ResultState( + // { + // storyMode: false, + // title: "Cum Song Erect by Kawai Sprite", + // songId: "cum", + // difficultyId: "nightmare", + // isNewHighscore: true, + // scoreData: + // { + // score: 1_234_567, + // tallies: + // { + // sick: 200, + // good: 0, + // bad: 0, + // shit: 0, + // missed: 0, + // combo: 0, + // maxCombo: 69, + // totalNotesHit: 200, + // totalNotes: 200 // 0, + // } + // }, + // })); + // } + + // if(heartsPerfect != null){ + // if (FlxG.keys.justPressed.I) + // { + // heartsPerfect.y -= 1; + // trace(heartsPerfect.x, heartsPerfect.y); + // } + // if (FlxG.keys.justPressed.J) + // { + // heartsPerfect.x -= 1; + // trace(heartsPerfect.x, heartsPerfect.y); + // } + // if (FlxG.keys.justPressed.L) + // { + // heartsPerfect.x += 1; + // trace(heartsPerfect.x, heartsPerfect.y); + // } + // if (FlxG.keys.justPressed.K) + // { + // heartsPerfect.y += 1; + // trace(heartsPerfect.x, heartsPerfect.y); + // } + // } + + // if(bfGreat != null){ + // if (FlxG.keys.justPressed.W) + // { + // bfGreat.y -= 1; + // trace(bfGreat.x, bfGreat.y); + // } + // if (FlxG.keys.justPressed.A) + // { + // bfGreat.x -= 1; + // trace(bfGreat.x, bfGreat.y); + // } + // if (FlxG.keys.justPressed.D) + // { + // bfGreat.x += 1; + // trace(bfGreat.x, bfGreat.y); + // } + // if (FlxG.keys.justPressed.S) + // { + // bfGreat.y += 1; + // trace(bfGreat.x, bfGreat.y); + // } + // } + // maskShaderSongName.swagSprX = songName.x; maskShaderDifficulty.swagSprX = difficulty.x; diff --git a/source/funkin/play/scoring/Scoring.hx b/source/funkin/play/scoring/Scoring.hx index 6155ec8798..04bd81cf84 100644 --- a/source/funkin/play/scoring/Scoring.hx +++ b/source/funkin/play/scoring/Scoring.hx @@ -403,9 +403,75 @@ enum abstract ScoringRank(String) { case PERFECT_GOLD | PERFECT: // return 2.5; - return 5.0; + return 95/24; case EXCELLENT: - return 1.75; + return 0; + case GREAT: + return 5/24; + case GOOD: + return 3/24; + case SHIT: + return 2/24; + default: + return 3.5; + } + } + + public function getBFDelay():Float + { + switch (abstract) + { + case PERFECT_GOLD | PERFECT: + // return 2.5; + return 95/24; + case EXCELLENT: + return 97/24; + case GREAT: + return 95/24; + case GOOD: + return 95/24; + case SHIT: + return 95/24; + default: + return 3.5; + } + } + + public function getFlashDelay():Float + { + switch (abstract) + { + case PERFECT_GOLD | PERFECT: + // return 2.5; + return 129/24; + case EXCELLENT: + return 122/24; + case GREAT: + return 109/24; + case GOOD: + return 107/24; + case SHIT: + return 186/24; + default: + return 3.5; + } + } + + public function getHighscoreDelay():Float + { + switch (abstract) + { + case PERFECT_GOLD | PERFECT: + // return 2.5; + return 140/24; + case EXCELLENT: + return 140/24; + case GREAT: + return 129/24; + case GOOD: + return 127/24; + case SHIT: + return 207/24; default: return 3.5; } From b8920effdcae5b2155a5a9a25e365dd500f9c705 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Sat, 1 Jun 2024 01:17:58 +0100 Subject: [PATCH 148/216] assets submod.. --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 7a0d92d300..de73a8ec8b 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 7a0d92d3007de42c452b2ea97a917d8c8d114ee7 +Subproject commit de73a8ec8b7462beedca5c2eb539aea38d4c7712 From fd28c91e75b949976bc074d0cd1d0cde5c97b6f4 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 31 May 2024 21:21:46 -0400 Subject: [PATCH 149/216] Update assets submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 7a0d92d300..59d376218d 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 7a0d92d3007de42c452b2ea97a917d8c8d114ee7 +Subproject commit 59d376218d288ef3001de6ef78b8d6d7c5f52842 From 12acdcd9d9cb4cf1a65e5598f421ecca962f33a3 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 31 May 2024 21:55:27 -0400 Subject: [PATCH 150/216] Fix a Results->Freeplay crash --- source/funkin/ui/freeplay/FreeplayState.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 192c6e3ce1..1bde92667e 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -868,7 +868,7 @@ class FreeplayState extends MusicBeatSubState FlxTween.tween(grpCapsules.members[curSelected].ranking, {"scale.x": 1, "scale.y": 1}, 0.1); - grpCapsules.members[curSelected].blurredRanking.animation.play(grpCapsules.members[curSelected].blurredRanking.animation.curAnim.name, true); + grpCapsules.members[curSelected].blurredRanking.animation.play(fromResults.newRank.getFreeplayRankIconAsset(), true); FlxTween.tween(grpCapsules.members[curSelected].blurredRanking, {"scale.x": 1, "scale.y": 1}, 0.1); new FlxTimer().start(0.1, _ -> { From 6851edc64b89ce960d34975af1cf2ce6699e5996 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 31 May 2024 21:55:33 -0400 Subject: [PATCH 151/216] Add new charts --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 59d376218d..0e5a66cb15 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 59d376218d288ef3001de6ef78b8d6d7c5f52842 +Subproject commit 0e5a66cb15229fde2c65503ba1267dfc7b4640b5 From e4eb9a7dc90f40ef667d78c027daecf58832819a Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sat, 1 Jun 2024 16:23:22 -0400 Subject: [PATCH 152/216] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 0e5a66cb15..3bfa4e3da8 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 0e5a66cb15229fde2c65503ba1267dfc7b4640b5 +Subproject commit 3bfa4e3da87713ea651f60d4f898c283e5d86093 From bd7875e86a9a3aabe11d9e6679579540ac011189 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sat, 1 Jun 2024 17:13:07 -0400 Subject: [PATCH 153/216] fix rank icons appearing when they shouldn't be --- source/funkin/play/scoring/Scoring.hx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/funkin/play/scoring/Scoring.hx b/source/funkin/play/scoring/Scoring.hx index 6155ec8798..a6d92454bd 100644 --- a/source/funkin/play/scoring/Scoring.hx +++ b/source/funkin/play/scoring/Scoring.hx @@ -351,6 +351,9 @@ class Scoring { if (scoreData == null) return null; + // we can return null here, meaning that the player hasn't actually played and finished the song (thus has no data) + if (scoreData.tallies.totalNotes == 0) return null; + // Perfect (Platinum) is a Sick Full Clear var isPerfectGold = scoreData.tallies.sick == scoreData.tallies.totalNotes; if (isPerfectGold) return ScoringRank.PERFECT_GOLD; From 63bd6f2ace9c093133f1c7e1c02de60ad969aa4a Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Sun, 2 Jun 2024 00:25:52 +0100 Subject: [PATCH 154/216] sparks nd more fixes.. i think --- source/funkin/play/ResultState.hx | 9 +- source/funkin/ui/freeplay/FreeplayState.hx | 194 +++++++++++++++------ source/funkin/ui/freeplay/SongMenuItem.hx | 15 ++ 3 files changed, 164 insertions(+), 54 deletions(-) diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index 1ad19b41e1..d38731e148 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -364,7 +364,7 @@ class ResultState extends MusicBeatSubState rankBg.zIndex = 99999; add(rankBg); - rankBg.alpha = 0; + rankBg.alpha = 0; refresh(); @@ -665,8 +665,7 @@ class ResultState extends MusicBeatSubState else { var rigged:Bool = true; - if (rank > Scoring.calculateRank(params?.prevScoreData)) - //if (rigged) + if (rank > Scoring.calculateRank(params?.prevScoreData)) // if (rigged) { trace('THE RANK IS Higher.....'); @@ -682,7 +681,8 @@ class ResultState extends MusicBeatSubState oldRank: Scoring.calculateRank(params?.prevScoreData), newRank: rank, songId: params.songId, - difficultyId: params.difficultyId + difficultyId: params.difficultyId, + playRankAnim: true } } })); @@ -698,6 +698,7 @@ class ResultState extends MusicBeatSubState fromResults: { oldRank: null, + playRankAnim: false, newRank: rank, songId: params.songId, difficultyId: params.difficultyId diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 186c84c338..e1d8eb81ce 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -6,6 +6,7 @@ import flixel.addons.ui.FlxInputText; import flixel.FlxCamera; import flixel.FlxSprite; import flixel.group.FlxGroup; +import funkin.graphics.shaders.GaussianBlurShader; import flixel.group.FlxGroup.FlxTypedGroup; import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup; import flixel.input.touch.FlxTouch; @@ -45,6 +46,7 @@ import funkin.util.MathUtil; import lime.utils.Assets; import flixel.tweens.misc.ShakeTween; import funkin.effects.IntervalShake; +import funkin.ui.freeplay.SongMenuItem.FreeplayRank; /** * Parameters used to initialize the FreeplayState. @@ -66,6 +68,11 @@ typedef FromResultsParams = */ var ?oldRank:ScoringRank; + /** + * Whether or not to play the rank animation on returning to freeplay. + */ + var playRankAnim:Bool; + /** * The new rank the song has. */ @@ -201,7 +208,8 @@ class FreeplayState extends MusicBeatSubState fromResultsParams = params?.fromResults; - if(fromResultsParams?.oldRank != null){ + if (fromResultsParams?.playRankAnim == true) + { prepForNewRank = true; } @@ -244,10 +252,10 @@ class FreeplayState extends MusicBeatSubState if (prepForNewRank == false) { FunkinSound.playMusic('freakyMenu', - { - overrideExisting: true, - restartTrack: false - }); + { + overrideExisting: true, + restartTrack: false + }); } // Add a null entry that represents the RANDOM option @@ -837,6 +845,9 @@ class FreeplayState extends MusicBeatSubState return songsToFilter; } + var sparks:FlxSprite; + var sparksADD:FlxSprite; + function rankAnimStart(fromResults:Null):Void { busy = true; @@ -848,6 +859,49 @@ class FreeplayState extends MusicBeatSubState FlxG.sound.music.volume = 0; rankBg.alpha = 1; + if (fromResults?.oldRank != null) + { + grpCapsules.members[curSelected].fakeRanking.rank = fromResults.oldRank; + grpCapsules.members[curSelected].fakeBlurredRanking.rank = fromResults.oldRank; + + sparks = new FlxSprite(0, 0); + sparks.frames = Paths.getSparrowAtlas('freeplay/sparks'); + sparks.animation.addByPrefix('sparks', 'sparks', 24, false); + sparks.visible = false; + sparks.blend = BlendMode.ADD; + sparks.setPosition(517, 134); + sparks.scale.set(0.5, 0.5); + add(sparks); + sparks.cameras = [rankCamera]; + + sparksADD = new FlxSprite(0, 0); + sparksADD.visible = false; + sparksADD.frames = Paths.getSparrowAtlas('freeplay/sparksadd'); + sparksADD.animation.addByPrefix('sparks add', 'sparks add', 24, false); + sparksADD.setPosition(498, 116); + sparksADD.blend = BlendMode.ADD; + sparksADD.scale.set(0.5, 0.5); + add(sparksADD); + sparksADD.cameras = [rankCamera]; + + switch (fromResults.oldRank) + { + case SHIT: + sparksADD.color = 0xFF6044FF; + case GOOD: + sparksADD.color = 0xFFEF8764; + case GREAT: + sparksADD.color = 0xFFEAF6FF; + case EXCELLENT: + sparksADD.color = 0xFFFDCB42; + case PERFECT: + sparksADD.color = 0xFFFF58B4; + case PERFECT_GOLD: + sparksADD.color = 0xFFFFB619; + } + // sparksADD.color = sparks.color; + } + grpCapsules.members[curSelected].doLerp = false; // originalPos.x = grpCapsules.members[curSelected].x; @@ -857,8 +911,8 @@ class FreeplayState extends MusicBeatSubState originalPos.y = 235.6; trace(originalPos); - grpCapsules.members[curSelected].ranking.alpha = 0; - grpCapsules.members[curSelected].blurredRanking.alpha = 0; + grpCapsules.members[curSelected].ranking.visible = false; + grpCapsules.members[curSelected].blurredRanking.visible = false; rankCamera.zoom = 1.85; FlxTween.tween(rankCamera, {"zoom": 1.8}, 0.6, {ease: FlxEase.sineIn}); @@ -880,9 +934,8 @@ class FreeplayState extends MusicBeatSubState function rankDisplayNew(fromResults:Null):Void { - grpCapsules.members[curSelected].ranking.alpha = 1; - grpCapsules.members[curSelected].blurredRanking.alpha = 1; - + grpCapsules.members[curSelected].ranking.visible = true; + grpCapsules.members[curSelected].blurredRanking.visible = true; grpCapsules.members[curSelected].ranking.scale.set(20, 20); grpCapsules.members[curSelected].blurredRanking.scale.set(20, 20); @@ -895,7 +948,23 @@ class FreeplayState extends MusicBeatSubState FlxTween.tween(grpCapsules.members[curSelected].blurredRanking, {"scale.x": 1, "scale.y": 1}, 0.1); new FlxTimer().start(0.1, _ -> { - trace(grpCapsules.members[curSelected].ranking.rank); + // trace(grpCapsules.members[curSelected].ranking.rank); + if (fromResults?.oldRank != null) + { + grpCapsules.members[curSelected].fakeRanking.visible = false; + grpCapsules.members[curSelected].fakeBlurredRanking.visible = false; + + sparks.visible = true; + sparksADD.visible = true; + sparks.animation.play('sparks', true); + sparksADD.animation.play('sparks add', true); + + sparks.animation.finishCallback = anim -> { + sparks.visible = false; + sparksADD.visible = false; + }; + } + switch (fromResultsParams?.newRank) { case SHIT: @@ -1053,10 +1122,10 @@ class FreeplayState extends MusicBeatSubState // dj.fistPump(); prepForNewRank = false; FunkinSound.playMusic('freakyMenu', - { - overrideExisting: true, - restartTrack: false - }); + { + overrideExisting: true, + restartTrack: false + }); FlxG.sound.music.fadeIn(4.0, 0.0, 1.0); }); } @@ -1092,35 +1161,56 @@ class FreeplayState extends MusicBeatSubState rankAnimStart(fromResultsParams); } - if (FlxG.keys.justPressed.H) - { - rankDisplayNew(fromResultsParams); - } + // if (FlxG.keys.justPressed.H) + // { + // rankDisplayNew(fromResultsParams); + // } + + // if (FlxG.keys.justPressed.G) + // { + // rankAnimSlam(fromResultsParams); + // } if (FlxG.keys.justPressed.G) { - rankAnimSlam(fromResultsParams); + sparks.y -= 2; + trace(sparks.x, sparks.y); + } + if (FlxG.keys.justPressed.V) + { + sparks.x -= 2; + trace(sparks.x, sparks.y); + } + if (FlxG.keys.justPressed.N) + { + sparks.x += 2; + trace(sparks.x, sparks.y); + } + if (FlxG.keys.justPressed.B) + { + sparks.y += 2; + trace(sparks.x, sparks.y); } if (FlxG.keys.justPressed.I) { - confirmTextGlow.y -= 1; - trace(confirmTextGlow.x, confirmTextGlow.y); + sparksADD.y -= 2; + trace(sparksADD.x, sparksADD.y); } if (FlxG.keys.justPressed.J) { - confirmTextGlow.x -= 1; - trace(confirmTextGlow.x, confirmTextGlow.y); + sparksADD.x -= 2; + trace(sparksADD.x, sparksADD.y); } if (FlxG.keys.justPressed.L) { - confirmTextGlow.x += 1; - trace(confirmTextGlow.x, confirmTextGlow.y); + sparksADD.x += 2; + trace(sparksADD.x, sparksADD.y); } if (FlxG.keys.justPressed.K) { - confirmTextGlow.y += 1; - trace(confirmTextGlow.x, confirmTextGlow.y); + sparksADD.y += 2; + trace(sparksADD.x, sparksADD.y); } #end @@ -1758,26 +1848,27 @@ class FreeplayState extends MusicBeatSubState } else { - if(prepForNewRank == false){ - var potentiallyErect:String = (currentDifficulty == "erect") || (currentDifficulty == "nightmare") ? "-erect" : ""; - // TODO: Stream the instrumental of the selected song? - FunkinSound.playMusic(daSongCapsule.songData.songId, - { - startingVolume: 0.0, - overrideExisting: true, - restartTrack: false, - pathsFunction: INST, - suffix: potentiallyErect, - partialParams: - { - loadPartial: true, - start: 0, - end: 0.1 - }, - onLoad: function() { - FlxG.sound.music.fadeIn(2, 0, 0.4); - } - }); + if (prepForNewRank == false) + { + var potentiallyErect:String = (currentDifficulty == "erect") || (currentDifficulty == "nightmare") ? "-erect" : ""; + // TODO: Stream the instrumental of the selected song? + FunkinSound.playMusic(daSongCapsule.songData.songId, + { + startingVolume: 0.0, + overrideExisting: true, + restartTrack: false, + pathsFunction: INST, + suffix: potentiallyErect, + partialParams: + { + loadPartial: true, + start: 0, + end: 0.1 + }, + onLoad: function() { + FlxG.sound.music.fadeIn(2, 0, 0.4); + } + }); } } grpCapsules.members[curSelected].selected = true; @@ -1791,9 +1882,12 @@ class FreeplayState extends MusicBeatSubState public static function build(?params:FreeplayStateParams, ?stickers:StickerSubState):MusicBeatState { var result:MainMenuState; - if(params?.fromResults.oldRank != null){ + if (params?.fromResults.playRankAnim == true) + { result = new MainMenuState(true); - }else{ + } + else + { result = new MainMenuState(false); } diff --git a/source/funkin/ui/freeplay/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx index b52032bc3f..3af75c1056 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -39,9 +39,13 @@ class SongMenuItem extends FlxSpriteGroup public var songText:CapsuleText; public var favIcon:FlxSprite; + public var ranking:FreeplayRank; public var blurredRanking:FreeplayRank; + public var fakeRanking:FreeplayRank; + public var fakeBlurredRanking:FreeplayRank; + var ranks:Array = ["fail", "average", "great", "excellent", "perfect", "perfectsick"]; public var targetPos:FlxPoint = new FlxPoint(); @@ -131,12 +135,23 @@ class SongMenuItem extends FlxSpriteGroup // doesn't get added, simply is here to help with visibility of things for the pop in! grpHide = new FlxGroup(); + fakeRanking = new FreeplayRank(420, 41); + add(fakeRanking); + + fakeBlurredRanking = new FreeplayRank(fakeRanking.x, fakeRanking.y); + fakeBlurredRanking.shader = new GaussianBlurShader(1); + add(fakeBlurredRanking); + + fakeRanking.visible = false; + fakeBlurredRanking.visible = false; + ranking = new FreeplayRank(420, 41); add(ranking); blurredRanking = new FreeplayRank(ranking.x, ranking.y); blurredRanking.shader = new GaussianBlurShader(1); add(blurredRanking); + // ranking.loadGraphic(Paths.image('freeplay/ranks/' + rank)); // ranking.scale.x = ranking.scale.y = realScaled; // ranking.alpha = 0.75; From b96fa51045f4cae5fa889eade75ac1f1c676034a Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Sun, 2 Jun 2024 00:26:13 +0100 Subject: [PATCH 155/216] assets submod!! --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index d64939d866..ad8a0a28ad 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit d64939d866c70a831b76ed78930782b66871dcc2 +Subproject commit ad8a0a28addb3153c01bca2f8a2fdea05c5ac9ea From 8248cffbafb1621b5c2811f01a02ee62bd3b48ee Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sat, 1 Jun 2024 20:36:14 -0400 Subject: [PATCH 156/216] small bool cleanings, and maybe fixes --- source/funkin/ui/freeplay/FreeplayState.hx | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index e1d8eb81ce..e97ab391b8 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1121,12 +1121,6 @@ class FreeplayState extends MusicBeatSubState new FlxTimer().start(2, _ -> { // dj.fistPump(); prepForNewRank = false; - FunkinSound.playMusic('freakyMenu', - { - overrideExisting: true, - restartTrack: false - }); - FlxG.sound.music.fadeIn(4.0, 0.0, 1.0); }); } @@ -1527,6 +1521,7 @@ class FreeplayState extends MusicBeatSubState overrideExisting: true, restartTrack: false }); + FlxG.sound.music.fadeIn(4.0, 0.0, 1.0); close(); } else @@ -1842,13 +1837,13 @@ class FreeplayState extends MusicBeatSubState { startingVolume: 0.0, overrideExisting: true, - restartTrack: true + restartTrack: false }); FlxG.sound.music.fadeIn(2, 0, 0.8); } else { - if (prepForNewRank == false) + if (!prepForNewRank) { var potentiallyErect:String = (currentDifficulty == "erect") || (currentDifficulty == "nightmare") ? "-erect" : ""; // TODO: Stream the instrumental of the selected song? @@ -1882,14 +1877,9 @@ class FreeplayState extends MusicBeatSubState public static function build(?params:FreeplayStateParams, ?stickers:StickerSubState):MusicBeatState { var result:MainMenuState; - if (params?.fromResults.playRankAnim == true) - { - result = new MainMenuState(true); - } + if (params?.fromResults.playRankAnim) result = new MainMenuState(true); else - { result = new MainMenuState(false); - } result.openSubState(new FreeplayState(params, stickers)); result.persistentUpdate = false; From 7aee1f900af2d19df18252a72eb382326b878c2f Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 31 May 2024 21:55:27 -0400 Subject: [PATCH 157/216] Fix a Results->Freeplay crash --- source/funkin/ui/freeplay/FreeplayState.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index e97ab391b8..0dd520ee31 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -944,7 +944,7 @@ class FreeplayState extends MusicBeatSubState FlxTween.tween(grpCapsules.members[curSelected].ranking, {"scale.x": 1, "scale.y": 1}, 0.1); - grpCapsules.members[curSelected].blurredRanking.animation.play(grpCapsules.members[curSelected].blurredRanking.animation.curAnim.name, true); + grpCapsules.members[curSelected].blurredRanking.animation.play(fromResults.newRank.getFreeplayRankIconAsset(), true); FlxTween.tween(grpCapsules.members[curSelected].blurredRanking, {"scale.x": 1, "scale.y": 1}, 0.1); new FlxTimer().start(0.1, _ -> { From 7c6c51ea71d8c8790a3ba742e0b7b5724ad33197 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sat, 1 Jun 2024 22:36:47 -0400 Subject: [PATCH 158/216] results dupe fix --- source/funkin/ui/freeplay/FreeplayState.hx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 6441c9cd58..218ecc2ab3 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -712,12 +712,6 @@ class FreeplayState extends MusicBeatSubState // If curSelected is 0, the result will be null and fall back to the rememberedSongId. rememberedSongId = grpCapsules.members[curSelected]?.songData?.songId ?? rememberedSongId; - if (fromResultsParams != null) - { - rememberedSongId = fromResultsParams.songId; - rememberedDifficulty = fromResultsParams.difficultyId; - } - for (cap in grpCapsules.members) { cap.songText.resetText(); @@ -828,6 +822,14 @@ class FreeplayState extends MusicBeatSubState { busy = true; + if (fromResults != null) + { + rememberedSongId = fromResults.songId; + rememberedDifficulty = fromResults.difficultyId; + changeSelection(); + changeDiff(); + } + dj.fistPump(); // rankCamera.fade(FlxColor.BLACK, 0.5, true); rankCamera.fade(0xFF000000, 0.5, true, null, true); From 51a44d481056b5846ed23c97af5f6547ff99ae76 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sat, 1 Jun 2024 23:36:57 -0400 Subject: [PATCH 159/216] persistent draw false for results screen (fixes FUNK-256) --- source/funkin/play/PlayState.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 478a132690..af3281c4bb 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -3144,7 +3144,7 @@ class PlayState extends MusicBeatSubState }, isNewHighscore: isNewHighscore }); - res.camera = camHUD; + this.persistentDraw = false; openSubState(res); } From 08f3b1d95b99ce84907fcf74bc12a68c699dc8a8 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sun, 2 Jun 2024 00:15:10 -0400 Subject: [PATCH 160/216] anim fixes on results --- source/funkin/play/ResultState.hx | 1 + 1 file changed, 1 insertion(+) diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index 8b8c0aea33..35976c3590 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -123,6 +123,7 @@ class ResultState extends MusicBeatSubState FlxG.cameras.add(cameraEverything, false); FlxG.cameras.setDefaultDrawTarget(cameraEverything, true); + this.camera = cameraEverything; // Reset the camera zoom on the results screen. FlxG.camera.zoom = 1.0; From f961ac8e4e55e4d9b9f4250b6c123869a6d1a96a Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sun, 2 Jun 2024 02:11:06 -0400 Subject: [PATCH 161/216] Actually fix a crash bug on Freeplay menu when selecting a mod --- hmm.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/hmm.json b/hmm.json index fe4e56dd90..f94b662ac9 100644 --- a/hmm.json +++ b/hmm.json @@ -1,12 +1,5 @@ { "dependencies": [ - { - "name": "FlxPartialSound", - "type": "git", - "dir": null, - "ref": "44aa7eb", - "url": "https://github.com/FunkinCrew/FlxPartialSound.git" - }, { "name": "discord_rpc", "type": "git", @@ -47,6 +40,13 @@ "ref": "17e0d59fdbc2b6283a5c0e4df41f1c7f27b71c49", "url": "https://github.com/FunkinCrew/flxanimate" }, + { + "name": "FlxPartialSound", + "type": "git", + "dir": null, + "ref": "f986332ba5ab02abd386ce662578baf04904604a", + "url": "https://github.com/FunkinCrew/FlxPartialSound.git" + }, { "name": "format", "type": "haxelib", From 75621435ea870d80532a66cbf13f60bd361811e3 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sun, 2 Jun 2024 02:53:07 -0400 Subject: [PATCH 162/216] lil more polish to fav icon + clipping --- source/funkin/ui/freeplay/FreeplayState.hx | 11 ++++++----- source/funkin/ui/freeplay/SongMenuItem.hx | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index d3471eeb1c..494bc20f01 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -655,7 +655,7 @@ class FreeplayState extends MusicBeatSubState cardGlow.visible = true; FlxTween.tween(cardGlow, {alpha: 0, "scale.x": 1.2, "scale.y": 1.2}, 0.45, {ease: FlxEase.sineOut}); - if (prepForNewRank == true) + if (prepForNewRank) { rankAnimStart(fromResultsParams); } @@ -686,7 +686,7 @@ class FreeplayState extends MusicBeatSubState rankBg.cameras = [rankCamera]; rankBg.alpha = 0; - if (prepForNewRank == true) + if (prepForNewRank) { rankCamera.fade(0xFF000000, 0, false, null, true); } @@ -782,10 +782,8 @@ class FreeplayState extends MusicBeatSubState funnyMenu.hsvShader = hsvShader; funnyMenu.newText.animation.curAnim.curFrame = 45 - ((i * 4) % 45); - - funnyMenu.forcePosition(); - funnyMenu.checkClip(); + funnyMenu.forcePosition(); grpCapsules.add(funnyMenu); } @@ -1223,6 +1221,8 @@ class FreeplayState extends MusicBeatSubState grpCapsules.members[realShit].favIcon.visible = true; grpCapsules.members[realShit].favIcon.animation.play('fav'); FunkinSound.playOnce(Paths.sound('fav'), 1); + grpCapsules.members[realShit].checkClip(); + grpCapsules.members[realShit].selected = grpCapsules.members[realShit].selected; // set selected again, so it can run it's getter function to initialize movement busy = true; grpCapsules.members[realShit].doLerp = false; @@ -1244,6 +1244,7 @@ class FreeplayState extends MusicBeatSubState FunkinSound.playOnce(Paths.sound('unfav'), 1); new FlxTimer().start(0.2, _ -> { grpCapsules.members[realShit].favIcon.visible = false; + grpCapsules.members[realShit].checkClip(); }); busy = true; diff --git a/source/funkin/ui/freeplay/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx index 41010f0b5b..b9fef5a79f 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -266,7 +266,7 @@ class SongMenuItem extends FlxSpriteGroup var clipType:Int = 0; if (ranking.visible == true) clipType += 1; - if (favIcon.visible == true) clipType += 1; + if (favIcon.visible == true) clipType = 2; switch (clipType) { case 2: From 6596c47f473d935ca135b1e66c384d52007755b8 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 3 Jun 2024 14:03:30 -0400 Subject: [PATCH 163/216] fabs --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index d9ea5ebe5e..f7c418c52f 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit d9ea5ebe5e4db8584a8b1e1e16820b4d1527794c +Subproject commit f7c418c52f38769daf56521ee801df699ae5435b From e12a48b6fc2721086fa54b6deb3d7cd08130ae2b Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 3 Jun 2024 18:18:33 -0400 Subject: [PATCH 164/216] fabs code stuff and difficulty fixin --- assets | 2 +- source/funkin/play/ResultState.hx | 123 ++++++++++++++---------------- 2 files changed, 59 insertions(+), 66 deletions(-) diff --git a/assets b/assets index f7c418c52f..3766c3b670 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit f7c418c52f38769daf56521ee801df699ae5435b +Subproject commit 3766c3b6709f043e63d8eae66887159975891073 diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index 1740c0371a..6f540687f3 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -143,14 +143,14 @@ class ResultState extends MusicBeatSubState bgFlash.scrollFactor.set(); bgFlash.visible = false; bgFlash.zIndex = 20; - //bgFlash.cameras = [cameraBG]; + // bgFlash.cameras = [cameraBG]; add(bgFlash); // The sound system which falls into place behind the score text. Plays every time! var soundSystem:FlxSprite = FunkinSprite.createSparrow(-15, -180, 'resultScreen/soundSystem'); soundSystem.animation.addByPrefix("idle", "sound system", 24, false); soundSystem.visible = false; - new FlxTimer().start(8/24, _ -> { + new FlxTimer().start(8 / 24, _ -> { soundSystem.animation.play("idle"); soundSystem.visible = true; }); @@ -168,13 +168,12 @@ class ResultState extends MusicBeatSubState heartsPerfect.anim.onComplete = () -> { if (heartsPerfect != null) { - //bfPerfect.anim.curFrame = 137; + // bfPerfect.anim.curFrame = 137; heartsPerfect.anim.curFrame = 43; heartsPerfect.anim.play(); // unpauses this anim, since it's on PlayOnce! } }; - bfPerfect = new FlxAtlasSprite(1342, 370, Paths.animateAtlas("resultScreen/results-bf/resultsPERFECT", "shared")); bfPerfect.visible = false; bfPerfect.zIndex = 500; @@ -183,7 +182,7 @@ class ResultState extends MusicBeatSubState bfPerfect.anim.onComplete = () -> { if (bfPerfect != null) { - //bfPerfect.anim.curFrame = 137; + // bfPerfect.anim.curFrame = 137; bfPerfect.anim.curFrame = 137; bfPerfect.anim.play(); // unpauses this anim, since it's on PlayOnce! } @@ -203,7 +202,6 @@ class ResultState extends MusicBeatSubState } }; - case GREAT: gfGreat = new FlxAtlasSprite(802, 331, Paths.animateAtlas("resultScreen/results-bf/resultsGREAT/gf", "shared")); gfGreat.visible = false; @@ -273,7 +271,7 @@ class ResultState extends MusicBeatSubState }); } - var diffSpr:String = 'dif${params?.difficultyId ?? 'Normal'}'; + var diffSpr:String = 'diff_${params?.difficultyId ?? 'Normal'}'; difficulty.loadGraphic(Paths.image("resultScreen/" + diffSpr)); add(difficulty); @@ -293,7 +291,7 @@ class ResultState extends MusicBeatSubState var blackTopBar:FlxSprite = new FlxSprite().loadGraphic(Paths.image("resultScreen/topBarBlack")); blackTopBar.y = -blackTopBar.height; - FlxTween.tween(blackTopBar, {y: 0}, 7/24, {ease: FlxEase.quartOut, startDelay: 3/24}); + FlxTween.tween(blackTopBar, {y: 0}, 7 / 24, {ease: FlxEase.quartOut, startDelay: 3 / 24}); blackTopBar.zIndex = 1010; add(blackTopBar); @@ -301,7 +299,7 @@ class ResultState extends MusicBeatSubState resultsAnim.visible = false; resultsAnim.zIndex = 1200; add(resultsAnim); - new FlxTimer().start(6/24, _ -> { + new FlxTimer().start(6 / 24, _ -> { resultsAnim.visible = true; resultsAnim.animation.play("result"); }); @@ -310,7 +308,7 @@ class ResultState extends MusicBeatSubState ratingsPopin.visible = false; ratingsPopin.zIndex = 1200; add(ratingsPopin); - new FlxTimer().start(21/24, _ -> { + new FlxTimer().start(21 / 24, _ -> { ratingsPopin.visible = true; ratingsPopin.animation.play("idle"); }); @@ -319,15 +317,13 @@ class ResultState extends MusicBeatSubState scorePopin.visible = false; scorePopin.zIndex = 1200; add(scorePopin); - new FlxTimer().start(36/24, _ -> { + new FlxTimer().start(36 / 24, _ -> { scorePopin.visible = true; scorePopin.animation.play("score"); - scorePopin.animation.finishCallback = anim -> { - - }; + scorePopin.animation.finishCallback = anim -> {}; }); - new FlxTimer().start(37/24, _ -> { + new FlxTimer().start(37 / 24, _ -> { score.visible = true; score.animateNumbers(); startRankTallySequence(); @@ -344,22 +340,22 @@ class ResultState extends MusicBeatSubState highscoreNew.frames = Paths.getSparrowAtlas("resultScreen/highscoreNew"); highscoreNew.animation.addByPrefix("new", "highscoreAnim0", 24, false); highscoreNew.visible = false; - //highscoreNew.setGraphicSize(Std.int(highscoreNew.width * 0.8)); + // highscoreNew.setGraphicSize(Std.int(highscoreNew.width * 0.8)); highscoreNew.updateHitbox(); highscoreNew.zIndex = 1200; add(highscoreNew); new FlxTimer().start(rank.getHighscoreDelay(), _ -> { - if (params.isNewHighscore ?? false) - { - highscoreNew.visible = true; - highscoreNew.animation.play("new"); - highscoreNew.animation.finishCallback = _ -> highscoreNew.animation.play("new", true, false, 16); - } - else - { - highscoreNew.visible = false; - } + if (params.isNewHighscore ?? false) + { + highscoreNew.visible = true; + highscoreNew.animation.play("new"); + highscoreNew.animation.finishCallback = _ -> highscoreNew.animation.play("new", true, false, 16); + } + else + { + highscoreNew.visible = false; + } }); var hStuf:Int = 50; @@ -411,17 +407,16 @@ class ResultState extends MusicBeatSubState }); } - - // if (params.isNewHighscore ?? false) - // { - // highscoreNew.visible = true; - // highscoreNew.animation.play("new"); - // //FlxTween.tween(highscoreNew, {y: highscoreNew.y + 10}, 0.8, {ease: FlxEase.quartOut}); - // } - // else - // { - // highscoreNew.visible = false; - // } + // if (params.isNewHighscore ?? false) + // { + // highscoreNew.visible = true; + // highscoreNew.animation.play("new"); + // //FlxTween.tween(highscoreNew, {y: highscoreNew.y + 10}, 0.8, {ease: FlxEase.quartOut}); + // } + // else + // { + // highscoreNew.visible = false; + // } new FlxTimer().start(rank.getMusicDelay(), _ -> { if (rank.hasMusicIntro()) @@ -468,7 +463,7 @@ class ResultState extends MusicBeatSubState function startRankTallySequence():Void { bgFlash.visible = true; - FlxTween.tween(bgFlash, {alpha: 0}, 5/24); + FlxTween.tween(bgFlash, {alpha: 0}, 5 / 24); var clearPercentFloat = (params.scoreData.tallies.sick + params.scoreData.tallies.good) / params.scoreData.tallies.totalNotes * 100; clearPercentTarget = Math.floor(clearPercentFloat); // Prevent off-by-one errors. @@ -478,7 +473,7 @@ class ResultState extends MusicBeatSubState trace('Clear percent target: ' + clearPercentFloat + ', round: ' + clearPercentTarget); var clearPercentCounter:ClearPercentCounter = new ClearPercentCounter(FlxG.width / 2 + 190, FlxG.height / 2 - 70, clearPercentLerp); - FlxTween.tween(clearPercentCounter, {curNumber: clearPercentTarget}, 58/24, + FlxTween.tween(clearPercentCounter, {curNumber: clearPercentTarget}, 58 / 24, { ease: FlxEase.quartOut, onUpdate: _ -> { @@ -501,7 +496,7 @@ class ResultState extends MusicBeatSubState clearPercentCounter.flash(false); }); - //displayRankText(); + // displayRankText(); // previously 2.0 seconds new FlxTimer().start(0.25, _ -> { @@ -514,7 +509,7 @@ class ResultState extends MusicBeatSubState } }); - //afterRankTallySequence(); + // afterRankTallySequence(); }); } }); @@ -554,7 +549,7 @@ class ResultState extends MusicBeatSubState { bgFlash.visible = true; bgFlash.alpha = 1; - FlxTween.tween(bgFlash, {alpha: 0}, 14/24); + FlxTween.tween(bgFlash, {alpha: 0}, 14 / 24); var rankTextVert:FlxBackdrop = new FlxBackdrop(Paths.image(rank.getVerTextAsset()), Y, 0, 30); rankTextVert.x = FlxG.width - 44; @@ -562,14 +557,13 @@ class ResultState extends MusicBeatSubState rankTextVert.zIndex = 990; add(rankTextVert); - FlxFlicker.flicker(rankTextVert, 2/24 * 3, 2/24, true); + FlxFlicker.flicker(rankTextVert, 2 / 24 * 3, 2 / 24, true); // Scrolling. - new FlxTimer().start(30/24, _ -> { - rankTextVert.velocity.y = -80; + new FlxTimer().start(30 / 24, _ -> { + rankTextVert.velocity.y = -80; }); - for (i in 0...12) { var rankTextBack:FlxBackdrop = new FlxBackdrop(Paths.image(rank.getHorTextAsset()), X, 10, 0); @@ -589,7 +583,6 @@ class ResultState extends MusicBeatSubState function afterRankTallySequence():Void { - showSmallClearPercent(); switch (rank) @@ -605,15 +598,15 @@ class ResultState extends MusicBeatSubState bfPerfect.playAnimation(''); } new FlxTimer().start(106 / 24, _ -> { - if (heartsPerfect == null) - { - trace("Could not build heartsPerfect animation!"); - } - else - { - heartsPerfect.visible = true; - heartsPerfect.playAnimation(''); - } + if (heartsPerfect == null) + { + trace("Could not build heartsPerfect animation!"); + } + else + { + heartsPerfect.visible = true; + heartsPerfect.playAnimation(''); + } }); case EXCELLENT: if (bfExcellent == null) @@ -637,15 +630,15 @@ class ResultState extends MusicBeatSubState } new FlxTimer().start(6 / 24, _ -> { - if (gfGreat == null) - { - trace("Could not build GREAT animation for gf!"); - } - else - { - gfGreat.visible = true; - gfGreat.playAnimation(''); - } + if (gfGreat == null) + { + trace("Could not build GREAT animation for gf!"); + } + else + { + gfGreat.visible = true; + gfGreat.playAnimation(''); + } }); case SHIT: if (bfShit == null) From cd85bcf22264b9527848a2d2963206b898ee8bd2 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 3 Jun 2024 18:32:46 -0400 Subject: [PATCH 165/216] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 3766c3b670..1f3e2932eb 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 3766c3b6709f043e63d8eae66887159975891073 +Subproject commit 1f3e2932ebc3395eb484e364605c233166052868 From bc21f0c6063453e10e102411c7c69018d978c29e Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 3 Jun 2024 19:39:37 -0400 Subject: [PATCH 166/216] Update assets submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 1f3e2932eb..4039bd018d 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 1f3e2932ebc3395eb484e364605c233166052868 +Subproject commit 4039bd018d474994b44317b74cdd724b5f73b749 From c056c7276285b847e4ea969ccb3b38dd23fd60b6 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 4 Jun 2024 14:26:24 -0400 Subject: [PATCH 167/216] Implement advanced save data repair. --- source/funkin/save/Save.hx | 81 +++++++++++++++++++ .../funkin/save/migrator/SaveDataMigrator.hx | 1 + source/funkin/util/VersionUtil.hx | 5 +- 3 files changed, 86 insertions(+), 1 deletion(-) diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx index 7f25a8e014..7634c1f51b 100644 --- a/source/funkin/save/Save.hx +++ b/source/funkin/save/Save.hx @@ -732,6 +732,87 @@ class Save } } + public static function archiveBadSaveData(data:Dynamic):Void + { + // We want to save this somewhere so we can try to recover it for the user in the future! + + final RECOVERY_SLOT_START = 1000; + + writeToAvailableSlot(RECOVERY_SLOT_START, data); + } + + public static function debug_queryBadSaveData():Void + { + final RECOVERY_SLOT_START = 1000; + final RECOVERY_SLOT_END = 1100; + var firstBadSaveData = querySlotRange(RECOVERY_SLOT_START, RECOVERY_SLOT_END); + if (firstBadSaveData > 0) + { + trace('[SAVE] Found bad save data in slot ${firstBadSaveData}!'); + trace('We should look into recovery...'); + + trace(haxe.Json.stringify(fetchFromSlotRaw(firstBadSaveData))); + } + } + + static function fetchFromSlotRaw(slot:Int):Null + { + var targetSaveData = new FlxSave(); + targetSaveData.bind('$SAVE_NAME${slot}', SAVE_PATH); + if (targetSaveData.isEmpty()) return null; + return targetSaveData.data; + } + + static function writeToAvailableSlot(slot:Int, data:Dynamic):Void + { + trace('[SAVE] Finding slot to write data to (starting with ${slot})...'); + + var targetSaveData = new FlxSave(); + targetSaveData.bind('$SAVE_NAME${slot}', SAVE_PATH); + while (!targetSaveData.isEmpty()) + { + // Keep trying to bind to slots until we find an empty slot. + trace('[SAVE] Slot ${slot} is taken, continuing...'); + slot++; + targetSaveData.bind('$SAVE_NAME${slot}', SAVE_PATH); + } + + trace('[SAVE] Writing data to slot ${slot}...'); + targetSaveData.mergeData(data, true); + + trace('[SAVE] Data written to slot ${slot}!'); + } + + /** + * Return true if the given save slot is not empty. + * @param slot The slot number to check. + * @return Whether the slot is not empty. + */ + static function querySlot(slot:Int):Bool + { + var targetSaveData = new FlxSave(); + targetSaveData.bind('$SAVE_NAME${slot}', SAVE_PATH); + return !targetSaveData.isEmpty(); + } + + /** + * Return true if any of the slots in the given range is not empty. + * @param start The starting slot number to check. + * @param end The ending slot number to check. + * @return The first slot in the range that is not empty, or `-1` if none are. + */ + static function querySlotRange(start:Int, end:Int):Int + { + for (i in start...end) + { + if (querySlot(i)) + { + return i; + } + } + return -1; + } + static function fetchLegacySaveData():Null { trace("[SAVE] Checking for legacy save data..."); diff --git a/source/funkin/save/migrator/SaveDataMigrator.hx b/source/funkin/save/migrator/SaveDataMigrator.hx index 4fa9dd6b31..b7d278cc6e 100644 --- a/source/funkin/save/migrator/SaveDataMigrator.hx +++ b/source/funkin/save/migrator/SaveDataMigrator.hx @@ -36,6 +36,7 @@ class SaveDataMigrator { var message:String = 'Error migrating save data, expected ${Save.SAVE_DATA_VERSION}.'; lime.app.Application.current.window.alert(message, "Save Data Failure"); + Save.archiveBadSaveData(inputData); trace('[SAVE] ' + message); return new Save(Save.getDefault()); } diff --git a/source/funkin/util/VersionUtil.hx b/source/funkin/util/VersionUtil.hx index 18d7eafa66..b84b663414 100644 --- a/source/funkin/util/VersionUtil.hx +++ b/source/funkin/util/VersionUtil.hx @@ -39,13 +39,16 @@ class VersionUtil if (thx.Types.isAnonymousObject(versionData.version)) { // This is bad! versionData.version should be an array! - versionData.version = [versionData.version[0], versionData.version[1], versionData.version[2]]; + trace('[SAVE] Version data repair required! (got ${versionData.version})'); + var fixedVersionData = [versionData.version[0], versionData.version[1], versionData.version[2]]; + versionData.version = fixedVersionData; var fixedVersion:thx.semver.Version = versionData; return fixedVersion; } else { + trace('[SAVE] Version data repair not required (got ${version})'); // No need for repair. return version; } From d4712a8ef7ebc60318e47b6c70faca646a9d0830 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 4 Jun 2024 16:24:24 -0400 Subject: [PATCH 168/216] alphabetical filtering for freeplay non-all sort --- source/funkin/ui/freeplay/FreeplayState.hx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 494bc20f01..fe64a1e6f4 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -804,6 +804,13 @@ class FreeplayState extends MusicBeatSubState */ public function sortSongs(songsToFilter:Array, songFilter:SongFilter):Array { + var filterAlphabetically = function(a:FreeplaySongData, b:FreeplaySongData):Int { + if (a?.songName.toLowerCase() < b?.songName.toLowerCase()) return -1; + else if (a?.songName.toLowerCase() > b?.songName.toLowerCase()) return 1; + else + return 0; + }; + switch (songFilter.filterType) { case REGEXP: @@ -818,6 +825,8 @@ class FreeplayState extends MusicBeatSubState return filterRegexp.match(str.songName); }); + songsToFilter.sort(filterAlphabetically); + case STARTSWITH: // extra note: this is essentially a "search" @@ -832,9 +841,13 @@ class FreeplayState extends MusicBeatSubState if (str == null) return true; // Random return str.isFav; }); + + songsToFilter.sort(filterAlphabetically); + default: // return all on default } + return songsToFilter; } From 29a33c8815a1ca3e33a731f9d8d405a57041f102 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 4 Jun 2024 16:38:21 -0400 Subject: [PATCH 169/216] modifies behaviour of how the difficulty stars appear --- source/funkin/ui/freeplay/AlbumRoll.hx | 7 ++++--- source/funkin/ui/freeplay/DifficultyStars.hx | 11 ++++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/source/funkin/ui/freeplay/AlbumRoll.hx b/source/funkin/ui/freeplay/AlbumRoll.hx index 20cd913794..49c5887225 100644 --- a/source/funkin/ui/freeplay/AlbumRoll.hx +++ b/source/funkin/ui/freeplay/AlbumRoll.hx @@ -66,7 +66,7 @@ class AlbumRoll extends FlxSpriteGroup add(newAlbumArt); difficultyStars = new DifficultyStars(140, 39); - difficultyStars.stars.visible = false; + difficultyStars.visible = false; add(difficultyStars); } @@ -149,7 +149,7 @@ class AlbumRoll extends FlxSpriteGroup newAlbumArt.visible = true; newAlbumArt.playAnimation(animNames.get('$albumId-active'), false, false, false); - difficultyStars.stars.visible = false; + difficultyStars.visible = false; new FlxTimer().start(0.75, function(_) { // showTitle(); showStars(); @@ -172,6 +172,7 @@ class AlbumRoll extends FlxSpriteGroup */ public function showStars():Void { - difficultyStars.stars.visible = true; // true; + difficultyStars.visible = true; // true; + difficultyStars.flameCheck(); } } diff --git a/source/funkin/ui/freeplay/DifficultyStars.hx b/source/funkin/ui/freeplay/DifficultyStars.hx index 51526bcbec..e7a2b8888d 100644 --- a/source/funkin/ui/freeplay/DifficultyStars.hx +++ b/source/funkin/ui/freeplay/DifficultyStars.hx @@ -19,7 +19,7 @@ class DifficultyStars extends FlxSpriteGroup public var stars:FlxAtlasSprite; - var flames:FreeplayFlames; + public var flames:FreeplayFlames; var hsvShader:HSVShader; @@ -80,11 +80,16 @@ class DifficultyStars extends FlxSpriteGroup curDifficulty = difficulty - 1; } + flameCheck(); + + return difficulty; + } + + public function flameCheck():Void + { if (difficulty > 10) flames.flameCount = difficulty - 10; else flames.flameCount = 0; - - return difficulty; } function set_curDifficulty(value:Int):Int From 84d4d044d647fa3460ca484526cb3282a0c51930 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 4 Jun 2024 16:47:58 -0400 Subject: [PATCH 170/216] check clip width when text changes --- source/funkin/ui/freeplay/CapsuleText.hx | 20 ++++++++++++++++---- source/funkin/ui/freeplay/SongMenuItem.hx | 2 +- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/source/funkin/ui/freeplay/CapsuleText.hx b/source/funkin/ui/freeplay/CapsuleText.hx index c3fd51d1fd..c3bcdb09bb 100644 --- a/source/funkin/ui/freeplay/CapsuleText.hx +++ b/source/funkin/ui/freeplay/CapsuleText.hx @@ -58,12 +58,24 @@ class CapsuleText extends FlxSpriteGroup function set_clipWidth(value:Int):Int { resetText(); - if (whiteText.width > value) + checkClipWidth(value); + return clipWidth = value; + } + + /** + * Checks if the text if it's too long, and clips if it is + * @param wid + */ + function checkClipWidth(?wid:Int):Void + { + if (wid == null) wid = clipWidth; + + if (whiteText.width > wid) { tooLong = true; - blurredText.clipRect = new FlxRect(0, 0, value, blurredText.height); - whiteText.clipRect = new FlxRect(0, 0, value, whiteText.height); + blurredText.clipRect = new FlxRect(0, 0, wid, blurredText.height); + whiteText.clipRect = new FlxRect(0, 0, wid, whiteText.height); } else { @@ -72,7 +84,6 @@ class CapsuleText extends FlxSpriteGroup blurredText.clipRect = null; whiteText.clipRect = null; } - return clipWidth = value; } function set_text(value:String):String @@ -86,6 +97,7 @@ class CapsuleText extends FlxSpriteGroup blurredText.text = value; whiteText.text = value; + checkClipWidth(); whiteText.textField.filters = [ new openfl.filters.GlowFilter(0x00ccff, 1, 5, 5, 210, BitmapFilterQuality.MEDIUM), // new openfl.filters.BlurFilter(5, 5, BitmapFilterQuality.LOW) diff --git a/source/funkin/ui/freeplay/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx index b9fef5a79f..d40809fada 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -326,7 +326,7 @@ class SongMenuItem extends FlxSpriteGroup var evilTrail:FlxTrail; - public function fadeAnim() + public function fadeAnim():Void { impactThing = new FunkinSprite(0, 0); impactThing.frames = capsule.frames; From 6a62f38c33a33c90c224bfc7ecbef0481e29c908 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 4 Jun 2024 16:51:27 -0400 Subject: [PATCH 171/216] quicki fix for incorrect clip tweens --- source/funkin/ui/freeplay/SongMenuItem.hx | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/source/funkin/ui/freeplay/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx index d40809fada..b861bca15b 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -671,14 +671,9 @@ class SongMenuItem extends FlxSpriteGroup ranking.alpha = this.selected ? 1 : 0.7; ranking.color = this.selected ? 0xFFFFFFFF : 0xFFAAAAAA; - if (selected) - { - if (songText.tooLong == true) songText.initMove(); - } - else - { - if (songText.tooLong == true) songText.resetText(); - } + if (songText.tooLong) songText.resetText(); + + if (selected && songText.tooLong) songText.initMove(); } } From ae950c738214e20446cc8ded5b163544a5ee0280 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 4 Jun 2024 19:44:00 -0400 Subject: [PATCH 172/216] Finish save data repair (you should be able to transfer your save now) --- CHANGELOG.md | 1 + source/funkin/save/Save.hx | 16 +++++++++------- source/funkin/save/changelog.md | 4 ++++ .../funkin/save/migrator/SaveDataMigrator.hx | 6 +++--- source/funkin/util/VersionUtil.hx | 18 ++++++++++++++++-- 5 files changed, 33 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5aefb8855..898978ca38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Senpai (increased the note speed) - Thorns (increased the note speed slightly) - Favorite songs marked in Freeplay are now stored between sessions. +- In the event that the game cannot load your save data, it will now perform a backup before clearing it, so that we can try to repair it in the future. - Custom note styles are now properly supported for songs; add new notestyles via JSON, then select it for use from the Chart Editor Metadata toolbox. (thanks Keoiki!) - Improved logic for NoteHitScriptEvents, allowing you to view the hit diff and modify whether a note hit is a combo break (thanks nebulazorua!) - Health icons now support a Winning frame without requiring a spritesheet, simply include a third frame in the icon file. (thanks gamerbross!) diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx index 7634c1f51b..2ff6b96cc1 100644 --- a/source/funkin/save/Save.hx +++ b/source/funkin/save/Save.hx @@ -16,7 +16,7 @@ import thx.semver.Version; @:nullSafety class Save { - public static final SAVE_DATA_VERSION:thx.semver.Version = "2.0.4"; + public static final SAVE_DATA_VERSION:thx.semver.Version = "2.0.5"; public static final SAVE_DATA_VERSION_RULE:thx.semver.VersionRule = "2.0.x"; // We load this version's saves from a new save path, to maintain SOME level of backwards compatibility. @@ -56,6 +56,9 @@ class Save if (data == null) this.data = Save.getDefault(); else this.data = data; + + // Make sure the verison number is up to date before we flush. + this.data.version = Save.SAVE_DATA_VERSION; } public static function getDefault():RawSaveData @@ -713,7 +716,6 @@ class Save { trace('[SAVE] Found legacy save data, converting...'); var gameSave = SaveDataMigrator.migrateFromLegacy(legacySaveData); - @:privateAccess FlxG.save.mergeData(gameSave.data, true); } else @@ -725,20 +727,19 @@ class Save } else { - trace('[SAVE] Loaded save data.'); - @:privateAccess + trace('[SAVE] Found existing save data.'); var gameSave = SaveDataMigrator.migrate(FlxG.save.data); FlxG.save.mergeData(gameSave.data, true); } } - public static function archiveBadSaveData(data:Dynamic):Void + public static function archiveBadSaveData(data:Dynamic):Int { // We want to save this somewhere so we can try to recover it for the user in the future! final RECOVERY_SLOT_START = 1000; - writeToAvailableSlot(RECOVERY_SLOT_START, data); + return writeToAvailableSlot(RECOVERY_SLOT_START, data); } public static function debug_queryBadSaveData():Void @@ -763,7 +764,7 @@ class Save return targetSaveData.data; } - static function writeToAvailableSlot(slot:Int, data:Dynamic):Void + static function writeToAvailableSlot(slot:Int, data:Dynamic):Int { trace('[SAVE] Finding slot to write data to (starting with ${slot})...'); @@ -781,6 +782,7 @@ class Save targetSaveData.mergeData(data, true); trace('[SAVE] Data written to slot ${slot}!'); + return slot; } /** diff --git a/source/funkin/save/changelog.md b/source/funkin/save/changelog.md index 7c9094f2dd..e3038373d2 100644 --- a/source/funkin/save/changelog.md +++ b/source/funkin/save/changelog.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.0.5] - 2024-05-21 +### Fixed +- Resolved an issue where HTML5 wouldn't store the semantic version properly, causing the game to fail to load the save. + ## [2.0.4] - 2024-05-21 ### Added - `favoriteSongs:Array` to `Save` diff --git a/source/funkin/save/migrator/SaveDataMigrator.hx b/source/funkin/save/migrator/SaveDataMigrator.hx index b7d278cc6e..7a929322a0 100644 --- a/source/funkin/save/migrator/SaveDataMigrator.hx +++ b/source/funkin/save/migrator/SaveDataMigrator.hx @@ -35,9 +35,9 @@ class SaveDataMigrator else { var message:String = 'Error migrating save data, expected ${Save.SAVE_DATA_VERSION}.'; - lime.app.Application.current.window.alert(message, "Save Data Failure"); - Save.archiveBadSaveData(inputData); - trace('[SAVE] ' + message); + var slot:Int = Save.archiveBadSaveData(inputData); + var fullMessage:String = 'An error occurred migrating your save data.\n${message}\nInvalid data has been moved to save slot ${slot}.'; + lime.app.Application.current.window.alert(fullMessage, "Save Data Failure"); return new Save(Save.getDefault()); } } diff --git a/source/funkin/util/VersionUtil.hx b/source/funkin/util/VersionUtil.hx index b84b663414..832ce008ab 100644 --- a/source/funkin/util/VersionUtil.hx +++ b/source/funkin/util/VersionUtil.hx @@ -23,6 +23,8 @@ class VersionUtil { try { + var versionRaw:thx.semver.Version.SemVer = version; + trace('${versionRaw} satisfies (${versionRule})? ${version.satisfies(versionRule)}'); return version.satisfies(versionRule); } catch (e) @@ -40,10 +42,22 @@ class VersionUtil { // This is bad! versionData.version should be an array! trace('[SAVE] Version data repair required! (got ${versionData.version})'); - var fixedVersionData = [versionData.version[0], versionData.version[1], versionData.version[2]]; - versionData.version = fixedVersionData; + // Turn the objects back into arrays. + // I'd use DynamicsT.values but IDK if it maintains order + versionData.version = [versionData.version[0], versionData.version[1], versionData.version[2]]; + + // This is so jank but it should work. + var buildData:Dynamic = cast versionData.build; + var buildDataFixed:Array = thx.Dynamics.DynamicsT.values(buildData) + .map(function(d:Dynamic) return StringId(d.toString())); + versionData.build = buildDataFixed; + + var preData:Dynamic = cast versionData.pre; + var preDataFixed:Array = thx.Dynamics.DynamicsT.values(preData).map(function(d:Dynamic) return StringId(d.toString())); + versionData.pre = preDataFixed; var fixedVersion:thx.semver.Version = versionData; + trace('[SAVE] Fixed version: ${fixedVersion}'); return fixedVersion; } else From 97400ed5d8dc8867f7eb4dde01ed7b0832309054 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 4 Jun 2024 22:26:35 -0400 Subject: [PATCH 173/216] santa sounds --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 4039bd018d..b7d3772e76 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 4039bd018d474994b44317b74cdd724b5f73b749 +Subproject commit b7d3772e76ca1d05626201594acb7f4b996d4a80 From f2dd626ed9ab616d6b66d72fb2b399683fd11999 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 4 Jun 2024 22:37:51 -0400 Subject: [PATCH 174/216] rollback viz hmm --- hmm.json | 2 +- source/funkin/audio/visualize/ABotVis.hx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hmm.json b/hmm.json index e364e405fe..a1998f515d 100644 --- a/hmm.json +++ b/hmm.json @@ -49,7 +49,7 @@ "name": "funkin.vis", "type": "git", "dir": null, - "ref": "38261833590773cb1de34ac5d11e0825696fc340", + "ref": "c6a1e24d48646849ea63563ca45561512c953779", "url": "https://github.com/FunkinCrew/funkVis" }, { diff --git a/source/funkin/audio/visualize/ABotVis.hx b/source/funkin/audio/visualize/ABotVis.hx index 15596318c3..8ddc416911 100644 --- a/source/funkin/audio/visualize/ABotVis.hx +++ b/source/funkin/audio/visualize/ABotVis.hx @@ -58,7 +58,7 @@ class ABotVis extends FlxTypedSpriteGroup public function initAnalyzer() { @:privateAccess - analyzer = new SpectralAnalyzer(snd._channel.__source, 7, 0.01, 30); + analyzer = new SpectralAnalyzer(snd._channel.__source, 7, 0.1, 30); // analyzer.maxDb = -35; // analyzer.fftN = 2048; } From 8bdaf8f513c9a003f1622123dce1aeeb1d8ebab5 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 4 Jun 2024 22:55:21 -0400 Subject: [PATCH 175/216] web rank sounds --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index b7d3772e76..f2202ff9d9 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit b7d3772e76ca1d05626201594acb7f4b996d4a80 +Subproject commit f2202ff9d920743830cf2b47442040ad80f5ca05 From 66d86a6969b924cba3c17ae5505aea7dbddcec6f Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 4 Jun 2024 23:07:08 -0400 Subject: [PATCH 176/216] 2hot death fix --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index f2202ff9d9..613365d989 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit f2202ff9d920743830cf2b47442040ad80f5ca05 +Subproject commit 613365d98921346f0502a62d0a5f68fce6d27373 From 50990b15e100a18f2f3d2cd8074e09a8c70e3749 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 4 Jun 2024 23:36:32 -0400 Subject: [PATCH 177/216] heart glow --- source/funkin/ui/freeplay/FreeplayState.hx | 6 ++++++ source/funkin/ui/freeplay/SongMenuItem.hx | 13 +++++++++++++ 2 files changed, 19 insertions(+) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index fe64a1e6f4..4fc94c2d79 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -757,6 +757,7 @@ class FreeplayState extends MusicBeatSubState randomCapsule.alpha = 0; randomCapsule.songText.visible = false; randomCapsule.favIcon.visible = false; + randomCapsule.favIconBlurred.visible = false; randomCapsule.ranking.visible = false; randomCapsule.blurredRanking.visible = false; randomCapsule.initJumpIn(0, force); @@ -779,6 +780,7 @@ class FreeplayState extends MusicBeatSubState funnyMenu.capsule.alpha = 0.5; funnyMenu.songText.visible = false; funnyMenu.favIcon.visible = tempSongs[i].isFav; + funnyMenu.favIconBlurred.visible = tempSongs[i].isFav; funnyMenu.hsvShader = hsvShader; funnyMenu.newText.animation.curAnim.curFrame = 45 - ((i * 4) % 45); @@ -1232,7 +1234,9 @@ class FreeplayState extends MusicBeatSubState if (isFav) { grpCapsules.members[realShit].favIcon.visible = true; + grpCapsules.members[realShit].favIconBlurred.visible = true; grpCapsules.members[realShit].favIcon.animation.play('fav'); + grpCapsules.members[realShit].favIconBlurred.animation.play('fav'); FunkinSound.playOnce(Paths.sound('fav'), 1); grpCapsules.members[realShit].checkClip(); grpCapsules.members[realShit].selected = grpCapsules.members[realShit].selected; // set selected again, so it can run it's getter function to initialize movement @@ -1254,9 +1258,11 @@ class FreeplayState extends MusicBeatSubState else { grpCapsules.members[realShit].favIcon.animation.play('fav', true, true, 9); + grpCapsules.members[realShit].favIconBlurred.animation.play('fav', true, true, 9); FunkinSound.playOnce(Paths.sound('unfav'), 1); new FlxTimer().start(0.2, _ -> { grpCapsules.members[realShit].favIcon.visible = false; + grpCapsules.members[realShit].favIconBlurred.visible = false; grpCapsules.members[realShit].checkClip(); }); diff --git a/source/funkin/ui/freeplay/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx index b861bca15b..fb91fbd1c5 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -38,6 +38,7 @@ class SongMenuItem extends FlxSpriteGroup public var selected(default, set):Bool; public var songText:CapsuleText; + public var favIconBlurred:FlxSprite; public var favIcon:FlxSprite; public var ranking:FreeplayRank; @@ -190,6 +191,16 @@ class SongMenuItem extends FlxSpriteGroup add(pixelIcon); grpHide.add(pixelIcon); + favIconBlurred = new FlxSprite(380, 40); + favIconBlurred.frames = Paths.getSparrowAtlas('freeplay/favHeart'); + favIconBlurred.animation.addByPrefix('fav', 'favorite heart', 24, false); + favIconBlurred.animation.play('fav'); + favIconBlurred.setGraphicSize(50, 50); + favIconBlurred.blend = BlendMode.ADD; + favIconBlurred.shader = new GaussianBlurShader(1.2); + favIconBlurred.visible = false; + add(favIconBlurred); + favIcon = new FlxSprite(380, 40); favIcon.frames = Paths.getSparrowAtlas('freeplay/favHeart'); favIcon.animation.addByPrefix('fav', 'favorite heart', 24, false); @@ -669,6 +680,8 @@ class SongMenuItem extends FlxSpriteGroup capsule.offset.x = this.selected ? 0 : -5; capsule.animation.play(this.selected ? "selected" : "unselected"); ranking.alpha = this.selected ? 1 : 0.7; + favIcon.alpha = this.selected ? 1 : 0.6; + favIconBlurred.alpha = this.selected ? 1 : 0; ranking.color = this.selected ? 0xFFFFFFFF : 0xFFAAAAAA; if (songText.tooLong) songText.resetText(); From 03bccee0542c363548b9cad25e1cbfd84e6fb0a3 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 4 Jun 2024 23:39:49 -0400 Subject: [PATCH 178/216] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 613365d989..efb7a833a7 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 613365d98921346f0502a62d0a5f68fce6d27373 +Subproject commit efb7a833a78ab9c3bd9fe36bb10a8adc6a87e30b From 5dda95c69baffddfae35f7e5fdf1fdb84661a80f Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 5 Jun 2024 00:40:14 -0400 Subject: [PATCH 179/216] Fix some display issues with the clear percent in the results screen. --- source/funkin/InitState.hx | 2 +- .../play/components/ClearPercentCounter.hx | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/source/funkin/InitState.hx b/source/funkin/InitState.hx index c7a08d714d..49b15ddf60 100644 --- a/source/funkin/InitState.hx +++ b/source/funkin/InitState.hx @@ -229,7 +229,7 @@ class InitState extends FlxState tallies: { sick: 130, - good: 70, + good: 60, bad: 69, shit: 69, missed: 69, diff --git a/source/funkin/play/components/ClearPercentCounter.hx b/source/funkin/play/components/ClearPercentCounter.hx index d296b0b0b1..6af40019b1 100644 --- a/source/funkin/play/components/ClearPercentCounter.hx +++ b/source/funkin/play/components/ClearPercentCounter.hx @@ -35,7 +35,7 @@ class ClearPercentCounter extends FlxTypedSpriteGroup super(x, y); flashShader = new PureColor(FlxColor.WHITE); - flashShader.colorSet = true; + flashShader.colorSet = false; curNumber = startingNumber; @@ -54,10 +54,7 @@ class ClearPercentCounter extends FlxTypedSpriteGroup */ public function flash(enabled:Bool):Void { - for (member in members) - { - member.shader = enabled ? flashShader : null; - } + flashShader.colorSet = enabled; } var tmr:Float = 0; @@ -98,6 +95,7 @@ class ClearPercentCounter extends FlxTypedSpriteGroup var yPos = (digitIndex - 1 + digitOffset) * (digitHeightOffset * this.scale.y); yPos += small ? 0 : 72; + trace('[COUNTER] Drawing digit ${num}'); if (digitIndex >= members.length) { // Three digits = LLR because the 1 and 0 won't be the same anyway. @@ -105,6 +103,8 @@ class ClearPercentCounter extends FlxTypedSpriteGroup // var variant:Bool = (seperatedScore.length % 2 != 0) ? (digitIndex % 2 == 0) : (digitIndex % 2 == 1); var numb:ClearPercentNumber = new ClearPercentNumber(xPos, yPos, num, variant, this.small); numb.scale.set(this.scale.x, this.scale.y); + numb.shader = flashShader; + numb.visible = true; add(numb); } else @@ -113,8 +113,15 @@ class ClearPercentCounter extends FlxTypedSpriteGroup // Reset the position of the number members[digitIndex].x = xPos + this.x; members[digitIndex].y = yPos + this.y; + members[digitIndex].visible = true; } } + trace('[COUNTER] Members: ${members.length}, expected members: ${seperatedScore.length + 1}'); + for (ind in (seperatedScore.length + 1)...(members.length)) + { + trace('Hiding digit ${ind}'); + members[ind].visible = false; + } } } From 640c1cf236f2578795c1385ac2ffad72a4095228 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 5 Jun 2024 00:49:59 -0400 Subject: [PATCH 180/216] Dave say 1 minute to make Dad sneak up and 2 minutes to play the cartoons --- source/funkin/ui/freeplay/DJBoyfriend.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/ui/freeplay/DJBoyfriend.hx b/source/funkin/ui/freeplay/DJBoyfriend.hx index 248526aaf6..bd2f73e422 100644 --- a/source/funkin/ui/freeplay/DJBoyfriend.hx +++ b/source/funkin/ui/freeplay/DJBoyfriend.hx @@ -27,8 +27,8 @@ class DJBoyfriend extends FlxAtlasSprite var gotSpooked:Bool = false; - static final SPOOK_PERIOD:Float = 120.0; - static final TV_PERIOD:Float = 180.0; + static final SPOOK_PERIOD:Float = 60.0; + static final TV_PERIOD:Float = 120.0; // Time since dad last SPOOKED you. var timeSinceSpook:Float = 0; From 9f3d80d1dbbefba5adc91aab84a0a25c91cb0394 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 5 Jun 2024 01:16:30 -0400 Subject: [PATCH 181/216] Cory made some chart tweaks. Plus some authorship changes. --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index efb7a833a7..6af0940504 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit efb7a833a78ab9c3bd9fe36bb10a8adc6a87e30b +Subproject commit 6af0940504514701e3625b65d8332c27198e9198 From 3534ba6224d8dd950c9f599cedd15e597cc469ab Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 5 Jun 2024 13:50:57 -0400 Subject: [PATCH 182/216] roses fix --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 6af0940504..faef517a06 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 6af0940504514701e3625b65d8332c27198e9198 +Subproject commit faef517a068bb6821d828462504d7baebc91306f From fa1fafba68be5b8abf0e7ad266b333a3d47c1875 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 5 Jun 2024 14:13:06 -0400 Subject: [PATCH 183/216] less effin traces --- source/funkin/play/components/ClearPercentCounter.hx | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/source/funkin/play/components/ClearPercentCounter.hx b/source/funkin/play/components/ClearPercentCounter.hx index 6af40019b1..e3d3795d97 100644 --- a/source/funkin/play/components/ClearPercentCounter.hx +++ b/source/funkin/play/components/ClearPercentCounter.hx @@ -59,14 +59,14 @@ class ClearPercentCounter extends FlxTypedSpriteGroup var tmr:Float = 0; - override function update(elapsed:Float) + override function update(elapsed:Float):Void { super.update(elapsed); if (numberChanged) drawNumbers(); } - function drawNumbers() + function drawNumbers():Void { var seperatedScore:Array = []; var tempCombo:Int = Math.round(curNumber); @@ -83,7 +83,7 @@ class ClearPercentCounter extends FlxTypedSpriteGroup for (ind => num in seperatedScore) { - var digitIndex = ind + 1; + var digitIndex:Int = ind + 1; // If there's only one digit, move it to the right // If there's three digits, move them all to the left var digitOffset = (seperatedScore.length == 1) ? 1 : (seperatedScore.length == 3) ? -1 : 0; @@ -95,7 +95,6 @@ class ClearPercentCounter extends FlxTypedSpriteGroup var yPos = (digitIndex - 1 + digitOffset) * (digitHeightOffset * this.scale.y); yPos += small ? 0 : 72; - trace('[COUNTER] Drawing digit ${num}'); if (digitIndex >= members.length) { // Three digits = LLR because the 1 and 0 won't be the same anyway. @@ -116,10 +115,8 @@ class ClearPercentCounter extends FlxTypedSpriteGroup members[digitIndex].visible = true; } } - trace('[COUNTER] Members: ${members.length}, expected members: ${seperatedScore.length + 1}'); for (ind in (seperatedScore.length + 1)...(members.length)) { - trace('Hiding digit ${ind}'); members[ind].visible = false; } } From 6e761ba156de336af2b567e14dfbfdc36c796129 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 5 Jun 2024 14:47:29 -0400 Subject: [PATCH 184/216] hardcode the songname position --- source/funkin/play/ResultState.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index 6f540687f3..48fb3b04e9 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -691,13 +691,13 @@ class ResultState extends MusicBeatSubState { clearPercentSmall.x = (difficulty.x + difficulty.width) + 60; clearPercentSmall.y = -clearPercentSmall.height; - FlxTween.tween(clearPercentSmall, {y: 122 - 5}, 0.5, {ease: FlxEase.expoOut, startDelay: 0.8}); + FlxTween.tween(clearPercentSmall, {y: 122 - 5}, 0.5, {ease: FlxEase.expoOut, startDelay: 0.85}); } songName.y = -songName.height; var fuckedupnumber = (10) * (songName.text.length / 15); FlxTween.tween(songName, {y: diffYTween - 25 - fuckedupnumber}, 0.5, {ease: FlxEase.expoOut, startDelay: 0.9}); - songName.x = clearPercentSmall.x + clearPercentSmall.width - 30; + songName.x = clearPercentSmall.x + 94; new FlxTimer().start(timerLength, _ -> { var tempSpeed = FlxPoint.get(speedOfTween.x, speedOfTween.y); From 5bcc0f9b25c8dc4d8942fa87fb085430efc99575 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 5 Jun 2024 15:02:29 -0400 Subject: [PATCH 185/216] partial sound loading should be more resiliant --- source/funkin/audio/FunkinSound.hx | 20 ++++++++++++++------ source/funkin/ui/freeplay/FreeplayState.hx | 2 ++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index 4cd0e7557d..4f61e70c27 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -357,6 +357,11 @@ class FunkinSound extends FlxSound implements ICloneable var shouldLoadPartial = params.partialParams?.loadPartial ?? false; + // even if we arent' trying to partial load a song, we want to error out any songs in progress, + // so we don't get overlapping music if someone were to load a new song while a partial one is loading! + + emptyPartialQueue(); + if (shouldLoadPartial) { var music = FunkinSound.loadPartial(pathToUse, params.partialParams?.start ?? 0.0, params.partialParams?.end ?? 1.0, params?.startingVolume ?? 1.0, @@ -364,12 +369,6 @@ class FunkinSound extends FlxSound implements ICloneable if (music != null) { - while (partialQueue.length > 0) - { - @:nullSafety(Off) - partialQueue.pop().error("Cancel loading partial sound"); - } - partialQueue.push(music); @:nullSafety(Off) @@ -406,6 +405,15 @@ class FunkinSound extends FlxSound implements ICloneable } } + public static function emptyPartialQueue():Void + { + while (partialQueue.length > 0) + { + @:nullSafety(Off) + partialQueue.pop().error("Cancel loading partial sound"); + } + } + static var partialQueue:Array>> = []; /** diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 4fc94c2d79..2ecbb5739c 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1769,6 +1769,8 @@ class FreeplayState extends MusicBeatSubState funnyScroll3.visible = false; new FlxTimer().start(1, function(tmr:FlxTimer) { + FunkinSound.emptyPartialQueue(); + Paths.setCurrentLevel(cap.songData.levelId); LoadingState.loadPlayState( { From c1bfc67f52d527bdeffa2a57c06a6dccbf105b0c Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 5 Jun 2024 15:43:25 -0400 Subject: [PATCH 186/216] remove effin trace --- source/funkin/ui/freeplay/SongMenuItem.hx | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/funkin/ui/freeplay/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx index fb91fbd1c5..a0fa0ae42c 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -708,8 +708,6 @@ class FreeplayRank extends FlxSprite animation.play(val.getFreeplayRankIconAsset(), true, false); - trace(val.getFreeplayRankIconAsset()); - centerOffsets(false); switch (val) From eaa63196b3fda9243784c3706610361da861e45e Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 5 Jun 2024 17:10:53 -0400 Subject: [PATCH 187/216] fix for dadbattle appearing on freeplay --- source/funkin/play/song/Song.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx index fd006c0f3a..d85703721b 100644 --- a/source/funkin/play/song/Song.hx +++ b/source/funkin/play/song/Song.hx @@ -378,7 +378,7 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry):Null { - if (diffId == null) diffId = listDifficulties(variation)[0]; + if (diffId == null) diffId = listDifficulties(variation, variations)[0]; if (variation == null) variation = Constants.DEFAULT_VARIATION; if (variations == null) variations = [variation]; From 8616722e6023729f354da0949d93a204ddd36dba Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 5 Jun 2024 17:14:04 -0400 Subject: [PATCH 188/216] asset submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index faef517a06..56fe3a3662 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit faef517a068bb6821d828462504d7baebc91306f +Subproject commit 56fe3a3662bf5588b4f6cfec492efe5d4cfd600c From 4311dd20744fac60909f8ecf923ef3533654505b Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 5 Jun 2024 17:58:22 -0400 Subject: [PATCH 189/216] hopefully dadbattle fix lol --- source/funkin/ui/freeplay/FreeplayState.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 2ecbb5739c..035ad26125 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -2024,7 +2024,7 @@ class FreeplaySongData function set_currentDifficulty(value:String):String { - if (currentDifficulty == value) return value; + // if (currentDifficulty == value) return value; currentDifficulty = value; updateValues(displayedVariations); @@ -2064,7 +2064,7 @@ class FreeplaySongData function updateValues(variations:Array):Void { - this.songDifficulties = song.listDifficulties(variations, false, false); + this.songDifficulties = song.listDifficulties(null, variations, false, false); if (!this.songDifficulties.contains(currentDifficulty)) currentDifficulty = Constants.DEFAULT_DIFFICULTY; var songDifficulty:SongDifficulty = song.getDifficulty(currentDifficulty, variations); From bc783a278a0ebd7e69ba9f81698346198bfb98d8 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 5 Jun 2024 18:21:57 -0400 Subject: [PATCH 190/216] rank clipping fix --- source/funkin/ui/freeplay/FreeplayState.hx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 035ad26125..a9721bd7cf 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1640,6 +1640,7 @@ class FreeplayState extends MusicBeatSubState { songCapsule.songData.currentDifficulty = currentDifficulty; songCapsule.init(null, null, songCapsule.songData); + songCapsule.checkClip(); } else { @@ -2024,8 +2025,6 @@ class FreeplaySongData function set_currentDifficulty(value:String):String { - // if (currentDifficulty == value) return value; - currentDifficulty = value; updateValues(displayedVariations); return value; From e27e96a1cb3ce63a3fc75054b67757e6ba6c20c1 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 5 Jun 2024 20:19:00 -0400 Subject: [PATCH 191/216] Update assets submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 56fe3a3662..68f223f965 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 56fe3a3662bf5588b4f6cfec492efe5d4cfd600c +Subproject commit 68f223f965c60a3874d7842ee2d448eee5afc87b From 642f272bce4a4399936fe1114e0db6795c0c19dd Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Thu, 6 Jun 2024 01:49:33 +0100 Subject: [PATCH 192/216] freeplay polish + new text --- source/funkin/play/song/Song.hx | 6 ++ source/funkin/ui/freeplay/FreeplayState.hx | 78 +++++++++++++--------- source/funkin/ui/freeplay/SongMenuItem.hx | 37 +++++++++- 3 files changed, 87 insertions(+), 34 deletions(-) diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx index d85703721b..df3e343e2b 100644 --- a/source/funkin/play/song/Song.hx +++ b/source/funkin/play/song/Song.hx @@ -91,6 +91,12 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry):Void { busy = true; + grpCapsules.members[curSelected].sparkle.alpha = 0; // grpCapsules.members[curSelected].forcePosition(); if (fromResults != null) @@ -1088,6 +1089,8 @@ class FreeplayState extends MusicBeatSubState // NOW we can interact with the menu busy = false; + grpCapsules.members[curSelected].sparkle.alpha = 0.7; + playCurSongPreview(capsule); }, null); // FlxTween.tween(capsule, {"targetPos.x": capsule.targetPos.x - 50}, 0.6, @@ -1814,7 +1817,7 @@ class FreeplayState extends MusicBeatSubState function changeSelection(change:Int = 0):Void { - FunkinSound.playOnce(Paths.sound('scrollMenu'), 0.4); + if (!prepForNewRank) FunkinSound.playOnce(Paths.sound('scrollMenu'), 0.4); var prevSelected:Int = curSelected; @@ -1855,43 +1858,48 @@ class FreeplayState extends MusicBeatSubState if (index < curSelected) capsule.targetPos.y -= 100; // another 100 for good measure } - if (grpCapsules.countLiving() > 0) + if (grpCapsules.countLiving() > 0 && !prepForNewRank) { - if (curSelected == 0) - { - FunkinSound.playMusic('freeplayRandom', - { - startingVolume: 0.0, - overrideExisting: true, - restartTrack: false - }); - FlxG.sound.music.fadeIn(2, 0, 0.8); - } - else - { - var potentiallyErect:String = (currentDifficulty == "erect") || (currentDifficulty == "nightmare") ? "-erect" : ""; - FunkinSound.playMusic(daSongCapsule.songData.songId, - { - startingVolume: 0.0, - overrideExisting: true, - restartTrack: false, - pathsFunction: INST, - suffix: potentiallyErect, - partialParams: - { - loadPartial: true, - start: 0.05, - end: 0.25 - }, - onLoad: function() { - FlxG.sound.music.fadeIn(2, 0, 0.4); - } - }); - } + playCurSongPreview(daSongCapsule); grpCapsules.members[curSelected].selected = true; } } + public function playCurSongPreview(daSongCapsule:SongMenuItem):Void + { + if (curSelected == 0) + { + FunkinSound.playMusic('freeplayRandom', + { + startingVolume: 0.0, + overrideExisting: true, + restartTrack: false + }); + FlxG.sound.music.fadeIn(2, 0, 0.8); + } + else + { + var potentiallyErect:String = (currentDifficulty == "erect") || (currentDifficulty == "nightmare") ? "-erect" : ""; + FunkinSound.playMusic(daSongCapsule.songData.songId, + { + startingVolume: 0.0, + overrideExisting: true, + restartTrack: false, + pathsFunction: INST, + suffix: potentiallyErect, + partialParams: + { + loadPartial: true, + start: 0.05, + end: 0.25 + }, + onLoad: function() { + FlxG.sound.music.fadeIn(2, 0, 0.4); + } + }); + } + } + /** * Build an instance of `FreeplayState` that is above the `MainMenuState`. * @return The MainMenuState with the FreeplayState as a substate. @@ -2004,6 +2012,8 @@ class FreeplaySongData */ public var isFav:Bool = false; + public var isNew:Bool = false; + var song:Song; public var levelId(default, null):String = ''; @@ -2083,6 +2093,8 @@ class FreeplaySongData } this.scoringRank = Save.instance.getSongRank(songId, currentDifficulty); + + this.isNew = song.isSongNew(currentDifficulty); } } diff --git a/source/funkin/ui/freeplay/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx index a0fa0ae42c..dc30b4345f 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -21,6 +21,8 @@ import flixel.tweens.FlxEase; import flixel.tweens.FlxTween; import flixel.addons.effects.FlxTrail; import funkin.play.scoring.Scoring.ScoringRank; +import funkin.save.Save; +import funkin.save.Save.SaveScoreData; import flixel.util.FlxColor; class SongMenuItem extends FlxSpriteGroup @@ -76,6 +78,10 @@ class SongMenuItem extends FlxSpriteGroup var impactThing:FunkinSprite; + public var sparkle:FlxSprite; + + var sparkleTimer:FlxTimer; + public function new(x:Float, y:Float) { super(x, y); @@ -110,7 +116,7 @@ class SongMenuItem extends FlxSpriteGroup newText.animation.play('newAnim', true); newText.setGraphicSize(Std.int(newText.width * 0.9)); - newText.visible = false; + // newText.visible = false; add(newText); @@ -153,6 +159,18 @@ class SongMenuItem extends FlxSpriteGroup blurredRanking.shader = new GaussianBlurShader(1); add(blurredRanking); + sparkle = new FlxSprite(ranking.x, ranking.y); + sparkle.frames = Paths.getSparrowAtlas('freeplay/sparkle'); + sparkle.animation.addByPrefix('sparkle', 'sparkle', 24, false); + sparkle.animation.play('sparkle', true); + sparkle.scale.set(0.8, 0.8); + sparkle.blend = BlendMode.ADD; + + sparkle.visible = false; + sparkle.alpha = 0.7; + + add(sparkle); + // ranking.loadGraphic(Paths.image('freeplay/ranks/' + rank)); // ranking.scale.x = ranking.scale.y = realScaled; // ranking.alpha = 0.75; @@ -218,6 +236,13 @@ class SongMenuItem extends FlxSpriteGroup setVisibleGrp(false); } + function sparkleEffect(timer:FlxTimer):Void + { + sparkle.setPosition(FlxG.random.float(ranking.x - 20, ranking.x + 3), FlxG.random.float(ranking.y - 29, ranking.y + 4)); + sparkle.animation.play('sparkle', true); + sparkleTimer = new FlxTimer().start(FlxG.random.float(1.2, 4.5), sparkleEffect); + } + // no way to grab weeks rn, so this needs to be done :/ // negative values mean weekends function checkWeek(name:String):Void @@ -415,8 +440,17 @@ class SongMenuItem extends FlxSpriteGroup function updateScoringRank(newRank:Null):Void { + if (sparkleTimer != null) sparkleTimer.cancel(); + sparkle.visible = false; + this.ranking.rank = newRank; this.blurredRanking.rank = newRank; + + if (newRank == PERFECT_GOLD) + { + sparkleTimer = new FlxTimer().start(1, sparkleEffect); + sparkle.visible = true; + } } function set_hsvShader(value:HSVShader):HSVShader @@ -468,6 +502,7 @@ class SongMenuItem extends FlxSpriteGroup updateBPM(Std.int(songData?.songStartingBpm) ?? 0); updateDifficultyRating(songData?.difficultyRating ?? 0); updateScoringRank(songData?.scoringRank); + newText.visible = songData?.isNew; // Update opacity, offsets, etc. updateSelected(); From b7eed4c4d3a1c1b4331e254f7eea75ff334fc3f4 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Thu, 6 Jun 2024 01:50:19 +0100 Subject: [PATCH 193/216] assets submoddd!!!!! --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 56fe3a3662..36e3954675 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 56fe3a3662bf5588b4f6cfec492efe5d4cfd600c +Subproject commit 36e3954675428214ae6d3ce5123ad3bc9882ea8b From 2596e6369ecbe27de8db7b86f6b3dbd05319e5fc Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 6 Jun 2024 14:00:22 -0400 Subject: [PATCH 194/216] More chart changes by SpazKid + changelog update --- CHANGELOG.md | 10 +++++++--- assets | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 898978ca38..42f1fee00d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,13 +15,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added a new Scroll Speed chart event to change the note speed mid-song (thanks ) ### Changed - Tweaked the charts for several songs: + - Tutorial (increased the note speed slightly) + - Spookeez - Monster - Winter Horrorland - - Stress - - Lit Up - - Tutorial (increased the note speed slightly) + - M.I.L.F. - Senpai (increased the note speed) + - Roses - Thorns (increased the note speed slightly) + - Ugh + - Stress + - Lit Up - Favorite songs marked in Freeplay are now stored between sessions. - In the event that the game cannot load your save data, it will now perform a backup before clearing it, so that we can try to repair it in the future. - Custom note styles are now properly supported for songs; add new notestyles via JSON, then select it for use from the Chart Editor Metadata toolbox. (thanks Keoiki!) diff --git a/assets b/assets index 56fe3a3662..6e124504f7 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 56fe3a3662bf5588b4f6cfec492efe5d4cfd600c +Subproject commit 6e124504f777048d357c4b94737dda1b569b4d03 From 700b6e11b8f06a9ad12c152e5974d5b4f016730c Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 6 Jun 2024 19:05:05 -0400 Subject: [PATCH 195/216] Update assets submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 6e124504f7..862b513556 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 6e124504f777048d357c4b94737dda1b569b4d03 +Subproject commit 862b51355622c29b5b11ff8ce979afeb53df4636 From e4647e9e2d754a8128a25dcc3d75e463fa8aed4c Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 6 Jun 2024 19:46:44 -0400 Subject: [PATCH 196/216] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 36e3954675..0062c05d55 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 36e3954675428214ae6d3ce5123ad3bc9882ea8b +Subproject commit 0062c05d559ae281ce39f8df3da6efb1f92ca808 From 0bb22b60d9b4703ddcfc2def84bf1a574f2631a4 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 6 Jun 2024 19:55:50 -0400 Subject: [PATCH 197/216] update game version --- Project.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.xml b/Project.xml index fcd29a25e4..d93cf3e425 100644 --- a/Project.xml +++ b/Project.xml @@ -2,7 +2,7 @@ - + From 4f0e77c974c7a62fb1deb6cc351668a4b01a4f92 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 6 Jun 2024 20:20:54 -0400 Subject: [PATCH 198/216] update hmm --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index ab55e30ba6..4f3d9ac4d2 100644 --- a/hmm.json +++ b/hmm.json @@ -56,7 +56,7 @@ "name": "funkin.vis", "type": "git", "dir": null, - "ref": "c6a1e24d48646849ea63563ca45561512c953779", + "ref": "38261833590773cb1de34ac5d11e0825696fc340", "url": "https://github.com/FunkinCrew/funkVis" }, { From e01e4d1e769ac111352ff3ecdbe620e7a2908363 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 6 Jun 2024 20:21:37 -0400 Subject: [PATCH 199/216] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 862b513556..e8fc4616c1 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 862b51355622c29b5b11ff8ce979afeb53df4636 +Subproject commit e8fc4616c167de66c4eddcfe1cbe51bae83536da From 7c638e02740a4937f2fb54b282f79ef25e2634e8 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 6 Jun 2024 20:26:25 -0400 Subject: [PATCH 200/216] Add satin panties erect difficulty chart --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 0062c05d55..e8bfc7461a 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 0062c05d559ae281ce39f8df3da6efb1f92ca808 +Subproject commit e8bfc7461a403e108a7f7b5fa4eebba38bb6a5fe From 715e834753fe18c4fa62e0aca627f80559ef8f82 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 6 Jun 2024 20:30:15 -0400 Subject: [PATCH 201/216] Update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 898978ca38..acb85df6cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,12 +25,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Favorite songs marked in Freeplay are now stored between sessions. - In the event that the game cannot load your save data, it will now perform a backup before clearing it, so that we can try to repair it in the future. - Custom note styles are now properly supported for songs; add new notestyles via JSON, then select it for use from the Chart Editor Metadata toolbox. (thanks Keoiki!) -- Improved logic for NoteHitScriptEvents, allowing you to view the hit diff and modify whether a note hit is a combo break (thanks nebulazorua!) - Health icons now support a Winning frame without requiring a spritesheet, simply include a third frame in the icon file. (thanks gamerbross!) - Remember that for more complex behaviors such as animations or transitions, you should use an XML file to define each frame. ### Fixed - Fixed a bug where the game would silently fail to load saves on HTML5 - Fixed some bugs with the props on the Story Menu not bopping properly +- Improved offsets for Pico and Tankman opponents so they don't slide around as much. - Additional fixes to the Loading bar on HTML5 (thanks lemz1!) - Fixed several bugs with the TitleState, including missing music when returning from the Main Menu (thanks gamerbross!) - Fixed a camera bug in the Main Menu (thanks richTrash21!) From c54c10f562e1931f39f0eb41d1f41c16c8505447 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 6 Jun 2024 20:46:12 -0400 Subject: [PATCH 202/216] lower fft res on desktop --- source/funkin/audio/visualize/ABotVis.hx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source/funkin/audio/visualize/ABotVis.hx b/source/funkin/audio/visualize/ABotVis.hx index ed22092b6c..1b04631445 100644 --- a/source/funkin/audio/visualize/ABotVis.hx +++ b/source/funkin/audio/visualize/ABotVis.hx @@ -55,6 +55,13 @@ class ABotVis extends FlxTypedSpriteGroup { @:privateAccess analyzer = new SpectralAnalyzer(snd._channel.__source, 7, 0.1, 30); + + #if desktop + // On desktop it uses FFT stuff that isn't as optimized as the direct browser stuff we use on HTML5 + // So we want to manually change it! + analyzer.fftN = 512; + #end + // analyzer.maxDb = -35; // analyzer.fftN = 2048; } From 7214e159e0174a04b21fd4f01bceaa405e062e4f Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 6 Jun 2024 20:50:53 -0400 Subject: [PATCH 203/216] update grig --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index 4f3d9ac4d2..68e0c5cb03 100644 --- a/hmm.json +++ b/hmm.json @@ -63,7 +63,7 @@ "name": "grig.audio", "type": "git", "dir": "src", - "ref": "cbf91e2180fd2e374924fe74844086aab7891666", + "ref": "57f5d47f2533fd0c3dcd025a86cb86c0dfa0b6d2", "url": "https://gitlab.com/haxe-grig/grig.audio.git" }, { From e2fbeeb13e37070f59627751216218f943f84a3d Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 6 Jun 2024 21:18:53 -0400 Subject: [PATCH 204/216] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index e8bfc7461a..4427687c48 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit e8bfc7461a403e108a7f7b5fa4eebba38bb6a5fe +Subproject commit 4427687c487d643c6051f8c4610470326c87ea4d From 6665924dd968ff96d074843988d34c64035aa479 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 6 Jun 2024 23:28:41 -0400 Subject: [PATCH 205/216] We forgot to credit burgerballs! --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e44005ffa8..1c4969cdee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [0.4.0] - 2024-05-?? +## [0.4.0] - 2024-06-06 ### Added - 2 new Erect remixes, Eggnog and Satin Panties. Check them out from the Freeplay menu! - Major visual improvements to the Results screen, with additional animations and audio based on your performance. @@ -12,7 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Freeplay now plays a preview of songs when you hover over them. - Added a Charter field to the chart format, to allow for crediting the creator of a level's chart. - You can see who charted a song from the Pause menu. -- Added a new Scroll Speed chart event to change the note speed mid-song (thanks ) +- Added a new Scroll Speed chart event to change the note speed mid-song (thanks burgerballs!) ### Changed - Tweaked the charts for several songs: - Tutorial (increased the note speed slightly) From 8700db198890ba5e83b0b0df22dc4b878a97dce0 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 6 Jun 2024 23:51:22 -0400 Subject: [PATCH 206/216] Make sure to credit all the community contributions properly. --- CHANGELOG.md | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c4969cdee..90d2a50017 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,23 +32,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Health icons now support a Winning frame without requiring a spritesheet, simply include a third frame in the icon file. (thanks gamerbross!) - Remember that for more complex behaviors such as animations or transitions, you should use an XML file to define each frame. ### Fixed +- Fixed an issue where Nene's visualizer would not play on Desktop builds - Fixed a bug where the game would silently fail to load saves on HTML5 - Fixed some bugs with the props on the Story Menu not bopping properly - Improved offsets for Pico and Tankman opponents so they don't slide around as much. -- Additional fixes to the Loading bar on HTML5 (thanks lemz1!) -- Fixed several bugs with the TitleState, including missing music when returning from the Main Menu (thanks gamerbross!) -- Fixed a camera bug in the Main Menu (thanks richTrash21!) -- Fixed a bug where changing difficulties in Story mode wouldn't update the score (thanks sectorA!) -- Fixed a crash in Freeplay caused by a level referencing an invalid song (thanks gamerbross!) +- Fixed a crash on Linux caused by an old version of hxCodec (thanks Noobz4Life!) +- Optimized animation handling for characters (thanks richTrash21!) +- Made improvements to compiling documentation (thanks gedehari!) - Fixed a bug where pressing the volume keys would stop the Toy commercial (thanks gamerbross!) - Fixed a bug where the Chart Editor Playtest would crash when losing (thanks gamerbross!) -- Fixed a bug where hold notes would display improperly in the Chart Editor when downscroll was enabled for gameplay (thanks gamerbross!) -- Fixed a bug where hold notes would be positioned wrong on downscroll (thanks MaybeMaru!) - Removed a large number of unused imports to optimize builds (thanks Ethan-makes-music!) +- Fixed a bug where hold notes would be positioned wrong on downscroll (thanks MaybeMaru!) +- Additional fixes to the Loading bar on HTML5 (thanks lemz1!) +- Fixed a crash in Freeplay caused by a level referencing an invalid song (thanks gamerbross!) - Improved debug logging for unscripted stages (thanks gamerbross!) -- Made improvements to compiling documentation (thanks gedehari!) -- Fixed a crash on Linux caused by an old version of hxCodec (thanks Noobz4Life!) -- Optimized animation handling for characters (thanks richTrash21!) +- Fixed a bug where changing difficulties in Story mode wouldn't update the score (thanks sectorA!) +- Fixed an issue where the Chart Editor would use an incorrect instrumental on imported Legacy songs (thanks gamerbross!) +- Fixed a camera bug in the Main Menu (thanks richTrash21!) +- Fixed several bugs with the TitleState, including missing music when returning from the Main Menu (thanks gamerbross!) +- Fixed a bug where opening the game from the command line would crash the preloader (thanks NotHyper474!) +- Fixed a bug where hold notes would display improperly in the Chart Editor when downscroll was enabled for gameplay (thanks gamerbross!) +- Fixed a bug where characters would sometimes use the wrong scale value (thanks PurSnake!) - Additional bug fixes and optimizations. ## [0.3.3] - 2024-05-14 From 3567e4e8e441613c0ed72d2cf13567568964cb7e Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 7 Jun 2024 00:43:31 -0400 Subject: [PATCH 207/216] Writing down more changes as I remember them --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90d2a50017..35618dca9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Stress - Lit Up - Favorite songs marked in Freeplay are now stored between sessions. +- The Freeplay easter eggs are now easier to see. - In the event that the game cannot load your save data, it will now perform a backup before clearing it, so that we can try to repair it in the future. - Custom note styles are now properly supported for songs; add new notestyles via JSON, then select it for use from the Chart Editor Metadata toolbox. (thanks Keoiki!) - Health icons now support a Winning frame without requiring a spritesheet, simply include a third frame in the icon file. (thanks gamerbross!) From 03cf3dcf99807e411288845b006a47cc902a2176 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Fri, 7 Jun 2024 03:29:58 -0400 Subject: [PATCH 208/216] README grammar fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4c6fd9e843..81f8b03e3b 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Friday Night Funkin' is a rhythm game. Built using HaxeFlixel for Ludum Dare 47. -This game was made with love to Newgrounds and it's community. Extra love to Tom Fulp. +This game was made with love to Newgrounds and its community. Extra love to Tom Fulp. - [Playable web demo on Newgrounds!](https://www.newgrounds.com/portal/view/770371) - [Demo download builds for Windows, Mac, and Linux from Itch.io!](https://ninja-muffin24.itch.io/funkin) From d4a524bbcbee7e4ba10da77fbfb4a9d6964a9bbe Mon Sep 17 00:00:00 2001 From: An-enderman <126195358+An-enderman@users.noreply.github.com> Date: Fri, 7 Jun 2024 16:40:37 +0200 Subject: [PATCH 209/216] Update COMPILING, adding one step I added the step that says to download Git, because the command "hmm install" requires Git to work. --- docs/COMPILING.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index 7278e027c2..6fbcfe6276 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -6,9 +6,10 @@ - `git clone --recurse-submodules https://github.com/FunkinCrew/funkin.git` - If you accidentally cloned without the `assets` submodule (aka didn't follow the step above), you can run `git submodule update --init --recursive` to get the assets in a foolproof way. 2. Install `hmm` (run `haxelib --global install hmm` and then `haxelib --global run hmm setup`) -3. Install all haxelibs of the current branch by running `hmm install` -4. Setup lime: `haxelib run lime setup` -5. Platform setup +3. Download Git from [git-scm.com](https://www.git-scm.com) +4. Install all haxelibs of the current branch by running `hmm install` +5. Setup lime: `haxelib run lime setup` +6. Platform setup - For Windows, download the [Visual Studio Build Tools](https://aka.ms/vs/17/release/vs_BuildTools.exe) - When prompted, select "Individual Components" and make sure to download the following: - MSVC v143 VS 2022 C++ x64/x86 build tools @@ -16,5 +17,5 @@ - Mac: [`lime setup mac` Documentation](https://lime.openfl.org/docs/advanced-setup/macos/) - Linux: [`lime setup linux` Documentation](https://lime.openfl.org/docs/advanced-setup/linux/) - HTML5: Compiles without any extra setup -6. If you are targeting for native, you may need to run `lime rebuild PLATFORM` and `lime rebuild PLATFORM -debug` -7. `lime test PLATFORM` ! Add `-debug` to enable several debug features such as time travel (`PgUp`/`PgDn` in Play State). +7. If you are targeting for native, you may need to run `lime rebuild PLATFORM` and `lime rebuild PLATFORM -debug` +8. `lime test PLATFORM` ! Add `-debug` to enable several debug features such as time travel (`PgUp`/`PgDn` in Play State). From a7e33e73ab13ad26db6feede8d6eb775edb9aa0a Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 7 Jun 2024 11:24:31 -0400 Subject: [PATCH 210/216] assets submod updated and gitmodules fix for public --- .gitmodules | 4 ++-- assets | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index 452c0089b7..be5e0aaa81 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "assets"] path = assets - url = https://github.com/FunkinCrew/Funkin-Assets-secret + url = https://github.com/FunkinCrew/funkin.assets [submodule "art"] path = art - url = https://github.com/FunkinCrew/Funkin-Art-secret + url = https://github.com/FunkinCrew/funkin.art diff --git a/assets b/assets index 4427687c48..3b8235e953 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 4427687c487d643c6051f8c4610470326c87ea4d +Subproject commit 3b8235e953505a6fe7f4ff253f5a99b9a7b9857a From 73984ea9d6830493b004800d85960b6ca69a85f8 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 7 Jun 2024 11:28:35 -0400 Subject: [PATCH 211/216] fix art submod --- art | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/art b/art index faeba700c5..66572f85d8 160000 --- a/art +++ b/art @@ -1 +1 @@ -Subproject commit faeba700c5526bd4fd57ccc927d875c82b9d3553 +Subproject commit 66572f85d826ce2ec1d45468c12733b161237ffa From 393355b512556dc3bd7ab33576b2e1c63903299b Mon Sep 17 00:00:00 2001 From: Hundrec Date: Fri, 7 Jun 2024 19:59:02 -0400 Subject: [PATCH 212/216] Fix botplay sustain release bug Copied opponent's holdTimer code to the player's side --- source/funkin/play/PlayState.hx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index b02cc69f74..d3e287da96 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -2269,11 +2269,20 @@ class PlayState extends MusicBeatSubState if (holdNote == null || !holdNote.alive) continue; // While the hold note is being hit, and there is length on the hold note... - if (!isBotPlayMode && holdNote.hitNote && !holdNote.missedNote && holdNote.sustainLength > 0) + if (holdNote.hitNote && !holdNote.missedNote && holdNote.sustainLength > 0) { // Grant the player health. - health += Constants.HEALTH_HOLD_BONUS_PER_SECOND * elapsed; - songScore += Std.int(Constants.SCORE_HOLD_BONUS_PER_SECOND * elapsed); + if (!isBotPlayMode) + { + health += Constants.HEALTH_HOLD_BONUS_PER_SECOND * elapsed; + songScore += Std.int(Constants.SCORE_HOLD_BONUS_PER_SECOND * elapsed); + } + + // Make sure the player keeps singing while the note is held by the bot. + if (isBotPlayMode && currentStage != null && currentStage.getBoyfriend() != null && currentStage.getBoyfriend().isSinging()) + { + currentStage.getBoyfriend().holdTimer = 0; + } } if (holdNote.missedNote && !holdNote.handledMiss) From ee6c4478a9ed35aee362b796b5c5fb62ba702e72 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Sat, 8 Jun 2024 02:02:54 +0200 Subject: [PATCH 213/216] Use FlxG.camera instead of camGame --- source/funkin/play/PlayState.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 369d789825..bb45f45e0d 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -3070,7 +3070,7 @@ class PlayState extends MusicBeatSubState FlxG.camera.targetOffset.x += 20; // Replace zoom animation with a fade out for now. - camGame.fade(FlxColor.BLACK, 0.6); + FlxG.camera.fade(FlxColor.BLACK, 0.6); FlxTween.tween(camHUD, {alpha: 0}, 0.6, { From cd485213dbc277b15a70f77679b747527c9a2a96 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Sat, 8 Jun 2024 02:26:17 +0200 Subject: [PATCH 214/216] Pause Camera Follow when pausing --- source/funkin/play/PlayState.hx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index bb45f45e0d..42dc6086c1 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1211,6 +1211,9 @@ class PlayState extends MusicBeatSubState cameraTweensPausedBySubState.add(cameraZoomTween); } + // Pause camera follow + FlxG.camera.followLerp = 0; + for (tween in scrollSpeedTweens) { if (tween != null && tween.active) @@ -1255,6 +1258,9 @@ class PlayState extends MusicBeatSubState } cameraTweensPausedBySubState.clear(); + // Resume camera follow + FlxG.camera.followLerp = Constants.DEFAULT_CAMERA_FOLLOW_RATE; + if (currentConversation != null) { currentConversation.resumeMusic(); @@ -3165,7 +3171,7 @@ class PlayState extends MusicBeatSubState cancelAllCameraTweens(); } - FlxG.camera.follow(cameraFollowPoint, LOCKON, 0.04); + FlxG.camera.follow(cameraFollowPoint, LOCKON, Constants.DEFAULT_CAMERA_FOLLOW_RATE); FlxG.camera.targetOffset.set(); if (resetZoom) From 2e4b94d528ca5bd5d369c264424be89bc4f3226d Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 7 Jun 2024 21:20:04 -0400 Subject: [PATCH 215/216] Fix additional merge conflicts --- source/funkin/ui/freeplay/FreeplayState.hx | 1 - 1 file changed, 1 deletion(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 576d44c948..5e07fb3967 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -172,7 +172,6 @@ class FreeplayState extends MusicBeatSubState var exitMovers:ExitMoverData = new Map(); var stickerSubState:StickerSubState; - var funnyCam:FunkinCamera; public static var rememberedDifficulty:Null = Constants.DEFAULT_DIFFICULTY; public static var rememberedSongId:Null = 'tutorial'; From 1172949a0425c0a80ded4205a60a253e0a473ed8 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Sun, 19 May 2024 00:23:51 +0200 Subject: [PATCH 216/216] Fix Options Menu not enabled in transIn --- source/funkin/ui/options/OptionsState.hx | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/source/funkin/ui/options/OptionsState.hx b/source/funkin/ui/options/OptionsState.hx index 81331b266f..e7950f0bd1 100644 --- a/source/funkin/ui/options/OptionsState.hx +++ b/source/funkin/ui/options/OptionsState.hx @@ -25,6 +25,8 @@ class OptionsState extends MusicBeatState override function create():Void { + persistentUpdate = true; + var menuBG = new FlxSprite().loadGraphic(Paths.image('menuBG')); var hsv = new HSVShader(); hsv.hue = -0.6; @@ -55,8 +57,6 @@ class OptionsState extends MusicBeatState setPage(Controls); } - // disable for intro transition - currentPage.enabled = false; super.create(); } @@ -86,13 +86,6 @@ class OptionsState extends MusicBeatState } } - override function finishTransIn() - { - super.finishTransIn(); - - currentPage.enabled = true; - } - function switchPage(name:PageName) { // TODO: Animate this transition?