From a652bfe9f0334f42dd65bc35a922f869e7e8b0fd Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 7 May 2024 14:01:00 -0400 Subject: [PATCH 001/870] 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 fe52d20de..ff24bb59b 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 e7b128385..c3abbcf3e 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/870] 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 fd133ac0a..d110e7de9 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/870] 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 964e0eeca..49bef5e4a 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/870] 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 c359d7a51..a6e4467a9 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/870] 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 8cfa2270f..71d1ad394 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/870] 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 e7b128385..c3abbcf3e 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/870] 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 4e6669479..4ced26b2d 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/870] 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 6a18f17d5..95e0668be 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 7ce3eabd17eb918ce326cf401e1e43cd80f62084 Mon Sep 17 00:00:00 2001 From: Sword352 Date: Wed, 8 May 2024 07:35:46 +0200 Subject: [PATCH 009/870] Better character animation offsets handling. --- source/funkin/play/character/BaseCharacter.hx | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/source/funkin/play/character/BaseCharacter.hx b/source/funkin/play/character/BaseCharacter.hx index 2796f8123..cb9d5ae3f 100644 --- a/source/funkin/play/character/BaseCharacter.hx +++ b/source/funkin/play/character/BaseCharacter.hx @@ -1,6 +1,7 @@ package funkin.play.character; import flixel.math.FlxPoint; +import flixel.FlxCamera; import funkin.modding.events.ScriptEvent; import funkin.play.character.CharacterData.CharacterDataParser; import funkin.play.character.CharacterData.CharacterRenderType; @@ -118,19 +119,17 @@ class BaseCharacter extends Bopper */ public var cameraFocusPoint(default, null):FlxPoint = new FlxPoint(0, 0); + /** + * Defines the animation offset. + */ + public var animOffset:FlxPoint = FlxPoint.get(); + override function set_animOffsets(value:Array):Array { if (animOffsets == null) value = [0, 0]; if ((animOffsets[0] == value[0]) && (animOffsets[1] == value[1])) return value; - // Make sure animOffets are halved when scale is 0.5. - var xDiff = (animOffsets[0] * this.scale.x / (this.isPixel ? 6 : 1)) - value[0]; - var yDiff = (animOffsets[1] * this.scale.y / (this.isPixel ? 6 : 1)) - value[1]; - - // Call the super function so that camera focus point is not affected. - super.set_x(this.x + xDiff); - super.set_y(this.y + yDiff); - + animOffset.set(value[0], value[1]); return animOffsets = value; } @@ -570,11 +569,25 @@ class BaseCharacter extends Bopper } } + // override getScreenPosition (used by FlxSprite's draw method) to account for animation offsets. + override function getScreenPosition(?result:FlxPoint, ?camera:FlxCamera):FlxPoint + { + var output:FlxPoint = super.getScreenPosition(result, camera); + output -= animOffset; + return output; + } + public override function onDestroy(event:ScriptEvent):Void { this.characterType = OTHER; } + override function destroy():Void + { + animOffset = flixel.util.FlxDestroyUtil.put(animOffset); + super.destroy(); + } + /** * Play the appropriate singing animation, for the given note direction. * @param dir The direction of the note. From 2e74678cafbc0d44559c2eb85b6847dd8cb8e249 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 8 May 2024 01:54:48 -0400 Subject: [PATCH 010/870] 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 7b7543845..5960795ea 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 dd86934712276f136193033237cb15095cc0e787 Mon Sep 17 00:00:00 2001 From: Sword352 Date: Wed, 8 May 2024 09:22:49 +0200 Subject: [PATCH 011/870] did the requested changes --- source/funkin/play/character/BaseCharacter.hx | 29 ------------------- source/funkin/play/stage/Bopper.hx | 27 +++++++++++++---- 2 files changed, 21 insertions(+), 35 deletions(-) diff --git a/source/funkin/play/character/BaseCharacter.hx b/source/funkin/play/character/BaseCharacter.hx index cb9d5ae3f..eee7d15a2 100644 --- a/source/funkin/play/character/BaseCharacter.hx +++ b/source/funkin/play/character/BaseCharacter.hx @@ -1,7 +1,6 @@ package funkin.play.character; import flixel.math.FlxPoint; -import flixel.FlxCamera; import funkin.modding.events.ScriptEvent; import funkin.play.character.CharacterData.CharacterDataParser; import funkin.play.character.CharacterData.CharacterRenderType; @@ -119,20 +118,6 @@ class BaseCharacter extends Bopper */ public var cameraFocusPoint(default, null):FlxPoint = new FlxPoint(0, 0); - /** - * Defines the animation offset. - */ - public var animOffset:FlxPoint = FlxPoint.get(); - - override function set_animOffsets(value:Array):Array - { - if (animOffsets == null) value = [0, 0]; - if ((animOffsets[0] == value[0]) && (animOffsets[1] == value[1])) return value; - - animOffset.set(value[0], value[1]); - return animOffsets = value; - } - /** * If the x position changes, other than via changing the animation offset, * then we need to update the camera focus point. @@ -569,25 +554,11 @@ class BaseCharacter extends Bopper } } - // override getScreenPosition (used by FlxSprite's draw method) to account for animation offsets. - override function getScreenPosition(?result:FlxPoint, ?camera:FlxCamera):FlxPoint - { - var output:FlxPoint = super.getScreenPosition(result, camera); - output -= animOffset; - return output; - } - public override function onDestroy(event:ScriptEvent):Void { this.characterType = OTHER; } - override function destroy():Void - { - animOffset = flixel.util.FlxDestroyUtil.put(animOffset); - super.destroy(); - } - /** * Play the appropriate singing animation, for the given note direction. * @param dir The direction of the note. diff --git a/source/funkin/play/stage/Bopper.hx b/source/funkin/play/stage/Bopper.hx index 262aff7bc..141a85c8f 100644 --- a/source/funkin/play/stage/Bopper.hx +++ b/source/funkin/play/stage/Bopper.hx @@ -1,6 +1,7 @@ package funkin.play.stage; import flixel.FlxSprite; +import flixel.FlxCamera; import flixel.math.FlxPoint; import flixel.util.FlxTimer; import funkin.modding.IScriptedClass.IPlayStateScriptedClass; @@ -67,6 +68,11 @@ class Bopper extends StageProp implements IPlayStateScriptedClass return value; } + /** + * Internally used to define the animation offsets to apply. + */ + var _currentAnimOffset:FlxPoint = FlxPoint.get(); + /** * The offset of the character relative to the position specified by the stage. */ @@ -95,12 +101,7 @@ class Bopper extends StageProp implements IPlayStateScriptedClass if (animOffsets == null) animOffsets = [0, 0]; if ((animOffsets[0] == value[0]) && (animOffsets[1] == value[1])) return value; - var xDiff = animOffsets[0] - value[0]; - var yDiff = animOffsets[1] - value[1]; - - this.x += xDiff; - this.y += yDiff; - + _currentAnimOffset.set(value[0], value[1]); return animOffsets = value; } @@ -349,6 +350,20 @@ class Bopper extends StageProp implements IPlayStateScriptedClass return this.animation.curAnim.name; } + // override getScreenPosition (used by FlxSprite's draw method) to account for animation offsets. + override function getScreenPosition(?result:FlxPoint, ?camera:FlxCamera):FlxPoint + { + var output:FlxPoint = super.getScreenPosition(result, camera); + output -= _currentAnimOffset; + return output; + } + + override function destroy():Void + { + _currentAnimOffset = flixel.util.FlxDestroyUtil.put(_currentAnimOffset); + super.destroy(); + } + public function onPause(event:PauseScriptEvent) {} public function onResume(event:ScriptEvent) {} From 4e5531744a1e7ee2023725badfabc2219e3ac4a0 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 8 May 2024 03:23:00 -0400 Subject: [PATCH 012/870] 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 4ced26b2d..57240d399 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 013/870] 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 466dbbb90..7a21a6e8f 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 014/870] 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 44ad819c4..c5f76710e 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 015/870] 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 c5f76710e..0ba4e17ec 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 016/870] 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 | 95 ++++++++----------- .../ui/debug/charting/ChartEditorState.hx | 2 +- 3 files changed, 57 insertions(+), 57 deletions(-) diff --git a/source/funkin/modding/events/ScriptEvent.hx b/source/funkin/modding/events/ScriptEvent.hx index 8d625290d..ece7870fd 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 0ba4e17ec..8ba48a1b5 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; } - - playerStrumline.hitNote(daNote, !isComboBreak); - - if (daRating == 'sick') - { - playerStrumline.playNoteSplash(daNote.noteData.getDirection()); - } - songScore += score; + } + + /** + * Handles rating popups when a note is hit. + */ + function popUpScore(daRating:String, ?combo:Int):Void + { + 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; + } + 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 b75cd8bf1..d28ca87d5 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 017/870] 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 8ba48a1b5..cdd8c7d71 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 018/870] 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 fd133ac0a..d110e7de9 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 f6334fb30b12b44635a9574587f7689d2f3beb28 Mon Sep 17 00:00:00 2001 From: Sword352 Date: Wed, 8 May 2024 22:18:41 +0200 Subject: [PATCH 019/870] Use `animOffsets` directly. --- source/funkin/play/stage/Bopper.hx | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/source/funkin/play/stage/Bopper.hx b/source/funkin/play/stage/Bopper.hx index 141a85c8f..5485edb3e 100644 --- a/source/funkin/play/stage/Bopper.hx +++ b/source/funkin/play/stage/Bopper.hx @@ -68,11 +68,6 @@ class Bopper extends StageProp implements IPlayStateScriptedClass return value; } - /** - * Internally used to define the animation offsets to apply. - */ - var _currentAnimOffset:FlxPoint = FlxPoint.get(); - /** * The offset of the character relative to the position specified by the stage. */ @@ -101,7 +96,6 @@ class Bopper extends StageProp implements IPlayStateScriptedClass if (animOffsets == null) animOffsets = [0, 0]; if ((animOffsets[0] == value[0]) && (animOffsets[1] == value[1])) return value; - _currentAnimOffset.set(value[0], value[1]); return animOffsets = value; } @@ -354,16 +348,11 @@ class Bopper extends StageProp implements IPlayStateScriptedClass override function getScreenPosition(?result:FlxPoint, ?camera:FlxCamera):FlxPoint { var output:FlxPoint = super.getScreenPosition(result, camera); - output -= _currentAnimOffset; + output.x -= animOffsets[0]; + output.y -= animOffsets[1]; return output; } - override function destroy():Void - { - _currentAnimOffset = flixel.util.FlxDestroyUtil.put(_currentAnimOffset); - super.destroy(); - } - public function onPause(event:PauseScriptEvent) {} public function onResume(event:ScriptEvent) {} From 4d1c2c1b8841bdf95ea6107298b3632be86334c1 Mon Sep 17 00:00:00 2001 From: MadBear422 Date: Wed, 8 May 2024 15:30:40 -0700 Subject: [PATCH 020/870] 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 eb60cb6db..1edbb6c00 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 021/870] 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 466dbbb90..7a21a6e8f 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 022/870] 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 be5e0aaa8..452c0089b 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 023/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index ff24bb59b..962130b22 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 024/870] 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 c560c5422..1287d5a1b 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 025/870] 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 962130b22..783f22e74 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 026/870] 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 1983d413b..548e4edfa 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 027/870] 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 44ad819c4..8903a4e63 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 028/870] initial freeplay songs loading --- Project.xml | 1 + checkstyle.json | 2 +- hmm.json | 9 +- source/funkin/Paths.hx | 20 ++++- source/funkin/audio/FunkinSound.hx | 97 ++++++++++++++++++++-- source/funkin/ui/freeplay/FreeplayState.hx | 23 +++-- 6 files changed, 127 insertions(+), 25 deletions(-) diff --git a/Project.xml b/Project.xml index fcfcfb9f3..87608bb88 100644 --- a/Project.xml +++ b/Project.xml @@ -126,6 +126,7 @@ + diff --git a/checkstyle.json b/checkstyle.json index dc89409da..41f0a7998 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 a6e4467a9..6b119c52f 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 54a4b7acf..b0a97c4fa 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 df05cc3ef..728a06a32 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 music = FunkinSound.load(Paths.music('$key/$key'), params?.startingVolume ?? 1.0, params.loop ?? true, false, true); - if (music != null) + var pathsFunction = params.pathsFunction ?? MUSIC; + var pathToUse = switch (pathsFunction) { - FlxG.sound.music = music; + case MUSIC: Paths.music('$key/$key'); + case INST: Paths.inst('$key'); + default: Paths.music('$key/$key'); + } - // Prevent repeat update() and onFocus() calls. - FlxG.sound.list.remove(FlxG.sound.music); + var shouldLoadPartial = params.partialParams?.loadPartial ?? false; - return true; + if (shouldLoadPartial) + { + var music = FunkinSound.loadPartial(pathToUse, params.partialParams?.start ?? 0, params.partialParams?.end ?? 1, params?.startingVolume ?? 1.0, + params.loop ?? true, false, true); + + if (music != null) + { + music.onComplete(function(partialMusic:Null) { + @:nullSafety(Off) + FlxG.sound.music = partialMusic; + FlxG.sound.list.remove(FlxG.sound.music); + }); + + 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 7b7543845..c290e6553 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 029/870] 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 728a06a32..5a49e29ee 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 c290e6553..d0183bf8e 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 030/870] 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 7278e027c..c5096c2f6 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 031/870] 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 0ba4e17ec..0b76ec6ee 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 000000000..f66f3b257 --- /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 95e0668be..bd0c8a1be 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 056a6a5a9..b358d7f03 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 aeb6dd0e4..663f2bbf4 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 032/870] 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 b358d7f03..9155c9b0a 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 033/870] 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 c5096c2f6..07df6367f 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 034/870] 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 e0b03f1cd..4dc0cd804 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 4c0f177f9..0a2ed042c 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 96a73a388..000000000 --- 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 035/870] 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 957daa43c..2d7099e8a 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 b75cd8bf1..a313981f4 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 036/870] Reimplement rank-based results animations. --- README.md | 2 +- assets | 2 +- source/funkin/play/ResultState.hx | 322 +++++++++++++++++++++--------- source/funkin/util/Constants.hx | 11 + 4 files changed, 240 insertions(+), 97 deletions(-) diff --git a/README.md b/README.md index 39c098af5..5728a6cb3 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 fe52d20de..6115eb683 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 56dd1e80f..7f8bdd77a 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 PERFECT | PERFECT_GOLD | PERFECT_PLATINUM: + if (bfPerfect == null) + { + trace("Could not build PERFECT animation!"); + } + else + { + bfPerfect.visible = true; + bfPerfect.playAnimation(''); + } - case NORMAL: - boyfriend.animation.play('fall'); - boyfriend.visible = true; + 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; + case SHIT: + if (bfShit == null) + { + trace("Could not build SHIT animation!"); + } + else + { + bfShit.visible = true; + bfShit.playAnimation('Intro'); + } - // 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) * 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(""); + 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; - // bfGfExcellent.visible = true; - // bfGfExcellent.playAnimation(""); + // 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 c50f17697..2f3b570b3 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 037/870] Update assets to add music. --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 6115eb683..7df2e5527 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 038/870] 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 0b76ec6ee..b4c733ee3 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 - ]; + cancelScrollSpeedTweens(); + for (i in strumlines) + { + var value:Float = speed; + var strum:Strumline = Reflect.getProperty(this, i); - 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}); + 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 f66f3b257..22da45b0c 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 bd0c8a1be..dbc8569c5 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 039/870] 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 b4c733ee3..4ce778fc1 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 040/870] Added Clear % tally to results. --- assets | 2 +- source/funkin/play/ResultState.hx | 381 +++++++++++++++++++++--------- 2 files changed, 266 insertions(+), 117 deletions(-) diff --git a/assets b/assets index 7df2e5527..927578f48 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 7f8bdd77a..df3134b9d 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) - { - 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(); + function afterRankTallySequence():Void + { + 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 | 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 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; + }); + }); + } + + 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; + }); + }); + } + + 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 041/870] 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 927578f48..fd112e293 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 927578f482b23dc4511fd8203560d631442d91a8 +Subproject commit fd112e293ee0f823ee98d5b8bd8a85e934f772f6 diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx index e71ae3213..23d8d2198 100644 --- a/source/funkin/play/song/Song.hx +++ b/source/funkin/play/song/Song.hx @@ -399,6 +399,27 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry + { + if (charId == null) charId = Constants.DEFAULT_CHARACTER; + + if (variations.contains(charId)) + { + return [charId]; + } + else + { + // TODO: How to exclude character variations while keeping other custom variations? + return variations; + } + } + /** * List all the difficulties in this song. * diff --git a/source/funkin/ui/freeplay/AlbumRoll.hx b/source/funkin/ui/freeplay/AlbumRoll.hx index 35facf131..50f4a432c 100644 --- a/source/funkin/ui/freeplay/AlbumRoll.hx +++ b/source/funkin/ui/freeplay/AlbumRoll.hx @@ -38,7 +38,7 @@ class AlbumRoll extends FlxSpriteGroup var newAlbumArt:FlxAtlasSprite; - // var difficultyStars:DifficultyStars; + var difficultyStars:DifficultyStars; var _exitMovers:Null; var albumData:Album; @@ -65,9 +65,9 @@ class AlbumRoll extends FlxSpriteGroup add(newAlbumArt); - // difficultyStars = new DifficultyStars(140, 39); - // difficultyStars.stars.visible = false; - // add(difficultyStars); + difficultyStars = new DifficultyStars(140, 39); + difficultyStars.stars.visible = false; + add(difficultyStars); } function onAlbumFinish(animName:String):Void @@ -86,9 +86,14 @@ class AlbumRoll extends FlxSpriteGroup { if (albumId == null) { - // difficultyStars.stars.visible = false; + this.visible = false; + difficultyStars.stars.visible = false; return; } + else + { + this.visible = true; + } albumData = AlbumRegistry.instance.fetchEntry(albumId); @@ -144,10 +149,10 @@ class AlbumRoll extends FlxSpriteGroup newAlbumArt.visible = true; newAlbumArt.playAnimation(animNames.get('$albumId-active'), false, false, false); - // difficultyStars.stars.visible = false; + difficultyStars.stars.visible = false; new FlxTimer().start(0.75, function(_) { // showTitle(); - // showStars(); + showStars(); }); } @@ -156,16 +161,17 @@ class AlbumRoll extends FlxSpriteGroup newAlbumArt.playAnimation(animNames.get('$albumId-trans'), false, false, false); } - // public function setDifficultyStars(?difficulty:Int):Void - // { - // if (difficulty == null) return; - // difficultyStars.difficulty = difficulty; - // } - // /** - // * Make the album stars visible. - // */ - // public function showStars():Void - // { - // difficultyStars.stars.visible = false; // true; - // } + public function setDifficultyStars(?difficulty:Int):Void + { + if (difficulty == null) return; + difficultyStars.difficulty = difficulty; + } + + /** + * Make the album stars visible. + */ + public function showStars():Void + { + difficultyStars.stars.visible = true; // true; + } } diff --git a/source/funkin/ui/freeplay/DifficultyStars.hx b/source/funkin/ui/freeplay/DifficultyStars.hx new file mode 100644 index 000000000..51526bcbe --- /dev/null +++ b/source/funkin/ui/freeplay/DifficultyStars.hx @@ -0,0 +1,106 @@ +package funkin.ui.freeplay; + +import flixel.group.FlxSpriteGroup; +import funkin.graphics.adobeanimate.FlxAtlasSprite; +import funkin.graphics.shaders.HSVShader; + +class DifficultyStars extends FlxSpriteGroup +{ + /** + * Internal handler var for difficulty... ranges from 0... to 15 + * 0 is 1 star... 15 is 0 stars! + */ + var curDifficulty(default, set):Int = 0; + + /** + * Range between 0 and 15 + */ + public var difficulty(default, set):Int = 1; + + public var stars:FlxAtlasSprite; + + var flames:FreeplayFlames; + + var hsvShader:HSVShader; + + public function new(x:Float, y:Float) + { + super(x, y); + + hsvShader = new HSVShader(); + + flames = new FreeplayFlames(0, 0); + add(flames); + + stars = new FlxAtlasSprite(0, 0, Paths.animateAtlas("freeplay/freeplayStars")); + stars.anim.play("diff stars"); + add(stars); + + stars.shader = hsvShader; + + for (memb in flames.members) + memb.shader = hsvShader; + } + + override function update(elapsed:Float):Void + { + super.update(elapsed); + + // "loops" the current animation + // for clarity, the animation file looks like + // frame : stars + // 0-99: 1 star + // 100-199: 2 stars + // ...... + // 1300-1499: 15 stars + // 1500 : 0 stars + if (curDifficulty < 15 && stars.anim.curFrame >= (curDifficulty + 1) * 100) + { + stars.anim.play("diff stars", true, false, curDifficulty * 100); + } + } + + function set_difficulty(value:Int):Int + { + difficulty = value; + + if (difficulty <= 0) + { + difficulty = 0; + curDifficulty = 15; + } + else if (difficulty <= 15) + { + difficulty = value; + curDifficulty = difficulty - 1; + } + else + { + difficulty = 15; + curDifficulty = difficulty - 1; + } + + if (difficulty > 10) flames.flameCount = difficulty - 10; + else + flames.flameCount = 0; + + return difficulty; + } + + function set_curDifficulty(value:Int):Int + { + curDifficulty = value; + if (curDifficulty == 15) + { + stars.anim.play("diff stars", true, false, 1500); + stars.anim.pause(); + } + else + { + stars.anim.curFrame = Std.int(curDifficulty * 100); + stars.anim.play("diff stars", true, false, curDifficulty * 100); + } + + return curDifficulty; + } +} diff --git a/source/funkin/ui/freeplay/FreeplayFlames.hx b/source/funkin/ui/freeplay/FreeplayFlames.hx index c20d85898..f6b6f5c3d 100644 --- a/source/funkin/ui/freeplay/FreeplayFlames.hx +++ b/source/funkin/ui/freeplay/FreeplayFlames.hx @@ -50,8 +50,19 @@ class FreeplayFlames extends FlxSpriteGroup } } + var timers:Array = []; + function set_flameCount(value:Int):Int { + // Stop all existing timers. + // This fixes a bug where quickly switching difficulties would show flames. + for (timer in timers) + { + timer.active = false; + timer.destroy(); + timers.remove(timer); + } + this.flameCount = value; var visibleCount:Int = 0; for (i in 0...5) @@ -62,10 +73,18 @@ class FreeplayFlames extends FlxSpriteGroup { if (!flame.visible) { - new FlxTimer().start(flameTimer * visibleCount, function(_) { + var nextTimer:FlxTimer = new FlxTimer().start(flameTimer * visibleCount, function(currentTimer:FlxTimer) { + if (i >= this.flameCount) + { + trace('EARLY EXIT'); + return; + } + timers.remove(currentTimer); flame.animation.play("flame", true); flame.visible = true; }); + timers.push(nextTimer); + visibleCount++; } } diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 7b7543845..239068288 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -120,8 +120,6 @@ class FreeplayState extends MusicBeatSubState var curCapsule:SongMenuItem; var curPlaying:Bool = false; - var displayedVariations:Array; - 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 f6d85e56e..cf9b52482 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -168,7 +168,7 @@ class SongMenuItem extends FlxSpriteGroup songText.text = songData?.songName ?? 'Random'; // Update capsule character. if (songData?.songCharacter != null) setCharacter(songData.songCharacter); - updateDifficultyRating(songData?.songRating ?? 0); + updateDifficultyRating(songData?.difficultyRating ?? 0); // Update opacity, offsets, etc. updateSelected(); } From fa4fa8116c7e07487e8b9f6fc4e71be2e0007703 Mon Sep 17 00:00:00 2001 From: nebulazorua Date: Sat, 11 May 2024 16:51:27 +0800 Subject: [PATCH 042/870] abstract enum pagename should make adding modded optionspages better and easier makes it so you dont have to leech off an unused PageName or write your own code for making modded options, helping with compatibility between mods. --- source/funkin/ui/options/OptionsState.hx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source/funkin/ui/options/OptionsState.hx b/source/funkin/ui/options/OptionsState.hx index 81331b266..57ba3f3d4 100644 --- a/source/funkin/ui/options/OptionsState.hx +++ b/source/funkin/ui/options/OptionsState.hx @@ -266,11 +266,11 @@ class OptionsMenu extends Page #end } -enum PageName +enum abstract PageName(String) { - Options; - Controls; - Colors; - Mods; - Preferences; + var Options = "options"; + var Controls = "controls"; + var Colors = "colors"; + var Mods = "mods"; + var Preferences = "preferences"; } From 6a52efe8a4293389502b4d2e763b0c88105649f0 Mon Sep 17 00:00:00 2001 From: Ikko Eltociear Ashimine Date: Sat, 11 May 2024 18:10:15 +0900 Subject: [PATCH 043/870] Update ScriptEventType.hx relevent -> relevant --- source/funkin/modding/events/ScriptEventType.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/modding/events/ScriptEventType.hx b/source/funkin/modding/events/ScriptEventType.hx index eeeb8ef29..6ac85649f 100644 --- a/source/funkin/modding/events/ScriptEventType.hx +++ b/source/funkin/modding/events/ScriptEventType.hx @@ -20,7 +20,7 @@ enum abstract ScriptEventType(String) from String to String var DESTROY = 'DESTROY'; /** - * Called when the relevent object is added to the game state. + * Called when the relevant object is added to the game state. * This assumes all data is loaded and ready to go. * * This event is not cancelable. From c0485fd1a23f0f683b79935245bc89af18d15e4a Mon Sep 17 00:00:00 2001 From: gamerbross Date: Sat, 11 May 2024 20:11:51 +0200 Subject: [PATCH 044/870] 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 7b7543845..a359010d3 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 045/870] 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 7b7543845..b0d435274 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 046/870] 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 74f72b826..b8fdb64d1 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 047/870] 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 b0d435274..d4a89531c 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 048/870] 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 7b7543845..52fc32196 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 049/870] 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 a6e4467a9..b9986547a 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 050/870] bump hxcodec version --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index b9986547a..288aa80b8 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 051/870] 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 95e0668be..b520f7b70 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 052/870] 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 b520f7b70..a7a051a66 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 053/870] 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 763d84853..9930d688c 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 054/870] 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 2796f8123..4ef86c6a9 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 c49b66f0e48881d7ad978428bb8237038cf6f2f6 Mon Sep 17 00:00:00 2001 From: cyn Date: Mon, 13 May 2024 11:23:16 -0700 Subject: [PATCH 055/870] flash fix --- source/funkin/ui/MenuItem.hx | 23 +++++++++++------------ source/funkin/ui/story/LevelTitle.hx | 24 ++++++++++++------------ 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/source/funkin/ui/MenuItem.hx b/source/funkin/ui/MenuItem.hx index ba5cc066b..2a483ea78 100644 --- a/source/funkin/ui/MenuItem.hx +++ b/source/funkin/ui/MenuItem.hx @@ -11,7 +11,6 @@ class MenuItem extends FlxSpriteGroup { public var targetY:Float = 0; public var week:FlxSprite; - public var flashingInt:Int = 0; public function new(x:Float, y:Float, weekNum:Int = 0, weekType:WeekType) { @@ -30,28 +29,28 @@ class MenuItem extends FlxSpriteGroup } var isFlashing:Bool = false; + var flashTick:Float = 0; + final flashFramerate:Float = 20; public function startFlashing():Void { isFlashing = true; } - // if it runs at 60fps, fake framerate will be 6 - // if it runs at 144 fps, fake framerate will be like 14, and will update the graphic every 0.016666 * 3 seconds still??? - // so it runs basically every so many seconds, not dependant on framerate?? - // I'm still learning how math works thanks whoever is reading this lol - var fakeFramerate:Int = Math.round((1 / FlxG.elapsed) / 10); - override function update(elapsed:Float) { super.update(elapsed); y = MathUtil.coolLerp(y, (targetY * 120) + 480, 0.17); - if (isFlashing) flashingInt += 1; - - if (flashingInt % fakeFramerate >= Math.floor(fakeFramerate / 2)) week.color = 0xFF33ffff; - else - week.color = FlxColor.WHITE; + if (isFlashing) + { + flashTick += elapsed; + if (flashTick >= 1 / flashFramerate) + { + flashTick %= 1 / flashFramerate; + week.color = (week.color == FlxColor.WHITE) ? 0xFF33ffff : FlxColor.WHITE; + } + } } } diff --git a/source/funkin/ui/story/LevelTitle.hx b/source/funkin/ui/story/LevelTitle.hx index e6f989016..2be2da154 100644 --- a/source/funkin/ui/story/LevelTitle.hx +++ b/source/funkin/ui/story/LevelTitle.hx @@ -13,13 +13,10 @@ class LevelTitle extends FlxSpriteGroup public final level:Level; public var targetY:Float; - public var isFlashing:Bool = false; var title:FlxSprite; var lock:FlxSprite; - var flashingInt:Int = 0; - public function new(x:Int, y:Int, level:Level) { super(x, y); @@ -46,20 +43,23 @@ class LevelTitle extends FlxSpriteGroup } } - // if it runs at 60fps, fake framerate will be 6 - // if it runs at 144 fps, fake framerate will be like 14, and will update the graphic every 0.016666 * 3 seconds still??? - // so it runs basically every so many seconds, not dependant on framerate?? - // I'm still learning how math works thanks whoever is reading this lol - var fakeFramerate:Int = Math.round((1 / FlxG.elapsed) / 10); + public var isFlashing:Bool = false; + var flashTick:Float = 0; + final flashFramerate:Float = 20; public override function update(elapsed:Float):Void { this.y = MathUtil.coolLerp(y, targetY, 0.17); - if (isFlashing) flashingInt += 1; - if (flashingInt % fakeFramerate >= Math.floor(fakeFramerate / 2)) title.color = 0xFF33ffff; - else - title.color = FlxColor.WHITE; + if (isFlashing) + { + flashTick += elapsed; + if (flashTick >= 1 / flashFramerate) + { + flashTick %= 1 / flashFramerate; + title.color = (title.color == FlxColor.WHITE) ? 0xFF33ffff : FlxColor.WHITE; + } + } } public function showLock():Void From 24933f5bb9bc725b90b95db6a4b2782f0f71b9d5 Mon Sep 17 00:00:00 2001 From: Hyper_ Date: Mon, 13 May 2024 17:16:49 -0300 Subject: [PATCH 056/870] 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 9930d688c..07f6bc13a 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 057/870] 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 a7a051a66..07d4ab69b 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 058/870] 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 28533e35b..9ac34465c 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 059/870] 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 7b7543845..bdaa87ede 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 060/870] 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 bdaa87ede..0a2674c8a 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 061/870] 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 9ac34465c..95c378b24 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 062/870] ludum dare 47 typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 62794b924..4c6fd9e84 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 063/870] 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 783f22e74..962130b22 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 a3726e025..1c7926f62 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 064/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 962130b22..783f22e74 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 065/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 783f22e74..962130b22 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 066/870] 0.3.3 changelog --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7f830047..2f0a0dcff 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 067/870] project.xml version bump --- Project.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.xml b/Project.xml index fcfcfb9f3..24cdac270 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 068/870] more changeloggy --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f0a0dcff..a852ca82d 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 069/870] git submodules trolled --- .gitmodules | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 452c0089b..be5e0aaa8 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 070/870] asset submod grr... --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 962130b22..783f22e74 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 071/870] 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 ece7870fd..dd55de23b 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 cdd8c7d71..f563c8d2e 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 072/870] 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 4ce778fc1..d63854d3f 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 22da45b0c..9abd4be90 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 073/870] 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 d63854d3f..176f3817c 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 074/870] 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 9155c9b0a..b358d7f03 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 075/870] 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 c3abbcf3e..4d50d75cc 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 a9ca09ce8..43dd485cf 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 076/870] 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 49bef5e4a..c9b3619e9 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 077/870] 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 3ecb756df..c5a3d0504 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 078/870] 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 74f72b826..6dc1dc008 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 a8a67245b..26fe0b042 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 fd112e293..ce7dabffb 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 00d34fadb..6a52eaf5d 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 44ad819c4..3e1d4cac8 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 df3134b9d..d038b7785 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++; + 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')); - clearPercentText.text = 'CLEAR: ${clearPercentLerp}%'; - FunkinSound.playOnce(Paths.sound('scrollMenu')); - } + // Flash background. + bgFlash.visible = true; + FlxTween.tween(bgFlash, {alpha: 0}, 0.4); - // Don't overshoot. - if (clearPercentLerp > clearPercentTarget) - { - clearPercentLerp = clearPercentTarget; - } + displayRankText(); - if (clearPercentLerp == clearPercentTarget) - { - if (rankTallyTimer != null) - { - rankTallyTimer.destroy(); - rankTallyTimer = null; + new FlxTimer().start(2.0, _ -> { + // remove(clearPercentCounter); + + afterRankTallySequence(); + }); } - - // Play confirm sound. - FunkinSound.playOnce(Paths.sound('confirmMenu')); - - new FlxTimer().start(1.0, _ -> { - remove(clearPercentText); - - afterRankTallySequence(); - }); - } - }, 0); // 0 = Loop until stopped + }); + 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"); - if (params.isNewHighscore) + // scorePopin.visible = true; + + 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 000000000..4c03ec3a9 --- /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 acbe59edd..08614e307 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 3ed59e726..9e308cb10 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 239068288..dbf223dc8 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 466dbbb90..fcff41dfd 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 079/870] 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 0d63cb6cc..e73b2860c 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 080/870] 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 81331b266..e7950f0bd 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 081/870] 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 7a21a6e8f..558a34834 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 082/870] 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 95c378b24..bc26ad97a 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 083/870] 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 44ad819c4..5b95c467c 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) + 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 { // 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 6a18f17d5..220b6723c 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 084/870] 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 fd112e293..778e16705 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 26380947a..bd25139a7 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 277dcd9e1..a3305c4ec 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 ab2abda8e..fdfac7f72 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 fb9d9b4e2..c345871a9 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 23d8d2198..5da78e9df 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 a313981f4..980f5db4f 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 f85307c64..80a421d80 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 2f3b570b3..4e706c612 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 085/870] 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 3cd3af070..4f1c66ade 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 086/870] 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 aeb6dd0e4..7c20358a4 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 087/870] 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 b75cd8bf1..d426abaaf 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 92b84168e1007342997bf0f7ee4619c4ad09e25f Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Mon, 20 May 2024 02:56:57 +0200 Subject: [PATCH 088/870] Add camOther to fix zooms on pause and stickers --- source/funkin/play/PlayState.hx | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 43dd485cf..20b9d3661 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -491,9 +491,9 @@ class PlayState extends MusicBeatSubState public var camGame:FlxCamera; /** - * The camera which contains, and controls visibility of, a video cutscene. + * The camera which contains, and controls visibility of, a video cutscene, dialogue, pause menu and sticker transition. */ - public var camCutscene:FlxCamera; + public var camOther:FlxCamera; /** * The combo popups. Includes the real-time combo counter and the rating. @@ -960,7 +960,7 @@ class PlayState extends MusicBeatSubState FlxTransitionableState.skipNextTransIn = true; FlxTransitionableState.skipNextTransOut = true; - pauseSubState.camera = camHUD; + pauseSubState.camera = camOther; openSubState(pauseSubState); // boyfriendPos.put(); // TODO: Why is this here? } @@ -1501,12 +1501,12 @@ class PlayState extends MusicBeatSubState camGame.bgColor = BACKGROUND_COLOR; // Show a pink background behind the stage. camHUD = new FlxCamera(); camHUD.bgColor.alpha = 0; // Show the game scene behind the camera. - camCutscene = new FlxCamera(); - camCutscene.bgColor.alpha = 0; // Show the game scene behind the camera. + camOther = new FlxCamera(); + camOther.bgColor.alpha = 0; // Show the game scene behind the camera. FlxG.cameras.reset(camGame); FlxG.cameras.add(camHUD, false); - FlxG.cameras.add(camCutscene, false); + FlxG.cameras.add(camOther, false); // Configure camera follow point. if (previousCameraFollowPoint != null) @@ -1900,7 +1900,6 @@ class PlayState extends MusicBeatSubState if (!result) return; isInCutscene = false; - camCutscene.visible = false; // TODO: Maybe tween in the camera after any cutscenes. camHUD.visible = true; @@ -1919,7 +1918,7 @@ class PlayState extends MusicBeatSubState if (!currentConversation.alive) currentConversation.revive(); currentConversation.completeCallback = onConversationComplete; - currentConversation.cameras = [camCutscene]; + currentConversation.cameras = [camOther]; currentConversation.zIndex = 1000; add(currentConversation); refresh(); @@ -2751,7 +2750,7 @@ class PlayState extends MusicBeatSubState persistentUpdate = false; FlxTransitionableState.skipNextTransIn = true; FlxTransitionableState.skipNextTransOut = true; - pauseSubState.camera = camCutscene; + pauseSubState.camera = camOther; openSubState(pauseSubState); } } @@ -2767,7 +2766,7 @@ class PlayState extends MusicBeatSubState persistentUpdate = false; FlxTransitionableState.skipNextTransIn = true; FlxTransitionableState.skipNextTransOut = true; - pauseSubState.camera = camCutscene; + pauseSubState.camera = camOther; openSubState(pauseSubState); } } 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 089/870] 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 a9ca09ce8..88fea72ac 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 090/870] 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 6d6e73e80..f8b1be9d2 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 7a21a6e8f..9af4e299f 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 0a6f1abd33d8cb474dcd8efe81380e5736538fc8 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Mon, 20 May 2024 23:52:45 +0200 Subject: [PATCH 091/870] Fix references to camCutscene --- source/funkin/play/cutscene/VideoCutscene.hx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/source/funkin/play/cutscene/VideoCutscene.hx b/source/funkin/play/cutscene/VideoCutscene.hx index 01a492a77..2177114aa 100644 --- a/source/funkin/play/cutscene/VideoCutscene.hx +++ b/source/funkin/play/cutscene/VideoCutscene.hx @@ -81,12 +81,11 @@ class VideoCutscene // Trigger the cutscene. Don't play the song in the background. PlayState.instance.isInCutscene = true; PlayState.instance.camHUD.visible = false; - PlayState.instance.camCutscene.visible = true; // Display a black screen to hide the game while the video is playing. blackScreen = new FlxSprite(-200, -200).makeGraphic(FlxG.width * 2, FlxG.height * 2, FlxColor.BLACK); blackScreen.scrollFactor.set(0, 0); - blackScreen.cameras = [PlayState.instance.camCutscene]; + blackScreen.cameras = [PlayState.instance.camOther]; PlayState.instance.add(blackScreen); VideoCutscene.cutsceneType = cutsceneType; @@ -120,7 +119,7 @@ class VideoCutscene vid.finishCallback = finishVideo.bind(0.5); - vid.cameras = [PlayState.instance.camCutscene]; + vid.cameras = [PlayState.instance.camOther]; PlayState.instance.add(vid); @@ -147,7 +146,7 @@ class VideoCutscene vid.bitmap.onEndReached.add(finishVideo.bind(0.5)); vid.autoPause = false; - vid.cameras = [PlayState.instance.camCutscene]; + vid.cameras = [PlayState.instance.camOther]; PlayState.instance.add(vid); @@ -305,7 +304,6 @@ class VideoCutscene vid = null; #end - PlayState.instance.camCutscene.visible = true; PlayState.instance.camHUD.visible = true; FlxTween.tween(blackScreen, {alpha: 0}, transitionTime, From f3868c2ee8d9dcf9488c349d8509545f0113f010 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 21 May 2024 02:23:21 -0400 Subject: [PATCH 092/870] 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 c359d7a51..1fe5a923d 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 acbe59edd..dbba4a4c4 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 3ed59e726..7f597b4ec 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 2f0c3818a..2a6b345d3 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 247ba19db..8f5550662 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 093/870] 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 1983d413b..cede0b688 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 acbe59edd..7b2d3f511 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 3fa9839d1..7c9094f2d 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 239068288..911d07a56 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 094/870] 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 fcfcfb9f3..b5630a46a 100644 --- a/Project.xml +++ b/Project.xml @@ -128,6 +128,7 @@ + diff --git a/source/funkin/import.hx b/source/funkin/import.hx index 250de99cb..c8431be33 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 23d8d2198..53408fb34 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 7f597b4ec..5398b2119 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 ffc756e1c..5a3efc36a 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 2a6b345d3..000000000 --- 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 caf8e8aab..0fe245e3a 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 095/870] 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 5398b2119..650666c5c 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 8f5550662..18d7eafa6 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 b0e7ed184..c40257409 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 096/870] 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 43dd485cf..dc07e1910 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 f85307c64..98e263aaf 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 47cbd4b62038cbd07079b7c1d6ee88c73d54d724 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 21 May 2024 19:11:10 -0400 Subject: [PATCH 097/870] Update compiling guide with more troubleshooting --- docs/COMPILING.md | 62 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index 07df6367f..b08fc528e 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -21,4 +21,64 @@ # 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`. +While performing the process of compilation, you may experience one of the following issues: + +## PolymodHandler: extra field coreAssetRedirect + +``` +Installing funkin.vis from https://github.com/FunkinCrew/funkVis branch: 98c9db09f0bbfedfe67a84538a5814aaef80bdea +Error: std@sys_remove_dir +Execution error: command "haxelib --never git funkin.vis https://github.com/FunkinCrew/funkVis 98c9db09f0bbfedfe67a84538a5814aaef80bdea" failed with status: 1 in cwd +``` + +If you receive this error, you are on an outdated version of Polymod. + +To solve, you should try reinstalling Polymod: + +``` +haxelib run hmm reinstall --force polymod +``` + +You can also try deleting your `.haxelib` folder in your Funkin' project, then reinstalling all your Haxelibs to prevent any other errors: + +``` +rm -rf ./.haxelib +haxelib run hmm reinstall --force +``` + +## PolymodHandler: Couldn't find a match for this asset library: (vlc) + +``` +source/funkin/modding/PolymodErrorHandler.hx:84: [ERROR] Your Lime/OpenFL configuration is using custom asset libraries, and you provided frameworkParams in Polymod.init(), but we couldn't find a match for this asset library: (vlc) +source/funkin/modding/PolymodHandler.hx:158: An error occurred! Failed when loading mods! +source/funkin/util/logging/CrashHandler.hx:62: Error while handling crash: Null Object Reference +``` + +This error is specific to Linux targets. If you receive this error, you are on an outdated verison of hxCodec. + +To solve, you should try reinstalling hxCodec: + +``` +haxelib run hmm reinstall --force hxCodec +``` + +You can also try deleting your `.haxelib` folder in your Funkin' project, then reinstalling all your Haxelibs to prevent any other errors: + +``` +rm -rf ./.haxelib +haxelib run hmm reinstall --force +``` + +## Git: stream 0 was not closed cleanly: PROTOCOL_ERROR + +``` +error: RPC failed; curl 92 HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR (err 1) +``` + +If you receive this error while cloning, you may be experiencing issues with your network connection. + +To solve, you should try modifying your git configuration before cloning again: + +``` +git config --global http.postBuffer 4096M +``` From f17f6393041a54e4b15418059f6a9ff9dc2a39cb Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 22 May 2024 01:07:20 -0400 Subject: [PATCH 098/870] 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 ce7dabffb..b6d930109 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 6a52eaf5d..d17554d11 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 d038b7785..fdcd0cc39 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 4c03ec3a9..d296b0b0b 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; - var clearPercentText:FunkinSprite = FunkinSprite.create(0, 0, 'resultScreen/clearPercent/clearPercentText'); + curNumber = startingNumber; + + 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 099/870] 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 0c2214529..820ac2ad1 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 100/870] Fix an issue with git modules --- .gitmodules | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index be5e0aaa8..2d5c11067 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 101/870] 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 957daa43c..ded00f378 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 102/870] 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 2f8231bb0..2dea92352 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 103/870] 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 2dea92352..4d1ad7019 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 104/870] 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 000000000..e8e490865 --- /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 000000000..195b22b7c --- /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 105/870] 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 195b22b7c..0bcc420d3 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 106/870] 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 5a49e29ee..aaddda9dc 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 107/870] 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 d17554d11..a945c10c5 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 fdcd0cc39..ee7c8eade 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 108/870] Update submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index b6d930109..2a57e3406 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 109/870] 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 778e16705..826be3bf1 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 110/870] Update Changelog --- CHANGELOG.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7f830047..10bbfe5f7 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 111/870] Attempt to repair local submodules --- .gitmodules | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitmodules b/.gitmodules index 2d5c11067..452c0089b 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 112/870] Take two at fixing submodules --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 66572f85d..52e007f5b 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 113/870] 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 24cdac270..03e87e2d8 100644 --- a/Project.xml +++ b/Project.xml @@ -125,6 +125,7 @@ + diff --git a/hmm.json b/hmm.json index 288aa80b8..a1998f515 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 ca77dd58a..15596318c 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 114/870] 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 31551dec9..345791eef 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 115/870] 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 118516bec..2df3a87da 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:11:34 +0200 Subject: [PATCH 116/870] add fps option --- source/Main.hx | 9 +- source/funkin/Preferences.hx | 29 +++ source/funkin/save/Save.hx | 10 +- source/funkin/ui/options/PreferencesMenu.hx | 211 ++++++++++++++++---- 4 files changed, 207 insertions(+), 52 deletions(-) diff --git a/source/Main.hx b/source/Main.hx index add5bbc67..8105e6c4f 100644 --- a/source/Main.hx +++ b/source/Main.hx @@ -2,6 +2,7 @@ package; import flixel.FlxGame; import flixel.FlxState; +import funkin.Preferences; import funkin.util.logging.CrashHandler; import funkin.ui.debug.MemoryCounter; import funkin.save.Save; @@ -22,12 +23,6 @@ class Main extends Sprite var gameHeight:Int = 720; // Height of the game in pixels (might be less / more in actual pixels depending on your zoom). var initialState:Class = funkin.InitState; // The FlxState the game starts with. var zoom:Float = -1; // If -1, zoom is automatically calculated to fit the window dimensions. - #if web - var framerate:Int = 60; // How many frames per second the game should run at. - #else - // TODO: This should probably be in the options menu? - var framerate:Int = 144; // How many frames per second the game should run at. - #end var skipSplash:Bool = true; // Whether to skip the flixel splash screen that appears in release mode. var startFullscreen:Bool = false; // Whether to start the game in fullscreen on desktop targets @@ -103,7 +98,7 @@ class Main extends Sprite // George recommends binding the save before FlxGame is created. Save.load(); - var game:FlxGame = new FlxGame(gameWidth, gameHeight, initialState, framerate, framerate, skipSplash, startFullscreen); + var game:FlxGame = new FlxGame(gameWidth, gameHeight, initialState, Preferences.framerate, Preferences.framerate, skipSplash, startFullscreen); // FlxG.game._customSoundTray wants just the class, it calls new from // create() in there, which gets called when it's added to stage diff --git a/source/funkin/Preferences.hx b/source/funkin/Preferences.hx index b2050c6a2..7a322283d 100644 --- a/source/funkin/Preferences.hx +++ b/source/funkin/Preferences.hx @@ -7,6 +7,35 @@ import funkin.save.Save; */ class Preferences { + /** + * FPS + * @default `60` + */ + public static var framerate(get, set):Int; + + static function get_framerate():Int + { + #if web + return 60; + #else + return Save?.instance?.options?.framerate ?? 60; + #end + } + + static function set_framerate(value:Int):Int + { + #if web + return 60; + #else + var save:Save = Save.instance; + save.options.framerate = value; + save.flush(); + FlxG.updateFramerate = value; + FlxG.drawFramerate = value; + return value; + #end + } + /** * Whether some particularly fowl language is displayed. * @default `true` diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx index acbe59edd..3600e9741 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 @@ -80,6 +81,7 @@ class Save options: { // Reasonable defaults. + framerate: 60, naughtyness: true, downscroll: false, flashingLights: true, @@ -835,6 +837,12 @@ typedef SaveScoreTallyData = */ typedef SaveDataOptions = { + /** + * FPS + * @default `60` + */ + var framerate:Int; + /** * Whether some particularly fowl language is displayed. * @default `true` diff --git a/source/funkin/ui/options/PreferencesMenu.hx b/source/funkin/ui/options/PreferencesMenu.hx index 783aef0ba..cf7296584 100644 --- a/source/funkin/ui/options/PreferencesMenu.hx +++ b/source/funkin/ui/options/PreferencesMenu.hx @@ -3,16 +3,16 @@ package funkin.ui.options; import flixel.FlxCamera; import flixel.FlxObject; import flixel.FlxSprite; +import flixel.math.FlxMath; import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup; import funkin.ui.AtlasText.AtlasFont; import funkin.ui.options.OptionsState.Page; import funkin.graphics.FunkinCamera; -import funkin.ui.TextMenuList.TextMenuItem; class PreferencesMenu extends Page { - var items:TextMenuList; - var preferenceItems:FlxTypedSpriteGroup; + var curSelected:Int = 0; + var prefs:FlxTypedSpriteGroup; var menuCamera:FlxCamera; var camFollow:FlxObject; @@ -26,22 +26,27 @@ class PreferencesMenu extends Page menuCamera.bgColor = 0x0; camera = menuCamera; - add(items = new TextMenuList()); - add(preferenceItems = new FlxTypedSpriteGroup()); + prefs = new FlxTypedSpriteGroup(); + add(prefs); createPrefItems(); camFollow = new FlxObject(FlxG.width / 2, 0, 140, 70); - if (items != null) camFollow.y = items.selectedItem.y; menuCamera.follow(camFollow, null, 0.06); var margin = 160; menuCamera.deadzone.set(0, margin, menuCamera.width, 40); menuCamera.minScrollY = 0; - items.onChange.add(function(selected) { - camFollow.y = selected.y; - }); + changeSelection(0); + } + + function addPref(pref:PreferenceItem):Void + { + pref.x = 0; + pref.y = 120 * prefs.length; + pref.ID = prefs.length; + prefs.add(pref); } /** @@ -49,50 +54,168 @@ class PreferencesMenu extends Page */ function createPrefItems():Void { - createPrefItemCheckbox('Naughtyness', 'Toggle displaying raunchy content', function(value:Bool):Void { - Preferences.naughtyness = value; - }, Preferences.naughtyness); - createPrefItemCheckbox('Downscroll', 'Enable to make notes move downwards', function(value:Bool):Void { - Preferences.downscroll = value; - }, Preferences.downscroll); - createPrefItemCheckbox('Flashing Lights', 'Disable to dampen flashing effects', function(value:Bool):Void { - Preferences.flashingLights = value; - }, Preferences.flashingLights); - createPrefItemCheckbox('Camera Zooming on Beat', 'Disable to stop the camera bouncing to the song', function(value:Bool):Void { - Preferences.zoomCamera = value; - }, Preferences.zoomCamera); - createPrefItemCheckbox('Debug Display', 'Enable to show FPS and other debug stats', function(value:Bool):Void { - Preferences.debugDisplay = value; - }, Preferences.debugDisplay); - createPrefItemCheckbox('Auto Pause', 'Automatically pause the game when it loses focus', function(value:Bool):Void { - Preferences.autoPause = value; - }, Preferences.autoPause); + #if !web + var pref:NumberedPreferenceItem = new NumberedPreferenceItem("FPS", "The framerate that the game is running on", Preferences.framerate, + function(value:Float):Void { + Preferences.framerate = Std.int(value); + }); + pref.minValue = 60; + pref.maxValue = 360; + pref.changeRate = 1; + pref.changeSpeed = 0.05; + addPref(pref); + #end + + // TODO: add these back + // createPrefItemCheckbox('Naughtyness', 'Toggle displaying raunchy content', function(value:Bool):Void { + // Preferences.naughtyness = value; + // }, Preferences.naughtyness); + // createPrefItemCheckbox('Downscroll', 'Enable to make notes move downwards', function(value:Bool):Void { + // Preferences.downscroll = value; + // }, Preferences.downscroll); + // createPrefItemCheckbox('Flashing Lights', 'Disable to dampen flashing effects', function(value:Bool):Void { + // Preferences.flashingLights = value; + // }, Preferences.flashingLights); + // createPrefItemCheckbox('Camera Zooming on Beat', 'Disable to stop the camera bouncing to the song', function(value:Bool):Void { + // Preferences.zoomCamera = value; + // }, Preferences.zoomCamera); + // createPrefItemCheckbox('Debug Display', 'Enable to show FPS and other debug stats', function(value:Bool):Void { + // Preferences.debugDisplay = value; + // }, Preferences.debugDisplay); + // createPrefItemCheckbox('Auto Pause', 'Automatically pause the game when it loses focus', function(value:Bool):Void { + // Preferences.autoPause = value; + // }, Preferences.autoPause); } - function createPrefItemCheckbox(prefName:String, prefDesc:String, onChange:Bool->Void, defaultValue:Bool):Void + function changeSelection(change:Int):Void { - var checkbox:CheckboxPreferenceItem = new CheckboxPreferenceItem(0, 120 * (items.length - 1 + 1), defaultValue); + curSelected += change; + if (curSelected < 0) + { + curSelected = prefs.length - 1; + } + else if (curSelected >= prefs.length) + { + curSelected = 0; + } - items.createItem(120, (120 * items.length) + 30, prefName, AtlasFont.BOLD, function() { - var value = !checkbox.currentValue; - onChange(value); - checkbox.currentValue = value; - }); - - preferenceItems.add(checkbox); + for (pref in prefs) + { + pref.x = 0; + if (pref.ID == curSelected) + { + pref.x = 20; + camFollow.y = pref.y; + } + } } - override function update(elapsed:Float) + override function update(elapsed:Float):Void { super.update(elapsed); - // Indent the selected item. - // TODO: Only do this on menu change? - items.forEach(function(daItem:TextMenuItem) { - if (items.selectedItem == daItem) daItem.x = 150; - else - daItem.x = 120; - }); + if (controls.UI_DOWN_P) + { + changeSelection(1); + } + else if (controls.UI_UP_P) + { + changeSelection(-1); + } + + var selectedPref:PreferenceItem = prefs.members[curSelected]; + selectedPref.handleInput(elapsed); + } +} + +class PreferenceItem extends FlxTypedSpriteGroup +{ + public var name:String = ""; + public var description:String = ""; + + public function handleInput(deltaTime:Float):Void {} +} + +class NumberedPreferenceItem extends PreferenceItem +{ + public var onChange:Float->Void; + public var changeRate:Float = 1.0; + public var changeSpeed:Float = 0.1; + + public var minValue(default, set):Null; + + function set_minValue(value:Float):Float + { + minValue = value; + currentValue = currentValue; + return value; + } + + public var maxValue(default, set):Null; + + function set_maxValue(value:Float):Float + { + maxValue = value; + currentValue = currentValue; + return value; + } + + public var currentValue(default, set):Float; + + function set_currentValue(value:Float):Float + { + currentValue = FlxMath.bound(value, minValue, maxValue); + onChange(currentValue); + updateText(); + return currentValue; + } + + var valueText:AtlasText; + var preferenceText:AtlasText; + + public function new(name:String, description:String, defaultValue:Float, onChange:Float->Void) + { + super(); + + this.valueText = new AtlasText(0, 0, '$defaultValue', AtlasFont.DEFAULT); + add(this.valueText); + + this.preferenceText = new AtlasText(this.valueText.width + 30, 0, '$name', AtlasFont.BOLD); + add(this.preferenceText); + + this.name = name; + this.description = description; + this.onChange = onChange; + this.currentValue = defaultValue; + } + + var timeToWait:Float = 0; + + public override function handleInput(deltaTime:Float):Void + { + timeToWait -= deltaTime; + + if (timeToWait > 0) + { + return; + } + + if (PlayerSettings.player1.controls.UI_RIGHT) + { + currentValue += changeRate; + timeToWait = changeSpeed; + } + else if (PlayerSettings.player1.controls.UI_LEFT) + { + currentValue -= changeRate; + timeToWait = changeSpeed; + } + } + + function updateText():Void + { + valueText.text = '$currentValue'; + preferenceText.x = valueText.width + 30; } } From dd6d12de2340563bcbe254b36977d119085a06aa Mon Sep 17 00:00:00 2001 From: lemz Date: Sat, 25 May 2024 01:20:10 +0200 Subject: [PATCH 117/870] rename vars --- source/funkin/ui/options/PreferencesMenu.hx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/source/funkin/ui/options/PreferencesMenu.hx b/source/funkin/ui/options/PreferencesMenu.hx index cf7296584..87917ad70 100644 --- a/source/funkin/ui/options/PreferencesMenu.hx +++ b/source/funkin/ui/options/PreferencesMenu.hx @@ -62,7 +62,7 @@ class PreferencesMenu extends Page pref.minValue = 60; pref.maxValue = 360; pref.changeRate = 1; - pref.changeSpeed = 0.05; + pref.changeDelay = 0.05; addPref(pref); #end @@ -133,14 +133,14 @@ class PreferenceItem extends FlxTypedSpriteGroup public var name:String = ""; public var description:String = ""; - public function handleInput(deltaTime:Float):Void {} + public function handleInput(elapsed:Float):Void {} } class NumberedPreferenceItem extends PreferenceItem { public var onChange:Float->Void; public var changeRate:Float = 1.0; - public var changeSpeed:Float = 0.1; + public var changeDelay:Float = 0.1; public var minValue(default, set):Null; @@ -191,9 +191,9 @@ class NumberedPreferenceItem extends PreferenceItem var timeToWait:Float = 0; - public override function handleInput(deltaTime:Float):Void + public override function handleInput(elapsed:Float):Void { - timeToWait -= deltaTime; + timeToWait -= elapsed; if (timeToWait > 0) { @@ -203,12 +203,12 @@ class NumberedPreferenceItem extends PreferenceItem if (PlayerSettings.player1.controls.UI_RIGHT) { currentValue += changeRate; - timeToWait = changeSpeed; + timeToWait = changeDelay; } else if (PlayerSettings.player1.controls.UI_LEFT) { currentValue -= changeRate; - timeToWait = changeSpeed; + timeToWait = changeDelay; } } From 4acfbfb76ddae10fae3cf848c1b7bbf4524baa55 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Sat, 25 May 2024 01:21:37 +0200 Subject: [PATCH 118/870] 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 ab2abda8e..87f3f8136 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 b75f6e58532534dd94cef1c93c24270e1f56425e Mon Sep 17 00:00:00 2001 From: lemz Date: Sat, 25 May 2024 02:19:11 +0200 Subject: [PATCH 119/870] Update PreferencesMenu.hx --- source/funkin/ui/options/PreferencesMenu.hx | 136 ++++++++++++-------- 1 file changed, 81 insertions(+), 55 deletions(-) diff --git a/source/funkin/ui/options/PreferencesMenu.hx b/source/funkin/ui/options/PreferencesMenu.hx index 87917ad70..acbb57525 100644 --- a/source/funkin/ui/options/PreferencesMenu.hx +++ b/source/funkin/ui/options/PreferencesMenu.hx @@ -66,25 +66,41 @@ class PreferencesMenu extends Page addPref(pref); #end - // TODO: add these back - // createPrefItemCheckbox('Naughtyness', 'Toggle displaying raunchy content', function(value:Bool):Void { - // Preferences.naughtyness = value; - // }, Preferences.naughtyness); - // createPrefItemCheckbox('Downscroll', 'Enable to make notes move downwards', function(value:Bool):Void { - // Preferences.downscroll = value; - // }, Preferences.downscroll); - // createPrefItemCheckbox('Flashing Lights', 'Disable to dampen flashing effects', function(value:Bool):Void { - // Preferences.flashingLights = value; - // }, Preferences.flashingLights); - // createPrefItemCheckbox('Camera Zooming on Beat', 'Disable to stop the camera bouncing to the song', function(value:Bool):Void { - // Preferences.zoomCamera = value; - // }, Preferences.zoomCamera); - // createPrefItemCheckbox('Debug Display', 'Enable to show FPS and other debug stats', function(value:Bool):Void { - // Preferences.debugDisplay = value; - // }, Preferences.debugDisplay); - // createPrefItemCheckbox('Auto Pause', 'Automatically pause the game when it loses focus', function(value:Bool):Void { - // Preferences.autoPause = value; - // }, Preferences.autoPause); + var pref:CheckboxPreferenceItem = new CheckboxPreferenceItem('Naughtyness', 'Toggle displaying raunchy content', Preferences.naughtyness, + function(value:Bool):Void { + Preferences.naughtyness = value; + }); + addPref(pref); + + var pref:CheckboxPreferenceItem = new CheckboxPreferenceItem('Downscroll', 'Enable to make notes move downwards', Preferences.downscroll, + function(value:Bool):Void { + Preferences.downscroll = value; + }); + addPref(pref); + + var pref:CheckboxPreferenceItem = new CheckboxPreferenceItem('Flashing Lights', 'Disable to dampen flashing effects', Preferences.flashingLights, + function(value:Bool):Void { + Preferences.flashingLights = value; + }); + addPref(pref); + + var pref:CheckboxPreferenceItem = new CheckboxPreferenceItem('Camera Zooming on Beat', 'Disable to stop the camera bouncing to the song', + Preferences.zoomCamera, function(value:Bool):Void { + Preferences.zoomCamera = value; + }); + addPref(pref); + + var pref:CheckboxPreferenceItem = new CheckboxPreferenceItem('Debug Display', 'Enable to show FPS and other debug stats', Preferences.debugDisplay, + function(value:Bool):Void { + Preferences.debugDisplay = value; + }); + addPref(pref); + + var pref:CheckboxPreferenceItem = new CheckboxPreferenceItem('Auto Pause', 'Automatically pause the game when it loses focus', Preferences.autoPause, + function(value:Bool):Void { + Preferences.autoPause = value; + }); + addPref(pref); } function changeSelection(change:Int):Void @@ -104,7 +120,7 @@ class PreferencesMenu extends Page pref.x = 0; if (pref.ID == curSelected) { - pref.x = 20; + pref.x = 30; camFollow.y = pref.y; } } @@ -124,7 +140,7 @@ class PreferencesMenu extends Page } var selectedPref:PreferenceItem = prefs.members[curSelected]; - selectedPref.handleInput(elapsed); + selectedPref?.handleInput(elapsed); } } @@ -177,10 +193,10 @@ class NumberedPreferenceItem extends PreferenceItem { super(); - this.valueText = new AtlasText(0, 0, '$defaultValue', AtlasFont.DEFAULT); + this.valueText = new AtlasText(20, 30, '$defaultValue', AtlasFont.DEFAULT); add(this.valueText); - this.preferenceText = new AtlasText(this.valueText.width + 30, 0, '$name', AtlasFont.BOLD); + this.preferenceText = new AtlasText(this.valueText.x + this.valueText.width + 30, 30, '$name', AtlasFont.BOLD); add(this.preferenceText); this.name = name; @@ -215,52 +231,62 @@ class NumberedPreferenceItem extends PreferenceItem function updateText():Void { valueText.text = '$currentValue'; - preferenceText.x = valueText.width + 30; + preferenceText.x = valueText.x + valueText.width + 30; } } -class CheckboxPreferenceItem extends FlxSprite +class CheckboxPreferenceItem extends PreferenceItem { + public var onChange:Bool->Void; + public var currentValue(default, set):Bool; - public function new(x:Float, y:Float, defaultValue:Bool = false) - { - super(x, y); - - frames = Paths.getSparrowAtlas('checkboxThingie'); - animation.addByPrefix('static', 'Check Box unselected', 24, false); - animation.addByPrefix('checked', 'Check Box selecting animation', 24, false); - - setGraphicSize(Std.int(width * 0.7)); - updateHitbox(); - - this.currentValue = defaultValue; - } - - override function update(elapsed:Float) - { - super.update(elapsed); - - switch (animation.curAnim.name) - { - case 'static': - offset.set(); - case 'checked': - offset.set(17, 70); - } - } - function set_currentValue(value:Bool):Bool { if (value) { - animation.play('checked', true); + checkBox.animation.play('checked', true); + checkBox.offset.set(17, 70); } else { - animation.play('static'); + checkBox.animation.play('static'); + checkBox.offset.set(); } + currentValue = value; + onChange(value); + return value; + } - return currentValue = value; + var checkBox:FlxSprite; + var preferenceText:AtlasText; + + public function new(name:String, description:String, defaultValue:Bool, onChange:Bool->Void) + { + super(); + + this.checkBox = new FlxSprite(); + this.checkBox.frames = Paths.getSparrowAtlas('checkboxThingie'); + this.checkBox.animation.addByPrefix('static', 'Check Box unselected', 24, false); + this.checkBox.animation.addByPrefix('checked', 'Check Box selecting animation', 24, false); + this.checkBox.setGraphicSize(Std.int(this.checkBox.width * 0.7)); + this.checkBox.updateHitbox(); + add(this.checkBox); + + this.preferenceText = new AtlasText(120, 30, '$name', AtlasFont.BOLD); + add(this.preferenceText); + + this.name = name; + this.description = description; + this.onChange = onChange; + this.currentValue = defaultValue; + } + + public override function handleInput(elapsed:Float):Void + { + if (PlayerSettings.player1.controls.ACCEPT) + { + currentValue = !currentValue; + } } } From 814d72cb3f241c61896adda8e6f84435ff056f4a Mon Sep 17 00:00:00 2001 From: lemz Date: Sat, 25 May 2024 03:06:27 +0200 Subject: [PATCH 120/870] sounds --- source/funkin/ui/options/PreferencesMenu.hx | 28 ++++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/source/funkin/ui/options/PreferencesMenu.hx b/source/funkin/ui/options/PreferencesMenu.hx index acbb57525..75bc0fdb3 100644 --- a/source/funkin/ui/options/PreferencesMenu.hx +++ b/source/funkin/ui/options/PreferencesMenu.hx @@ -4,13 +4,20 @@ import flixel.FlxCamera; import flixel.FlxObject; import flixel.FlxSprite; import flixel.math.FlxMath; +import flixel.effects.FlxFlicker; import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup; import funkin.ui.AtlasText.AtlasFont; import funkin.ui.options.OptionsState.Page; import funkin.graphics.FunkinCamera; +import funkin.audio.FunkinSound; class PreferencesMenu extends Page { + /** + * Wether you can selected a different option + */ + public static var allowScrolling:Bool = true; + var curSelected:Int = 0; var prefs:FlxTypedSpriteGroup; @@ -130,12 +137,14 @@ class PreferencesMenu extends Page { super.update(elapsed); - if (controls.UI_DOWN_P) + if (controls.UI_DOWN_P && allowScrolling) { + FunkinSound.playOnce(Paths.sound('scrollMenu')); changeSelection(1); } - else if (controls.UI_UP_P) + else if (controls.UI_UP_P && allowScrolling) { + FunkinSound.playOnce(Paths.sound('scrollMenu')); changeSelection(-1); } @@ -220,11 +229,13 @@ class NumberedPreferenceItem extends PreferenceItem { currentValue += changeRate; timeToWait = changeDelay; + // FunkinSound.playOnce(Paths.sound('scrollMenu')); } else if (PlayerSettings.player1.controls.UI_LEFT) { currentValue -= changeRate; timeToWait = changeDelay; + // FunkinSound.playOnce(Paths.sound('scrollMenu')); } } @@ -282,11 +293,20 @@ class CheckboxPreferenceItem extends PreferenceItem this.currentValue = defaultValue; } + var isAccepting:Bool = false; + public override function handleInput(elapsed:Float):Void { - if (PlayerSettings.player1.controls.ACCEPT) + if (PlayerSettings.player1.controls.ACCEPT && !isAccepting) { - currentValue = !currentValue; + isAccepting = true; + PreferencesMenu.allowScrolling = false; + FunkinSound.playOnce(Paths.sound('confirmMenu')); + FlxFlicker.flicker(preferenceText, 1, 0.06, true, false, function(_) { + isAccepting = false; + PreferencesMenu.allowScrolling = true; + currentValue = !currentValue; + }); } } } From 267fd0eadcaceedc69bae06bf3d3344f4251bfdc Mon Sep 17 00:00:00 2001 From: lemz Date: Sat, 25 May 2024 16:30:08 +0200 Subject: [PATCH 121/870] alpha stuff and correct text positioning --- source/funkin/ui/options/PreferencesMenu.hx | 42 +++++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/source/funkin/ui/options/PreferencesMenu.hx b/source/funkin/ui/options/PreferencesMenu.hx index 75bc0fdb3..4e9e0bca8 100644 --- a/source/funkin/ui/options/PreferencesMenu.hx +++ b/source/funkin/ui/options/PreferencesMenu.hx @@ -124,12 +124,15 @@ class PreferencesMenu extends Page for (pref in prefs) { - pref.x = 0; if (pref.ID == curSelected) { - pref.x = 30; + pref.onSelect(true); camFollow.y = pref.y; } + else + { + pref.onSelect(false); + } } } @@ -159,6 +162,8 @@ class PreferenceItem extends FlxTypedSpriteGroup public var description:String = ""; public function handleInput(elapsed:Float):Void {} + + public function onSelect(isSelected:Bool):Void {} } class NumberedPreferenceItem extends PreferenceItem @@ -239,10 +244,27 @@ class NumberedPreferenceItem extends PreferenceItem } } + var isSelected:Bool = false; + + public override function onSelect(isSelected:Bool):Void + { + this.isSelected = isSelected; + if (isSelected) + { + preferenceText.x = valueText.x + valueText.width + 60; + preferenceText.alpha = 1.0; + } + else + { + preferenceText.x = valueText.x + valueText.width + 30; + preferenceText.alpha = 0.6; + } + } + function updateText():Void { valueText.text = '$currentValue'; - preferenceText.x = valueText.x + valueText.width + 30; + preferenceText.x = valueText.x + valueText.width + (isSelected ? 60 : 30); } } @@ -309,4 +331,18 @@ class CheckboxPreferenceItem extends PreferenceItem }); } } + + public override function onSelect(isSelected:Bool):Void + { + if (isSelected) + { + preferenceText.x = 150; + preferenceText.alpha = 1.0; + } + else + { + preferenceText.alpha = 0.6; + preferenceText.x = 120; + } + } } 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 122/870] [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 eb9eb1810..e9c99558d 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 123/870] update funkVis in hmm --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index a1998f515..e364e405f 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 124/870] 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 9616dfe18..77e44bd1d 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 c1f8ad3ba..3f5fc078a 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 df05cc3ef..939b17f28 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 5037ee1d0..9a1e0e0c1 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 ca77dd58a..b94f20b38 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 cc68f4ae0..bff845796 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 636c0726a..615e80d95 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 204ced1e1..ba235fe89 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 dc75acb81..40ee9cb8c 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 1f649b472..a939f91bf 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 32ced2fbd..8eaba8117 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 30e3f451b..650519836 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 ca072897f..fad1e43ad 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 125/870] 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 31551dec9..345791eef 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 126/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 8a8239cb5..371cce1fd 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 127/870] 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 2df3a87da..118516bec 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 128/870] 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 24cdac270..dce45546f 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 129/870] flxpartialsound lock to current version --- hmm.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hmm.json b/hmm.json index 6b119c52f..5260d5229 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 130/870] 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 aaddda9dc..39a26aac1 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 131/870] update hmm flxpartialsound --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index 5260d5229..91d2f08bb 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 132/870] 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 820ac2ad1..c1a001e5d 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 133/870] 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 b71af2b3b..9d2569588 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 134/870] remove random < in project.xml lol --- Project.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/Project.xml b/Project.xml index 16e4b9854..fcd29a25e 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 4a531888b550f10564f058b8d2155645d33a7867 Mon Sep 17 00:00:00 2001 From: lemz Date: Thu, 30 May 2024 00:22:10 +0200 Subject: [PATCH 135/870] Update PreferencesMenu.hx --- source/funkin/ui/options/PreferencesMenu.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/options/PreferencesMenu.hx b/source/funkin/ui/options/PreferencesMenu.hx index 4e9e0bca8..205ef1809 100644 --- a/source/funkin/ui/options/PreferencesMenu.hx +++ b/source/funkin/ui/options/PreferencesMenu.hx @@ -14,7 +14,7 @@ import funkin.audio.FunkinSound; class PreferencesMenu extends Page { /** - * Wether you can selected a different option + * Wether you can select a different option */ public static var allowScrolling:Bool = true; From 8d7591a796f9c0c392eb66c8e494d5f9a7a5e36a Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 29 May 2024 21:43:54 -0400 Subject: [PATCH 136/870] 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 5a3efc36a..0547404a1 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 137/870] 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 c345871a9..8c45fac65 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 138/870] 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 9abd4be90..c752d2f6d 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 139/870] 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 000000000..545739cc3 --- /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 140/870] 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 3a520e015..c3fd51d1f 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 5f1144fab..248526aaf 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 7b7543845..a665f0756 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 f6d85e56e..0f72199ba 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 141/870] update assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index fe52d20de..dabdf9b1d 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 142/870] 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 | 99 +++++---- 8 files changed, 389 insertions(+), 241 deletions(-) diff --git a/assets b/assets index 8fea0bf1f..2719d3fc1 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 a945c10c5..d0009f95b 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 a95166e21..e69a50b00 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 ee7c8eade..79880038d 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 744091b44..6155ec879 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 934d6a4aa..7f25a8e01 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 530f28c33..904a2ca4a 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 536a9cfe6..ad6ea386e 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; + public var rank(default, set):Null = null; - var numToRank:Array = ["LOSS", "GOOD", "GREAT", "EXCELLENT", "PERFECT", "PERFECTSICK"]; - - 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: - // offset.x -= 1; - offset.y -= 8; - case 3: - // offset.y += 5; - case 4: - // offset.y += 5; - default: - centerOffsets(false); + this.visible = false; } - updateHitbox(); - return val; + else + { + this.visible = true; + + animation.play(val.getFreeplayRankIconAsset(), true, false); + + centerOffsets(false); + + switch (val) + { + case SHIT: + // offset.x -= 1; + 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(); + } + + 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 143/870] 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 c9b3619e9..c6dbcd505 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 144/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 2719d3fc1..4bc0b35f6 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 145/870] 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 ad6ea386e..75a4c07a3 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 146/870] art submod --- art | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/art b/art index 66572f85d..faeba700c 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 147/870] update difficulties --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 4bc0b35f6..11bcd1b79 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 148/870] 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 11bcd1b79..7a0d92d30 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 d0009f95b..c7a08d714 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 79880038d..8b8c0aea3 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 149/870] Disable song previews for mod songs rather than crashing the game --- source/funkin/audio/FunkinSound.hx | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index b94c6008c..7663c1305 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"); - }); + 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); - }); + 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 150/870] 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 192c6e3ce..f0695e51e 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 151/870] 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 b94c6008c..cf4a71189 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 152/870] 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 79880038d..1ad19b41e 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 6155ec879..f941f3f01 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 6be1fecf7..44769e9b3 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 50f4a432c..20cd91379 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 192c6e3ce..186c84c33 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 ad6ea386e..b52032bc3 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 22262006a..c504b3c3e 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 153/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 4bc0b35f6..d64939d86 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 154/870] 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 192c6e3ce..71052a923 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 155/870] 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 bd25139a7..ca805e139 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 156/870] 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 0308cd871..a78eeae4c 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 157/870] 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 4e706c612..1e0978839 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 158/870] 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 ca805e139..769af8f08 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 dd0d28479..04b5a1b69 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 22b883c75..bebd86d02 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 2240ec50e..844d0f4db 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 a78eeae4c..e84f7ec43 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 159/870] Readd a reverted freeplay bugfix --- source/funkin/audio/FunkinSound.hx | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index b94c6008c..7663c1305 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"); - }); + 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); - }); + 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 160/870] Update the changelog --- CHANGELOG.md | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10bbfe5f7..f5aefb885 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 161/870] 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 d5d5a6567..23e6c8d32 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 162/870] results timing redo + fixed anims for all ranks --- source/funkin/play/ResultState.hx | 280 +++++++++++++++++++++----- source/funkin/play/scoring/Scoring.hx | 70 ++++++- 2 files changed, 293 insertions(+), 57 deletions(-) diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index 8b8c0aea3..8a7332a83 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); - // Scrolling. - rankTextVert.velocity.y = -50; + FlxFlicker.flicker(rankTextVert, 2/24 * 3, 2/24, true); - for (i in 0...10) + // Scrolling. + 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); 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 6155ec879..04bd81cf8 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 163/870] assets submod.. --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 7a0d92d30..de73a8ec8 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 164/870] Update assets submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 7a0d92d30..59d376218 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 165/870] 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 192c6e3ce..1bde92667 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 166/870] Add new charts --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 59d376218..0e5a66cb1 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 167/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 0e5a66cb1..3bfa4e3da 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 168/870] 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 6155ec879..a6d92454b 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 169/870] 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 1ad19b41e..d38731e14 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 186c84c33..e1d8eb81c 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 b52032bc3..3af75c105 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 170/870] assets submod!! --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index d64939d86..ad8a0a28a 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 171/870] 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 e1d8eb81c..e97ab391b 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 172/870] 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 e97ab391b..0dd520ee3 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 173/870] 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 6441c9cd5..218ecc2ab 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 174/870] 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 478a13269..af3281c4b 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 175/870] 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 8b8c0aea3..35976c359 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 176/870] 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 fe4e56dd9..f94b662ac 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 177/870] 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 d3471eeb1..494bc20f0 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 41010f0b5..b9fef5a79 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 178/870] fabs --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index d9ea5ebe5..f7c418c52 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 179/870] 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 f7c418c52..3766c3b67 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 1740c0371..6f540687f 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 180/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 3766c3b67..1f3e2932e 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 181/870] Update assets submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 1f3e2932e..4039bd018 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 182/870] 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 7f25a8e01..7634c1f51 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 4fa9dd6b3..b7d278cc6 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 18d7eafa6..b84b66341 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 183/870] 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 494bc20f0..fe64a1e6f 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 184/870] 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 20cd91379..49c588722 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 51526bcbe..e7a2b8888 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 185/870] 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 c3fd51d1f..c3bcdb09b 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 b9fef5a79..d40809fad 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 186/870] 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 d40809fad..b861bca15 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 187/870] 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 f5aefb885..898978ca3 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 7634c1f51..2ff6b96cc 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 7c9094f2d..e3038373d 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 b7d278cc6..7a929322a 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 b84b66341..832ce008a 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 188/870] santa sounds --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 4039bd018..b7d3772e7 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 189/870] 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 e364e405f..a1998f515 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 15596318c..8ddc41691 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 190/870] web rank sounds --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index b7d3772e7..f2202ff9d 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 191/870] 2hot death fix --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index f2202ff9d..613365d98 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 192/870] 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 fe64a1e6f..4fc94c2d7 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 b861bca15..fb91fbd1c 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 193/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 613365d98..efb7a833a 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 194/870] 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 c7a08d714..49b15ddf6 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 d296b0b0b..6af40019b 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 195/870] 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 248526aaf..bd2f73e42 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 196/870] 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 efb7a833a..6af094050 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 197/870] roses fix --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 6af094050..faef517a0 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 198/870] 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 6af40019b..e3d3795d9 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 199/870] 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 6f540687f..48fb3b04e 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 200/870] 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 4cd0e7557..4f61e70c2 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 4fc94c2d7..2ecbb5739 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 201/870] 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 fb91fbd1c..a0fa0ae42 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 202/870] 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 fd006c0f3..d85703721 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 203/870] asset submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index faef517a0..56fe3a366 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 204/870] 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 2ecbb5739..035ad2612 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 205/870] 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 035ad2612..a9721bd7c 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 6d133f007d9aa09bd46ee7212298bcd702028537 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 5 Jun 2024 19:25:53 -0400 Subject: [PATCH 206/870] Fix a bug where the event data toolbox wouldn't rebuild, and it would crash. --- source/funkin/audio/FunkinSound.hx | 6 +- .../ui/debug/charting/ChartEditorState.hx | 2 +- .../toolboxes/ChartEditorEventDataToolbox.hx | 58 +++++++++++++------ .../charting/util/ChartEditorDropdowns.hx | 38 ++++++++++++ 4 files changed, 83 insertions(+), 21 deletions(-) diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index 4cd0e7557..58b910051 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -227,12 +227,12 @@ class FunkinSound extends FlxSound implements ICloneable // already paused before we lost focus. if (_lostFocus && !_alreadyPaused) { - trace('Resuming audio (${this._label}) on focus!'); + // trace('Resuming audio (${this._label}) on focus!'); resume(); } else { - trace('Not resuming audio (${this._label}) on focus!'); + // trace('Not resuming audio (${this._label}) on focus!'); } _lostFocus = false; } @@ -242,7 +242,7 @@ class FunkinSound extends FlxSound implements ICloneable */ override function onFocusLost():Void { - trace('Focus lost, pausing audio!'); + // trace('Focus lost, pausing audio!'); _lostFocus = true; _alreadyPaused = _paused; pause(); diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 260393fac..08edb45ab 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -904,7 +904,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState function set_notePreviewDirty(value:Bool):Bool { - trace('Note preview dirtied!'); + // trace('Note preview dirtied!'); return notePreviewDirty = value; } diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorEventDataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorEventDataToolbox.hx index f0949846d..cee25963e 100644 --- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorEventDataToolbox.hx +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorEventDataToolbox.hx @@ -58,17 +58,8 @@ class ChartEditorEventDataToolbox extends ChartEditorBaseToolbox function initialize():Void { - toolboxEventsEventKind.dataSource = new ArrayDataSource(); - - var songEvents:Array = SongEventRegistry.listEvents(); - - for (event in songEvents) - { - toolboxEventsEventKind.dataSource.add({text: event.getTitle(), value: event.id}); - } - toolboxEventsEventKind.onChange = function(event:UIEvent) { - var eventType:String = event.data.value; + var eventType:String = event.data.id; trace('ChartEditorToolboxHandler.buildToolboxEventDataLayout() - Event type changed: $eventType'); @@ -83,7 +74,7 @@ class ChartEditorEventDataToolbox extends ChartEditorBaseToolbox return; } - buildEventDataFormFromSchema(toolboxEventsDataGrid, schema); + buildEventDataFormFromSchema(toolboxEventsDataGrid, schema, chartEditorState.eventKindToPlace); if (!_initializing && chartEditorState.currentEventSelection.length > 0) { @@ -98,14 +89,38 @@ class ChartEditorEventDataToolbox extends ChartEditorBaseToolbox chartEditorState.notePreviewDirty = true; } } - toolboxEventsEventKind.value = chartEditorState.eventKindToPlace; + var startingEventValue = ChartEditorDropdowns.populateDropdownWithSongEvents(toolboxEventsEventKind, chartEditorState.eventKindToPlace); + toolboxEventsEventKind.value = startingEventValue; } public override function refresh():Void { super.refresh(); - toolboxEventsEventKind.value = chartEditorState.eventKindToPlace; + var newDropdownElement = ChartEditorDropdowns.findDropdownElement(chartEditorState.eventKindToPlace, toolboxEventsEventKind); + + if (newDropdownElement == null) + { + throw 'ChartEditorToolboxHandler.buildToolboxEventDataLayout() - Event kind not in dropdown: ${chartEditorState.eventKindToPlace}'; + } + else if (toolboxEventsEventKind.value != newDropdownElement) + { + toolboxEventsEventKind.value = newDropdownElement; + + var schema:SongEventSchema = SongEventRegistry.getEventSchema(chartEditorState.eventKindToPlace); + if (schema == null) + { + trace('ChartEditorToolboxHandler.buildToolboxEventDataLayout() - Unknown event kind: ${chartEditorState.eventKindToPlace}'); + } + else + { + buildEventDataFormFromSchema(toolboxEventsDataGrid, schema, chartEditorState.eventKindToPlace); + } + } + else + { + trace('ChartEditorToolboxHandler.buildToolboxEventDataLayout() - Event kind not changed: ${toolboxEventsEventKind.value} == ${newDropdownElement}'); + } for (pair in chartEditorState.eventDataToPlace.keyValueIterator()) { @@ -116,7 +131,7 @@ class ChartEditorEventDataToolbox extends ChartEditorBaseToolbox if (field == null) { - throw 'ChartEditorToolboxHandler.refresh() - Field "${fieldId}" does not exist in the event data form.'; + throw 'ChartEditorToolboxHandler.refresh() - Field "${fieldId}" does not exist in the event data form for kind ${lastEventKind}.'; } else { @@ -141,9 +156,15 @@ class ChartEditorEventDataToolbox extends ChartEditorBaseToolbox } } - function buildEventDataFormFromSchema(target:Box, schema:SongEventSchema):Void + var lastEventKind:String = 'unknown'; + + function buildEventDataFormFromSchema(target:Box, schema:SongEventSchema, eventKind:String):Void { - trace(schema); + trace('Building event data form from schema for event kind: ${eventKind}'); + // trace(schema); + + lastEventKind = eventKind ?? 'unknown'; + // Clear the frame. target.removeAllComponents(); @@ -197,12 +218,15 @@ class ChartEditorEventDataToolbox extends ChartEditorBaseToolbox for (optionName in field.keys.keys()) { var optionValue:Null = field.keys.get(optionName); - trace('$optionName : $optionValue'); + // trace('$optionName : $optionValue'); dropDown.dataSource.add({value: optionValue, text: optionName}); } dropDown.value = field.defaultValue; + // TODO: Add an option to customize sort. + dropDown.dataSource.sort('text', ASCENDING); + input = dropDown; case STRING: input = new TextField(); diff --git a/source/funkin/ui/debug/charting/util/ChartEditorDropdowns.hx b/source/funkin/ui/debug/charting/util/ChartEditorDropdowns.hx index d2a0a053e..55aab0ab0 100644 --- a/source/funkin/ui/debug/charting/util/ChartEditorDropdowns.hx +++ b/source/funkin/ui/debug/charting/util/ChartEditorDropdowns.hx @@ -3,11 +3,13 @@ package funkin.ui.debug.charting.util; import funkin.data.notestyle.NoteStyleRegistry; import funkin.play.notes.notestyle.NoteStyle; import funkin.data.stage.StageData; +import funkin.play.event.SongEvent; import funkin.data.stage.StageRegistry; import funkin.play.character.CharacterData; import haxe.ui.components.DropDown; import funkin.play.stage.Stage; import funkin.play.character.BaseCharacter.CharacterType; +import funkin.data.event.SongEventRegistry; import funkin.play.character.CharacterData.CharacterDataParser; /** @@ -81,6 +83,42 @@ class ChartEditorDropdowns return returnValue; } + public static function populateDropdownWithSongEvents(dropDown:DropDown, startingEventId:String):DropDownEntry + { + dropDown.dataSource.clear(); + + var returnValue:DropDownEntry = {id: "FocusCamera", text: "Focus Camera"}; + + var songEvents:Array = SongEventRegistry.listEvents(); + + for (event in songEvents) + { + var value = {id: event.id, text: event.getTitle()}; + if (startingEventId == event.id) returnValue = value; + dropDown.dataSource.add(value); + } + + dropDown.dataSource.sort('text', ASCENDING); + + return returnValue; + } + + /** + * Given the ID of a dropdown element, find the corresponding entry in the dropdown's dataSource. + */ + public static function findDropdownElement(id:String, dropDown:DropDown):Null + { + // Attempt to find the entry. + for (entryIndex in 0...dropDown.dataSource.size) + { + var entry = dropDown.dataSource.get(entryIndex); + if (entry.id == id) return entry; + } + + // Not found. + return null; + } + /** * Populate a dropdown with a list of note styles. */ From 6fb19dc4d363f3eef7c534216e1435f38bbfbd01 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 5 Jun 2024 20:09:26 -0400 Subject: [PATCH 207/870] Update chart editor dropdowns to be searchable --- CHANGELOG.md | 2 ++ assets | 2 +- .../ui/debug/charting/toolboxes/ChartEditorEventDataToolbox.hx | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 898978ca3..6bf59061d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,9 +28,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - 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. +- Improved the Event Toolbox in the Chart Editor; dropdowns are now bigger, include search field, and display elements in alphabetical order rather than a random order. ### 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 +- Fixed a bug where the Chart Editor would crash when attempting to select an event with the Event toolbox open - 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!) diff --git a/assets b/assets index faef517a0..ecedb373c 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit faef517a068bb6821d828462504d7baebc91306f +Subproject commit ecedb373ce7a4a6bac0026253813da7363743ca0 diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorEventDataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorEventDataToolbox.hx index cee25963e..4e4d5a077 100644 --- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorEventDataToolbox.hx +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorEventDataToolbox.hx @@ -209,6 +209,9 @@ class ChartEditorEventDataToolbox extends ChartEditorBaseToolbox var dropDown:DropDown = new DropDown(); dropDown.id = field.name; dropDown.width = 200.0; + dropDown.dropdownSize = 10; + dropDown.dropdownWidth = 300; + dropDown.searchable = true; dropDown.dataSource = new ArrayDataSource(); if (field.keys == null) throw 'Field "${field.name}" is of Enum type but has no keys.'; From e27e96a1cb3ce63a3fc75054b67757e6ba6c20c1 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 5 Jun 2024 20:19:00 -0400 Subject: [PATCH 208/870] Update assets submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 56fe3a366..68f223f96 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 209/870] 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 d85703721..df3e343e2 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 a0fa0ae42..dc30b4345 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 210/870] assets submoddd!!!!! --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 56fe3a366..36e395467 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 211/870] 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 898978ca3..42f1fee00 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 + - M.I.L.F. + - Senpai (increased the note speed) + - Roses + - Thorns (increased the note speed slightly) + - Ugh - 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. - 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 56fe3a366..6e124504f 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 56fe3a3662bf5588b4f6cfec492efe5d4cfd600c +Subproject commit 6e124504f777048d357c4b94737dda1b569b4d03 From a81b6b2d6e979b3ab5c680f33b846277f3557ab7 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 6 Jun 2024 16:44:20 -0400 Subject: [PATCH 212/870] Fix issue with rendering the grid in 3/4 time signature --- source/funkin/play/GameOverSubState.hx | 2 +- source/funkin/play/components/HealthIcon.hx | 3 ++- .../ui/debug/charting/handlers/ChartEditorThemeHandler.hx | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/source/funkin/play/GameOverSubState.hx b/source/funkin/play/GameOverSubState.hx index 4d50d75cc..ac45dc194 100644 --- a/source/funkin/play/GameOverSubState.hx +++ b/source/funkin/play/GameOverSubState.hx @@ -237,7 +237,7 @@ class GameOverSubState extends MusicBeatSubState } // KEYBOARD ONLY: Restart the level when pressing the assigned key. - if (controls.ACCEPT && blueballed) + if (controls.ACCEPT && blueballed && !mustNotExit) { blueballed = false; confirmDeath(); diff --git a/source/funkin/play/components/HealthIcon.hx b/source/funkin/play/components/HealthIcon.hx index a3204329a..2442b0dc5 100644 --- a/source/funkin/play/components/HealthIcon.hx +++ b/source/funkin/play/components/HealthIcon.hx @@ -53,8 +53,9 @@ class HealthIcon extends FunkinSprite /** * Apply the "bop" animation once every X steps. + * Defaults to once per beat. */ - public var bopEvery:Int = 4; + public var bopEvery:Int = Constants.STEPS_PER_BEAT; /** * The amount, in degrees, to rotate the icon by when boping. diff --git a/source/funkin/ui/debug/charting/handlers/ChartEditorThemeHandler.hx b/source/funkin/ui/debug/charting/handlers/ChartEditorThemeHandler.hx index b1af0ce4c..e42102a52 100644 --- a/source/funkin/ui/debug/charting/handlers/ChartEditorThemeHandler.hx +++ b/source/funkin/ui/debug/charting/handlers/ChartEditorThemeHandler.hx @@ -201,7 +201,8 @@ class ChartEditorThemeHandler // Selection borders horizontally in the middle. for (i in 1...(Conductor.instance.stepsPerMeasure)) { - if ((i % Conductor.instance.beatsPerMeasure) == 0) + // There may be a different number of beats per measure, but there's always 4 steps per beat. + if ((i % Constants.STEPS_PER_BEAT) == 0) { state.gridBitmap.fillRect(new Rectangle(0, (ChartEditorState.GRID_SIZE * i) - (GRID_BEAT_DIVIDER_WIDTH / 2), state.gridBitmap.width, GRID_BEAT_DIVIDER_WIDTH), From 70f027cc3fb7310403f388b8927cd2ea41f50177 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 6 Jun 2024 16:44:47 -0400 Subject: [PATCH 213/870] Fix another crash with the chart editor event toolbox --- .../debug/charting/commands/SetItemSelectionCommand.hx | 10 +++++++++- .../charting/toolboxes/ChartEditorEventDataToolbox.hx | 6 ++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/source/funkin/ui/debug/charting/commands/SetItemSelectionCommand.hx b/source/funkin/ui/debug/charting/commands/SetItemSelectionCommand.hx index 73cf80fa0..661c44d85 100644 --- a/source/funkin/ui/debug/charting/commands/SetItemSelectionCommand.hx +++ b/source/funkin/ui/debug/charting/commands/SetItemSelectionCommand.hx @@ -35,7 +35,15 @@ class SetItemSelectionCommand implements ChartEditorCommand { var eventSelected = this.events[0]; - state.eventKindToPlace = eventSelected.eventKind; + if (state.eventKindToPlace == eventSelected.eventKind) + { + trace('Target event kind matches selection: ${eventSelected.eventKind}'); + } + else + { + trace('Switching target event kind to match selection: ${state.eventKindToPlace} != ${eventSelected.eventKind}'); + state.eventKindToPlace = eventSelected.eventKind; + } // This code is here to parse event data that's not built as a struct for some reason. // TODO: Clean this up or get rid of it. diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorEventDataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorEventDataToolbox.hx index 4e4d5a077..8f021840a 100644 --- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorEventDataToolbox.hx +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorEventDataToolbox.hx @@ -90,6 +90,7 @@ class ChartEditorEventDataToolbox extends ChartEditorBaseToolbox } } var startingEventValue = ChartEditorDropdowns.populateDropdownWithSongEvents(toolboxEventsEventKind, chartEditorState.eventKindToPlace); + trace('ChartEditorToolboxHandler.buildToolboxEventDataLayout() - Starting event kind: ${startingEventValue}'); toolboxEventsEventKind.value = startingEventValue; } @@ -103,7 +104,7 @@ class ChartEditorEventDataToolbox extends ChartEditorBaseToolbox { throw 'ChartEditorToolboxHandler.buildToolboxEventDataLayout() - Event kind not in dropdown: ${chartEditorState.eventKindToPlace}'; } - else if (toolboxEventsEventKind.value != newDropdownElement) + else if (toolboxEventsEventKind.value != newDropdownElement || lastEventKind != toolboxEventsEventKind.value.id) { toolboxEventsEventKind.value = newDropdownElement; @@ -114,12 +115,13 @@ class ChartEditorEventDataToolbox extends ChartEditorBaseToolbox } else { + trace('ChartEditorToolboxHandler.buildToolboxEventDataLayout() - Event kind changed: ${toolboxEventsEventKind.value.id} != ${newDropdownElement.id} != ${lastEventKind}, rebuilding form'); buildEventDataFormFromSchema(toolboxEventsDataGrid, schema, chartEditorState.eventKindToPlace); } } else { - trace('ChartEditorToolboxHandler.buildToolboxEventDataLayout() - Event kind not changed: ${toolboxEventsEventKind.value} == ${newDropdownElement}'); + trace('ChartEditorToolboxHandler.buildToolboxEventDataLayout() - Event kind not changed: ${toolboxEventsEventKind.value} == ${newDropdownElement} == ${lastEventKind}'); } for (pair in chartEditorState.eventDataToPlace.keyValueIterator()) From fe5f1eb6ea5b88e9186d448f814204df81845a31 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 6 Jun 2024 17:11:30 -0400 Subject: [PATCH 214/870] Fix merge conflict --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index ecedb373c..898e94729 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit ecedb373ce7a4a6bac0026253813da7363743ca0 +Subproject commit 898e94729aa2f0ad4179d6f66dd075070c3172dc From 700b6e11b8f06a9ad12c152e5974d5b4f016730c Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 6 Jun 2024 19:05:05 -0400 Subject: [PATCH 215/870] Update assets submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 6e124504f..862b51355 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 216/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 36e395467..0062c05d5 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 217/870] update game version --- Project.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.xml b/Project.xml index fcd29a25e..d93cf3e42 100644 --- a/Project.xml +++ b/Project.xml @@ -2,7 +2,7 @@ - + From 266049df658061b705ee772d013080ab47940240 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 6 Jun 2024 20:10:28 -0400 Subject: [PATCH 218/870] Update assets submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 898e94729..6ea0324f7 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 898e94729aa2f0ad4179d6f66dd075070c3172dc +Subproject commit 6ea0324f79a6fdabe802c39598ba2b823ed1e593 From 4f0e77c974c7a62fb1deb6cc351668a4b01a4f92 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 6 Jun 2024 20:20:54 -0400 Subject: [PATCH 219/870] update hmm --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index ab55e30ba..4f3d9ac4d 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 220/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 862b51355..e8fc4616c 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 221/870] Add satin panties erect difficulty chart --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 0062c05d5..e8bfc7461 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 222/870] Update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 898978ca3..acb85df6c 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 223/870] 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 ed22092b6..1b0463144 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 224/870] update grig --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index 4f3d9ac4d..68e0c5cb0 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 225/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index e8bfc7461..4427687c4 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit e8bfc7461a403e108a7f7b5fa4eebba38bb6a5fe +Subproject commit 4427687c487d643c6051f8c4610470326c87ea4d From ca345e6c4fad9cc7fd3e6d0de41e68a6cb0298b9 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 6 Jun 2024 21:38:00 -0400 Subject: [PATCH 226/870] Play song IDs based on the chart file's "instrumental" field, not the variation ID. --- source/funkin/play/PlayState.hx | 9 ++++++++- source/funkin/play/song/Song.hx | 4 ++-- source/funkin/ui/freeplay/FreeplayState.hx | 18 ++++++++++++++---- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index b02cc69f7..6bc4b2d89 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -175,6 +175,12 @@ class PlayState extends MusicBeatSubState */ public var currentVariation:String = Constants.DEFAULT_VARIATION; + /** + * The currently selected instrumental ID. + * @default `''` + */ + public var currentInstrumental:String = ''; + /** * The currently active Stage. This is the object containing all the props. */ @@ -603,6 +609,7 @@ class PlayState extends MusicBeatSubState currentSong = params.targetSong; if (params.targetDifficulty != null) currentDifficulty = params.targetDifficulty; if (params.targetVariation != null) currentVariation = params.targetVariation; + if (params.targetInstrumental != null) currentInstrumental = params.targetInstrumental; isPracticeMode = params.practiceMode ?? false; isBotPlayMode = params.botPlayMode ?? false; isMinimalMode = params.minimalMode ?? false; @@ -1968,7 +1975,7 @@ class PlayState extends MusicBeatSubState if (!overrideMusic && !isGamePaused && currentChart != null) { - currentChart.playInst(1.0, false); + currentChart.playInst(1.0, currentInstrumental, false); } if (FlxG.sound.music == null) diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx index df3e343e2..dde5ee7b8 100644 --- a/source/funkin/play/song/Song.hx +++ b/source/funkin/play/song/Song.hx @@ -682,9 +682,9 @@ class SongDifficulty FlxG.sound.cache(getInstPath(instrumental)); } - public function playInst(volume:Float = 1.0, looped:Bool = false):Void + public function playInst(volume:Float = 1.0, instId:String = '', looped:Bool = false):Void { - var suffix:String = (variation != null && variation != '' && variation != 'default') ? '-$variation' : ''; + var suffix:String = (instId != '') ? '-$instId' : ''; FlxG.sound.music = FunkinSound.load(Paths.inst(this.song.id, suffix), volume, looped, false, true); diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 607b7a353..c47933fd7 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1726,11 +1726,20 @@ class FreeplayState extends MusicBeatSubState FlxG.log.warn('WARN: could not find song with id (${cap.songData.songId})'); return; } - var targetDifficulty:String = currentDifficulty; - var targetVariation:String = targetSong.getFirstValidVariation(targetDifficulty); - + var targetDifficultyId:String = currentDifficulty; + var targetVariation:String = targetSong.getFirstValidVariation(targetDifficultyId); PlayStatePlaylist.campaignId = cap.songData.levelId; + var targetDifficulty:SongDifficulty = targetSong.getDifficulty(targetDifficultyId, targetVariation); + if (targetDifficulty == null) + { + FlxG.log.warn('WARN: could not find difficulty with id (${targetDifficultyId})'); + return; + } + + // TODO: Change this with alternate instrumentals + var targetInstId:String = targetDifficulty.characters.instrumental; + // Visual and audio effects. FunkinSound.playOnce(Paths.sound('confirmMenu')); dj.confirm(); @@ -1779,8 +1788,9 @@ class FreeplayState extends MusicBeatSubState LoadingState.loadPlayState( { targetSong: targetSong, - targetDifficulty: targetDifficulty, + targetDifficulty: targetDifficultyId, targetVariation: targetVariation, + targetInstrumental: targetInstId, practiceMode: false, minimalMode: false, From 6665924dd968ff96d074843988d34c64035aa479 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 6 Jun 2024 23:28:41 -0400 Subject: [PATCH 227/870] We forgot to credit burgerballs! --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e44005ffa..1c4969cde 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 228/870] Make sure to credit all the community contributions properly. --- CHANGELOG.md | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c4969cde..90d2a5001 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 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!) -- 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!) +- 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!) +- 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!) +- 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 229/870] 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 90d2a5001..35618dca9 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 230/870] README grammar fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4c6fd9e84..81f8b03e3 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 231/870] 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 7278e027c..6fbcfe627 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 232/870] 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 452c0089b..be5e0aaa8 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 4427687c4..3b8235e95 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 233/870] fix art submod --- art | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/art b/art index faeba700c..66572f85d 160000 --- a/art +++ b/art @@ -1 +1 @@ -Subproject commit faeba700c5526bd4fd57ccc927d875c82b9d3553 +Subproject commit 66572f85d826ce2ec1d45468c12733b161237ffa From a0adbc72b36dea5cafeccf10b71c46e90be2b138 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 7 Jun 2024 13:04:45 -0400 Subject: [PATCH 234/870] regexp for numbers --- source/funkin/ui/freeplay/FreeplayState.hx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 607b7a353..66df2a88d 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -583,6 +583,8 @@ class FreeplayState extends MusicBeatSubState generateSongList({filterType: FAVORITE}, true); case 'ALL': generateSongList(null, true); + case '#': + generateSongList({filterType: REGEXP, filterData: '0-9'}, true); default: generateSongList({filterType: REGEXP, filterData: str}, true); } From 34c91dae76c87e5821d661e409bcfdbf283c8f5a Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 7 Jun 2024 14:24:57 -0400 Subject: [PATCH 235/870] dadbattle hard/erect fix --- assets | 2 +- source/funkin/ui/freeplay/FreeplayState.hx | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/assets b/assets index 4427687c4..d5ab93cb0 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 4427687c487d643c6051f8c4610470326c87ea4d +Subproject commit d5ab93cb024364404dbeb79d0d0228bb06602f13 diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 607b7a353..a6cba9b13 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -285,7 +285,10 @@ class FreeplayState extends MusicBeatSubState // Only display songs which actually have available difficulties for the current character. var displayedVariations = song.getVariationsByCharId(currentCharacter); + trace(songId); + trace(displayedVariations); var availableDifficultiesForSong:Array = song.listDifficulties(displayedVariations, false); + trace(availableDifficultiesForSong); if (availableDifficultiesForSong.length == 0) continue; songs.push(new FreeplaySongData(levelId, songId, song, displayedVariations)); @@ -2076,7 +2079,7 @@ class FreeplaySongData this.songDifficulties = song.listDifficulties(null, variations, false, false); if (!this.songDifficulties.contains(currentDifficulty)) currentDifficulty = Constants.DEFAULT_DIFFICULTY; - var songDifficulty:SongDifficulty = song.getDifficulty(currentDifficulty, variations); + var songDifficulty:SongDifficulty = song.getDifficulty(currentDifficulty, null, variations); if (songDifficulty == null) return; this.songStartingBpm = songDifficulty.getStartingBPM(); this.songName = songDifficulty.songName; From 7b90a3cee3fca0f9c435169c03d3ca9eea65b517 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 7 Jun 2024 14:36:14 -0400 Subject: [PATCH 236/870] lil changelog in progres --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 35618dca9..8397af666 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ 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.1] +### Fixed +- Bug where Dadbattle shows up as Dadbattle Erect when returning to freeplay +- Fixed 2Hot not appearing under the "#" category in Freeplay menu + ## [0.4.0] - 2024-06-06 ### Added - 2 new Erect remixes, Eggnog and Satin Panties. Check them out from the Freeplay menu! From 393355b512556dc3bd7ab33576b2e1c63903299b Mon Sep 17 00:00:00 2001 From: Hundrec Date: Fri, 7 Jun 2024 19:59:02 -0400 Subject: [PATCH 237/870] 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 b02cc69f7..d3e287da9 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 238/870] 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 369d78982..bb45f45e0 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 239/870] 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 bb45f45e0..42dc6086c 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 240/870] 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 576d44c94..5e07fb396 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 241/870] 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 81331b266..e7950f0bd 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 45b43108d12be31bd79d26dbce1b6dadd8182191 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 7 Jun 2024 22:36:25 -0400 Subject: [PATCH 242/870] lower fft amount on desktop --- source/funkin/audio/visualize/ABotVis.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/audio/visualize/ABotVis.hx b/source/funkin/audio/visualize/ABotVis.hx index 1b0463144..a455cb8a2 100644 --- a/source/funkin/audio/visualize/ABotVis.hx +++ b/source/funkin/audio/visualize/ABotVis.hx @@ -54,12 +54,12 @@ class ABotVis extends FlxTypedSpriteGroup public function initAnalyzer() { @:privateAccess - analyzer = new SpectralAnalyzer(snd._channel.__source, 7, 0.1, 30); + analyzer = new SpectralAnalyzer(snd._channel.__source, 7, 0.1, 40); #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; + analyzer.fftN = 256; #end // analyzer.maxDb = -35; From bc80e39a8543df6c44b102d3ddf4b4c1f2a93ff0 Mon Sep 17 00:00:00 2001 From: zacksgamerz <81515012+zacksgamerz@users.noreply.github.com> Date: Sat, 8 Jun 2024 19:07:22 +0700 Subject: [PATCH 243/870] you're to your --- .github/ISSUE_TEMPLATE/bug.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md index efa81b56d..733656a11 100644 --- a/.github/ISSUE_TEMPLATE/bug.md +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -41,4 +41,4 @@ labels: bug -## If you're game is FROZEN and you're playing a web version, press F12 to open up browser dev window, and go to console, and copy-paste whatever red error you're getting +## If your game is FROZEN and you're playing a web version, press F12 to open up browser dev window, and go to console, and copy-paste whatever red error you're getting From ade4aeb3f7c49115591d69f739b41857886edbbc Mon Sep 17 00:00:00 2001 From: Karim Akra <144803230+KarimAkra@users.noreply.github.com> Date: Sun, 9 Jun 2024 01:24:02 +0300 Subject: [PATCH 244/870] get Float instead of Int in cpp (Float is 64-bit in so it works easier than Int64) --- source/funkin/util/MemoryUtil.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/util/MemoryUtil.hx b/source/funkin/util/MemoryUtil.hx index f5935ed67..18fd41472 100644 --- a/source/funkin/util/MemoryUtil.hx +++ b/source/funkin/util/MemoryUtil.hx @@ -48,11 +48,11 @@ class MemoryUtil * Calculate the total memory usage of the program, in bytes. * @return Int */ - public static function getMemoryUsed():Int + public static function getMemoryUsed():#if cpp Float #else Int #end { #if cpp // There is also Gc.MEM_INFO_RESERVED, MEM_INFO_CURRENT, and MEM_INFO_LARGE. - return cpp.vm.Gc.memInfo(cpp.vm.Gc.MEM_INFO_USAGE); + return cpp.vm.Gc.memInfo64(cpp.vm.Gc.MEM_INFO_USAGE); #else return openfl.system.System.totalMemory; #end From 7904a6a20ff76364f6342578ec7d6849e4b098a0 Mon Sep 17 00:00:00 2001 From: Karim Akra <144803230+KarimAkra@users.noreply.github.com> Date: Sun, 9 Jun 2024 01:25:21 +0300 Subject: [PATCH 245/870] use Math.fround instead of Math.round --- source/funkin/ui/debug/MemoryCounter.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/debug/MemoryCounter.hx b/source/funkin/ui/debug/MemoryCounter.hx index b25b55645..50421f398 100644 --- a/source/funkin/ui/debug/MemoryCounter.hx +++ b/source/funkin/ui/debug/MemoryCounter.hx @@ -36,7 +36,7 @@ class MemoryCounter extends TextField @:noCompletion #if !flash override #end function __enterFrame(deltaTime:Float):Void { - var mem:Float = Math.round(MemoryUtil.getMemoryUsed() / BYTES_PER_MEG / ROUND_TO) * ROUND_TO; + var mem:Float = Math.fround(MemoryUtil.getMemoryUsed() / BYTES_PER_MEG / ROUND_TO) * ROUND_TO; if (mem > memPeak) memPeak = mem; From 73982fbd606051fd6e0f2bf9e78ca174fdab0d88 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Sun, 9 Jun 2024 00:29:55 +0200 Subject: [PATCH 246/870] Fix Stack Overflow if song doesn't have "normal" difficulty --- source/funkin/ui/freeplay/FreeplayState.hx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 5e07fb396..0ef268d31 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -2046,6 +2046,8 @@ class FreeplaySongData function set_currentDifficulty(value:String):String { + if (currentDifficulty == value) return value; + currentDifficulty = value; updateValues(displayedVariations); return value; From 3334cc35637cd0ddb58f8675dd92e6495bfa1949 Mon Sep 17 00:00:00 2001 From: tposejank <81495861+tposejank@users.noreply.github.com> Date: Sat, 8 Jun 2024 22:40:09 -0400 Subject: [PATCH 247/870] Update and rename bug.md to bug.yml --- .github/ISSUE_TEMPLATE/bug.md | 44 ------------------------ .github/ISSUE_TEMPLATE/bug.yml | 61 ++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 44 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug.md create mode 100644 .github/ISSUE_TEMPLATE/bug.yml diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md deleted file mode 100644 index efa81b56d..000000000 --- a/.github/ISSUE_TEMPLATE/bug.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -name: Bug Report -about: Report a bug or critical performance issue -title: 'Bug Report: [DESCRIBE YOUR BUG IN DETAIL HERE]' -labels: bug ---- - -[weed]: <> (FILL THIS ISSUE THING OUT AS MUCH AS POSSIBLE) -[weed]: <> (OR ELSE YOUR ISSUE WILL BE LESS LIKELY TO BE SOLVED!) -[weed]: <> (DO NOT POST ABOUT ISSUES FROM OTHER FNF MOD ENGINES! I CANNOT AND PROBABLY WON'T SOLVE THOSE!) -[weed]: <> (GO TO THEIR RESPECTIVE GITHUB ISSUES AND REPORT THEM THERE LOL!) - -[weed]: <> (ALSO MAKE SURE THAT YOU USE PROPER LABELS, IF YOU'RE RUNNING INTO COMPILER ISSUES, USE THE compiler issue LABEL!!!) - -#### Please check for duplicates or similar issues, as well performing simple troubleshooting steps (such as clearing cookies, clearing AppData, trying another browser) before submitting an issue. -### If you are playing the game in a browser, what site are you playing it from? - -[weed]: <> (Put an X in the [ ] thingies to fill out checkbox!) -[weed]: <> (something like [x] pretty much, don't screw up or you will look stupid) - -- [ ] [Newgrounds](https://www.newgrounds.com/portal/view/770371) -- [ ] [Itch.io](https://ninja-muffin24.itch.io/funkin)? Specify below -- - [ ] Windows -- - [ ] Mac -- - [ ] Linux - -### If you are playing the game in a browser, what browser are you using? - -[weed]: <> (Again, put an x in the [ ] box!) - -- [ ] Google Chrome (or chomium based like Brave, vivaldi, MS Edge) -- [ ] Firefox -- [ ] Safari - -## What version of the game are you using? Look in the bottom left corner of the main menu. (ex: 0.2.7, 0.2.1, shit like that) - - -## Have you identified any steps to reproduce the bug? If so, please describe them below in as much detail as possible. Use images if possible. - -## Please describe your issue. Provide extensive detail and images if possible. - - - -## If you're game is FROZEN and you're playing a web version, press F12 to open up browser dev window, and go to console, and copy-paste whatever red error you're getting diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml new file mode 100644 index 000000000..c0334394f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -0,0 +1,61 @@ +name: Bug Report +description: Report a bug or an issue in the game +labels: ["bug"] +title: "Bug Report: " +body: + - type: checkboxes + attributes: + label: Issue Checklist + options: + - label: I have properly named the issue + - label: I looked in issues/discussions, if it has been previously reported + + - type: dropdown + attributes: + label: What platform are you using? + options: + - Itch.io - Windows + - Itch.io - MacOS + - Itch.io - Linux + - Newgrounds (Web) + validations: + required: true + + - type: dropdown + attributes: + label: If you were playing on a browser, which one were you using? + options: + - Google Chrome + - Microsoft Edge + - Firefox + - Opera + - Safari + - Other (Specify below) + + - type: input + attributes: + label: Version + description: What version were you using? + placeholder: ex. 0.4.0 + validations: + required: true + + - type: markdown + attributes: + value: "## Describe your bug." + + - type: markdown + attributes: + value: "### Please do not report issues from other engines. These must be reported in their repositories." + + - type: markdown + attributes: + value: "#### Provide as many details as you can." + + - type: textarea + attributes: + label: Context (Provide images, videos, etc.) + + - type: textarea + attributes: + label: Steps to reproduce (or crash logs, errors, etc.) From 6b74befb5f622d75aeedc9ef6f9457b125904152 Mon Sep 17 00:00:00 2001 From: tposejank <81495861+tposejank@users.noreply.github.com> Date: Sat, 8 Jun 2024 22:42:50 -0400 Subject: [PATCH 248/870] Run it through prettier --- .github/ISSUE_TEMPLATE/bug.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index c0334394f..457bf11e1 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -20,7 +20,7 @@ body: - Newgrounds (Web) validations: required: true - + - type: dropdown attributes: label: If you were playing on a browser, which one were you using? @@ -41,16 +41,16 @@ body: required: true - type: markdown - attributes: - value: "## Describe your bug." + attributes: + value: "## Describe your bug." - type: markdown - attributes: - value: "### Please do not report issues from other engines. These must be reported in their repositories." + attributes: + value: "### Please do not report issues from other engines. These must be reported in their repositories." - type: markdown - attributes: - value: "#### Provide as many details as you can." + attributes: + value: "#### Provide as many details as you can." - type: textarea attributes: From c1da4d336c4d96e6eab73499a7dd8b23fcbb4f47 Mon Sep 17 00:00:00 2001 From: tposejank <81495861+tposejank@users.noreply.github.com> Date: Sat, 8 Jun 2024 22:48:05 -0400 Subject: [PATCH 249/870] Update and rename compiling.md to compiling.yml --- .github/ISSUE_TEMPLATE/compiling.md | 25 ----------------- .github/ISSUE_TEMPLATE/compiling.yml | 42 ++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 25 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/compiling.md create mode 100644 .github/ISSUE_TEMPLATE/compiling.yml diff --git a/.github/ISSUE_TEMPLATE/compiling.md b/.github/ISSUE_TEMPLATE/compiling.md deleted file mode 100644 index 14aea44a7..000000000 --- a/.github/ISSUE_TEMPLATE/compiling.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -name: Compiling help -about: If you need help compiling the game, and you're running into issues. (Look through the 'compiling help' label in case it's been solved!) -title: 'Compiling help: [BRIEF DESCRIPTION / ERROR MESSAGE OUTPUT]' -labels: compiling help ---- - -[weed]: <> (FILL THIS ISSUE THING OUT AS MUCH AS POSSIBLE) -[weed]: <> (OR ELSE YOUR ISSUE WILL BE LESS LIKELY TO BE SOLVED!) -[weed]: <> (DO NOT POST ABOUT ISSUES FROM OTHER FNF MOD ENGINES! I CANNOT AND PROBABLY WON'T SOLVE THOSE!) -[weed]: <> (GO TO THEIR RESPECTIVE GITHUB ISSUES AND REPORT THEM THERE LOL!) - -#### Please check for duplicates or similar compiler issues by filtering for 'compiler help' - -[weed]: <> (Put an X in the [ ] thingies to fill out checkbox!) -[weed]: <> (something like [x] pretty much, don't screw up or you will look stupid) - - -- [ ] Windows -- [ ] Mac -- [ ] Linux -- [ ] HTML5 - -## Please describe your issue. Provide extensive detail and images if possible. - diff --git a/.github/ISSUE_TEMPLATE/compiling.yml b/.github/ISSUE_TEMPLATE/compiling.yml new file mode 100644 index 000000000..d446b64b4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/compiling.yml @@ -0,0 +1,42 @@ +name: Compiling help +description: If you need help compiling the game, and you're running into issues. +labels: ["compiling help"] +title: "Compiling help: " +body: + - type: checkboxes + attributes: + label: Issue Checklist + options: + - label: I have properly named the issue + - label: I looked in issues/discussions, if it has been previously reported + + - type: dropdown + attributes: + label: What platform are you compiling to? + options: + - Windows + - MacOS + - Linux + - HTML5 + validations: + required: true + + - type: markdown + attributes: + value: "## Describe the issue." + + - type: markdown + attributes: + value: "### Please do not report issues from other engines. These must be reported in their repositories." + + - type: markdown + attributes: + value: "#### Provide as many details as you can." + + - type: textarea + attributes: + label: Context (Provide images, videos, etc.) + + - type: textarea + attributes: + label: Steps to reproduce (or crash logs, errors, etc.) From 3f77d1d7cab89e080de5df26dff94bd8e1ff12bf Mon Sep 17 00:00:00 2001 From: tposejank <81495861+tposejank@users.noreply.github.com> Date: Sat, 8 Jun 2024 22:50:44 -0400 Subject: [PATCH 250/870] Update and rename enhancement.md to enhancement.yml --- .github/ISSUE_TEMPLATE/enhancement.md | 8 -------- .github/ISSUE_TEMPLATE/enhancement.yml | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 8 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/enhancement.md create mode 100644 .github/ISSUE_TEMPLATE/enhancement.yml diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md deleted file mode 100644 index e1cc3ae0d..000000000 --- a/.github/ISSUE_TEMPLATE/enhancement.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: Enhancement -about: Suggest a new feature -title: 'Enhancement: ' -labels: enhancement ---- -#### Please check for duplicates or similar issues before creating this issue. -## What is your suggestion, and why should it be implemented? diff --git a/.github/ISSUE_TEMPLATE/enhancement.yml b/.github/ISSUE_TEMPLATE/enhancement.yml new file mode 100644 index 000000000..29c7e5669 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/enhancement.yml @@ -0,0 +1,15 @@ +name: Enhancement +description: Suggest a new feature +labels: ["enhancement"] +title: "Enhancement: " +body: + - type: checkboxes + attributes: + label: Issue Checklist + options: + - label: I have properly named the issue + - label: I looked in issues/discussions, if it has been previously reported + + - type: textarea + attributes: + label: What is your suggestion, and why should it be implemented? From 0808469a6207b33d58c6de9789d4319ace01f5c3 Mon Sep 17 00:00:00 2001 From: tposejank <81495861+tposejank@users.noreply.github.com> Date: Sat, 8 Jun 2024 22:52:37 -0400 Subject: [PATCH 251/870] Update and rename question.md to question.yml --- .github/ISSUE_TEMPLATE/question.md | 12 ------------ .github/ISSUE_TEMPLATE/question.yml | 8 ++++++++ 2 files changed, 8 insertions(+), 12 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/question.md create mode 100644 .github/ISSUE_TEMPLATE/question.yml diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md deleted file mode 100644 index a257c217a..000000000 --- a/.github/ISSUE_TEMPLATE/question.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -name: Question -about: Ask a general question -title: 'Question: ' -labels: question ---- - -[weed]: <> (This isn't a place for AMA type questions, if you want to ask any of the devs something, reach out to them on twitter prob ) -[weed]: <> (any biz bullshit can go to cameron.taylor.ninja@gmail.com) - -#### Please check for duplicates or similar issues before asking your question. -## What is your question? diff --git a/.github/ISSUE_TEMPLATE/question.yml b/.github/ISSUE_TEMPLATE/question.yml new file mode 100644 index 000000000..c6e6e1b11 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question.yml @@ -0,0 +1,8 @@ +name: Question +description: Ask a general question +labels: ["question"] +title: "Question: " +body: + - type: textarea + attributes: + label: What is your question? From 347f487358c4873960e58ec1500d2976e5293463 Mon Sep 17 00:00:00 2001 From: tposejank <81495861+tposejank@users.noreply.github.com> Date: Sat, 8 Jun 2024 22:54:44 -0400 Subject: [PATCH 252/870] Create config.yml --- .github/ISSUE_TEMPLATE/config.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..3ba13e0ce --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1 @@ +blank_issues_enabled: false From 19ef15dbc8381b37807d6aae28bcb3b64bb94ca2 Mon Sep 17 00:00:00 2001 From: tposejank <81495861+tposejank@users.noreply.github.com> Date: Sat, 8 Jun 2024 22:59:17 -0400 Subject: [PATCH 253/870] Update and rename bug.md to bug.yml --- .github/PULL_REQUEST_TEMPLATE/bug.md | 10 ---------- .github/PULL_REQUEST_TEMPLATE/bug.yml | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 10 deletions(-) delete mode 100644 .github/PULL_REQUEST_TEMPLATE/bug.md create mode 100644 .github/PULL_REQUEST_TEMPLATE/bug.yml diff --git a/.github/PULL_REQUEST_TEMPLATE/bug.md b/.github/PULL_REQUEST_TEMPLATE/bug.md deleted file mode 100644 index 41914c5ed..000000000 --- a/.github/PULL_REQUEST_TEMPLATE/bug.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -name: Bug Fix -about: Fix a bug or critical performance issue -title: 'Bug Fix: ' -labels: bug ---- -#### Please check for duplicates or similar PRs before creating this issue. -## Does this PR close any issue(s)? If so, link them below. - -## Briefly describe the issue(s) fixed. diff --git a/.github/PULL_REQUEST_TEMPLATE/bug.yml b/.github/PULL_REQUEST_TEMPLATE/bug.yml new file mode 100644 index 000000000..c8aa2fcb3 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/bug.yml @@ -0,0 +1,18 @@ +name: Bug Fix +description: Fix a bug or critical performance issue +labels: ["bug"] +title: "Bug Fix: " +body: + - type: checkboxes + attributes: + label: Issue Checklist + options: + - label: I have checked if this PR isn't a duplicate + + - type: textarea + attributes: + label: Does this PR fix any issues? Please link them below if so. + + - type: textarea + attributes: + label: Briefly describe the issue(s) fixed. From 075989ce9c403c6a64f5eb3f04136acf68991cf0 Mon Sep 17 00:00:00 2001 From: tposejank <81495861+tposejank@users.noreply.github.com> Date: Sat, 8 Jun 2024 23:00:24 -0400 Subject: [PATCH 254/870] Update and rename enhancement.md to enhancement.yml --- .github/PULL_REQUEST_TEMPLATE/enhancement.md | 10 ---------- .github/PULL_REQUEST_TEMPLATE/enhancement.yml | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 10 deletions(-) delete mode 100644 .github/PULL_REQUEST_TEMPLATE/enhancement.md create mode 100644 .github/PULL_REQUEST_TEMPLATE/enhancement.yml diff --git a/.github/PULL_REQUEST_TEMPLATE/enhancement.md b/.github/PULL_REQUEST_TEMPLATE/enhancement.md deleted file mode 100644 index e208deefe..000000000 --- a/.github/PULL_REQUEST_TEMPLATE/enhancement.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -name: Enhancement -about: Add a new feature -title: 'Enhancement: ' -labels: enhancement ---- -#### Please check for duplicates or similar PRs before creating this issue. -## Does this PR close any issue(s)? If so, link them below. - -## What do your change(s) add, and why should they be implemented? diff --git a/.github/PULL_REQUEST_TEMPLATE/enhancement.yml b/.github/PULL_REQUEST_TEMPLATE/enhancement.yml new file mode 100644 index 000000000..57186b980 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/enhancement.yml @@ -0,0 +1,18 @@ +name: Enhancement +description: Add a new feature +labels: ["enhancement"] +title: "Enhancement: " +body: + - type: checkboxes + attributes: + label: Issue Checklist + options: + - label: I have checked if this PR isn't a duplicate + + - type: textarea + attributes: + label: Does this PR fix any issues? Please link them below if so. + + - type: textarea + attributes: + label: What do your change(s) add, and why should they be implemented? From 09aa8fbf52941d8f35cd36418263147673f341b1 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sun, 9 Jun 2024 02:22:03 -0400 Subject: [PATCH 255/870] Rebindable controls for the Freeplay menu --- source/funkin/input/Controls.hx | 160 ++++++++++++------ source/funkin/ui/freeplay/FreeplayState.hx | 57 +------ source/funkin/ui/freeplay/LetterSort.hx | 10 +- source/funkin/ui/options/ControlsMenu.hx | 18 +- source/funkin/util/WindowUtil.hx | 2 +- .../funkin/util/plugins/ScreenshotPlugin.hx | 2 +- 6 files changed, 141 insertions(+), 108 deletions(-) diff --git a/source/funkin/input/Controls.hx b/source/funkin/input/Controls.hx index 345791eef..e2cae5613 100644 --- a/source/funkin/input/Controls.hx +++ b/source/funkin/input/Controls.hx @@ -58,7 +58,11 @@ class Controls extends FlxActionSet var _back = new FunkinAction(Action.BACK); var _pause = new FunkinAction(Action.PAUSE); var _reset = new FunkinAction(Action.RESET); - var _screenshot = new FunkinAction(Action.SCREENSHOT); + var _window_screenshot = new FunkinAction(Action.WINDOW_SCREENSHOT); + var _window_fullscreen = new FunkinAction(Action.WINDOW_FULLSCREEN); + var _freeplay_favorite = new FunkinAction(Action.FREEPLAY_FAVORITE); + var _freeplay_left = new FunkinAction(Action.FREEPLAY_LEFT); + var _freeplay_right = new FunkinAction(Action.FREEPLAY_RIGHT); var _cutscene_advance = new FunkinAction(Action.CUTSCENE_ADVANCE); var _debug_menu = new FunkinAction(Action.DEBUG_MENU); var _debug_chart = new FunkinAction(Action.DEBUG_CHART); @@ -66,7 +70,6 @@ class Controls extends FlxActionSet var _volume_up = new FunkinAction(Action.VOLUME_UP); var _volume_down = new FunkinAction(Action.VOLUME_DOWN); var _volume_mute = new FunkinAction(Action.VOLUME_MUTE); - var _fullscreen = new FunkinAction(Action.FULLSCREEN); var byName:Map = new Map(); @@ -233,10 +236,30 @@ class Controls extends FlxActionSet inline function get_RESET() return _reset.check(); - public var SCREENSHOT(get, never):Bool; + public var WINDOW_FULLSCREEN(get, never):Bool; - inline function get_SCREENSHOT() - return _screenshot.check(); + inline function get_WINDOW_FULLSCREEN() + return _window_fullscreen.check(); + + public var WINDOW_SCREENSHOT(get, never):Bool; + + inline function get_WINDOW_SCREENSHOT() + return _window_screenshot.check(); + + public var FREEPLAY_FAVORITE(get, never):Bool; + + inline function get_FREEPLAY_FAVORITE() + return _freeplay_favorite.check(); + + public var FREEPLAY_LEFT(get, never):Bool; + + inline function get_FREEPLAY_LEFT() + return _freeplay_left.check(); + + public var FREEPLAY_RIGHT(get, never):Bool; + + inline function get_FREEPLAY_RIGHT() + return _freeplay_right.check(); public var CUTSCENE_ADVANCE(get, never):Bool; @@ -273,11 +296,6 @@ class Controls extends FlxActionSet inline function get_VOLUME_MUTE() return _volume_mute.check(); - public var FULLSCREEN(get, never):Bool; - - inline function get_FULLSCREEN() - return _fullscreen.check(); - public function new(name, scheme:KeyboardScheme = null) { super(name); @@ -294,7 +312,11 @@ class Controls extends FlxActionSet add(_back); add(_pause); add(_reset); - add(_screenshot); + add(_window_screenshot); + add(_window_fullscreen); + add(_freeplay_favorite); + add(_freeplay_left); + add(_freeplay_right); add(_cutscene_advance); add(_debug_menu); add(_debug_chart); @@ -302,7 +324,6 @@ class Controls extends FlxActionSet add(_volume_up); add(_volume_down); add(_volume_mute); - add(_fullscreen); for (action in digitalActions) { if (Std.isOfType(action, FunkinAction)) { @@ -398,7 +419,11 @@ class Controls extends FlxActionSet case BACK: _back; case PAUSE: _pause; case RESET: _reset; - case SCREENSHOT: _screenshot; + case WINDOW_SCREENSHOT: _window_screenshot; + case WINDOW_FULLSCREEN: _window_fullscreen; + case FREEPLAY_FAVORITE: _freeplay_favorite; + case FREEPLAY_LEFT: _freeplay_left; + case FREEPLAY_RIGHT: _freeplay_right; case CUTSCENE_ADVANCE: _cutscene_advance; case DEBUG_MENU: _debug_menu; case DEBUG_CHART: _debug_chart; @@ -406,7 +431,6 @@ class Controls extends FlxActionSet case VOLUME_UP: _volume_up; case VOLUME_DOWN: _volume_down; case VOLUME_MUTE: _volume_mute; - case FULLSCREEN: _fullscreen; } } @@ -466,8 +490,16 @@ class Controls extends FlxActionSet func(_pause, JUST_PRESSED); case RESET: func(_reset, JUST_PRESSED); - case SCREENSHOT: - func(_screenshot, JUST_PRESSED); + case WINDOW_SCREENSHOT: + func(_window_screenshot, JUST_PRESSED); + case WINDOW_FULLSCREEN: + func(_window_fullscreen, JUST_PRESSED); + case FREEPLAY_FAVORITE: + func(_freeplay_favorite, JUST_PRESSED); + case FREEPLAY_LEFT: + func(_freeplay_left, JUST_PRESSED); + case FREEPLAY_RIGHT: + func(_freeplay_right, JUST_PRESSED); case CUTSCENE_ADVANCE: func(_cutscene_advance, JUST_PRESSED); case DEBUG_MENU: @@ -482,8 +514,6 @@ class Controls extends FlxActionSet func(_volume_down, JUST_PRESSED); case VOLUME_MUTE: func(_volume_mute, JUST_PRESSED); - case FULLSCREEN: - func(_fullscreen, JUST_PRESSED); } } @@ -678,7 +708,11 @@ class Controls extends FlxActionSet bindKeys(Control.BACK, getDefaultKeybinds(scheme, Control.BACK)); bindKeys(Control.PAUSE, getDefaultKeybinds(scheme, Control.PAUSE)); bindKeys(Control.RESET, getDefaultKeybinds(scheme, Control.RESET)); - bindKeys(Control.SCREENSHOT, getDefaultKeybinds(scheme, Control.SCREENSHOT)); + bindKeys(Control.WINDOW_SCREENSHOT, getDefaultKeybinds(scheme, Control.WINDOW_SCREENSHOT)); + bindKeys(Control.WINDOW_FULLSCREEN, getDefaultKeybinds(scheme, Control.WINDOW_FULLSCREEN)); + bindKeys(Control.FREEPLAY_FAVORITE, getDefaultKeybinds(scheme, Control.FREEPLAY_FAVORITE)); + bindKeys(Control.FREEPLAY_LEFT, getDefaultKeybinds(scheme, Control.FREEPLAY_LEFT)); + bindKeys(Control.FREEPLAY_RIGHT, getDefaultKeybinds(scheme, Control.FREEPLAY_RIGHT)); bindKeys(Control.CUTSCENE_ADVANCE, getDefaultKeybinds(scheme, Control.CUTSCENE_ADVANCE)); bindKeys(Control.DEBUG_MENU, getDefaultKeybinds(scheme, Control.DEBUG_MENU)); bindKeys(Control.DEBUG_CHART, getDefaultKeybinds(scheme, Control.DEBUG_CHART)); @@ -686,7 +720,6 @@ class Controls extends FlxActionSet bindKeys(Control.VOLUME_UP, getDefaultKeybinds(scheme, Control.VOLUME_UP)); bindKeys(Control.VOLUME_DOWN, getDefaultKeybinds(scheme, Control.VOLUME_DOWN)); bindKeys(Control.VOLUME_MUTE, getDefaultKeybinds(scheme, Control.VOLUME_MUTE)); - bindKeys(Control.FULLSCREEN, getDefaultKeybinds(scheme, Control.FULLSCREEN)); bindMobileLol(); } @@ -707,7 +740,11 @@ class Controls extends FlxActionSet case Control.BACK: return [X, BACKSPACE, ESCAPE]; case Control.PAUSE: return [P, ENTER, ESCAPE]; case Control.RESET: return [R]; - case Control.SCREENSHOT: return [F3]; // TODO: Change this back to PrintScreen + case Control.WINDOW_FULLSCREEN: return [F11]; // We use F for other things LOL. + case Control.WINDOW_SCREENSHOT: return [F3]; + case Control.FREEPLAY_FAVORITE: return [F]; // Favorite a song on the menu + case Control.FREEPLAY_LEFT: return [Q]; // Switch tabs on the menu + case Control.FREEPLAY_RIGHT: return [E]; // Switch tabs on the menu case Control.CUTSCENE_ADVANCE: return [Z, ENTER]; case Control.DEBUG_MENU: return [GRAVEACCENT]; case Control.DEBUG_CHART: return []; @@ -715,8 +752,6 @@ 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.F11]; // We use F for other things LOL. - } case Duo(true): switch (control) { @@ -732,7 +767,11 @@ class Controls extends FlxActionSet case Control.BACK: return [H, X]; case Control.PAUSE: return [ONE]; case Control.RESET: return [R]; - case Control.SCREENSHOT: return [PRINTSCREEN]; + case Control.WINDOW_SCREENSHOT: return [F3]; + case Control.WINDOW_FULLSCREEN: return [F11]; + case Control.FREEPLAY_FAVORITE: return [F]; // Favorite a song on the menu + case Control.FREEPLAY_LEFT: return [Q]; // Switch tabs on the menu + case Control.FREEPLAY_RIGHT: return [E]; // Switch tabs on the menu case Control.CUTSCENE_ADVANCE: return [G, Z]; case Control.DEBUG_MENU: return [GRAVEACCENT]; case Control.DEBUG_CHART: return []; @@ -740,7 +779,6 @@ class Controls extends FlxActionSet case Control.VOLUME_UP: return [PLUS]; case Control.VOLUME_DOWN: return [MINUS]; case Control.VOLUME_MUTE: return [ZERO]; - case Control.FULLSCREEN: return [FlxKey.F]; } case Duo(false): @@ -757,15 +795,18 @@ class Controls extends FlxActionSet case Control.BACK: return [ESCAPE]; case Control.PAUSE: return [ONE]; case Control.RESET: return [R]; - case Control.SCREENSHOT: return [PRINTSCREEN]; + case Control.WINDOW_SCREENSHOT: return []; + case Control.WINDOW_FULLSCREEN: return []; + case Control.FREEPLAY_FAVORITE: return []; + case Control.FREEPLAY_LEFT: return []; + case Control.FREEPLAY_RIGHT: return []; case Control.CUTSCENE_ADVANCE: return [ENTER]; - case Control.DEBUG_MENU: return [GRAVEACCENT]; + case Control.DEBUG_MENU: return []; case Control.DEBUG_CHART: return []; case Control.DEBUG_STAGE: return []; case Control.VOLUME_UP: return [NUMPADPLUS]; case Control.VOLUME_DOWN: return [NUMPADMINUS]; case Control.VOLUME_MUTE: return [NUMPADZERO]; - case Control.FULLSCREEN: return []; } default: @@ -856,34 +897,37 @@ class Controls extends FlxActionSet public function addDefaultGamepad(id):Void { addGamepadLiteral(id, [ - Control.ACCEPT => getDefaultGamepadBinds(Control.ACCEPT), Control.BACK => getDefaultGamepadBinds(Control.BACK), Control.UI_UP => getDefaultGamepadBinds(Control.UI_UP), Control.UI_DOWN => getDefaultGamepadBinds(Control.UI_DOWN), Control.UI_LEFT => getDefaultGamepadBinds(Control.UI_LEFT), Control.UI_RIGHT => getDefaultGamepadBinds(Control.UI_RIGHT), - // don't swap A/B or X/Y for switch on these. A is always the bottom face button Control.NOTE_UP => getDefaultGamepadBinds(Control.NOTE_UP), Control.NOTE_DOWN => getDefaultGamepadBinds(Control.NOTE_DOWN), Control.NOTE_LEFT => getDefaultGamepadBinds(Control.NOTE_LEFT), Control.NOTE_RIGHT => getDefaultGamepadBinds(Control.NOTE_RIGHT), Control.PAUSE => getDefaultGamepadBinds(Control.PAUSE), Control.RESET => getDefaultGamepadBinds(Control.RESET), - // Control.SCREENSHOT => [], - // Control.VOLUME_UP => [RIGHT_SHOULDER], - // Control.VOLUME_DOWN => [LEFT_SHOULDER], - // Control.VOLUME_MUTE => [RIGHT_TRIGGER], + Control.WINDOW_FULLSCREEN => getDefaultGamepadBinds(Control.WINDOW_FULLSCREEN), + Control.WINDOW_SCREENSHOT => getDefaultGamepadBinds(Control.WINDOW_SCREENSHOT), Control.CUTSCENE_ADVANCE => getDefaultGamepadBinds(Control.CUTSCENE_ADVANCE), - // Control.DEBUG_MENU - // Control.DEBUG_CHART + Control.FREEPLAY_FAVORITE => getDefaultGamepadBinds(Control.FREEPLAY_FAVORITE), + Control.FREEPLAY_LEFT => getDefaultGamepadBinds(Control.FREEPLAY_LEFT), + Control.FREEPLAY_RIGHT => getDefaultGamepadBinds(Control.FREEPLAY_RIGHT), + Control.VOLUME_UP => getDefaultGamepadBinds(Control.VOLUME_UP), + Control.VOLUME_DOWN => getDefaultGamepadBinds(Control.VOLUME_DOWN), + Control.VOLUME_MUTE => getDefaultGamepadBinds(Control.VOLUME_MUTE), + Control.DEBUG_MENU => getDefaultGamepadBinds(Control.DEBUG_MENU), + Control.DEBUG_CHART => getDefaultGamepadBinds(Control.DEBUG_CHART), + Control.DEBUG_STAGE => getDefaultGamepadBinds(Control.DEBUG_STAGE), ]); } function getDefaultGamepadBinds(control:Control):Array { switch(control) { case Control.ACCEPT: return [#if switch B #else A #end]; - case Control.BACK: return [#if switch A #else B #end, FlxGamepadInputID.BACK]; + case Control.BACK: return [#if switch A #else B #end]; case Control.UI_UP: return [DPAD_UP, LEFT_STICK_DIGITAL_UP]; case Control.UI_DOWN: return [DPAD_DOWN, LEFT_STICK_DIGITAL_DOWN]; case Control.UI_LEFT: return [DPAD_LEFT, LEFT_STICK_DIGITAL_LEFT]; @@ -893,15 +937,19 @@ class Controls extends FlxActionSet case Control.NOTE_LEFT: return [DPAD_LEFT, X, LEFT_STICK_DIGITAL_LEFT, RIGHT_STICK_DIGITAL_LEFT]; case Control.NOTE_RIGHT: return [DPAD_RIGHT, B, LEFT_STICK_DIGITAL_RIGHT, RIGHT_STICK_DIGITAL_RIGHT]; case Control.PAUSE: return [START]; - case Control.RESET: return [RIGHT_SHOULDER]; - case Control.SCREENSHOT: return []; - case Control.VOLUME_UP: return []; - case Control.VOLUME_DOWN: return []; - case Control.VOLUME_MUTE: return []; + case Control.RESET: return [FlxGamepadInputID.BACK]; // Back (i.e. Select) + case Control.WINDOW_FULLSCREEN: []; + case Control.WINDOW_SCREENSHOT: []; case Control.CUTSCENE_ADVANCE: return [A]; - case Control.DEBUG_MENU: return []; - case Control.DEBUG_CHART: return []; - case Control.FULLSCREEN: return []; + case Control.FREEPLAY_FAVORITE: [FlxGamepadInputID.BACK]; // Back (i.e. Select) + case Control.FREEPLAY_LEFT: [LEFT_SHOULDER]; + case Control.FREEPLAY_RIGHT: [RIGHT_SHOULDER]; + case Control.VOLUME_UP: []; + case Control.VOLUME_DOWN: []; + case Control.VOLUME_MUTE: []; + case Control.DEBUG_MENU: []; + case Control.DEBUG_CHART: []; + case Control.DEBUG_STAGE: []; default: // Fallthrough. } @@ -1392,7 +1440,7 @@ class FlxActionInputDigitalAndroid extends FlxActionInputDigital override public function check(Action:FlxAction):Bool { - returnswitch(trigger) + return switch(trigger) { #if android case PRESSED: FlxG.android.checkStatus(inputID, PRESSED) || FlxG.android.checkStatus(inputID, PRESSED); @@ -1425,14 +1473,18 @@ enum Control UI_RIGHT; UI_DOWN; RESET; - SCREENSHOT; ACCEPT; BACK; PAUSE; - FULLSCREEN; // CUTSCENE CUTSCENE_ADVANCE; - // SCREENSHOT + // FREEPLAY + FREEPLAY_FAVORITE; + FREEPLAY_LEFT; + FREEPLAY_RIGHT; + // WINDOW + WINDOW_SCREENSHOT; + WINDOW_FULLSCREEN; // VOLUME VOLUME_UP; VOLUME_DOWN; @@ -1475,11 +1527,15 @@ enum abstract Action(String) to String from String var BACK = "back"; var PAUSE = "pause"; var RESET = "reset"; - var FULLSCREEN = "fullscreen"; - // SCREENSHOT - var SCREENSHOT = "screenshot"; + // WINDOW + var WINDOW_FULLSCREEN = "window_fullscreen"; + var WINDOW_SCREENSHOT = "window_screenshot"; // CUTSCENE var CUTSCENE_ADVANCE = "cutscene_advance"; + // FREEPLAY + var FREEPLAY_FAVORITE = "freeplay_favorite"; + var FREEPLAY_LEFT = "freeplay_left"; + var FREEPLAY_RIGHT = "freeplay_right"; // VOLUME var VOLUME_UP = "volume_up"; var VOLUME_DOWN = "volume_down"; diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 5e07fb396..1a4d03411 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -965,16 +965,18 @@ class FreeplayState extends MusicBeatSubState grpCapsules.members[curSelected].ranking.scale.set(20, 20); grpCapsules.members[curSelected].blurredRanking.scale.set(20, 20); - grpCapsules.members[curSelected].ranking.animation.play(fromResults.newRank.getFreeplayRankIconAsset(), true); - // grpCapsules.members[curSelected].ranking.animation.curAnim.name, true); + if (fromResults?.newRank != null) { + grpCapsules.members[curSelected].ranking.animation.play(fromResults.newRank.getFreeplayRankIconAsset(), true); + } FlxTween.tween(grpCapsules.members[curSelected].ranking, {"scale.x": 1, "scale.y": 1}, 0.1); - grpCapsules.members[curSelected].blurredRanking.animation.play(fromResults.newRank.getFreeplayRankIconAsset(), true); + if (fromResults?.newRank != null) { + 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, _ -> { - // trace(grpCapsules.members[curSelected].ranking.rank); if (fromResults?.oldRank != null) { grpCapsules.members[curSelected].fakeRanking.visible = false; @@ -1003,7 +1005,6 @@ class FreeplayState extends MusicBeatSubState 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}); @@ -1021,13 +1022,11 @@ class FreeplayState extends MusicBeatSubState 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(fromResults); - // IntervalShake.shake(grpCapsules.members[curSelected].capsule, 0.3, 1 / 30, 0, 0.3, FlxEase.quartIn); }); } @@ -1192,51 +1191,9 @@ class FreeplayState extends MusicBeatSubState // { // rankAnimSlam(fromResultsParams); // } - - if (FlxG.keys.justPressed.G) - { - 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) - { - sparksADD.y -= 2; - trace(sparksADD.x, sparksADD.y); - } - if (FlxG.keys.justPressed.J) - { - sparksADD.x -= 2; - trace(sparksADD.x, sparksADD.y); - } - if (FlxG.keys.justPressed.L) - { - sparksADD.x += 2; - trace(sparksADD.x, sparksADD.y); - } - if (FlxG.keys.justPressed.K) - { - sparksADD.y += 2; - trace(sparksADD.x, sparksADD.y); - } #end - if (FlxG.keys.justPressed.F && !busy) + if (controls.FREEPLAY_FAVORITE && !busy) { var targetSong = grpCapsules.members[curSelected]?.songData; if (targetSong != null) diff --git a/source/funkin/ui/freeplay/LetterSort.hx b/source/funkin/ui/freeplay/LetterSort.hx index e813c9198..049e9194a 100644 --- a/source/funkin/ui/freeplay/LetterSort.hx +++ b/source/funkin/ui/freeplay/LetterSort.hx @@ -8,6 +8,7 @@ import flixel.tweens.FlxTween; import flixel.tweens.FlxEase; import flixel.util.FlxColor; import flixel.util.FlxTimer; +import funkin.input.Controls; import funkin.graphics.adobeanimate.FlxAtlasSprite; class LetterSort extends FlxTypedSpriteGroup @@ -69,14 +70,19 @@ class LetterSort extends FlxTypedSpriteGroup changeSelection(0); } + var controls(get, never):Controls; + + inline function get_controls():Controls + return PlayerSettings.player1.controls; + override function update(elapsed:Float):Void { super.update(elapsed); if (inputEnabled) { - if (FlxG.keys.justPressed.E) changeSelection(1); - if (FlxG.keys.justPressed.Q) changeSelection(-1); + if (controls.FREEPLAY_LEFT) changeSelection(-1); + if (controls.FREEPLAY_RIGHT) changeSelection(1); } } diff --git a/source/funkin/ui/options/ControlsMenu.hx b/source/funkin/ui/options/ControlsMenu.hx index dd7d5ff38..1f40a8455 100644 --- a/source/funkin/ui/options/ControlsMenu.hx +++ b/source/funkin/ui/options/ControlsMenu.hx @@ -28,6 +28,8 @@ class ControlsMenu extends funkin.ui.options.OptionsState.Page [NOTE_UP, NOTE_DOWN, NOTE_LEFT, NOTE_RIGHT], [UI_UP, UI_DOWN, UI_LEFT, UI_RIGHT, ACCEPT, BACK], [CUTSCENE_ADVANCE], + [FREEPLAY_FAVORITE, FREEPLAY_LEFT, FREEPLAY_RIGHT], + [WINDOW_FULLSCREEN, WINDOW_SCREENSHOT], [VOLUME_UP, VOLUME_DOWN, VOLUME_MUTE], [DEBUG_MENU, DEBUG_CHART] ]; @@ -108,6 +110,18 @@ class ControlsMenu extends funkin.ui.options.OptionsState.Page headers.add(new AtlasText(0, y, "CUTSCENE", AtlasFont.BOLD)).screenCenter(X); y += spacer; } + else if (currentHeader != "FREEPLAY_" && name.indexOf("FREEPLAY_") == 0) + { + currentHeader = "FREEPLAY_"; + headers.add(new AtlasText(0, y, "FREEPLAY", AtlasFont.BOLD)).screenCenter(X); + y += spacer; + } + else if (currentHeader != "WINDOW_" && name.indexOf("WINDOW_") == 0) + { + currentHeader = "WINDOW_"; + headers.add(new AtlasText(0, y, "WINDOW", AtlasFont.BOLD)).screenCenter(X); + y += spacer; + } else if (currentHeader != "VOLUME_" && name.indexOf("VOLUME_") == 0) { currentHeader = "VOLUME_"; @@ -123,10 +137,10 @@ class ControlsMenu extends funkin.ui.options.OptionsState.Page if (currentHeader != null && name.indexOf(currentHeader) == 0) name = name.substr(currentHeader.length); - var label = labels.add(new AtlasText(150, y, name, AtlasFont.BOLD)); + var label = labels.add(new AtlasText(100, y, name, AtlasFont.BOLD)); label.alpha = 0.6; for (i in 0...COLUMNS) - createItem(label.x + 400 + i * 300, y, control, i); + createItem(label.x + 550 + i * 400, y, control, i); y += spacer; } diff --git a/source/funkin/util/WindowUtil.hx b/source/funkin/util/WindowUtil.hx index 07f6bc13a..0fe63fe32 100644 --- a/source/funkin/util/WindowUtil.hx +++ b/source/funkin/util/WindowUtil.hx @@ -92,7 +92,7 @@ class WindowUtil }); openfl.Lib.current.stage.addEventListener(openfl.events.KeyboardEvent.KEY_DOWN, (e:openfl.events.KeyboardEvent) -> { - for (key in PlayerSettings.player1.controls.getKeysForAction(FULLSCREEN)) + for (key in PlayerSettings.player1.controls.getKeysForAction(WINDOW_FULLSCREEN)) { if (e.keyCode == key) { diff --git a/source/funkin/util/plugins/ScreenshotPlugin.hx b/source/funkin/util/plugins/ScreenshotPlugin.hx index 9ac21d4b8..c859710de 100644 --- a/source/funkin/util/plugins/ScreenshotPlugin.hx +++ b/source/funkin/util/plugins/ScreenshotPlugin.hx @@ -103,7 +103,7 @@ class ScreenshotPlugin extends FlxBasic public function hasPressedScreenshot():Bool { - return PlayerSettings.player1.controls.SCREENSHOT; + return PlayerSettings.player1.controls.WINDOW_SCREENSHOT; } public function updatePreferences():Void From 839d6a0841e0d1ee04f49a14e73c0166f3a9f491 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sun, 9 Jun 2024 02:27:36 -0400 Subject: [PATCH 256/870] A couple chart fixes --- CHANGELOG.md | 6 ++++++ assets | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 35618dca9..623039e20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ 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-06-?? +### Changed +- Tweaked the chart for Lit Up some more to fix some offset notes. +### Fixed +- Fixed an issue where M.I.L.F. displayed the wrong difficulty rating in the Freeplay menu. + ## [0.4.0] - 2024-06-06 ### Added - 2 new Erect remixes, Eggnog and Satin Panties. Check them out from the Freeplay menu! diff --git a/assets b/assets index 3b8235e95..84aeb428e 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 3b8235e953505a6fe7f4ff253f5a99b9a7b9857a +Subproject commit 84aeb428e0bfb967323d250b68e359174be4c38a From 4997bc27fd0473b5b6f3996ac7150b0240cb62c0 Mon Sep 17 00:00:00 2001 From: Karim Akra <144803230+KarimAkra@users.noreply.github.com> Date: Sun, 9 Jun 2024 12:47:17 +0300 Subject: [PATCH 257/870] remove the library strip --- source/funkin/audio/FunkinSound.hx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index 4f61e70c2..be5cc6931 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -491,8 +491,10 @@ class FunkinSound extends FlxSound implements ICloneable 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 + // we are bypassing the openfl/lime asset library fuss on web only + #if web path = Paths.stripLibrary(path); + #end var soundRequest = FlxPartialSound.partialLoadFromFile(path, start, end); From 9455b6eadc121b5497fa94c9b1b2ceb31b23d6eb Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sun, 9 Jun 2024 12:41:00 -0400 Subject: [PATCH 258/870] simplified the bug template to have less clutter --- .github/ISSUE_TEMPLATE/bug.md | 56 +++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md index efa81b56d..82c121b5a 100644 --- a/.github/ISSUE_TEMPLATE/bug.md +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -5,40 +5,46 @@ title: 'Bug Report: [DESCRIBE YOUR BUG IN DETAIL HERE]' labels: bug --- -[weed]: <> (FILL THIS ISSUE THING OUT AS MUCH AS POSSIBLE) -[weed]: <> (OR ELSE YOUR ISSUE WILL BE LESS LIKELY TO BE SOLVED!) -[weed]: <> (DO NOT POST ABOUT ISSUES FROM OTHER FNF MOD ENGINES! I CANNOT AND PROBABLY WON'T SOLVE THOSE!) -[weed]: <> (GO TO THEIR RESPECTIVE GITHUB ISSUES AND REPORT THEM THERE LOL!) + -- [ ] Google Chrome (or chomium based like Brave, vivaldi, MS Edge) -- [ ] Firefox -- [ ] Safari +## Describe the bug + -## What version of the game are you using? Look in the bottom left corner of the main menu. (ex: 0.2.7, 0.2.1, shit like that) +## To Reproduce + +## Expected behavior + +## Screenshots/Video + -## Have you identified any steps to reproduce the bug? If so, please describe them below in as much detail as possible. Use images if possible. +## Desktop + - OS: + + - Browser + + - Version: + -## Please describe your issue. Provide extensive detail and images if possible. +## Additional context + - - -## If you're game is FROZEN and you're playing a web version, press F12 to open up browser dev window, and go to console, and copy-paste whatever red error you're getting + From 9f960f5c284e019e2787a0fe913368db18b68ad7 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sun, 9 Jun 2024 12:43:43 -0400 Subject: [PATCH 259/870] removed compiling help and question templates --- .github/ISSUE_TEMPLATE/compiling.md | 25 ------------------------- .github/ISSUE_TEMPLATE/question.md | 12 ------------ 2 files changed, 37 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/compiling.md delete mode 100644 .github/ISSUE_TEMPLATE/question.md diff --git a/.github/ISSUE_TEMPLATE/compiling.md b/.github/ISSUE_TEMPLATE/compiling.md deleted file mode 100644 index 14aea44a7..000000000 --- a/.github/ISSUE_TEMPLATE/compiling.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -name: Compiling help -about: If you need help compiling the game, and you're running into issues. (Look through the 'compiling help' label in case it's been solved!) -title: 'Compiling help: [BRIEF DESCRIPTION / ERROR MESSAGE OUTPUT]' -labels: compiling help ---- - -[weed]: <> (FILL THIS ISSUE THING OUT AS MUCH AS POSSIBLE) -[weed]: <> (OR ELSE YOUR ISSUE WILL BE LESS LIKELY TO BE SOLVED!) -[weed]: <> (DO NOT POST ABOUT ISSUES FROM OTHER FNF MOD ENGINES! I CANNOT AND PROBABLY WON'T SOLVE THOSE!) -[weed]: <> (GO TO THEIR RESPECTIVE GITHUB ISSUES AND REPORT THEM THERE LOL!) - -#### Please check for duplicates or similar compiler issues by filtering for 'compiler help' - -[weed]: <> (Put an X in the [ ] thingies to fill out checkbox!) -[weed]: <> (something like [x] pretty much, don't screw up or you will look stupid) - - -- [ ] Windows -- [ ] Mac -- [ ] Linux -- [ ] HTML5 - -## Please describe your issue. Provide extensive detail and images if possible. - diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md deleted file mode 100644 index a257c217a..000000000 --- a/.github/ISSUE_TEMPLATE/question.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -name: Question -about: Ask a general question -title: 'Question: ' -labels: question ---- - -[weed]: <> (This isn't a place for AMA type questions, if you want to ask any of the devs something, reach out to them on twitter prob ) -[weed]: <> (any biz bullshit can go to cameron.taylor.ninja@gmail.com) - -#### Please check for duplicates or similar issues before asking your question. -## What is your question? From bdaadfbfdd7067be46c73bc87a174f72469688f2 Mon Sep 17 00:00:00 2001 From: Ikko Eltociear Ashimine Date: Mon, 10 Jun 2024 02:26:55 +0900 Subject: [PATCH 260/870] chore: update MenuList.hx lenth -> length --- source/funkin/ui/MenuList.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/MenuList.hx b/source/funkin/ui/MenuList.hx index 63a688778..c815e0adc 100644 --- a/source/funkin/ui/MenuList.hx +++ b/source/funkin/ui/MenuList.hx @@ -142,7 +142,7 @@ class MenuTypedList extends FlxTypedGroup */ function navGrid(latSize:Int, latPrev:Bool, latNext:Bool, latAllowWrap:Bool, prev:Bool, next:Bool, allowWrap:Bool):Int { - // The grid lenth along the variable-length axis + // The grid length along the variable-length axis var size = Math.ceil(length / latSize); // The selected position along the variable-length axis var index = Math.floor(selectedIndex / latSize); From f2d5a80bd158ffd49c93d272e04083caa9bf0b44 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sun, 9 Jun 2024 15:06:45 -0400 Subject: [PATCH 261/870] completes funk-305 --- source/funkin/ui/freeplay/SongMenuItem.hx | 27 +++++++++++++++++------ 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/source/funkin/ui/freeplay/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx index dc30b4345..7708b3bcf 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -219,7 +219,7 @@ class SongMenuItem extends FlxSpriteGroup favIconBlurred.visible = false; add(favIconBlurred); - favIcon = new FlxSprite(380, 40); + favIcon = new FlxSprite(favIconBlurred.x, favIconBlurred.y); favIcon.frames = Paths.getSparrowAtlas('freeplay/favHeart'); favIcon.animation.addByPrefix('fav', 'favorite heart', 24, false); favIcon.animation.play('fav'); @@ -294,21 +294,34 @@ class SongMenuItem extends FlxSpriteGroup } } - // 255, 27 normal - // 220, 27 favourited + /** + * Checks whether the song is favorited, and/or has a rank, and adjusts the clipping + * for the scenario when the text could be too long + */ public function checkClip():Void { var clipSize:Int = 290; var clipType:Int = 0; - if (ranking.visible == true) clipType += 1; - if (favIcon.visible == true) clipType = 2; + if (ranking.visible) + { + favIconBlurred.x = this.x + 370; + favIcon.x = favIconBlurred.x; + clipType += 1; + } + else + { + favIconBlurred.x = favIcon.x = this.x + 405; + } + + if (favIcon.visible) clipType += 1; + switch (clipType) { case 2: - clipSize = 220; + clipSize = 210; case 1: - clipSize = 255; + clipSize = 245; } songText.clipWidth = clipSize; } From 55edb9ea14cc003de542e60e11cc5f3453b0d5da Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sun, 9 Jun 2024 15:38:22 -0400 Subject: [PATCH 262/870] pressing escape on title screen exits game --- source/funkin/ui/title/TitleState.hx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source/funkin/ui/title/TitleState.hx b/source/funkin/ui/title/TitleState.hx index c6dbcd505..8087916cb 100644 --- a/source/funkin/ui/title/TitleState.hx +++ b/source/funkin/ui/title/TitleState.hx @@ -265,6 +265,13 @@ class TitleState extends MusicBeatState if (FlxG.keys.pressed.DOWN) FlxG.sound.music.pitch -= 0.5 * elapsed; #end + #if desktop + if (FlxG.keys.justPressed.ESCAPE) + { + Sys.exit(0); + } + #end + Conductor.instance.update(); /* if (FlxG.onMobile) From b811aeec803b6689def1ded61df766961e0a5080 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sun, 9 Jun 2024 16:15:33 -0400 Subject: [PATCH 263/870] fix for pico explo --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index d5ab93cb0..6421057fa 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit d5ab93cb024364404dbeb79d0d0228bb06602f13 +Subproject commit 6421057faae19782fcda81349bbdeb40f014323e From 9618cd2128323889d19246fb519b56494a9d20c7 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Mon, 10 Jun 2024 16:53:32 +0200 Subject: [PATCH 264/870] Fix chart reset when charting and pressing chart key --- source/funkin/play/PlayState.hx | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index b3d0a9f8a..1e22e98af 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -2284,7 +2284,7 @@ class PlayState extends MusicBeatSubState 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()) { @@ -2612,10 +2612,18 @@ class PlayState extends MusicBeatSubState { disableKeys = true; persistentUpdate = false; - FlxG.switchState(() -> new ChartEditorState( - { - targetSongId: currentSong.id, - })); + if (isChartingMode) + { + FlxG.sound.music?.pause(); + this.close(); + } + else + { + FlxG.switchState(() -> new ChartEditorState( + { + targetSongId: currentSong.id, + })); + } } #end From 9fa603363c9ecf50d4576f18f3d2692372e12ca5 Mon Sep 17 00:00:00 2001 From: AppleHair <95587502+AppleHair@users.noreply.github.com> Date: Mon, 10 Jun 2024 19:42:27 +0300 Subject: [PATCH 265/870] [BUGFIX] Made freeplay use the metadata to get the instrumental suffix Song previews in freeplay will now use the instrumental suffix from the current difficulty's corresponding song variation metadata instead of using the variation id as an instrumental suffix and checking only the "erect" variation. --- source/funkin/ui/freeplay/FreeplayState.hx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 5e07fb396..5a7fa54d2 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1890,14 +1890,17 @@ class FreeplayState extends MusicBeatSubState } else { - var potentiallyErect:String = (currentDifficulty == "erect") || (currentDifficulty == "nightmare") ? "-erect" : ""; + var previewSong:Null = SongRegistry.instance.fetchEntry(daSongCapsule.songData.songId); + var instSuffix:String = previewSong?.getDifficulty(currentDifficulty, + previewSong?.variations ?? Constants.DEFAULT_VARIATION_LIST)?.characters?.instrumental ?? ''; + instSuffix = (instSuffix != '') ? '-$instSuffix' : ''; FunkinSound.playMusic(daSongCapsule.songData.songId, { startingVolume: 0.0, overrideExisting: true, restartTrack: false, pathsFunction: INST, - suffix: potentiallyErect, + suffix: instSuffix, partialParams: { loadPartial: true, From 8f44d9606d4cdf5c9935175894a706dcd50319a4 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Mon, 10 Jun 2024 18:04:18 +0200 Subject: [PATCH 266/870] Remove unnecessary scrollMenu sounds + adjust volume --- source/funkin/play/PauseSubState.hx | 5 +++-- source/funkin/ui/MenuList.hx | 2 +- source/funkin/ui/freeplay/FreeplayState.hx | 4 ++-- source/funkin/ui/story/StoryMenuState.hx | 3 ++- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/source/funkin/play/PauseSubState.hx b/source/funkin/play/PauseSubState.hx index 8c45fac65..d0c759b16 100644 --- a/source/funkin/play/PauseSubState.hx +++ b/source/funkin/play/PauseSubState.hx @@ -449,13 +449,14 @@ class PauseSubState extends MusicBeatSubState */ function changeSelection(change:Int = 0):Void { - FunkinSound.playOnce(Paths.sound('scrollMenu'), 0.4); - + var prevEntry:Int = currentEntry; currentEntry += change; if (currentEntry < 0) currentEntry = currentMenuEntries.length - 1; if (currentEntry >= currentMenuEntries.length) currentEntry = 0; + if (currentEntry != prevEntry) FunkinSound.playOnce(Paths.sound('scrollMenu'), 0.4); + for (entryIndex in 0...currentMenuEntries.length) { var isCurrent:Bool = entryIndex == currentEntry; diff --git a/source/funkin/ui/MenuList.hx b/source/funkin/ui/MenuList.hx index 63a688778..6fd606378 100644 --- a/source/funkin/ui/MenuList.hx +++ b/source/funkin/ui/MenuList.hx @@ -94,7 +94,7 @@ class MenuTypedList extends FlxTypedGroup if (newIndex != selectedIndex) { - FunkinSound.playOnce(Paths.sound('scrollMenu')); + FunkinSound.playOnce(Paths.sound('scrollMenu'), 0.4); selectItem(newIndex); } diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 09f79fcfd..e80109900 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1833,12 +1833,12 @@ class FreeplayState extends MusicBeatSubState function changeSelection(change:Int = 0):Void { - if (!prepForNewRank) FunkinSound.playOnce(Paths.sound('scrollMenu'), 0.4); - var prevSelected:Int = curSelected; curSelected += change; + if (!prepForNewRank && curSelected != prevSelected) FunkinSound.playOnce(Paths.sound('scrollMenu'), 0.4); + if (curSelected < 0) curSelected = grpCapsules.countLiving() - 1; if (curSelected >= grpCapsules.countLiving()) curSelected = 0; diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx index c1a001e5d..06a83ab4d 100644 --- a/source/funkin/ui/story/StoryMenuState.hx +++ b/source/funkin/ui/story/StoryMenuState.hx @@ -387,6 +387,7 @@ class StoryMenuState extends MusicBeatState function changeLevel(change:Int = 0):Void { var currentIndex:Int = levelList.indexOf(currentLevelId); + var prevIndex:Int = currentIndex; currentIndex += change; @@ -417,7 +418,7 @@ class StoryMenuState extends MusicBeatState } } - FunkinSound.playOnce(Paths.sound('scrollMenu'), 0.4); + if (currentIndex != prevIndex) FunkinSound.playOnce(Paths.sound('scrollMenu'), 0.4); updateText(); updateBackground(previousLevelId); From f31ea8fb73ade3a5ff073b4c96b59625be17e8de Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 10 Jun 2024 16:13:32 -0400 Subject: [PATCH 267/870] add sound for changing sorting --- 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 e80109900..c54091d26 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -602,6 +602,7 @@ class FreeplayState extends MusicBeatSubState // that is, only if there's more than one song in the group! if (grpCapsules.members.length > 0) { + FunkinSound.playOnce(Paths.sound('scrollMenu'), 0.4); curSelected = 1; changeSelection(); } From da61b72c48200faf5276d3f87f347970c4d3221a Mon Sep 17 00:00:00 2001 From: DM-kun <86197998+DMMaster636@users.noreply.github.com> Date: Sat, 8 Jun 2024 19:58:34 +0200 Subject: [PATCH 268/870] crash fix --- source/funkin/play/GameOverSubState.hx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/funkin/play/GameOverSubState.hx b/source/funkin/play/GameOverSubState.hx index ac45dc194..c84d5b154 100644 --- a/source/funkin/play/GameOverSubState.hx +++ b/source/funkin/play/GameOverSubState.hx @@ -71,7 +71,7 @@ class GameOverSubState extends MusicBeatSubState var gameOverMusic:Null = null; /** - * Whether the player has confirmed and prepared to restart the level. + * Whether the player has confirmed and prepared to restart the level or to go back to the freeplay menu. * This means the animation and transition have already started. */ var isEnding:Bool = false; @@ -244,8 +244,9 @@ class GameOverSubState extends MusicBeatSubState } // KEYBOARD ONLY: Return to the menu when pressing the assigned key. - if (controls.BACK && !mustNotExit) + if (controls.BACK && !mustNotExit && !isEnding) { + isEnding = true; blueballed = false; PlayState.instance.deathCounter = 0; // PlayState.seenCutscene = false; // old thing... From f91f4b2ddba32357ee7a4f4c3bae5cb99c5f2974 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sun, 9 Jun 2024 12:41:00 -0400 Subject: [PATCH 269/870] simplified the bug template to have less clutter --- .github/ISSUE_TEMPLATE/bug.md | 56 +++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md index 733656a11..82c121b5a 100644 --- a/.github/ISSUE_TEMPLATE/bug.md +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -5,40 +5,46 @@ title: 'Bug Report: [DESCRIBE YOUR BUG IN DETAIL HERE]' labels: bug --- -[weed]: <> (FILL THIS ISSUE THING OUT AS MUCH AS POSSIBLE) -[weed]: <> (OR ELSE YOUR ISSUE WILL BE LESS LIKELY TO BE SOLVED!) -[weed]: <> (DO NOT POST ABOUT ISSUES FROM OTHER FNF MOD ENGINES! I CANNOT AND PROBABLY WON'T SOLVE THOSE!) -[weed]: <> (GO TO THEIR RESPECTIVE GITHUB ISSUES AND REPORT THEM THERE LOL!) + -- [ ] Google Chrome (or chomium based like Brave, vivaldi, MS Edge) -- [ ] Firefox -- [ ] Safari +## Describe the bug + -## What version of the game are you using? Look in the bottom left corner of the main menu. (ex: 0.2.7, 0.2.1, shit like that) +## To Reproduce + +## Expected behavior + +## Screenshots/Video + -## Have you identified any steps to reproduce the bug? If so, please describe them below in as much detail as possible. Use images if possible. +## Desktop + - OS: + + - Browser + + - Version: + -## Please describe your issue. Provide extensive detail and images if possible. +## Additional context + - - -## If your game is FROZEN and you're playing a web version, press F12 to open up browser dev window, and go to console, and copy-paste whatever red error you're getting + From 13d49017ac4bd55fcd59003f38cedc58da7167af Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sun, 9 Jun 2024 12:43:43 -0400 Subject: [PATCH 270/870] removed compiling help and question templates --- .github/ISSUE_TEMPLATE/compiling.md | 25 ------------------------- .github/ISSUE_TEMPLATE/question.md | 12 ------------ 2 files changed, 37 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/compiling.md delete mode 100644 .github/ISSUE_TEMPLATE/question.md diff --git a/.github/ISSUE_TEMPLATE/compiling.md b/.github/ISSUE_TEMPLATE/compiling.md deleted file mode 100644 index 14aea44a7..000000000 --- a/.github/ISSUE_TEMPLATE/compiling.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -name: Compiling help -about: If you need help compiling the game, and you're running into issues. (Look through the 'compiling help' label in case it's been solved!) -title: 'Compiling help: [BRIEF DESCRIPTION / ERROR MESSAGE OUTPUT]' -labels: compiling help ---- - -[weed]: <> (FILL THIS ISSUE THING OUT AS MUCH AS POSSIBLE) -[weed]: <> (OR ELSE YOUR ISSUE WILL BE LESS LIKELY TO BE SOLVED!) -[weed]: <> (DO NOT POST ABOUT ISSUES FROM OTHER FNF MOD ENGINES! I CANNOT AND PROBABLY WON'T SOLVE THOSE!) -[weed]: <> (GO TO THEIR RESPECTIVE GITHUB ISSUES AND REPORT THEM THERE LOL!) - -#### Please check for duplicates or similar compiler issues by filtering for 'compiler help' - -[weed]: <> (Put an X in the [ ] thingies to fill out checkbox!) -[weed]: <> (something like [x] pretty much, don't screw up or you will look stupid) - - -- [ ] Windows -- [ ] Mac -- [ ] Linux -- [ ] HTML5 - -## Please describe your issue. Provide extensive detail and images if possible. - diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md deleted file mode 100644 index a257c217a..000000000 --- a/.github/ISSUE_TEMPLATE/question.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -name: Question -about: Ask a general question -title: 'Question: ' -labels: question ---- - -[weed]: <> (This isn't a place for AMA type questions, if you want to ask any of the devs something, reach out to them on twitter prob ) -[weed]: <> (any biz bullshit can go to cameron.taylor.ninja@gmail.com) - -#### Please check for duplicates or similar issues before asking your question. -## What is your question? From e8f8a0c1819297c8ce9ac92517dd61978b6be6c8 Mon Sep 17 00:00:00 2001 From: Ikko Eltociear Ashimine Date: Mon, 10 Jun 2024 02:26:55 +0900 Subject: [PATCH 271/870] chore: update MenuList.hx lenth -> length --- source/funkin/ui/MenuList.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/MenuList.hx b/source/funkin/ui/MenuList.hx index 6fd606378..d7319abd6 100644 --- a/source/funkin/ui/MenuList.hx +++ b/source/funkin/ui/MenuList.hx @@ -142,7 +142,7 @@ class MenuTypedList extends FlxTypedGroup */ function navGrid(latSize:Int, latPrev:Bool, latNext:Bool, latAllowWrap:Bool, prev:Bool, next:Bool, allowWrap:Bool):Int { - // The grid lenth along the variable-length axis + // The grid length along the variable-length axis var size = Math.ceil(length / latSize); // The selected position along the variable-length axis var index = Math.floor(selectedIndex / latSize); From 00021523bc1f1d7f99fc436a6d16e32a26dbcdb9 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sun, 9 Jun 2024 15:17:41 -0400 Subject: [PATCH 272/870] lower volume on freeplay easter egg --- source/funkin/ui/freeplay/DJBoyfriend.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/freeplay/DJBoyfriend.hx b/source/funkin/ui/freeplay/DJBoyfriend.hx index bd2f73e42..bbf043dd4 100644 --- a/source/funkin/ui/freeplay/DJBoyfriend.hx +++ b/source/funkin/ui/freeplay/DJBoyfriend.hx @@ -266,7 +266,7 @@ class DJBoyfriend extends FlxAtlasSprite // Fade out music to 40% volume over 1 second. // This helps make the TV a bit more audible. - FlxG.sound.music.fadeOut(1.0, 0.4); + FlxG.sound.music.fadeOut(1.0, 0.1); // Play the cartoon at a random time between the start and 5 seconds from the end. cartoonSnd.time = FlxG.random.float(0, Math.max(cartoonSnd.length - (5 * Constants.MS_PER_SEC), 0.0)); From c0a7e4f728d38a9717000164d893fde61f49aafe Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 10 Jun 2024 19:32:53 -0400 Subject: [PATCH 273/870] Readd camera events to Roses --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 84aeb428e..54eb4feaf 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 84aeb428e0bfb967323d250b68e359174be4c38a +Subproject commit 54eb4feaf7b740dbe1988cb35debc97bdff372b8 From fb71f9087d546854d4b44311682d84dcdd44fd32 Mon Sep 17 00:00:00 2001 From: NotHyper-474 Date: Mon, 10 Jun 2024 23:12:28 -0300 Subject: [PATCH 274/870] Fix trace --- source/funkin/ui/transition/LoadingState.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/transition/LoadingState.hx b/source/funkin/ui/transition/LoadingState.hx index bc26ad97a..0f2ce1076 100644 --- a/source/funkin/ui/transition/LoadingState.hx +++ b/source/funkin/ui/transition/LoadingState.hx @@ -346,7 +346,7 @@ class LoadingState extends MusicBeatSubState return 'Done precaching ${path}'; }, true); - trace("Queued ${path} for precaching"); + trace('Queued ${path} for precaching'); // FunkinSprite.cacheTexture(path); } From b30faad7d9b5c659c14db2694ac7b5938606a3e1 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 11 Jun 2024 00:40:43 -0400 Subject: [PATCH 275/870] Save high scores and high ranks separately. --- source/funkin/play/PlayState.hx | 29 ++-- source/funkin/play/scoring/Scoring.hx | 158 ++++++++++++--------- source/funkin/save/Save.hx | 102 ++++++++++++- source/funkin/ui/freeplay/FreeplayState.hx | 14 +- source/funkin/ui/mainmenu/MainMenuState.hx | 27 ++++ source/funkin/util/FileUtil.hx | 1 + 6 files changed, 251 insertions(+), 80 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index b3d0a9f8a..ad7a398d4 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -2284,7 +2284,7 @@ class PlayState extends MusicBeatSubState 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()) { @@ -2818,8 +2818,13 @@ class PlayState extends MusicBeatSubState deathCounter = 0; + // TODO: This line of code makes me sad, but you can't really fix it without a breaking migration. + // `easy`, `erect`, `normal-pico`, etc. + var suffixedDifficulty = (currentVariation != Constants.DEFAULT_VARIATION + && currentVariation != 'erect') ? '$currentDifficulty-${currentVariation}' : currentDifficulty; + var isNewHighscore = false; - var prevScoreData:Null = Save.instance.getSongScore(currentSong.id, currentDifficulty); + var prevScoreData:Null = Save.instance.getSongScore(currentSong.id, suffixedDifficulty); if (currentSong != null && currentSong.validScore) { @@ -2844,13 +2849,21 @@ class PlayState extends MusicBeatSubState // adds current song data into the tallies for the level (story levels) Highscore.talliesLevel = Highscore.combineTallies(Highscore.tallies, Highscore.talliesLevel); - if (!isPracticeMode && !isBotPlayMode && Save.instance.isSongHighScore(currentSong.id, currentDifficulty, data)) + if (!isPracticeMode && !isBotPlayMode) { - Save.instance.setSongScore(currentSong.id, currentDifficulty, data); - #if newgrounds - NGio.postScore(score, currentSong.id); - #end - isNewHighscore = true; + isNewHighscore = Save.instance.isSongHighScore(currentSong.id, suffixedDifficulty, data); + + // If no high score is present, save both score and rank. + // If score or rank are better, save the highest one. + // If neither are higher, nothing will change. + Save.instance.applySongRank(currentSong.id, suffixedDifficulty, data); + + if (isNewHighscore) + { + #if newgrounds + NGio.postScore(score, currentSong.id); + #end + } } } diff --git a/source/funkin/play/scoring/Scoring.hx b/source/funkin/play/scoring/Scoring.hx index d6f71fc7e..dc2c40647 100644 --- a/source/funkin/play/scoring/Scoring.hx +++ b/source/funkin/play/scoring/Scoring.hx @@ -356,7 +356,10 @@ class Scoring // Perfect (Platinum) is a Sick Full Clear var isPerfectGold = scoreData.tallies.sick == scoreData.tallies.totalNotes; - if (isPerfectGold) return ScoringRank.PERFECT_GOLD; + if (isPerfectGold) + { + return ScoringRank.PERFECT_GOLD; + } // Else, use the standard grades @@ -397,62 +400,79 @@ enum abstract ScoringRank(String) var GOOD; var SHIT; - @:op(A > B) static function compare(a:Null, b:Null):Bool + /** + * Converts ScoringRank to an integer value for comparison. + * Better ranks should be tied to a higher value. + */ + static function getValue(rank:Null):Int + { + if (rank == null) return -1; + switch (rank) + { + case PERFECT_GOLD: + return 5; + case PERFECT: + return 4; + case EXCELLENT: + return 3; + case GREAT: + return 2; + case GOOD: + return 1; + case SHIT: + return 0; + default: + return -1; + } + } + + // Yes, we really need a different function for each comparison operator. + @:op(A > B) static function compareGT(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; + var temp1:Int = getValue(a); + var temp2:Int = getValue(b); - // 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; - } + return temp1 > temp2; } + @:op(A >= B) static function compareGTEQ(a:Null, b:Null):Bool + { + if (a != null && b == null) return true; + if (a == null || b == null) return false; + + var temp1:Int = getValue(a); + var temp2:Int = getValue(b); + + return temp1 >= temp2; + } + + @:op(A < B) static function compareLT(a:Null, b:Null):Bool + { + if (a != null && b == null) return true; + if (a == null || b == null) return false; + + var temp1:Int = getValue(a); + var temp2:Int = getValue(b); + + return temp1 < temp2; + } + + @:op(A <= B) static function compareLTEQ(a:Null, b:Null):Bool + { + if (a != null && b == null) return true; + if (a == null || b == null) return false; + + var temp1:Int = getValue(a); + var temp2:Int = getValue(b); + + return temp1 <= temp2; + } + + // @:op(A == B) isn't necessary! + /** * Delay in seconds */ @@ -462,15 +482,15 @@ enum abstract ScoringRank(String) { case PERFECT_GOLD | PERFECT: // return 2.5; - return 95/24; + return 95 / 24; case EXCELLENT: return 0; case GREAT: - return 5/24; + return 5 / 24; case GOOD: - return 3/24; + return 3 / 24; case SHIT: - return 2/24; + return 2 / 24; default: return 3.5; } @@ -482,15 +502,15 @@ enum abstract ScoringRank(String) { case PERFECT_GOLD | PERFECT: // return 2.5; - return 95/24; + return 95 / 24; case EXCELLENT: - return 97/24; + return 97 / 24; case GREAT: - return 95/24; + return 95 / 24; case GOOD: - return 95/24; + return 95 / 24; case SHIT: - return 95/24; + return 95 / 24; default: return 3.5; } @@ -502,15 +522,15 @@ enum abstract ScoringRank(String) { case PERFECT_GOLD | PERFECT: // return 2.5; - return 129/24; + return 129 / 24; case EXCELLENT: - return 122/24; + return 122 / 24; case GREAT: - return 109/24; + return 109 / 24; case GOOD: - return 107/24; + return 107 / 24; case SHIT: - return 186/24; + return 186 / 24; default: return 3.5; } @@ -522,15 +542,15 @@ enum abstract ScoringRank(String) { case PERFECT_GOLD | PERFECT: // return 2.5; - return 140/24; + return 140 / 24; case EXCELLENT: - return 140/24; + return 140 / 24; case GREAT: - return 129/24; + return 129 / 24; case GOOD: - return 127/24; + return 127 / 24; case SHIT: - return 207/24; + return 207 / 24; default: return 3.5; } diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx index 2ff6b96cc..2900ce2be 100644 --- a/source/funkin/save/Save.hx +++ b/source/funkin/save/Save.hx @@ -1,6 +1,7 @@ package funkin.save; import flixel.util.FlxSave; +import funkin.util.FileUtil; import funkin.input.Controls.Device; import funkin.play.scoring.Scoring; import funkin.play.scoring.Scoring.ScoringRank; @@ -58,7 +59,7 @@ class Save this.data = data; // Make sure the verison number is up to date before we flush. - this.data.version = Save.SAVE_DATA_VERSION; + updateVersionToLatest(); } public static function getDefault():RawSaveData @@ -503,7 +504,7 @@ class Save } /** - * Apply the score the user achieved for a given song on a given difficulty. + * Directly set the score the user achieved for a given song on a given difficulty. */ public function setSongScore(songId:String, difficultyId:String, score:SaveScoreData):Void { @@ -518,6 +519,44 @@ class Save flush(); } + /** + * Only replace the ranking data for the song, because the old score is still better. + */ + public function applySongRank(songId:String, difficultyId:String, newScoreData:SaveScoreData):Void + { + var newRank = Scoring.calculateRank(newScoreData); + if (newScoreData == null || newRank == null) return; + + var song = data.scores.songs.get(songId); + if (song == null) + { + song = []; + data.scores.songs.set(songId, song); + } + + var previousScoreData = song.get(difficultyId); + + var previousRank = Scoring.calculateRank(previousScoreData); + + if (previousScoreData == null || previousRank == null) + { + // Directly set the highscore. + setSongScore(songId, difficultyId, newScoreData); + return; + } + + // Set the high score and the high rank separately. + var newScore:SaveScoreData = + { + score: (previousScoreData.score > newScoreData.score) ? previousScoreData.score : newScoreData.score, + tallies: (previousRank > newRank) ? previousScoreData.tallies : newScoreData.tallies + }; + + song.set(difficultyId, newScore); + + flush(); + } + /** * Is the provided score data better than the current high score for the given song? * @param songId The song ID to check. @@ -543,6 +582,39 @@ class Save return score.score > currentScore.score; } + /** + * Is the provided score data better than the current rank for the given song? + * @param songId The song ID to check. + * @param difficultyId The difficulty to check. + * @param score The score to check the rank for. + * @return Whether the score's rank is better than the current rank. + */ + public function isSongHighRank(songId:String, difficultyId:String = 'normal', score:SaveScoreData):Bool + { + var newScoreRank = Scoring.calculateRank(score); + if (newScoreRank == null) + { + // The provided score is invalid. + return false; + } + + var song = data.scores.songs.get(songId); + if (song == null) + { + song = []; + data.scores.songs.set(songId, song); + } + var currentScore = song.get(difficultyId); + var currentScoreRank = Scoring.calculateRank(currentScore); + if (currentScoreRank == null) + { + // There is no primary highscore for this song. + return true; + } + + return newScoreRank > currentScoreRank; + } + /** * Has the provided song been beaten on one of the listed difficulties? * @param songId The song ID to check. @@ -832,6 +904,29 @@ class Save return cast legacySave.data; } } + + /** + * Serialize this Save into a JSON string. + * @param pretty Whether the JSON should be big ol string (false), + * or formatted with tabs (true) + * @return The JSON string. + */ + public function serialize(pretty:Bool = true):String + { + var ignoreNullOptionals = true; + var writer = new json2object.JsonWriter(ignoreNullOptionals); + return writer.write(data, pretty ? ' ' : null); + } + + public function updateVersionToLatest():Void + { + this.data.version = Save.SAVE_DATA_VERSION; + } + + public function debug_dumpSave():Void + { + FileUtil.saveFile(haxe.io.Bytes.ofString(this.serialize()), [FileUtil.FILE_FILTER_JSON], null, null, './save.json', 'Write save data as JSON...'); + } } /** @@ -904,6 +999,9 @@ typedef SaveHighScoresData = typedef SaveDataMods = { var enabledMods:Array; + + // TODO: Make this not trip up the serializer when debugging. + @:jignored var modOptions:Map; } diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index c54091d26..f0ca9a942 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1608,7 +1608,19 @@ class FreeplayState extends MusicBeatSubState var daSong:Null = grpCapsules.members[curSelected].songData; if (daSong != null) { - var songScore:SaveScoreData = Save.instance.getSongScore(grpCapsules.members[curSelected].songData.songId, currentDifficulty); + // TODO: Make this actually be the variation you're focused on. We don't need to fetch the song metadata just to calculate it. + var targetSong:Song = SongRegistry.instance.fetchEntry(grpCapsules.members[curSelected].songData.songId); + if (targetSong == null) + { + FlxG.log.warn('WARN: could not find song with id (${grpCapsules.members[curSelected].songData.songId})'); + return; + } + var targetVariation:String = targetSong.getFirstValidVariation(currentDifficulty); + + // TODO: This line of code makes me sad, but you can't really fix it without a breaking migration. + var suffixedDifficulty = (targetVariation != Constants.DEFAULT_VARIATION + && targetVariation != 'erect') ? '$currentDifficulty-${targetVariation}' : currentDifficulty; + var songScore:SaveScoreData = Save.instance.getSongScore(grpCapsules.members[curSelected].songData.songId, suffixedDifficulty); intendedScore = songScore?.score ?? 0; intendedCompletion = songScore == null ? 0.0 : ((songScore.tallies.sick + songScore.tallies.good) / songScore.tallies.totalNotes); rememberedDifficulty = currentDifficulty; diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index b6ec25e61..d09536eea 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -371,6 +371,33 @@ class MainMenuState extends MusicBeatState } }); } + + if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.R) + { + // Give the user a hypothetical overridden score, + // and see if we can maintain that golden P rank. + funkin.save.Save.instance.setSongScore('tutorial', 'easy', + { + score: 1234567, + tallies: + { + sick: 0, + good: 0, + bad: 0, + shit: 1, + missed: 0, + combo: 0, + maxCombo: 0, + totalNotesHit: 1, + totalNotes: 10, + } + }); + } + + if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.E) + { + funkin.save.Save.instance.debug_dumpSave(); + } #end if (FlxG.sound.music != null && FlxG.sound.music.volume < 0.8) diff --git a/source/funkin/util/FileUtil.hx b/source/funkin/util/FileUtil.hx index 7a7b1422c..00a0a14b7 100644 --- a/source/funkin/util/FileUtil.hx +++ b/source/funkin/util/FileUtil.hx @@ -19,6 +19,7 @@ import haxe.ui.containers.dialogs.Dialogs.FileDialogExtensionInfo; class FileUtil { public static final FILE_FILTER_FNFC:FileFilter = new FileFilter("Friday Night Funkin' Chart (.fnfc)", "*.fnfc"); + public static final FILE_FILTER_JSON:FileFilter = new FileFilter("JSON Data File (.json)", "*.json"); public static final FILE_FILTER_ZIP:FileFilter = new FileFilter("ZIP Archive (.zip)", "*.zip"); public static final FILE_FILTER_PNG:FileFilter = new FileFilter("PNG Image (.png)", "*.png"); From f48a65e9cebc754a721de00dbb2ad26c4f9869f0 Mon Sep 17 00:00:00 2001 From: tposejank <81495861+tposejank@users.noreply.github.com> Date: Tue, 11 Jun 2024 02:09:56 -0400 Subject: [PATCH 276/870] Remove question & compiling help --- .github/ISSUE_TEMPLATE/compiling.yml | 42 ---------------------------- .github/ISSUE_TEMPLATE/question.yml | 8 ------ 2 files changed, 50 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/compiling.yml delete mode 100644 .github/ISSUE_TEMPLATE/question.yml diff --git a/.github/ISSUE_TEMPLATE/compiling.yml b/.github/ISSUE_TEMPLATE/compiling.yml deleted file mode 100644 index d446b64b4..000000000 --- a/.github/ISSUE_TEMPLATE/compiling.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: Compiling help -description: If you need help compiling the game, and you're running into issues. -labels: ["compiling help"] -title: "Compiling help: " -body: - - type: checkboxes - attributes: - label: Issue Checklist - options: - - label: I have properly named the issue - - label: I looked in issues/discussions, if it has been previously reported - - - type: dropdown - attributes: - label: What platform are you compiling to? - options: - - Windows - - MacOS - - Linux - - HTML5 - validations: - required: true - - - type: markdown - attributes: - value: "## Describe the issue." - - - type: markdown - attributes: - value: "### Please do not report issues from other engines. These must be reported in their repositories." - - - type: markdown - attributes: - value: "#### Provide as many details as you can." - - - type: textarea - attributes: - label: Context (Provide images, videos, etc.) - - - type: textarea - attributes: - label: Steps to reproduce (or crash logs, errors, etc.) diff --git a/.github/ISSUE_TEMPLATE/question.yml b/.github/ISSUE_TEMPLATE/question.yml deleted file mode 100644 index c6e6e1b11..000000000 --- a/.github/ISSUE_TEMPLATE/question.yml +++ /dev/null @@ -1,8 +0,0 @@ -name: Question -description: Ask a general question -labels: ["question"] -title: "Question: " -body: - - type: textarea - attributes: - label: What is your question? From 93c0bd0b634a44466239ea79886be21a46bce1f2 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 11 Jun 2024 11:25:43 -0400 Subject: [PATCH 277/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 54eb4feaf..c22ed15e8 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 54eb4feaf7b740dbe1988cb35debc97bdff372b8 +Subproject commit c22ed15e83182f628d7830773021e3e48c596174 From 37a15e0a0fd9e1825680fb4fb9eb2a42922157ac Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 11 Jun 2024 12:13:10 -0400 Subject: [PATCH 278/870] reactive speaker to gamevolume on desktop --- source/funkin/audio/visualize/ABotVis.hx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/funkin/audio/visualize/ABotVis.hx b/source/funkin/audio/visualize/ABotVis.hx index a455cb8a2..cf43a8add 100644 --- a/source/funkin/audio/visualize/ABotVis.hx +++ b/source/funkin/audio/visualize/ABotVis.hx @@ -101,6 +101,10 @@ class ABotVis extends FlxTypedSpriteGroup { var animFrame:Int = Math.round(levels[i].value * 5); + #if desktop + animFrame = Math.round(animFrame * FlxG.sound.volume); + #end + animFrame = Math.floor(Math.min(5, animFrame)); animFrame = Math.floor(Math.max(0, animFrame)); From 1e3ef61fc9e34675c48189a106d6aae37cb885ad Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 11 Jun 2024 15:57:45 -0400 Subject: [PATCH 279/870] freeplay bg nicer AA and proper sizing --- source/funkin/graphics/shaders/AngleMask.hx | 76 +++++++++++++++------ source/funkin/ui/freeplay/FreeplayState.hx | 19 ++++-- 2 files changed, 70 insertions(+), 25 deletions(-) diff --git a/source/funkin/graphics/shaders/AngleMask.hx b/source/funkin/graphics/shaders/AngleMask.hx index 30e508a58..c5ef87b72 100644 --- a/source/funkin/graphics/shaders/AngleMask.hx +++ b/source/funkin/graphics/shaders/AngleMask.hx @@ -5,35 +5,73 @@ import flixel.system.FlxAssets.FlxShader; class AngleMask extends FlxShader { @:glFragmentSource(' - #pragma header - uniform vec2 endPosition; - void main() - { - vec4 base = texture2D(bitmap, openfl_TextureCoordv); + #pragma header - vec2 uv = openfl_TextureCoordv.xy; + uniform vec2 endPosition; + vec2 hash22(vec2 p) { + vec3 p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973)); + p3 += dot(p3, p3.yzx + 33.33); + return fract((p3.xx + p3.yz) * p3.zy); + } - vec2 start = vec2(0.0, 0.0); - vec2 end = vec2(endPosition.x / openfl_TextureSize.x, 1.0); + // ====== GAMMA CORRECTION ====== // + // Helps with color mixing -- good to have by default in almost any shader + // See https://www.shadertoy.com/view/lscSzl + vec3 gamma(in vec3 color) { + return pow(color, vec3(1.0 / 2.2)); + } - float dx = end.x - start.x; - float dy = end.y - start.y; + vec4 mainPass(vec2 fragCoord) { + vec4 base = texture2D(bitmap, fragCoord); - float angle = atan(dy, dx); + vec2 uv = fragCoord.xy; - uv.x -= start.x; - uv.y -= start.y; + vec2 start = vec2(0.0, 0.0); + vec2 end = vec2(endPosition.x / openfl_TextureSize.x, 1.0); - float uvA = atan(uv.y, uv.x); + float dx = end.x - start.x; + float dy = end.y - start.y; - if (uvA < angle) - gl_FragColor = base; - else - gl_FragColor = vec4(0.0); + float angle = atan(dy, dx); - }') + uv.x -= start.x; + uv.y -= start.y; + + float uvA = atan(uv.y, uv.x); + + if (uvA < angle) + return base; + else + return vec4(0.0); + } + + vec4 antialias(vec2 fragCoord) { + + const float AA_STAGES = 2.0; + + const float AA_TOTAL_PASSES = AA_STAGES * AA_STAGES + 1.0; + const float AA_JITTER = 0.5; + + // Run the shader multiple times with a random subpixel offset each time and average the results + vec4 color = mainPass(fragCoord); + for (float x = 0.0; x < AA_STAGES; x++) + { + for (float y = 0.0; y < AA_STAGES; y++) + { + vec2 offset = AA_JITTER * (2.0 * hash22(vec2(x, y)) - 1.0) / openfl_TextureSize.xy; + color += mainPass(fragCoord + offset); + } + } + return color / AA_TOTAL_PASSES; + } + + void main() { + vec4 col = antialias(openfl_TextureCoordv); + // col.xyz = gamma(col.xyz); + gl_FragColor = col; + }') public function new() { super(); diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 06684ae7c..1149aec0c 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -458,15 +458,20 @@ class FreeplayState extends MusicBeatSubState add(dj); - bgDad = new FlxSprite(pinkBack.width * 0.75, 0).loadGraphic(Paths.image('freeplay/freeplayBGdad')); - bgDad.setGraphicSize(0, FlxG.height); - bgDad.updateHitbox(); + bgDad = new FlxSprite(pinkBack.width * 0.74, 0).loadGraphic(Paths.image('freeplay/freeplayBGdad')); bgDad.shader = new AngleMask(); bgDad.visible = false; var blackOverlayBullshitLOLXD:FlxSprite = new FlxSprite(FlxG.width).makeGraphic(Std.int(bgDad.width), Std.int(bgDad.height), FlxColor.BLACK); add(blackOverlayBullshitLOLXD); // used to mask the text lol! + // this makes the texture sizes consistent, for the angle shader + bgDad.setGraphicSize(0, FlxG.height); + blackOverlayBullshitLOLXD.setGraphicSize(0, FlxG.height); + + bgDad.updateHitbox(); + blackOverlayBullshitLOLXD.updateHitbox(); + exitMovers.set([blackOverlayBullshitLOLXD, bgDad], { x: FlxG.width * 1.5, @@ -475,7 +480,7 @@ class FreeplayState extends MusicBeatSubState }); add(bgDad); - FlxTween.tween(blackOverlayBullshitLOLXD, {x: pinkBack.width * 0.76}, 0.7, {ease: FlxEase.quintOut}); + FlxTween.tween(blackOverlayBullshitLOLXD, {x: pinkBack.width * 0.74}, 0.7, {ease: FlxEase.quintOut}); blackOverlayBullshitLOLXD.shader = bgDad.shader; @@ -971,13 +976,15 @@ class FreeplayState extends MusicBeatSubState grpCapsules.members[curSelected].ranking.scale.set(20, 20); grpCapsules.members[curSelected].blurredRanking.scale.set(20, 20); - if (fromResults?.newRank != null) { + if (fromResults?.newRank != null) + { grpCapsules.members[curSelected].ranking.animation.play(fromResults.newRank.getFreeplayRankIconAsset(), true); } FlxTween.tween(grpCapsules.members[curSelected].ranking, {"scale.x": 1, "scale.y": 1}, 0.1); - if (fromResults?.newRank != null) { + if (fromResults?.newRank != null) + { grpCapsules.members[curSelected].blurredRanking.animation.play(fromResults.newRank.getFreeplayRankIconAsset(), true); } FlxTween.tween(grpCapsules.members[curSelected].blurredRanking, {"scale.x": 1, "scale.y": 1}, 0.1); From b7eaa238e01ba0003ebd53cf71ecb2930c6c7b76 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Wed, 12 Jun 2024 00:34:04 +0200 Subject: [PATCH 280/870] Revert camCutscene rename --- source/funkin/play/PlayState.hx | 16 ++++++++-------- source/funkin/play/cutscene/VideoCutscene.hx | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 20b9d3661..b88fef188 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -493,7 +493,7 @@ class PlayState extends MusicBeatSubState /** * The camera which contains, and controls visibility of, a video cutscene, dialogue, pause menu and sticker transition. */ - public var camOther:FlxCamera; + public var camCutscene:FlxCamera; /** * The combo popups. Includes the real-time combo counter and the rating. @@ -960,7 +960,7 @@ class PlayState extends MusicBeatSubState FlxTransitionableState.skipNextTransIn = true; FlxTransitionableState.skipNextTransOut = true; - pauseSubState.camera = camOther; + pauseSubState.camera = camCutscene; openSubState(pauseSubState); // boyfriendPos.put(); // TODO: Why is this here? } @@ -1501,12 +1501,12 @@ class PlayState extends MusicBeatSubState camGame.bgColor = BACKGROUND_COLOR; // Show a pink background behind the stage. camHUD = new FlxCamera(); camHUD.bgColor.alpha = 0; // Show the game scene behind the camera. - camOther = new FlxCamera(); - camOther.bgColor.alpha = 0; // Show the game scene behind the camera. + camCutscene = new FlxCamera(); + camCutscene.bgColor.alpha = 0; // Show the game scene behind the camera. FlxG.cameras.reset(camGame); FlxG.cameras.add(camHUD, false); - FlxG.cameras.add(camOther, false); + FlxG.cameras.add(camCutscene, false); // Configure camera follow point. if (previousCameraFollowPoint != null) @@ -1918,7 +1918,7 @@ class PlayState extends MusicBeatSubState if (!currentConversation.alive) currentConversation.revive(); currentConversation.completeCallback = onConversationComplete; - currentConversation.cameras = [camOther]; + currentConversation.cameras = [camCutscene]; currentConversation.zIndex = 1000; add(currentConversation); refresh(); @@ -2750,7 +2750,7 @@ class PlayState extends MusicBeatSubState persistentUpdate = false; FlxTransitionableState.skipNextTransIn = true; FlxTransitionableState.skipNextTransOut = true; - pauseSubState.camera = camOther; + pauseSubState.camera = camCutscene; openSubState(pauseSubState); } } @@ -2766,7 +2766,7 @@ class PlayState extends MusicBeatSubState persistentUpdate = false; FlxTransitionableState.skipNextTransIn = true; FlxTransitionableState.skipNextTransOut = true; - pauseSubState.camera = camOther; + pauseSubState.camera = camCutscene; openSubState(pauseSubState); } } diff --git a/source/funkin/play/cutscene/VideoCutscene.hx b/source/funkin/play/cutscene/VideoCutscene.hx index 2177114aa..7612c3ab6 100644 --- a/source/funkin/play/cutscene/VideoCutscene.hx +++ b/source/funkin/play/cutscene/VideoCutscene.hx @@ -85,7 +85,7 @@ class VideoCutscene // Display a black screen to hide the game while the video is playing. blackScreen = new FlxSprite(-200, -200).makeGraphic(FlxG.width * 2, FlxG.height * 2, FlxColor.BLACK); blackScreen.scrollFactor.set(0, 0); - blackScreen.cameras = [PlayState.instance.camOther]; + blackScreen.cameras = [PlayState.instance.camCutscene]; PlayState.instance.add(blackScreen); VideoCutscene.cutsceneType = cutsceneType; @@ -119,7 +119,7 @@ class VideoCutscene vid.finishCallback = finishVideo.bind(0.5); - vid.cameras = [PlayState.instance.camOther]; + vid.cameras = [PlayState.instance.camCutscene]; PlayState.instance.add(vid); @@ -146,7 +146,7 @@ class VideoCutscene vid.bitmap.onEndReached.add(finishVideo.bind(0.5)); vid.autoPause = false; - vid.cameras = [PlayState.instance.camOther]; + vid.cameras = [PlayState.instance.camCutscene]; PlayState.instance.add(vid); From c4d6e18885bc02fb723e1f73a87ad2ca67a6ede3 Mon Sep 17 00:00:00 2001 From: AppleHair <95587502+AppleHair@users.noreply.github.com> Date: Wed, 12 Jun 2024 11:23:45 +0300 Subject: [PATCH 281/870] now using getVariationsByCharId instead --- 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 5a7fa54d2..1caad3ee5 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1892,7 +1892,7 @@ class FreeplayState extends MusicBeatSubState { var previewSong:Null = SongRegistry.instance.fetchEntry(daSongCapsule.songData.songId); var instSuffix:String = previewSong?.getDifficulty(currentDifficulty, - previewSong?.variations ?? Constants.DEFAULT_VARIATION_LIST)?.characters?.instrumental ?? ''; + previewSong?.getVariationsByCharId(currentCharacter) ?? Constants.DEFAULT_VARIATION_LIST)?.characters?.instrumental ?? ''; instSuffix = (instSuffix != '') ? '-$instSuffix' : ''; FunkinSound.playMusic(daSongCapsule.songData.songId, { From 47f885ae97f37eaf0f165c377dc76f41df260ba0 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 12 Jun 2024 13:33:19 -0400 Subject: [PATCH 282/870] Charter credits for Eggnog Erect --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index c22ed15e8..2e1594ee4 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit c22ed15e83182f628d7830773021e3e48c596174 +Subproject commit 2e1594ee4c04c7148628bae471bdd061c9deb6b7 From 1ebcae79fe186e0f5aa4c1d917a017c810981c4b Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 12 Jun 2024 13:14:24 -0400 Subject: [PATCH 283/870] changelog for 0.4.1 --- CHANGELOG.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78391c275..1e331cf27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,21 @@ 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.1] +## [0.4.1] - 2024-06-12 +### Added +- Pressing ESCAPE on the title screen on desktop now exits the game, allowing you to exit the game while in fullscreen on desktop ### Changed - Tweaked the chart for Lit Up some more to fix some offset notes. +- A-Bot speaker now reacts to the user's volume preference on desktop (thanks to [M7theguy for the issue report/suggestion](https://github.com/FunkinCrew/Funkin/issues/2744)!) +- On Freeplay, heart icons are shifted to the right when you favorite a song that has no rank on it. +- Only play `scrollMenu` sound effect when there's a real change on the freeplay menu ([thanks gamerbross for the PR!](https://github.com/FunkinCrew/Funkin/pull/2741)) ### Fixed -- Bug where Dadbattle shows up as Dadbattle Erect when returning to freeplay +- Fixed crash when attempting to exit the gameover screen when also attempting to retry the song ([thanks DMMaster636 for the PR!](https://github.com/FunkinCrew/Funkin/pull/2709)) +- Fix botplay sustain release bug ([thanks Hundrec!](Fix botplay sustain release bug #2683)) +- Fix for the camera not pausing during a gameplay pause ([thanks gamerbross!](https://github.com/FunkinCrew/Funkin/pull/2684)) +- Fixed issue where Pico's gameplay sprite would unintentionally appear on the gameover screen when dying on 2Hot from an explosion +- Freeplay previews properly fade volume during the BF idle animation +- Fixed bug where Dadbattle incorrectly appeared as Dadbattle Erect when returning to freeplay on Hard - Fixed 2Hot not appearing under the "#" category in Freeplay menu - Fixed a bug where the Chart Editor would crash when attempting to select an event with the Event toolbox open - Improved offsets for Pico and Tankman opponents so they don't slide around as much. From f8ecddc5b313d555d4fefa33dd570ad57be598a8 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 12 Jun 2024 13:19:31 -0400 Subject: [PATCH 284/870] added eric code to changelog --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e331cf27..9997ca4bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,12 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.4.1] - 2024-06-12 ### Added - Pressing ESCAPE on the title screen on desktop now exits the game, allowing you to exit the game while in fullscreen on desktop +- Freeplay menu controls are now rebindable ### Changed +- Highscores and ranks are now saved separately, which fixes the issue where people would overwrite their saves with higher scores, +which would remove their rank if they had a lower one. - Tweaked the chart for Lit Up some more to fix some offset notes. - A-Bot speaker now reacts to the user's volume preference on desktop (thanks to [M7theguy for the issue report/suggestion](https://github.com/FunkinCrew/Funkin/issues/2744)!) - On Freeplay, heart icons are shifted to the right when you favorite a song that has no rank on it. - Only play `scrollMenu` sound effect when there's a real change on the freeplay menu ([thanks gamerbross for the PR!](https://github.com/FunkinCrew/Funkin/pull/2741)) +- Gave antialiasing to the edge of the dad graphic on Freeplay +- Rearranged some controls in the controls menu ### Fixed +- Fixed an issue in the controls menu where some control binds would overlap their names - Fixed crash when attempting to exit the gameover screen when also attempting to retry the song ([thanks DMMaster636 for the PR!](https://github.com/FunkinCrew/Funkin/pull/2709)) - Fix botplay sustain release bug ([thanks Hundrec!](Fix botplay sustain release bug #2683)) - Fix for the camera not pausing during a gameplay pause ([thanks gamerbross!](https://github.com/FunkinCrew/Funkin/pull/2684)) @@ -23,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed a bug where the Chart Editor would crash when attempting to select an event with the Event toolbox open - Improved offsets for Pico and Tankman opponents so they don't slide around as much. - Fixed an issue where M.I.L.F. displayed the wrong difficulty rating in the Freeplay menu. +- Fixed the black "temp" graphic on freeplay from being incorrectly sized / masked, now it's identical to the dad freeplay graphic From 7ce0544b18e2d227739052f9d7bf0798f8a905b4 Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 12 Jun 2024 13:25:00 -0400 Subject: [PATCH 285/870] Update CHANGELOG.md --- CHANGELOG.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9997ca4bc..054f01f49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.4.1] - 2024-06-12 ### Added - Pressing ESCAPE on the title screen on desktop now exits the game, allowing you to exit the game while in fullscreen on desktop -- Freeplay menu controls are now rebindable +- Freeplay menu controls (favoriting and switching categories) are now rebindable from the Options menu, and now have default binds on controllers. ### Changed - Highscores and ranks are now saved separately, which fixes the issue where people would overwrite their saves with higher scores, which would remove their rank if they had a lower one. @@ -17,6 +17,10 @@ which would remove their rank if they had a lower one. - Only play `scrollMenu` sound effect when there's a real change on the freeplay menu ([thanks gamerbross for the PR!](https://github.com/FunkinCrew/Funkin/pull/2741)) - Gave antialiasing to the edge of the dad graphic on Freeplay - Rearranged some controls in the controls menu +- Made several chart revisions + - Re-enabled custom camera events in Roses (Erect/Nightmare) + - Tweaked the chart for Lit Up (Hard) + - Corrected the difficulty ratings for M.I.L.F. (Easy/Normal/Hard) ### Fixed - Fixed an issue in the controls menu where some control binds would overlap their names - Fixed crash when attempting to exit the gameover screen when also attempting to retry the song ([thanks DMMaster636 for the PR!](https://github.com/FunkinCrew/Funkin/pull/2709)) @@ -28,11 +32,8 @@ which would remove their rank if they had a lower one. - Fixed 2Hot not appearing under the "#" category in Freeplay menu - Fixed a bug where the Chart Editor would crash when attempting to select an event with the Event toolbox open - Improved offsets for Pico and Tankman opponents so they don't slide around as much. -- Fixed an issue where M.I.L.F. displayed the wrong difficulty rating in the Freeplay menu. - Fixed the black "temp" graphic on freeplay from being incorrectly sized / masked, now it's identical to the dad freeplay graphic - - ## [0.4.0] - 2024-06-06 ### Added - 2 new Erect remixes, Eggnog and Satin Panties. Check them out from the Freeplay menu! From 48653ababd38c56a82a22e8e01855c7222ea25ce Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 12 Jun 2024 14:56:15 -0400 Subject: [PATCH 286/870] Update CHANGELOG.md --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 054f01f49..755b3b3bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Highscores and ranks are now saved separately, which fixes the issue where people would overwrite their saves with higher scores, which would remove their rank if they had a lower one. -- Tweaked the chart for Lit Up some more to fix some offset notes. - A-Bot speaker now reacts to the user's volume preference on desktop (thanks to [M7theguy for the issue report/suggestion](https://github.com/FunkinCrew/Funkin/issues/2744)!) - On Freeplay, heart icons are shifted to the right when you favorite a song that has no rank on it. - Only play `scrollMenu` sound effect when there's a real change on the freeplay menu ([thanks gamerbross for the PR!](https://github.com/FunkinCrew/Funkin/pull/2741)) From cce2ab7fff202bb74e358966e42028f27ee11268 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 12 Jun 2024 15:05:32 -0400 Subject: [PATCH 287/870] update project.xml for 0.4.1 lol --- Project.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.xml b/Project.xml index e0e25883d..fae9c768b 100644 --- a/Project.xml +++ b/Project.xml @@ -2,7 +2,7 @@ - + From 9908f973cf1ec322a11ada5e8928992d6cf8bc2b Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 12 Jun 2024 15:27:56 -0400 Subject: [PATCH 288/870] someone pls tell me how to use two different git submodules --- .gitmodules | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 452c0089b..be5e0aaa8 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 7a2b023f307c673d212ddec1817e97ef8933167e Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 12 Jun 2024 15:29:44 -0400 Subject: [PATCH 289/870] gitmodules for dev repo --- .gitmodules | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index be5e0aaa8..452c0089b 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 80981eee3733c3507250a37e2bff9807a481aa0c Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 12 Jun 2024 15:41:42 -0400 Subject: [PATCH 290/870] inputs null fix --- source/funkin/input/Controls.hx | 370 +++++++++++++++++++------------- 1 file changed, 218 insertions(+), 152 deletions(-) diff --git a/source/funkin/input/Controls.hx b/source/funkin/input/Controls.hx index e2cae5613..f6c881f6d 100644 --- a/source/funkin/input/Controls.hx +++ b/source/funkin/input/Controls.hx @@ -31,6 +31,7 @@ class Controls extends FlxActionSet * Uses FlxActions to funnel various inputs to a single action. */ var _ui_up = new FunkinAction(Action.UI_UP); + var _ui_left = new FunkinAction(Action.UI_LEFT); var _ui_right = new FunkinAction(Action.UI_RIGHT); var _ui_down = new FunkinAction(Action.UI_DOWN); @@ -325,19 +326,18 @@ class Controls extends FlxActionSet add(_volume_down); add(_volume_mute); - for (action in digitalActions) { - if (Std.isOfType(action, FunkinAction)) { + for (action in digitalActions) + { + if (Std.isOfType(action, FunkinAction)) + { var funkinAction:FunkinAction = cast action; byName[funkinAction.name] = funkinAction; - if (funkinAction.namePressed != null) - byName[funkinAction.namePressed] = funkinAction; - if (funkinAction.nameReleased != null) - byName[funkinAction.nameReleased] = funkinAction; + if (funkinAction.namePressed != null) byName[funkinAction.namePressed] = funkinAction; + if (funkinAction.nameReleased != null) byName[funkinAction.nameReleased] = funkinAction; } } - if (scheme == null) - scheme = None; + if (scheme == null) scheme = None; setKeyboardScheme(scheme, false); } @@ -350,38 +350,38 @@ class Controls extends FlxActionSet public function check(name:Action, trigger:FlxInputState = JUST_PRESSED, gamepadOnly:Bool = false):Bool { #if debug - if (!byName.exists(name)) - throw 'Invalid name: $name'; + if (!byName.exists(name)) throw 'Invalid name: $name'; #end var action = byName[name]; - if (gamepadOnly) - return action.checkFiltered(trigger, GAMEPAD); + if (gamepadOnly) return action.checkFiltered(trigger, GAMEPAD); else return action.checkFiltered(trigger); } - public function getKeysForAction(name:Action):Array { + public function getKeysForAction(name:Action):Array + { #if debug - if (!byName.exists(name)) - throw 'Invalid name: $name'; + if (!byName.exists(name)) throw 'Invalid name: $name'; #end // TODO: Revert to `.map().filter()` once HashLink doesn't complain anymore. var result:Array = []; - for (input in byName[name].inputs) { + for (input in byName[name].inputs) + { if (input.device == KEYBOARD) result.push(input.inputID); } return result; } - public function getButtonsForAction(name:Action):Array { + public function getButtonsForAction(name:Action):Array + { #if debug - if (!byName.exists(name)) - throw 'Invalid name: $name'; + if (!byName.exists(name)) throw 'Invalid name: $name'; #end var result:Array = []; - for (input in byName[name].inputs) { + for (input in byName[name].inputs) + { if (input.device == GAMEPAD) result.push(input.inputID); } return result; @@ -405,7 +405,7 @@ class Controls extends FlxActionSet function getActionFromControl(control:Control):FlxActionDigital { - return switch(control) + return switch (control) { case UI_UP: _ui_up; case UI_DOWN: _ui_down; @@ -448,7 +448,7 @@ class Controls extends FlxActionSet */ function forEachBound(control:Control, func:FlxActionDigital->FlxInputState->Void) { - switch(control) + switch (control) { case UI_UP: func(_ui_up, PRESSED); @@ -519,10 +519,9 @@ class Controls extends FlxActionSet public function replaceBinding(control:Control, device:Device, toAdd:Int, toRemove:Int) { - if (toAdd == toRemove) - return; + if (toAdd == toRemove) return; - switch(device) + switch (device) { case Keys: forEachBound(control, function(action, state) replaceKey(action, toAdd, toRemove, state)); @@ -534,7 +533,8 @@ class Controls extends FlxActionSet function replaceKey(action:FlxActionDigital, toAdd:FlxKey, toRemove:FlxKey, state:FlxInputState) { - if (action.inputs.length == 0) { + if (action.inputs.length == 0) + { // Add the keybind, don't replace. addKeys(action, [toAdd], state); return; @@ -548,34 +548,44 @@ class Controls extends FlxActionSet if (input.device == KEYBOARD && input.inputID == toRemove) { - if (toAdd == FlxKey.NONE) { + if (toAdd == FlxKey.NONE) + { // Remove the keybind, don't replace. action.inputs.remove(input); - } else { + } + else + { // Replace the keybind. @:privateAccess action.inputs[i].inputID = toAdd; } hasReplaced = true; - } else if (input.device == KEYBOARD && input.inputID == toAdd) { + } + else if (input.device == KEYBOARD && input.inputID == toAdd) + { // This key is already bound! - if (hasReplaced) { + if (hasReplaced) + { // Remove the duplicate keybind, don't replace. action.inputs.remove(input); - } else { + } + else + { hasReplaced = true; } } } - if (!hasReplaced) { + if (!hasReplaced) + { addKeys(action, [toAdd], state); } } function replaceButton(action:FlxActionDigital, deviceID:Int, toAdd:FlxGamepadInputID, toRemove:FlxGamepadInputID, state:FlxInputState) { - if (action.inputs.length == 0) { + if (action.inputs.length == 0) + { addButtons(action, [toAdd], state, deviceID); return; } @@ -594,7 +604,8 @@ class Controls extends FlxActionSet } } - if (!hasReplaced) { + if (!hasReplaced) + { addButtons(action, [toAdd], state, deviceID); } } @@ -606,18 +617,16 @@ class Controls extends FlxActionSet var action = controls.byName[name]; for (input in action.inputs) { - if (device == null || isDevice(input, device)) - byName[name].add(cast input); + if (device == null || isDevice(input, device)) byName[name].add(cast input); } } - switch(device) + switch (device) { case null: // add all for (gamepad in controls.gamepadsAdded) - if (gamepadsAdded.indexOf(gamepad) == -1) - gamepadsAdded.push(gamepad); + if (gamepadsAdded.indexOf(gamepad) == -1) gamepadsAdded.push(gamepad); mergeKeyboardScheme(controls.keyboardScheme); @@ -637,7 +646,7 @@ class Controls extends FlxActionSet { if (scheme != None) { - switch(keyboardScheme) + switch (keyboardScheme) { case None: keyboardScheme = scheme; @@ -672,7 +681,8 @@ class Controls extends FlxActionSet static function addKeys(action:FlxActionDigital, keys:Array, state:FlxInputState) { - for (key in keys) { + for (key in keys) + { if (key == FlxKey.NONE) continue; // Ignore unbound keys. action.addKey(key, state); } @@ -684,15 +694,13 @@ class Controls extends FlxActionSet while (i-- > 0) { var input = action.inputs[i]; - if (input.device == KEYBOARD && keys.indexOf(cast input.inputID) != -1) - action.remove(input); + if (input.device == KEYBOARD && keys.indexOf(cast input.inputID) != -1) action.remove(input); } } public function setKeyboardScheme(scheme:KeyboardScheme, reset = true) { - if (reset) - removeKeyboard(); + if (reset) removeKeyboard(); keyboardScheme = scheme; @@ -724,10 +732,13 @@ class Controls extends FlxActionSet bindMobileLol(); } - function getDefaultKeybinds(scheme:KeyboardScheme, control:Control):Array { - switch (scheme) { + function getDefaultKeybinds(scheme:KeyboardScheme, control:Control):Array + { + switch (scheme) + { case Solo: - switch (control) { + switch (control) + { case Control.UI_UP: return [W, FlxKey.UP]; case Control.UI_DOWN: return [S, FlxKey.DOWN]; case Control.UI_LEFT: return [A, FlxKey.LEFT]; @@ -754,7 +765,8 @@ class Controls extends FlxActionSet case Control.VOLUME_MUTE: return [ZERO, NUMPADZERO]; } case Duo(true): - switch (control) { + switch (control) + { case Control.UI_UP: return [W]; case Control.UI_DOWN: return [S]; case Control.UI_LEFT: return [A]; @@ -779,10 +791,10 @@ class Controls extends FlxActionSet case Control.VOLUME_UP: return [PLUS]; case Control.VOLUME_DOWN: return [MINUS]; case Control.VOLUME_MUTE: return [ZERO]; - } case Duo(false): - switch (control) { + switch (control) + { case Control.UI_UP: return [FlxKey.UP]; case Control.UI_DOWN: return [FlxKey.DOWN]; case Control.UI_LEFT: return [FlxKey.LEFT]; @@ -807,7 +819,6 @@ class Controls extends FlxActionSet case Control.VOLUME_UP: return [NUMPADPLUS]; case Control.VOLUME_DOWN: return [NUMPADMINUS]; case Control.VOLUME_MUTE: return [NUMPADZERO]; - } default: // Fallthrough. @@ -834,8 +845,7 @@ class Controls extends FlxActionSet #end #if android - forEachBound(Control.BACK, function(action, pres) - { + forEachBound(Control.BACK, function(action, pres) { action.add(new FlxActionInputDigitalAndroid(FlxAndroidKey.BACK, JUST_PRESSED)); }); #end @@ -849,8 +859,7 @@ class Controls extends FlxActionSet while (i-- > 0) { var input = action.inputs[i]; - if (input.device == KEYBOARD) - action.remove(input); + if (input.device == KEYBOARD) action.remove(input); } } } @@ -862,11 +871,13 @@ class Controls extends FlxActionSet fromSaveData(padData, Gamepad(id)); } - public function getGamepadIds():Array { + public function getGamepadIds():Array + { return gamepadsAdded; } - public function getGamepads():Array { + public function getGamepads():Array + { return [for (id in gamepadsAdded) FlxG.gamepads.getByID(id)]; } @@ -886,8 +897,7 @@ class Controls extends FlxActionSet while (i-- > 0) { var input = action.inputs[i]; - if (isGamepad(input, deviceID)) - action.remove(input); + if (isGamepad(input, deviceID)) action.remove(input); } } @@ -924,32 +934,58 @@ class Controls extends FlxActionSet ]); } - function getDefaultGamepadBinds(control:Control):Array { - switch(control) { - case Control.ACCEPT: return [#if switch B #else A #end]; - case Control.BACK: return [#if switch A #else B #end]; - case Control.UI_UP: return [DPAD_UP, LEFT_STICK_DIGITAL_UP]; - case Control.UI_DOWN: return [DPAD_DOWN, LEFT_STICK_DIGITAL_DOWN]; - case Control.UI_LEFT: return [DPAD_LEFT, LEFT_STICK_DIGITAL_LEFT]; - case Control.UI_RIGHT: return [DPAD_RIGHT, LEFT_STICK_DIGITAL_RIGHT]; - case Control.NOTE_UP: return [DPAD_UP, Y, LEFT_STICK_DIGITAL_UP, RIGHT_STICK_DIGITAL_UP]; - case Control.NOTE_DOWN: return [DPAD_DOWN, A, LEFT_STICK_DIGITAL_DOWN, RIGHT_STICK_DIGITAL_DOWN]; - case Control.NOTE_LEFT: return [DPAD_LEFT, X, LEFT_STICK_DIGITAL_LEFT, RIGHT_STICK_DIGITAL_LEFT]; - case Control.NOTE_RIGHT: return [DPAD_RIGHT, B, LEFT_STICK_DIGITAL_RIGHT, RIGHT_STICK_DIGITAL_RIGHT]; - case Control.PAUSE: return [START]; - case Control.RESET: return [FlxGamepadInputID.BACK]; // Back (i.e. Select) - case Control.WINDOW_FULLSCREEN: []; - case Control.WINDOW_SCREENSHOT: []; - case Control.CUTSCENE_ADVANCE: return [A]; - case Control.FREEPLAY_FAVORITE: [FlxGamepadInputID.BACK]; // Back (i.e. Select) - case Control.FREEPLAY_LEFT: [LEFT_SHOULDER]; - case Control.FREEPLAY_RIGHT: [RIGHT_SHOULDER]; - case Control.VOLUME_UP: []; - case Control.VOLUME_DOWN: []; - case Control.VOLUME_MUTE: []; - case Control.DEBUG_MENU: []; - case Control.DEBUG_CHART: []; - case Control.DEBUG_STAGE: []; + function getDefaultGamepadBinds(control:Control):Array + { + switch (control) + { + case Control.ACCEPT: + return [#if switch B #else A #end]; + case Control.BACK: + return [#if switch A #else B #end]; + case Control.UI_UP: + return [DPAD_UP, LEFT_STICK_DIGITAL_UP]; + case Control.UI_DOWN: + return [DPAD_DOWN, LEFT_STICK_DIGITAL_DOWN]; + case Control.UI_LEFT: + return [DPAD_LEFT, LEFT_STICK_DIGITAL_LEFT]; + case Control.UI_RIGHT: + return [DPAD_RIGHT, LEFT_STICK_DIGITAL_RIGHT]; + case Control.NOTE_UP: + return [DPAD_UP, Y, LEFT_STICK_DIGITAL_UP, RIGHT_STICK_DIGITAL_UP]; + case Control.NOTE_DOWN: + return [DPAD_DOWN, A, LEFT_STICK_DIGITAL_DOWN, RIGHT_STICK_DIGITAL_DOWN]; + case Control.NOTE_LEFT: + return [DPAD_LEFT, X, LEFT_STICK_DIGITAL_LEFT, RIGHT_STICK_DIGITAL_LEFT]; + case Control.NOTE_RIGHT: + return [DPAD_RIGHT, B, LEFT_STICK_DIGITAL_RIGHT, RIGHT_STICK_DIGITAL_RIGHT]; + case Control.PAUSE: + return [START]; + case Control.RESET: + return [FlxGamepadInputID.BACK]; // Back (i.e. Select) + case Control.WINDOW_FULLSCREEN: + []; + case Control.WINDOW_SCREENSHOT: + []; + case Control.CUTSCENE_ADVANCE: + return [A]; + case Control.FREEPLAY_FAVORITE: + [FlxGamepadInputID.BACK]; // Back (i.e. Select) + case Control.FREEPLAY_LEFT: + [LEFT_SHOULDER]; + case Control.FREEPLAY_RIGHT: + [RIGHT_SHOULDER]; + case Control.VOLUME_UP: + []; + case Control.VOLUME_DOWN: + []; + case Control.VOLUME_MUTE: + []; + case Control.DEBUG_MENU: + []; + case Control.DEBUG_CHART: + []; + case Control.DEBUG_STAGE: + []; default: // Fallthrough. } @@ -967,8 +1003,7 @@ class Controls extends FlxActionSet public function touchShit(control:Control, id) { - forEachBound(control, function(action, state) - { + forEachBound(control, function(action, state) { // action }); } @@ -984,7 +1019,8 @@ class Controls extends FlxActionSet inline static function addButtons(action:FlxActionDigital, buttons:Array, state, id) { - for (button in buttons) { + for (button in buttons) + { if (button == FlxGamepadInputID.NONE) continue; // Ignore unbound keys. action.addGamepad(button, state, id); } @@ -996,29 +1032,25 @@ class Controls extends FlxActionSet while (i-- > 0) { var input = action.inputs[i]; - if (isGamepad(input, gamepadID) && buttons.indexOf(cast input.inputID) != -1) - action.remove(input); + if (isGamepad(input, gamepadID) && buttons.indexOf(cast input.inputID) != -1) action.remove(input); } } public function getInputsFor(control:Control, device:Device, ?list:Array):Array { - if (list == null) - list = []; + if (list == null) list = []; - switch(device) + switch (device) { case Keys: for (input in getActionFromControl(control).inputs) { - if (input.device == KEYBOARD) - list.push(input.inputID); + if (input.device == KEYBOARD) list.push(input.inputID); } case Gamepad(id): for (input in getActionFromControl(control).inputs) { - if (isGamepad(input, id)) - list.push(input.inputID); + if (isGamepad(input, id)) list.push(input.inputID); } } return list; @@ -1026,7 +1058,7 @@ class Controls extends FlxActionSet public function removeDevice(device:Device) { - switch(device) + switch (device) { case Keys: setKeyboardScheme(None); @@ -1040,27 +1072,32 @@ class Controls extends FlxActionSet * An EMPTY array means the control is uninitialized and needs to be reset to default. * An array with a single FlxKey.NONE means the control was intentionally unbound by the user. */ - public function fromSaveData(data:Dynamic, device:Device) + public function fromSaveData(data:Dynamic, device:Device):Void { for (control in Control.createAll()) { var inputs:Array = Reflect.field(data, control.getName()); - inputs = inputs.distinct(); + inputs = inputs?.distinct(); if (inputs != null) { - if (inputs.length == 0) { + if (inputs.length == 0) + { trace('Control ${control} is missing bindings, resetting to default.'); - switch(device) + switch (device) { case Keys: bindKeys(control, getDefaultKeybinds(Solo, control)); case Gamepad(id): bindButtons(control, id, getDefaultGamepadBinds(control)); } - } else if (inputs == [FlxKey.NONE]) { + } + else if (inputs == [FlxKey.NONE]) + { trace('Control ${control} is unbound, leaving it be.'); - } else { - switch(device) + } + else + { + switch (device) { case Keys: bindKeys(control, inputs.copy()); @@ -1068,9 +1105,11 @@ class Controls extends FlxActionSet bindButtons(control, id, inputs.copy()); } } - } else { + } + else + { trace('Control ${control} is missing bindings, resetting to default.'); - switch(device) + switch (device) { case Keys: bindKeys(control, getDefaultKeybinds(Solo, control)); @@ -1095,9 +1134,12 @@ class Controls extends FlxActionSet var inputs = getInputsFor(control, device); isEmpty = isEmpty && inputs.length == 0; - if (inputs.length == 0) { + if (inputs.length == 0) + { inputs = [FlxKey.NONE]; - } else { + } + else + { inputs = inputs.distinct(); } @@ -1109,7 +1151,7 @@ class Controls extends FlxActionSet static function isDevice(input:FlxActionInput, device:Device) { - return switch(device) + return switch (device) { case Keys: input.device == KEYBOARD; case Gamepad(id): isGamepad(input, id); @@ -1141,7 +1183,8 @@ typedef Swipes = * - Combining `pressed` and `released` inputs into one action. * - Filtering by input method (`KEYBOARD`, `MOUSE`, `GAMEPAD`, etc). */ -class FunkinAction extends FlxActionDigital { +class FunkinAction extends FlxActionDigital +{ public var namePressed(default, null):Null; public var nameReleased(default, null):Null; @@ -1158,83 +1201,102 @@ class FunkinAction extends FlxActionDigital { /** * Input checks default to whether the input was just pressed, on any input device. */ - public override function check():Bool { + public override function check():Bool + { return checkFiltered(JUST_PRESSED); } /** * Check whether the input is currently being held. */ - public function checkPressed():Bool { + public function checkPressed():Bool + { return checkFiltered(PRESSED); } /** * Check whether the input is currently being held, and was not held last frame. */ - public function checkJustPressed():Bool { + public function checkJustPressed():Bool + { return checkFiltered(JUST_PRESSED); } /** * Check whether the input is not currently being held. */ - public function checkReleased():Bool { + public function checkReleased():Bool + { return checkFiltered(RELEASED); } /** * Check whether the input is not currently being held, and was held last frame. */ - public function checkJustReleased():Bool { + public function checkJustReleased():Bool + { return checkFiltered(JUST_RELEASED); } /** * Check whether the input is currently being held by a gamepad device. */ - public function checkPressedGamepad():Bool { + public function checkPressedGamepad():Bool + { return checkFiltered(PRESSED, GAMEPAD); } /** * Check whether the input is currently being held by a gamepad device, and was not held last frame. */ - public function checkJustPressedGamepad():Bool { + public function checkJustPressedGamepad():Bool + { return checkFiltered(JUST_PRESSED, GAMEPAD); } /** * Check whether the input is not currently being held by a gamepad device. */ - public function checkReleasedGamepad():Bool { + public function checkReleasedGamepad():Bool + { return checkFiltered(RELEASED, GAMEPAD); } /** * Check whether the input is not currently being held by a gamepad device, and was held last frame. */ - public function checkJustReleasedGamepad():Bool { + public function checkJustReleasedGamepad():Bool + { return checkFiltered(JUST_RELEASED, GAMEPAD); } - public function checkMultiFiltered(?filterTriggers:Array, ?filterDevices:Array):Bool { - if (filterTriggers == null) { + public function checkMultiFiltered(?filterTriggers:Array, ?filterDevices:Array):Bool + { + if (filterTriggers == null) + { filterTriggers = [PRESSED, JUST_PRESSED]; } - if (filterDevices == null) { + if (filterDevices == null) + { filterDevices = []; } // Perform checkFiltered for each combination. - for (i in filterTriggers) { - if (filterDevices.length == 0) { - if (checkFiltered(i)) { + for (i in filterTriggers) + { + if (filterDevices.length == 0) + { + if (checkFiltered(i)) + { return true; } - } else { - for (j in filterDevices) { - if (checkFiltered(i, j)) { + } + else + { + for (j in filterDevices) + { + if (checkFiltered(i, j)) + { return true; } } @@ -1249,52 +1311,56 @@ class FunkinAction extends FlxActionDigital { * @param filterTrigger Optionally filter by trigger condition (`JUST_PRESSED`, `PRESSED`, `JUST_RELEASED`, `RELEASED`). * @param filterDevice Optionally filter by device (`KEYBOARD`, `MOUSE`, `GAMEPAD`, `OTHER`). */ - public function checkFiltered(?filterTrigger:FlxInputState, ?filterDevice:FlxInputDevice):Bool { + public function checkFiltered(?filterTrigger:FlxInputState, ?filterDevice:FlxInputDevice):Bool + { // The normal // Make sure we only update the inputs once per frame. var key = '${filterTrigger}:${filterDevice}'; var cacheEntry = cache.get(key); - if (cacheEntry != null && cacheEntry.timestamp == FlxG.game.ticks) { + if (cacheEntry != null && cacheEntry.timestamp == FlxG.game.ticks) + { return cacheEntry.value; } // Use a for loop instead so we can remove inputs while iterating. // We don't return early because we need to call check() on ALL inputs. var result = false; - var len = inputs != null ? inputs.length : 0; - for (i in 0...len) - { - var j = len - i - 1; - var input = inputs[j]; + var len = inputs != null ? inputs.length : 0; + for (i in 0...len) + { + var j = len - i - 1; + var input = inputs[j]; // Filter out dead inputs. - if (input.destroyed) - { - inputs.splice(j, 1); - continue; - } + if (input.destroyed) + { + inputs.splice(j, 1); + continue; + } // Update the input. input.update(); // Check whether the input is the right trigger. - if (filterTrigger != null && input.trigger != filterTrigger) { + if (filterTrigger != null && input.trigger != filterTrigger) + { continue; } // Check whether the input is the right device. - if (filterDevice != null && input.device != filterDevice) { + if (filterDevice != null && input.device != filterDevice) + { continue; } // Check whether the input has triggered. - if (input.check(this)) - { - result = true; - } - } + if (input.check(this)) + { + result = true; + } + } // We need to cache this result. cache.set(key, {timestamp: FlxG.game.ticks, value: result}); @@ -1391,12 +1457,12 @@ class FlxActionInputDigitalMobileSwipeGameplay extends FlxActionInputDigital { var degAngle = FlxAngle.asDegrees(swp.touchAngle); - switch(trigger) + switch (trigger) { case JUST_PRESSED: if (swp.touchLength >= activateLength) { - switch(inputID) + switch (inputID) { case FlxDirectionFlags.UP: if (degAngle >= 45 && degAngle <= 90 + 45) return properTouch(swp); @@ -1440,7 +1506,7 @@ class FlxActionInputDigitalAndroid extends FlxActionInputDigital override public function check(Action:FlxAction):Bool { - return switch(trigger) + return switch (trigger) { #if android case PRESSED: FlxG.android.checkStatus(inputID, PRESSED) || FlxG.android.checkStatus(inputID, PRESSED); From 1c45c9b03b86f2c4dc1049f0a41fd61b5e167af5 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 12 Jun 2024 15:50:59 -0400 Subject: [PATCH 291/870] git modules --- .gitmodules | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 452c0089b..be5e0aaa8 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 a63b60d458bedca9bb980e6d7c8e47b73357adfc Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 12 Jun 2024 20:31:27 -0400 Subject: [PATCH 292/870] fix for release, no bf printing directly to stdout! --- source/funkin/util/logging/AnsiTrace.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/util/logging/AnsiTrace.hx b/source/funkin/util/logging/AnsiTrace.hx index 9fdc19e1b..2c18d494d 100644 --- a/source/funkin/util/logging/AnsiTrace.hx +++ b/source/funkin/util/logging/AnsiTrace.hx @@ -51,7 +51,7 @@ class AnsiTrace public static function traceBF() { - #if sys + #if (sys && debug) if (colorSupported) { for (line in ansiBF) From 1f1fe62a06827f2487fb99d45b5a551dc07ed454 Mon Sep 17 00:00:00 2001 From: AppleHair <95587502+AppleHair@users.noreply.github.com> Date: Fri, 14 Jun 2024 16:53:33 +0300 Subject: [PATCH 293/870] [BUGFIX] Fixed Ranks not appearing in freeplay for custom variations Freeplay tries to access a song's rank using the current difficulty name alone, but custom variation ranks are being saved with a variation prefix. This PR makes freeplay look for the variation prefix when necessary. --- source/funkin/ui/freeplay/FreeplayState.hx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 0caaf4591..23c0f6afb 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -2094,8 +2094,13 @@ class FreeplaySongData { this.albumId = songDifficulty.album; } + + // TODO: This line of code makes me sad, but you can't really fix it without a breaking migration. + // `easy`, `erect`, `normal-pico`, etc. + var suffixedDifficulty = (songDifficulty.variation != Constants.DEFAULT_VARIATION + && songDifficulty.variation != 'erect') ? '$currentDifficulty-${songDifficulty.variation}' : currentDifficulty; - this.scoringRank = Save.instance.getSongRank(songId, currentDifficulty); + this.scoringRank = Save.instance.getSongRank(songId, suffixedDifficulty); this.isNew = song.isSongNew(currentDifficulty); } From b8c971786486b04663b4cafaf8da88e02296a684 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Fri, 14 Jun 2024 21:52:52 -0700 Subject: [PATCH 294/870] Reorder download Git step in compiling guide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moved “download Git” from the middle of the guide to the setup step Should prevent errors with Git before installing Git --- docs/COMPILING.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index e7c19875a..b8ddee4a7 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -2,14 +2,14 @@ 0. Setup - Download Haxe from [Haxe.org](https://haxe.org) + - Download Git from [git-scm.com](https://www.git-scm.com) 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. 2. Install `hmm` (run `haxelib --global install hmm` and then `haxelib --global run hmm 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 +3. Install all haxelibs of the current branch by running `hmm install` +4. Setup lime: `haxelib run lime setup` +5. 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 @@ -17,8 +17,8 @@ - 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 -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). +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 From 32ad9d159ee46429e582f1bd7c891ccf4cae6138 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Sat, 15 Jun 2024 13:37:21 -0400 Subject: [PATCH 295/870] Add ZIP button warning and restructured sentences Each step should be easier to follow with this structure --- docs/COMPILING.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index b8ddee4a7..b2a106c86 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -3,12 +3,13 @@ 0. Setup - Download Haxe from [Haxe.org](https://haxe.org) - Download Git from [git-scm.com](https://www.git-scm.com) -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. -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` + - Do NOT download the repository using the Download ZIP button on GitHub or you may run into errors! + - Instead, open a command prompt and do the following steps... +1. Run `git clone --recurse-submodules https://github.com/FunkinCrew/funkin.git` to clone the repository with the necessary assets submodule + - _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. Run `haxelib --global install hmm` and then `haxelib --global run hmm setup` to install hmm.json +3. Run `hmm install` to install all haxelibs of the current branch +4. Run `haxelib run lime setup` to set up lime 5. 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: From ba4677857aefbd10def4e03b3def59756deccdba Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Sat, 15 Jun 2024 20:23:55 +0200 Subject: [PATCH 296/870] Few animation editor bugfixes --- hmm.json | 2 +- .../ui/debug/anim/DebugBoundingState.hx | 23 ++++++++++++------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/hmm.json b/hmm.json index 68e0c5cb0..d217740db 100644 --- a/hmm.json +++ b/hmm.json @@ -30,7 +30,7 @@ "name": "flixel-ui", "type": "git", "dir": null, - "ref": "719b4f10d94186ed55f6fef1b6618d32abec8c15", + "ref": "d0afed7293c71ffdb1184751317fc709b44c9056", "url": "https://github.com/HaxeFlixel/flixel-ui" }, { diff --git a/source/funkin/ui/debug/anim/DebugBoundingState.hx b/source/funkin/ui/debug/anim/DebugBoundingState.hx index 04784a5b7..d82bcc612 100644 --- a/source/funkin/ui/debug/anim/DebugBoundingState.hx +++ b/source/funkin/ui/debug/anim/DebugBoundingState.hx @@ -1,6 +1,7 @@ package funkin.ui.debug.anim; import flixel.addons.display.FlxGridOverlay; +import flixel.addons.display.FlxBackdrop; import flixel.addons.ui.FlxInputText; import flixel.addons.ui.FlxUIDropDownMenu; import flixel.FlxCamera; @@ -55,7 +56,7 @@ class DebugBoundingState extends FlxState TODAY'S TO-DO - Cleaner UI */ - var bg:FlxSprite; + var bg:FlxBackdrop; var fileInfo:FlxText; var txtGrp:FlxGroup; @@ -80,7 +81,7 @@ class DebugBoundingState extends FlxState { // get the screen position, according to the HUD camera, temp default to FlxG.camera juuust in case? var hudMousePos:FlxPoint = FlxG.mouse.getScreenPosition(hudCam ?? FlxG.camera); - return Screen.instance.hasSolidComponentUnderPoint(hudMousePos.x, hudMousePos.y); + return Screen.instance.hasSolidComponentUnderPoint(hudMousePos.x, hudMousePos.y) || FlxG.mouse.overlaps(animDropDownMenu, hudCam); } override function create() @@ -103,10 +104,7 @@ class DebugBoundingState extends FlxState hudCam = new FlxCamera(); hudCam.bgColor.alpha = 0; - bg = FlxGridOverlay.create(10, 10); - // bg = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.GREEN); - - bg.scrollFactor.set(); + bg = new FlxBackdrop(FlxGridOverlay.createGrid(10, 10, FlxG.width, FlxG.height, true, 0xffe7e6e6, 0xffd9d5d5)); add(bg); // we are setting this as the default draw camera only temporarily, to trick haxeui @@ -289,16 +287,20 @@ class DebugBoundingState extends FlxState public var mouseOffset:FlxPoint = FlxPoint.get(0, 0); public var oldPos:FlxPoint = FlxPoint.get(0, 0); + public var movingCharacter:Bool = false; function mouseOffsetMovement() { if (swagChar != null) { - if (FlxG.mouse.justPressed) + if (FlxG.mouse.justPressed && !haxeUIFocused) { + movingCharacter = true; mouseOffset.set(FlxG.mouse.x - -swagChar.animOffsets[0], FlxG.mouse.y - -swagChar.animOffsets[1]); } + if (!movingCharacter) return; + if (FlxG.mouse.pressed) { swagChar.animOffsets = [(FlxG.mouse.x - mouseOffset.x) * -1, (FlxG.mouse.y - mouseOffset.y) * -1]; @@ -307,6 +309,11 @@ class DebugBoundingState extends FlxState txtOffsetShit.text = 'Offset: ' + swagChar.animOffsets; } + + if (FlxG.mouse.justReleased) + { + movingCharacter = false; + } } } @@ -373,7 +380,7 @@ class DebugBoundingState extends FlxState offsetView.visible = true; offsetView.active = true; offsetControls(); - if (!haxeUIFocused) mouseOffsetMovement(); + mouseOffsetMovement(); } if (FlxG.keys.justPressed.H) hudCam.visible = !hudCam.visible; From 9bd09e37915300ca595950a6dcc2b215f7dcf077 Mon Sep 17 00:00:00 2001 From: Eric Date: Sun, 16 Jun 2024 18:48:01 -0400 Subject: [PATCH 297/870] Make downloading the assets submodule a separate step. --- docs/COMPILING.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index b2a106c86..cc90bd348 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -5,8 +5,9 @@ - Download Git from [git-scm.com](https://www.git-scm.com) - Do NOT download the repository using the Download ZIP button on GitHub or you may run into errors! - Instead, open a command prompt and do the following steps... -1. Run `git clone --recurse-submodules https://github.com/FunkinCrew/funkin.git` to clone the repository with the necessary assets submodule - - _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._ +1. Run `git clone https://github.com/FunkinCrew/funkin.git` to clone the base repository. +2. Run `git submodule update --init --recursive` to download the game's assets. + - NOTE: By performing this operation, you are downloading Content which is proprietary and protected by national and international copyright and trademark laws. See [the LICENSE.md file for the Funkin.assets](https://github.com/FunkinCrew/funkin.assets/blob/main/LICENSE.md) repo for more information. 2. Run `haxelib --global install hmm` and then `haxelib --global run hmm setup` to install hmm.json 3. Run `hmm install` to install all haxelibs of the current branch 4. Run `haxelib run lime setup` to set up lime From 5cde06bc8687d6eae12bbbb18b1a3a673a0549fa Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sun, 9 Jun 2024 12:41:00 -0400 Subject: [PATCH 298/870] simplified the bug template to have less clutter From 4b354f6f32abb20f1d0cb1be3b787a3310eed190 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sun, 9 Jun 2024 12:41:00 -0400 Subject: [PATCH 299/870] simplified the bug template to have less clutter --- .github/ISSUE_TEMPLATE/bug.md | 50 +++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug.md diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md new file mode 100644 index 000000000..82c121b5a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -0,0 +1,50 @@ +--- +name: Bug Report +about: Report a bug or critical performance issue +title: 'Bug Report: [DESCRIBE YOUR BUG IN DETAIL HERE]' +labels: bug +--- + + + +## Describe the bug + + +## To Reproduce + +## Expected behavior + + +## Screenshots/Video + + +## Desktop + - OS: + + - Browser + + - Version: + + +## Additional context + + + From ac08f5518dd957a9e720063041069c6070a0f00d Mon Sep 17 00:00:00 2001 From: tposejank <81495861+tposejank@users.noreply.github.com> Date: Mon, 17 Jun 2024 00:45:00 -0400 Subject: [PATCH 300/870] Thanks, Git! --- .github/ISSUE_TEMPLATE/bug.md | 50 ----------------------------------- 1 file changed, 50 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug.md diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md deleted file mode 100644 index 82c121b5a..000000000 --- a/.github/ISSUE_TEMPLATE/bug.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -name: Bug Report -about: Report a bug or critical performance issue -title: 'Bug Report: [DESCRIBE YOUR BUG IN DETAIL HERE]' -labels: bug ---- - - - -## Describe the bug - - -## To Reproduce - -## Expected behavior - - -## Screenshots/Video - - -## Desktop - - OS: - - - Browser - - - Version: - - -## Additional context - - - From 60f6e5ec50b4a98923e1bdea0104d742aed7b507 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sun, 9 Jun 2024 12:41:00 -0400 Subject: [PATCH 301/870] simplified the bug template to have less clutter --- .github/ISSUE_TEMPLATE/bug.md | 50 +++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug.md diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md new file mode 100644 index 000000000..82c121b5a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -0,0 +1,50 @@ +--- +name: Bug Report +about: Report a bug or critical performance issue +title: 'Bug Report: [DESCRIBE YOUR BUG IN DETAIL HERE]' +labels: bug +--- + + + +## Describe the bug + + +## To Reproduce + +## Expected behavior + + +## Screenshots/Video + + +## Desktop + - OS: + + - Browser + + - Version: + + +## Additional context + + + From 3c81f93ca2a191d7682e1472a42baf2674ea743c Mon Sep 17 00:00:00 2001 From: tposejank <81495861+tposejank@users.noreply.github.com> Date: Mon, 17 Jun 2024 00:47:46 -0400 Subject: [PATCH 302/870] will you --- .github/ISSUE_TEMPLATE/bug.md | 51 +---------------------------------- 1 file changed, 1 insertion(+), 50 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md index 82c121b5a..45b983be3 100644 --- a/.github/ISSUE_TEMPLATE/bug.md +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -1,50 +1 @@ ---- -name: Bug Report -about: Report a bug or critical performance issue -title: 'Bug Report: [DESCRIBE YOUR BUG IN DETAIL HERE]' -labels: bug ---- - - - -## Describe the bug - - -## To Reproduce - -## Expected behavior - - -## Screenshots/Video - - -## Desktop - - OS: - - - Browser - - - Version: - - -## Additional context - - - +hi From b5c4a8589aa1d29aeaca4b892aef5f8d78838691 Mon Sep 17 00:00:00 2001 From: tposejank <81495861+tposejank@users.noreply.github.com> Date: Mon, 17 Jun 2024 00:49:09 -0400 Subject: [PATCH 303/870] Delete --- .github/ISSUE_TEMPLATE/bug.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug.md diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md deleted file mode 100644 index 32f95c0d1..000000000 --- a/.github/ISSUE_TEMPLATE/bug.md +++ /dev/null @@ -1 +0,0 @@ -hi \ No newline at end of file From 37b8c881a8809ffd8b192afec9f336a798fa8eb2 Mon Sep 17 00:00:00 2001 From: tposejank <81495861+tposejank@users.noreply.github.com> Date: Mon, 17 Jun 2024 01:06:14 -0400 Subject: [PATCH 304/870] Fulfill requests & new crash template --- .github/ISSUE_TEMPLATE/bug.yml | 4 +- .github/ISSUE_TEMPLATE/crash.yml | 69 +++++++++++++++++++ .github/ISSUE_TEMPLATE/enhancement.yml | 2 +- .github/PULL_REQUEST_TEMPLATE/bug.yml | 4 +- .github/PULL_REQUEST_TEMPLATE/enhancement.yml | 4 +- 5 files changed, 76 insertions(+), 7 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/crash.yml diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 457bf11e1..ffbc02fbc 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -1,6 +1,6 @@ name: Bug Report description: Report a bug or an issue in the game -labels: ["bug"] +labels: ["type: minor bug", "status: pending triage"] title: "Bug Report: " body: - type: checkboxes @@ -36,7 +36,7 @@ body: attributes: label: Version description: What version were you using? - placeholder: ex. 0.4.0 + placeholder: ex. 0.4.1 validations: required: true diff --git a/.github/ISSUE_TEMPLATE/crash.yml b/.github/ISSUE_TEMPLATE/crash.yml new file mode 100644 index 000000000..7c160244d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/crash.yml @@ -0,0 +1,69 @@ +name: Crash Report +description: Report a crash that occurred while playing. +labels: ["type: major bug", "status: pending triage"] +title: "Crash: " +body: + - type: checkboxes + attributes: + label: Issue Checklist + options: + - label: I have properly named the issue + - label: I looked in issues/discussions, if it has been previously reported + + - type: dropdown + attributes: + label: What platform are you using? + options: + - Itch.io - Windows + - Itch.io - MacOS + - Itch.io - Linux + - Newgrounds (Web) + validations: + required: true + + - type: dropdown + attributes: + label: If you were playing on a browser, which one were you using? + options: + - Google Chrome + - Microsoft Edge + - Firefox + - Opera + - Safari + - Other (Specify below) + + - type: input + attributes: + label: Version + description: What version were you using? + placeholder: ex. 0.4.1 + validations: + required: true + + - type: markdown + attributes: + value: "## Describe the issue." + + - type: markdown + attributes: + value: "### Please do not report issues from other engines. These must be reported in their repositories." + + - type: markdown + attributes: + value: "#### Provide as many details as you can." + + - type: textarea + attributes: + label: Context (Provide images, videos, etc. of the crash happening) + + - type: textarea + attributes: + label: Steps to reproduce + validations: + required: true + + - type: textarea + attributes: + label: Crash Logs (can be found in the crash folder) + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/enhancement.yml b/.github/ISSUE_TEMPLATE/enhancement.yml index 29c7e5669..327a91fec 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.yml +++ b/.github/ISSUE_TEMPLATE/enhancement.yml @@ -1,6 +1,6 @@ name: Enhancement description: Suggest a new feature -labels: ["enhancement"] +labels: ["type: enhancement", "status: pending triage"] title: "Enhancement: " body: - type: checkboxes diff --git a/.github/PULL_REQUEST_TEMPLATE/bug.yml b/.github/PULL_REQUEST_TEMPLATE/bug.yml index c8aa2fcb3..ca17d0168 100644 --- a/.github/PULL_REQUEST_TEMPLATE/bug.yml +++ b/.github/PULL_REQUEST_TEMPLATE/bug.yml @@ -1,6 +1,6 @@ name: Bug Fix description: Fix a bug or critical performance issue -labels: ["bug"] +labels: ["type: minor bug", "status: pending triage"] title: "Bug Fix: " body: - type: checkboxes @@ -8,7 +8,7 @@ body: label: Issue Checklist options: - label: I have checked if this PR isn't a duplicate - + - type: textarea attributes: label: Does this PR fix any issues? Please link them below if so. diff --git a/.github/PULL_REQUEST_TEMPLATE/enhancement.yml b/.github/PULL_REQUEST_TEMPLATE/enhancement.yml index 57186b980..c39bd3e4a 100644 --- a/.github/PULL_REQUEST_TEMPLATE/enhancement.yml +++ b/.github/PULL_REQUEST_TEMPLATE/enhancement.yml @@ -1,6 +1,6 @@ name: Enhancement description: Add a new feature -labels: ["enhancement"] +labels: ["type: enhancement", "status: pending triage"] title: "Enhancement: " body: - type: checkboxes @@ -8,7 +8,7 @@ body: label: Issue Checklist options: - label: I have checked if this PR isn't a duplicate - + - type: textarea attributes: label: Does this PR fix any issues? Please link them below if so. From 250ec840efa17b323f69748271982659ad61cc06 Mon Sep 17 00:00:00 2001 From: MaybeMaru <97055307+MaybeMaru@users.noreply.github.com> Date: Tue, 18 Jun 2024 15:11:00 +0200 Subject: [PATCH 305/870] Add missing constants --- source/funkin/play/notes/Strumline.hx | 2 +- source/funkin/play/notes/SustainTrail.hx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/play/notes/Strumline.hx b/source/funkin/play/notes/Strumline.hx index 0e4b6645f..3c114b5e0 100644 --- a/source/funkin/play/notes/Strumline.hx +++ b/source/funkin/play/notes/Strumline.hx @@ -37,7 +37,7 @@ class Strumline extends FlxSpriteGroup static function get_RENDER_DISTANCE_MS():Float { - return FlxG.height / 0.45; + return FlxG.height / Constants.PIXELS_PER_MS; } /** diff --git a/source/funkin/play/notes/SustainTrail.hx b/source/funkin/play/notes/SustainTrail.hx index b358d7f03..f6d43b33f 100644 --- a/source/funkin/play/notes/SustainTrail.hx +++ b/source/funkin/play/notes/SustainTrail.hx @@ -160,7 +160,7 @@ class SustainTrail extends FlxSprite */ public static inline function sustainHeight(susLength:Float, scroll:Float) { - return (susLength * 0.45 * scroll); + return (susLength * Constants.PIXELS_PER_MS * scroll); } function set_sustainLength(s:Float):Float From 24bdf2db644b9f225764b825ba01b6287e618199 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sun, 16 Jun 2024 18:34:10 -0400 Subject: [PATCH 306/870] Fix a bug where songs with no notes would crash the results screen. --- source/funkin/play/ResultState.hx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index 48fb3b04e..a2c5f7e62 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -464,7 +464,9 @@ class ResultState extends MusicBeatSubState { 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; + // NOTE: Only divide if totalNotes > 0 to prevent divide-by-zero errors. + var clearPercentFloat = params.scoreData.tallies.totalNotes == 0 ? 0.0 : (params.scoreData.tallies.sick + + params.scoreData.tallies.good) / params.scoreData.tallies.totalNotes * 100; clearPercentTarget = Math.floor(clearPercentFloat); // Prevent off-by-one errors. From 42192dfe97712f24a43c9ec45694049a6c5f4c70 Mon Sep 17 00:00:00 2001 From: Karim Akra <144803230+KarimAkra@users.noreply.github.com> Date: Sun, 9 Jun 2024 12:47:17 +0300 Subject: [PATCH 307/870] remove the library strip --- source/funkin/audio/FunkinSound.hx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index c70f195d2..11b713f4d 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -491,8 +491,10 @@ class FunkinSound extends FlxSound implements ICloneable 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 + // we are bypassing the openfl/lime asset library fuss on web only + #if web path = Paths.stripLibrary(path); + #end var soundRequest = FlxPartialSound.partialLoadFromFile(path, start, end); From e2be19039c2a11bcf2050dd823b61b043c950fc5 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 17 Jun 2024 12:22:49 -0400 Subject: [PATCH 308/870] Get rid of a warning about missing BPM info --- 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 0caaf4591..68c63efc4 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1888,6 +1888,7 @@ class FreeplayState extends MusicBeatSubState startingVolume: 0.0, overrideExisting: true, restartTrack: false, + mapTimeChanges: false, // The music metadata is not alongside the audio file so this won't work. pathsFunction: INST, suffix: potentiallyErect, partialParams: From 0ed103b2f0c18061c45b50eebac8e30450ee2773 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sat, 15 Jun 2024 06:33:30 -0400 Subject: [PATCH 309/870] submoduel --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 2e1594ee4..15a816fb8 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 2e1594ee4c04c7148628bae471bdd061c9deb6b7 +Subproject commit 15a816fb833555c22be92bd408eaf147ed4c64be From cf44774b218c3b323b975c4dd075be8e04c96826 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sat, 15 Jun 2024 06:53:41 -0400 Subject: [PATCH 310/870] submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 15a816fb8..01a285b38 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 15a816fb833555c22be92bd408eaf147ed4c64be +Subproject commit 01a285b38ecf10218153a1d40a2e4ea5b2132d7b From 78bbf5a7aab2ea50df4a817039062922fec562fd Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sat, 15 Jun 2024 06:55:08 -0400 Subject: [PATCH 311/870] submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 01a285b38..4b9507525 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 01a285b38ecf10218153a1d40a2e4ea5b2132d7b +Subproject commit 4b95075255baeaba3585fabff7052c257856fafe From 60e741434c6ecd1f15c4e62f4ea364b8648c3538 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 18 Jun 2024 17:56:24 -0400 Subject: [PATCH 312/870] Implemented playable character registry, added Freeplay character filtering, added alt instrumental support --- assets | 2 +- source/funkin/InitState.hx | 2 + .../funkin/data/freeplay/player/CHANGELOG.md | 9 ++ .../funkin/data/freeplay/player/PlayerData.hx | 63 ++++++++ .../data/freeplay/player/PlayerRegistry.hx | 151 ++++++++++++++++++ source/funkin/modding/PolymodHandler.hx | 6 +- source/funkin/play/song/Song.hx | 34 ++-- .../handlers/ChartEditorDialogHandler.hx | 7 +- source/funkin/ui/freeplay/FreeplayState.hx | 80 +++++++--- .../freeplay/charselect/PlayableCharacter.hx | 108 +++++++++++++ .../charselect/ScriptedPlayableCharacter.hx | 8 + source/funkin/util/VersionUtil.hx | 1 - 12 files changed, 433 insertions(+), 38 deletions(-) create mode 100644 source/funkin/data/freeplay/player/CHANGELOG.md create mode 100644 source/funkin/data/freeplay/player/PlayerData.hx create mode 100644 source/funkin/data/freeplay/player/PlayerRegistry.hx create mode 100644 source/funkin/ui/freeplay/charselect/PlayableCharacter.hx create mode 100644 source/funkin/ui/freeplay/charselect/ScriptedPlayableCharacter.hx diff --git a/assets b/assets index 2e1594ee4..fece99b3b 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 2e1594ee4c04c7148628bae471bdd061c9deb6b7 +Subproject commit fece99b3b121045fb2f6f02dba485201b32f1c87 diff --git a/source/funkin/InitState.hx b/source/funkin/InitState.hx index 49b15ddf6..c2a56bdc2 100644 --- a/source/funkin/InitState.hx +++ b/source/funkin/InitState.hx @@ -1,5 +1,6 @@ package funkin; +import funkin.data.freeplay.player.PlayerRegistry; import funkin.ui.debug.charting.ChartEditorState; import funkin.ui.transition.LoadingState; import flixel.FlxState; @@ -164,6 +165,7 @@ class InitState extends FlxState SongRegistry.instance.loadEntries(); LevelRegistry.instance.loadEntries(); NoteStyleRegistry.instance.loadEntries(); + PlayerRegistry.instance.loadEntries(); ConversationRegistry.instance.loadEntries(); DialogueBoxRegistry.instance.loadEntries(); SpeakerRegistry.instance.loadEntries(); diff --git a/source/funkin/data/freeplay/player/CHANGELOG.md b/source/funkin/data/freeplay/player/CHANGELOG.md new file mode 100644 index 000000000..7a31e11ca --- /dev/null +++ b/source/funkin/data/freeplay/player/CHANGELOG.md @@ -0,0 +1,9 @@ +# Freeplay Playable Character Data Schema Changelog + +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). + +## [1.0.0] +Initial release. diff --git a/source/funkin/data/freeplay/player/PlayerData.hx b/source/funkin/data/freeplay/player/PlayerData.hx new file mode 100644 index 000000000..d7b814584 --- /dev/null +++ b/source/funkin/data/freeplay/player/PlayerData.hx @@ -0,0 +1,63 @@ +package funkin.data.freeplay.player; + +import funkin.data.animation.AnimationData; + +@:nullSafety +class PlayerData +{ + /** + * The sematic version number of the player data JSON format. + * Supports fancy comparisons like NPM does it's neat. + */ + @:default(funkin.data.freeplay.player.PlayerRegistry.PLAYER_DATA_VERSION) + public var version:String; + + /** + * A readable name for this playable character. + */ + public var name:String = 'Unknown'; + + /** + * The character IDs this character is associated with. + * Only songs that use these characters will show up in Freeplay. + */ + @:default([]) + public var ownedChars:Array = []; + + /** + * Whether to show songs with character IDs that aren't associated with any specific character. + */ + @:optional + @:default(false) + public var showUnownedChars:Bool = false; + + /** + * Whether this character is unlocked by default. + * Use a ScriptedPlayableCharacter to add custom logic. + */ + @:optional + @:default(true) + public var unlocked:Bool = true; + + public function new() + { + this.version = PlayerRegistry.PLAYER_DATA_VERSION; + } + + /** + * Convert this StageData into a JSON string. + */ + 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 = PlayerRegistry.PLAYER_DATA_VERSION; + } +} diff --git a/source/funkin/data/freeplay/player/PlayerRegistry.hx b/source/funkin/data/freeplay/player/PlayerRegistry.hx new file mode 100644 index 000000000..3de9efd41 --- /dev/null +++ b/source/funkin/data/freeplay/player/PlayerRegistry.hx @@ -0,0 +1,151 @@ +package funkin.data.freeplay.player; + +import funkin.data.freeplay.player.PlayerData; +import funkin.ui.freeplay.charselect.PlayableCharacter; +import funkin.ui.freeplay.charselect.ScriptedPlayableCharacter; + +class PlayerRegistry extends BaseRegistry +{ + /** + * The current version string for the stage data format. + * Handle breaking changes by incrementing this value + * and adding migration to the `migratePlayerData()` function. + */ + public static final PLAYER_DATA_VERSION:thx.semver.Version = "1.0.0"; + + public static final PLAYER_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x"; + + public static var instance(get, never):PlayerRegistry; + static var _instance:Null = null; + + static function get_instance():PlayerRegistry + { + if (_instance == null) _instance = new PlayerRegistry(); + return _instance; + } + + /** + * A mapping between stage character IDs and Freeplay playable character IDs. + */ + var ownedCharacterIds:Map = []; + + public function new() + { + super('PLAYER', 'players', PLAYER_DATA_VERSION_RULE); + } + + public override function loadEntries():Void + { + super.loadEntries(); + + for (playerId in listEntryIds()) + { + var player = fetchEntry(playerId); + if (player == null) continue; + + var currentPlayerCharIds = player.getOwnedCharacterIds(); + for (characterId in currentPlayerCharIds) + { + ownedCharacterIds.set(characterId, playerId); + } + } + + log('Loaded ${countEntries()} playable characters with ${ownedCharacterIds.size()} associations.'); + } + + /** + * Get the playable character associated with a given stage character. + * @param characterId The stage character ID. + * @return The playable character. + */ + public function getCharacterOwnerId(characterId:String):String + { + return ownedCharacterIds[characterId]; + } + + /** + * Return true if the given stage character is associated with a specific playable character. + * If so, the level should only appear if that character is selected in Freeplay. + * @param characterId The stage character ID. + * @return Whether the character is owned by any one character. + */ + public function isCharacterOwned(characterId:String):Bool + { + return ownedCharacterIds.exists(characterId); + } + + /** + * Read, parse, and validate the JSON data and produce the corresponding data object. + */ + public function parseEntryData(id:String):Null + { + // JsonParser does not take type parameters, + // otherwise this function would be in BaseRegistry. + var parser = new json2object.JsonParser(); + parser.ignoreUnknownVariables = false; + + switch (loadEntryFile(id)) + { + case {fileName: fileName, contents: contents}: + parser.fromJson(contents, fileName); + default: + return null; + } + + if (parser.errors.length > 0) + { + printErrors(parser.errors, id); + return null; + } + return parser.value; + } + + /** + * Parse and validate the JSON data and produce the corresponding data object. + * + * NOTE: Must be implemented on the implementation class. + * @param contents The JSON as a string. + * @param fileName An optional file name for error reporting. + */ + public function parseEntryDataRaw(contents:String, ?fileName:String):Null + { + var parser = new json2object.JsonParser(); + parser.ignoreUnknownVariables = false; + parser.fromJson(contents, fileName); + + if (parser.errors.length > 0) + { + printErrors(parser.errors, fileName); + return null; + } + return parser.value; + } + + function createScriptedEntry(clsName:String):PlayableCharacter + { + return ScriptedPlayableCharacter.init(clsName, "unknown"); + } + + function getScriptedClassNames():Array + { + return ScriptedPlayableCharacter.listScriptClasses(); + } + + /** + * A list of all the playable characters from the base game, in order. + */ + public function listBaseGamePlayerIds():Array + { + return ["bf", "pico"]; + } + + /** + * A list of all installed playable characters that are not from the base game. + */ + public function listModdedPlayerIds():Array + { + return listEntryIds().filter(function(id:String):Bool { + return listBaseGamePlayerIds().indexOf(id) == -1; + }); + } +} diff --git a/source/funkin/modding/PolymodHandler.hx b/source/funkin/modding/PolymodHandler.hx index ae754b780..c352aa606 100644 --- a/source/funkin/modding/PolymodHandler.hx +++ b/source/funkin/modding/PolymodHandler.hx @@ -8,6 +8,7 @@ import funkin.data.event.SongEventRegistry; import funkin.data.story.level.LevelRegistry; import funkin.data.notestyle.NoteStyleRegistry; import funkin.data.song.SongRegistry; +import funkin.data.freeplay.player.PlayerRegistry; import funkin.data.stage.StageRegistry; import funkin.data.freeplay.album.AlbumRegistry; import funkin.modding.module.ModuleHandler; @@ -369,15 +370,18 @@ class PolymodHandler // These MUST be imported at the top of the file and not referred to by fully qualified name, // to ensure build macros work properly. + SongEventRegistry.loadEventCache(); + SongRegistry.instance.loadEntries(); LevelRegistry.instance.loadEntries(); NoteStyleRegistry.instance.loadEntries(); - SongEventRegistry.loadEventCache(); + PlayerRegistry.instance.loadEntries(); ConversationRegistry.instance.loadEntries(); DialogueBoxRegistry.instance.loadEntries(); SpeakerRegistry.instance.loadEntries(); AlbumRegistry.instance.loadEntries(); StageRegistry.instance.loadEntries(); + CharacterDataParser.loadCharacterCache(); // TODO: Migrate characters to BaseRegistry. ModuleHandler.loadModuleCache(); } diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx index dde5ee7b8..91d35d8fa 100644 --- a/source/funkin/play/song/Song.hx +++ b/source/funkin/play/song/Song.hx @@ -14,6 +14,7 @@ import funkin.data.song.SongData.SongTimeFormat; import funkin.data.song.SongRegistry; import funkin.modding.IScriptedClass.IPlayStateScriptedClass; import funkin.modding.events.ScriptEvent; +import funkin.ui.freeplay.charselect.PlayableCharacter; import funkin.util.SortUtil; import openfl.utils.Assets; @@ -401,11 +402,11 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry):Null + public function getFirstValidVariation(?diffId:String, ?currentCharacter:PlayableCharacter, ?possibleVariations:Array):Null { if (possibleVariations == null) { - possibleVariations = variations; + possibleVariations = getVariationsByCharacter(currentCharacter); possibleVariations.sort(SortUtil.defaultsThenAlphabetically.bind(Constants.DEFAULT_VARIATION_LIST)); } if (diffId == null) diffId = listDifficulties(null, possibleVariations)[0]; @@ -422,22 +423,29 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry + public function getVariationsByCharacter(?char:PlayableCharacter):Array { - if (charId == null) charId = Constants.DEFAULT_CHARACTER; + if (char == null) return variations; - if (variations.contains(charId)) + var result = []; + trace('Evaluating variations for ${this.id} ${char.id}: ${this.variations}'); + for (variation in variations) { - return [charId]; - } - else - { - // TODO: How to exclude character variations while keeping other custom variations? - return variations; + var metadata = _metadata.get(variation); + + var playerCharId = metadata?.playData?.characters?.player; + if (playerCharId == null) continue; + + if (char.shouldShowCharacter(playerCharId)) + { + result.push(variation); + } } + + return result; } /** @@ -455,6 +463,8 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry = song.listDifficulties(displayedVariations, false); - trace(availableDifficultiesForSong); + trace('Available Difficulties: $availableDifficultiesForSong'); if (availableDifficultiesForSong.length == 0) continue; songs.push(new FreeplaySongData(levelId, songId, song, displayedVariations)); @@ -454,7 +458,7 @@ class FreeplayState extends MusicBeatSubState }); // TODO: Replace this. - if (currentCharacter == 'pico') dj.visible = false; + if (currentCharacterId == 'pico') dj.visible = false; add(dj); @@ -1195,6 +1199,16 @@ class FreeplayState extends MusicBeatSubState rankAnimStart(fromResultsParams); } + if (FlxG.keys.justPressed.P) + { + FlxG.switchState(FreeplayState.build( + { + { + character: currentCharacterId == "pico" ? "bf" : "pico", + } + })); + } + // if (FlxG.keys.justPressed.H) // { // rankDisplayNew(fromResultsParams); @@ -1302,9 +1316,9 @@ class FreeplayState extends MusicBeatSubState { if (busy) return; - var upP:Bool = controls.UI_UP_P && !FlxG.keys.pressed.CONTROL; - var downP:Bool = controls.UI_DOWN_P && !FlxG.keys.pressed.CONTROL; - var accepted:Bool = controls.ACCEPT && !FlxG.keys.pressed.CONTROL; + var upP:Bool = controls.UI_UP_P; + var downP:Bool = controls.UI_DOWN_P; + var accepted:Bool = controls.ACCEPT; if (FlxG.onMobile) { @@ -1378,7 +1392,7 @@ class FreeplayState extends MusicBeatSubState } #end - if (!FlxG.keys.pressed.CONTROL && (controls.UI_UP || controls.UI_DOWN)) + if ((controls.UI_UP || controls.UI_DOWN)) { if (spamming) { @@ -1440,13 +1454,13 @@ class FreeplayState extends MusicBeatSubState } #end - if (controls.UI_LEFT_P && !FlxG.keys.pressed.CONTROL) + if (controls.UI_LEFT_P) { dj.resetAFKTimer(); changeDiff(-1); generateSongList(currentFilter, true); } - if (controls.UI_RIGHT_P && !FlxG.keys.pressed.CONTROL) + if (controls.UI_RIGHT_P) { dj.resetAFKTimer(); changeDiff(1); @@ -1720,7 +1734,7 @@ class FreeplayState extends MusicBeatSubState return; } var targetDifficultyId:String = currentDifficulty; - var targetVariation:String = targetSong.getFirstValidVariation(targetDifficultyId); + var targetVariation:String = targetSong.getFirstValidVariation(targetDifficultyId, currentCharacter); PlayStatePlaylist.campaignId = cap.songData.levelId; var targetDifficulty:SongDifficulty = targetSong.getDifficulty(targetDifficultyId, targetVariation); @@ -1730,8 +1744,18 @@ class FreeplayState extends MusicBeatSubState return; } - // TODO: Change this with alternate instrumentals - var targetInstId:String = targetDifficulty.characters.instrumental; + var baseInstrumentalId:String = targetDifficulty?.characters?.instrumental ?? ''; + var altInstrumentalIds:Array = targetDifficulty?.characters?.altInstrumentals ?? []; + + var targetInstId:String = baseInstrumentalId; + + // TODO: Make this a UI element. + #if (debug || FORCE_DEBUG_VERSION) + if (altInstrumentalIds.length > 0 && FlxG.keys.pressed.CONTROL) + { + targetInstId = altInstrumentalIds[0]; + } + #end // Visual and audio effects. FunkinSound.playOnce(Paths.sound('confirmMenu')); @@ -1883,9 +1907,23 @@ class FreeplayState extends MusicBeatSubState else { var previewSong:Null = SongRegistry.instance.fetchEntry(daSongCapsule.songData.songId); - var instSuffix:String = previewSong?.getDifficulty(currentDifficulty, - previewSong?.getVariationsByCharId(currentCharacter) ?? Constants.DEFAULT_VARIATION_LIST)?.characters?.instrumental ?? ''; + var songDifficulty = previewSong?.getDifficulty(currentDifficulty, + previewSong?.getVariationsByCharacter(currentCharacter) ?? Constants.DEFAULT_VARIATION_LIST); + var baseInstrumentalId:String = songDifficulty?.characters?.instrumental ?? ''; + var altInstrumentalIds:Array = songDifficulty?.characters?.altInstrumentals ?? []; + + var instSuffix:String = baseInstrumentalId; + + // TODO: Make this a UI element. + #if (debug || FORCE_DEBUG_VERSION) + if (altInstrumentalIds.length > 0 && FlxG.keys.pressed.CONTROL) + { + instSuffix = altInstrumentalIds[0]; + } + #end + instSuffix = (instSuffix != '') ? '-$instSuffix' : ''; + FunkinSound.playMusic(daSongCapsule.songData.songId, { startingVolume: 0.0, @@ -1913,7 +1951,7 @@ class FreeplayState extends MusicBeatSubState public static function build(?params:FreeplayStateParams, ?stickers:StickerSubState):MusicBeatState { var result:MainMenuState; - if (params?.fromResults.playRankAnim) result = new MainMenuState(true); + if (params?.fromResults?.playRankAnim) result = new MainMenuState(true); else result = new MainMenuState(false); @@ -1951,8 +1989,8 @@ class DifficultySelector extends FlxSprite override function update(elapsed:Float):Void { - if (flipX && controls.UI_RIGHT_P && !FlxG.keys.pressed.CONTROL) moveShitDown(); - if (!flipX && controls.UI_LEFT_P && !FlxG.keys.pressed.CONTROL) moveShitDown(); + if (flipX && controls.UI_RIGHT_P) moveShitDown(); + if (!flipX && controls.UI_LEFT_P) moveShitDown(); super.update(elapsed); } diff --git a/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx b/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx new file mode 100644 index 000000000..743345004 --- /dev/null +++ b/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx @@ -0,0 +1,108 @@ +package funkin.ui.freeplay.charselect; + +import funkin.data.IRegistryEntry; +import funkin.data.freeplay.player.PlayerData; +import funkin.data.freeplay.player.PlayerRegistry; + +/** + * An object used to retrieve data about a playable character (also known as "weeks"). + * Can be scripted to override each function, for custom behavior. + */ +class PlayableCharacter implements IRegistryEntry +{ + /** + * The ID of the playable character. + */ + public final id:String; + + /** + * Playable character data as parsed from the JSON file. + */ + public final _data:PlayerData; + + /** + * @param id The ID of the JSON file to parse. + */ + public function new(id:String) + { + this.id = id; + _data = _fetchData(id); + + if (_data == null) + { + throw 'Could not parse playable character data for id: $id'; + } + } + + /** + * Retrieve the readable name of the playable character. + */ + public function getName():String + { + // TODO: Maybe add localization support? + return _data.name; + } + + /** + * Retrieve the list of stage character IDs associated with this playable character. + * @return The list of associated character IDs + */ + public function getOwnedCharacterIds():Array + { + return _data.ownedChars; + } + + /** + * Return `true` if, when this character is selected in Freeplay, + * songs unassociated with a specific character should appear. + */ + public function shouldShowUnownedChars():Bool + { + return _data.showUnownedChars; + } + + public function shouldShowCharacter(id:String):Bool + { + if (_data.ownedChars.contains(id)) + { + return true; + } + + if (_data.showUnownedChars) + { + var result = !PlayerRegistry.instance.isCharacterOwned(id); + return result; + } + + return false; + } + + /** + * Returns whether this character is unlocked. + */ + public function isUnlocked():Bool + { + return _data.unlocked; + } + + /** + * Called when the character is destroyed. + * TODO: Document when this gets called + */ + public function destroy():Void {} + + public function toString():String + { + return 'PlayableCharacter($id)'; + } + + /** + * Retrieve and parse the JSON data for a playable character by ID. + * @param id The ID of the character + * @return The parsed player data, or null if not found or invalid + */ + static function _fetchData(id:String):Null + { + return PlayerRegistry.instance.parseEntryDataWithMigration(id, PlayerRegistry.instance.fetchEntryVersion(id)); + } +} diff --git a/source/funkin/ui/freeplay/charselect/ScriptedPlayableCharacter.hx b/source/funkin/ui/freeplay/charselect/ScriptedPlayableCharacter.hx new file mode 100644 index 000000000..f75a58092 --- /dev/null +++ b/source/funkin/ui/freeplay/charselect/ScriptedPlayableCharacter.hx @@ -0,0 +1,8 @@ +package funkin.ui.freeplay.charselect; + +/** + * A script that can be tied to a PlayableCharacter. + * Create a scripted class that extends PlayableCharacter to use this. + */ +@:hscriptClass +class ScriptedPlayableCharacter extends funkin.ui.freeplay.charselect.PlayableCharacter implements polymod.hscript.HScriptedClass {} diff --git a/source/funkin/util/VersionUtil.hx b/source/funkin/util/VersionUtil.hx index 832ce008a..9bf46a188 100644 --- a/source/funkin/util/VersionUtil.hx +++ b/source/funkin/util/VersionUtil.hx @@ -24,7 +24,6 @@ class VersionUtil try { var versionRaw:thx.semver.Version.SemVer = version; - trace('${versionRaw} satisfies (${versionRule})? ${version.satisfies(versionRule)}'); return version.satisfies(versionRule); } catch (e) From 263039f52ce5096abc5929c9af3b95ef9440e229 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 18 Jun 2024 20:07:27 -0400 Subject: [PATCH 313/870] Make Boyfriend DJ animations data driven --- assets | 2 +- .../funkin/data/freeplay/player/PlayerData.hx | 93 +++++ source/funkin/ui/freeplay/DJBoyfriend.hx | 371 ------------------ source/funkin/ui/freeplay/FreeplayDJ.hx | 369 +++++++++++++++++ source/funkin/ui/freeplay/FreeplayState.hx | 24 +- .../freeplay/charselect/PlayableCharacter.hx | 5 + source/funkin/util/tools/MapTools.hx | 4 + 7 files changed, 484 insertions(+), 384 deletions(-) delete mode 100644 source/funkin/ui/freeplay/DJBoyfriend.hx create mode 100644 source/funkin/ui/freeplay/FreeplayDJ.hx diff --git a/assets b/assets index fece99b3b..6ec72f8ae 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit fece99b3b121045fb2f6f02dba485201b32f1c87 +Subproject commit 6ec72f8aeb5ab77997dee4e2e98ae03f0ec347b8 diff --git a/source/funkin/data/freeplay/player/PlayerData.hx b/source/funkin/data/freeplay/player/PlayerData.hx index d7b814584..10fc54b78 100644 --- a/source/funkin/data/freeplay/player/PlayerData.hx +++ b/source/funkin/data/freeplay/player/PlayerData.hx @@ -31,6 +31,12 @@ class PlayerData @:default(false) public var showUnownedChars:Bool = false; + /** + * Data for displaying this character in the Freeplay menu. + * If null, display no DJ. + */ + public var freeplayDJ:Null = null; + /** * Whether this character is unlocked by default. * Use a ScriptedPlayableCharacter to add custom logic. @@ -61,3 +67,90 @@ class PlayerData this.version = PlayerRegistry.PLAYER_DATA_VERSION; } } + +class PlayerFreeplayDJData +{ + var assetPath:String; + var animations:Array; + + @:jignored + var animationMap:Map; + + @:optional + var cartoon:Null; + + public function new() + { + animationMap = new Map(); + } + + function mapAnimations() + { + if (animationMap == null) animationMap = new Map(); + + animationMap.clear(); + for (anim in animations) + { + animationMap.set(anim.name, anim); + } + } + + public function getAtlasPath():String + { + return Paths.animateAtlas(assetPath); + } + + public function getAnimationPrefix(name:String):Null + { + if (animationMap.size() == 0) mapAnimations(); + + var anim = animationMap.get(name); + if (anim == null) return null; + return anim.prefix; + } + + public function getAnimationOffsets(name:String):Null> + { + if (animationMap.size() == 0) mapAnimations(); + + var anim = animationMap.get(name); + if (anim == null) return null; + return anim.offsets; + } + + // TODO: These should really be frame labels, ehe. + + public function getCartoonSoundClickFrame():Int + { + return cartoon?.soundClickFrame ?? 80; + } + + public function getCartoonSoundCartoonFrame():Int + { + return cartoon?.soundCartoonFrame ?? 85; + } + + public function getCartoonLoopBlinkFrame():Int + { + return cartoon?.loopBlinkFrame ?? 112; + } + + public function getCartoonLoopFrame():Int + { + return cartoon?.loopFrame ?? 166; + } + + public function getCartoonChannelChangeFrame():Int + { + return cartoon?.channelChangeFrame ?? 60; + } +} + +typedef PlayerFreeplayDJCartoonData = +{ + var soundClickFrame:Int; + var soundCartoonFrame:Int; + var loopBlinkFrame:Int; + var loopFrame:Int; + var channelChangeFrame:Int; +} diff --git a/source/funkin/ui/freeplay/DJBoyfriend.hx b/source/funkin/ui/freeplay/DJBoyfriend.hx deleted file mode 100644 index bbf043dd4..000000000 --- a/source/funkin/ui/freeplay/DJBoyfriend.hx +++ /dev/null @@ -1,371 +0,0 @@ -package funkin.ui.freeplay; - -import flixel.FlxSprite; -import flixel.util.FlxSignal; -import funkin.util.assets.FlxAnimationUtil; -import funkin.graphics.adobeanimate.FlxAtlasSprite; -import funkin.audio.FunkinSound; -import flixel.util.FlxTimer; -import funkin.audio.FunkinSound; -import funkin.audio.FlxStreamSound; - -class DJBoyfriend extends FlxAtlasSprite -{ - // Represents the sprite's current status. - // Without state machines I would have driven myself crazy years ago. - public var currentState:DJBoyfriendState = Intro; - - // A callback activated when the intro animation finishes. - public var onIntroDone:FlxSignal = new FlxSignal(); - - // A callback activated when Boyfriend gets spooked. - public var onSpook:FlxSignal = new FlxSignal(); - - // playAnim stolen from Character.hx, cuz im lazy lol! - // TODO: Switch this class to use SwagSprite instead. - public var animOffsets:Map>; - - var gotSpooked:Bool = false; - - static final SPOOK_PERIOD:Float = 60.0; - static final TV_PERIOD:Float = 120.0; - - // Time since dad last SPOOKED you. - var timeSinceSpook:Float = 0; - - public function new(x:Float, y:Float) - { - super(x, y, Paths.animateAtlas("freeplay/freeplay-boyfriend", "preload")); - - animOffsets = new Map>(); - - anim.callback = function(name, number) { - switch (name) - { - case "Boyfriend DJ watchin tv OG": - if (number == 80) - { - FunkinSound.playOnce(Paths.sound('remote_click')); - } - if (number == 85) - { - runTvLogic(); - } - default: - } - }; - - setupAnimations(); - - FlxG.debugger.track(this); - FlxG.console.registerObject("dj", this); - - anim.onComplete = onFinishAnim; - - FlxG.console.registerFunction("tv", function() { - currentState = TV; - }); - } - - /* - [remote hand under,boyfriend top head,brim piece,arm cringe l,red lazer,dj arm in,bf fist pump arm,hand raised right,forearm left,fist shaking,bf smile eyes closed face,arm cringe r,bf clenched face,face shrug,boyfriend falling,blue tint 1,shirt sleeve,bf clenched fist,head BF relaxed,blue tint 2,hand down left,blue tint 3,blue tint 4,head less smooshed,blue tint 5,boyfriend freeplay,BF head slight turn,blue tint 6,arm shrug l,blue tint 7,shoulder raised w sleeve,blue tint 8,fist pump face,blue tint 9,foot rested light,hand turnaround,arm chill right,Boyfriend DJ,arm shrug r,head back bf,hat top piece,dad bod,face surprise snap,Boyfriend DJ fist pump,office chair,foot rested right,chest down,office chair upright,body chill,bf dj afk,head mouth open dad,BF Head defalt HAIR BLOWING,hand shrug l,face piece,foot wag,turn table,shoulder up left,turntable lights,boyfriend dj body shirt blowing,body chunk turned,hand down right,dj arm out,hand shrug r,body chest out,rave hand,palm,chill face default,head back semi bf,boyfriend bottom head,DJ arm,shoulder right dad,bf surprise,boyfriend dj body,hs1,Boyfriend DJ watchin tv OG,spinning disk,hs2,arm chill left,boyfriend dj intro,hs3,hs4,chill face extra,hs5,remote hand upright,hs6,pant over table,face surprise,bf arm peace,arm turnaround,bf eyes 1,arm slammed table,eye squit,leg BF,head mid piece,arm backing,arm swoopin in,shoe right lowering,forearm right,hand out,blue tint 10,body falling back,remote thumb press,shoulder,hair spike single,bf bent - arm,crt,foot raised right,dad hand,chill face 1,chill face 2,clenched fist,head SMOOSHED,shoulder left dad,df1,body chunk upright,df2,df3,df4,hat front piece,df5,foot rested right 2,hand in,arm spun,shoe raised left,bf 1 finger hand,bf mouth 1,Boyfriend DJ confirm,forearm down ,hand raised left,remote thumb up] - */ - override public function listAnimations():Array - { - var anims:Array = []; - @:privateAccess - for (animKey in anim.symbolDictionary) - { - anims.push(animKey.name); - } - return anims; - } - - var lowPumpLoopPoint:Int = 4; - - public override function update(elapsed:Float):Void - { - super.update(elapsed); - - switch (currentState) - { - case Intro: - // Play the intro animation then leave this state immediately. - if (getCurrentAnimation() != 'boyfriend dj intro') playFlashAnimation('boyfriend dj intro', true); - timeSinceSpook = 0; - case Idle: - // We are in this state the majority of the time. - if (getCurrentAnimation() != 'Boyfriend DJ') - { - playFlashAnimation('Boyfriend DJ', true); - } - - if (getCurrentAnimation() == 'Boyfriend DJ' && this.isLoopFinished()) - { - if (timeSinceSpook >= SPOOK_PERIOD && !gotSpooked) - { - currentState = Spook; - } - else if (timeSinceSpook >= TV_PERIOD) - { - currentState = TV; - } - } - timeSinceSpook += elapsed; - 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') - { - onSpook.dispatch(); - playFlashAnimation('bf dj afk', false); - gotSpooked = true; - } - timeSinceSpook = 0; - case TV: - if (getCurrentAnimation() != 'Boyfriend DJ watchin tv OG') playFlashAnimation('Boyfriend DJ watchin tv OG', true); - timeSinceSpook = 0; - default: - // I shit myself. - } - - if (FlxG.keys.pressed.CONTROL) - { - if (FlxG.keys.justPressed.LEFT) - { - this.offsetX -= FlxG.keys.pressed.ALT ? 0.1 : (FlxG.keys.pressed.SHIFT ? 10.0 : 1.0); - } - - if (FlxG.keys.justPressed.RIGHT) - { - this.offsetX += FlxG.keys.pressed.ALT ? 0.1 : (FlxG.keys.pressed.SHIFT ? 10.0 : 1.0); - } - - if (FlxG.keys.justPressed.UP) - { - this.offsetY -= FlxG.keys.pressed.ALT ? 0.1 : (FlxG.keys.pressed.SHIFT ? 10.0 : 1.0); - } - - if (FlxG.keys.justPressed.DOWN) - { - this.offsetY += FlxG.keys.pressed.ALT ? 0.1 : (FlxG.keys.pressed.SHIFT ? 10.0 : 1.0); - } - - if (FlxG.keys.justPressed.SPACE) - { - currentState = (currentState == Idle ? TV : Idle); - } - } - } - - function onFinishAnim():Void - { - var name = anim.curSymbol.name; - switch (name) - { - case "boyfriend dj intro": - // trace('Finished intro'); - currentState = Idle; - onIntroDone.dispatch(); - case "Boyfriend DJ": - // trace('Finished idle'); - case "bf dj afk": - // trace('Finished spook'); - 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; - - // BF switches channels when the video ends, or at a 10% chance each time his idle loops. - if (FlxG.random.bool(5)) - { - frame = 60; - // boyfriend switches channel code? - // runTvLogic(); - } - trace('Replay idle: ${frame}'); - anim.play("Boyfriend DJ watchin tv OG", true, false, frame); - // trace('Finished confirm'); - } - } - - public function resetAFKTimer():Void - { - timeSinceSpook = 0; - gotSpooked = false; - } - - var offsetX:Float = 0.0; - var offsetY:Float = 0.0; - - function setupAnimations():Void - { - // Intro - addOffset('boyfriend dj intro', 8.0 - 1.3, 3.0 - 0.4); - - // Idle - addOffset('Boyfriend DJ', 0, 0); - - // Confirm - addOffset('Boyfriend DJ confirm', 0, 0); - - // AFK: Spook - addOffset('bf dj afk', 649.5, 58.5); - - // AFK: TV - addOffset('Boyfriend DJ watchin tv OG', 0, 0); - } - - var cartoonSnd:Null = null; - - public var playingCartoon:Bool = false; - - public function runTvLogic() - { - if (cartoonSnd == null) - { - // tv is OFF, but getting turned on - FunkinSound.playOnce(Paths.sound('tv_on'), 1.0, function() { - loadCartoon(); - }); - } - else - { - // plays it smidge after the click - FunkinSound.playOnce(Paths.sound('channel_switch'), 1.0, function() { - cartoonSnd.destroy(); - loadCartoon(); - }); - } - - // loadCartoon(); - } - - function loadCartoon() - { - cartoonSnd = FunkinSound.load(Paths.sound(getRandomFlashToon()), 1.0, false, true, true, function() { - anim.play("Boyfriend DJ watchin tv OG", true, false, 60); - }); - - // Fade out music to 40% volume over 1 second. - // This helps make the TV a bit more audible. - FlxG.sound.music.fadeOut(1.0, 0.1); - - // Play the cartoon at a random time between the start and 5 seconds from the end. - cartoonSnd.time = FlxG.random.float(0, Math.max(cartoonSnd.length - (5 * Constants.MS_PER_SEC), 0.0)); - } - - final cartoonList:Array = openfl.utils.Assets.list().filter(function(path) return path.startsWith("assets/sounds/cartoons/")); - - function getRandomFlashToon():String - { - var randomFile = FlxG.random.getObject(cartoonList); - - // Strip folder prefix - randomFile = randomFile.replace("assets/sounds/", ""); - // Strip file extension - randomFile = randomFile.substring(0, randomFile.length - 4); - - return randomFile; - } - - public function confirm():Void - { - 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]; - } - - override public function getCurrentAnimation():String - { - if (this.anim == null || this.anim.curSymbol == null) return ""; - return this.anim.curSymbol.name; - } - - public function playFlashAnimation(id:String, ?Force:Bool = false, ?Reverse:Bool = false, ?Frame:Int = 0):Void - { - anim.play(id, Force, Reverse, Frame); - applyAnimOffset(); - } - - function applyAnimOffset() - { - var AnimName = getCurrentAnimation(); - var daOffset = animOffsets.get(AnimName); - if (animOffsets.exists(AnimName)) - { - var xValue = daOffset[0]; - var yValue = daOffset[1]; - if (AnimName == "Boyfriend DJ watchin tv OG") - { - xValue += offsetX; - yValue += offsetY; - } - - offset.set(xValue, yValue); - } - else - { - offset.set(0, 0); - } - } - - public override function destroy():Void - { - super.destroy(); - - if (cartoonSnd != null) - { - cartoonSnd.destroy(); - cartoonSnd = null; - } - } -} - -enum DJBoyfriendState -{ - Intro; - Idle; - Confirm; - PumpIntro; - FistPump; - Spook; - TV; -} diff --git a/source/funkin/ui/freeplay/FreeplayDJ.hx b/source/funkin/ui/freeplay/FreeplayDJ.hx new file mode 100644 index 000000000..f9effe793 --- /dev/null +++ b/source/funkin/ui/freeplay/FreeplayDJ.hx @@ -0,0 +1,369 @@ +package funkin.ui.freeplay; + +import flixel.FlxSprite; +import flixel.util.FlxSignal; +import funkin.util.assets.FlxAnimationUtil; +import funkin.graphics.adobeanimate.FlxAtlasSprite; +import funkin.audio.FunkinSound; +import flixel.util.FlxTimer; +import funkin.data.freeplay.player.PlayerRegistry; +import funkin.data.freeplay.player.PlayerData.PlayerFreeplayDJData; +import funkin.audio.FunkinSound; +import funkin.audio.FlxStreamSound; + +class FreeplayDJ extends FlxAtlasSprite +{ + // Represents the sprite's current status. + // Without state machines I would have driven myself crazy years ago. + public var currentState:DJBoyfriendState = Intro; + + // A callback activated when the intro animation finishes. + public var onIntroDone:FlxSignal = new FlxSignal(); + + // A callback activated when the idle easter egg plays. + public var onIdleEasterEgg:FlxSignal = new FlxSignal(); + + var seenIdleEasterEgg:Bool = false; + + static final IDLE_EGG_PERIOD:Float = 60.0; + static final IDLE_CARTOON_PERIOD:Float = 120.0; + + // Time since last special idle animation you. + var timeIdling:Float = 0; + + final characterId:String = Constants.DEFAULT_CHARACTER; + final playableCharData:PlayerFreeplayDJData; + + public function new(x:Float, y:Float, characterId:String) + { + this.characterId = characterId; + + var playableChar = PlayerRegistry.instance.fetchEntry(characterId); + playableCharData = playableChar.getFreeplayDJData(); + + super(x, y, playableCharData.getAtlasPath()); + + anim.callback = function(name, number) { + if (name == playableCharData.getAnimationPrefix('cartoon')) + { + if (number == playableCharData.getCartoonSoundClickFrame()) + { + FunkinSound.playOnce(Paths.sound('remote_click')); + } + if (number == playableCharData.getCartoonSoundCartoonFrame()) + { + runTvLogic(); + } + } + }; + + FlxG.debugger.track(this); + FlxG.console.registerObject("dj", this); + + anim.onComplete = onFinishAnim; + + FlxG.console.registerFunction("freeplayCartoon", function() { + currentState = Cartoon; + }); + } + + override public function listAnimations():Array + { + var anims:Array = []; + @:privateAccess + for (animKey in anim.symbolDictionary) + { + anims.push(animKey.name); + } + return anims; + } + + var lowPumpLoopPoint:Int = 4; + + public override function update(elapsed:Float):Void + { + super.update(elapsed); + + switch (currentState) + { + case Intro: + // Play the intro animation then leave this state immediately. + var animPrefix = playableCharData.getAnimationPrefix('intro'); + if (getCurrentAnimation() != animPrefix) playFlashAnimation(animPrefix, true); + timeIdling = 0; + case Idle: + // We are in this state the majority of the time. + var animPrefix = playableCharData.getAnimationPrefix('idle'); + if (getCurrentAnimation() != animPrefix) + { + playFlashAnimation(animPrefix, true); + } + + if (getCurrentAnimation() == animPrefix && this.isLoopFinished()) + { + if (timeIdling >= IDLE_EGG_PERIOD && !seenIdleEasterEgg) + { + currentState = IdleEasterEgg; + } + else if (timeIdling >= IDLE_CARTOON_PERIOD) + { + currentState = Cartoon; + } + } + timeIdling += elapsed; + case Confirm: + var animPrefix = playableCharData.getAnimationPrefix('confirm'); + if (getCurrentAnimation() != animPrefix) playFlashAnimation(animPrefix, false); + timeIdling = 0; + case FistPumpIntro: + var animPrefix = playableCharData.getAnimationPrefix('fistPump'); + if (getCurrentAnimation() != animPrefix) playFlashAnimation('Boyfriend DJ fist pump', false); + if (getCurrentAnimation() == animPrefix && anim.curFrame >= 4) + { + anim.play("Boyfriend DJ fist pump", true, false, 0); + } + case FistPump: + + case IdleEasterEgg: + var animPrefix = playableCharData.getAnimationPrefix('idleEasterEgg'); + if (getCurrentAnimation() != animPrefix) + { + onIdleEasterEgg.dispatch(); + playFlashAnimation(animPrefix, false); + seenIdleEasterEgg = true; + } + timeIdling = 0; + case Cartoon: + var animPrefix = playableCharData.getAnimationPrefix('cartoon'); + if (getCurrentAnimation() != animPrefix) playFlashAnimation(animPrefix, true); + timeIdling = 0; + default: + // I shit myself. + } + + if (FlxG.keys.pressed.CONTROL) + { + if (FlxG.keys.justPressed.LEFT) + { + this.offsetX -= FlxG.keys.pressed.ALT ? 0.1 : (FlxG.keys.pressed.SHIFT ? 10.0 : 1.0); + } + + if (FlxG.keys.justPressed.RIGHT) + { + this.offsetX += FlxG.keys.pressed.ALT ? 0.1 : (FlxG.keys.pressed.SHIFT ? 10.0 : 1.0); + } + + if (FlxG.keys.justPressed.UP) + { + this.offsetY -= FlxG.keys.pressed.ALT ? 0.1 : (FlxG.keys.pressed.SHIFT ? 10.0 : 1.0); + } + + if (FlxG.keys.justPressed.DOWN) + { + this.offsetY += FlxG.keys.pressed.ALT ? 0.1 : (FlxG.keys.pressed.SHIFT ? 10.0 : 1.0); + } + + if (FlxG.keys.justPressed.SPACE) + { + currentState = (currentState == Idle ? Cartoon : Idle); + } + } + } + + function onFinishAnim():Void + { + var name = anim.curSymbol.name; + + if (name == playableCharData.getAnimationPrefix('intro')) + { + currentState = Idle; + onIntroDone.dispatch(); + } + else if (name == playableCharData.getAnimationPrefix('idle')) + { + // trace('Finished idle'); + } + else if (name == playableCharData.getAnimationPrefix('confirm')) + { + // trace('Finished confirm'); + } + else if (name == playableCharData.getAnimationPrefix('fistPump')) + { + // trace('Finished fist pump'); + currentState = Idle; + } + else if (name == playableCharData.getAnimationPrefix('idleEasterEgg')) + { + // trace('Finished spook'); + currentState = Idle; + } + else if (name == playableCharData.getAnimationPrefix('loss')) + { + // trace('Finished loss reaction'); + currentState = Idle; + } + else if (name == playableCharData.getAnimationPrefix('cartoon')) + { + // trace('Finished cartoon'); + + var frame:Int = FlxG.random.bool(33) ? playableCharData.getCartoonLoopBlinkFrame() : playableCharData.getCartoonLoopFrame(); + + // Character switches channels when the video ends, or at a 10% chance each time his idle loops. + if (FlxG.random.bool(5)) + { + frame = playableCharData.getCartoonChannelChangeFrame(); + // boyfriend switches channel code? + // runTvLogic(); + } + trace('Replay idle: ${frame}'); + anim.play(playableCharData.getAnimationPrefix('cartoon'), true, false, frame); + // trace('Finished confirm'); + } + else + { + trace('Finished ${name}'); + } + } + + public function resetAFKTimer():Void + { + timeIdling = 0; + seenIdleEasterEgg = false; + } + + var offsetX:Float = 0.0; + var offsetY:Float = 0.0; + + var cartoonSnd:Null = null; + + public var playingCartoon:Bool = false; + + public function runTvLogic() + { + if (cartoonSnd == null) + { + // tv is OFF, but getting turned on + FunkinSound.playOnce(Paths.sound('tv_on'), 1.0, function() { + loadCartoon(); + }); + } + else + { + // plays it smidge after the click + FunkinSound.playOnce(Paths.sound('channel_switch'), 1.0, function() { + cartoonSnd.destroy(); + loadCartoon(); + }); + } + + // loadCartoon(); + } + + function loadCartoon() + { + cartoonSnd = FunkinSound.load(Paths.sound(getRandomFlashToon()), 1.0, false, true, true, function() { + anim.play("Boyfriend DJ watchin tv OG", true, false, 60); + }); + + // Fade out music to 40% volume over 1 second. + // This helps make the TV a bit more audible. + FlxG.sound.music.fadeOut(1.0, 0.1); + + // Play the cartoon at a random time between the start and 5 seconds from the end. + cartoonSnd.time = FlxG.random.float(0, Math.max(cartoonSnd.length - (5 * Constants.MS_PER_SEC), 0.0)); + } + + final cartoonList:Array = openfl.utils.Assets.list().filter(function(path) return path.startsWith("assets/sounds/cartoons/")); + + function getRandomFlashToon():String + { + var randomFile = FlxG.random.getObject(cartoonList); + + // Strip folder prefix + randomFile = randomFile.replace("assets/sounds/", ""); + // Strip file extension + randomFile = randomFile.substring(0, randomFile.length - 4); + + return randomFile; + } + + public function confirm():Void + { + currentState = Confirm; + } + + public function fistPump():Void + { + currentState = FistPumpIntro; + } + + 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); + } + + override public function getCurrentAnimation():String + { + if (this.anim == null || this.anim.curSymbol == null) return ""; + return this.anim.curSymbol.name; + } + + public function playFlashAnimation(id:String, ?Force:Bool = false, ?Reverse:Bool = false, ?Frame:Int = 0):Void + { + anim.play(id, Force, Reverse, Frame); + applyAnimOffset(); + } + + function applyAnimOffset() + { + var AnimName = getCurrentAnimation(); + var daOffset = playableCharData.getAnimationOffsets(AnimName); + if (daOffset != null) + { + var xValue = daOffset[0]; + var yValue = daOffset[1]; + if (AnimName == "Boyfriend DJ watchin tv OG") + { + xValue += offsetX; + yValue += offsetY; + } + + trace('Successfully applied offset: ' + xValue + ', ' + yValue); + offset.set(xValue, yValue); + } + else + { + trace('No offset found, defaulting to: 0, 0'); + offset.set(0, 0); + } + } + + public override function destroy():Void + { + super.destroy(); + + if (cartoonSnd != null) + { + cartoonSnd.destroy(); + cartoonSnd = null; + } + } +} + +enum DJBoyfriendState +{ + Intro; + Idle; + Confirm; + FistPumpIntro; + FistPump; + IdleEasterEgg; + Cartoon; +} diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 30863f2a9..6b342fb40 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -167,7 +167,7 @@ class FreeplayState extends MusicBeatSubState var curCapsule:SongMenuItem; var curPlaying:Bool = false; - var dj:DJBoyfriend; + var dj:FreeplayDJ; var ostName:FlxText; var albumRoll:AlbumRoll; @@ -211,6 +211,7 @@ class FreeplayState extends MusicBeatSubState { currentCharacterId = params?.character ?? Constants.DEFAULT_CHARACTER; currentCharacter = PlayerRegistry.instance.fetchEntry(currentCharacterId); + if (currentCharacter == null) throw 'Could not build Freeplay state for character: $currentCharacterId'; fromResultsParams = params?.fromResults; @@ -450,17 +451,16 @@ class FreeplayState extends MusicBeatSubState add(cardGlow); - dj = new DJBoyfriend(640, 366); - exitMovers.set([dj], - { - x: -dj.width * 1.6, - speed: 0.5 - }); - - // TODO: Replace this. - if (currentCharacterId == 'pico') dj.visible = false; - - add(dj); + if (currentCharacter?.getFreeplayDJData() != null) + { + dj = new FreeplayDJ(640, 366, currentCharacterId); + exitMovers.set([dj], + { + x: -dj.width * 1.6, + speed: 0.5 + }); + add(dj); + } bgDad = new FlxSprite(pinkBack.width * 0.74, 0).loadGraphic(Paths.image('freeplay/freeplayBGdad')); bgDad.shader = new AngleMask(); diff --git a/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx b/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx index 743345004..282e35d7a 100644 --- a/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx +++ b/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx @@ -77,6 +77,11 @@ class PlayableCharacter implements IRegistryEntry return false; } + public function getFreeplayDJData():PlayerFreeplayDJData + { + return _data.freeplayDJ; + } + /** * Returns whether this character is unlocked. */ diff --git a/source/funkin/util/tools/MapTools.hx b/source/funkin/util/tools/MapTools.hx index b98cb0adf..807f0aebd 100644 --- a/source/funkin/util/tools/MapTools.hx +++ b/source/funkin/util/tools/MapTools.hx @@ -14,6 +14,7 @@ class MapTools */ public static function size(map:Map):Int { + if (map == null) return 0; return map.keys().array().length; } @@ -22,6 +23,7 @@ class MapTools */ public static function values(map:Map):Array { + if (map == null) return []; return [for (i in map.iterator()) i]; } @@ -30,6 +32,7 @@ class MapTools */ public static function clone(map:Map):Map { + if (map == null) return null; return map.copy(); } @@ -76,6 +79,7 @@ class MapTools */ public static function keyValues(map:Map):Array { + if (map == null) return []; return map.keys().array(); } } From dd413d42ab5bdd63b18e2663f69d8182b032c76e Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 19 Jun 2024 23:47:11 -0400 Subject: [PATCH 314/870] more retro week 6 stuff --- assets | 2 +- source/funkin/effects/RetroCameraFade.hx | 106 ++++++++++++++++++ source/funkin/graphics/FunkinSprite.hx | 101 +++++++++++++++++ source/funkin/play/Countdown.hx | 19 +++- source/funkin/play/GameOverSubState.hx | 25 ++++- .../play/character/MultiSparrowCharacter.hx | 2 + .../funkin/play/character/PackerCharacter.hx | 2 + .../funkin/play/character/SparrowCharacter.hx | 2 + source/funkin/play/components/PopUpStuff.hx | 30 +++-- source/funkin/play/stage/Stage.hx | 4 + 10 files changed, 277 insertions(+), 16 deletions(-) create mode 100644 source/funkin/effects/RetroCameraFade.hx diff --git a/assets b/assets index 4b9507525..225e248f1 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 4b95075255baeaba3585fabff7052c257856fafe +Subproject commit 225e248f148a92500a6fe90e4f10e4cd2acee782 diff --git a/source/funkin/effects/RetroCameraFade.hx b/source/funkin/effects/RetroCameraFade.hx new file mode 100644 index 000000000..d4c1da5ef --- /dev/null +++ b/source/funkin/effects/RetroCameraFade.hx @@ -0,0 +1,106 @@ +package funkin.effects; + +import flixel.util.FlxTimer; +import flixel.FlxCamera; +import openfl.filters.ColorMatrixFilter; + +class RetroCameraFade +{ + // im lazy, but we only use this for week 6 + // and also sorta yoinked for djflixel, lol ! + public static function fadeWhite(camera:FlxCamera, camSteps:Int = 5, time:Float = 1):Void + { + var steps:Int = 0; + var stepsTotal:Int = camSteps; + + new FlxTimer().start(time / stepsTotal, _ -> { + var V:Float = (1 / stepsTotal) * steps; + if (steps == stepsTotal) V = 1; + + var matrix = [ + 1, 0, 0, 0, V * 255, + 0, 1, 0, 0, V * 255, + 0, 0, 1, 0, V * 255, + 0, 0, 0, 1, 0 + ]; + camera.filters = [new ColorMatrixFilter(matrix)]; + steps++; + }, stepsTotal + 1); + } + + public static function fadeFromWhite(camera:FlxCamera, camSteps:Int = 5, time:Float = 1):Void + { + var steps:Int = camSteps; + var stepsTotal:Int = camSteps; + + var matrixDerp = [ + 1, 0, 0, 0, 1.0 * 255, + 0, 1, 0, 0, 1.0 * 255, + 0, 0, 1, 0, 1.0 * 255, + 0, 0, 0, 1, 0 + ]; + camera.filters = [new ColorMatrixFilter(matrixDerp)]; + + new FlxTimer().start(time / stepsTotal, _ -> { + var V:Float = (1 / stepsTotal) * steps; + if (steps == stepsTotal) V = 1; + + var matrix = [ + 1, 0, 0, 0, V * 255, + 0, 1, 0, 0, V * 255, + 0, 0, 1, 0, V * 255, + 0, 0, 0, 1, 0 + ]; + camera.filters = [new ColorMatrixFilter(matrix)]; + steps--; + }, camSteps); + } + + public static function fadeToBlack(camera:FlxCamera, camSteps:Int = 5, time:Float = 1):Void + { + var steps:Int = 0; + var stepsTotal:Int = camSteps; + + new FlxTimer().start(time / stepsTotal, _ -> { + var V:Float = (1 / stepsTotal) * steps; + if (steps == stepsTotal) V = 1; + + var matrix = [ + 1, 0, 0, 0, -V * 255, + 0, 1, 0, 0, -V * 255, + 0, 0, 1, 0, -V * 255, + 0, 0, 0, 1, 0 + ]; + camera.filters = [new ColorMatrixFilter(matrix)]; + steps++; + }, camSteps); + } + + public static function fadeBlack(camera:FlxCamera, camSteps:Int = 5, time:Float = 1):Void + { + var steps:Int = camSteps; + var stepsTotal:Int = camSteps; + + var matrixDerp = [ + 1, 0, 0, 0, -1.0 * 255, + 0, 1, 0, 0, -1.0 * 255, + 0, 0, 1, 0, -1.0 * 255, + 0, 0, 0, 1, 0 + ]; + camera.filters = [new ColorMatrixFilter(matrixDerp)]; + + new FlxTimer().start(time / stepsTotal, _ -> { + var V:Float = (1 / stepsTotal) * steps; + if (steps == stepsTotal) V = 1; + + var matrix = [ + 1, 0, 0, 0, -V * 255, + 0, 1, 0, 0, -V * 255, + 0, 0, 1, 0, -V * 255, + 0, 0, 0, 1, 0 + ]; + camera.filters = [new ColorMatrixFilter(matrix)]; + steps--; + }, camSteps + 1); + } +} diff --git a/source/funkin/graphics/FunkinSprite.hx b/source/funkin/graphics/FunkinSprite.hx index bfd2e8028..521553527 100644 --- a/source/funkin/graphics/FunkinSprite.hx +++ b/source/funkin/graphics/FunkinSprite.hx @@ -7,6 +7,10 @@ import flixel.tweens.FlxTween; import openfl.display3D.textures.TextureBase; import funkin.graphics.framebuffer.FixedBitmapData; import openfl.display.BitmapData; +import flixel.math.FlxRect; +import flixel.math.FlxPoint; +import flixel.graphics.frames.FlxFrame; +import flixel.FlxCamera; /** * An FlxSprite with additional functionality. @@ -269,6 +273,103 @@ class FunkinSprite extends FlxSprite return result; } + @:access(flixel.FlxCamera) + override function getBoundingBox(camera:FlxCamera):FlxRect + { + getScreenPosition(_point, camera); + + _rect.set(_point.x, _point.y, width, height); + _rect = camera.transformRect(_rect); + + if (isPixelPerfectRender(camera)) + { + _rect.width = _rect.width / this.scale.x; + _rect.height = _rect.height / this.scale.y; + _rect.x = _rect.x / this.scale.x; + _rect.y = _rect.y / this.scale.y; + _rect.floor(); + _rect.x = _rect.x * this.scale.x; + _rect.y = _rect.y * this.scale.y; + _rect.width = _rect.width * this.scale.x; + _rect.height = _rect.height * this.scale.y; + } + + return _rect; + } + + /** + * Returns the screen position of this object. + * + * @param result Optional arg for the returning point + * @param camera The desired "screen" coordinate space. If `null`, `FlxG.camera` is used. + * @return The screen position of this object. + */ + public override function getScreenPosition(?result:FlxPoint, ?camera:FlxCamera):FlxPoint + { + if (result == null) result = FlxPoint.get(); + + if (camera == null) camera = FlxG.camera; + + result.set(x, y); + if (pixelPerfectPosition) + { + _rect.width = _rect.width / this.scale.x; + _rect.height = _rect.height / this.scale.y; + _rect.x = _rect.x / this.scale.x; + _rect.y = _rect.y / this.scale.y; + _rect.round(); + _rect.x = _rect.x * this.scale.x; + _rect.y = _rect.y * this.scale.y; + _rect.width = _rect.width * this.scale.x; + _rect.height = _rect.height * this.scale.y; + } + + return result.subtract(camera.scroll.x * scrollFactor.x, camera.scroll.y * scrollFactor.y); + } + + override function drawSimple(camera:FlxCamera):Void + { + getScreenPosition(_point, camera).subtractPoint(offset); + if (isPixelPerfectRender(camera)) + { + _point.x = _point.x / this.scale.x; + _point.y = _point.y / this.scale.y; + _point.round(); + + _point.x = _point.x * this.scale.x; + _point.y = _point.y * this.scale.y; + } + + _point.copyToFlash(_flashPoint); + camera.copyPixels(_frame, framePixels, _flashRect, _flashPoint, colorTransform, blend, antialiasing); + } + + override function drawComplex(camera:FlxCamera):Void + { + _frame.prepareMatrix(_matrix, FlxFrameAngle.ANGLE_0, checkFlipX(), checkFlipY()); + _matrix.translate(-origin.x, -origin.y); + _matrix.scale(scale.x, scale.y); + + if (bakedRotationAngle <= 0) + { + updateTrig(); + + if (angle != 0) _matrix.rotateWithTrig(_cosAngle, _sinAngle); + } + + getScreenPosition(_point, camera).subtractPoint(offset); + _point.add(origin.x, origin.y); + _matrix.translate(_point.x, _point.y); + + if (isPixelPerfectRender(camera)) + { + _matrix.tx = Math.round(_matrix.tx / this.scale.x) * this.scale.x; + _matrix.ty = Math.round(_matrix.ty / this.scale.y) * this.scale.y; + } + + camera.drawPixels(_frame, framePixels, _matrix, colorTransform, blend, antialiasing, shader); + } + public override function destroy():Void { frames = null; diff --git a/source/funkin/play/Countdown.hx b/source/funkin/play/Countdown.hx index 10636afdf..55c2a8992 100644 --- a/source/funkin/play/Countdown.hx +++ b/source/funkin/play/Countdown.hx @@ -9,6 +9,7 @@ import funkin.modding.module.ModuleHandler; import funkin.modding.events.ScriptEvent; import funkin.modding.events.ScriptEvent.CountdownScriptEvent; import flixel.util.FlxTimer; +import funkin.util.EaseUtil; import funkin.audio.FunkinSound; class Countdown @@ -117,7 +118,7 @@ class Countdown * * If you want to call this from a module, it's better to use the event system and cancel the onCountdownStep event. */ - public static function pauseCountdown() + public static function pauseCountdown():Void { if (countdownTimer != null && !countdownTimer.finished) { @@ -130,7 +131,7 @@ class Countdown * * If you want to call this from a module, it's better to use the event system and cancel the onCountdownStep event. */ - public static function resumeCountdown() + public static function resumeCountdown():Void { if (countdownTimer != null && !countdownTimer.finished) { @@ -143,7 +144,7 @@ class Countdown * * If you want to call this from a module, it's better to use the event system and cancel the onCountdownStart event. */ - public static function stopCountdown() + public static function stopCountdown():Void { if (countdownTimer != null) { @@ -156,7 +157,7 @@ class Countdown /** * Stops the current countdown, then starts the song for you. */ - public static function skipCountdown() + public static function skipCountdown():Void { stopCountdown(); // This will trigger PlayState.startSong() @@ -185,8 +186,11 @@ class Countdown { var spritePath:String = null; + var fadeEase = FlxEase.cubeInOut; + if (isPixelStyle) { + fadeEase = EaseUtil.stepped(8); switch (index) { case TWO: @@ -227,7 +231,7 @@ class Countdown countdownSprite.screenCenter(); // Fade sprite in, then out, then destroy it. - FlxTween.tween(countdownSprite, {y: countdownSprite.y += 100, alpha: 0}, Conductor.instance.beatLengthMs / 1000, + FlxTween.tween(countdownSprite, {y: countdownSprite.y += 100}, Conductor.instance.beatLengthMs / 1000, { ease: FlxEase.cubeInOut, onComplete: function(twn:FlxTween) { @@ -235,6 +239,11 @@ class Countdown } }); + FlxTween.tween(countdownSprite, {alpha: 0}, Conductor.instance.beatLengthMs / 1000, + { + ease: fadeEase + }); + PlayState.instance.add(countdownSprite); } diff --git a/source/funkin/play/GameOverSubState.hx b/source/funkin/play/GameOverSubState.hx index c84d5b154..1e1c91dc5 100644 --- a/source/funkin/play/GameOverSubState.hx +++ b/source/funkin/play/GameOverSubState.hx @@ -16,6 +16,7 @@ import funkin.ui.MusicBeatSubState; import funkin.ui.story.StoryMenuState; import funkin.util.MathUtil; import openfl.utils.Assets; +import funkin.effects.RetroCameraFade; /** * A substate which renders over the PlayState when the player dies. @@ -331,9 +332,12 @@ class GameOverSubState extends MusicBeatSubState // After the animation finishes... new FlxTimer().start(0.7, function(tmr:FlxTimer) { // ...fade out the graphics. Then after that happens... - FlxG.camera.fade(FlxColor.BLACK, 2, false, function() { + + var resetPlaying = function(pixel:Bool = false) { // ...close the GameOverSubState. - FlxG.camera.fade(FlxColor.BLACK, 1, true, null, true); + if (pixel) RetroCameraFade.fadeBlack(FlxG.camera, 10, 1); + else + FlxG.camera.fade(FlxColor.BLACK, 1, true, null, true); PlayState.instance.needsReset = true; if (PlayState.instance.isMinimalMode || boyfriend == null) {} @@ -350,7 +354,22 @@ class GameOverSubState extends MusicBeatSubState // Close the substate. close(); - }); + }; + + if (musicSuffix == '-pixel') + { + RetroCameraFade.fadeToBlack(FlxG.camera, 10, 2); + new FlxTimer().start(2, _ -> { + FlxG.camera.filters = []; + resetPlaying(true); + }); + } + else + { + FlxG.camera.fade(FlxColor.BLACK, 2, false, function() { + resetPlaying(); + }); + } }); } } diff --git a/source/funkin/play/character/MultiSparrowCharacter.hx b/source/funkin/play/character/MultiSparrowCharacter.hx index 48c5afb58..41c96fbfa 100644 --- a/source/funkin/play/character/MultiSparrowCharacter.hx +++ b/source/funkin/play/character/MultiSparrowCharacter.hx @@ -41,6 +41,8 @@ class MultiSparrowCharacter extends BaseCharacter { this.isPixel = true; this.antialiasing = false; + pixelPerfectRender = true; + pixelPerfectPosition = true; } else { diff --git a/source/funkin/play/character/PackerCharacter.hx b/source/funkin/play/character/PackerCharacter.hx index 2bfac800a..22edbe339 100644 --- a/source/funkin/play/character/PackerCharacter.hx +++ b/source/funkin/play/character/PackerCharacter.hx @@ -43,6 +43,8 @@ class PackerCharacter extends BaseCharacter { this.isPixel = true; this.antialiasing = false; + pixelPerfectRender = true; + pixelPerfectPosition = true; } else { diff --git a/source/funkin/play/character/SparrowCharacter.hx b/source/funkin/play/character/SparrowCharacter.hx index a36aed84d..81d98b138 100644 --- a/source/funkin/play/character/SparrowCharacter.hx +++ b/source/funkin/play/character/SparrowCharacter.hx @@ -46,6 +46,8 @@ class SparrowCharacter extends BaseCharacter { this.isPixel = true; this.antialiasing = false; + pixelPerfectRender = true; + pixelPerfectPosition = true; } else { diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx index b7e206e97..1bdfd98a8 100644 --- a/source/funkin/play/components/PopUpStuff.hx +++ b/source/funkin/play/components/PopUpStuff.hx @@ -7,8 +7,9 @@ import flixel.util.FlxDirection; import funkin.graphics.FunkinSprite; import funkin.play.PlayState; import funkin.util.TimerUtil; +import funkin.util.EaseUtil; -class PopUpStuff extends FlxTypedGroup +class PopUpStuff extends FlxTypedGroup { public var offsets:Array = [0, 0]; @@ -17,7 +18,7 @@ class PopUpStuff extends FlxTypedGroup super(); } - public function displayRating(daRating:String) + public function displayRating(daRating:String):Void { var perfStart:Float = TimerUtil.start(); @@ -40,10 +41,15 @@ class PopUpStuff extends FlxTypedGroup add(rating); + var fadeEase = null; + if (PlayState.instance.currentStageId.startsWith('school')) { rating.setGraphicSize(Std.int(rating.width * Constants.PIXEL_ART_SCALE * 0.7)); rating.antialiasing = false; + rating.pixelPerfectRender = true; + rating.pixelPerfectPosition = true; + fadeEase = EaseUtil.stepped(2); } else { @@ -61,7 +67,8 @@ class PopUpStuff extends FlxTypedGroup remove(rating, true); rating.destroy(); }, - startDelay: Conductor.instance.beatLengthMs * 0.001 + startDelay: Conductor.instance.beatLengthMs * 0.001, + ease: fadeEase }); trace('displayRating took: ${TimerUtil.seconds(perfStart)}'); @@ -92,10 +99,15 @@ class PopUpStuff extends FlxTypedGroup // add(comboSpr); + var fadeEase = null; + if (PlayState.instance.currentStageId.startsWith('school')) { - comboSpr.setGraphicSize(Std.int(comboSpr.width * Constants.PIXEL_ART_SCALE * 0.7)); + comboSpr.setGraphicSize(Std.int(comboSpr.width * Constants.PIXEL_ART_SCALE * 1)); comboSpr.antialiasing = false; + comboSpr.pixelPerfectRender = true; + comboSpr.pixelPerfectPosition = true; + fadeEase = EaseUtil.stepped(2); } else { @@ -110,7 +122,8 @@ class PopUpStuff extends FlxTypedGroup remove(comboSpr, true); comboSpr.destroy(); }, - startDelay: Conductor.instance.beatLengthMs * 0.001 + startDelay: Conductor.instance.beatLengthMs * 0.001, + ease: fadeEase }); var seperatedScore:Array = []; @@ -133,8 +146,10 @@ class PopUpStuff extends FlxTypedGroup if (PlayState.instance.currentStageId.startsWith('school')) { - numScore.setGraphicSize(Std.int(numScore.width * Constants.PIXEL_ART_SCALE * 0.7)); + numScore.setGraphicSize(Std.int(numScore.width * Constants.PIXEL_ART_SCALE * 1)); numScore.antialiasing = false; + numScore.pixelPerfectRender = true; + numScore.pixelPerfectPosition = true; } else { @@ -156,7 +171,8 @@ class PopUpStuff extends FlxTypedGroup remove(numScore, true); numScore.destroy(); }, - startDelay: Conductor.instance.beatLengthMs * 0.002 + startDelay: Conductor.instance.beatLengthMs * 0.002, + ease: fadeEase }); daLoop++; diff --git a/source/funkin/play/stage/Stage.hx b/source/funkin/play/stage/Stage.hx index 4f8ab4434..f4e22e380 100644 --- a/source/funkin/play/stage/Stage.hx +++ b/source/funkin/play/stage/Stage.hx @@ -249,6 +249,10 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements // If pixel, disable antialiasing. propSprite.antialiasing = !dataProp.isPixel; + // If pixel, we render it pixel perfect so there's less "mixels" + propSprite.pixelPerfectRender = dataProp.isPixel; + propSprite.pixelPerfectPosition = dataProp.isPixel; + propSprite.scrollFactor.x = dataProp.scroll[0]; propSprite.scrollFactor.y = dataProp.scroll[1]; From 73efd963b9e1a98c77fdb6a2a8f57517d08f16d1 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Thu, 20 Jun 2024 07:24:36 +0200 Subject: [PATCH 315/870] Fix crash after pressing F5 and coming back from stickers --- source/funkin/ui/freeplay/FreeplayState.hx | 2 +- source/funkin/ui/story/StoryMenuState.hx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 0caaf4591..949aa4bfe 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -214,7 +214,7 @@ class FreeplayState extends MusicBeatSubState prepForNewRank = true; } - if (stickers != null) + if (stickers?.members != null) { stickerSubState = stickers; } diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx index 06a83ab4d..7707850ce 100644 --- a/source/funkin/ui/story/StoryMenuState.hx +++ b/source/funkin/ui/story/StoryMenuState.hx @@ -113,7 +113,7 @@ class StoryMenuState extends MusicBeatState { super(); - if (stickers != null) + if (stickers?.members != null) { stickerSubState = stickers; } From 9b3a748f3768f2d742b922aeedb7e62ee9766e40 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 20 Jun 2024 16:17:53 -0400 Subject: [PATCH 316/870] Working Pico DJ --- assets | 2 +- source/funkin/Paths.hx | 11 +- .../funkin/data/freeplay/player/PlayerData.hx | 42 ++- source/funkin/play/scoring/Scoring.hx | 4 +- source/funkin/ui/freeplay/FreeplayDJ.hx | 14 +- source/funkin/ui/freeplay/FreeplayState.hx | 278 ++++++++++-------- .../freeplay/charselect/PlayableCharacter.hx | 5 + source/funkin/ui/mainmenu/MainMenuState.hx | 5 +- source/funkin/util/SortUtil.hx | 2 +- 9 files changed, 216 insertions(+), 147 deletions(-) diff --git a/assets b/assets index 6ec72f8ae..8dd51cde0 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 6ec72f8aeb5ab77997dee4e2e98ae03f0ec347b8 +Subproject commit 8dd51cde0b9a3730abe9f97d0f50365c396ca784 diff --git a/source/funkin/Paths.hx b/source/funkin/Paths.hx index b0a97c4fa..285af7ca2 100644 --- a/source/funkin/Paths.hx +++ b/source/funkin/Paths.hx @@ -11,9 +11,16 @@ class Paths { static var currentLevel:Null = null; - public static function setCurrentLevel(name:String):Void + public static function setCurrentLevel(name:Null):Void { - currentLevel = name.toLowerCase(); + if (name == null) + { + currentLevel = null; + } + else + { + currentLevel = name.toLowerCase(); + } } public static function stripLibrary(path:String):String diff --git a/source/funkin/data/freeplay/player/PlayerData.hx b/source/funkin/data/freeplay/player/PlayerData.hx index 10fc54b78..c461c9555 100644 --- a/source/funkin/data/freeplay/player/PlayerData.hx +++ b/source/funkin/data/freeplay/player/PlayerData.hx @@ -35,6 +35,7 @@ class PlayerData * Data for displaying this character in the Freeplay menu. * If null, display no DJ. */ + @:optional public var freeplayDJ:Null = null; /** @@ -73,9 +74,25 @@ class PlayerFreeplayDJData var assetPath:String; var animations:Array; + @:optional + @:default("BOYFRIEND") + var text1:String; + + @:optional + @:default("HOT BLOODED IN MORE WAYS THAN ONE") + var text2:String; + + @:optional + @:default("PROTECT YO NUTS") + var text3:String; + + @:jignored var animationMap:Map; + @:jignored + var prefixToOffsetsMap:Map>; + @:optional var cartoon:Null; @@ -87,11 +104,14 @@ class PlayerFreeplayDJData function mapAnimations() { if (animationMap == null) animationMap = new Map(); + if (prefixToOffsetsMap == null) prefixToOffsetsMap = new Map(); animationMap.clear(); + prefixToOffsetsMap.clear(); for (anim in animations) { animationMap.set(anim.name, anim); + prefixToOffsetsMap.set(anim.prefix, anim.offsets); } } @@ -100,6 +120,15 @@ class PlayerFreeplayDJData return Paths.animateAtlas(assetPath); } + public function getFreeplayDJText(index:Int):String { + switch (index) { + case 1: return text1; + case 2: return text2; + case 3: return text3; + default: return ''; + } + } + public function getAnimationPrefix(name:String):Null { if (animationMap.size() == 0) mapAnimations(); @@ -109,13 +138,16 @@ class PlayerFreeplayDJData return anim.prefix; } - public function getAnimationOffsets(name:String):Null> + public function getAnimationOffsetsByPrefix(?prefix:String):Array { - if (animationMap.size() == 0) mapAnimations(); + if (prefixToOffsetsMap.size() == 0) mapAnimations(); + if (prefix == null) return [0, 0]; + return prefixToOffsetsMap.get(prefix); + } - var anim = animationMap.get(name); - if (anim == null) return null; - return anim.offsets; + public function getAnimationOffsets(name:String):Array + { + return getAnimationOffsetsByPrefix(getAnimationPrefix(name)); } // TODO: These should really be frame labels, ehe. diff --git a/source/funkin/play/scoring/Scoring.hx b/source/funkin/play/scoring/Scoring.hx index dc2c40647..02e5750bc 100644 --- a/source/funkin/play/scoring/Scoring.hx +++ b/source/funkin/play/scoring/Scoring.hx @@ -590,7 +590,7 @@ enum abstract ScoringRank(String) } } - public function getFreeplayRankIconAsset():Null + public function getFreeplayRankIconAsset():String { switch (abstract) { @@ -607,7 +607,7 @@ enum abstract ScoringRank(String) case SHIT: return 'LOSS'; default: - return null; + return 'LOSS'; } } diff --git a/source/funkin/ui/freeplay/FreeplayDJ.hx b/source/funkin/ui/freeplay/FreeplayDJ.hx index f9effe793..72eddd0ca 100644 --- a/source/funkin/ui/freeplay/FreeplayDJ.hx +++ b/source/funkin/ui/freeplay/FreeplayDJ.hx @@ -135,8 +135,12 @@ class FreeplayDJ extends FlxAtlasSprite timeIdling = 0; case Cartoon: var animPrefix = playableCharData.getAnimationPrefix('cartoon'); - if (getCurrentAnimation() != animPrefix) playFlashAnimation(animPrefix, true); - timeIdling = 0; + if (animPrefix == null) { + currentState = IdleEasterEgg; + } else { + if (getCurrentAnimation() != animPrefix) playFlashAnimation(animPrefix, true); + timeIdling = 0; + } default: // I shit myself. } @@ -324,7 +328,7 @@ class FreeplayDJ extends FlxAtlasSprite function applyAnimOffset() { var AnimName = getCurrentAnimation(); - var daOffset = playableCharData.getAnimationOffsets(AnimName); + var daOffset = playableCharData.getAnimationOffsetsByPrefix(AnimName); if (daOffset != null) { var xValue = daOffset[0]; @@ -335,12 +339,12 @@ class FreeplayDJ extends FlxAtlasSprite yValue += offsetY; } - trace('Successfully applied offset: ' + xValue + ', ' + yValue); + trace('Successfully applied offset ($AnimName): ' + xValue + ', ' + yValue); offset.set(xValue, yValue); } else { - trace('No offset found, defaulting to: 0, 0'); + trace('No offset found ($AnimName), defaulting to: 0, 0'); offset.set(0, 0); } } diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 6b342fb40..06a090769 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1,54 +1,55 @@ package funkin.ui.freeplay; -import funkin.graphics.adobeanimate.FlxAtlasSprite; import flixel.addons.transition.FlxTransitionableState; 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; 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; import flixel.tweens.FlxTween; +import flixel.tweens.misc.ShakeTween; import flixel.util.FlxColor; import flixel.util.FlxSpriteUtil; import flixel.util.FlxTimer; import funkin.audio.FunkinSound; -import funkin.data.story.level.LevelRegistry; -import funkin.data.song.SongRegistry; import funkin.data.freeplay.player.PlayerRegistry; +import funkin.data.song.SongRegistry; +import funkin.data.story.level.LevelRegistry; +import funkin.effects.IntervalShake; +import funkin.graphics.adobeanimate.FlxAtlasSprite; import funkin.graphics.FunkinCamera; import funkin.graphics.FunkinSprite; import funkin.graphics.shaders.AngleMask; +import funkin.graphics.shaders.GaussianBlurShader; import funkin.graphics.shaders.HSVShader; import funkin.graphics.shaders.PureColor; import funkin.graphics.shaders.StrokeShader; import funkin.input.Controls; import funkin.play.PlayStatePlaylist; +import funkin.play.scoring.Scoring; +import funkin.play.scoring.Scoring.ScoringRank; import funkin.play.song.Song; -import funkin.ui.story.Level; 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.freeplay.charselect.PlayableCharacter; +import funkin.ui.freeplay.SongMenuItem.FreeplayRank; import funkin.ui.mainmenu.MainMenuState; import funkin.ui.MusicBeatSubState; +import funkin.ui.story.Level; import funkin.ui.transition.LoadingState; import funkin.ui.transition.StickerSubState; import funkin.util.MathUtil; +import funkin.util.SortUtil; import lime.utils.Assets; -import flixel.tweens.misc.ShakeTween; -import funkin.effects.IntervalShake; -import funkin.ui.freeplay.SongMenuItem.FreeplayRank; -import funkin.ui.freeplay.charselect.PlayableCharacter; +import openfl.display.BlendMode; /** * Parameters used to initialize the FreeplayState. @@ -94,6 +95,7 @@ typedef FromResultsParams = /** * The state for the freeplay menu, allowing the player to select any song to play. */ +@:nullSafety class FreeplayState extends MusicBeatSubState { // @@ -164,10 +166,9 @@ class FreeplayState extends MusicBeatSubState var grpSongs:FlxTypedGroup; var grpCapsules:FlxTypedGroup; - var curCapsule:SongMenuItem; var curPlaying:Bool = false; - var dj:FreeplayDJ; + var dj:Null = null; var ostName:FlxText; var albumRoll:AlbumRoll; @@ -175,7 +176,7 @@ class FreeplayState extends MusicBeatSubState var letterSort:LetterSort; var exitMovers:ExitMoverData = new Map(); - var stickerSubState:StickerSubState; + var stickerSubState:Null = null; public static var rememberedDifficulty:Null = Constants.DEFAULT_DIFFICULTY; public static var rememberedSongId:Null = 'tutorial'; @@ -210,8 +211,12 @@ class FreeplayState extends MusicBeatSubState public function new(?params:FreeplayStateParams, ?stickers:StickerSubState) { currentCharacterId = params?.character ?? Constants.DEFAULT_CHARACTER; - currentCharacter = PlayerRegistry.instance.fetchEntry(currentCharacterId); - if (currentCharacter == null) throw 'Could not build Freeplay state for character: $currentCharacterId'; + var fetchPlayableCharacter = function():PlayableCharacter { + var result = PlayerRegistry.instance.fetchEntry(params?.character ?? Constants.DEFAULT_CHARACTER); + if (result == null) throw 'No valid playable character with id ${params?.character}'; + return result; + }; + currentCharacter = fetchPlayableCharacter(); fromResultsParams = params?.fromResults; @@ -220,12 +225,54 @@ class FreeplayState extends MusicBeatSubState prepForNewRank = true; } + super(FlxColor.TRANSPARENT); + if (stickers != null) { stickerSubState = stickers; } - super(FlxColor.TRANSPARENT); + // We build a bunch of sprites BEFORE create() so we can guarantee they aren't null later on. + albumRoll = new AlbumRoll(); + fp = new FreeplayScore(460, 60, 7, 100); + cardGlow = new FlxSprite(-30, -30).loadGraphic(Paths.image('freeplay/cardGlow')); + confirmGlow = new FlxSprite(-30, 240).loadGraphic(Paths.image('freeplay/confirmGlow')); + confirmTextGlow = new FlxSprite(-8, 115).loadGraphic(Paths.image('freeplay/glowingText')); + rankCamera = new FunkinCamera('rankCamera', 0, 0, FlxG.width, FlxG.height); + funnyCam = new FunkinCamera('freeplayFunny', 0, 0, FlxG.width, FlxG.height); + funnyScroll = new BGScrollingText(0, 220, currentCharacter.getFreeplayDJText(1), FlxG.width / 2, false, 60); + funnyScroll2 = new BGScrollingText(0, 335, currentCharacter.getFreeplayDJText(1), FlxG.width / 2, false, 60); + grpCapsules = new FlxTypedGroup(); + grpDifficulties = new FlxTypedSpriteGroup(-300, 80); + letterSort = new LetterSort(400, 75); + grpSongs = new FlxTypedGroup(); + moreWays = new BGScrollingText(0, 160, currentCharacter.getFreeplayDJText(2), FlxG.width, true, 43); + moreWays2 = new BGScrollingText(0, 397, currentCharacter.getFreeplayDJText(2), FlxG.width, true, 43); + pinkBack = FunkinSprite.create('freeplay/pinkBack'); + rankBg = new FunkinSprite(0, 0); + rankVignette = new FlxSprite(0, 0).loadGraphic(Paths.image('freeplay/rankVignette')); + sparks = new FlxSprite(0, 0); + sparksADD = new FlxSprite(0, 0); + txtCompletion = new AtlasText(1185, 87, '69', AtlasFont.FREEPLAY_CLEAR); + txtNuts = new BGScrollingText(0, 285, currentCharacter.getFreeplayDJText(3), FlxG.width / 2, true, 43); + + ostName = new FlxText(8, 8, FlxG.width - 8 - 8, 'OFFICIAL OST', 48); + + orangeBackShit = new FunkinSprite(84, 440).makeSolidColor(Std.int(pinkBack.width), 75, 0xFFFEDA00); + + bgDad = new FlxSprite(pinkBack.width * 0.74, 0).loadGraphic(Paths.image('freeplay/freeplayBGdad')); + alsoOrangeLOL = new FunkinSprite(0, orangeBackShit.y).makeSolidColor(100, Std.int(orangeBackShit.height), 0xFFFFD400); + confirmGlow2 = new FlxSprite(confirmGlow.x, confirmGlow.y).loadGraphic(Paths.image('freeplay/confirmGlow2')); + funnyScroll3 = new BGScrollingText(0, orangeBackShit.y + 10, currentCharacter.getFreeplayDJText(1), FlxG.width / 2, 60); + 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), + }); } override function create():Void @@ -236,12 +283,6 @@ 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; @@ -277,7 +318,7 @@ class FreeplayState extends MusicBeatSubState // programmatically adds the songs via LevelRegistry and SongRegistry for (levelId in LevelRegistry.instance.listSortedLevelIds()) { - var level:Level = LevelRegistry.instance.fetchEntry(levelId); + var level:Null = LevelRegistry.instance.fetchEntry(levelId); if (level == null) { @@ -287,7 +328,7 @@ class FreeplayState extends MusicBeatSubState for (songId in level.getSongs()) { - var song:Song = SongRegistry.instance.fetchEntry(songId); + var song:Null = SongRegistry.instance.fetchEntry(songId); if (song == null) { @@ -319,17 +360,14 @@ class FreeplayState extends MusicBeatSubState trace(FlxG.camera.initialZoom); trace(FlxCamera.defaultZoom); - 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); - orangeBackShit = new FunkinSprite(84, 440).makeSolidColor(Std.int(pinkBack.width), 75, 0xFFFEDA00); add(orangeBackShit); - alsoOrangeLOL = new FunkinSprite(0, orangeBackShit.y).makeSolidColor(100, Std.int(orangeBackShit.height), 0xFFFFD400); add(alsoOrangeLOL); exitMovers.set([pinkBack, orangeBackShit, alsoOrangeLOL], @@ -344,15 +382,11 @@ 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; @@ -367,7 +401,6 @@ class FreeplayState extends MusicBeatSubState FlxG.debugger.addTrackerProfile(new TrackerProfile(BGScrollingText, ['x', 'y', 'speed', 'size'])); - 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); @@ -378,7 +411,6 @@ class FreeplayState extends MusicBeatSubState speed: 0.4, }); - funnyScroll = new BGScrollingText(0, 220, 'BOYFRIEND', FlxG.width / 2, false, 60); funnyScroll.funnyColor = 0xFFFF9963; funnyScroll.speed = -3.8; grpTxtScrolls.add(funnyScroll); @@ -391,7 +423,6 @@ class FreeplayState extends MusicBeatSubState wait: 0 }); - txtNuts = new BGScrollingText(0, 285, 'PROTECT YO NUTS', FlxG.width / 2, true, 43); txtNuts.speed = 3.5; grpTxtScrolls.add(txtNuts); exitMovers.set([txtNuts], @@ -400,7 +431,6 @@ class FreeplayState extends MusicBeatSubState speed: 0.4, }); - funnyScroll2 = new BGScrollingText(0, 335, 'BOYFRIEND', FlxG.width / 2, false, 60); funnyScroll2.funnyColor = 0xFFFF9963; funnyScroll2.speed = -3.8; grpTxtScrolls.add(funnyScroll2); @@ -411,7 +441,6 @@ class FreeplayState extends MusicBeatSubState speed: 0.5, }); - 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); @@ -422,7 +451,6 @@ class FreeplayState extends MusicBeatSubState speed: 0.4 }); - funnyScroll3 = new BGScrollingText(0, orangeBackShit.y + 10, 'BOYFRIEND', FlxG.width / 2, 60); funnyScroll3.funnyColor = 0xFFFEA400; funnyScroll3.speed = -3.8; grpTxtScrolls.add(funnyScroll3); @@ -433,19 +461,8 @@ 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; @@ -462,7 +479,6 @@ class FreeplayState extends MusicBeatSubState add(dj); } - bgDad = new FlxSprite(pinkBack.width * 0.74, 0).loadGraphic(Paths.image('freeplay/freeplayBGdad')); bgDad.shader = new AngleMask(); bgDad.visible = false; @@ -488,17 +504,13 @@ class FreeplayState extends MusicBeatSubState blackOverlayBullshitLOLXD.shader = bgDad.shader; - rankBg = new FunkinSprite(0, 0); rankBg.makeSolidColor(FlxG.width, FlxG.height, 0xD3000000); add(rankBg); - grpSongs = new FlxTypedGroup(); add(grpSongs); - grpCapsules = new FlxTypedGroup(); add(grpCapsules); - grpDifficulties = new FlxTypedSpriteGroup(-300, 80); add(grpDifficulties); exitMovers.set([grpDifficulties], @@ -525,7 +537,6 @@ class FreeplayState extends MusicBeatSubState if (diffSprite.difficultyId == currentDifficulty) diffSprite.visible = true; } - albumRoll = new AlbumRoll(); albumRoll.albumId = null; add(albumRoll); @@ -540,7 +551,6 @@ class FreeplayState extends MusicBeatSubState fnfFreeplay.font = 'VCR OSD Mono'; fnfFreeplay.visible = false; - ostName = new FlxText(8, 8, FlxG.width - 8 - 8, 'OFFICIAL OST', 48); ostName.font = 'VCR OSD Mono'; ostName.alignment = RIGHT; ostName.visible = false; @@ -572,7 +582,6 @@ class FreeplayState extends MusicBeatSubState tmr.time = FlxG.random.float(20, 60); }, 0); - fp = new FreeplayScore(460, 60, 7, 100); fp.visible = false; add(fp); @@ -580,11 +589,9 @@ class FreeplayState extends MusicBeatSubState clearBoxSprite.visible = false; add(clearBoxSprite); - txtCompletion = new AtlasText(1185, 87, '69', AtlasFont.FREEPLAY_CLEAR); txtCompletion.visible = false; add(txtCompletion); - letterSort = new LetterSort(400, 75); add(letterSort); letterSort.visible = false; @@ -632,7 +639,8 @@ class FreeplayState extends MusicBeatSubState // be careful not to "add()" things in here unless it's to a group that's already added to the state // otherwise it won't be properly attatched to funnyCamera (relavent code should be at the bottom of create()) - dj.onIntroDone.add(function() { + var onDJIntroDone = function() { + // when boyfriend hits dat shiii albumRoll.playIntro(); @@ -679,20 +687,24 @@ 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) + if (prepForNewRank && fromResultsParams != null) { rankAnimStart(fromResultsParams); } - }); + }; + + if (dj != null) { + dj.onIntroDone.add(onDJIntroDone); + } else { + onDJIntroDone(); + } 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); - rankVignette = new FlxSprite(0, 0).loadGraphic(Paths.image('freeplay/rankVignette')); rankVignette.scale.set(2, 2); rankVignette.updateHitbox(); rankVignette.blend = BlendMode.ADD; @@ -704,7 +716,6 @@ class FreeplayState extends MusicBeatSubState 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]; @@ -716,8 +727,8 @@ class FreeplayState extends MusicBeatSubState } } - var currentFilter:SongFilter = null; - var currentFilteredSongs:Array = []; + var currentFilter:Null = null; + var currentFilteredSongs:Array> = []; /** * Given the current filter, rebuild the current song list. @@ -728,7 +739,7 @@ class FreeplayState extends MusicBeatSubState */ public function generateSongList(filterStuff:Null, force:Bool = false, onlyIfChanged:Bool = true):Void { - var tempSongs:Array = songs; + var tempSongs:Array> = songs; // Remember just the difficulty because it's important for song sorting. if (rememberedDifficulty != null) @@ -790,11 +801,12 @@ class FreeplayState extends MusicBeatSubState for (i in 0...tempSongs.length) { - if (tempSongs[i] == null) continue; + var tempSong = tempSongs[i]; + if (tempSong == null) continue; var funnyMenu:SongMenuItem = grpCapsules.recycle(SongMenuItem); - funnyMenu.init(FlxG.width, 0, tempSongs[i]); + funnyMenu.init(FlxG.width, 0, tempSong); funnyMenu.onConfirm = function() { capsuleOnConfirmDefault(funnyMenu); }; @@ -803,8 +815,8 @@ class FreeplayState extends MusicBeatSubState funnyMenu.ID = i; funnyMenu.capsule.alpha = 0.5; funnyMenu.songText.visible = false; - funnyMenu.favIcon.visible = tempSongs[i].isFav; - funnyMenu.favIconBlurred.visible = tempSongs[i].isFav; + funnyMenu.favIcon.visible = tempSong.isFav; + funnyMenu.favIconBlurred.visible = tempSong.isFav; funnyMenu.hsvShader = hsvShader; funnyMenu.newText.animation.curAnim.curFrame = 45 - ((i * 4) % 45); @@ -828,13 +840,10 @@ class FreeplayState extends MusicBeatSubState * @param songFilter The filter to apply * @return Array */ - public function sortSongs(songsToFilter:Array, songFilter:SongFilter):Array + 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; + var filterAlphabetically = function(a:Null, b:Null):Int { + return SortUtil.alphabetically(a?.songName ?? '', b?.songName ?? ''); }; switch (songFilter.filterType) @@ -858,7 +867,7 @@ class FreeplayState extends MusicBeatSubState songsToFilter = songsToFilter.filter(str -> { if (str == null) return true; // Random - return str.songName.toLowerCase().startsWith(songFilter.filterData); + return str.songName.toLowerCase().startsWith(songFilter.filterData ?? ''); }); case ALL: // no filter! @@ -880,32 +889,28 @@ class FreeplayState extends MusicBeatSubState var sparks:FlxSprite; var sparksADD:FlxSprite; - function rankAnimStart(fromResults:Null):Void + function rankAnimStart(fromResults:FromResultsParams):Void { busy = true; grpCapsules.members[curSelected].sparkle.alpha = 0; // grpCapsules.members[curSelected].forcePosition(); - if (fromResults != null) - { - rememberedSongId = fromResults.songId; - rememberedDifficulty = fromResults.difficultyId; - changeSelection(); - changeDiff(); - } + rememberedSongId = fromResults.songId; + rememberedDifficulty = fromResults.difficultyId; + changeSelection(); + changeDiff(); - dj.fistPump(); + if (dj != null) dj.fistPump(); // rankCamera.fade(FlxColor.BLACK, 0.5, true); rankCamera.fade(0xFF000000, 0.5, true, null, true); if (FlxG.sound.music != null) FlxG.sound.music.volume = 0; rankBg.alpha = 1; - if (fromResults?.oldRank != null) + 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; @@ -915,7 +920,6 @@ class FreeplayState extends MusicBeatSubState 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); @@ -980,14 +984,14 @@ class FreeplayState extends MusicBeatSubState grpCapsules.members[curSelected].ranking.scale.set(20, 20); grpCapsules.members[curSelected].blurredRanking.scale.set(20, 20); - if (fromResults?.newRank != null) + if (fromResults != null && fromResults.newRank != null) { grpCapsules.members[curSelected].ranking.animation.play(fromResults.newRank.getFreeplayRankIconAsset(), true); } FlxTween.tween(grpCapsules.members[curSelected].ranking, {"scale.x": 1, "scale.y": 1}, 0.1); - if (fromResults?.newRank != null) + if (fromResults != null && fromResults.newRank != null) { grpCapsules.members[curSelected].blurredRanking.animation.play(fromResults.newRank.getFreeplayRankIconAsset(), true); } @@ -1078,11 +1082,11 @@ class FreeplayState extends MusicBeatSubState if (fromResultsParams?.newRank == SHIT) { - dj.pumpFistBad(); + if (dj != null) dj.pumpFistBad(); } else { - dj.pumpFist(); + if (dj != null) dj.pumpFist(); } rankCamera.zoom = 0.8; @@ -1196,7 +1200,13 @@ class FreeplayState extends MusicBeatSubState #if debug if (FlxG.keys.justPressed.T) { - rankAnimStart(fromResultsParams); + rankAnimStart(fromResultsParams ?? + { + playRankAnim: true, + newRank: PERFECT_GOLD, + songId: "tutorial", + difficultyId: "hard" + }); } if (FlxG.keys.justPressed.P) @@ -1427,7 +1437,7 @@ class FreeplayState extends MusicBeatSubState } spamTimer += elapsed; - dj.resetAFKTimer(); + if (dj != null) dj.resetAFKTimer(); } else { @@ -1438,31 +1448,31 @@ class FreeplayState extends MusicBeatSubState #if !html5 if (FlxG.mouse.wheel != 0) { - dj.resetAFKTimer(); + if (dj != null) dj.resetAFKTimer(); changeSelection(-Math.round(FlxG.mouse.wheel)); } #else if (FlxG.mouse.wheel < 0) { - dj.resetAFKTimer(); + if (dj != null) dj.resetAFKTimer(); changeSelection(-Math.round(FlxG.mouse.wheel / 8)); } else if (FlxG.mouse.wheel > 0) { - dj.resetAFKTimer(); + if (dj != null) dj.resetAFKTimer(); changeSelection(-Math.round(FlxG.mouse.wheel / 8)); } #end if (controls.UI_LEFT_P) { - dj.resetAFKTimer(); + if (dj != null) dj.resetAFKTimer(); changeDiff(-1); generateSongList(currentFilter, true); } if (controls.UI_RIGHT_P) { - dj.resetAFKTimer(); + if (dj != null) dj.resetAFKTimer(); changeDiff(1); generateSongList(currentFilter, true); } @@ -1472,7 +1482,7 @@ class FreeplayState extends MusicBeatSubState busy = true; FlxTween.globalManager.clear(); FlxTimer.globalManager.clear(); - dj.onIntroDone.removeAll(); + if (dj != null) dj.onIntroDone.removeAll(); FunkinSound.playOnce(Paths.sound('cancelMenu')); @@ -1498,7 +1508,8 @@ class FreeplayState extends MusicBeatSubState for (grpSpr in exitMovers.keys()) { - var moveData:MoveData = exitMovers.get(grpSpr); + var moveData:Null = exitMovers.get(grpSpr); + if (moveData == null) continue; for (spr in grpSpr) { @@ -1506,14 +1517,14 @@ class FreeplayState extends MusicBeatSubState var funnyMoveShit:MoveData = moveData; - if (moveData.x == null) funnyMoveShit.x = spr.x; - if (moveData.y == null) funnyMoveShit.y = spr.y; - if (moveData.speed == null) funnyMoveShit.speed = 0.2; - if (moveData.wait == null) funnyMoveShit.wait = 0; + var moveDataX = funnyMoveShit.x ?? spr.x; + var moveDataY = funnyMoveShit.y ?? spr.y; + var moveDataSpeed = funnyMoveShit.speed ?? 0.2; + var moveDataWait = funnyMoveShit.wait ?? 0; - FlxTween.tween(spr, {x: funnyMoveShit.x, y: funnyMoveShit.y}, funnyMoveShit.speed, {ease: FlxEase.expoIn}); + FlxTween.tween(spr, {x: moveDataX, y: moveDataY}, moveDataSpeed, {ease: FlxEase.expoIn}); - longestTimer = Math.max(longestTimer, funnyMoveShit.speed + funnyMoveShit.wait); + longestTimer = Math.max(longestTimer, moveDataSpeed + moveDataWait); } } @@ -1586,19 +1597,18 @@ class FreeplayState extends MusicBeatSubState var daSong:Null = grpCapsules.members[curSelected].songData; if (daSong != null) { - // TODO: Make this actually be the variation you're focused on. We don't need to fetch the song metadata just to calculate it. - var targetSong:Song = SongRegistry.instance.fetchEntry(grpCapsules.members[curSelected].songData.songId); + var targetSong:Null = SongRegistry.instance.fetchEntry(daSong.songId); if (targetSong == null) { - FlxG.log.warn('WARN: could not find song with id (${grpCapsules.members[curSelected].songData.songId})'); + FlxG.log.warn('WARN: could not find song with id (${daSong.songId})'); return; } - var targetVariation:String = targetSong.getFirstValidVariation(currentDifficulty); + var targetVariation:String = targetSong.getFirstValidVariation(currentDifficulty) ?? ''; // TODO: This line of code makes me sad, but you can't really fix it without a breaking migration. var suffixedDifficulty = (targetVariation != Constants.DEFAULT_VARIATION && targetVariation != 'erect') ? '$currentDifficulty-${targetVariation}' : currentDifficulty; - var songScore:SaveScoreData = Save.instance.getSongScore(grpCapsules.members[curSelected].songData.songId, suffixedDifficulty); + var songScore:Null = Save.instance.getSongScore(daSong.songId, suffixedDifficulty); intendedScore = songScore?.score ?? 0; intendedCompletion = songScore == null ? 0.0 : ((songScore.tallies.sick + songScore.tallies.good) / songScore.tallies.totalNotes); rememberedDifficulty = currentDifficulty; @@ -1660,7 +1670,7 @@ class FreeplayState extends MusicBeatSubState } // Set the album graphic and play the animation if relevant. - var newAlbumId:String = daSong?.albumId; + var newAlbumId:Null = daSong?.albumId; if (albumRoll.albumId != newAlbumId) { albumRoll.albumId = newAlbumId; @@ -1698,7 +1708,7 @@ class FreeplayState extends MusicBeatSubState }); trace('Available songs: ${availableSongCapsules.map(function(cap) { - return cap.songData.songName; + return cap?.songData?.songName; })}'); if (availableSongCapsules.length == 0) @@ -1727,17 +1737,20 @@ class FreeplayState extends MusicBeatSubState PlayStatePlaylist.isStoryMode = false; - var targetSong:Song = SongRegistry.instance.fetchEntry(cap.songData.songId); - if (targetSong == null) + var targetSongId:String = cap?.songData?.songId ?? 'unknown'; + var targetSongNullable:Null = SongRegistry.instance.fetchEntry(targetSongId); + if (targetSongNullable == null) { - FlxG.log.warn('WARN: could not find song with id (${cap.songData.songId})'); + FlxG.log.warn('WARN: could not find song with id (${targetSongId})'); return; } + var targetSong:Song = targetSongNullable; var targetDifficultyId:String = currentDifficulty; - var targetVariation:String = targetSong.getFirstValidVariation(targetDifficultyId, currentCharacter); - PlayStatePlaylist.campaignId = cap.songData.levelId; + var targetVariation:Null = targetSong.getFirstValidVariation(targetDifficultyId, currentCharacter); + var targetLevelId:Null = cap?.songData?.levelId; + PlayStatePlaylist.campaignId = targetLevelId ?? null; - var targetDifficulty:SongDifficulty = targetSong.getDifficulty(targetDifficultyId, targetVariation); + var targetDifficulty:Null = targetSong.getDifficulty(targetDifficultyId, targetVariation); if (targetDifficulty == null) { FlxG.log.warn('WARN: could not find difficulty with id (${targetDifficultyId})'); @@ -1759,7 +1772,7 @@ class FreeplayState extends MusicBeatSubState // Visual and audio effects. FunkinSound.playOnce(Paths.sound('confirmMenu')); - dj.confirm(); + if (dj != null) dj.confirm(); grpCapsules.members[curSelected].forcePosition(); grpCapsules.members[curSelected].songText.flickerText(); @@ -1801,7 +1814,7 @@ class FreeplayState extends MusicBeatSubState new FlxTimer().start(1, function(tmr:FlxTimer) { FunkinSound.emptyPartialQueue(); - Paths.setCurrentLevel(cap.songData.levelId); + Paths.setCurrentLevel(cap?.songData?.levelId); LoadingState.loadPlayState( { targetSong: targetSong, @@ -1856,7 +1869,7 @@ class FreeplayState extends MusicBeatSubState var daSongCapsule:SongMenuItem = grpCapsules.members[curSelected]; if (daSongCapsule.songData != null) { - var songScore:SaveScoreData = Save.instance.getSongScore(daSongCapsule.songData.songId, currentDifficulty); + var songScore:Null = Save.instance.getSongScore(daSongCapsule.songData.songId, currentDifficulty); intendedScore = songScore?.score ?? 0; intendedCompletion = songScore == null ? 0.0 : ((songScore.tallies.sick + songScore.tallies.good) / songScore.tallies.totalNotes); diffIdsCurrent = daSongCapsule.songData.songDifficulties; @@ -1906,7 +1919,10 @@ class FreeplayState extends MusicBeatSubState } else { - var previewSong:Null = SongRegistry.instance.fetchEntry(daSongCapsule.songData.songId); + var previewSongId:Null = daSongCapsule?.songData?.songId; + if (previewSongId == null) return; + + var previewSong:Null = SongRegistry.instance.fetchEntry(previewSongId); var songDifficulty = previewSong?.getDifficulty(currentDifficulty, previewSong?.getVariationsByCharacter(currentCharacter) ?? Constants.DEFAULT_VARIATION_LIST); var baseInstrumentalId:String = songDifficulty?.characters?.instrumental ?? ''; @@ -1924,7 +1940,9 @@ class FreeplayState extends MusicBeatSubState instSuffix = (instSuffix != '') ? '-$instSuffix' : ''; - FunkinSound.playMusic(daSongCapsule.songData.songId, + trace('Attempting to play partial preview: ${previewSongId}:${instSuffix}'); + + FunkinSound.playMusic(previewSongId, { startingVolume: 0.0, overrideExisting: true, @@ -1951,7 +1969,7 @@ class FreeplayState extends MusicBeatSubState public static function build(?params:FreeplayStateParams, ?stickers:StickerSubState):MusicBeatState { var result:MainMenuState; - if (params?.fromResults?.playRankAnim) result = new MainMenuState(true); + if (params?.fromResults?.playRankAnim ?? false) result = new MainMenuState(true); else result = new MainMenuState(false); diff --git a/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx b/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx index 282e35d7a..6d7b96c58 100644 --- a/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx +++ b/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx @@ -82,6 +82,11 @@ class PlayableCharacter implements IRegistryEntry return _data.freeplayDJ; } + public function getFreeplayDJText(index:Int):String + { + return _data.freeplayDJ.getFreeplayDJText(index); + } + /** * Returns whether this character is unlocked. */ diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index d09536eea..56ffc9a27 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -117,7 +117,10 @@ class MainMenuState extends MusicBeatState FlxTransitionableState.skipNextTransIn = true; FlxTransitionableState.skipNextTransOut = true; - openSubState(new FreeplayState()); + openSubState(new FreeplayState( + { + character: FlxG.keys.pressed.SHIFT ? 'pico' : 'bf', + })); }); #if CAN_OPEN_LINKS diff --git a/source/funkin/util/SortUtil.hx b/source/funkin/util/SortUtil.hx index c5ac175be..f6d3721f0 100644 --- a/source/funkin/util/SortUtil.hx +++ b/source/funkin/util/SortUtil.hx @@ -97,7 +97,7 @@ class SortUtil * @param b The second string to compare. * @return 1 if `a` comes before `b`, -1 if `b` comes before `a`, 0 if they are equal */ - public static function alphabetically(a:String, b:String):Int + public static function alphabetically(?a:String, ?b:String):Int { a = a.toUpperCase(); b = b.toUpperCase(); From dd7a894b518e6cf6467ad73ee15e277c244217a3 Mon Sep 17 00:00:00 2001 From: Pixel <146671762+JVNpixels@users.noreply.github.com> Date: Fri, 21 Jun 2024 08:42:51 -0700 Subject: [PATCH 317/870] Update StoryMenuState.hx --- source/funkin/ui/story/StoryMenuState.hx | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx index 06a83ab4d..8623d8f39 100644 --- a/source/funkin/ui/story/StoryMenuState.hx +++ b/source/funkin/ui/story/StoryMenuState.hx @@ -336,6 +336,24 @@ class StoryMenuState extends MusicBeatState changeDifficulty(0); } + #if !html5 + if (FlxG.mouse.wheel != 0) + { + changeLevel(-Math.round(FlxG.mouse.wheel)); + } + #else + if (FlxG.mouse.wheel < 0) + { + changeLevel(-Math.round(FlxG.mouse.wheel / 8)); + } + else if (FlxG.mouse.wheel > 0) + { + changeLevel(-Math.round(FlxG.mouse.wheel / 8)); + } + #end + + // HTML and NON HTML builds mouse fix. + // TODO: Querying UI_RIGHT_P (justPressed) after UI_RIGHT always returns false. Fix it! if (controls.UI_RIGHT_P) { From 0589624d117d52f3ec6224af26b4041205db612c Mon Sep 17 00:00:00 2001 From: Pixel <146671762+JVNpixels@users.noreply.github.com> Date: Fri, 21 Jun 2024 22:46:07 -0700 Subject: [PATCH 318/870] Update source/funkin/ui/story/StoryMenuState.hx Co-authored-by: gamerbross <55158797+gamerbross@users.noreply.github.com> --- source/funkin/ui/story/StoryMenuState.hx | 1 - 1 file changed, 1 deletion(-) diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx index 8623d8f39..5f21a9a88 100644 --- a/source/funkin/ui/story/StoryMenuState.hx +++ b/source/funkin/ui/story/StoryMenuState.hx @@ -352,7 +352,6 @@ class StoryMenuState extends MusicBeatState } #end - // HTML and NON HTML builds mouse fix. // TODO: Querying UI_RIGHT_P (justPressed) after UI_RIGHT always returns false. Fix it! if (controls.UI_RIGHT_P) From be38ae6c0003ac63aea38f490b66e07b10f0bd6e Mon Sep 17 00:00:00 2001 From: Pixel <146671762+JVNpixels@users.noreply.github.com> Date: Sat, 22 Jun 2024 19:23:40 -0700 Subject: [PATCH 319/870] Extra newline removal. Removes the extra line in code. --- source/funkin/ui/story/StoryMenuState.hx | 1 - 1 file changed, 1 deletion(-) diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx index 5f21a9a88..90786b3f6 100644 --- a/source/funkin/ui/story/StoryMenuState.hx +++ b/source/funkin/ui/story/StoryMenuState.hx @@ -352,7 +352,6 @@ class StoryMenuState extends MusicBeatState } #end - // TODO: Querying UI_RIGHT_P (justPressed) after UI_RIGHT always returns false. Fix it! if (controls.UI_RIGHT_P) { From 3b3b9d97ba08d8e315df0bcd755d79d1e6e27a81 Mon Sep 17 00:00:00 2001 From: lemz Date: Sun, 23 Jun 2024 21:03:30 +0200 Subject: [PATCH 320/870] use different implementation --- source/funkin/ui/AtlasText.hx | 26 ++ source/funkin/ui/options/PreferencesMenu.hx | 353 ++++-------------- .../options/items/CheckboxPreferenceItem.hx | 49 +++ .../ui/options/items/NumberPreferenceItem.hx | 107 ++++++ 4 files changed, 249 insertions(+), 286 deletions(-) create mode 100644 source/funkin/ui/options/items/CheckboxPreferenceItem.hx create mode 100644 source/funkin/ui/options/items/NumberPreferenceItem.hx diff --git a/source/funkin/ui/AtlasText.hx b/source/funkin/ui/AtlasText.hx index 186d87c2a..ef74abc1e 100644 --- a/source/funkin/ui/AtlasText.hx +++ b/source/funkin/ui/AtlasText.hx @@ -152,6 +152,32 @@ class AtlasText extends FlxTypedSpriteGroup } } + public function getWidth():Int + { + var width = 0; + for (char in this.text.split("")) + { + switch (char) + { + case " ": + { + width += 40; + } + case "\n": + {} + case char: + { + var sprite = new AtlasChar(atlas, char); + sprite.revive(); + sprite.char = char; + sprite.alpha = 1; + width += Std.int(sprite.width); + } + } + } + return width; + } + override function toString() { return "InputItem, " + FlxStringUtil.getDebugString([ diff --git a/source/funkin/ui/options/PreferencesMenu.hx b/source/funkin/ui/options/PreferencesMenu.hx index 205ef1809..d03fe9073 100644 --- a/source/funkin/ui/options/PreferencesMenu.hx +++ b/source/funkin/ui/options/PreferencesMenu.hx @@ -3,23 +3,18 @@ package funkin.ui.options; import flixel.FlxCamera; import flixel.FlxObject; import flixel.FlxSprite; -import flixel.math.FlxMath; -import flixel.effects.FlxFlicker; import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup; import funkin.ui.AtlasText.AtlasFont; import funkin.ui.options.OptionsState.Page; +import funkin.ui.options.items.CheckboxPreferenceItem; +import funkin.ui.options.items.NumberPreferenceItem; import funkin.graphics.FunkinCamera; -import funkin.audio.FunkinSound; +import funkin.ui.TextMenuList.TextMenuItem; class PreferencesMenu extends Page { - /** - * Wether you can select a different option - */ - public static var allowScrolling:Bool = true; - - var curSelected:Int = 0; - var prefs:FlxTypedSpriteGroup; + var items:TextMenuList; + var preferenceItems:FlxTypedSpriteGroup; var menuCamera:FlxCamera; var camFollow:FlxObject; @@ -33,27 +28,22 @@ class PreferencesMenu extends Page menuCamera.bgColor = 0x0; camera = menuCamera; - prefs = new FlxTypedSpriteGroup(); - add(prefs); + add(items = new TextMenuList()); + add(preferenceItems = new FlxTypedSpriteGroup()); createPrefItems(); camFollow = new FlxObject(FlxG.width / 2, 0, 140, 70); + if (items != null) camFollow.y = items.selectedItem.y; menuCamera.follow(camFollow, null, 0.06); var margin = 160; menuCamera.deadzone.set(0, margin, menuCamera.width, 40); menuCamera.minScrollY = 0; - changeSelection(0); - } - - function addPref(pref:PreferenceItem):Void - { - pref.x = 0; - pref.y = 120 * prefs.length; - pref.ID = prefs.length; - prefs.add(pref); + items.onChange.add(function(selected) { + camFollow.y = selected.y; + }); } /** @@ -62,287 +52,78 @@ class PreferencesMenu extends Page function createPrefItems():Void { #if !web - var pref:NumberedPreferenceItem = new NumberedPreferenceItem("FPS", "The framerate that the game is running on", Preferences.framerate, - function(value:Float):Void { - Preferences.framerate = Std.int(value); - }); - pref.minValue = 60; - pref.maxValue = 360; - pref.changeRate = 1; - pref.changeDelay = 0.05; - addPref(pref); + createPrefItemNumber('FPS', 'The framerate that the game is running on', function(value:Float) { + Preferences.framerate = Std.int(value); + }, Preferences.framerate, 60, 360, 1, 0); #end - - var pref:CheckboxPreferenceItem = new CheckboxPreferenceItem('Naughtyness', 'Toggle displaying raunchy content', Preferences.naughtyness, - function(value:Bool):Void { - Preferences.naughtyness = value; - }); - addPref(pref); - - var pref:CheckboxPreferenceItem = new CheckboxPreferenceItem('Downscroll', 'Enable to make notes move downwards', Preferences.downscroll, - function(value:Bool):Void { - Preferences.downscroll = value; - }); - addPref(pref); - - var pref:CheckboxPreferenceItem = new CheckboxPreferenceItem('Flashing Lights', 'Disable to dampen flashing effects', Preferences.flashingLights, - function(value:Bool):Void { - Preferences.flashingLights = value; - }); - addPref(pref); - - var pref:CheckboxPreferenceItem = new CheckboxPreferenceItem('Camera Zooming on Beat', 'Disable to stop the camera bouncing to the song', - Preferences.zoomCamera, function(value:Bool):Void { - Preferences.zoomCamera = value; - }); - addPref(pref); - - var pref:CheckboxPreferenceItem = new CheckboxPreferenceItem('Debug Display', 'Enable to show FPS and other debug stats', Preferences.debugDisplay, - function(value:Bool):Void { - Preferences.debugDisplay = value; - }); - addPref(pref); - - var pref:CheckboxPreferenceItem = new CheckboxPreferenceItem('Auto Pause', 'Automatically pause the game when it loses focus', Preferences.autoPause, - function(value:Bool):Void { - Preferences.autoPause = value; - }); - addPref(pref); - } - - function changeSelection(change:Int):Void - { - curSelected += change; - if (curSelected < 0) - { - curSelected = prefs.length - 1; - } - else if (curSelected >= prefs.length) - { - curSelected = 0; - } - - for (pref in prefs) - { - if (pref.ID == curSelected) - { - pref.onSelect(true); - camFollow.y = pref.y; - } - else - { - pref.onSelect(false); - } - } + createPrefItemCheckbox('Naughtyness', 'Toggle displaying raunchy content', function(value:Bool):Void { + Preferences.naughtyness = value; + }, Preferences.naughtyness); + createPrefItemCheckbox('Downscroll', 'Enable to make notes move downwards', function(value:Bool):Void { + Preferences.downscroll = value; + }, Preferences.downscroll); + createPrefItemCheckbox('Flashing Lights', 'Disable to dampen flashing effects', function(value:Bool):Void { + Preferences.flashingLights = value; + }, Preferences.flashingLights); + createPrefItemCheckbox('Camera Zooming on Beat', 'Disable to stop the camera bouncing to the song', function(value:Bool):Void { + Preferences.zoomCamera = value; + }, Preferences.zoomCamera); + createPrefItemCheckbox('Debug Display', 'Enable to show FPS and other debug stats', function(value:Bool):Void { + Preferences.debugDisplay = value; + }, Preferences.debugDisplay); + createPrefItemCheckbox('Auto Pause', 'Automatically pause the game when it loses focus', function(value:Bool):Void { + Preferences.autoPause = value; + }, Preferences.autoPause); } override function update(elapsed:Float):Void { super.update(elapsed); - if (controls.UI_DOWN_P && allowScrolling) - { - FunkinSound.playOnce(Paths.sound('scrollMenu')); - changeSelection(1); - } - else if (controls.UI_UP_P && allowScrolling) - { - FunkinSound.playOnce(Paths.sound('scrollMenu')); - changeSelection(-1); - } + // Indent the selected item. + // TODO: Only do this on menu change? + items.forEach(function(daItem:TextMenuItem) { + var thyOffset:Int = 0; + if (Std.isOfType(daItem, NumberPreferenceItem)) thyOffset = cast(daItem, NumberPreferenceItem).lefthandText.getWidth(); - var selectedPref:PreferenceItem = prefs.members[curSelected]; - selectedPref?.handleInput(elapsed); - } -} - -class PreferenceItem extends FlxTypedSpriteGroup -{ - public var name:String = ""; - public var description:String = ""; - - public function handleInput(elapsed:Float):Void {} - - public function onSelect(isSelected:Bool):Void {} -} - -class NumberedPreferenceItem extends PreferenceItem -{ - public var onChange:Float->Void; - public var changeRate:Float = 1.0; - public var changeDelay:Float = 0.1; - - public var minValue(default, set):Null; - - function set_minValue(value:Float):Float - { - minValue = value; - currentValue = currentValue; - return value; - } - - public var maxValue(default, set):Null; - - function set_maxValue(value:Float):Float - { - maxValue = value; - currentValue = currentValue; - return value; - } - - public var currentValue(default, set):Float; - - function set_currentValue(value:Float):Float - { - currentValue = FlxMath.bound(value, minValue, maxValue); - onChange(currentValue); - updateText(); - return currentValue; - } - - var valueText:AtlasText; - var preferenceText:AtlasText; - - public function new(name:String, description:String, defaultValue:Float, onChange:Float->Void) - { - super(); - - this.valueText = new AtlasText(20, 30, '$defaultValue', AtlasFont.DEFAULT); - add(this.valueText); - - this.preferenceText = new AtlasText(this.valueText.x + this.valueText.width + 30, 30, '$name', AtlasFont.BOLD); - add(this.preferenceText); - - this.name = name; - this.description = description; - this.onChange = onChange; - this.currentValue = defaultValue; - } - - var timeToWait:Float = 0; - - public override function handleInput(elapsed:Float):Void - { - timeToWait -= elapsed; - - if (timeToWait > 0) - { - return; - } - - if (PlayerSettings.player1.controls.UI_RIGHT) - { - currentValue += changeRate; - timeToWait = changeDelay; - // FunkinSound.playOnce(Paths.sound('scrollMenu')); - } - else if (PlayerSettings.player1.controls.UI_LEFT) - { - currentValue -= changeRate; - timeToWait = changeDelay; - // FunkinSound.playOnce(Paths.sound('scrollMenu')); - } - } - - var isSelected:Bool = false; + // Very messy but it works + if (thyOffset == 0) + { + if (items.selectedItem == daItem) thyOffset += 150; + else + thyOffset += 120; + } + else if (items.selectedItem == daItem) + { + thyOffset += 70; + } + else + { + thyOffset += 25; + } - public override function onSelect(isSelected:Bool):Void - { - this.isSelected = isSelected; - if (isSelected) - { - preferenceText.x = valueText.x + valueText.width + 60; - preferenceText.alpha = 1.0; - } - else - { - preferenceText.x = valueText.x + valueText.width + 30; - preferenceText.alpha = 0.6; - } + daItem.x = thyOffset; + }); } - function updateText():Void + function createPrefItemCheckbox(prefName:String, prefDesc:String, onChange:Bool->Void, defaultValue:Bool):Void { - valueText.text = '$currentValue'; - preferenceText.x = valueText.x + valueText.width + (isSelected ? 60 : 30); - } -} - -class CheckboxPreferenceItem extends PreferenceItem -{ - public var onChange:Bool->Void; + var checkbox:CheckboxPreferenceItem = new CheckboxPreferenceItem(0, 120 * (items.length - 1 + 1), defaultValue); - public var currentValue(default, set):Bool; + items.createItem(120, (120 * items.length) + 30, prefName, AtlasFont.BOLD, function() { + var value = !checkbox.currentValue; + onChange(value); + checkbox.currentValue = value; + }); - function set_currentValue(value:Bool):Bool - { - if (value) - { - checkBox.animation.play('checked', true); - checkBox.offset.set(17, 70); - } - else - { - checkBox.animation.play('static'); - checkBox.offset.set(); - } - currentValue = value; - onChange(value); - return value; - } - - var checkBox:FlxSprite; - var preferenceText:AtlasText; - - public function new(name:String, description:String, defaultValue:Bool, onChange:Bool->Void) - { - super(); - - this.checkBox = new FlxSprite(); - this.checkBox.frames = Paths.getSparrowAtlas('checkboxThingie'); - this.checkBox.animation.addByPrefix('static', 'Check Box unselected', 24, false); - this.checkBox.animation.addByPrefix('checked', 'Check Box selecting animation', 24, false); - this.checkBox.setGraphicSize(Std.int(this.checkBox.width * 0.7)); - this.checkBox.updateHitbox(); - add(this.checkBox); - - this.preferenceText = new AtlasText(120, 30, '$name', AtlasFont.BOLD); - add(this.preferenceText); - - this.name = name; - this.description = description; - this.onChange = onChange; - this.currentValue = defaultValue; - } - - var isAccepting:Bool = false; - - public override function handleInput(elapsed:Float):Void - { - if (PlayerSettings.player1.controls.ACCEPT && !isAccepting) - { - isAccepting = true; - PreferencesMenu.allowScrolling = false; - FunkinSound.playOnce(Paths.sound('confirmMenu')); - FlxFlicker.flicker(preferenceText, 1, 0.06, true, false, function(_) { - isAccepting = false; - PreferencesMenu.allowScrolling = true; - currentValue = !currentValue; - }); - } + preferenceItems.add(checkbox); } - public override function onSelect(isSelected:Bool):Void + function createPrefItemNumber(prefName:String, prefDesc:String, onChange:Float->Void, defaultValue:Float, min:Float, max:Float, step:Float, + precision:Int):Void { - if (isSelected) - { - preferenceText.x = 150; - preferenceText.alpha = 1.0; - } - else - { - preferenceText.alpha = 0.6; - preferenceText.x = 120; - } + var item = new NumberPreferenceItem(145, (120 * items.length) + 30, prefName, defaultValue, min, max, step, precision, onChange); + items.addItem(prefName, item); + preferenceItems.add(item.lefthandText); } } diff --git a/source/funkin/ui/options/items/CheckboxPreferenceItem.hx b/source/funkin/ui/options/items/CheckboxPreferenceItem.hx new file mode 100644 index 000000000..88c4fb6b0 --- /dev/null +++ b/source/funkin/ui/options/items/CheckboxPreferenceItem.hx @@ -0,0 +1,49 @@ +package funkin.ui.options.items; + +import flixel.FlxSprite.FlxSprite; + +class CheckboxPreferenceItem extends FlxSprite +{ + public var currentValue(default, set):Bool; + + public function new(x:Float, y:Float, defaultValue:Bool = false) + { + super(x, y); + + frames = Paths.getSparrowAtlas('checkboxThingie'); + animation.addByPrefix('static', 'Check Box unselected', 24, false); + animation.addByPrefix('checked', 'Check Box selecting animation', 24, false); + + setGraphicSize(Std.int(width * 0.7)); + updateHitbox(); + + this.currentValue = defaultValue; + } + + override function update(elapsed:Float) + { + super.update(elapsed); + + switch (animation.curAnim.name) + { + case 'static': + offset.set(); + case 'checked': + offset.set(17, 70); + } + } + + function set_currentValue(value:Bool):Bool + { + if (value) + { + animation.play('checked', true); + } + else + { + animation.play('static'); + } + + return currentValue = value; + } +} diff --git a/source/funkin/ui/options/items/NumberPreferenceItem.hx b/source/funkin/ui/options/items/NumberPreferenceItem.hx new file mode 100644 index 000000000..795b6c994 --- /dev/null +++ b/source/funkin/ui/options/items/NumberPreferenceItem.hx @@ -0,0 +1,107 @@ +package funkin.ui.options.items; + +import funkin.ui.TextMenuList; +import funkin.ui.AtlasText; +import funkin.input.Controls; + +/** + * Preference item that allows the player to pick a value between min and max + */ +class NumberPreferenceItem extends TextMenuItem +{ + function controls():Controls + { + return PlayerSettings.player1.controls; + } + + public var lefthandText:AtlasText; + + public var currentValue:Float; + public var min:Float; + public var max:Float; + public var step:Float; + public var precision:Int; + public var onChangeCallback:NullVoid>; + + public function new(x:Float, y:Float, name:String, defaultValue:Float, min:Float, max:Float, step:Float, precision:Int, ?callback:Float->Void):Void + { + super(x, y, name, function() { + callback(this.currentValue); + }); + lefthandText = new AtlasText(20, y, formatted(defaultValue), AtlasFont.DEFAULT); + + updateHitbox(); + + this.currentValue = defaultValue; + this.min = min; + this.max = max; + this.step = step; + this.precision = precision; + this.onChangeCallback = callback; + } + + static final HOLD_DELAY:Float = 0.5; // seconds + static final CHANGE_RATE:Float = 0.02; // seconds + + var holdDelayTimer:Float = HOLD_DELAY; // seconds + var changeRateTimer:Float = 0.0; // seconds + + override function update(elapsed:Float):Void + { + super.update(elapsed); + + // var fancyTextFancyColor:Color; + if (selected) + { + holdDelayTimer -= elapsed; + if (holdDelayTimer <= 0.0) + { + changeRateTimer -= elapsed; + } + + var jpLeft:Bool = controls().UI_LEFT_P; + var jpRight:Bool = controls().UI_RIGHT_P; + + if (jpLeft || jpRight) + { + holdDelayTimer = HOLD_DELAY; + changeRateTimer = 0.0; + } + + var shouldDecrease:Bool = jpLeft; + var shouldIncrease:Bool = jpRight; + + if (controls().UI_LEFT && holdDelayTimer <= 0.0 && changeRateTimer <= 0.0) + { + shouldDecrease = true; + changeRateTimer = CHANGE_RATE; + } + else if (controls().UI_RIGHT && holdDelayTimer <= 0.0 && changeRateTimer <= 0.0) + { + shouldIncrease = true; + changeRateTimer = CHANGE_RATE; + } + + if (shouldDecrease) currentValue -= step; + else if (shouldIncrease) currentValue += step; + currentValue = currentValue.clamp(min, max); + if (onChangeCallback != null && (shouldIncrease || shouldDecrease)) + { + onChangeCallback(currentValue); + } + } + + lefthandText.text = formatted(currentValue); + } + + function formatted(value:Float):String + { + return '${toFixed(value)}'; + } + + function toFixed(value:Float):Float + { + var multiplier:Float = Math.pow(10, precision); + return Math.floor(value * multiplier) / multiplier; + } +} From ef2885ed0e0b68ddf2e534eef1b5f6269c6700d2 Mon Sep 17 00:00:00 2001 From: AbnormalPoof Date: Mon, 24 Jun 2024 03:55:59 -0500 Subject: [PATCH 321/870] video cutscene autopause magic --- source/funkin/play/PlayState.hx | 16 ++++++++++++++-- source/funkin/play/cutscene/VideoCutscene.hx | 2 +- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index f55cef388..de8492882 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1301,12 +1301,18 @@ class PlayState extends MusicBeatSubState super.closeSubState(); } - #if discord_rpc /** * Function called when the game window gains focus. */ public override function onFocus():Void { + if (VideoCutscene.isPlaying() && FlxG.autoPause && isGamePaused) VideoCutscene.pauseVideo(); + #if html5 + else + VideoCutscene.resumeVideo(); + #end + + #if discord_rpc if (health > Constants.HEALTH_MIN && !paused && FlxG.autoPause) { if (Conductor.instance.songPosition > 0.0) DiscordClient.changePresence(detailsText, currentSong.song @@ -1318,6 +1324,7 @@ class PlayState extends MusicBeatSubState else DiscordClient.changePresence(detailsText, currentSong.song + ' (' + storyDifficultyText + ')', iconRPC); } + #end super.onFocus(); } @@ -1327,12 +1334,17 @@ class PlayState extends MusicBeatSubState */ public override function onFocusLost():Void { + #if html5 + if (FlxG.autoPause) VideoCutscene.pauseVideo(); + #end + + #if discord_rpc if (health > Constants.HEALTH_MIN && !paused && FlxG.autoPause) DiscordClient.changePresence(detailsPausedText, currentSong.song + ' (' + storyDifficultyText + ')', iconRPC); + #end super.onFocusLost(); } - #end /** * Removes any references to the current stage, then clears the stage cache, diff --git a/source/funkin/play/cutscene/VideoCutscene.hx b/source/funkin/play/cutscene/VideoCutscene.hx index 01a492a77..abbcd4f54 100644 --- a/source/funkin/play/cutscene/VideoCutscene.hx +++ b/source/funkin/play/cutscene/VideoCutscene.hx @@ -145,7 +145,7 @@ class VideoCutscene { vid.zIndex = 0; vid.bitmap.onEndReached.add(finishVideo.bind(0.5)); - vid.autoPause = false; + vid.autoPause = FlxG.autoPause; vid.cameras = [PlayState.instance.camCutscene]; From aa24dc4aa03b1fc91ea6af000f9d2d87dc755e7a Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 24 Jun 2024 13:34:33 -0400 Subject: [PATCH 322/870] remove bopper trace --- source/funkin/play/stage/Bopper.hx | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/funkin/play/stage/Bopper.hx b/source/funkin/play/stage/Bopper.hx index 262aff7bc..11fb9e499 100644 --- a/source/funkin/play/stage/Bopper.hx +++ b/source/funkin/play/stage/Bopper.hx @@ -200,12 +200,10 @@ class Bopper extends StageProp implements IPlayStateScriptedClass { if (hasDanced) { - trace('DanceRight (alternate)'); playAnimation('danceRight$idleSuffix', forceRestart); } else { - trace('DanceLeft (alternate)'); playAnimation('danceLeft$idleSuffix', forceRestart); } hasDanced = !hasDanced; From aa3e3eb9b65dc26f8a2332cdb3f03050fa3e459b Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 24 Jun 2024 14:13:30 -0400 Subject: [PATCH 323/870] fix: bf v pose playing during a gameover --- source/funkin/play/GameOverSubState.hx | 1 + 1 file changed, 1 insertion(+) diff --git a/source/funkin/play/GameOverSubState.hx b/source/funkin/play/GameOverSubState.hx index c84d5b154..e8568aac6 100644 --- a/source/funkin/play/GameOverSubState.hx +++ b/source/funkin/play/GameOverSubState.hx @@ -144,6 +144,7 @@ class GameOverSubState extends MusicBeatSubState else { boyfriend = PlayState.instance.currentStage.getBoyfriend(true); + boyfriend.canPlayOtherAnims = true; boyfriend.isDead = true; add(boyfriend); boyfriend.resetCharacter(); From 81cada675c99359c461da88193564ba22b32bbba Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 12 Jun 2024 20:31:27 -0400 Subject: [PATCH 324/870] fix for release, no bf printing directly to stdout! --- source/funkin/util/logging/AnsiTrace.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/util/logging/AnsiTrace.hx b/source/funkin/util/logging/AnsiTrace.hx index 9fdc19e1b..2c18d494d 100644 --- a/source/funkin/util/logging/AnsiTrace.hx +++ b/source/funkin/util/logging/AnsiTrace.hx @@ -51,7 +51,7 @@ class AnsiTrace public static function traceBF() { - #if sys + #if (sys && debug) if (colorSupported) { for (line in ansiBF) From d44275c2c7050ed207cb031328f0d9966b812c85 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sun, 16 Jun 2024 18:34:10 -0400 Subject: [PATCH 325/870] Fix a bug where songs with no notes would crash the results screen. --- source/funkin/play/ResultState.hx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index 48fb3b04e..a2c5f7e62 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -464,7 +464,9 @@ class ResultState extends MusicBeatSubState { 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; + // NOTE: Only divide if totalNotes > 0 to prevent divide-by-zero errors. + var clearPercentFloat = params.scoreData.tallies.totalNotes == 0 ? 0.0 : (params.scoreData.tallies.sick + + params.scoreData.tallies.good) / params.scoreData.tallies.totalNotes * 100; clearPercentTarget = Math.floor(clearPercentFloat); // Prevent off-by-one errors. From 983d241e47845e97f2e059358c1a31b0ff5d18e3 Mon Sep 17 00:00:00 2001 From: Karim Akra <144803230+KarimAkra@users.noreply.github.com> Date: Sun, 9 Jun 2024 12:47:17 +0300 Subject: [PATCH 326/870] remove the library strip --- source/funkin/audio/FunkinSound.hx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index c70f195d2..11b713f4d 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -491,8 +491,10 @@ class FunkinSound extends FlxSound implements ICloneable 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 + // we are bypassing the openfl/lime asset library fuss on web only + #if web path = Paths.stripLibrary(path); + #end var soundRequest = FlxPartialSound.partialLoadFromFile(path, start, end); From 4e65c49e0e1a0f7c0bf8edb3c2c5a7d55a5828ef Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 17 Jun 2024 12:22:49 -0400 Subject: [PATCH 327/870] Get rid of a warning about missing BPM info --- 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 0caaf4591..68c63efc4 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1888,6 +1888,7 @@ class FreeplayState extends MusicBeatSubState startingVolume: 0.0, overrideExisting: true, restartTrack: false, + mapTimeChanges: false, // The music metadata is not alongside the audio file so this won't work. pathsFunction: INST, suffix: potentiallyErect, partialParams: From 0f972cb11c1d4bdf3e376f09a1229436dcb3fe47 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sat, 15 Jun 2024 06:33:30 -0400 Subject: [PATCH 328/870] submoduel --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 2e1594ee4..15a816fb8 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 2e1594ee4c04c7148628bae471bdd061c9deb6b7 +Subproject commit 15a816fb833555c22be92bd408eaf147ed4c64be From 92917e17c689a6f43b0d7230e019d5cd5c0a63bc Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sat, 15 Jun 2024 06:53:41 -0400 Subject: [PATCH 329/870] submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 15a816fb8..01a285b38 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 15a816fb833555c22be92bd408eaf147ed4c64be +Subproject commit 01a285b38ecf10218153a1d40a2e4ea5b2132d7b From 93aa02868eb9af3ca1701aeb1467a997e7cf90a0 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sat, 15 Jun 2024 06:55:08 -0400 Subject: [PATCH 330/870] submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 01a285b38..4b9507525 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 01a285b38ecf10218153a1d40a2e4ea5b2132d7b +Subproject commit 4b95075255baeaba3585fabff7052c257856fafe From de6ba0c741854adc8ce6cb394cebc13f77c0876b Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 24 Jun 2024 14:32:40 -0400 Subject: [PATCH 331/870] flxpartialsound hmm update --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index 68e0c5cb0..9daba9902 100644 --- a/hmm.json +++ b/hmm.json @@ -44,7 +44,7 @@ "name": "FlxPartialSound", "type": "git", "dir": null, - "ref": "f986332ba5ab02abd386ce662578baf04904604a", + "ref": "a1eab7b9bf507b87200a3341719054fe427f3b15", "url": "https://github.com/FunkinCrew/FlxPartialSound.git" }, { From 47b7aa702a0b0cccf803632d81829db6040e962c Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 24 Jun 2024 14:46:09 -0400 Subject: [PATCH 332/870] submod --- .gitmodules | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index be5e0aaa8..452c0089b 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 a5442b407ea09c4fccf0d6366841f05355164a3b Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 24 Jun 2024 21:53:56 -0400 Subject: [PATCH 333/870] haxeui --- hmm.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hmm.json b/hmm.json index 9daba9902..278541e1f 100644 --- a/hmm.json +++ b/hmm.json @@ -75,14 +75,14 @@ "name": "haxeui-core", "type": "git", "dir": null, - "ref": "0212d8fdfcafeb5f0d5a41e1ddba8ff21d0e183b", + "ref": "5dc4c933bdc029f6139a47962e3b8c754060f210", "url": "https://github.com/haxeui/haxeui-core" }, { "name": "haxeui-flixel", "type": "git", "dir": null, - "ref": "63a906a6148958dbfde8c7b48d90b0693767fd95", + "ref": "57c1604d6b5174839d7e0e012a4dd5dcbfc129da", "url": "https://github.com/haxeui/haxeui-flixel" }, { From f3e04114ebd7418bee7eeada80a57704a13a3cbb Mon Sep 17 00:00:00 2001 From: lemz Date: Tue, 25 Jun 2024 17:05:15 +0200 Subject: [PATCH 334/870] use new offsets --- source/funkin/ui/options/PreferencesMenu.hx | 23 ++++++++++--------- .../ui/options/items/NumberPreferenceItem.hx | 2 +- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/source/funkin/ui/options/PreferencesMenu.hx b/source/funkin/ui/options/PreferencesMenu.hx index d03fe9073..d004a46c7 100644 --- a/source/funkin/ui/options/PreferencesMenu.hx +++ b/source/funkin/ui/options/PreferencesMenu.hx @@ -84,22 +84,23 @@ class PreferencesMenu extends Page // TODO: Only do this on menu change? items.forEach(function(daItem:TextMenuItem) { var thyOffset:Int = 0; - if (Std.isOfType(daItem, NumberPreferenceItem)) thyOffset = cast(daItem, NumberPreferenceItem).lefthandText.getWidth(); + // Initializing thy text width (if thou text present) + var thyTextWidth:Int = 0; + if (Std.isOfType(daItem, NumberPreferenceItem)) thyTextWidth = cast(daItem, NumberPreferenceItem).lefthandText.getWidth(); - // Very messy but it works - if (thyOffset == 0) + if (thyTextWidth != 0) { - if (items.selectedItem == daItem) thyOffset += 150; - else - thyOffset += 120; + // Magic number because of the weird offset thats being added by default + thyOffset += thyTextWidth - 75; } - else if (items.selectedItem == daItem) + + if (items.selectedItem == daItem) { - thyOffset += 70; + thyOffset += 150; } else { - thyOffset += 25; + thyOffset += 120; } daItem.x = thyOffset; @@ -110,7 +111,7 @@ class PreferencesMenu extends Page { var checkbox:CheckboxPreferenceItem = new CheckboxPreferenceItem(0, 120 * (items.length - 1 + 1), defaultValue); - items.createItem(120, (120 * items.length) + 30, prefName, AtlasFont.BOLD, function() { + items.createItem(0, (120 * items.length) + 30, prefName, AtlasFont.BOLD, function() { var value = !checkbox.currentValue; onChange(value); checkbox.currentValue = value; @@ -122,7 +123,7 @@ class PreferencesMenu extends Page function createPrefItemNumber(prefName:String, prefDesc:String, onChange:Float->Void, defaultValue:Float, min:Float, max:Float, step:Float, precision:Int):Void { - var item = new NumberPreferenceItem(145, (120 * items.length) + 30, prefName, defaultValue, min, max, step, precision, onChange); + var item = new NumberPreferenceItem(0, (120 * items.length) + 30, prefName, defaultValue, min, max, step, precision, onChange); items.addItem(prefName, item); preferenceItems.add(item.lefthandText); } diff --git a/source/funkin/ui/options/items/NumberPreferenceItem.hx b/source/funkin/ui/options/items/NumberPreferenceItem.hx index 795b6c994..eeea3112e 100644 --- a/source/funkin/ui/options/items/NumberPreferenceItem.hx +++ b/source/funkin/ui/options/items/NumberPreferenceItem.hx @@ -28,7 +28,7 @@ class NumberPreferenceItem extends TextMenuItem super(x, y, name, function() { callback(this.currentValue); }); - lefthandText = new AtlasText(20, y, formatted(defaultValue), AtlasFont.DEFAULT); + lefthandText = new AtlasText(15, y, formatted(defaultValue), AtlasFont.DEFAULT); updateHitbox(); From bdbc1364973543cb2186f67420a7420021df1165 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 24 Jun 2024 23:43:34 -0400 Subject: [PATCH 335/870] fix the camera not panning when opening then closing the debug menu during transition --- source/funkin/ui/mainmenu/MainMenuState.hx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index d09536eea..2eba406d9 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -153,6 +153,9 @@ class MainMenuState extends MusicBeatState resetCamStuff(); + // reset camera when debug menu is closed + subStateClosed.add(_ -> resetCamStuff(false)); + subStateOpened.add(sub -> { if (Type.getClass(sub) == FreeplayState) { @@ -182,10 +185,11 @@ class MainMenuState extends MusicBeatState }); } - function resetCamStuff():Void + function resetCamStuff(?snap:Bool = true):Void { FlxG.camera.follow(camFollow, null, 0.06); - FlxG.camera.snapToTarget(); + + if (snap) FlxG.camera.snapToTarget(); } function createMenuItem(name:String, atlas:String, callback:Void->Void, fireInstantly:Bool = false):Void @@ -344,8 +348,6 @@ class MainMenuState extends MusicBeatState persistentUpdate = false; FlxG.state.openSubState(new DebugMenuSubState()); - // reset camera when debug menu is closed - subStateClosed.addOnce(_ -> resetCamStuff()); } #end From da834dab8d243b0da3b99b48f07b1a436333586f Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 24 Jun 2024 16:26:42 -0400 Subject: [PATCH 336/870] fix for heart icons being on the wrong frames --- source/funkin/ui/freeplay/SongMenuItem.hx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/funkin/ui/freeplay/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx index 7708b3bcf..65a5d2e2d 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -213,6 +213,7 @@ class SongMenuItem extends FlxSpriteGroup 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); @@ -516,6 +517,9 @@ class SongMenuItem extends FlxSpriteGroup updateDifficultyRating(songData?.difficultyRating ?? 0); updateScoringRank(songData?.scoringRank); newText.visible = songData?.isNew; + favIcon.animation.curAnim.curFrame = favIcon.animation.curAnim.numFrames - 1; + favIconBlurred.animation.curAnim.curFrame = favIconBlurred.animation.curAnim.numFrames - 1; + // Update opacity, offsets, etc. updateSelected(); From 458e51c327dcd7162ae1a39742e36c38cebaf61b Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 24 Jun 2024 21:53:56 -0400 Subject: [PATCH 337/870] haxeui --- hmm.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hmm.json b/hmm.json index 9daba9902..278541e1f 100644 --- a/hmm.json +++ b/hmm.json @@ -75,14 +75,14 @@ "name": "haxeui-core", "type": "git", "dir": null, - "ref": "0212d8fdfcafeb5f0d5a41e1ddba8ff21d0e183b", + "ref": "5dc4c933bdc029f6139a47962e3b8c754060f210", "url": "https://github.com/haxeui/haxeui-core" }, { "name": "haxeui-flixel", "type": "git", "dir": null, - "ref": "63a906a6148958dbfde8c7b48d90b0693767fd95", + "ref": "57c1604d6b5174839d7e0e012a4dd5dcbfc129da", "url": "https://github.com/haxeui/haxeui-flixel" }, { From 9b4f9db73e2f65be52e4129579fd0f8f73837a83 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 24 Jun 2024 22:01:44 -0400 Subject: [PATCH 338/870] update thx related haxelibs --- hmm.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hmm.json b/hmm.json index 278541e1f..db00b878c 100644 --- a/hmm.json +++ b/hmm.json @@ -174,15 +174,15 @@ "name": "thx.core", "type": "git", "dir": null, - "ref": "22605ff44f01971d599641790d6bae4869f7d9f4", - "url": "https://github.com/FunkinCrew/thx.core" + "ref": "6240b6e136f7490d9298edbe8c1891374bd7cdf2", + "url": "https://github.com/fponticelli/thx.core" }, { "name": "thx.semver", "type": "git", "dir": null, - "ref": "cf8d213589a2c7ce4a59b0fdba9e8ff36bc029fa", - "url": "https://github.com/FunkinCrew/thx.semver" + "ref": "bdb191fe7cf745c02a980749906dbf22719e200b", + "url": "https://github.com/fponticelli/thx.semver" } ] } From 39c3af58f24fb01b4c48db0864f46993e8d6dd38 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 24 Jun 2024 14:13:30 -0400 Subject: [PATCH 339/870] fix: bf v pose playing during a gameover --- source/funkin/play/GameOverSubState.hx | 1 + 1 file changed, 1 insertion(+) diff --git a/source/funkin/play/GameOverSubState.hx b/source/funkin/play/GameOverSubState.hx index c84d5b154..e8568aac6 100644 --- a/source/funkin/play/GameOverSubState.hx +++ b/source/funkin/play/GameOverSubState.hx @@ -144,6 +144,7 @@ class GameOverSubState extends MusicBeatSubState else { boyfriend = PlayState.instance.currentStage.getBoyfriend(true); + boyfriend.canPlayOtherAnims = true; boyfriend.isDead = true; add(boyfriend); boyfriend.resetCharacter(); From 57514302616b8033604e452c506bde9c419f2ff2 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 24 Jun 2024 23:43:34 -0400 Subject: [PATCH 340/870] fix the camera not panning when opening then closing the debug menu during transition --- source/funkin/ui/mainmenu/MainMenuState.hx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index d09536eea..2eba406d9 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -153,6 +153,9 @@ class MainMenuState extends MusicBeatState resetCamStuff(); + // reset camera when debug menu is closed + subStateClosed.add(_ -> resetCamStuff(false)); + subStateOpened.add(sub -> { if (Type.getClass(sub) == FreeplayState) { @@ -182,10 +185,11 @@ class MainMenuState extends MusicBeatState }); } - function resetCamStuff():Void + function resetCamStuff(?snap:Bool = true):Void { FlxG.camera.follow(camFollow, null, 0.06); - FlxG.camera.snapToTarget(); + + if (snap) FlxG.camera.snapToTarget(); } function createMenuItem(name:String, atlas:String, callback:Void->Void, fireInstantly:Bool = false):Void @@ -344,8 +348,6 @@ class MainMenuState extends MusicBeatState persistentUpdate = false; FlxG.state.openSubState(new DebugMenuSubState()); - // reset camera when debug menu is closed - subStateClosed.addOnce(_ -> resetCamStuff()); } #end From ab2f949d7e4fd2011c4d228fc147e5ac70b2f2d9 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 24 Jun 2024 16:26:42 -0400 Subject: [PATCH 341/870] fix for heart icons being on the wrong frames --- source/funkin/ui/freeplay/SongMenuItem.hx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/funkin/ui/freeplay/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx index 7708b3bcf..65a5d2e2d 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -213,6 +213,7 @@ class SongMenuItem extends FlxSpriteGroup 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); @@ -516,6 +517,9 @@ class SongMenuItem extends FlxSpriteGroup updateDifficultyRating(songData?.difficultyRating ?? 0); updateScoringRank(songData?.scoringRank); newText.visible = songData?.isNew; + favIcon.animation.curAnim.curFrame = favIcon.animation.curAnim.numFrames - 1; + favIconBlurred.animation.curAnim.curFrame = favIconBlurred.animation.curAnim.numFrames - 1; + // Update opacity, offsets, etc. updateSelected(); From 1757532097efb747e5e64366095da6ef5e12ca30 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 19 Jun 2024 23:47:11 -0400 Subject: [PATCH 342/870] more retro week 6 stuff --- assets | 2 +- source/funkin/effects/RetroCameraFade.hx | 106 ++++++++++++++++++ source/funkin/graphics/FunkinSprite.hx | 101 +++++++++++++++++ source/funkin/play/Countdown.hx | 19 +++- source/funkin/play/GameOverSubState.hx | 25 ++++- .../play/character/MultiSparrowCharacter.hx | 2 + .../funkin/play/character/PackerCharacter.hx | 2 + .../funkin/play/character/SparrowCharacter.hx | 2 + source/funkin/play/components/PopUpStuff.hx | 30 +++-- source/funkin/play/stage/Stage.hx | 4 + 10 files changed, 277 insertions(+), 16 deletions(-) create mode 100644 source/funkin/effects/RetroCameraFade.hx diff --git a/assets b/assets index 4b9507525..225e248f1 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 4b95075255baeaba3585fabff7052c257856fafe +Subproject commit 225e248f148a92500a6fe90e4f10e4cd2acee782 diff --git a/source/funkin/effects/RetroCameraFade.hx b/source/funkin/effects/RetroCameraFade.hx new file mode 100644 index 000000000..d4c1da5ef --- /dev/null +++ b/source/funkin/effects/RetroCameraFade.hx @@ -0,0 +1,106 @@ +package funkin.effects; + +import flixel.util.FlxTimer; +import flixel.FlxCamera; +import openfl.filters.ColorMatrixFilter; + +class RetroCameraFade +{ + // im lazy, but we only use this for week 6 + // and also sorta yoinked for djflixel, lol ! + public static function fadeWhite(camera:FlxCamera, camSteps:Int = 5, time:Float = 1):Void + { + var steps:Int = 0; + var stepsTotal:Int = camSteps; + + new FlxTimer().start(time / stepsTotal, _ -> { + var V:Float = (1 / stepsTotal) * steps; + if (steps == stepsTotal) V = 1; + + var matrix = [ + 1, 0, 0, 0, V * 255, + 0, 1, 0, 0, V * 255, + 0, 0, 1, 0, V * 255, + 0, 0, 0, 1, 0 + ]; + camera.filters = [new ColorMatrixFilter(matrix)]; + steps++; + }, stepsTotal + 1); + } + + public static function fadeFromWhite(camera:FlxCamera, camSteps:Int = 5, time:Float = 1):Void + { + var steps:Int = camSteps; + var stepsTotal:Int = camSteps; + + var matrixDerp = [ + 1, 0, 0, 0, 1.0 * 255, + 0, 1, 0, 0, 1.0 * 255, + 0, 0, 1, 0, 1.0 * 255, + 0, 0, 0, 1, 0 + ]; + camera.filters = [new ColorMatrixFilter(matrixDerp)]; + + new FlxTimer().start(time / stepsTotal, _ -> { + var V:Float = (1 / stepsTotal) * steps; + if (steps == stepsTotal) V = 1; + + var matrix = [ + 1, 0, 0, 0, V * 255, + 0, 1, 0, 0, V * 255, + 0, 0, 1, 0, V * 255, + 0, 0, 0, 1, 0 + ]; + camera.filters = [new ColorMatrixFilter(matrix)]; + steps--; + }, camSteps); + } + + public static function fadeToBlack(camera:FlxCamera, camSteps:Int = 5, time:Float = 1):Void + { + var steps:Int = 0; + var stepsTotal:Int = camSteps; + + new FlxTimer().start(time / stepsTotal, _ -> { + var V:Float = (1 / stepsTotal) * steps; + if (steps == stepsTotal) V = 1; + + var matrix = [ + 1, 0, 0, 0, -V * 255, + 0, 1, 0, 0, -V * 255, + 0, 0, 1, 0, -V * 255, + 0, 0, 0, 1, 0 + ]; + camera.filters = [new ColorMatrixFilter(matrix)]; + steps++; + }, camSteps); + } + + public static function fadeBlack(camera:FlxCamera, camSteps:Int = 5, time:Float = 1):Void + { + var steps:Int = camSteps; + var stepsTotal:Int = camSteps; + + var matrixDerp = [ + 1, 0, 0, 0, -1.0 * 255, + 0, 1, 0, 0, -1.0 * 255, + 0, 0, 1, 0, -1.0 * 255, + 0, 0, 0, 1, 0 + ]; + camera.filters = [new ColorMatrixFilter(matrixDerp)]; + + new FlxTimer().start(time / stepsTotal, _ -> { + var V:Float = (1 / stepsTotal) * steps; + if (steps == stepsTotal) V = 1; + + var matrix = [ + 1, 0, 0, 0, -V * 255, + 0, 1, 0, 0, -V * 255, + 0, 0, 1, 0, -V * 255, + 0, 0, 0, 1, 0 + ]; + camera.filters = [new ColorMatrixFilter(matrix)]; + steps--; + }, camSteps + 1); + } +} diff --git a/source/funkin/graphics/FunkinSprite.hx b/source/funkin/graphics/FunkinSprite.hx index bfd2e8028..521553527 100644 --- a/source/funkin/graphics/FunkinSprite.hx +++ b/source/funkin/graphics/FunkinSprite.hx @@ -7,6 +7,10 @@ import flixel.tweens.FlxTween; import openfl.display3D.textures.TextureBase; import funkin.graphics.framebuffer.FixedBitmapData; import openfl.display.BitmapData; +import flixel.math.FlxRect; +import flixel.math.FlxPoint; +import flixel.graphics.frames.FlxFrame; +import flixel.FlxCamera; /** * An FlxSprite with additional functionality. @@ -269,6 +273,103 @@ class FunkinSprite extends FlxSprite return result; } + @:access(flixel.FlxCamera) + override function getBoundingBox(camera:FlxCamera):FlxRect + { + getScreenPosition(_point, camera); + + _rect.set(_point.x, _point.y, width, height); + _rect = camera.transformRect(_rect); + + if (isPixelPerfectRender(camera)) + { + _rect.width = _rect.width / this.scale.x; + _rect.height = _rect.height / this.scale.y; + _rect.x = _rect.x / this.scale.x; + _rect.y = _rect.y / this.scale.y; + _rect.floor(); + _rect.x = _rect.x * this.scale.x; + _rect.y = _rect.y * this.scale.y; + _rect.width = _rect.width * this.scale.x; + _rect.height = _rect.height * this.scale.y; + } + + return _rect; + } + + /** + * Returns the screen position of this object. + * + * @param result Optional arg for the returning point + * @param camera The desired "screen" coordinate space. If `null`, `FlxG.camera` is used. + * @return The screen position of this object. + */ + public override function getScreenPosition(?result:FlxPoint, ?camera:FlxCamera):FlxPoint + { + if (result == null) result = FlxPoint.get(); + + if (camera == null) camera = FlxG.camera; + + result.set(x, y); + if (pixelPerfectPosition) + { + _rect.width = _rect.width / this.scale.x; + _rect.height = _rect.height / this.scale.y; + _rect.x = _rect.x / this.scale.x; + _rect.y = _rect.y / this.scale.y; + _rect.round(); + _rect.x = _rect.x * this.scale.x; + _rect.y = _rect.y * this.scale.y; + _rect.width = _rect.width * this.scale.x; + _rect.height = _rect.height * this.scale.y; + } + + return result.subtract(camera.scroll.x * scrollFactor.x, camera.scroll.y * scrollFactor.y); + } + + override function drawSimple(camera:FlxCamera):Void + { + getScreenPosition(_point, camera).subtractPoint(offset); + if (isPixelPerfectRender(camera)) + { + _point.x = _point.x / this.scale.x; + _point.y = _point.y / this.scale.y; + _point.round(); + + _point.x = _point.x * this.scale.x; + _point.y = _point.y * this.scale.y; + } + + _point.copyToFlash(_flashPoint); + camera.copyPixels(_frame, framePixels, _flashRect, _flashPoint, colorTransform, blend, antialiasing); + } + + override function drawComplex(camera:FlxCamera):Void + { + _frame.prepareMatrix(_matrix, FlxFrameAngle.ANGLE_0, checkFlipX(), checkFlipY()); + _matrix.translate(-origin.x, -origin.y); + _matrix.scale(scale.x, scale.y); + + if (bakedRotationAngle <= 0) + { + updateTrig(); + + if (angle != 0) _matrix.rotateWithTrig(_cosAngle, _sinAngle); + } + + getScreenPosition(_point, camera).subtractPoint(offset); + _point.add(origin.x, origin.y); + _matrix.translate(_point.x, _point.y); + + if (isPixelPerfectRender(camera)) + { + _matrix.tx = Math.round(_matrix.tx / this.scale.x) * this.scale.x; + _matrix.ty = Math.round(_matrix.ty / this.scale.y) * this.scale.y; + } + + camera.drawPixels(_frame, framePixels, _matrix, colorTransform, blend, antialiasing, shader); + } + public override function destroy():Void { frames = null; diff --git a/source/funkin/play/Countdown.hx b/source/funkin/play/Countdown.hx index 10636afdf..55c2a8992 100644 --- a/source/funkin/play/Countdown.hx +++ b/source/funkin/play/Countdown.hx @@ -9,6 +9,7 @@ import funkin.modding.module.ModuleHandler; import funkin.modding.events.ScriptEvent; import funkin.modding.events.ScriptEvent.CountdownScriptEvent; import flixel.util.FlxTimer; +import funkin.util.EaseUtil; import funkin.audio.FunkinSound; class Countdown @@ -117,7 +118,7 @@ class Countdown * * If you want to call this from a module, it's better to use the event system and cancel the onCountdownStep event. */ - public static function pauseCountdown() + public static function pauseCountdown():Void { if (countdownTimer != null && !countdownTimer.finished) { @@ -130,7 +131,7 @@ class Countdown * * If you want to call this from a module, it's better to use the event system and cancel the onCountdownStep event. */ - public static function resumeCountdown() + public static function resumeCountdown():Void { if (countdownTimer != null && !countdownTimer.finished) { @@ -143,7 +144,7 @@ class Countdown * * If you want to call this from a module, it's better to use the event system and cancel the onCountdownStart event. */ - public static function stopCountdown() + public static function stopCountdown():Void { if (countdownTimer != null) { @@ -156,7 +157,7 @@ class Countdown /** * Stops the current countdown, then starts the song for you. */ - public static function skipCountdown() + public static function skipCountdown():Void { stopCountdown(); // This will trigger PlayState.startSong() @@ -185,8 +186,11 @@ class Countdown { var spritePath:String = null; + var fadeEase = FlxEase.cubeInOut; + if (isPixelStyle) { + fadeEase = EaseUtil.stepped(8); switch (index) { case TWO: @@ -227,7 +231,7 @@ class Countdown countdownSprite.screenCenter(); // Fade sprite in, then out, then destroy it. - FlxTween.tween(countdownSprite, {y: countdownSprite.y += 100, alpha: 0}, Conductor.instance.beatLengthMs / 1000, + FlxTween.tween(countdownSprite, {y: countdownSprite.y += 100}, Conductor.instance.beatLengthMs / 1000, { ease: FlxEase.cubeInOut, onComplete: function(twn:FlxTween) { @@ -235,6 +239,11 @@ class Countdown } }); + FlxTween.tween(countdownSprite, {alpha: 0}, Conductor.instance.beatLengthMs / 1000, + { + ease: fadeEase + }); + PlayState.instance.add(countdownSprite); } diff --git a/source/funkin/play/GameOverSubState.hx b/source/funkin/play/GameOverSubState.hx index e8568aac6..6eb954c0f 100644 --- a/source/funkin/play/GameOverSubState.hx +++ b/source/funkin/play/GameOverSubState.hx @@ -16,6 +16,7 @@ import funkin.ui.MusicBeatSubState; import funkin.ui.story.StoryMenuState; import funkin.util.MathUtil; import openfl.utils.Assets; +import funkin.effects.RetroCameraFade; /** * A substate which renders over the PlayState when the player dies. @@ -332,9 +333,12 @@ class GameOverSubState extends MusicBeatSubState // After the animation finishes... new FlxTimer().start(0.7, function(tmr:FlxTimer) { // ...fade out the graphics. Then after that happens... - FlxG.camera.fade(FlxColor.BLACK, 2, false, function() { + + var resetPlaying = function(pixel:Bool = false) { // ...close the GameOverSubState. - FlxG.camera.fade(FlxColor.BLACK, 1, true, null, true); + if (pixel) RetroCameraFade.fadeBlack(FlxG.camera, 10, 1); + else + FlxG.camera.fade(FlxColor.BLACK, 1, true, null, true); PlayState.instance.needsReset = true; if (PlayState.instance.isMinimalMode || boyfriend == null) {} @@ -351,7 +355,22 @@ class GameOverSubState extends MusicBeatSubState // Close the substate. close(); - }); + }; + + if (musicSuffix == '-pixel') + { + RetroCameraFade.fadeToBlack(FlxG.camera, 10, 2); + new FlxTimer().start(2, _ -> { + FlxG.camera.filters = []; + resetPlaying(true); + }); + } + else + { + FlxG.camera.fade(FlxColor.BLACK, 2, false, function() { + resetPlaying(); + }); + } }); } } diff --git a/source/funkin/play/character/MultiSparrowCharacter.hx b/source/funkin/play/character/MultiSparrowCharacter.hx index 48c5afb58..41c96fbfa 100644 --- a/source/funkin/play/character/MultiSparrowCharacter.hx +++ b/source/funkin/play/character/MultiSparrowCharacter.hx @@ -41,6 +41,8 @@ class MultiSparrowCharacter extends BaseCharacter { this.isPixel = true; this.antialiasing = false; + pixelPerfectRender = true; + pixelPerfectPosition = true; } else { diff --git a/source/funkin/play/character/PackerCharacter.hx b/source/funkin/play/character/PackerCharacter.hx index 2bfac800a..22edbe339 100644 --- a/source/funkin/play/character/PackerCharacter.hx +++ b/source/funkin/play/character/PackerCharacter.hx @@ -43,6 +43,8 @@ class PackerCharacter extends BaseCharacter { this.isPixel = true; this.antialiasing = false; + pixelPerfectRender = true; + pixelPerfectPosition = true; } else { diff --git a/source/funkin/play/character/SparrowCharacter.hx b/source/funkin/play/character/SparrowCharacter.hx index a36aed84d..81d98b138 100644 --- a/source/funkin/play/character/SparrowCharacter.hx +++ b/source/funkin/play/character/SparrowCharacter.hx @@ -46,6 +46,8 @@ class SparrowCharacter extends BaseCharacter { this.isPixel = true; this.antialiasing = false; + pixelPerfectRender = true; + pixelPerfectPosition = true; } else { diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx index b7e206e97..1bdfd98a8 100644 --- a/source/funkin/play/components/PopUpStuff.hx +++ b/source/funkin/play/components/PopUpStuff.hx @@ -7,8 +7,9 @@ import flixel.util.FlxDirection; import funkin.graphics.FunkinSprite; import funkin.play.PlayState; import funkin.util.TimerUtil; +import funkin.util.EaseUtil; -class PopUpStuff extends FlxTypedGroup +class PopUpStuff extends FlxTypedGroup { public var offsets:Array = [0, 0]; @@ -17,7 +18,7 @@ class PopUpStuff extends FlxTypedGroup super(); } - public function displayRating(daRating:String) + public function displayRating(daRating:String):Void { var perfStart:Float = TimerUtil.start(); @@ -40,10 +41,15 @@ class PopUpStuff extends FlxTypedGroup add(rating); + var fadeEase = null; + if (PlayState.instance.currentStageId.startsWith('school')) { rating.setGraphicSize(Std.int(rating.width * Constants.PIXEL_ART_SCALE * 0.7)); rating.antialiasing = false; + rating.pixelPerfectRender = true; + rating.pixelPerfectPosition = true; + fadeEase = EaseUtil.stepped(2); } else { @@ -61,7 +67,8 @@ class PopUpStuff extends FlxTypedGroup remove(rating, true); rating.destroy(); }, - startDelay: Conductor.instance.beatLengthMs * 0.001 + startDelay: Conductor.instance.beatLengthMs * 0.001, + ease: fadeEase }); trace('displayRating took: ${TimerUtil.seconds(perfStart)}'); @@ -92,10 +99,15 @@ class PopUpStuff extends FlxTypedGroup // add(comboSpr); + var fadeEase = null; + if (PlayState.instance.currentStageId.startsWith('school')) { - comboSpr.setGraphicSize(Std.int(comboSpr.width * Constants.PIXEL_ART_SCALE * 0.7)); + comboSpr.setGraphicSize(Std.int(comboSpr.width * Constants.PIXEL_ART_SCALE * 1)); comboSpr.antialiasing = false; + comboSpr.pixelPerfectRender = true; + comboSpr.pixelPerfectPosition = true; + fadeEase = EaseUtil.stepped(2); } else { @@ -110,7 +122,8 @@ class PopUpStuff extends FlxTypedGroup remove(comboSpr, true); comboSpr.destroy(); }, - startDelay: Conductor.instance.beatLengthMs * 0.001 + startDelay: Conductor.instance.beatLengthMs * 0.001, + ease: fadeEase }); var seperatedScore:Array = []; @@ -133,8 +146,10 @@ class PopUpStuff extends FlxTypedGroup if (PlayState.instance.currentStageId.startsWith('school')) { - numScore.setGraphicSize(Std.int(numScore.width * Constants.PIXEL_ART_SCALE * 0.7)); + numScore.setGraphicSize(Std.int(numScore.width * Constants.PIXEL_ART_SCALE * 1)); numScore.antialiasing = false; + numScore.pixelPerfectRender = true; + numScore.pixelPerfectPosition = true; } else { @@ -156,7 +171,8 @@ class PopUpStuff extends FlxTypedGroup remove(numScore, true); numScore.destroy(); }, - startDelay: Conductor.instance.beatLengthMs * 0.002 + startDelay: Conductor.instance.beatLengthMs * 0.002, + ease: fadeEase }); daLoop++; diff --git a/source/funkin/play/stage/Stage.hx b/source/funkin/play/stage/Stage.hx index 4f8ab4434..f4e22e380 100644 --- a/source/funkin/play/stage/Stage.hx +++ b/source/funkin/play/stage/Stage.hx @@ -249,6 +249,10 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements // If pixel, disable antialiasing. propSprite.antialiasing = !dataProp.isPixel; + // If pixel, we render it pixel perfect so there's less "mixels" + propSprite.pixelPerfectRender = dataProp.isPixel; + propSprite.pixelPerfectPosition = dataProp.isPixel; + propSprite.scrollFactor.x = dataProp.scroll[0]; propSprite.scrollFactor.y = dataProp.scroll[1]; From 8a144352a030d24f78eea554bb5ee89daaeff815 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 24 Jun 2024 13:34:33 -0400 Subject: [PATCH 343/870] remove bopper trace --- source/funkin/play/stage/Bopper.hx | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/funkin/play/stage/Bopper.hx b/source/funkin/play/stage/Bopper.hx index 262aff7bc..11fb9e499 100644 --- a/source/funkin/play/stage/Bopper.hx +++ b/source/funkin/play/stage/Bopper.hx @@ -200,12 +200,10 @@ class Bopper extends StageProp implements IPlayStateScriptedClass { if (hasDanced) { - trace('DanceRight (alternate)'); playAnimation('danceRight$idleSuffix', forceRestart); } else { - trace('DanceLeft (alternate)'); playAnimation('danceLeft$idleSuffix', forceRestart); } hasDanced = !hasDanced; From e7dd724be6e0f95324ffbdbb1d19e4a5075619da Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 25 Jun 2024 13:56:42 -0400 Subject: [PATCH 344/870] assets --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 225e248f1..4b9507525 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 225e248f148a92500a6fe90e4f10e4cd2acee782 +Subproject commit 4b95075255baeaba3585fabff7052c257856fafe From ef7612d1c25921f92f076058bc460ccae3bccac5 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 24 Jun 2024 22:05:16 -0400 Subject: [PATCH 345/870] discord RPC haxelib --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index db00b878c..bedfd7447 100644 --- a/hmm.json +++ b/hmm.json @@ -5,7 +5,7 @@ "type": "git", "dir": null, "ref": "2d83fa863ef0c1eace5f1cf67c3ac315d1a3a8a5", - "url": "https://github.com/Aidan63/linc_discord-rpc" + "url": "https://github.com/FunkinCrew/linc_discord-rpc" }, { "name": "flixel", From e7f39ea08183eb0f2a2a532e2736ebfbfebd4706 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 24 Jun 2024 22:07:01 -0400 Subject: [PATCH 346/870] hxp hmm update --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index bedfd7447..8eaf24212 100644 --- a/hmm.json +++ b/hmm.json @@ -112,7 +112,7 @@ { "name": "hxp", "type": "haxelib", - "version": "1.2.2" + "version": "1.3.0" }, { "name": "json2object", From 08d35eb00d0f1a7a2c1af823fedab384e9c176f1 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Tue, 25 Jun 2024 18:07:09 -0400 Subject: [PATCH 347/870] Fix tankmanpixel icon in Chart Editor --- source/funkin/play/character/CharacterData.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/play/character/CharacterData.hx b/source/funkin/play/character/CharacterData.hx index 7d3d6cfb9..8b1649e26 100644 --- a/source/funkin/play/character/CharacterData.hx +++ b/source/funkin/play/character/CharacterData.hx @@ -305,8 +305,8 @@ class CharacterDataParser icon = "darnell"; case "senpai-angry": icon = "senpai"; - case "tankman" | "tankman-atlas": - icon = "tankmen"; + case "tankman-atlas": + icon = "tankman"; } var path = Paths.image("freeplay/icons/" + icon + "pixel"); From 4a73d7e1cec158c7258eca8099954f029fdb5103 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 25 Jun 2024 18:22:30 -0400 Subject: [PATCH 348/870] Add change counts labels to Actions labeler --- .github/changed-lines-count-labeler.yml | 12 ++++++++++++ .github/workflows/labeler.yml | 15 ++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 .github/changed-lines-count-labeler.yml diff --git a/.github/changed-lines-count-labeler.yml b/.github/changed-lines-count-labeler.yml new file mode 100644 index 000000000..6f890f534 --- /dev/null +++ b/.github/changed-lines-count-labeler.yml @@ -0,0 +1,12 @@ +# Add 'small' to any changes below 10 lines +small: + max: 9 + +# Add 'medium' to any changes between 10 and 100 lines +medium: + min: 10 + max: 99 + +# Add 'large' to any changes for more than 100 lines +large: + min: 100 diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 0bcc420d3..a861af578 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -9,6 +9,19 @@ jobs: pull-requests: write runs-on: ubuntu-latest steps: - - uses: actions/labeler@v5 + - name: Set basic labels + uses: actions/labeler@v5 with: sync-labels: true + changed-lines-count-labeler: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + name: An action for automatically labelling pull requests based on the changed lines count + steps: + - name: Set change count labels + uses: vkirilichev/changed-lines-count-labeler@v0.2 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + configuration-path: .github/changed-lines-count-labeler.yml From dad8b0815dc790181abd375b25946b05c41a1bda Mon Sep 17 00:00:00 2001 From: cyn Date: Mon, 13 May 2024 11:23:16 -0700 Subject: [PATCH 349/870] flash fix --- source/funkin/ui/MenuItem.hx | 23 +++++++++++------------ source/funkin/ui/story/LevelTitle.hx | 24 ++++++++++++------------ 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/source/funkin/ui/MenuItem.hx b/source/funkin/ui/MenuItem.hx index ba5cc066b..2a483ea78 100644 --- a/source/funkin/ui/MenuItem.hx +++ b/source/funkin/ui/MenuItem.hx @@ -11,7 +11,6 @@ class MenuItem extends FlxSpriteGroup { public var targetY:Float = 0; public var week:FlxSprite; - public var flashingInt:Int = 0; public function new(x:Float, y:Float, weekNum:Int = 0, weekType:WeekType) { @@ -30,28 +29,28 @@ class MenuItem extends FlxSpriteGroup } var isFlashing:Bool = false; + var flashTick:Float = 0; + final flashFramerate:Float = 20; public function startFlashing():Void { isFlashing = true; } - // if it runs at 60fps, fake framerate will be 6 - // if it runs at 144 fps, fake framerate will be like 14, and will update the graphic every 0.016666 * 3 seconds still??? - // so it runs basically every so many seconds, not dependant on framerate?? - // I'm still learning how math works thanks whoever is reading this lol - var fakeFramerate:Int = Math.round((1 / FlxG.elapsed) / 10); - override function update(elapsed:Float) { super.update(elapsed); y = MathUtil.coolLerp(y, (targetY * 120) + 480, 0.17); - if (isFlashing) flashingInt += 1; - - if (flashingInt % fakeFramerate >= Math.floor(fakeFramerate / 2)) week.color = 0xFF33ffff; - else - week.color = FlxColor.WHITE; + if (isFlashing) + { + flashTick += elapsed; + if (flashTick >= 1 / flashFramerate) + { + flashTick %= 1 / flashFramerate; + week.color = (week.color == FlxColor.WHITE) ? 0xFF33ffff : FlxColor.WHITE; + } + } } } diff --git a/source/funkin/ui/story/LevelTitle.hx b/source/funkin/ui/story/LevelTitle.hx index e6f989016..2be2da154 100644 --- a/source/funkin/ui/story/LevelTitle.hx +++ b/source/funkin/ui/story/LevelTitle.hx @@ -13,13 +13,10 @@ class LevelTitle extends FlxSpriteGroup public final level:Level; public var targetY:Float; - public var isFlashing:Bool = false; var title:FlxSprite; var lock:FlxSprite; - var flashingInt:Int = 0; - public function new(x:Int, y:Int, level:Level) { super(x, y); @@ -46,20 +43,23 @@ class LevelTitle extends FlxSpriteGroup } } - // if it runs at 60fps, fake framerate will be 6 - // if it runs at 144 fps, fake framerate will be like 14, and will update the graphic every 0.016666 * 3 seconds still??? - // so it runs basically every so many seconds, not dependant on framerate?? - // I'm still learning how math works thanks whoever is reading this lol - var fakeFramerate:Int = Math.round((1 / FlxG.elapsed) / 10); + public var isFlashing:Bool = false; + var flashTick:Float = 0; + final flashFramerate:Float = 20; public override function update(elapsed:Float):Void { this.y = MathUtil.coolLerp(y, targetY, 0.17); - if (isFlashing) flashingInt += 1; - if (flashingInt % fakeFramerate >= Math.floor(fakeFramerate / 2)) title.color = 0xFF33ffff; - else - title.color = FlxColor.WHITE; + if (isFlashing) + { + flashTick += elapsed; + if (flashTick >= 1 / flashFramerate) + { + flashTick %= 1 / flashFramerate; + title.color = (title.color == FlxColor.WHITE) ? 0xFF33ffff : FlxColor.WHITE; + } + } } public function showLock():Void From a7bdf2383267cbdfc294b9cf0f8e92eb4711777a Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Mon, 10 Jun 2024 16:53:32 +0200 Subject: [PATCH 350/870] Fix chart reset when charting and pressing chart key --- source/funkin/play/PlayState.hx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index f55cef388..d7173b9a7 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -2619,10 +2619,18 @@ class PlayState extends MusicBeatSubState { disableKeys = true; persistentUpdate = false; - FlxG.switchState(() -> new ChartEditorState( - { - targetSongId: currentSong.id, - })); + if (isChartingMode) + { + FlxG.sound.music?.pause(); + this.close(); + } + else + { + FlxG.switchState(() -> new ChartEditorState( + { + targetSongId: currentSong.id, + })); + } } #end From 6f26fbba5f55a1f7e1fbfdf918dfd4b8e806c3b2 Mon Sep 17 00:00:00 2001 From: NotHyper-474 Date: Mon, 10 Jun 2024 23:12:28 -0300 Subject: [PATCH 351/870] Fix trace --- source/funkin/ui/transition/LoadingState.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/transition/LoadingState.hx b/source/funkin/ui/transition/LoadingState.hx index bc26ad97a..0f2ce1076 100644 --- a/source/funkin/ui/transition/LoadingState.hx +++ b/source/funkin/ui/transition/LoadingState.hx @@ -346,7 +346,7 @@ class LoadingState extends MusicBeatSubState return 'Done precaching ${path}'; }, true); - trace("Queued ${path} for precaching"); + trace('Queued ${path} for precaching'); // FunkinSprite.cacheTexture(path); } From 16d64991edfcfba64b4715d59cd570ed1b40f366 Mon Sep 17 00:00:00 2001 From: MaybeMaru <97055307+MaybeMaru@users.noreply.github.com> Date: Tue, 18 Jun 2024 15:11:00 +0200 Subject: [PATCH 352/870] Add missing constants --- source/funkin/play/notes/Strumline.hx | 2 +- source/funkin/play/notes/SustainTrail.hx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/play/notes/Strumline.hx b/source/funkin/play/notes/Strumline.hx index 0e4b6645f..3c114b5e0 100644 --- a/source/funkin/play/notes/Strumline.hx +++ b/source/funkin/play/notes/Strumline.hx @@ -37,7 +37,7 @@ class Strumline extends FlxSpriteGroup static function get_RENDER_DISTANCE_MS():Float { - return FlxG.height / 0.45; + return FlxG.height / Constants.PIXELS_PER_MS; } /** diff --git a/source/funkin/play/notes/SustainTrail.hx b/source/funkin/play/notes/SustainTrail.hx index b358d7f03..f6d43b33f 100644 --- a/source/funkin/play/notes/SustainTrail.hx +++ b/source/funkin/play/notes/SustainTrail.hx @@ -160,7 +160,7 @@ class SustainTrail extends FlxSprite */ public static inline function sustainHeight(susLength:Float, scroll:Float) { - return (susLength * 0.45 * scroll); + return (susLength * Constants.PIXELS_PER_MS * scroll); } function set_sustainLength(s:Float):Float From 91bc63004abdd1a669ac6779d83fde5c88b641bd Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Thu, 27 Jun 2024 21:00:25 +0200 Subject: [PATCH 353/870] FunkinSound.playOnce return sound --- source/funkin/audio/FunkinSound.hx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index c70f195d2..8d2ad9a32 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -533,11 +533,12 @@ class FunkinSound extends FlxSound implements ICloneable * Play a sound effect once, then destroy it. * @param key * @param volume - * @return static function construct():FunkinSound + * @return A `FunkinSound` object, or `null` if the sound could not be loaded. */ - public static function playOnce(key:String, volume:Float = 1.0, ?onComplete:Void->Void, ?onLoad:Void->Void):Void + public static function playOnce(key:String, volume:Float = 1.0, ?onComplete:Void->Void, ?onLoad:Void->Void):FunkinSound { var result = FunkinSound.load(key, volume, false, true, true, onComplete, onLoad); + return result; } /** From 02dd7e7264ab8c2d9f2136a1e07ff7e0e41e6904 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Thu, 27 Jun 2024 21:05:01 +0200 Subject: [PATCH 354/870] Implement danceEvery for Characters --- source/funkin/play/character/BaseCharacter.hx | 1 + 1 file changed, 1 insertion(+) diff --git a/source/funkin/play/character/BaseCharacter.hx b/source/funkin/play/character/BaseCharacter.hx index 4ef86c6a9..f9e1f00f2 100644 --- a/source/funkin/play/character/BaseCharacter.hx +++ b/source/funkin/play/character/BaseCharacter.hx @@ -180,6 +180,7 @@ class BaseCharacter extends Bopper { this.characterName = _data.name; this.name = _data.name; + this.danceEvery = _data.danceEvery; this.singTimeSteps = _data.singTime; this.globalOffsets = _data.offsets; this.flipX = _data.flipX; From 84dd1cd3b98d58d230196036db61556ad40eae43 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 28 Jun 2024 22:29:59 -0400 Subject: [PATCH 355/870] Fix several character animation issues --- assets | 2 +- source/funkin/modding/events/ScriptEvent.hx | 3 +- source/funkin/play/character/BaseCharacter.hx | 109 ++++++++++++++---- source/funkin/util/Constants.hx | 15 +++ 4 files changed, 102 insertions(+), 27 deletions(-) diff --git a/assets b/assets index 225e248f1..9050732ec 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 225e248f148a92500a6fe90e4f10e4cd2acee782 +Subproject commit 9050732ec1cc69cbca9a9a73ee817459f84bdc53 diff --git a/source/funkin/modding/events/ScriptEvent.hx b/source/funkin/modding/events/ScriptEvent.hx index dd55de23b..70055b262 100644 --- a/source/funkin/modding/events/ScriptEvent.hx +++ b/source/funkin/modding/events/ScriptEvent.hx @@ -151,7 +151,8 @@ class HitNoteScriptEvent extends NoteScriptEvent public var hitDiff:Float = 0; /** - * If the hit causes a notesplash + * Whether this note hit causes a note splash to display. + * Defaults to true only on "sick" notes. */ public var doesNotesplash:Bool = false; diff --git a/source/funkin/play/character/BaseCharacter.hx b/source/funkin/play/character/BaseCharacter.hx index 4ef86c6a9..980cf2106 100644 --- a/source/funkin/play/character/BaseCharacter.hx +++ b/source/funkin/play/character/BaseCharacter.hx @@ -308,13 +308,26 @@ class BaseCharacter extends Bopper // so we can query which ones are available. this.comboNoteCounts = findCountAnimations('combo'); // example: combo50 this.dropNoteCounts = findCountAnimations('drop'); // example: drop50 - // trace('${this.animation.getNameList()}'); - // trace('Combo note counts: ' + this.comboNoteCounts); - // trace('Drop note counts: ' + this.dropNoteCounts); + if (comboNoteCounts.length > 0) trace('Combo note counts: ' + this.comboNoteCounts); + if (dropNoteCounts.length > 0) trace('Drop note counts: ' + this.dropNoteCounts); super.onCreate(event); } + override function onAnimationFinished(animationName:String):Void + { + super.onAnimationFinished(animationName); + + trace('${characterId} has finished animation: ${animationName}'); + if ((animationName.endsWith(Constants.ANIMATION_END_SUFFIX) && !animationName.startsWith('idle') && !animationName.startsWith('dance')) + || animationName.startsWith('combo') + || animationName.startsWith('drop')) + { + // Force the character to play the idle after the animation ends. + this.dance(true); + } + } + function resetCameraFocusPoint():Void { // Calculate the camera focus point @@ -368,9 +381,11 @@ class BaseCharacter extends Bopper // and Darnell (this keeps the flame on his lighter flickering). // Works for idle, singLEFT/RIGHT/UP/DOWN, alt singing animations, and anything else really. - if (!getCurrentAnimation().endsWith('-hold') && hasAnimation(getCurrentAnimation() + '-hold') && isAnimationFinished()) + if (!getCurrentAnimation().endsWith(Constants.ANIMATION_HOLD_SUFFIX) + && hasAnimation(getCurrentAnimation() + Constants.ANIMATION_HOLD_SUFFIX) + && isAnimationFinished()) { - playAnimation(getCurrentAnimation() + '-hold'); + playAnimation(getCurrentAnimation() + Constants.ANIMATION_HOLD_SUFFIX); } // Handle character note hold time. @@ -395,7 +410,25 @@ class BaseCharacter extends Bopper { trace('holdTimer reached ${holdTimer}sec (> ${singTimeSec}), stopping sing animation'); holdTimer = 0; - dance(true); + + var currentAnimation:String = getCurrentAnimation(); + // Strip "-hold" from the end. + if (currentAnimation.endsWith(Constants.ANIMATION_HOLD_SUFFIX)) currentAnimation = currentAnimation.substring(0, + currentAnimation.length - Constants.ANIMATION_HOLD_SUFFIX.length); + + var endAnimation:String = currentAnimation + Constants.ANIMATION_END_SUFFIX; + if (hasAnimation(endAnimation)) + { + // Play the '-end' animation, if one exists. + trace('${characterId}: playing ${endAnimation}'); + playAnimation(endAnimation); + } + else + { + // Play the idle animation. + trace('${characterId}: attempting dance'); + dance(true); + } } } else @@ -408,7 +441,8 @@ class BaseCharacter extends Bopper public function isSinging():Bool { - return getCurrentAnimation().startsWith('sing'); + var currentAnimation:String = getCurrentAnimation(); + return currentAnimation.startsWith('sing') && !currentAnimation.endsWith(Constants.ANIMATION_END_SUFFIX); } override function dance(force:Bool = false):Void @@ -418,15 +452,15 @@ class BaseCharacter extends Bopper if (!force) { + // Prevent dancing while a singing animation is playing. if (isSinging()) return; + // Prevent dancing while a non-idle special animation is playing. var currentAnimation:String = getCurrentAnimation(); - if ((currentAnimation == 'hey' || currentAnimation == 'cheer') && !isAnimationFinished()) return; + if (!currentAnimation.startsWith('dance') && !currentAnimation.startsWith('idle') && !isAnimationFinished()) return; } - // Prevent dancing while another animation is playing. - if (!force && isSinging()) return; - + trace('${characterId}: Actually dancing'); // Otherwise, fallback to the super dance() method, which handles playing the idle animation. super.dance(); } @@ -499,6 +533,16 @@ class BaseCharacter extends Bopper this.playSingAnimation(event.note.noteData.getDirection(), false); holdTimer = 0; } + else if (characterType == GF && event.note.noteData.getMustHitNote()) + { + switch (event.judgement) + { + case 'sick' | 'good': + playComboAnimation(event.comboCount); + default: + playComboDropAnimation(event.comboCount); + } + } } /** @@ -521,25 +565,40 @@ class BaseCharacter extends Bopper } else if (event.note.noteData.getMustHitNote() && characterType == GF) { - var dropAnim = ''; + playComboDropAnimation(Highscore.tallies.combo); + } + } - // Choose the combo drop anim to play. - // If there are several (for example, drop10 and drop50) the highest one will be used. - // If the combo count is too low, no animation will be played. - for (count in dropNoteCounts) - { - if (event.comboCount >= count) - { - dropAnim = 'drop${count}'; - } - } + function playComboAnimation(comboCount:Int):Void + { + var comboAnim = 'combo${comboCount}'; + if (hasAnimation(comboAnim)) + { + trace('Playing GF combo animation: ${comboAnim}'); + this.playAnimation(comboAnim, true, true); + } + } - if (dropAnim != '') + function playComboDropAnimation(comboCount:Int):Void + { + var dropAnim:Null = null; + + // Choose the combo drop anim to play. + // If there are several (for example, drop10 and drop50) the highest one will be used. + // If the combo count is too low, no animation will be played. + for (count in dropNoteCounts) + { + if (comboCount >= count) { - trace('Playing GF combo drop animation: ${dropAnim}'); - this.playAnimation(dropAnim, true, true); + dropAnim = 'drop${count}'; } } + + if (dropAnim != null) + { + trace('Playing GF combo drop animation: ${dropAnim}'); + this.playAnimation(dropAnim, true, true); + } } /** diff --git a/source/funkin/util/Constants.hx b/source/funkin/util/Constants.hx index 1e0978839..2d4fef1f4 100644 --- a/source/funkin/util/Constants.hx +++ b/source/funkin/util/Constants.hx @@ -283,6 +283,21 @@ class Constants */ public static final DEFAULT_TIME_SIGNATURE_DEN:Int = 4; + /** + * ANIMATIONS + */ + // ============================== + + /** + * A suffix used for animations played when an animation would loop. + */ + public static final ANIMATION_HOLD_SUFFIX:String = '-hold'; + + /** + * A suffix used for animations played when an animation would end before transitioning to another. + */ + public static final ANIMATION_END_SUFFIX:String = '-end'; + /** * TIMING */ From 9d9d7a853cee3e162fb4ddb041e2ed67fddb3701 Mon Sep 17 00:00:00 2001 From: AbnormalPoof Date: Mon, 24 Jun 2024 03:55:59 -0500 Subject: [PATCH 356/870] video cutscene autopause magic --- source/funkin/play/PlayState.hx | 16 ++++++++++++++-- source/funkin/play/cutscene/VideoCutscene.hx | 2 +- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index f55cef388..de8492882 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1301,12 +1301,18 @@ class PlayState extends MusicBeatSubState super.closeSubState(); } - #if discord_rpc /** * Function called when the game window gains focus. */ public override function onFocus():Void { + if (VideoCutscene.isPlaying() && FlxG.autoPause && isGamePaused) VideoCutscene.pauseVideo(); + #if html5 + else + VideoCutscene.resumeVideo(); + #end + + #if discord_rpc if (health > Constants.HEALTH_MIN && !paused && FlxG.autoPause) { if (Conductor.instance.songPosition > 0.0) DiscordClient.changePresence(detailsText, currentSong.song @@ -1318,6 +1324,7 @@ class PlayState extends MusicBeatSubState else DiscordClient.changePresence(detailsText, currentSong.song + ' (' + storyDifficultyText + ')', iconRPC); } + #end super.onFocus(); } @@ -1327,12 +1334,17 @@ class PlayState extends MusicBeatSubState */ public override function onFocusLost():Void { + #if html5 + if (FlxG.autoPause) VideoCutscene.pauseVideo(); + #end + + #if discord_rpc if (health > Constants.HEALTH_MIN && !paused && FlxG.autoPause) DiscordClient.changePresence(detailsPausedText, currentSong.song + ' (' + storyDifficultyText + ')', iconRPC); + #end super.onFocusLost(); } - #end /** * Removes any references to the current stage, then clears the stage cache, diff --git a/source/funkin/play/cutscene/VideoCutscene.hx b/source/funkin/play/cutscene/VideoCutscene.hx index 01a492a77..abbcd4f54 100644 --- a/source/funkin/play/cutscene/VideoCutscene.hx +++ b/source/funkin/play/cutscene/VideoCutscene.hx @@ -145,7 +145,7 @@ class VideoCutscene { vid.zIndex = 0; vid.bitmap.onEndReached.add(finishVideo.bind(0.5)); - vid.autoPause = false; + vid.autoPause = FlxG.autoPause; vid.cameras = [PlayState.instance.camCutscene]; From 6bf28a54165a57cd15beb945b7ac1ac6c7691696 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Thu, 27 Jun 2024 21:05:01 +0200 Subject: [PATCH 357/870] Implement danceEvery for Characters --- source/funkin/play/character/BaseCharacter.hx | 1 + 1 file changed, 1 insertion(+) diff --git a/source/funkin/play/character/BaseCharacter.hx b/source/funkin/play/character/BaseCharacter.hx index 4ef86c6a9..f9e1f00f2 100644 --- a/source/funkin/play/character/BaseCharacter.hx +++ b/source/funkin/play/character/BaseCharacter.hx @@ -180,6 +180,7 @@ class BaseCharacter extends Bopper { this.characterName = _data.name; this.name = _data.name; + this.danceEvery = _data.danceEvery; this.singTimeSteps = _data.singTime; this.globalOffsets = _data.offsets; this.flipX = _data.flipX; From b022581e2321eb0b214f0745ae39e35bf485192a Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 28 Jun 2024 23:25:59 -0400 Subject: [PATCH 358/870] Make danceEvery a float precise up to 0.25 beats (1 step) --- source/funkin/data/stage/StageData.hx | 8 ++--- source/funkin/data/story/level/LevelData.hx | 8 +++-- source/funkin/play/character/BaseCharacter.hx | 2 +- source/funkin/play/character/CharacterData.hx | 36 ++++++++++--------- source/funkin/play/stage/Bopper.hx | 18 ++++++---- 5 files changed, 40 insertions(+), 32 deletions(-) diff --git a/source/funkin/data/stage/StageData.hx b/source/funkin/data/stage/StageData.hx index bebd86d02..eda8e3148 100644 --- a/source/funkin/data/stage/StageData.hx +++ b/source/funkin/data/stage/StageData.hx @@ -140,12 +140,12 @@ typedef StageDataProp = * If not zero, this prop will play an animation every X beats of the song. * This requires animations to be defined. If `danceLeft` and `danceRight` are defined, * they will alternated between, otherwise the `idle` animation will be used. - * - * @default 0 + * Supports up to 0.25 precision. + * @default 0.0 */ - @:default(0) + @:default(0.0) @:optional - var danceEvery:Int; + var danceEvery:Float; /** * How much the prop scrolls relative to the camera. Used to create a parallax effect. diff --git a/source/funkin/data/story/level/LevelData.hx b/source/funkin/data/story/level/LevelData.hx index ceb2cc054..d01689a82 100644 --- a/source/funkin/data/story/level/LevelData.hx +++ b/source/funkin/data/story/level/LevelData.hx @@ -91,11 +91,13 @@ typedef LevelPropData = /** * The frequency to bop at, in beats. - * @default 1 = every beat, 2 = every other beat, etc. + * 1 = every beat, 2 = every other beat, etc. + * Supports up to 0.25 precision. + * @default 0.0 */ - @:default(1) + @:default(0.0) @:optional - var danceEvery:Int; + var danceEvery:Float; /** * The offset on the position to render the prop at. diff --git a/source/funkin/play/character/BaseCharacter.hx b/source/funkin/play/character/BaseCharacter.hx index f9e1f00f2..863fccafa 100644 --- a/source/funkin/play/character/BaseCharacter.hx +++ b/source/funkin/play/character/BaseCharacter.hx @@ -164,7 +164,7 @@ class BaseCharacter extends Bopper public function new(id:String, renderType:CharacterRenderType) { - super(); + super(CharacterDataParser.DEFAULT_DANCEEVERY); this.characterId = id; _data = CharacterDataParser.fetchCharacterData(this.characterId); diff --git a/source/funkin/play/character/CharacterData.hx b/source/funkin/play/character/CharacterData.hx index 8b1649e26..d447eb97f 100644 --- a/source/funkin/play/character/CharacterData.hx +++ b/source/funkin/play/character/CharacterData.hx @@ -383,21 +383,21 @@ class CharacterDataParser * Values that are too high will cause the character to hold their singing pose for too long after they're done. * @default `8 steps` */ - static final DEFAULT_SINGTIME:Float = 8.0; + public static final DEFAULT_SINGTIME:Float = 8.0; - static final DEFAULT_DANCEEVERY:Int = 1; - static final DEFAULT_FLIPX:Bool = false; - static final DEFAULT_FLIPY:Bool = false; - static final DEFAULT_FRAMERATE:Int = 24; - static final DEFAULT_ISPIXEL:Bool = false; - static final DEFAULT_LOOP:Bool = false; - static final DEFAULT_NAME:String = 'Untitled Character'; - static final DEFAULT_OFFSETS:Array = [0, 0]; - static final DEFAULT_HEALTHICON_OFFSETS:Array = [0, 25]; - static final DEFAULT_RENDERTYPE:CharacterRenderType = CharacterRenderType.Sparrow; - static final DEFAULT_SCALE:Float = 1; - static final DEFAULT_SCROLL:Array = [0, 0]; - static final DEFAULT_STARTINGANIM:String = 'idle'; + public static final DEFAULT_DANCEEVERY:Float = 1.0; + public static final DEFAULT_FLIPX:Bool = false; + public static final DEFAULT_FLIPY:Bool = false; + public static final DEFAULT_FRAMERATE:Int = 24; + public static final DEFAULT_ISPIXEL:Bool = false; + public static final DEFAULT_LOOP:Bool = false; + public static final DEFAULT_NAME:String = 'Untitled Character'; + public static final DEFAULT_OFFSETS:Array = [0, 0]; + public static final DEFAULT_HEALTHICON_OFFSETS:Array = [0, 25]; + public static final DEFAULT_RENDERTYPE:CharacterRenderType = CharacterRenderType.Sparrow; + public static final DEFAULT_SCALE:Float = 1; + public static final DEFAULT_SCROLL:Array = [0, 0]; + public static final DEFAULT_STARTINGANIM:String = 'idle'; /** * Set unspecified parameters to their defaults. @@ -665,10 +665,12 @@ typedef CharacterData = /** * The frequency at which the character will play its idle animation, in beats. * Increasing this number will make the character dance less often. - * - * @default 1 + * Supports up to `0.25` precision. + * @default `1.0` on characters */ - var danceEvery:Null; + @:optional + @:default(1.0) + var danceEvery:Null; /** * The minimum duration that a character will play a note animation for, in beats. diff --git a/source/funkin/play/stage/Bopper.hx b/source/funkin/play/stage/Bopper.hx index 11fb9e499..0061e85fb 100644 --- a/source/funkin/play/stage/Bopper.hx +++ b/source/funkin/play/stage/Bopper.hx @@ -19,8 +19,10 @@ class Bopper extends StageProp implements IPlayStateScriptedClass /** * The bopper plays the dance animation once every `danceEvery` beats. * Set to 0 to disable idle animation. + * Supports up to 0.25 precision. + * @default 0.0 on props, 1.0 on characters */ - public var danceEvery:Int = 1; + public var danceEvery:Float = 0.0; /** * Whether the bopper should dance left and right. @@ -110,7 +112,7 @@ class Bopper extends StageProp implements IPlayStateScriptedClass */ var hasDanced:Bool = false; - public function new(danceEvery:Int = 1) + public function new(danceEvery:Float = 0.0) { super(); this.danceEvery = danceEvery; @@ -171,16 +173,20 @@ class Bopper extends StageProp implements IPlayStateScriptedClass } /** - * Called once every beat of the song. + * Called once every step of the song. */ - public function onBeatHit(event:SongTimeScriptEvent):Void + public function onStepHit(event:SongTimeScriptEvent) { - if (danceEvery > 0 && event.beat % danceEvery == 0) + if (danceEvery > 0) trace('step hit(${danceEvery}): ${event.step % (danceEvery * Constants.STEPS_PER_BEAT)} == 0?'); + if (danceEvery > 0 && (event.step % (danceEvery * Constants.STEPS_PER_BEAT)) == 0) { + trace('dance onStepHit!'); dance(shouldBop); } } + public function onBeatHit(event:SongTimeScriptEvent):Void {} + /** * Called every `danceEvery` beats of the song. */ @@ -367,8 +373,6 @@ class Bopper extends StageProp implements IPlayStateScriptedClass public function onNoteGhostMiss(event:GhostMissNoteScriptEvent) {} - public function onStepHit(event:SongTimeScriptEvent) {} - public function onCountdownStart(event:CountdownScriptEvent) {} public function onCountdownStep(event:CountdownScriptEvent) {} From 03eab140f15ca68610892f0720b5c139217522b4 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Thu, 27 Jun 2024 21:00:25 +0200 Subject: [PATCH 359/870] FunkinSound.playOnce return sound --- source/funkin/audio/FunkinSound.hx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index 11b713f4d..c6a9650dd 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -535,11 +535,12 @@ class FunkinSound extends FlxSound implements ICloneable * Play a sound effect once, then destroy it. * @param key * @param volume - * @return static function construct():FunkinSound + * @return A `FunkinSound` object, or `null` if the sound could not be loaded. */ - public static function playOnce(key:String, volume:Float = 1.0, ?onComplete:Void->Void, ?onLoad:Void->Void):Void + public static function playOnce(key:String, volume:Float = 1.0, ?onComplete:Void->Void, ?onLoad:Void->Void):FunkinSound { var result = FunkinSound.load(key, volume, false, true, true, onComplete, onLoad); + return result; } /** From 62501a1dedd444426ed7cd946b70df880940e371 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 29 Jun 2024 00:03:28 -0400 Subject: [PATCH 360/870] Fix null safety 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 c6a9650dd..9cb131c91 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -537,7 +537,7 @@ class FunkinSound extends FlxSound implements ICloneable * @param volume * @return A `FunkinSound` object, or `null` if the sound could not be loaded. */ - public static function playOnce(key:String, volume:Float = 1.0, ?onComplete:Void->Void, ?onLoad:Void->Void):FunkinSound + public static function playOnce(key:String, volume:Float = 1.0, ?onComplete:Void->Void, ?onLoad:Void->Void):Null { var result = FunkinSound.load(key, volume, false, true, true, onComplete, onLoad); return result; From 32deb8d190b4adf1797ad6a1fbe2eb7d9a24e3fb Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Thu, 20 Jun 2024 07:24:36 +0200 Subject: [PATCH 361/870] Fix crash after pressing F5 and coming back from stickers --- source/funkin/ui/freeplay/FreeplayState.hx | 2 +- source/funkin/ui/story/StoryMenuState.hx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 68c63efc4..19bf601e3 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -214,7 +214,7 @@ class FreeplayState extends MusicBeatSubState prepForNewRank = true; } - if (stickers != null) + if (stickers?.members != null) { stickerSubState = stickers; } diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx index 06a83ab4d..7707850ce 100644 --- a/source/funkin/ui/story/StoryMenuState.hx +++ b/source/funkin/ui/story/StoryMenuState.hx @@ -113,7 +113,7 @@ class StoryMenuState extends MusicBeatState { super(); - if (stickers != null) + if (stickers?.members != null) { stickerSubState = stickers; } From 7e6ef61169ed79cefec39cf5539eb96e172dda09 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Sun, 9 Jun 2024 00:29:55 +0200 Subject: [PATCH 362/870] Fix Stack Overflow if song doesn't have "normal" difficulty --- source/funkin/ui/freeplay/FreeplayState.hx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 68c63efc4..a330c5eed 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -2039,6 +2039,8 @@ class FreeplaySongData function set_currentDifficulty(value:String):String { + if (currentDifficulty == value) return value; + currentDifficulty = value; updateValues(displayedVariations); return value; From 55d02d49c2b39a7139b3f69cae5186c7ea9224d2 Mon Sep 17 00:00:00 2001 From: Pixel <146671762+JVNpixels@users.noreply.github.com> Date: Fri, 21 Jun 2024 08:42:51 -0700 Subject: [PATCH 363/870] Update StoryMenuState.hx --- source/funkin/ui/story/StoryMenuState.hx | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx index 06a83ab4d..8623d8f39 100644 --- a/source/funkin/ui/story/StoryMenuState.hx +++ b/source/funkin/ui/story/StoryMenuState.hx @@ -336,6 +336,24 @@ class StoryMenuState extends MusicBeatState changeDifficulty(0); } + #if !html5 + if (FlxG.mouse.wheel != 0) + { + changeLevel(-Math.round(FlxG.mouse.wheel)); + } + #else + if (FlxG.mouse.wheel < 0) + { + changeLevel(-Math.round(FlxG.mouse.wheel / 8)); + } + else if (FlxG.mouse.wheel > 0) + { + changeLevel(-Math.round(FlxG.mouse.wheel / 8)); + } + #end + + // HTML and NON HTML builds mouse fix. + // TODO: Querying UI_RIGHT_P (justPressed) after UI_RIGHT always returns false. Fix it! if (controls.UI_RIGHT_P) { From 90f3a8f2853fdba6124cb0ff874e79186db9512a Mon Sep 17 00:00:00 2001 From: Pixel <146671762+JVNpixels@users.noreply.github.com> Date: Fri, 21 Jun 2024 22:46:07 -0700 Subject: [PATCH 364/870] Update source/funkin/ui/story/StoryMenuState.hx Co-authored-by: gamerbross <55158797+gamerbross@users.noreply.github.com> --- source/funkin/ui/story/StoryMenuState.hx | 1 - 1 file changed, 1 deletion(-) diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx index 8623d8f39..5f21a9a88 100644 --- a/source/funkin/ui/story/StoryMenuState.hx +++ b/source/funkin/ui/story/StoryMenuState.hx @@ -352,7 +352,6 @@ class StoryMenuState extends MusicBeatState } #end - // HTML and NON HTML builds mouse fix. // TODO: Querying UI_RIGHT_P (justPressed) after UI_RIGHT always returns false. Fix it! if (controls.UI_RIGHT_P) From a9c6b9ff8a4533db315c399d4fb216fad3bbc2d1 Mon Sep 17 00:00:00 2001 From: Pixel <146671762+JVNpixels@users.noreply.github.com> Date: Sat, 22 Jun 2024 19:23:40 -0700 Subject: [PATCH 365/870] Extra newline removal. Removes the extra line in code. --- source/funkin/ui/story/StoryMenuState.hx | 1 - 1 file changed, 1 deletion(-) diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx index 5f21a9a88..90786b3f6 100644 --- a/source/funkin/ui/story/StoryMenuState.hx +++ b/source/funkin/ui/story/StoryMenuState.hx @@ -352,7 +352,6 @@ class StoryMenuState extends MusicBeatState } #end - // TODO: Querying UI_RIGHT_P (justPressed) after UI_RIGHT always returns false. Fix it! if (controls.UI_RIGHT_P) { From 09c8a2600ee2d36a6ab23cfd4e68b7227bc15a90 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Sat, 29 Jun 2024 22:54:25 +0200 Subject: [PATCH 366/870] Fix null safety compiling --- source/funkin/audio/FunkinSound.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index 8d2ad9a32..a0175ad4d 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -535,9 +535,9 @@ class FunkinSound extends FlxSound implements ICloneable * @param volume * @return A `FunkinSound` object, or `null` if the sound could not be loaded. */ - public static function playOnce(key:String, volume:Float = 1.0, ?onComplete:Void->Void, ?onLoad:Void->Void):FunkinSound + public static function playOnce(key:String, volume:Float = 1.0, ?onComplete:Void->Void, ?onLoad:Void->Void):Null { - var result = FunkinSound.load(key, volume, false, true, true, onComplete, onLoad); + var result:Null = FunkinSound.load(key, volume, false, true, true, onComplete, onLoad); return result; } From 488fc6888f7d8588866ddcc1310c434365eae2d0 Mon Sep 17 00:00:00 2001 From: FlooferLand! <76737186+FlooferLand@users.noreply.github.com> Date: Mon, 1 Jul 2024 14:42:50 +0300 Subject: [PATCH 367/870] Added new settings items --- source/funkin/ui/options/MenuItemEnums.hx | 10 ++ source/funkin/ui/options/PreferencesMenu.hx | 141 +++++++++++------- .../options/items/CheckboxPreferenceItem.hx | 49 ++++++ .../ui/options/items/EnumPreferenceItem.hx | 84 +++++++++++ .../ui/options/items/NumberPreferenceItem.hx | 136 +++++++++++++++++ 5 files changed, 368 insertions(+), 52 deletions(-) create mode 100644 source/funkin/ui/options/MenuItemEnums.hx create mode 100644 source/funkin/ui/options/items/CheckboxPreferenceItem.hx create mode 100644 source/funkin/ui/options/items/EnumPreferenceItem.hx create mode 100644 source/funkin/ui/options/items/NumberPreferenceItem.hx diff --git a/source/funkin/ui/options/MenuItemEnums.hx b/source/funkin/ui/options/MenuItemEnums.hx new file mode 100644 index 000000000..4513a92af --- /dev/null +++ b/source/funkin/ui/options/MenuItemEnums.hx @@ -0,0 +1,10 @@ +package funkin.ui.options; + +// Add enums for use with `EnumPreferenceItem` here! +/* Example: + class MyOptionEnum + { + public static inline var YuhUh = "true"; // "true" is the value's ID + public static inline var NuhUh = "false"; + } + */ diff --git a/source/funkin/ui/options/PreferencesMenu.hx b/source/funkin/ui/options/PreferencesMenu.hx index 783aef0ba..5fbefceed 100644 --- a/source/funkin/ui/options/PreferencesMenu.hx +++ b/source/funkin/ui/options/PreferencesMenu.hx @@ -8,6 +8,11 @@ import funkin.ui.AtlasText.AtlasFont; import funkin.ui.options.OptionsState.Page; import funkin.graphics.FunkinCamera; import funkin.ui.TextMenuList.TextMenuItem; +import funkin.audio.FunkinSound; +import funkin.ui.options.MenuItemEnums; +import funkin.ui.options.items.CheckboxPreferenceItem; +import funkin.ui.options.items.NumberPreferenceItem; +import funkin.ui.options.items.EnumPreferenceItem; class PreferencesMenu extends Page { @@ -69,11 +74,51 @@ class PreferencesMenu extends Page }, Preferences.autoPause); } + override function update(elapsed:Float):Void + { + super.update(elapsed); + + // Indent the selected item. + items.forEach(function(daItem:TextMenuItem) { + var thyOffset:Int = 0; + + // Initializing thy text width (if thou text present) + var thyTextWidth:Int = 0; + if (Std.isOfType(daItem, EnumPreferenceItem)) thyTextWidth = cast(daItem, EnumPreferenceItem).lefthandText.getWidth(); + else if (Std.isOfType(daItem, NumberPreferenceItem)) thyTextWidth = cast(daItem, NumberPreferenceItem).lefthandText.getWidth(); + + if (thyTextWidth != 0) + { + // Magic number because of the weird offset thats being added by default + thyOffset += thyTextWidth - 75; + } + + if (items.selectedItem == daItem) + { + thyOffset += 150; + } + else + { + thyOffset += 120; + } + + daItem.x = thyOffset; + }); + } + + // - Preference item creation methods - + // Should be moved into a separate PreferenceItems class but you can't access PreferencesMenu.items and PreferencesMenu.preferenceItems from outside. + + /** + * Creates a pref item that works with booleans + * @param onChange Gets called every time the player changes the value; use this to apply the value + * @param defaultValue The value that is loaded in when the pref item is created (usually your Preferences.settingVariable) + */ function createPrefItemCheckbox(prefName:String, prefDesc:String, onChange:Bool->Void, defaultValue:Bool):Void { var checkbox:CheckboxPreferenceItem = new CheckboxPreferenceItem(0, 120 * (items.length - 1 + 1), defaultValue); - items.createItem(120, (120 * items.length) + 30, prefName, AtlasFont.BOLD, function() { + items.createItem(0, (120 * items.length) + 30, prefName, AtlasFont.BOLD, function() { var value = !checkbox.currentValue; onChange(value); checkbox.currentValue = value; @@ -82,62 +127,54 @@ class PreferencesMenu extends Page preferenceItems.add(checkbox); } - override function update(elapsed:Float) + /** + * Creates a pref item that works with general numbers + * @param onChange Gets called every time the player changes the value; use this to apply the value + * @param valueFormatter Will get called every time the game needs to display the float value; use this to change how the displayed value looks + * @param defaultValue The value that is loaded in when the pref item is created (usually your Preferences.settingVariable) + * @param min Minimum value (example: 0) + * @param max Maximum value (example: 10) + * @param step The value to increment/decrement by (default = 0.1) + * @param precision Rounds decimals up to a `precision` amount of digits (ex: 4 -> 0.1234, 2 -> 0.12) + */ + function createPrefItemNumber(prefName:String, prefDesc:String, onChange:Float->Void, ?valueFormatter:Float->String, defaultValue:Int, min:Int, max:Int, + step:Float = 0.1, precision:Int):Void { - super.update(elapsed); + var item = new NumberPreferenceItem(0, (120 * items.length) + 30, prefName, defaultValue, min, max, step, precision, onChange, valueFormatter); + items.addItem(prefName, item); + preferenceItems.add(item.lefthandText); + } - // Indent the selected item. - // TODO: Only do this on menu change? - items.forEach(function(daItem:TextMenuItem) { - if (items.selectedItem == daItem) daItem.x = 150; - else - daItem.x = 120; - }); - } -} - -class CheckboxPreferenceItem extends FlxSprite -{ - public var currentValue(default, set):Bool; - - public function new(x:Float, y:Float, defaultValue:Bool = false) + /** + * Creates a pref item that works with number percentages + * @param onChange Gets called every time the player changes the value; use this to apply the value + * @param defaultValue The value that is loaded in when the pref item is created (usually your Preferences.settingVariable) + * @param min Minimum value (default = 0) + * @param max Maximum value (default = 100) + */ + function createPrefItemPercentage(prefName:String, prefDesc:String, onChange:Int->Void, defaultValue:Int, min:Int = 0, max:Int = 100):Void { - super(x, y); - - frames = Paths.getSparrowAtlas('checkboxThingie'); - animation.addByPrefix('static', 'Check Box unselected', 24, false); - animation.addByPrefix('checked', 'Check Box selecting animation', 24, false); - - setGraphicSize(Std.int(width * 0.7)); - updateHitbox(); - - this.currentValue = defaultValue; + var newCallback = function(value:Float) { + onChange(Std.int(value)); + }; + var formatter = function(value:Float) { + return '${value}%'; + }; + var item = new NumberPreferenceItem(0, (120 * items.length) + 30, prefName, defaultValue, min, max, 10, 0, newCallback, formatter); + items.addItem(prefName, item); + preferenceItems.add(item.lefthandText); } - override function update(elapsed:Float) + /** + * Creates a pref item that works with enums + * @param values Maps enum values to display strings _(ex: `NoteHitSoundType.PingPong => "Ping pong"`)_ + * @param onChange Gets called every time the player changes the value; use this to apply the value + * @param defaultValue The value that is loaded in when the pref item is created (usually your Preferences.settingVariable) + */ + function createPrefItemEnum(prefName:String, prefDesc:String, values:Map, onChange:String->Void, defaultValue:String):Void { - super.update(elapsed); - - switch (animation.curAnim.name) - { - case 'static': - offset.set(); - case 'checked': - offset.set(17, 70); - } - } - - function set_currentValue(value:Bool):Bool - { - if (value) - { - animation.play('checked', true); - } - else - { - animation.play('static'); - } - - return currentValue = value; + var item = new EnumPreferenceItem(0, (120 * items.length) + 30, prefName, values, defaultValue, onChange); + items.addItem(prefName, item); + preferenceItems.add(item.lefthandText); } } diff --git a/source/funkin/ui/options/items/CheckboxPreferenceItem.hx b/source/funkin/ui/options/items/CheckboxPreferenceItem.hx new file mode 100644 index 000000000..88c4fb6b0 --- /dev/null +++ b/source/funkin/ui/options/items/CheckboxPreferenceItem.hx @@ -0,0 +1,49 @@ +package funkin.ui.options.items; + +import flixel.FlxSprite.FlxSprite; + +class CheckboxPreferenceItem extends FlxSprite +{ + public var currentValue(default, set):Bool; + + public function new(x:Float, y:Float, defaultValue:Bool = false) + { + super(x, y); + + frames = Paths.getSparrowAtlas('checkboxThingie'); + animation.addByPrefix('static', 'Check Box unselected', 24, false); + animation.addByPrefix('checked', 'Check Box selecting animation', 24, false); + + setGraphicSize(Std.int(width * 0.7)); + updateHitbox(); + + this.currentValue = defaultValue; + } + + override function update(elapsed:Float) + { + super.update(elapsed); + + switch (animation.curAnim.name) + { + case 'static': + offset.set(); + case 'checked': + offset.set(17, 70); + } + } + + function set_currentValue(value:Bool):Bool + { + if (value) + { + animation.play('checked', true); + } + else + { + animation.play('static'); + } + + return currentValue = value; + } +} diff --git a/source/funkin/ui/options/items/EnumPreferenceItem.hx b/source/funkin/ui/options/items/EnumPreferenceItem.hx new file mode 100644 index 000000000..02a273353 --- /dev/null +++ b/source/funkin/ui/options/items/EnumPreferenceItem.hx @@ -0,0 +1,84 @@ +package funkin.ui.options.items; + +import funkin.ui.TextMenuList; +import funkin.ui.AtlasText; +import funkin.input.Controls; +import funkin.ui.options.MenuItemEnums; +import haxe.EnumTools; + +/** + * Preference item that allows the player to pick a value from an enum (list of values) + */ +class EnumPreferenceItem extends TextMenuItem +{ + function controls():Controls + { + return PlayerSettings.player1.controls; + } + + public var lefthandText:AtlasText; + + public var currentValue:String; + public var onChangeCallback:NullVoid>; + public var map:Map; + public var keys:Array = []; + + var index = 0; + + public function new(x:Float, y:Float, name:String, map:Map, defaultValue:String, ?callback:String->Void) + { + super(x, y, name, function() { + callback(this.currentValue); + }); + + updateHitbox(); + + this.map = map; + this.currentValue = defaultValue; + this.onChangeCallback = callback; + + var i:Int = 0; + for (key in map.keys()) + { + this.keys.push(key); + if (this.currentValue == key) index = i; + i += 1; + } + + lefthandText = new AtlasText(15, y, formatted(defaultValue), AtlasFont.DEFAULT); + } + + override function update(elapsed:Float):Void + { + super.update(elapsed); + + // var fancyTextFancyColor:Color; + if (selected) + { + var shouldDecrease:Bool = controls().UI_LEFT_P; + var shouldIncrease:Bool = controls().UI_RIGHT_P; + + if (shouldDecrease) index -= 1; + if (shouldIncrease) index += 1; + + if (index > keys.length - 1) index = 0; + if (index < 0) index = keys.length - 1; + + currentValue = keys[index]; + if (onChangeCallback != null && (shouldIncrease || shouldDecrease)) + { + onChangeCallback(currentValue); + } + } + + lefthandText.text = formatted(currentValue); + } + + function formatted(value:String):String + { + // FIXME: Can't add arrows around the text because the font doesn't support < > + // var leftArrow:String = selected ? '<' : ''; + // var rightArrow:String = selected ? '>' : ''; + return '${map.get(value) ?? value}'; + } +} diff --git a/source/funkin/ui/options/items/NumberPreferenceItem.hx b/source/funkin/ui/options/items/NumberPreferenceItem.hx new file mode 100644 index 000000000..f3cd3cd46 --- /dev/null +++ b/source/funkin/ui/options/items/NumberPreferenceItem.hx @@ -0,0 +1,136 @@ +package funkin.ui.options.items; + +import funkin.ui.TextMenuList; +import funkin.ui.AtlasText; +import funkin.input.Controls; + +/** + * Preference item that allows the player to pick a value between min and max + */ +class NumberPreferenceItem extends TextMenuItem +{ + function controls():Controls + { + return PlayerSettings.player1.controls; + } + + // Widgets + public var lefthandText:AtlasText; + + // Constants + static final HOLD_DELAY:Float = 0.3; // seconds + static final CHANGE_RATE:Float = 0.08; // seconds + + // Constructor-initialized variables + public var currentValue:Float; + public var min:Float; + public var max:Float; + public var step:Float; + public var precision:Int; + public var onChangeCallback:NullVoid>; + public var valueFormatter:NullString>; + + // Variables + var holdDelayTimer:Float = HOLD_DELAY; // seconds + var changeRateTimer:Float = 0.0; // seconds + + /** + * @param min Minimum value (example: 0) + * @param max Maximum value (example: 100) + * @param step The value to increment/decrement by (example: 10) + * @param callback Will get called every time the user changes the setting; use this to apply/save the setting. + * @param valueFormatter Will get called every time the game needs to display the float value; use this to change how the displayed string looks + */ + public function new(x:Float, y:Float, name:String, defaultValue:Float, min:Float, max:Float, step:Float, precision:Int, ?callback:Float->Void, + ?valueFormatter:Float->String):Void + { + super(x, y, name, function() { + callback(this.currentValue); + }); + lefthandText = new AtlasText(15, y, formatted(defaultValue), AtlasFont.DEFAULT); + + updateHitbox(); + + this.currentValue = defaultValue; + this.min = min; + this.max = max; + this.step = step; + this.precision = precision; + this.onChangeCallback = callback; + this.valueFormatter = valueFormatter; + } + + override function update(elapsed:Float):Void + { + super.update(elapsed); + + // var fancyTextFancyColor:Color; + if (selected) + { + holdDelayTimer -= elapsed; + if (holdDelayTimer <= 0.0) + { + changeRateTimer -= elapsed; + } + + var jpLeft:Bool = controls().UI_LEFT_P; + var jpRight:Bool = controls().UI_RIGHT_P; + + if (jpLeft || jpRight) + { + holdDelayTimer = HOLD_DELAY; + changeRateTimer = 0.0; + } + + var shouldDecrease:Bool = jpLeft; + var shouldIncrease:Bool = jpRight; + + if (controls().UI_LEFT && holdDelayTimer <= 0.0 && changeRateTimer <= 0.0) + { + shouldDecrease = true; + changeRateTimer = CHANGE_RATE; + } + else if (controls().UI_RIGHT && holdDelayTimer <= 0.0 && changeRateTimer <= 0.0) + { + shouldIncrease = true; + changeRateTimer = CHANGE_RATE; + } + + // Actually increasing/decreasing the value + if (shouldDecrease) + { + var isBelowMin:Bool = currentValue - step < min; + currentValue = (currentValue - step).clamp(min, max); + if (onChangeCallback != null && !isBelowMin) onChangeCallback(currentValue); + } + else if (shouldIncrease) + { + var isAboveMax:Bool = currentValue + step > max; + currentValue = (currentValue + step).clamp(min, max); + if (onChangeCallback != null && !isAboveMax) onChangeCallback(currentValue); + } + } + + lefthandText.text = formatted(currentValue); + } + + /** Turns the float into a string */ + function formatted(value:Float):String + { + var float:Float = toFixed(value); + if (valueFormatter != null) + { + return valueFormatter(float); + } + else + { + return '${float}'; + } + } + + function toFixed(value:Float):Float + { + var multiplier:Float = Math.pow(10, precision); + return Math.floor(value * multiplier) / multiplier; + } +} From be5e0aafeb68b366db11227f72befb99d4e7b2f4 Mon Sep 17 00:00:00 2001 From: FlooferLand! <76737186+FlooferLand@users.noreply.github.com> Date: Mon, 1 Jul 2024 14:44:23 +0300 Subject: [PATCH 368/870] Added getWidth --- source/funkin/ui/AtlasText.hx | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/source/funkin/ui/AtlasText.hx b/source/funkin/ui/AtlasText.hx index 186d87c2a..ef74abc1e 100644 --- a/source/funkin/ui/AtlasText.hx +++ b/source/funkin/ui/AtlasText.hx @@ -152,6 +152,32 @@ class AtlasText extends FlxTypedSpriteGroup } } + public function getWidth():Int + { + var width = 0; + for (char in this.text.split("")) + { + switch (char) + { + case " ": + { + width += 40; + } + case "\n": + {} + case char: + { + var sprite = new AtlasChar(atlas, char); + sprite.revive(); + sprite.char = char; + sprite.alpha = 1; + width += Std.int(sprite.width); + } + } + } + return width; + } + override function toString() { return "InputItem, " + FlxStringUtil.getDebugString([ From 2916bd6ff7ec9f1e136d84323d8880ca009a3f4e Mon Sep 17 00:00:00 2001 From: Hundrec Date: Fri, 14 Jun 2024 21:52:52 -0700 Subject: [PATCH 369/870] Reorder download Git step in compiling guide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moved “download Git” from the middle of the guide to the setup step Should prevent errors with Git before installing Git --- docs/COMPILING.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index e7c19875a..b8ddee4a7 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -2,14 +2,14 @@ 0. Setup - Download Haxe from [Haxe.org](https://haxe.org) + - Download Git from [git-scm.com](https://www.git-scm.com) 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. 2. Install `hmm` (run `haxelib --global install hmm` and then `haxelib --global run hmm 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 +3. Install all haxelibs of the current branch by running `hmm install` +4. Setup lime: `haxelib run lime setup` +5. 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 @@ -17,8 +17,8 @@ - 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 -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). +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 From 9fb4a8719a6cd07aa2af2638adc494786ca5425e Mon Sep 17 00:00:00 2001 From: Hundrec Date: Sat, 15 Jun 2024 13:37:21 -0400 Subject: [PATCH 370/870] Add ZIP button warning and restructured sentences Each step should be easier to follow with this structure --- docs/COMPILING.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index b8ddee4a7..b2a106c86 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -3,12 +3,13 @@ 0. Setup - Download Haxe from [Haxe.org](https://haxe.org) - Download Git from [git-scm.com](https://www.git-scm.com) -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. -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` + - Do NOT download the repository using the Download ZIP button on GitHub or you may run into errors! + - Instead, open a command prompt and do the following steps... +1. Run `git clone --recurse-submodules https://github.com/FunkinCrew/funkin.git` to clone the repository with the necessary assets submodule + - _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. Run `haxelib --global install hmm` and then `haxelib --global run hmm setup` to install hmm.json +3. Run `hmm install` to install all haxelibs of the current branch +4. Run `haxelib run lime setup` to set up lime 5. 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: From 841a61408c13ff34760a448c588e35bc3b203bf0 Mon Sep 17 00:00:00 2001 From: Eric Date: Sun, 16 Jun 2024 18:48:01 -0400 Subject: [PATCH 371/870] Make downloading the assets submodule a separate step. --- docs/COMPILING.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index b2a106c86..cc90bd348 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -5,8 +5,9 @@ - Download Git from [git-scm.com](https://www.git-scm.com) - Do NOT download the repository using the Download ZIP button on GitHub or you may run into errors! - Instead, open a command prompt and do the following steps... -1. Run `git clone --recurse-submodules https://github.com/FunkinCrew/funkin.git` to clone the repository with the necessary assets submodule - - _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._ +1. Run `git clone https://github.com/FunkinCrew/funkin.git` to clone the base repository. +2. Run `git submodule update --init --recursive` to download the game's assets. + - NOTE: By performing this operation, you are downloading Content which is proprietary and protected by national and international copyright and trademark laws. See [the LICENSE.md file for the Funkin.assets](https://github.com/FunkinCrew/funkin.assets/blob/main/LICENSE.md) repo for more information. 2. Run `haxelib --global install hmm` and then `haxelib --global run hmm setup` to install hmm.json 3. Run `hmm install` to install all haxelibs of the current branch 4. Run `haxelib run lime setup` to set up lime From 8a4f19d603b5900692c8c646c05e8b409688e963 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 25 Jun 2024 18:22:30 -0400 Subject: [PATCH 372/870] Add change counts labels to Actions labeler --- .github/changed-lines-count-labeler.yml | 12 ++++++++++++ .github/workflows/labeler.yml | 15 ++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 .github/changed-lines-count-labeler.yml diff --git a/.github/changed-lines-count-labeler.yml b/.github/changed-lines-count-labeler.yml new file mode 100644 index 000000000..6f890f534 --- /dev/null +++ b/.github/changed-lines-count-labeler.yml @@ -0,0 +1,12 @@ +# Add 'small' to any changes below 10 lines +small: + max: 9 + +# Add 'medium' to any changes between 10 and 100 lines +medium: + min: 10 + max: 99 + +# Add 'large' to any changes for more than 100 lines +large: + min: 100 diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 0bcc420d3..a861af578 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -9,6 +9,19 @@ jobs: pull-requests: write runs-on: ubuntu-latest steps: - - uses: actions/labeler@v5 + - name: Set basic labels + uses: actions/labeler@v5 with: sync-labels: true + changed-lines-count-labeler: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + name: An action for automatically labelling pull requests based on the changed lines count + steps: + - name: Set change count labels + uses: vkirilichev/changed-lines-count-labeler@v0.2 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + configuration-path: .github/changed-lines-count-labeler.yml From fbc78adb65c7db8b045f1ea5d6599ae7348912a0 Mon Sep 17 00:00:00 2001 From: FlooferLand! <76737186+FlooferLand@users.noreply.github.com> Date: Mon, 1 Jul 2024 14:42:50 +0300 Subject: [PATCH 373/870] Added new settings items --- source/funkin/ui/options/MenuItemEnums.hx | 10 ++ source/funkin/ui/options/PreferencesMenu.hx | 141 +++++++++++------- .../options/items/CheckboxPreferenceItem.hx | 49 ++++++ .../ui/options/items/EnumPreferenceItem.hx | 84 +++++++++++ .../ui/options/items/NumberPreferenceItem.hx | 136 +++++++++++++++++ 5 files changed, 368 insertions(+), 52 deletions(-) create mode 100644 source/funkin/ui/options/MenuItemEnums.hx create mode 100644 source/funkin/ui/options/items/CheckboxPreferenceItem.hx create mode 100644 source/funkin/ui/options/items/EnumPreferenceItem.hx create mode 100644 source/funkin/ui/options/items/NumberPreferenceItem.hx diff --git a/source/funkin/ui/options/MenuItemEnums.hx b/source/funkin/ui/options/MenuItemEnums.hx new file mode 100644 index 000000000..4513a92af --- /dev/null +++ b/source/funkin/ui/options/MenuItemEnums.hx @@ -0,0 +1,10 @@ +package funkin.ui.options; + +// Add enums for use with `EnumPreferenceItem` here! +/* Example: + class MyOptionEnum + { + public static inline var YuhUh = "true"; // "true" is the value's ID + public static inline var NuhUh = "false"; + } + */ diff --git a/source/funkin/ui/options/PreferencesMenu.hx b/source/funkin/ui/options/PreferencesMenu.hx index 783aef0ba..5fbefceed 100644 --- a/source/funkin/ui/options/PreferencesMenu.hx +++ b/source/funkin/ui/options/PreferencesMenu.hx @@ -8,6 +8,11 @@ import funkin.ui.AtlasText.AtlasFont; import funkin.ui.options.OptionsState.Page; import funkin.graphics.FunkinCamera; import funkin.ui.TextMenuList.TextMenuItem; +import funkin.audio.FunkinSound; +import funkin.ui.options.MenuItemEnums; +import funkin.ui.options.items.CheckboxPreferenceItem; +import funkin.ui.options.items.NumberPreferenceItem; +import funkin.ui.options.items.EnumPreferenceItem; class PreferencesMenu extends Page { @@ -69,11 +74,51 @@ class PreferencesMenu extends Page }, Preferences.autoPause); } + override function update(elapsed:Float):Void + { + super.update(elapsed); + + // Indent the selected item. + items.forEach(function(daItem:TextMenuItem) { + var thyOffset:Int = 0; + + // Initializing thy text width (if thou text present) + var thyTextWidth:Int = 0; + if (Std.isOfType(daItem, EnumPreferenceItem)) thyTextWidth = cast(daItem, EnumPreferenceItem).lefthandText.getWidth(); + else if (Std.isOfType(daItem, NumberPreferenceItem)) thyTextWidth = cast(daItem, NumberPreferenceItem).lefthandText.getWidth(); + + if (thyTextWidth != 0) + { + // Magic number because of the weird offset thats being added by default + thyOffset += thyTextWidth - 75; + } + + if (items.selectedItem == daItem) + { + thyOffset += 150; + } + else + { + thyOffset += 120; + } + + daItem.x = thyOffset; + }); + } + + // - Preference item creation methods - + // Should be moved into a separate PreferenceItems class but you can't access PreferencesMenu.items and PreferencesMenu.preferenceItems from outside. + + /** + * Creates a pref item that works with booleans + * @param onChange Gets called every time the player changes the value; use this to apply the value + * @param defaultValue The value that is loaded in when the pref item is created (usually your Preferences.settingVariable) + */ function createPrefItemCheckbox(prefName:String, prefDesc:String, onChange:Bool->Void, defaultValue:Bool):Void { var checkbox:CheckboxPreferenceItem = new CheckboxPreferenceItem(0, 120 * (items.length - 1 + 1), defaultValue); - items.createItem(120, (120 * items.length) + 30, prefName, AtlasFont.BOLD, function() { + items.createItem(0, (120 * items.length) + 30, prefName, AtlasFont.BOLD, function() { var value = !checkbox.currentValue; onChange(value); checkbox.currentValue = value; @@ -82,62 +127,54 @@ class PreferencesMenu extends Page preferenceItems.add(checkbox); } - override function update(elapsed:Float) + /** + * Creates a pref item that works with general numbers + * @param onChange Gets called every time the player changes the value; use this to apply the value + * @param valueFormatter Will get called every time the game needs to display the float value; use this to change how the displayed value looks + * @param defaultValue The value that is loaded in when the pref item is created (usually your Preferences.settingVariable) + * @param min Minimum value (example: 0) + * @param max Maximum value (example: 10) + * @param step The value to increment/decrement by (default = 0.1) + * @param precision Rounds decimals up to a `precision` amount of digits (ex: 4 -> 0.1234, 2 -> 0.12) + */ + function createPrefItemNumber(prefName:String, prefDesc:String, onChange:Float->Void, ?valueFormatter:Float->String, defaultValue:Int, min:Int, max:Int, + step:Float = 0.1, precision:Int):Void { - super.update(elapsed); + var item = new NumberPreferenceItem(0, (120 * items.length) + 30, prefName, defaultValue, min, max, step, precision, onChange, valueFormatter); + items.addItem(prefName, item); + preferenceItems.add(item.lefthandText); + } - // Indent the selected item. - // TODO: Only do this on menu change? - items.forEach(function(daItem:TextMenuItem) { - if (items.selectedItem == daItem) daItem.x = 150; - else - daItem.x = 120; - }); - } -} - -class CheckboxPreferenceItem extends FlxSprite -{ - public var currentValue(default, set):Bool; - - public function new(x:Float, y:Float, defaultValue:Bool = false) + /** + * Creates a pref item that works with number percentages + * @param onChange Gets called every time the player changes the value; use this to apply the value + * @param defaultValue The value that is loaded in when the pref item is created (usually your Preferences.settingVariable) + * @param min Minimum value (default = 0) + * @param max Maximum value (default = 100) + */ + function createPrefItemPercentage(prefName:String, prefDesc:String, onChange:Int->Void, defaultValue:Int, min:Int = 0, max:Int = 100):Void { - super(x, y); - - frames = Paths.getSparrowAtlas('checkboxThingie'); - animation.addByPrefix('static', 'Check Box unselected', 24, false); - animation.addByPrefix('checked', 'Check Box selecting animation', 24, false); - - setGraphicSize(Std.int(width * 0.7)); - updateHitbox(); - - this.currentValue = defaultValue; + var newCallback = function(value:Float) { + onChange(Std.int(value)); + }; + var formatter = function(value:Float) { + return '${value}%'; + }; + var item = new NumberPreferenceItem(0, (120 * items.length) + 30, prefName, defaultValue, min, max, 10, 0, newCallback, formatter); + items.addItem(prefName, item); + preferenceItems.add(item.lefthandText); } - override function update(elapsed:Float) + /** + * Creates a pref item that works with enums + * @param values Maps enum values to display strings _(ex: `NoteHitSoundType.PingPong => "Ping pong"`)_ + * @param onChange Gets called every time the player changes the value; use this to apply the value + * @param defaultValue The value that is loaded in when the pref item is created (usually your Preferences.settingVariable) + */ + function createPrefItemEnum(prefName:String, prefDesc:String, values:Map, onChange:String->Void, defaultValue:String):Void { - super.update(elapsed); - - switch (animation.curAnim.name) - { - case 'static': - offset.set(); - case 'checked': - offset.set(17, 70); - } - } - - function set_currentValue(value:Bool):Bool - { - if (value) - { - animation.play('checked', true); - } - else - { - animation.play('static'); - } - - return currentValue = value; + var item = new EnumPreferenceItem(0, (120 * items.length) + 30, prefName, values, defaultValue, onChange); + items.addItem(prefName, item); + preferenceItems.add(item.lefthandText); } } diff --git a/source/funkin/ui/options/items/CheckboxPreferenceItem.hx b/source/funkin/ui/options/items/CheckboxPreferenceItem.hx new file mode 100644 index 000000000..88c4fb6b0 --- /dev/null +++ b/source/funkin/ui/options/items/CheckboxPreferenceItem.hx @@ -0,0 +1,49 @@ +package funkin.ui.options.items; + +import flixel.FlxSprite.FlxSprite; + +class CheckboxPreferenceItem extends FlxSprite +{ + public var currentValue(default, set):Bool; + + public function new(x:Float, y:Float, defaultValue:Bool = false) + { + super(x, y); + + frames = Paths.getSparrowAtlas('checkboxThingie'); + animation.addByPrefix('static', 'Check Box unselected', 24, false); + animation.addByPrefix('checked', 'Check Box selecting animation', 24, false); + + setGraphicSize(Std.int(width * 0.7)); + updateHitbox(); + + this.currentValue = defaultValue; + } + + override function update(elapsed:Float) + { + super.update(elapsed); + + switch (animation.curAnim.name) + { + case 'static': + offset.set(); + case 'checked': + offset.set(17, 70); + } + } + + function set_currentValue(value:Bool):Bool + { + if (value) + { + animation.play('checked', true); + } + else + { + animation.play('static'); + } + + return currentValue = value; + } +} diff --git a/source/funkin/ui/options/items/EnumPreferenceItem.hx b/source/funkin/ui/options/items/EnumPreferenceItem.hx new file mode 100644 index 000000000..02a273353 --- /dev/null +++ b/source/funkin/ui/options/items/EnumPreferenceItem.hx @@ -0,0 +1,84 @@ +package funkin.ui.options.items; + +import funkin.ui.TextMenuList; +import funkin.ui.AtlasText; +import funkin.input.Controls; +import funkin.ui.options.MenuItemEnums; +import haxe.EnumTools; + +/** + * Preference item that allows the player to pick a value from an enum (list of values) + */ +class EnumPreferenceItem extends TextMenuItem +{ + function controls():Controls + { + return PlayerSettings.player1.controls; + } + + public var lefthandText:AtlasText; + + public var currentValue:String; + public var onChangeCallback:NullVoid>; + public var map:Map; + public var keys:Array = []; + + var index = 0; + + public function new(x:Float, y:Float, name:String, map:Map, defaultValue:String, ?callback:String->Void) + { + super(x, y, name, function() { + callback(this.currentValue); + }); + + updateHitbox(); + + this.map = map; + this.currentValue = defaultValue; + this.onChangeCallback = callback; + + var i:Int = 0; + for (key in map.keys()) + { + this.keys.push(key); + if (this.currentValue == key) index = i; + i += 1; + } + + lefthandText = new AtlasText(15, y, formatted(defaultValue), AtlasFont.DEFAULT); + } + + override function update(elapsed:Float):Void + { + super.update(elapsed); + + // var fancyTextFancyColor:Color; + if (selected) + { + var shouldDecrease:Bool = controls().UI_LEFT_P; + var shouldIncrease:Bool = controls().UI_RIGHT_P; + + if (shouldDecrease) index -= 1; + if (shouldIncrease) index += 1; + + if (index > keys.length - 1) index = 0; + if (index < 0) index = keys.length - 1; + + currentValue = keys[index]; + if (onChangeCallback != null && (shouldIncrease || shouldDecrease)) + { + onChangeCallback(currentValue); + } + } + + lefthandText.text = formatted(currentValue); + } + + function formatted(value:String):String + { + // FIXME: Can't add arrows around the text because the font doesn't support < > + // var leftArrow:String = selected ? '<' : ''; + // var rightArrow:String = selected ? '>' : ''; + return '${map.get(value) ?? value}'; + } +} diff --git a/source/funkin/ui/options/items/NumberPreferenceItem.hx b/source/funkin/ui/options/items/NumberPreferenceItem.hx new file mode 100644 index 000000000..f3cd3cd46 --- /dev/null +++ b/source/funkin/ui/options/items/NumberPreferenceItem.hx @@ -0,0 +1,136 @@ +package funkin.ui.options.items; + +import funkin.ui.TextMenuList; +import funkin.ui.AtlasText; +import funkin.input.Controls; + +/** + * Preference item that allows the player to pick a value between min and max + */ +class NumberPreferenceItem extends TextMenuItem +{ + function controls():Controls + { + return PlayerSettings.player1.controls; + } + + // Widgets + public var lefthandText:AtlasText; + + // Constants + static final HOLD_DELAY:Float = 0.3; // seconds + static final CHANGE_RATE:Float = 0.08; // seconds + + // Constructor-initialized variables + public var currentValue:Float; + public var min:Float; + public var max:Float; + public var step:Float; + public var precision:Int; + public var onChangeCallback:NullVoid>; + public var valueFormatter:NullString>; + + // Variables + var holdDelayTimer:Float = HOLD_DELAY; // seconds + var changeRateTimer:Float = 0.0; // seconds + + /** + * @param min Minimum value (example: 0) + * @param max Maximum value (example: 100) + * @param step The value to increment/decrement by (example: 10) + * @param callback Will get called every time the user changes the setting; use this to apply/save the setting. + * @param valueFormatter Will get called every time the game needs to display the float value; use this to change how the displayed string looks + */ + public function new(x:Float, y:Float, name:String, defaultValue:Float, min:Float, max:Float, step:Float, precision:Int, ?callback:Float->Void, + ?valueFormatter:Float->String):Void + { + super(x, y, name, function() { + callback(this.currentValue); + }); + lefthandText = new AtlasText(15, y, formatted(defaultValue), AtlasFont.DEFAULT); + + updateHitbox(); + + this.currentValue = defaultValue; + this.min = min; + this.max = max; + this.step = step; + this.precision = precision; + this.onChangeCallback = callback; + this.valueFormatter = valueFormatter; + } + + override function update(elapsed:Float):Void + { + super.update(elapsed); + + // var fancyTextFancyColor:Color; + if (selected) + { + holdDelayTimer -= elapsed; + if (holdDelayTimer <= 0.0) + { + changeRateTimer -= elapsed; + } + + var jpLeft:Bool = controls().UI_LEFT_P; + var jpRight:Bool = controls().UI_RIGHT_P; + + if (jpLeft || jpRight) + { + holdDelayTimer = HOLD_DELAY; + changeRateTimer = 0.0; + } + + var shouldDecrease:Bool = jpLeft; + var shouldIncrease:Bool = jpRight; + + if (controls().UI_LEFT && holdDelayTimer <= 0.0 && changeRateTimer <= 0.0) + { + shouldDecrease = true; + changeRateTimer = CHANGE_RATE; + } + else if (controls().UI_RIGHT && holdDelayTimer <= 0.0 && changeRateTimer <= 0.0) + { + shouldIncrease = true; + changeRateTimer = CHANGE_RATE; + } + + // Actually increasing/decreasing the value + if (shouldDecrease) + { + var isBelowMin:Bool = currentValue - step < min; + currentValue = (currentValue - step).clamp(min, max); + if (onChangeCallback != null && !isBelowMin) onChangeCallback(currentValue); + } + else if (shouldIncrease) + { + var isAboveMax:Bool = currentValue + step > max; + currentValue = (currentValue + step).clamp(min, max); + if (onChangeCallback != null && !isAboveMax) onChangeCallback(currentValue); + } + } + + lefthandText.text = formatted(currentValue); + } + + /** Turns the float into a string */ + function formatted(value:Float):String + { + var float:Float = toFixed(value); + if (valueFormatter != null) + { + return valueFormatter(float); + } + else + { + return '${float}'; + } + } + + function toFixed(value:Float):Float + { + var multiplier:Float = Math.pow(10, precision); + return Math.floor(value * multiplier) / multiplier; + } +} From cd08116aed64f4761087e287a00786b77f40d02b Mon Sep 17 00:00:00 2001 From: FlooferLand! <76737186+FlooferLand@users.noreply.github.com> Date: Mon, 1 Jul 2024 14:44:23 +0300 Subject: [PATCH 374/870] Added getWidth --- source/funkin/ui/AtlasText.hx | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/source/funkin/ui/AtlasText.hx b/source/funkin/ui/AtlasText.hx index 186d87c2a..ef74abc1e 100644 --- a/source/funkin/ui/AtlasText.hx +++ b/source/funkin/ui/AtlasText.hx @@ -152,6 +152,32 @@ class AtlasText extends FlxTypedSpriteGroup } } + public function getWidth():Int + { + var width = 0; + for (char in this.text.split("")) + { + switch (char) + { + case " ": + { + width += 40; + } + case "\n": + {} + case char: + { + var sprite = new AtlasChar(atlas, char); + sprite.revive(); + sprite.char = char; + sprite.alpha = 1; + width += Std.int(sprite.width); + } + } + } + return width; + } + override function toString() { return "InputItem, " + FlxStringUtil.getDebugString([ From 432c7090750d7abefad68b411ac83bb99543682b Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 27 Jun 2024 19:50:38 -0400 Subject: [PATCH 375/870] Animated pixel icons for freeplay mend --- assets | 2 +- source/funkin/ui/freeplay/FreeplayState.hx | 2 +- source/funkin/ui/freeplay/SongMenuItem.hx | 42 ++++++++++++++++++++-- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/assets b/assets index 225e248f1..c274cf6d5 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 225e248f148a92500a6fe90e4f10e4cd2acee782 +Subproject commit c274cf6d5a9d7e9e275f1f22d87d628eb379da5b diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 68c63efc4..eae123401 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1738,7 +1738,7 @@ class FreeplayState extends MusicBeatSubState dj.confirm(); grpCapsules.members[curSelected].forcePosition(); - grpCapsules.members[curSelected].songText.flickerText(); + grpCapsules.members[curSelected].confirm(); // FlxTween.color(bgDad, 0.33, 0xFFFFFFFF, 0xFF555555, {ease: FlxEase.quadOut}); FlxTween.color(pinkBack, 0.33, 0xFFFFD0D5, 0xFF171831, {ease: FlxEase.quadOut}); diff --git a/source/funkin/ui/freeplay/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx index 65a5d2e2d..68525a5f7 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -543,8 +543,6 @@ class SongMenuItem extends FlxSpriteGroup charPath += 'monsterpixel'; case 'mom-car': charPath += 'mommypixel'; - case 'dad': - charPath += 'daddypixel'; case 'darnell-blazin': charPath += 'darnellpixel'; case 'senpai-angry': @@ -559,7 +557,17 @@ class SongMenuItem extends FlxSpriteGroup return; } - pixelIcon.loadGraphic(Paths.image(charPath)); + var isAnimated = openfl.utils.Assets.exists(Paths.file('images/$charPath.xml')); + + if (isAnimated) + { + pixelIcon.frames = Paths.getSparrowAtlas(charPath); + } + else + { + pixelIcon.loadGraphic(Paths.image(charPath)); + } + pixelIcon.scale.x = pixelIcon.scale.y = 2; switch (char) @@ -571,6 +579,22 @@ class SongMenuItem extends FlxSpriteGroup } // pixelIcon.origin.x = capsule.origin.x; // pixelIcon.offset.x -= pixelIcon.origin.x; + + if (isAnimated) + { + pixelIcon.active = true; + + pixelIcon.animation.addByPrefix('idle', 'idle0', 10, true); + pixelIcon.animation.addByPrefix('confirm', 'confirm0', 10, false); + pixelIcon.animation.addByPrefix('confirm-hold', 'confirm-hold0', 10, true); + + pixelIcon.animation.finishCallback = function(name:String):Void { + trace('Finish pixel animation: ${name}'); + if (name == 'confirm') pixelIcon.animation.play('confirm-hold'); + }; + + pixelIcon.animation.play('idle'); + } } var frameInTicker:Float = 0; @@ -711,6 +735,18 @@ class SongMenuItem extends FlxSpriteGroup super.update(elapsed); } + /** + * Play any animations associated with selecting this song. + */ + public function confirm():Void + { + if (songText != null) songText.flickerText(); + if (pixelIcon != null) + { + pixelIcon.animation.play('confirm'); + } + } + public function intendedY(index:Int):Float { return (index * ((height * realScaled) + 10)) + 120; From bcaeae27f12be0a170d10b69e607eec29eba740c Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 1 Jul 2024 22:07:50 -0400 Subject: [PATCH 376/870] xml fix derp --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index c274cf6d5..0dbd2e96c 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit c274cf6d5a9d7e9e275f1f22d87d628eb379da5b +Subproject commit 0dbd2e96ca25ab5966cef05db6c76fe7fb145abf From d686890f763bd7a4db1841464dd7e3559fac1d0f Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Sat, 15 Jun 2024 05:59:58 +0100 Subject: [PATCH 377/870] most of the old code --- source/funkin/ui/charSelect/CharIcon.hx | 17 + .../funkin/ui/charSelect/CharIconCharacter.hx | 49 ++ source/funkin/ui/charSelect/CharIconLocked.hx | 3 + source/funkin/ui/charSelect/CharSelectGF.hx | 137 ++++ .../funkin/ui/charSelect/CharSelectPlayer.hx | 58 ++ .../ui/charSelect/CharSelectSubState.hx | 618 ++++++++++++++++++ source/funkin/ui/charSelect/Nametag.hx | 101 +++ source/funkin/ui/debug/DebugMenuSubState.hx | 6 + 8 files changed, 989 insertions(+) create mode 100644 source/funkin/ui/charSelect/CharIcon.hx create mode 100644 source/funkin/ui/charSelect/CharIconCharacter.hx create mode 100644 source/funkin/ui/charSelect/CharIconLocked.hx create mode 100644 source/funkin/ui/charSelect/CharSelectGF.hx create mode 100644 source/funkin/ui/charSelect/CharSelectPlayer.hx create mode 100644 source/funkin/ui/charSelect/CharSelectSubState.hx create mode 100644 source/funkin/ui/charSelect/Nametag.hx diff --git a/source/funkin/ui/charSelect/CharIcon.hx b/source/funkin/ui/charSelect/CharIcon.hx new file mode 100644 index 000000000..6d6274286 --- /dev/null +++ b/source/funkin/ui/charSelect/CharIcon.hx @@ -0,0 +1,17 @@ +package funkin.ui.charSelect; + +import flixel.FlxSprite; + +class CharIcon extends FlxSprite +{ + public var locked:Bool = false; + + public function new(x:Float, y:Float, locked:Bool = false) + { + super(x, y); + + this.locked = locked; + + makeGraphic(128, 128); + } +} diff --git a/source/funkin/ui/charSelect/CharIconCharacter.hx b/source/funkin/ui/charSelect/CharIconCharacter.hx new file mode 100644 index 000000000..7f7b5c212 --- /dev/null +++ b/source/funkin/ui/charSelect/CharIconCharacter.hx @@ -0,0 +1,49 @@ +package funkin.ui.charSelect; + +import openfl.display.BitmapData; +import openfl.filters.DropShadowFilter; +import openfl.filters.ConvolutionFilter; +import funkin.graphics.shaders.StrokeShader; + +class CharIconCharacter extends CharIcon +{ + public var dropShadowFilter:DropShadowFilter; + + var matrixFilter:Array = [ + 1, 1, 1, + 1, 1, 1, + 1, 1, 1 + ]; + + var divisor:Int = 1; + var bias:Int = 0; + var convolutionFilter:ConvolutionFilter; + + public var noDropShadow:BitmapData; + public var withDropShadow:BitmapData; + + var strokeShader:StrokeShader; + + public function new(path:String) + { + super(0, 0, false); + + loadGraphic(Paths.image('freeplay/icons/' + path + 'pixel')); + setGraphicSize(128, 128); + updateHitbox(); + antialiasing = false; + + strokeShader = new StrokeShader(); + // shader = strokeShader; + + // noDropShadow = pixels.clone(); + + // dropShadowFilter = new DropShadowFilter(5, 45, 0, 1, 0, 0); + // convolutionFilter = new ConvolutionFilter(3, 3, matrixFilter, divisor, bias); + // pixels.applyFilter(pixels, pixels.rect, new openfl.geom.Point(0, 0), dropShadowFilter); + // pixels.applyFilter(pixels, pixels.rect, new openfl.geom.Point(0, 0), convolutionFilter); + // withDropShadow = pixels.clone(); + + // pixels = noDropShadow.clone(); + } +} diff --git a/source/funkin/ui/charSelect/CharIconLocked.hx b/source/funkin/ui/charSelect/CharIconLocked.hx new file mode 100644 index 000000000..dbe84a6ce --- /dev/null +++ b/source/funkin/ui/charSelect/CharIconLocked.hx @@ -0,0 +1,3 @@ +package funkin.ui.charSelect; + +class CharIconLocked extends CharIcon {} diff --git a/source/funkin/ui/charSelect/CharSelectGF.hx b/source/funkin/ui/charSelect/CharSelectGF.hx new file mode 100644 index 000000000..6d8e3e657 --- /dev/null +++ b/source/funkin/ui/charSelect/CharSelectGF.hx @@ -0,0 +1,137 @@ +package funkin.ui.charSelect; + +import funkin.graphics.adobeanimate.FlxAtlasSprite; +import flixel.tweens.FlxTween; +import flixel.tweens.FlxEase; +import flixel.math.FlxMath; +import funkin.util.FramesJSFLParser; +import funkin.util.FramesJSFLParser.FramesJSFLInfo; +import funkin.util.FramesJSFLParser.FramesJSFLFrame; +import flixel.math.FlxMath; + +class CharSelectGF extends FlxAtlasSprite +{ + var fadeTimer:Float = 0; + var fadingStatus:FadeStatus = OFF; + var fadeAnimIndex:Int = 0; + + var animInInfo:FramesJSFLInfo; + var animOutInfo:FramesJSFLInfo; + + var intendedYPos:Float = 0; + var intendedAlpha:Float = 0; + + public function new() + { + super(0, 0, Paths.animateAtlas("charSelect/gfChill")); + anim.play(""); + switchGF("bf"); + } + + override public function update(elapsed:Float) + { + super.update(elapsed); + + switch (fadingStatus) + { + case OFF: + // do nothing if it's off! + // or maybe force position to be 0,0? + // maybe reset timers? + resetFadeAnimParams(); + case FADE_OUT: + doFade(animOutInfo); + case FADE_IN: + doFade(animInInfo); + default: + } + + if (FlxG.keys.justPressed.J) + { + alpha = 1; + x = y = 0; + fadingStatus = FADE_OUT; + } + if (FlxG.keys.justPressed.K) + { + alpha = 0; + fadingStatus = FADE_IN; + } + } + + /** + * @param animInfo Should not be confused with animInInfo! + * This is merely a local var for the function! + */ + function doFade(animInfo:FramesJSFLInfo) + { + fadeTimer += FlxG.elapsed; + if (fadeTimer >= 1 / 24) + { + fadeTimer = 0; + // only inc the index for the first frame, used for reference of where to "start" + if (fadeAnimIndex == 0) + { + fadeAnimIndex++; + return; + } + + var curFrame:FramesJSFLFrame = animInfo.frames[fadeAnimIndex]; + var prevFrame:FramesJSFLFrame = animInfo.frames[fadeAnimIndex - 1]; + + var xDiff:Float = curFrame.x - prevFrame.x; + var yDiff:Float = curFrame.y - prevFrame.y; + var alphaDiff:Float = curFrame.alpha - prevFrame.alpha; + alphaDiff /= 100; // flash exports alpha as a whole number + + alpha += alphaDiff; + alpha = FlxMath.bound(alpha, 0, 1); + x += xDiff; + y += yDiff; + + fadeAnimIndex++; + } + + if (fadeAnimIndex >= animInfo.frames.length) fadingStatus = OFF; + } + + function resetFadeAnimParams() + { + fadeTimer = 0; + fadeAnimIndex = 0; + } + + public function switchGF(str:String) + { + str = switch (str) + { + case "pico": + "nene"; + case "bf": + "gf"; + default: + "gf"; + } + + switch str + { + default: + loadAtlas(Paths.animateAtlas("charSelect/" + str + "Chill")); + } + + animInInfo = FramesJSFLParser.parse(Paths.file("images/charSelect/" + str + "AnimInfo/" + str + "In.txt")); + animOutInfo = FramesJSFLParser.parse(Paths.file("images/charSelect/" + str + "AnimInfo/" + str + "Out.txt")); + + anim.play(""); + playAnimation("idle", true, false, true); + + updateHitbox(); + } +} + +enum FadeStatus +{ + OFF; + FADE_OUT; + FADE_IN; +} diff --git a/source/funkin/ui/charSelect/CharSelectPlayer.hx b/source/funkin/ui/charSelect/CharSelectPlayer.hx new file mode 100644 index 000000000..9322369ba --- /dev/null +++ b/source/funkin/ui/charSelect/CharSelectPlayer.hx @@ -0,0 +1,58 @@ +package funkin.ui.charSelect; + +import flixel.FlxSprite; +import funkin.graphics.adobeanimate.FlxAtlasSprite; + +class CharSelectPlayer extends FlxAtlasSprite +{ + public function new(x:Float, y:Float) + { + super(x, y, Paths.animateAtlas("charSelect/bfChill")); + + onAnimationFinish.add(function(animLabel:String) { + switch (animLabel) + { + case "slidein": + if (hasAnimation("slidein idle point")) playAnimation("slidein idle point", true, false, false); + else + playAnimation("idle", true, false, true); + case "slidein idle point": + playAnimation("idle", true, false, true); + case "select": + anim.pause(); + case "deselect": + playAnimation("deselect loop start", true, false, true); + } + }); + } + + public function updatePosition(str:String) + { + switch (str) + { + case "bf": + x = 0; + y = 0; + case "pico": + x = 0; + y = 0; + case "random": + } + } + + public function switchChar(str:String) + { + switch str + { + default: + loadAtlas(Paths.animateAtlas("charSelect/" + str + "Chill")); + } + + anim.play(""); + playAnimation("slidein", true, false, false); + + updateHitbox(); + + updatePosition(str); + } +} diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx new file mode 100644 index 000000000..a360328a2 --- /dev/null +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -0,0 +1,618 @@ +package funkin.ui.charSelect; + +import flixel.text.FlxText; +import flixel.FlxSprite; +import flixel.system.debug.watch.Tracker.TrackerProfile; +import flixel.math.FlxPoint; +import flixel.tweens.FlxTween; +import openfl.display.BlendMode; +import flixel.group.FlxGroup.FlxTypedGroup; +import flixel.group.FlxSpriteGroup; +import funkin.play.stage.Stage; +import funkin.play.stage.StageData.StageDataParser; +import funkin.modding.events.ScriptEvent; +import funkin.modding.events.ScriptEventDispatcher; +import funkin.graphics.adobeanimate.FlxAtlasSprite; +import flixel.FlxObject; +import openfl.display.BlendMode; +import flixel.group.FlxGroup; +import funkin.util.MathUtil; +import flixel.util.FlxTimer; +import flixel.tweens.FlxEase; +import flixel.sound.FlxSound; +import funkin.audio.FunkinSound; + +class CharSelectSubState extends MusicBeatSubState +{ + var cursor:FlxSprite; + var cursorBlue:FlxSprite; + var cursorDarkBlue:FlxSprite; + + var grpCursors:FlxTypedGroup; + + var cursorConfirmed:FlxSprite; + var cursorDenied:FlxSprite; + + var cursorX:Int = 0; + var cursorY:Int = 0; + + var cursorFactor:Float = 110; + var cursorOffsetX:Float = -16; + var cursorOffsetY:Float = -48; + + var cursorLocIntended:FlxPoint = new FlxPoint(0, 0); + var lerpAmnt:Float = 0.95; + + var tmrFrames:Int = 60; + + var currentStage:Stage; + + var playerChill:CharSelectPlayer; + var playerChillOut:CharSelectPlayer; + var gfChill:CharSelectGF; + var gfChillOut:CharSelectGF; + + var curChar(default, set):String = "pico"; + var nametag:Nametag; + var camFollow:FlxObject; + + var availableChars:Map = new Map(); + var pressedSelect:Bool = false; + + var selectTimer:FlxTimer = new FlxTimer(); + var selectSound:FunkinSound; + + public function new() + { + super(); + + availableChars.set(4, "bf"); + availableChars.set(3, "pico"); + } + + override public function create() + { + super.create(); + + selectSound = new FunkinSound(); + selectSound.loadEmbedded(Paths.sound('CS_select')); + selectSound.pitch = 1; + selectSound.volume = 0.7; + FlxG.sound.defaultSoundGroup.add(selectSound); + + Conductor.forceBPM(90); + + var bg:FlxSprite = new FlxSprite(-153, -140); + bg.loadGraphic(Paths.image('charSelect/charSelectBG')); + bg.scrollFactor.set(0.1, 0.1); + add(bg); + + var crowd:FlxAtlasSprite = new FlxAtlasSprite(0, 0, Paths.animateAtlas("charSelect/crowd")); + crowd.anim.play(""); + crowd.scrollFactor.set(0.3, 0.3); + add(crowd); + + var stageSpr:FlxSprite = new FlxSprite(-40, 391); + stageSpr.frames = Paths.getSparrowAtlas("charSelect/charSelectStage"); + stageSpr.animation.addByPrefix("idle", "stage", 24, true); + stageSpr.animation.play("idle"); + add(stageSpr); + + var curtains:FlxSprite = new FlxSprite(-47, -49); + curtains.loadGraphic(Paths.image('charSelect/curtains')); + curtains.scrollFactor.set(1.4, 1.4); + add(curtains); + + var barthing:FlxAtlasSprite = new FlxAtlasSprite(0, 0, Paths.animateAtlas("charSelect/barThing")); + barthing.anim.play(""); + barthing.blend = BlendMode.MULTIPLY; + barthing.scrollFactor.set(0, 0); + add(barthing); + + var charLight:FlxSprite = new FlxSprite(800, 250); + charLight.loadGraphic(Paths.image('charSelect/charLight')); + add(charLight); + + var charLightGF:FlxSprite = new FlxSprite(180, 240); + charLightGF.loadGraphic(Paths.image('charSelect/charLight')); + add(charLightGF); + + gfChill = new CharSelectGF(); + gfChill.switchGF("bf"); + add(gfChill); + + playerChill = new CharSelectPlayer(0, 0); + playerChill.switchChar("bf"); + add(playerChill); + + playerChillOut = new CharSelectPlayer(0, 0); + playerChillOut.switchChar("bf"); + add(playerChillOut); + + var speakers:FlxAtlasSprite = new FlxAtlasSprite(0, 0, Paths.animateAtlas("charSelect/charSelectSpeakers")); + speakers.anim.play(""); + speakers.scrollFactor.set(1.8, 1.8); + add(speakers); + + var fgBlur:FlxSprite = new FlxSprite(-125, 170); + fgBlur.loadGraphic(Paths.image('charSelect/foregroundBlur')); + fgBlur.blend = openfl.display.BlendMode.MULTIPLY; + add(fgBlur); + + var dipshitBlur:FlxSprite = new FlxSprite(419, -65); + dipshitBlur.frames = Paths.getSparrowAtlas("charSelect/dipshitBlur"); + dipshitBlur.animation.addByPrefix('idle', "CHOOSE vertical", 24, true); + dipshitBlur.blend = BlendMode.ADD; + dipshitBlur.animation.play("idle"); + add(dipshitBlur); + + var dipshitBacking:FlxSprite = new FlxSprite(423, -17); + dipshitBacking.frames = Paths.getSparrowAtlas("charSelect/dipshitBacking"); + dipshitBacking.animation.addByPrefix('idle', "CHOOSE horizontal", 24, true); + dipshitBacking.blend = BlendMode.ADD; + dipshitBacking.animation.play("idle"); + add(dipshitBacking); + + var chooseDipshit:FlxSprite = new FlxSprite(426, -13); + chooseDipshit.loadGraphic(Paths.image('charSelect/chooseDipshit')); + add(chooseDipshit); + + chooseDipshit.scrollFactor.set(); + dipshitBacking.scrollFactor.set(); + dipshitBlur.scrollFactor.set(); + + nametag = new Nametag(); + add(nametag); + + nametag.scrollFactor.set(); + + FlxG.debugger.addTrackerProfile(new TrackerProfile(FlxSprite, ["x", "y", "alpha", "scale", "blend"])); + FlxG.debugger.addTrackerProfile(new TrackerProfile(FlxAtlasSprite, ["x", "y"])); + FlxG.debugger.addTrackerProfile(new TrackerProfile(FlxSound, ["pitch", "volume"])); + + // FlxG.debugger.track(crowd); + // FlxG.debugger.track(stageSpr, "stageSpr"); + // FlxG.debugger.track(bfChill, "bf chill"); + // FlxG.debugger.track(playerChill, "player"); + // FlxG.debugger.track(nametag, "nametag"); + FlxG.debugger.track(selectSound, "selectSound"); + // FlxG.debugger.track(chooseDipshit, "choose dipshit"); + // FlxG.debugger.track(barthing, "barthing"); + // FlxG.debugger.track(fgBlur, "fgBlur"); + // FlxG.debugger.track(dipshitBlur, "dipshitBlur"); + // FlxG.debugger.track(dipshitBacking, "dipshitBacking"); + // FlxG.debugger.track(charLightGF, "charLight"); + // FlxG.debugger.track(gfChill, "gfChill"); + + grpCursors = new FlxTypedGroup(); + add(grpCursors); + + cursor = new FlxSprite(0, 0); + cursor.loadGraphic(Paths.image('charSelect/charSelector')); + cursor.color = 0xFFFFFF00; + + // FFCC00 + + cursorBlue = new FlxSprite(0, 0); + cursorBlue.loadGraphic(Paths.image('charSelect/charSelector')); + cursorBlue.color = 0xFF3EBBFF; + + cursorDarkBlue = new FlxSprite(0, 0); + cursorDarkBlue.loadGraphic(Paths.image('charSelect/charSelector')); + cursorDarkBlue.color = 0xFF3C74F7; + + cursorBlue.blend = BlendMode.SCREEN; + cursorDarkBlue.blend = BlendMode.SCREEN; + + cursorConfirmed = new FlxSprite(0, 0); + cursorConfirmed.scrollFactor.set(); + cursorConfirmed.frames = Paths.getSparrowAtlas("charSelect/charSelectorConfirm"); + cursorConfirmed.animation.addByPrefix("idle", "cursor ACCEPTED", 24, true); + cursorConfirmed.visible = false; + add(cursorConfirmed); + + cursorDenied = new FlxSprite(0, 0); + cursorDenied.scrollFactor.set(); + cursorDenied.frames = Paths.getSparrowAtlas("charSelect/charSelectorDenied"); + cursorDenied.animation.addByPrefix("idle", "cursor DENIED", 24, false); + cursorDenied.visible = false; + add(cursorDenied); + + grpCursors.add(cursorDarkBlue); + grpCursors.add(cursorBlue); + grpCursors.add(cursor); + + initLocks(); + + cursor.scrollFactor.set(); + cursorBlue.scrollFactor.set(); + cursorDarkBlue.scrollFactor.set(); + + FlxTween.color(cursor, 0.2, 0xFFFFFF00, 0xFFFFCC00, {type: FlxTween.PINGPONG}); + + // FlxG.debugger.track(cursor); + + FlxG.debugger.addTrackerProfile(new TrackerProfile(CharSelectSubState, ["curChar", "grpXSpread", "grpYSpread"])); + FlxG.debugger.track(this); + + FlxG.sound.playMusic(Paths.music('charSelect/charSelectMusic')); + + camFollow = new FlxObject(0, 0, 1, 1); + add(camFollow); + camFollow.screenCenter(); + + FlxG.camera.follow(camFollow, LOCKON, 0.01); + + var temp:FlxSprite = new FlxSprite(); + temp.loadGraphic(Paths.image('charSelect/placement')); + add(temp); + temp.alpha = 0.0; + Conductor.stepHit.add(spamOnStep); + // FlxG.debugger.track(temp, "tempBG"); + } + + var grpIcons:FlxSpriteGroup; + + var grpXSpread(default, set):Float = 107; + var grpYSpread(default, set):Float = 127; + + function initLocks() + { + grpIcons = new FlxSpriteGroup(); + add(grpIcons); + + FlxG.debugger.addTrackerProfile(new TrackerProfile(FlxSpriteGroup, ["x", "y"])); + // FlxG.debugger.track(grpIcons, "iconGrp"); + + for (i in 0...9) + { + if (availableChars.exists(i)) + { + var path:String = availableChars.get(i); + var temp:CharIconCharacter = new CharIconCharacter(path); + temp.ID = 0; + + var idleAnimPrefix:String = switch (path) + { + case "pico": + "Pico Icon"; + case "bf": + "boyfriend icon instance 1"; + case _: + "Pico Icon"; + }; + + // temp.animation.addByPrefix("idle", idleAnimPrefix, 0, false); + // temp.animation.play("idle"); + grpIcons.add(temp); + } + else + { + var temp:FlxSprite = new FlxSprite(); + temp.ID = 1; + temp.frames = Paths.getSparrowAtlas("charSelect/locks"); + + var lockIndex:Int = i + 1; + + if (i == 3) lockIndex = 3; + + if (i >= 4) lockIndex = i - 2; + + temp.animation.addByIndices("idle", "LOCK FULL " + lockIndex + " instance 1", [0], "", 24); + temp.animation.addByIndices("selected", "LOCK FULL " + lockIndex + " instance 1", [3, 4, 5], "", 24, false); + temp.animation.addByIndices("clicked", "LOCK FULL " + lockIndex + " instance 1", [9, 10, 11, 12, 13, 14, 15], "", 24, false); + + temp.animation.play("idle"); + + grpIcons.add(temp); + } + } + + updateIconPositions(); + + grpIcons.scrollFactor.set(); + } + + function updateIconPositions() + { + grpIcons.x = 450; + grpIcons.y = 120; + for (index => member in grpIcons.members) + { + var posX:Float = (index % 3); + var posY:Float = Math.floor(index / 3); + + member.x = posX * grpXSpread; + member.y = posY * grpYSpread; + + member.x += grpIcons.x; + member.y += grpIcons.y; + } + } + + var holdTmrUp:Float = 0; + var holdTmrDown:Float = 0; + var holdTmrLeft:Float = 0; + var holdTmrRight:Float = 0; + var spamUp:Bool = false; + var spamDown:Bool = false; + var spamLeft:Bool = false; + var spamRight:Bool = false; + + override public function update(elapsed:Float) + { + super.update(elapsed); + + Conductor.update(); + + if (controls.UI_UP_R || controls.UI_DOWN_R || controls.UI_LEFT_R || controls.UI_RIGHT_R) selectSound.pitch = 1; + + if (controls.UI_UP) holdTmrUp += elapsed; + if (controls.UI_UP_R) + { + holdTmrUp = 0; + spamUp = false; + } + + if (controls.UI_DOWN) holdTmrDown += elapsed; + if (controls.UI_DOWN_R) + { + holdTmrDown = 0; + spamDown = false; + } + + if (controls.UI_LEFT) holdTmrLeft += elapsed; + if (controls.UI_LEFT_R) + { + holdTmrLeft = 0; + spamLeft = false; + } + + if (controls.UI_RIGHT) holdTmrRight += elapsed; + if (controls.UI_RIGHT_R) + { + holdTmrRight = 0; + spamRight = false; + } + + var initSpam = 0.5; + + if (holdTmrUp >= initSpam) spamUp = true; + if (holdTmrDown >= initSpam) spamDown = true; + if (holdTmrLeft >= initSpam) spamLeft = true; + if (holdTmrRight >= initSpam) spamRight = true; + + if (controls.UI_UP_P) + { + cursorY -= 1; + holdTmrUp = 0; + + selectSound.play(true); + } + if (controls.UI_DOWN_P) + { + cursorY += 1; + holdTmrDown = 0; + selectSound.play(true); + } + if (controls.UI_LEFT_P) + { + cursorX -= 1; + holdTmrLeft = 0; + selectSound.play(true); + } + if (controls.UI_RIGHT_P) + { + cursorX += 1; + holdTmrRight = 0; + selectSound.play(true); + } + + if (cursorX < -1) + { + cursorX = 1; + } + if (cursorX > 1) + { + cursorX = -1; + } + if (cursorY < -1) + { + cursorY = 1; + } + if (cursorY > 1) + { + cursorY = -1; + } + + if (availableChars.exists(getCurrentSelected())) + { + curChar = availableChars.get(getCurrentSelected()); + + if (controls.ACCEPT) + { + cursorConfirmed.visible = true; + cursorConfirmed.x = cursor.x - 2; + cursorConfirmed.y = cursor.y - 4; + cursorConfirmed.animation.play("idle", true); + + grpCursors.visible = false; + + FlxG.sound.play(Paths.sound('CS_confirm')); + + FlxTween.tween(FlxG.sound.music, {pitch: 0.1}, 1.5, {ease: FlxEase.quadInOut}); + playerChill.playAnimation("select"); + pressedSelect = true; + selectTimer.start(1.5, (_) -> { + pressedSelect = false; + close(); + }); + } + + if (pressedSelect && controls.BACK) + { + cursorConfirmed.visible = false; + grpCursors.visible = true; + + FlxTween.globalManager.cancelTweensOf(FlxG.sound.music); + FlxTween.tween(FlxG.sound.music, {pitch: 1.0}, 1, {ease: FlxEase.quartInOut}); + playerChill.playAnimation("deselect"); + pressedSelect = false; + selectTimer.cancel(); + } + } + else + { + curChar = "locked"; + + if (controls.ACCEPT) + { + cursorDenied.visible = true; + cursorDenied.x = cursor.x - 2; + cursorDenied.y = cursor.y - 4; + cursorDenied.animation.play("idle", true); + cursorDenied.animation.finishCallback = (_) -> { + cursorDenied.visible = false; + }; + } + } + + updateLockAnims(); + + camFollow.screenCenter(); + camFollow.x += cursorX * 10; + camFollow.y += cursorY * 10; + + cursorLocIntended.x = (cursorFactor * cursorX) + (FlxG.width / 2) - cursor.width / 2; + cursorLocIntended.y = (cursorFactor * cursorY) + (FlxG.height / 2) - cursor.height / 2; + + cursorLocIntended.x += cursorOffsetX; + cursorLocIntended.y += cursorOffsetY; + + cursor.x = MathUtil.coolLerp(cursor.x, cursorLocIntended.x, lerpAmnt); + cursor.y = MathUtil.coolLerp(cursor.y, cursorLocIntended.y, lerpAmnt); + + cursorBlue.x = MathUtil.coolLerp(cursorBlue.x, cursor.x, lerpAmnt * 0.4); + cursorBlue.y = MathUtil.coolLerp(cursorBlue.y, cursor.y, lerpAmnt * 0.4); + + cursorDarkBlue.x = MathUtil.coolLerp(cursorDarkBlue.x, cursorLocIntended.x, lerpAmnt * 0.2); + cursorDarkBlue.y = MathUtil.coolLerp(cursorDarkBlue.y, cursorLocIntended.y, lerpAmnt * 0.2); + } + + function spamOnStep() + { + if (spamUp || spamDown || spamLeft || spamRight) + { + selectSound.changePitchBySemitone(1); + if (selectSound.pitch > 5) selectSound.pitch = 5; + selectSound.play(true); + + if (spamUp) + { + cursorY -= 1; + holdTmrUp = 0; + } + if (spamDown) + { + cursorY += 1; + holdTmrDown = 0; + } + if (spamLeft) + { + cursorX -= 1; + holdTmrLeft = 0; + } + if (spamRight) + { + cursorX += 1; + holdTmrRight = 0; + } + } + } + + private function updateLockAnims() + { + for (index => member in grpIcons.group.members) + { + switch (member.ID) + { + case 1: + if (index == getCurrentSelected()) + { + switch (member.animation.curAnim.name) + { + case "idle": + member.animation.play("selected"); + case "selected" | "clicked": + if (controls.ACCEPT) member.animation.play("clicked", true); + } + } + else + { + member.animation.play("idle"); + } + case 0: + var memb:CharIconCharacter = cast member; + + if (index == getCurrentSelected()) + { + // memb.pixels = memb.withDropShadow.clone(); + memb.setGraphicSize(128 * 1.3); + } + else + { + // memb.pixels = memb.noDropShadow.clone(); + memb.setGraphicSize(128); + } + } + } + } + + function getCurrentSelected() + { + var tempX:Int = cursorX + 1; + var tempY:Int = cursorY + 1; + var gridPosition:Int = tempX + tempY * 3; + return gridPosition; + } + + function set_curChar(value:String):String + { + if (curChar == value) return value; + + curChar = value; + + nametag.switchChar(value); + playerChill.visible = false; + playerChillOut.visible = true; + playerChillOut.anim.goToFrameLabel("slideout"); + playerChillOut.anim.callback = (_, frame:Int) -> { + if (frame == playerChillOut.anim.getFrameLabel("slideout").index + 1) + { + playerChill.visible = true; + playerChill.switchChar(value); + gfChill.switchGF(value); + } + if (frame == playerChillOut.anim.getFrameLabel("slideout").index + 2) + { + playerChillOut.switchChar(value); + playerChillOut.visible = false; + } + }; + return value; + } + + function set_grpXSpread(value:Float):Float + { + grpXSpread = value; + updateIconPositions(); + return value; + } + + function set_grpYSpread(value:Float):Float + { + grpYSpread = value; + updateIconPositions(); + return value; + } +} diff --git a/source/funkin/ui/charSelect/Nametag.hx b/source/funkin/ui/charSelect/Nametag.hx new file mode 100644 index 000000000..b6cedb0c7 --- /dev/null +++ b/source/funkin/ui/charSelect/Nametag.hx @@ -0,0 +1,101 @@ +package funkin.ui.charSelect; + +import flixel.FlxSprite; +import funkin.graphics.shaders.MosaicEffect; +import flixel.util.FlxTimer; + +class Nametag extends FlxSprite +{ + var midpointX(default, set):Float = 1008; + var midpointY(default, set):Float = 100; + var mosaicShader:MosaicEffect; + + public function new(?x:Float = 0, ?y:Float = 0) + { + super(x, y); + + mosaicShader = new MosaicEffect(); + shader = mosaicShader; + + switchChar("bf"); + + FlxG.debugger.addTrackerProfile(new TrackerProfile(Nametag, ["midpointX", "midpointY"])); + FlxG.debugger.track(this, "Nametag"); + } + + public function updatePosition():Void + { + var offsetX:Float = getMidpoint().x - midpointX; + var offsetY:Float = getMidpoint().y - midpointY; + + x -= offsetX; + y -= offsetY; + } + + public function switchChar(str:String):Void + { + shaderEffect(); + + new FlxTimer().start(4 / 30, _ -> { + var path:String = str; + switch str + { + case "bf": + path = "boyfriend"; + } + + loadGraphic(Paths.image('charSelect/' + path + "Nametag")); + updateHitbox(); + scale.x = scale.y = 0.77; + + updatePosition(); + shaderEffect(true); + }); + } + + function shaderEffect(fadeOut:Bool = false):Void + { + if (fadeOut) + { + setBlockTimer(0, 1, 1); + setBlockTimer(1, width / 27, height / 26); + setBlockTimer(2, width / 10, height / 10); + + setBlockTimer(3, 1, 1); + } + else + { + setBlockTimer(0, (width / 10), (height / 10)); + setBlockTimer(1, width / 73, height / 6); + setBlockTimer(2, width / 10, height / 10); + } + } + + function setBlockTimer(frame:Int, ?forceX:Float, ?forceY:Float) + { + var daX:Float = 10 * FlxG.random.int(1, 4); + var daY:Float = 10 * FlxG.random.int(1, 4); + + if (forceX != null) daX = forceX; + + if (forceY != null) daY = forceY; + + new FlxTimer().start(frame / 30, _ -> { + mosaicShader.setBlockSize(daX, daY); + }); + } + + function set_midpointX(val:Float):Float + { + this.midpointX = val; + updatePosition(); + return val; + } + + function set_midpointY(val:Float):Float + { + this.midpointY = val; + updatePosition(); + return val; + } +} diff --git a/source/funkin/ui/debug/DebugMenuSubState.hx b/source/funkin/ui/debug/DebugMenuSubState.hx index f8b1be9d2..22dc5dba6 100644 --- a/source/funkin/ui/debug/DebugMenuSubState.hx +++ b/source/funkin/ui/debug/DebugMenuSubState.hx @@ -56,6 +56,7 @@ class DebugMenuSubState extends MusicBeatSubState // Call onMenuChange when the first item is created to move the camera . onMenuChange(createItem("CHART EDITOR", openChartEditor)); // createItem("Input Offset Testing", openInputOffsetTesting); + createItem("CHARACTER SELECT", openCharSelect, true); createItem("ANIMATION EDITOR", openAnimationEditor); // createItem("STAGE EDITOR", openStageEditor); // createItem("TEST STICKERS", testStickers); @@ -102,6 +103,11 @@ class DebugMenuSubState extends MusicBeatSubState trace('Input Offset Testing'); } + function openCharSelect() + { + FlxG.switchState(new funkin.ui.charSelect.CharSelectSubState()); + } + function openAnimationEditor() { FlxG.switchState(() -> new funkin.ui.debug.anim.DebugBoundingState()); From be4ca0f47d2b6736984d4d7933d8e80f264b676a Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Sat, 15 Jun 2024 06:00:13 +0100 Subject: [PATCH 378/870] assets..... submod... --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 0dbd2e96c..83f658fcd 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 0dbd2e96ca25ab5966cef05db6c76fe7fb145abf +Subproject commit 83f658fcd87de54ff9c1f7a497b916239d53a491 From 28068b1a86f46e7ff2dacaa18c426b6644bb6767 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Sat, 15 Jun 2024 06:08:55 +0100 Subject: [PATCH 379/870] updating more stuff --- .../funkin/graphics/shaders/MosaicEffect.hx | 23 +++++++++ .../ui/charSelect/CharSelectSubState.hx | 1 - source/funkin/util/FramesJSFLParser.hx | 48 +++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 source/funkin/graphics/shaders/MosaicEffect.hx create mode 100644 source/funkin/util/FramesJSFLParser.hx diff --git a/source/funkin/graphics/shaders/MosaicEffect.hx b/source/funkin/graphics/shaders/MosaicEffect.hx new file mode 100644 index 000000000..fc3737aff --- /dev/null +++ b/source/funkin/graphics/shaders/MosaicEffect.hx @@ -0,0 +1,23 @@ +package funkin.graphics.shaders; + +import flixel.addons.display.FlxRuntimeShader; +import openfl.utils.Assets; +import funkin.Paths; +import flixel.math.FlxPoint; + +class MosaicEffect extends FlxRuntimeShader +{ + public var blockSize:FlxPoint = FlxPoint.get(1.0, 1.0); + + public function new() + { + super(Assets.getText(Paths.frag('mosaic'))); + setBlockSize(1.0, 1.0); + } + + public function setBlockSize(w:Float, h:Float) + { + blockSize.set(w, h); + setFloatArray("uBlocksize", [w, h]); + } +} diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index a360328a2..40fa874f3 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -9,7 +9,6 @@ import openfl.display.BlendMode; import flixel.group.FlxGroup.FlxTypedGroup; import flixel.group.FlxSpriteGroup; import funkin.play.stage.Stage; -import funkin.play.stage.StageData.StageDataParser; import funkin.modding.events.ScriptEvent; import funkin.modding.events.ScriptEventDispatcher; import funkin.graphics.adobeanimate.FlxAtlasSprite; diff --git a/source/funkin/util/FramesJSFLParser.hx b/source/funkin/util/FramesJSFLParser.hx new file mode 100644 index 000000000..33bcf9d9d --- /dev/null +++ b/source/funkin/util/FramesJSFLParser.hx @@ -0,0 +1,48 @@ +package funkin.util; + +import openfl.Assets; + +/** + * See `funScripts/jsfl/frames.jsfl` for more information in the art repo/folder! + * Homemade dipshit proprietary format to get simple animation info out of flash! + * Pure convienience! + */ +class FramesJSFLParser +{ + public static function parse(path:String):FramesJSFLInfo + { + var text:String = Assets.getText(path); + + // TODO: error handle if text is null + + var output:FramesJSFLInfo = {frames: []}; + + var frames:Array = text.split("\n"); + + for (frame in frames) + { + var frameInfo:Array = frame.split(" "); + + var x:Float = Std.parseFloat(frameInfo[0]); + var y:Float = Std.parseFloat(frameInfo[1]); + var alpha:Float = Std.parseFloat(frameInfo[2]); + + var shit:FramesJSFLFrame = {x: x, y: y, alpha: alpha}; + output.frames.push(shit); + } + + return output; + } +} + +typedef FramesJSFLInfo = +{ + var frames:Array; +} + +typedef FramesJSFLFrame = +{ + var x:Float; + var y:Float; + var alpha:Float; +} From b1b7a032bec5cbd43149b8da971a17a9539b2a7f Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Sat, 15 Jun 2024 07:03:22 +0100 Subject: [PATCH 380/870] music updates --- source/funkin/ui/charSelect/CharSelectSubState.hx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index 40fa874f3..19f00dc92 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -79,7 +79,12 @@ class CharSelectSubState extends MusicBeatSubState selectSound.volume = 0.7; FlxG.sound.defaultSoundGroup.add(selectSound); - Conductor.forceBPM(90); + FunkinSound.playMusic('charSelect', + { + startingVolume: 0.0, + overrideExisting: true, + restartTrack: true + }); var bg:FlxSprite = new FlxSprite(-153, -140); bg.loadGraphic(Paths.image('charSelect/charSelectBG')); @@ -342,7 +347,7 @@ class CharSelectSubState extends MusicBeatSubState { super.update(elapsed); - Conductor.update(); + // Conductor.update(); if (controls.UI_UP_R || controls.UI_DOWN_R || controls.UI_LEFT_R || controls.UI_RIGHT_R) selectSound.pitch = 1; @@ -502,7 +507,7 @@ class CharSelectSubState extends MusicBeatSubState { if (spamUp || spamDown || spamLeft || spamRight) { - selectSound.changePitchBySemitone(1); + // selectSound.changePitchBySemitone(1); if (selectSound.pitch > 5) selectSound.pitch = 5; selectSound.play(true); From 8dfd36d227d9c9cbf736bff713762ffeb36f0d0f Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sat, 15 Jun 2024 03:27:59 -0400 Subject: [PATCH 381/870] menu spam fixie --- checkstyle.json | 3 ++- source/funkin/ui/charSelect/CharSelectSubState.hx | 14 ++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/checkstyle.json b/checkstyle.json index 41f0a7998..6c463f75a 100644 --- a/checkstyle.json +++ b/checkstyle.json @@ -327,7 +327,8 @@ "INLINE", "DYNAMIC", "FINAL" - ] + ], + "severity": "IGNORE" }, "type": "ModifierOrder" }, diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index 19f00dc92..022db2909 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -69,7 +69,7 @@ class CharSelectSubState extends MusicBeatSubState availableChars.set(3, "pico"); } - override public function create() + override public function create():Void { super.create(); @@ -79,6 +79,8 @@ class CharSelectSubState extends MusicBeatSubState selectSound.volume = 0.7; FlxG.sound.defaultSoundGroup.add(selectSound); + Conductor.instance.forceBPM(90); + FunkinSound.playMusic('charSelect', { startingVolume: 0.0, @@ -343,11 +345,11 @@ class CharSelectSubState extends MusicBeatSubState var spamLeft:Bool = false; var spamRight:Bool = false; - override public function update(elapsed:Float) + override public function update(elapsed:Float):Void { super.update(elapsed); - // Conductor.update(); + Conductor.instance.update(); if (controls.UI_UP_R || controls.UI_DOWN_R || controls.UI_LEFT_R || controls.UI_RIGHT_R) selectSound.pitch = 1; @@ -503,7 +505,7 @@ class CharSelectSubState extends MusicBeatSubState cursorDarkBlue.y = MathUtil.coolLerp(cursorDarkBlue.y, cursorLocIntended.y, lerpAmnt * 0.2); } - function spamOnStep() + function spamOnStep():Void { if (spamUp || spamDown || spamLeft || spamRight) { @@ -534,7 +536,7 @@ class CharSelectSubState extends MusicBeatSubState } } - private function updateLockAnims() + private function updateLockAnims():Void { for (index => member in grpIcons.group.members) { @@ -572,7 +574,7 @@ class CharSelectSubState extends MusicBeatSubState } } - function getCurrentSelected() + function getCurrentSelected():Int { var tempX:Int = cursorX + 1; var tempY:Int = cursorY + 1; From 3fa9b2a635b54a4c94ebbfc2ff4a5a1c20584101 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Thu, 20 Jun 2024 02:40:50 +0100 Subject: [PATCH 382/870] new music --- .../funkin/ui/charSelect/CharSelectSubState.hx | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index 022db2909..0e8bdd1bb 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -79,14 +79,23 @@ class CharSelectSubState extends MusicBeatSubState selectSound.volume = 0.7; FlxG.sound.defaultSoundGroup.add(selectSound); - Conductor.instance.forceBPM(90); - - FunkinSound.playMusic('charSelect', + // playing it here to preload it. not doing this makes a super awkward pause at the end of the intro + // TODO: probably make an intro thing for funkinSound itself that preloads the next audio? + FunkinSound.playMusic('stayFunky', { - startingVolume: 0.0, + startingVolume: 0, overrideExisting: true, restartTrack: true }); + var introMusic:String = Paths.music('stayFunky/stayFunky-intro'); + FunkinSound.load(introMusic, 1.0, false, true, true, () -> { + FunkinSound.playMusic('stayFunky', + { + startingVolume: 1, + overrideExisting: true, + restartTrack: true + }); + }); var bg:FlxSprite = new FlxSprite(-153, -140); bg.loadGraphic(Paths.image('charSelect/charSelectBG')); From 927e37b35bda92888f0c0b47256884a0285cadd3 Mon Sep 17 00:00:00 2001 From: lemz Date: Tue, 2 Jul 2024 17:18:46 +0200 Subject: [PATCH 383/870] use new numberpreferenceitem --- source/funkin/ui/options/PreferencesMenu.hx | 8 +-- .../ui/options/items/NumberPreferenceItem.hx | 55 ++++++++++++++----- 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/source/funkin/ui/options/PreferencesMenu.hx b/source/funkin/ui/options/PreferencesMenu.hx index d004a46c7..80dad0241 100644 --- a/source/funkin/ui/options/PreferencesMenu.hx +++ b/source/funkin/ui/options/PreferencesMenu.hx @@ -54,7 +54,7 @@ class PreferencesMenu extends Page #if !web createPrefItemNumber('FPS', 'The framerate that the game is running on', function(value:Float) { Preferences.framerate = Std.int(value); - }, Preferences.framerate, 60, 360, 1, 0); + }, null, Preferences.framerate, 60, 360, 1, 0); #end createPrefItemCheckbox('Naughtyness', 'Toggle displaying raunchy content', function(value:Bool):Void { Preferences.naughtyness = value; @@ -120,10 +120,10 @@ class PreferencesMenu extends Page preferenceItems.add(checkbox); } - function createPrefItemNumber(prefName:String, prefDesc:String, onChange:Float->Void, defaultValue:Float, min:Float, max:Float, step:Float, - precision:Int):Void + function createPrefItemNumber(prefName:String, prefDesc:String, onChange:Float->Void, ?valueFormatter:Float->String, defaultValue:Int, min:Int, max:Int, + step:Float = 0.1, precision:Int):Void { - var item = new NumberPreferenceItem(0, (120 * items.length) + 30, prefName, defaultValue, min, max, step, precision, onChange); + var item = new NumberPreferenceItem(0, (120 * items.length) + 30, prefName, defaultValue, min, max, step, precision, onChange, valueFormatter); items.addItem(prefName, item); preferenceItems.add(item.lefthandText); } diff --git a/source/funkin/ui/options/items/NumberPreferenceItem.hx b/source/funkin/ui/options/items/NumberPreferenceItem.hx index eeea3112e..f3cd3cd46 100644 --- a/source/funkin/ui/options/items/NumberPreferenceItem.hx +++ b/source/funkin/ui/options/items/NumberPreferenceItem.hx @@ -14,16 +14,35 @@ class NumberPreferenceItem extends TextMenuItem return PlayerSettings.player1.controls; } + // Widgets public var lefthandText:AtlasText; + // Constants + static final HOLD_DELAY:Float = 0.3; // seconds + static final CHANGE_RATE:Float = 0.08; // seconds + + // Constructor-initialized variables public var currentValue:Float; public var min:Float; public var max:Float; public var step:Float; public var precision:Int; public var onChangeCallback:NullVoid>; + public var valueFormatter:NullString>; - public function new(x:Float, y:Float, name:String, defaultValue:Float, min:Float, max:Float, step:Float, precision:Int, ?callback:Float->Void):Void + // Variables + var holdDelayTimer:Float = HOLD_DELAY; // seconds + var changeRateTimer:Float = 0.0; // seconds + + /** + * @param min Minimum value (example: 0) + * @param max Maximum value (example: 100) + * @param step The value to increment/decrement by (example: 10) + * @param callback Will get called every time the user changes the setting; use this to apply/save the setting. + * @param valueFormatter Will get called every time the game needs to display the float value; use this to change how the displayed string looks + */ + public function new(x:Float, y:Float, name:String, defaultValue:Float, min:Float, max:Float, step:Float, precision:Int, ?callback:Float->Void, + ?valueFormatter:Float->String):Void { super(x, y, name, function() { callback(this.currentValue); @@ -38,14 +57,9 @@ class NumberPreferenceItem extends TextMenuItem this.step = step; this.precision = precision; this.onChangeCallback = callback; + this.valueFormatter = valueFormatter; } - static final HOLD_DELAY:Float = 0.5; // seconds - static final CHANGE_RATE:Float = 0.02; // seconds - - var holdDelayTimer:Float = HOLD_DELAY; // seconds - var changeRateTimer:Float = 0.0; // seconds - override function update(elapsed:Float):Void { super.update(elapsed); @@ -82,21 +96,36 @@ class NumberPreferenceItem extends TextMenuItem changeRateTimer = CHANGE_RATE; } - if (shouldDecrease) currentValue -= step; - else if (shouldIncrease) currentValue += step; - currentValue = currentValue.clamp(min, max); - if (onChangeCallback != null && (shouldIncrease || shouldDecrease)) + // Actually increasing/decreasing the value + if (shouldDecrease) { - onChangeCallback(currentValue); + var isBelowMin:Bool = currentValue - step < min; + currentValue = (currentValue - step).clamp(min, max); + if (onChangeCallback != null && !isBelowMin) onChangeCallback(currentValue); + } + else if (shouldIncrease) + { + var isAboveMax:Bool = currentValue + step > max; + currentValue = (currentValue + step).clamp(min, max); + if (onChangeCallback != null && !isAboveMax) onChangeCallback(currentValue); } } lefthandText.text = formatted(currentValue); } + /** Turns the float into a string */ function formatted(value:Float):String { - return '${toFixed(value)}'; + var float:Float = toFixed(value); + if (valueFormatter != null) + { + return valueFormatter(float); + } + else + { + return '${float}'; + } } function toFixed(value:Float):Float From 105e3dccba49897e594e8d6c9a23cc2768fd596b Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 2 Jul 2024 21:26:16 -0400 Subject: [PATCH 384/870] spritesheet fixins for char select --- .gitignore | 1 + source/funkin/ui/PixelatedIcon.hx | 79 ++++++++++++++++++ .../ui/charSelect/CharSelectSubState.hx | 29 +++---- source/funkin/ui/freeplay/SongMenuItem.hx | 81 +------------------ 4 files changed, 95 insertions(+), 95 deletions(-) create mode 100644 source/funkin/ui/PixelatedIcon.hx diff --git a/.gitignore b/.gitignore index 84585eee0..ae402bdee 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ shitAudio/ node_modules/ package.json package-lock.json +.aider* diff --git a/source/funkin/ui/PixelatedIcon.hx b/source/funkin/ui/PixelatedIcon.hx new file mode 100644 index 000000000..8d9b97d9c --- /dev/null +++ b/source/funkin/ui/PixelatedIcon.hx @@ -0,0 +1,79 @@ +package funkin.ui; + +import flixel.FlxSprite; + +/** + * The icon that gets used for Freeplay capsules and char select + * NOT to be confused with the CharIcon class, which is for the in-game icons + */ +class PixelatedIcon extends FlxSprite +{ + public function new(x:Float, y:Float) + { + super(x, y); + this.makeGraphic(32, 32, 0x00000000); + this.antialiasing = false; + this.active = false; + } + + public function setCharacter(char:String):Void + { + var charPath:String = "freeplay/icons/"; + + switch (char) + { + case 'monster-christmas': + charPath += 'monsterpixel'; + case 'mom-car': + charPath += 'mommypixel'; + case 'darnell-blazin': + charPath += 'darnellpixel'; + case 'senpai-angry': + charPath += 'senpaipixel'; + default: + charPath += '${char}pixel'; + } + + if (!openfl.utils.Assets.exists(Paths.image(charPath))) + { + trace('[WARN] Character ${char} has no freeplay icon.'); + return; + } + + var isAnimated = openfl.utils.Assets.exists(Paths.file('images/$charPath.xml')); + + if (isAnimated) + { + this.frames = Paths.getSparrowAtlas(charPath); + } + else + { + this.loadGraphic(Paths.image(charPath)); + } + + this.scale.x = this.scale.y = 2; + + switch (char) + { + case 'parents-christmas': + this.origin.x = 140; + default: + this.origin.x = 100; + } + + if (isAnimated) + { + this.active = true; + this.animation.addByPrefix('idle', 'idle0', 10, true); + this.animation.addByPrefix('confirm', 'confirm0', 10, false); + this.animation.addByPrefix('confirm-hold', 'confirm-hold0', 10, true); + + this.animation.finishCallback = function(name:String):Void { + trace('Finish pixel animation: ${name}'); + if (name == 'confirm') this.animation.play('confirm-hold'); + }; + + this.animation.play('idle'); + } + } +} diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index 0e8bdd1bb..d73366390 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -1,12 +1,13 @@ package funkin.ui.charSelect; import flixel.text.FlxText; -import flixel.FlxSprite; +import funkin.ui.PixelatedIcon; import flixel.system.debug.watch.Tracker.TrackerProfile; import flixel.math.FlxPoint; import flixel.tweens.FlxTween; import openfl.display.BlendMode; import flixel.group.FlxGroup.FlxTypedGroup; +import flixel.FlxSprite; import flixel.group.FlxSpriteGroup; import funkin.play.stage.Stage; import funkin.modding.events.ScriptEvent; @@ -284,21 +285,11 @@ class CharSelectSubState extends MusicBeatSubState if (availableChars.exists(i)) { var path:String = availableChars.get(i); - var temp:CharIconCharacter = new CharIconCharacter(path); + var temp:PixelatedIcon = new PixelatedIcon(0, 0); + temp.setCharacter(path); + temp.setGraphicSize(128, 128); + temp.updateHitbox(); temp.ID = 0; - - var idleAnimPrefix:String = switch (path) - { - case "pico": - "Pico Icon"; - case "bf": - "boyfriend icon instance 1"; - case _: - "Pico Icon"; - }; - - // temp.animation.addByPrefix("idle", idleAnimPrefix, 0, false); - // temp.animation.play("idle"); grpIcons.add(temp); } else @@ -567,17 +558,19 @@ class CharSelectSubState extends MusicBeatSubState member.animation.play("idle"); } case 0: - var memb:CharIconCharacter = cast member; + var memb:PixelatedIcon = cast member; if (index == getCurrentSelected()) { // memb.pixels = memb.withDropShadow.clone(); - memb.setGraphicSize(128 * 1.3); + memb.scale.set(2.6, 2.6); + + if (controls.ACCEPT) memb.animation.play("confirm"); } else { // memb.pixels = memb.noDropShadow.clone(); - memb.setGraphicSize(128); + memb.scale.set(2, 2); } } } diff --git a/source/funkin/ui/freeplay/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx index 68525a5f7..2eec83223 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -24,12 +24,13 @@ import funkin.play.scoring.Scoring.ScoringRank; import funkin.save.Save; import funkin.save.Save.SaveScoreData; import flixel.util.FlxColor; +import funkin.ui.PixelatedIcon; class SongMenuItem extends FlxSpriteGroup { public var capsule:FlxSprite; - var pixelIcon:FlxSprite; + var pixelIcon:PixelatedIcon; /** * Modify this by calling `init()` @@ -201,11 +202,7 @@ class SongMenuItem extends FlxSpriteGroup // TODO: Use value from metadata instead of random. updateDifficultyRating(FlxG.random.int(0, 20)); - pixelIcon = new FlxSprite(160, 35); - - pixelIcon.makeGraphic(32, 32, 0x00000000); - pixelIcon.antialiasing = false; - pixelIcon.active = false; + pixelIcon = new PixelatedIcon(160, 35); add(pixelIcon); grpHide.add(pixelIcon); @@ -512,7 +509,7 @@ class SongMenuItem extends FlxSpriteGroup // Update capsule text. songText.text = songData?.songName ?? 'Random'; // Update capsule character. - if (songData?.songCharacter != null) setCharacter(songData.songCharacter); + if (songData?.songCharacter != null) pixelIcon.setCharacter(songData.songCharacter); updateBPM(Std.int(songData?.songStartingBpm) ?? 0); updateDifficultyRating(songData?.difficultyRating ?? 0); updateScoringRank(songData?.scoringRank); @@ -526,76 +523,6 @@ class SongMenuItem extends FlxSpriteGroup checkWeek(songData?.songId); } - /** - * Set the character displayed next to this song in the freeplay menu. - * @param char The character ID used by this song. - * If the character has no freeplay icon, a warning will be thrown and nothing will display. - */ - public function setCharacter(char:String):Void - { - var charPath:String = "freeplay/icons/"; - - // TODO: Put this in the character metadata where it belongs. - // TODO: Also, can use CharacterDataParser.getCharPixelIconAsset() - switch (char) - { - case 'monster-christmas': - charPath += 'monsterpixel'; - case 'mom-car': - charPath += 'mommypixel'; - case 'darnell-blazin': - charPath += 'darnellpixel'; - case 'senpai-angry': - charPath += 'senpaipixel'; - default: - charPath += '${char}pixel'; - } - - if (!openfl.utils.Assets.exists(Paths.image(charPath))) - { - trace('[WARN] Character ${char} has no freeplay icon.'); - return; - } - - var isAnimated = openfl.utils.Assets.exists(Paths.file('images/$charPath.xml')); - - if (isAnimated) - { - pixelIcon.frames = Paths.getSparrowAtlas(charPath); - } - else - { - pixelIcon.loadGraphic(Paths.image(charPath)); - } - - pixelIcon.scale.x = pixelIcon.scale.y = 2; - - switch (char) - { - case 'parents-christmas': - pixelIcon.origin.x = 140; - default: - pixelIcon.origin.x = 100; - } - // pixelIcon.origin.x = capsule.origin.x; - // pixelIcon.offset.x -= pixelIcon.origin.x; - - if (isAnimated) - { - pixelIcon.active = true; - - pixelIcon.animation.addByPrefix('idle', 'idle0', 10, true); - pixelIcon.animation.addByPrefix('confirm', 'confirm0', 10, false); - pixelIcon.animation.addByPrefix('confirm-hold', 'confirm-hold0', 10, true); - - pixelIcon.animation.finishCallback = function(name:String):Void { - trace('Finish pixel animation: ${name}'); - if (name == 'confirm') pixelIcon.animation.play('confirm-hold'); - }; - - pixelIcon.animation.play('idle'); - } - } var frameInTicker:Float = 0; var frameInTypeBeat:Int = 0; From 837efcea369467bf69c98e9d7cc5d0e57ad43c64 Mon Sep 17 00:00:00 2001 From: AppleHair <95587502+AppleHair@users.noreply.github.com> Date: Mon, 10 Jun 2024 19:42:27 +0300 Subject: [PATCH 385/870] [BUGFIX] Made freeplay use the metadata to get the instrumental suffix Song previews in freeplay will now use the instrumental suffix from the current difficulty's corresponding song variation metadata instead of using the variation id as an instrumental suffix and checking only the "erect" variation. --- source/funkin/ui/freeplay/FreeplayState.hx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 3b003cf89..92410622f 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1882,7 +1882,10 @@ class FreeplayState extends MusicBeatSubState } else { - var potentiallyErect:String = (currentDifficulty == "erect") || (currentDifficulty == "nightmare") ? "-erect" : ""; + var previewSong:Null = SongRegistry.instance.fetchEntry(daSongCapsule.songData.songId); + var instSuffix:String = previewSong?.getDifficulty(currentDifficulty, + previewSong?.variations ?? Constants.DEFAULT_VARIATION_LIST)?.characters?.instrumental ?? ''; + instSuffix = (instSuffix != '') ? '-$instSuffix' : ''; FunkinSound.playMusic(daSongCapsule.songData.songId, { startingVolume: 0.0, @@ -1890,7 +1893,7 @@ class FreeplayState extends MusicBeatSubState restartTrack: false, mapTimeChanges: false, // The music metadata is not alongside the audio file so this won't work. pathsFunction: INST, - suffix: potentiallyErect, + suffix: instSuffix, partialParams: { loadPartial: true, From b1021530d8bb97e259c9443a62d306c96f54147d Mon Sep 17 00:00:00 2001 From: AppleHair <95587502+AppleHair@users.noreply.github.com> Date: Wed, 12 Jun 2024 11:23:45 +0300 Subject: [PATCH 386/870] now using getVariationsByCharId instead --- 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 92410622f..69b499e80 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1884,7 +1884,7 @@ class FreeplayState extends MusicBeatSubState { var previewSong:Null = SongRegistry.instance.fetchEntry(daSongCapsule.songData.songId); var instSuffix:String = previewSong?.getDifficulty(currentDifficulty, - previewSong?.variations ?? Constants.DEFAULT_VARIATION_LIST)?.characters?.instrumental ?? ''; + previewSong?.getVariationsByCharId(currentCharacter) ?? Constants.DEFAULT_VARIATION_LIST)?.characters?.instrumental ?? ''; instSuffix = (instSuffix != '') ? '-$instSuffix' : ''; FunkinSound.playMusic(daSongCapsule.songData.songId, { From 72a00b9ae20ff2f2ee20fc58bd7c6fb7f0687696 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 18 Jun 2024 17:56:24 -0400 Subject: [PATCH 387/870] Implemented playable character registry, added Freeplay character filtering, added alt instrumental support --- assets | 2 +- source/funkin/InitState.hx | 2 + .../funkin/data/freeplay/player/CHANGELOG.md | 9 ++ .../funkin/data/freeplay/player/PlayerData.hx | 63 ++++++++ .../data/freeplay/player/PlayerRegistry.hx | 151 ++++++++++++++++++ source/funkin/modding/PolymodHandler.hx | 6 +- source/funkin/play/song/Song.hx | 34 ++-- .../handlers/ChartEditorDialogHandler.hx | 7 +- source/funkin/ui/freeplay/FreeplayState.hx | 80 +++++++--- .../freeplay/charselect/PlayableCharacter.hx | 108 +++++++++++++ .../charselect/ScriptedPlayableCharacter.hx | 8 + source/funkin/util/VersionUtil.hx | 1 - 12 files changed, 433 insertions(+), 38 deletions(-) create mode 100644 source/funkin/data/freeplay/player/CHANGELOG.md create mode 100644 source/funkin/data/freeplay/player/PlayerData.hx create mode 100644 source/funkin/data/freeplay/player/PlayerRegistry.hx create mode 100644 source/funkin/ui/freeplay/charselect/PlayableCharacter.hx create mode 100644 source/funkin/ui/freeplay/charselect/ScriptedPlayableCharacter.hx diff --git a/assets b/assets index 0dbd2e96c..bc1650ba7 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 0dbd2e96ca25ab5966cef05db6c76fe7fb145abf +Subproject commit bc1650ba789d675683a8c0cc27b1e2a42cb686cf diff --git a/source/funkin/InitState.hx b/source/funkin/InitState.hx index 49b15ddf6..c2a56bdc2 100644 --- a/source/funkin/InitState.hx +++ b/source/funkin/InitState.hx @@ -1,5 +1,6 @@ package funkin; +import funkin.data.freeplay.player.PlayerRegistry; import funkin.ui.debug.charting.ChartEditorState; import funkin.ui.transition.LoadingState; import flixel.FlxState; @@ -164,6 +165,7 @@ class InitState extends FlxState SongRegistry.instance.loadEntries(); LevelRegistry.instance.loadEntries(); NoteStyleRegistry.instance.loadEntries(); + PlayerRegistry.instance.loadEntries(); ConversationRegistry.instance.loadEntries(); DialogueBoxRegistry.instance.loadEntries(); SpeakerRegistry.instance.loadEntries(); diff --git a/source/funkin/data/freeplay/player/CHANGELOG.md b/source/funkin/data/freeplay/player/CHANGELOG.md new file mode 100644 index 000000000..7a31e11ca --- /dev/null +++ b/source/funkin/data/freeplay/player/CHANGELOG.md @@ -0,0 +1,9 @@ +# Freeplay Playable Character Data Schema Changelog + +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). + +## [1.0.0] +Initial release. diff --git a/source/funkin/data/freeplay/player/PlayerData.hx b/source/funkin/data/freeplay/player/PlayerData.hx new file mode 100644 index 000000000..d7b814584 --- /dev/null +++ b/source/funkin/data/freeplay/player/PlayerData.hx @@ -0,0 +1,63 @@ +package funkin.data.freeplay.player; + +import funkin.data.animation.AnimationData; + +@:nullSafety +class PlayerData +{ + /** + * The sematic version number of the player data JSON format. + * Supports fancy comparisons like NPM does it's neat. + */ + @:default(funkin.data.freeplay.player.PlayerRegistry.PLAYER_DATA_VERSION) + public var version:String; + + /** + * A readable name for this playable character. + */ + public var name:String = 'Unknown'; + + /** + * The character IDs this character is associated with. + * Only songs that use these characters will show up in Freeplay. + */ + @:default([]) + public var ownedChars:Array = []; + + /** + * Whether to show songs with character IDs that aren't associated with any specific character. + */ + @:optional + @:default(false) + public var showUnownedChars:Bool = false; + + /** + * Whether this character is unlocked by default. + * Use a ScriptedPlayableCharacter to add custom logic. + */ + @:optional + @:default(true) + public var unlocked:Bool = true; + + public function new() + { + this.version = PlayerRegistry.PLAYER_DATA_VERSION; + } + + /** + * Convert this StageData into a JSON string. + */ + 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 = PlayerRegistry.PLAYER_DATA_VERSION; + } +} diff --git a/source/funkin/data/freeplay/player/PlayerRegistry.hx b/source/funkin/data/freeplay/player/PlayerRegistry.hx new file mode 100644 index 000000000..3de9efd41 --- /dev/null +++ b/source/funkin/data/freeplay/player/PlayerRegistry.hx @@ -0,0 +1,151 @@ +package funkin.data.freeplay.player; + +import funkin.data.freeplay.player.PlayerData; +import funkin.ui.freeplay.charselect.PlayableCharacter; +import funkin.ui.freeplay.charselect.ScriptedPlayableCharacter; + +class PlayerRegistry extends BaseRegistry +{ + /** + * The current version string for the stage data format. + * Handle breaking changes by incrementing this value + * and adding migration to the `migratePlayerData()` function. + */ + public static final PLAYER_DATA_VERSION:thx.semver.Version = "1.0.0"; + + public static final PLAYER_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x"; + + public static var instance(get, never):PlayerRegistry; + static var _instance:Null = null; + + static function get_instance():PlayerRegistry + { + if (_instance == null) _instance = new PlayerRegistry(); + return _instance; + } + + /** + * A mapping between stage character IDs and Freeplay playable character IDs. + */ + var ownedCharacterIds:Map = []; + + public function new() + { + super('PLAYER', 'players', PLAYER_DATA_VERSION_RULE); + } + + public override function loadEntries():Void + { + super.loadEntries(); + + for (playerId in listEntryIds()) + { + var player = fetchEntry(playerId); + if (player == null) continue; + + var currentPlayerCharIds = player.getOwnedCharacterIds(); + for (characterId in currentPlayerCharIds) + { + ownedCharacterIds.set(characterId, playerId); + } + } + + log('Loaded ${countEntries()} playable characters with ${ownedCharacterIds.size()} associations.'); + } + + /** + * Get the playable character associated with a given stage character. + * @param characterId The stage character ID. + * @return The playable character. + */ + public function getCharacterOwnerId(characterId:String):String + { + return ownedCharacterIds[characterId]; + } + + /** + * Return true if the given stage character is associated with a specific playable character. + * If so, the level should only appear if that character is selected in Freeplay. + * @param characterId The stage character ID. + * @return Whether the character is owned by any one character. + */ + public function isCharacterOwned(characterId:String):Bool + { + return ownedCharacterIds.exists(characterId); + } + + /** + * Read, parse, and validate the JSON data and produce the corresponding data object. + */ + public function parseEntryData(id:String):Null + { + // JsonParser does not take type parameters, + // otherwise this function would be in BaseRegistry. + var parser = new json2object.JsonParser(); + parser.ignoreUnknownVariables = false; + + switch (loadEntryFile(id)) + { + case {fileName: fileName, contents: contents}: + parser.fromJson(contents, fileName); + default: + return null; + } + + if (parser.errors.length > 0) + { + printErrors(parser.errors, id); + return null; + } + return parser.value; + } + + /** + * Parse and validate the JSON data and produce the corresponding data object. + * + * NOTE: Must be implemented on the implementation class. + * @param contents The JSON as a string. + * @param fileName An optional file name for error reporting. + */ + public function parseEntryDataRaw(contents:String, ?fileName:String):Null + { + var parser = new json2object.JsonParser(); + parser.ignoreUnknownVariables = false; + parser.fromJson(contents, fileName); + + if (parser.errors.length > 0) + { + printErrors(parser.errors, fileName); + return null; + } + return parser.value; + } + + function createScriptedEntry(clsName:String):PlayableCharacter + { + return ScriptedPlayableCharacter.init(clsName, "unknown"); + } + + function getScriptedClassNames():Array + { + return ScriptedPlayableCharacter.listScriptClasses(); + } + + /** + * A list of all the playable characters from the base game, in order. + */ + public function listBaseGamePlayerIds():Array + { + return ["bf", "pico"]; + } + + /** + * A list of all installed playable characters that are not from the base game. + */ + public function listModdedPlayerIds():Array + { + return listEntryIds().filter(function(id:String):Bool { + return listBaseGamePlayerIds().indexOf(id) == -1; + }); + } +} diff --git a/source/funkin/modding/PolymodHandler.hx b/source/funkin/modding/PolymodHandler.hx index ae754b780..c352aa606 100644 --- a/source/funkin/modding/PolymodHandler.hx +++ b/source/funkin/modding/PolymodHandler.hx @@ -8,6 +8,7 @@ import funkin.data.event.SongEventRegistry; import funkin.data.story.level.LevelRegistry; import funkin.data.notestyle.NoteStyleRegistry; import funkin.data.song.SongRegistry; +import funkin.data.freeplay.player.PlayerRegistry; import funkin.data.stage.StageRegistry; import funkin.data.freeplay.album.AlbumRegistry; import funkin.modding.module.ModuleHandler; @@ -369,15 +370,18 @@ class PolymodHandler // These MUST be imported at the top of the file and not referred to by fully qualified name, // to ensure build macros work properly. + SongEventRegistry.loadEventCache(); + SongRegistry.instance.loadEntries(); LevelRegistry.instance.loadEntries(); NoteStyleRegistry.instance.loadEntries(); - SongEventRegistry.loadEventCache(); + PlayerRegistry.instance.loadEntries(); ConversationRegistry.instance.loadEntries(); DialogueBoxRegistry.instance.loadEntries(); SpeakerRegistry.instance.loadEntries(); AlbumRegistry.instance.loadEntries(); StageRegistry.instance.loadEntries(); + CharacterDataParser.loadCharacterCache(); // TODO: Migrate characters to BaseRegistry. ModuleHandler.loadModuleCache(); } diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx index dde5ee7b8..91d35d8fa 100644 --- a/source/funkin/play/song/Song.hx +++ b/source/funkin/play/song/Song.hx @@ -14,6 +14,7 @@ import funkin.data.song.SongData.SongTimeFormat; import funkin.data.song.SongRegistry; import funkin.modding.IScriptedClass.IPlayStateScriptedClass; import funkin.modding.events.ScriptEvent; +import funkin.ui.freeplay.charselect.PlayableCharacter; import funkin.util.SortUtil; import openfl.utils.Assets; @@ -401,11 +402,11 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry):Null + public function getFirstValidVariation(?diffId:String, ?currentCharacter:PlayableCharacter, ?possibleVariations:Array):Null { if (possibleVariations == null) { - possibleVariations = variations; + possibleVariations = getVariationsByCharacter(currentCharacter); possibleVariations.sort(SortUtil.defaultsThenAlphabetically.bind(Constants.DEFAULT_VARIATION_LIST)); } if (diffId == null) diffId = listDifficulties(null, possibleVariations)[0]; @@ -422,22 +423,29 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry + public function getVariationsByCharacter(?char:PlayableCharacter):Array { - if (charId == null) charId = Constants.DEFAULT_CHARACTER; + if (char == null) return variations; - if (variations.contains(charId)) + var result = []; + trace('Evaluating variations for ${this.id} ${char.id}: ${this.variations}'); + for (variation in variations) { - return [charId]; - } - else - { - // TODO: How to exclude character variations while keeping other custom variations? - return variations; + var metadata = _metadata.get(variation); + + var playerCharId = metadata?.playData?.characters?.player; + if (playerCharId == null) continue; + + if (char.shouldShowCharacter(playerCharId)) + { + result.push(variation); + } } + + return result; } /** @@ -455,6 +463,8 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry = song.listDifficulties(displayedVariations, false); - trace(availableDifficultiesForSong); + trace('Available Difficulties: $availableDifficultiesForSong'); if (availableDifficultiesForSong.length == 0) continue; songs.push(new FreeplaySongData(levelId, songId, song, displayedVariations)); @@ -454,7 +458,7 @@ class FreeplayState extends MusicBeatSubState }); // TODO: Replace this. - if (currentCharacter == 'pico') dj.visible = false; + if (currentCharacterId == 'pico') dj.visible = false; add(dj); @@ -1195,6 +1199,16 @@ class FreeplayState extends MusicBeatSubState rankAnimStart(fromResultsParams); } + if (FlxG.keys.justPressed.P) + { + FlxG.switchState(FreeplayState.build( + { + { + character: currentCharacterId == "pico" ? "bf" : "pico", + } + })); + } + // if (FlxG.keys.justPressed.H) // { // rankDisplayNew(fromResultsParams); @@ -1302,9 +1316,9 @@ class FreeplayState extends MusicBeatSubState { if (busy) return; - var upP:Bool = controls.UI_UP_P && !FlxG.keys.pressed.CONTROL; - var downP:Bool = controls.UI_DOWN_P && !FlxG.keys.pressed.CONTROL; - var accepted:Bool = controls.ACCEPT && !FlxG.keys.pressed.CONTROL; + var upP:Bool = controls.UI_UP_P; + var downP:Bool = controls.UI_DOWN_P; + var accepted:Bool = controls.ACCEPT; if (FlxG.onMobile) { @@ -1378,7 +1392,7 @@ class FreeplayState extends MusicBeatSubState } #end - if (!FlxG.keys.pressed.CONTROL && (controls.UI_UP || controls.UI_DOWN)) + if ((controls.UI_UP || controls.UI_DOWN)) { if (spamming) { @@ -1440,13 +1454,13 @@ class FreeplayState extends MusicBeatSubState } #end - if (controls.UI_LEFT_P && !FlxG.keys.pressed.CONTROL) + if (controls.UI_LEFT_P) { dj.resetAFKTimer(); changeDiff(-1); generateSongList(currentFilter, true); } - if (controls.UI_RIGHT_P && !FlxG.keys.pressed.CONTROL) + if (controls.UI_RIGHT_P) { dj.resetAFKTimer(); changeDiff(1); @@ -1720,7 +1734,7 @@ class FreeplayState extends MusicBeatSubState return; } var targetDifficultyId:String = currentDifficulty; - var targetVariation:String = targetSong.getFirstValidVariation(targetDifficultyId); + var targetVariation:String = targetSong.getFirstValidVariation(targetDifficultyId, currentCharacter); PlayStatePlaylist.campaignId = cap.songData.levelId; var targetDifficulty:SongDifficulty = targetSong.getDifficulty(targetDifficultyId, targetVariation); @@ -1730,8 +1744,18 @@ class FreeplayState extends MusicBeatSubState return; } - // TODO: Change this with alternate instrumentals - var targetInstId:String = targetDifficulty.characters.instrumental; + var baseInstrumentalId:String = targetDifficulty?.characters?.instrumental ?? ''; + var altInstrumentalIds:Array = targetDifficulty?.characters?.altInstrumentals ?? []; + + var targetInstId:String = baseInstrumentalId; + + // TODO: Make this a UI element. + #if (debug || FORCE_DEBUG_VERSION) + if (altInstrumentalIds.length > 0 && FlxG.keys.pressed.CONTROL) + { + targetInstId = altInstrumentalIds[0]; + } + #end // Visual and audio effects. FunkinSound.playOnce(Paths.sound('confirmMenu')); @@ -1883,9 +1907,23 @@ class FreeplayState extends MusicBeatSubState else { var previewSong:Null = SongRegistry.instance.fetchEntry(daSongCapsule.songData.songId); - var instSuffix:String = previewSong?.getDifficulty(currentDifficulty, - previewSong?.getVariationsByCharId(currentCharacter) ?? Constants.DEFAULT_VARIATION_LIST)?.characters?.instrumental ?? ''; + var songDifficulty = previewSong?.getDifficulty(currentDifficulty, + previewSong?.getVariationsByCharacter(currentCharacter) ?? Constants.DEFAULT_VARIATION_LIST); + var baseInstrumentalId:String = songDifficulty?.characters?.instrumental ?? ''; + var altInstrumentalIds:Array = songDifficulty?.characters?.altInstrumentals ?? []; + + var instSuffix:String = baseInstrumentalId; + + // TODO: Make this a UI element. + #if (debug || FORCE_DEBUG_VERSION) + if (altInstrumentalIds.length > 0 && FlxG.keys.pressed.CONTROL) + { + instSuffix = altInstrumentalIds[0]; + } + #end + instSuffix = (instSuffix != '') ? '-$instSuffix' : ''; + FunkinSound.playMusic(daSongCapsule.songData.songId, { startingVolume: 0.0, @@ -1914,7 +1952,7 @@ class FreeplayState extends MusicBeatSubState public static function build(?params:FreeplayStateParams, ?stickers:StickerSubState):MusicBeatState { var result:MainMenuState; - if (params?.fromResults.playRankAnim) result = new MainMenuState(true); + if (params?.fromResults?.playRankAnim) result = new MainMenuState(true); else result = new MainMenuState(false); @@ -1952,8 +1990,8 @@ class DifficultySelector extends FlxSprite override function update(elapsed:Float):Void { - if (flipX && controls.UI_RIGHT_P && !FlxG.keys.pressed.CONTROL) moveShitDown(); - if (!flipX && controls.UI_LEFT_P && !FlxG.keys.pressed.CONTROL) moveShitDown(); + if (flipX && controls.UI_RIGHT_P) moveShitDown(); + if (!flipX && controls.UI_LEFT_P) moveShitDown(); super.update(elapsed); } diff --git a/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx b/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx new file mode 100644 index 000000000..743345004 --- /dev/null +++ b/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx @@ -0,0 +1,108 @@ +package funkin.ui.freeplay.charselect; + +import funkin.data.IRegistryEntry; +import funkin.data.freeplay.player.PlayerData; +import funkin.data.freeplay.player.PlayerRegistry; + +/** + * An object used to retrieve data about a playable character (also known as "weeks"). + * Can be scripted to override each function, for custom behavior. + */ +class PlayableCharacter implements IRegistryEntry +{ + /** + * The ID of the playable character. + */ + public final id:String; + + /** + * Playable character data as parsed from the JSON file. + */ + public final _data:PlayerData; + + /** + * @param id The ID of the JSON file to parse. + */ + public function new(id:String) + { + this.id = id; + _data = _fetchData(id); + + if (_data == null) + { + throw 'Could not parse playable character data for id: $id'; + } + } + + /** + * Retrieve the readable name of the playable character. + */ + public function getName():String + { + // TODO: Maybe add localization support? + return _data.name; + } + + /** + * Retrieve the list of stage character IDs associated with this playable character. + * @return The list of associated character IDs + */ + public function getOwnedCharacterIds():Array + { + return _data.ownedChars; + } + + /** + * Return `true` if, when this character is selected in Freeplay, + * songs unassociated with a specific character should appear. + */ + public function shouldShowUnownedChars():Bool + { + return _data.showUnownedChars; + } + + public function shouldShowCharacter(id:String):Bool + { + if (_data.ownedChars.contains(id)) + { + return true; + } + + if (_data.showUnownedChars) + { + var result = !PlayerRegistry.instance.isCharacterOwned(id); + return result; + } + + return false; + } + + /** + * Returns whether this character is unlocked. + */ + public function isUnlocked():Bool + { + return _data.unlocked; + } + + /** + * Called when the character is destroyed. + * TODO: Document when this gets called + */ + public function destroy():Void {} + + public function toString():String + { + return 'PlayableCharacter($id)'; + } + + /** + * Retrieve and parse the JSON data for a playable character by ID. + * @param id The ID of the character + * @return The parsed player data, or null if not found or invalid + */ + static function _fetchData(id:String):Null + { + return PlayerRegistry.instance.parseEntryDataWithMigration(id, PlayerRegistry.instance.fetchEntryVersion(id)); + } +} diff --git a/source/funkin/ui/freeplay/charselect/ScriptedPlayableCharacter.hx b/source/funkin/ui/freeplay/charselect/ScriptedPlayableCharacter.hx new file mode 100644 index 000000000..f75a58092 --- /dev/null +++ b/source/funkin/ui/freeplay/charselect/ScriptedPlayableCharacter.hx @@ -0,0 +1,8 @@ +package funkin.ui.freeplay.charselect; + +/** + * A script that can be tied to a PlayableCharacter. + * Create a scripted class that extends PlayableCharacter to use this. + */ +@:hscriptClass +class ScriptedPlayableCharacter extends funkin.ui.freeplay.charselect.PlayableCharacter implements polymod.hscript.HScriptedClass {} diff --git a/source/funkin/util/VersionUtil.hx b/source/funkin/util/VersionUtil.hx index 832ce008a..9bf46a188 100644 --- a/source/funkin/util/VersionUtil.hx +++ b/source/funkin/util/VersionUtil.hx @@ -24,7 +24,6 @@ class VersionUtil try { var versionRaw:thx.semver.Version.SemVer = version; - trace('${versionRaw} satisfies (${versionRule})? ${version.satisfies(versionRule)}'); return version.satisfies(versionRule); } catch (e) From 5c2bad888d520117d81264d4690dd046cb1d208b Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 18 Jun 2024 20:07:27 -0400 Subject: [PATCH 388/870] Make Boyfriend DJ animations data driven --- .../funkin/data/freeplay/player/PlayerData.hx | 93 +++++ source/funkin/ui/freeplay/DJBoyfriend.hx | 371 ------------------ source/funkin/ui/freeplay/FreeplayDJ.hx | 369 +++++++++++++++++ source/funkin/ui/freeplay/FreeplayState.hx | 24 +- .../freeplay/charselect/PlayableCharacter.hx | 5 + source/funkin/util/tools/MapTools.hx | 4 + 6 files changed, 483 insertions(+), 383 deletions(-) delete mode 100644 source/funkin/ui/freeplay/DJBoyfriend.hx create mode 100644 source/funkin/ui/freeplay/FreeplayDJ.hx diff --git a/source/funkin/data/freeplay/player/PlayerData.hx b/source/funkin/data/freeplay/player/PlayerData.hx index d7b814584..10fc54b78 100644 --- a/source/funkin/data/freeplay/player/PlayerData.hx +++ b/source/funkin/data/freeplay/player/PlayerData.hx @@ -31,6 +31,12 @@ class PlayerData @:default(false) public var showUnownedChars:Bool = false; + /** + * Data for displaying this character in the Freeplay menu. + * If null, display no DJ. + */ + public var freeplayDJ:Null = null; + /** * Whether this character is unlocked by default. * Use a ScriptedPlayableCharacter to add custom logic. @@ -61,3 +67,90 @@ class PlayerData this.version = PlayerRegistry.PLAYER_DATA_VERSION; } } + +class PlayerFreeplayDJData +{ + var assetPath:String; + var animations:Array; + + @:jignored + var animationMap:Map; + + @:optional + var cartoon:Null; + + public function new() + { + animationMap = new Map(); + } + + function mapAnimations() + { + if (animationMap == null) animationMap = new Map(); + + animationMap.clear(); + for (anim in animations) + { + animationMap.set(anim.name, anim); + } + } + + public function getAtlasPath():String + { + return Paths.animateAtlas(assetPath); + } + + public function getAnimationPrefix(name:String):Null + { + if (animationMap.size() == 0) mapAnimations(); + + var anim = animationMap.get(name); + if (anim == null) return null; + return anim.prefix; + } + + public function getAnimationOffsets(name:String):Null> + { + if (animationMap.size() == 0) mapAnimations(); + + var anim = animationMap.get(name); + if (anim == null) return null; + return anim.offsets; + } + + // TODO: These should really be frame labels, ehe. + + public function getCartoonSoundClickFrame():Int + { + return cartoon?.soundClickFrame ?? 80; + } + + public function getCartoonSoundCartoonFrame():Int + { + return cartoon?.soundCartoonFrame ?? 85; + } + + public function getCartoonLoopBlinkFrame():Int + { + return cartoon?.loopBlinkFrame ?? 112; + } + + public function getCartoonLoopFrame():Int + { + return cartoon?.loopFrame ?? 166; + } + + public function getCartoonChannelChangeFrame():Int + { + return cartoon?.channelChangeFrame ?? 60; + } +} + +typedef PlayerFreeplayDJCartoonData = +{ + var soundClickFrame:Int; + var soundCartoonFrame:Int; + var loopBlinkFrame:Int; + var loopFrame:Int; + var channelChangeFrame:Int; +} diff --git a/source/funkin/ui/freeplay/DJBoyfriend.hx b/source/funkin/ui/freeplay/DJBoyfriend.hx deleted file mode 100644 index bbf043dd4..000000000 --- a/source/funkin/ui/freeplay/DJBoyfriend.hx +++ /dev/null @@ -1,371 +0,0 @@ -package funkin.ui.freeplay; - -import flixel.FlxSprite; -import flixel.util.FlxSignal; -import funkin.util.assets.FlxAnimationUtil; -import funkin.graphics.adobeanimate.FlxAtlasSprite; -import funkin.audio.FunkinSound; -import flixel.util.FlxTimer; -import funkin.audio.FunkinSound; -import funkin.audio.FlxStreamSound; - -class DJBoyfriend extends FlxAtlasSprite -{ - // Represents the sprite's current status. - // Without state machines I would have driven myself crazy years ago. - public var currentState:DJBoyfriendState = Intro; - - // A callback activated when the intro animation finishes. - public var onIntroDone:FlxSignal = new FlxSignal(); - - // A callback activated when Boyfriend gets spooked. - public var onSpook:FlxSignal = new FlxSignal(); - - // playAnim stolen from Character.hx, cuz im lazy lol! - // TODO: Switch this class to use SwagSprite instead. - public var animOffsets:Map>; - - var gotSpooked:Bool = false; - - static final SPOOK_PERIOD:Float = 60.0; - static final TV_PERIOD:Float = 120.0; - - // Time since dad last SPOOKED you. - var timeSinceSpook:Float = 0; - - public function new(x:Float, y:Float) - { - super(x, y, Paths.animateAtlas("freeplay/freeplay-boyfriend", "preload")); - - animOffsets = new Map>(); - - anim.callback = function(name, number) { - switch (name) - { - case "Boyfriend DJ watchin tv OG": - if (number == 80) - { - FunkinSound.playOnce(Paths.sound('remote_click')); - } - if (number == 85) - { - runTvLogic(); - } - default: - } - }; - - setupAnimations(); - - FlxG.debugger.track(this); - FlxG.console.registerObject("dj", this); - - anim.onComplete = onFinishAnim; - - FlxG.console.registerFunction("tv", function() { - currentState = TV; - }); - } - - /* - [remote hand under,boyfriend top head,brim piece,arm cringe l,red lazer,dj arm in,bf fist pump arm,hand raised right,forearm left,fist shaking,bf smile eyes closed face,arm cringe r,bf clenched face,face shrug,boyfriend falling,blue tint 1,shirt sleeve,bf clenched fist,head BF relaxed,blue tint 2,hand down left,blue tint 3,blue tint 4,head less smooshed,blue tint 5,boyfriend freeplay,BF head slight turn,blue tint 6,arm shrug l,blue tint 7,shoulder raised w sleeve,blue tint 8,fist pump face,blue tint 9,foot rested light,hand turnaround,arm chill right,Boyfriend DJ,arm shrug r,head back bf,hat top piece,dad bod,face surprise snap,Boyfriend DJ fist pump,office chair,foot rested right,chest down,office chair upright,body chill,bf dj afk,head mouth open dad,BF Head defalt HAIR BLOWING,hand shrug l,face piece,foot wag,turn table,shoulder up left,turntable lights,boyfriend dj body shirt blowing,body chunk turned,hand down right,dj arm out,hand shrug r,body chest out,rave hand,palm,chill face default,head back semi bf,boyfriend bottom head,DJ arm,shoulder right dad,bf surprise,boyfriend dj body,hs1,Boyfriend DJ watchin tv OG,spinning disk,hs2,arm chill left,boyfriend dj intro,hs3,hs4,chill face extra,hs5,remote hand upright,hs6,pant over table,face surprise,bf arm peace,arm turnaround,bf eyes 1,arm slammed table,eye squit,leg BF,head mid piece,arm backing,arm swoopin in,shoe right lowering,forearm right,hand out,blue tint 10,body falling back,remote thumb press,shoulder,hair spike single,bf bent - arm,crt,foot raised right,dad hand,chill face 1,chill face 2,clenched fist,head SMOOSHED,shoulder left dad,df1,body chunk upright,df2,df3,df4,hat front piece,df5,foot rested right 2,hand in,arm spun,shoe raised left,bf 1 finger hand,bf mouth 1,Boyfriend DJ confirm,forearm down ,hand raised left,remote thumb up] - */ - override public function listAnimations():Array - { - var anims:Array = []; - @:privateAccess - for (animKey in anim.symbolDictionary) - { - anims.push(animKey.name); - } - return anims; - } - - var lowPumpLoopPoint:Int = 4; - - public override function update(elapsed:Float):Void - { - super.update(elapsed); - - switch (currentState) - { - case Intro: - // Play the intro animation then leave this state immediately. - if (getCurrentAnimation() != 'boyfriend dj intro') playFlashAnimation('boyfriend dj intro', true); - timeSinceSpook = 0; - case Idle: - // We are in this state the majority of the time. - if (getCurrentAnimation() != 'Boyfriend DJ') - { - playFlashAnimation('Boyfriend DJ', true); - } - - if (getCurrentAnimation() == 'Boyfriend DJ' && this.isLoopFinished()) - { - if (timeSinceSpook >= SPOOK_PERIOD && !gotSpooked) - { - currentState = Spook; - } - else if (timeSinceSpook >= TV_PERIOD) - { - currentState = TV; - } - } - timeSinceSpook += elapsed; - 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') - { - onSpook.dispatch(); - playFlashAnimation('bf dj afk', false); - gotSpooked = true; - } - timeSinceSpook = 0; - case TV: - if (getCurrentAnimation() != 'Boyfriend DJ watchin tv OG') playFlashAnimation('Boyfriend DJ watchin tv OG', true); - timeSinceSpook = 0; - default: - // I shit myself. - } - - if (FlxG.keys.pressed.CONTROL) - { - if (FlxG.keys.justPressed.LEFT) - { - this.offsetX -= FlxG.keys.pressed.ALT ? 0.1 : (FlxG.keys.pressed.SHIFT ? 10.0 : 1.0); - } - - if (FlxG.keys.justPressed.RIGHT) - { - this.offsetX += FlxG.keys.pressed.ALT ? 0.1 : (FlxG.keys.pressed.SHIFT ? 10.0 : 1.0); - } - - if (FlxG.keys.justPressed.UP) - { - this.offsetY -= FlxG.keys.pressed.ALT ? 0.1 : (FlxG.keys.pressed.SHIFT ? 10.0 : 1.0); - } - - if (FlxG.keys.justPressed.DOWN) - { - this.offsetY += FlxG.keys.pressed.ALT ? 0.1 : (FlxG.keys.pressed.SHIFT ? 10.0 : 1.0); - } - - if (FlxG.keys.justPressed.SPACE) - { - currentState = (currentState == Idle ? TV : Idle); - } - } - } - - function onFinishAnim():Void - { - var name = anim.curSymbol.name; - switch (name) - { - case "boyfriend dj intro": - // trace('Finished intro'); - currentState = Idle; - onIntroDone.dispatch(); - case "Boyfriend DJ": - // trace('Finished idle'); - case "bf dj afk": - // trace('Finished spook'); - 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; - - // BF switches channels when the video ends, or at a 10% chance each time his idle loops. - if (FlxG.random.bool(5)) - { - frame = 60; - // boyfriend switches channel code? - // runTvLogic(); - } - trace('Replay idle: ${frame}'); - anim.play("Boyfriend DJ watchin tv OG", true, false, frame); - // trace('Finished confirm'); - } - } - - public function resetAFKTimer():Void - { - timeSinceSpook = 0; - gotSpooked = false; - } - - var offsetX:Float = 0.0; - var offsetY:Float = 0.0; - - function setupAnimations():Void - { - // Intro - addOffset('boyfriend dj intro', 8.0 - 1.3, 3.0 - 0.4); - - // Idle - addOffset('Boyfriend DJ', 0, 0); - - // Confirm - addOffset('Boyfriend DJ confirm', 0, 0); - - // AFK: Spook - addOffset('bf dj afk', 649.5, 58.5); - - // AFK: TV - addOffset('Boyfriend DJ watchin tv OG', 0, 0); - } - - var cartoonSnd:Null = null; - - public var playingCartoon:Bool = false; - - public function runTvLogic() - { - if (cartoonSnd == null) - { - // tv is OFF, but getting turned on - FunkinSound.playOnce(Paths.sound('tv_on'), 1.0, function() { - loadCartoon(); - }); - } - else - { - // plays it smidge after the click - FunkinSound.playOnce(Paths.sound('channel_switch'), 1.0, function() { - cartoonSnd.destroy(); - loadCartoon(); - }); - } - - // loadCartoon(); - } - - function loadCartoon() - { - cartoonSnd = FunkinSound.load(Paths.sound(getRandomFlashToon()), 1.0, false, true, true, function() { - anim.play("Boyfriend DJ watchin tv OG", true, false, 60); - }); - - // Fade out music to 40% volume over 1 second. - // This helps make the TV a bit more audible. - FlxG.sound.music.fadeOut(1.0, 0.1); - - // Play the cartoon at a random time between the start and 5 seconds from the end. - cartoonSnd.time = FlxG.random.float(0, Math.max(cartoonSnd.length - (5 * Constants.MS_PER_SEC), 0.0)); - } - - final cartoonList:Array = openfl.utils.Assets.list().filter(function(path) return path.startsWith("assets/sounds/cartoons/")); - - function getRandomFlashToon():String - { - var randomFile = FlxG.random.getObject(cartoonList); - - // Strip folder prefix - randomFile = randomFile.replace("assets/sounds/", ""); - // Strip file extension - randomFile = randomFile.substring(0, randomFile.length - 4); - - return randomFile; - } - - public function confirm():Void - { - 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]; - } - - override public function getCurrentAnimation():String - { - if (this.anim == null || this.anim.curSymbol == null) return ""; - return this.anim.curSymbol.name; - } - - public function playFlashAnimation(id:String, ?Force:Bool = false, ?Reverse:Bool = false, ?Frame:Int = 0):Void - { - anim.play(id, Force, Reverse, Frame); - applyAnimOffset(); - } - - function applyAnimOffset() - { - var AnimName = getCurrentAnimation(); - var daOffset = animOffsets.get(AnimName); - if (animOffsets.exists(AnimName)) - { - var xValue = daOffset[0]; - var yValue = daOffset[1]; - if (AnimName == "Boyfriend DJ watchin tv OG") - { - xValue += offsetX; - yValue += offsetY; - } - - offset.set(xValue, yValue); - } - else - { - offset.set(0, 0); - } - } - - public override function destroy():Void - { - super.destroy(); - - if (cartoonSnd != null) - { - cartoonSnd.destroy(); - cartoonSnd = null; - } - } -} - -enum DJBoyfriendState -{ - Intro; - Idle; - Confirm; - PumpIntro; - FistPump; - Spook; - TV; -} diff --git a/source/funkin/ui/freeplay/FreeplayDJ.hx b/source/funkin/ui/freeplay/FreeplayDJ.hx new file mode 100644 index 000000000..f9effe793 --- /dev/null +++ b/source/funkin/ui/freeplay/FreeplayDJ.hx @@ -0,0 +1,369 @@ +package funkin.ui.freeplay; + +import flixel.FlxSprite; +import flixel.util.FlxSignal; +import funkin.util.assets.FlxAnimationUtil; +import funkin.graphics.adobeanimate.FlxAtlasSprite; +import funkin.audio.FunkinSound; +import flixel.util.FlxTimer; +import funkin.data.freeplay.player.PlayerRegistry; +import funkin.data.freeplay.player.PlayerData.PlayerFreeplayDJData; +import funkin.audio.FunkinSound; +import funkin.audio.FlxStreamSound; + +class FreeplayDJ extends FlxAtlasSprite +{ + // Represents the sprite's current status. + // Without state machines I would have driven myself crazy years ago. + public var currentState:DJBoyfriendState = Intro; + + // A callback activated when the intro animation finishes. + public var onIntroDone:FlxSignal = new FlxSignal(); + + // A callback activated when the idle easter egg plays. + public var onIdleEasterEgg:FlxSignal = new FlxSignal(); + + var seenIdleEasterEgg:Bool = false; + + static final IDLE_EGG_PERIOD:Float = 60.0; + static final IDLE_CARTOON_PERIOD:Float = 120.0; + + // Time since last special idle animation you. + var timeIdling:Float = 0; + + final characterId:String = Constants.DEFAULT_CHARACTER; + final playableCharData:PlayerFreeplayDJData; + + public function new(x:Float, y:Float, characterId:String) + { + this.characterId = characterId; + + var playableChar = PlayerRegistry.instance.fetchEntry(characterId); + playableCharData = playableChar.getFreeplayDJData(); + + super(x, y, playableCharData.getAtlasPath()); + + anim.callback = function(name, number) { + if (name == playableCharData.getAnimationPrefix('cartoon')) + { + if (number == playableCharData.getCartoonSoundClickFrame()) + { + FunkinSound.playOnce(Paths.sound('remote_click')); + } + if (number == playableCharData.getCartoonSoundCartoonFrame()) + { + runTvLogic(); + } + } + }; + + FlxG.debugger.track(this); + FlxG.console.registerObject("dj", this); + + anim.onComplete = onFinishAnim; + + FlxG.console.registerFunction("freeplayCartoon", function() { + currentState = Cartoon; + }); + } + + override public function listAnimations():Array + { + var anims:Array = []; + @:privateAccess + for (animKey in anim.symbolDictionary) + { + anims.push(animKey.name); + } + return anims; + } + + var lowPumpLoopPoint:Int = 4; + + public override function update(elapsed:Float):Void + { + super.update(elapsed); + + switch (currentState) + { + case Intro: + // Play the intro animation then leave this state immediately. + var animPrefix = playableCharData.getAnimationPrefix('intro'); + if (getCurrentAnimation() != animPrefix) playFlashAnimation(animPrefix, true); + timeIdling = 0; + case Idle: + // We are in this state the majority of the time. + var animPrefix = playableCharData.getAnimationPrefix('idle'); + if (getCurrentAnimation() != animPrefix) + { + playFlashAnimation(animPrefix, true); + } + + if (getCurrentAnimation() == animPrefix && this.isLoopFinished()) + { + if (timeIdling >= IDLE_EGG_PERIOD && !seenIdleEasterEgg) + { + currentState = IdleEasterEgg; + } + else if (timeIdling >= IDLE_CARTOON_PERIOD) + { + currentState = Cartoon; + } + } + timeIdling += elapsed; + case Confirm: + var animPrefix = playableCharData.getAnimationPrefix('confirm'); + if (getCurrentAnimation() != animPrefix) playFlashAnimation(animPrefix, false); + timeIdling = 0; + case FistPumpIntro: + var animPrefix = playableCharData.getAnimationPrefix('fistPump'); + if (getCurrentAnimation() != animPrefix) playFlashAnimation('Boyfriend DJ fist pump', false); + if (getCurrentAnimation() == animPrefix && anim.curFrame >= 4) + { + anim.play("Boyfriend DJ fist pump", true, false, 0); + } + case FistPump: + + case IdleEasterEgg: + var animPrefix = playableCharData.getAnimationPrefix('idleEasterEgg'); + if (getCurrentAnimation() != animPrefix) + { + onIdleEasterEgg.dispatch(); + playFlashAnimation(animPrefix, false); + seenIdleEasterEgg = true; + } + timeIdling = 0; + case Cartoon: + var animPrefix = playableCharData.getAnimationPrefix('cartoon'); + if (getCurrentAnimation() != animPrefix) playFlashAnimation(animPrefix, true); + timeIdling = 0; + default: + // I shit myself. + } + + if (FlxG.keys.pressed.CONTROL) + { + if (FlxG.keys.justPressed.LEFT) + { + this.offsetX -= FlxG.keys.pressed.ALT ? 0.1 : (FlxG.keys.pressed.SHIFT ? 10.0 : 1.0); + } + + if (FlxG.keys.justPressed.RIGHT) + { + this.offsetX += FlxG.keys.pressed.ALT ? 0.1 : (FlxG.keys.pressed.SHIFT ? 10.0 : 1.0); + } + + if (FlxG.keys.justPressed.UP) + { + this.offsetY -= FlxG.keys.pressed.ALT ? 0.1 : (FlxG.keys.pressed.SHIFT ? 10.0 : 1.0); + } + + if (FlxG.keys.justPressed.DOWN) + { + this.offsetY += FlxG.keys.pressed.ALT ? 0.1 : (FlxG.keys.pressed.SHIFT ? 10.0 : 1.0); + } + + if (FlxG.keys.justPressed.SPACE) + { + currentState = (currentState == Idle ? Cartoon : Idle); + } + } + } + + function onFinishAnim():Void + { + var name = anim.curSymbol.name; + + if (name == playableCharData.getAnimationPrefix('intro')) + { + currentState = Idle; + onIntroDone.dispatch(); + } + else if (name == playableCharData.getAnimationPrefix('idle')) + { + // trace('Finished idle'); + } + else if (name == playableCharData.getAnimationPrefix('confirm')) + { + // trace('Finished confirm'); + } + else if (name == playableCharData.getAnimationPrefix('fistPump')) + { + // trace('Finished fist pump'); + currentState = Idle; + } + else if (name == playableCharData.getAnimationPrefix('idleEasterEgg')) + { + // trace('Finished spook'); + currentState = Idle; + } + else if (name == playableCharData.getAnimationPrefix('loss')) + { + // trace('Finished loss reaction'); + currentState = Idle; + } + else if (name == playableCharData.getAnimationPrefix('cartoon')) + { + // trace('Finished cartoon'); + + var frame:Int = FlxG.random.bool(33) ? playableCharData.getCartoonLoopBlinkFrame() : playableCharData.getCartoonLoopFrame(); + + // Character switches channels when the video ends, or at a 10% chance each time his idle loops. + if (FlxG.random.bool(5)) + { + frame = playableCharData.getCartoonChannelChangeFrame(); + // boyfriend switches channel code? + // runTvLogic(); + } + trace('Replay idle: ${frame}'); + anim.play(playableCharData.getAnimationPrefix('cartoon'), true, false, frame); + // trace('Finished confirm'); + } + else + { + trace('Finished ${name}'); + } + } + + public function resetAFKTimer():Void + { + timeIdling = 0; + seenIdleEasterEgg = false; + } + + var offsetX:Float = 0.0; + var offsetY:Float = 0.0; + + var cartoonSnd:Null = null; + + public var playingCartoon:Bool = false; + + public function runTvLogic() + { + if (cartoonSnd == null) + { + // tv is OFF, but getting turned on + FunkinSound.playOnce(Paths.sound('tv_on'), 1.0, function() { + loadCartoon(); + }); + } + else + { + // plays it smidge after the click + FunkinSound.playOnce(Paths.sound('channel_switch'), 1.0, function() { + cartoonSnd.destroy(); + loadCartoon(); + }); + } + + // loadCartoon(); + } + + function loadCartoon() + { + cartoonSnd = FunkinSound.load(Paths.sound(getRandomFlashToon()), 1.0, false, true, true, function() { + anim.play("Boyfriend DJ watchin tv OG", true, false, 60); + }); + + // Fade out music to 40% volume over 1 second. + // This helps make the TV a bit more audible. + FlxG.sound.music.fadeOut(1.0, 0.1); + + // Play the cartoon at a random time between the start and 5 seconds from the end. + cartoonSnd.time = FlxG.random.float(0, Math.max(cartoonSnd.length - (5 * Constants.MS_PER_SEC), 0.0)); + } + + final cartoonList:Array = openfl.utils.Assets.list().filter(function(path) return path.startsWith("assets/sounds/cartoons/")); + + function getRandomFlashToon():String + { + var randomFile = FlxG.random.getObject(cartoonList); + + // Strip folder prefix + randomFile = randomFile.replace("assets/sounds/", ""); + // Strip file extension + randomFile = randomFile.substring(0, randomFile.length - 4); + + return randomFile; + } + + public function confirm():Void + { + currentState = Confirm; + } + + public function fistPump():Void + { + currentState = FistPumpIntro; + } + + 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); + } + + override public function getCurrentAnimation():String + { + if (this.anim == null || this.anim.curSymbol == null) return ""; + return this.anim.curSymbol.name; + } + + public function playFlashAnimation(id:String, ?Force:Bool = false, ?Reverse:Bool = false, ?Frame:Int = 0):Void + { + anim.play(id, Force, Reverse, Frame); + applyAnimOffset(); + } + + function applyAnimOffset() + { + var AnimName = getCurrentAnimation(); + var daOffset = playableCharData.getAnimationOffsets(AnimName); + if (daOffset != null) + { + var xValue = daOffset[0]; + var yValue = daOffset[1]; + if (AnimName == "Boyfriend DJ watchin tv OG") + { + xValue += offsetX; + yValue += offsetY; + } + + trace('Successfully applied offset: ' + xValue + ', ' + yValue); + offset.set(xValue, yValue); + } + else + { + trace('No offset found, defaulting to: 0, 0'); + offset.set(0, 0); + } + } + + public override function destroy():Void + { + super.destroy(); + + if (cartoonSnd != null) + { + cartoonSnd.destroy(); + cartoonSnd = null; + } + } +} + +enum DJBoyfriendState +{ + Intro; + Idle; + Confirm; + FistPumpIntro; + FistPump; + IdleEasterEgg; + Cartoon; +} diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 9f23440df..98e48b338 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -167,7 +167,7 @@ class FreeplayState extends MusicBeatSubState var curCapsule:SongMenuItem; var curPlaying:Bool = false; - var dj:DJBoyfriend; + var dj:FreeplayDJ; var ostName:FlxText; var albumRoll:AlbumRoll; @@ -211,6 +211,7 @@ class FreeplayState extends MusicBeatSubState { currentCharacterId = params?.character ?? Constants.DEFAULT_CHARACTER; currentCharacter = PlayerRegistry.instance.fetchEntry(currentCharacterId); + if (currentCharacter == null) throw 'Could not build Freeplay state for character: $currentCharacterId'; fromResultsParams = params?.fromResults; @@ -450,17 +451,16 @@ class FreeplayState extends MusicBeatSubState add(cardGlow); - dj = new DJBoyfriend(640, 366); - exitMovers.set([dj], - { - x: -dj.width * 1.6, - speed: 0.5 - }); - - // TODO: Replace this. - if (currentCharacterId == 'pico') dj.visible = false; - - add(dj); + if (currentCharacter?.getFreeplayDJData() != null) + { + dj = new FreeplayDJ(640, 366, currentCharacterId); + exitMovers.set([dj], + { + x: -dj.width * 1.6, + speed: 0.5 + }); + add(dj); + } bgDad = new FlxSprite(pinkBack.width * 0.74, 0).loadGraphic(Paths.image('freeplay/freeplayBGdad')); bgDad.shader = new AngleMask(); diff --git a/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx b/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx index 743345004..282e35d7a 100644 --- a/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx +++ b/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx @@ -77,6 +77,11 @@ class PlayableCharacter implements IRegistryEntry return false; } + public function getFreeplayDJData():PlayerFreeplayDJData + { + return _data.freeplayDJ; + } + /** * Returns whether this character is unlocked. */ diff --git a/source/funkin/util/tools/MapTools.hx b/source/funkin/util/tools/MapTools.hx index b98cb0adf..807f0aebd 100644 --- a/source/funkin/util/tools/MapTools.hx +++ b/source/funkin/util/tools/MapTools.hx @@ -14,6 +14,7 @@ class MapTools */ public static function size(map:Map):Int { + if (map == null) return 0; return map.keys().array().length; } @@ -22,6 +23,7 @@ class MapTools */ public static function values(map:Map):Array { + if (map == null) return []; return [for (i in map.iterator()) i]; } @@ -30,6 +32,7 @@ class MapTools */ public static function clone(map:Map):Map { + if (map == null) return null; return map.copy(); } @@ -76,6 +79,7 @@ class MapTools */ public static function keyValues(map:Map):Array { + if (map == null) return []; return map.keys().array(); } } From ad57e64994dd8a9f5494d4c6984c9686448ef105 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 20 Jun 2024 16:17:53 -0400 Subject: [PATCH 389/870] Working Pico DJ --- source/funkin/Paths.hx | 11 +- .../funkin/data/freeplay/player/PlayerData.hx | 42 ++- source/funkin/play/scoring/Scoring.hx | 4 +- source/funkin/ui/freeplay/FreeplayDJ.hx | 14 +- source/funkin/ui/freeplay/FreeplayState.hx | 280 ++++++++++-------- .../freeplay/charselect/PlayableCharacter.hx | 5 + source/funkin/ui/mainmenu/MainMenuState.hx | 5 +- source/funkin/util/SortUtil.hx | 2 +- 8 files changed, 217 insertions(+), 146 deletions(-) diff --git a/source/funkin/Paths.hx b/source/funkin/Paths.hx index b0a97c4fa..285af7ca2 100644 --- a/source/funkin/Paths.hx +++ b/source/funkin/Paths.hx @@ -11,9 +11,16 @@ class Paths { static var currentLevel:Null = null; - public static function setCurrentLevel(name:String):Void + public static function setCurrentLevel(name:Null):Void { - currentLevel = name.toLowerCase(); + if (name == null) + { + currentLevel = null; + } + else + { + currentLevel = name.toLowerCase(); + } } public static function stripLibrary(path:String):String diff --git a/source/funkin/data/freeplay/player/PlayerData.hx b/source/funkin/data/freeplay/player/PlayerData.hx index 10fc54b78..c461c9555 100644 --- a/source/funkin/data/freeplay/player/PlayerData.hx +++ b/source/funkin/data/freeplay/player/PlayerData.hx @@ -35,6 +35,7 @@ class PlayerData * Data for displaying this character in the Freeplay menu. * If null, display no DJ. */ + @:optional public var freeplayDJ:Null = null; /** @@ -73,9 +74,25 @@ class PlayerFreeplayDJData var assetPath:String; var animations:Array; + @:optional + @:default("BOYFRIEND") + var text1:String; + + @:optional + @:default("HOT BLOODED IN MORE WAYS THAN ONE") + var text2:String; + + @:optional + @:default("PROTECT YO NUTS") + var text3:String; + + @:jignored var animationMap:Map; + @:jignored + var prefixToOffsetsMap:Map>; + @:optional var cartoon:Null; @@ -87,11 +104,14 @@ class PlayerFreeplayDJData function mapAnimations() { if (animationMap == null) animationMap = new Map(); + if (prefixToOffsetsMap == null) prefixToOffsetsMap = new Map(); animationMap.clear(); + prefixToOffsetsMap.clear(); for (anim in animations) { animationMap.set(anim.name, anim); + prefixToOffsetsMap.set(anim.prefix, anim.offsets); } } @@ -100,6 +120,15 @@ class PlayerFreeplayDJData return Paths.animateAtlas(assetPath); } + public function getFreeplayDJText(index:Int):String { + switch (index) { + case 1: return text1; + case 2: return text2; + case 3: return text3; + default: return ''; + } + } + public function getAnimationPrefix(name:String):Null { if (animationMap.size() == 0) mapAnimations(); @@ -109,13 +138,16 @@ class PlayerFreeplayDJData return anim.prefix; } - public function getAnimationOffsets(name:String):Null> + public function getAnimationOffsetsByPrefix(?prefix:String):Array { - if (animationMap.size() == 0) mapAnimations(); + if (prefixToOffsetsMap.size() == 0) mapAnimations(); + if (prefix == null) return [0, 0]; + return prefixToOffsetsMap.get(prefix); + } - var anim = animationMap.get(name); - if (anim == null) return null; - return anim.offsets; + public function getAnimationOffsets(name:String):Array + { + return getAnimationOffsetsByPrefix(getAnimationPrefix(name)); } // TODO: These should really be frame labels, ehe. diff --git a/source/funkin/play/scoring/Scoring.hx b/source/funkin/play/scoring/Scoring.hx index dc2c40647..02e5750bc 100644 --- a/source/funkin/play/scoring/Scoring.hx +++ b/source/funkin/play/scoring/Scoring.hx @@ -590,7 +590,7 @@ enum abstract ScoringRank(String) } } - public function getFreeplayRankIconAsset():Null + public function getFreeplayRankIconAsset():String { switch (abstract) { @@ -607,7 +607,7 @@ enum abstract ScoringRank(String) case SHIT: return 'LOSS'; default: - return null; + return 'LOSS'; } } diff --git a/source/funkin/ui/freeplay/FreeplayDJ.hx b/source/funkin/ui/freeplay/FreeplayDJ.hx index f9effe793..72eddd0ca 100644 --- a/source/funkin/ui/freeplay/FreeplayDJ.hx +++ b/source/funkin/ui/freeplay/FreeplayDJ.hx @@ -135,8 +135,12 @@ class FreeplayDJ extends FlxAtlasSprite timeIdling = 0; case Cartoon: var animPrefix = playableCharData.getAnimationPrefix('cartoon'); - if (getCurrentAnimation() != animPrefix) playFlashAnimation(animPrefix, true); - timeIdling = 0; + if (animPrefix == null) { + currentState = IdleEasterEgg; + } else { + if (getCurrentAnimation() != animPrefix) playFlashAnimation(animPrefix, true); + timeIdling = 0; + } default: // I shit myself. } @@ -324,7 +328,7 @@ class FreeplayDJ extends FlxAtlasSprite function applyAnimOffset() { var AnimName = getCurrentAnimation(); - var daOffset = playableCharData.getAnimationOffsets(AnimName); + var daOffset = playableCharData.getAnimationOffsetsByPrefix(AnimName); if (daOffset != null) { var xValue = daOffset[0]; @@ -335,12 +339,12 @@ class FreeplayDJ extends FlxAtlasSprite yValue += offsetY; } - trace('Successfully applied offset: ' + xValue + ', ' + yValue); + trace('Successfully applied offset ($AnimName): ' + xValue + ', ' + yValue); offset.set(xValue, yValue); } else { - trace('No offset found, defaulting to: 0, 0'); + trace('No offset found ($AnimName), defaulting to: 0, 0'); offset.set(0, 0); } } diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 98e48b338..5725101cd 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1,54 +1,55 @@ package funkin.ui.freeplay; -import funkin.graphics.adobeanimate.FlxAtlasSprite; import flixel.addons.transition.FlxTransitionableState; 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; 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; import flixel.tweens.FlxTween; +import flixel.tweens.misc.ShakeTween; import flixel.util.FlxColor; import flixel.util.FlxSpriteUtil; import flixel.util.FlxTimer; import funkin.audio.FunkinSound; -import funkin.data.story.level.LevelRegistry; -import funkin.data.song.SongRegistry; import funkin.data.freeplay.player.PlayerRegistry; +import funkin.data.song.SongRegistry; +import funkin.data.story.level.LevelRegistry; +import funkin.effects.IntervalShake; +import funkin.graphics.adobeanimate.FlxAtlasSprite; import funkin.graphics.FunkinCamera; import funkin.graphics.FunkinSprite; import funkin.graphics.shaders.AngleMask; +import funkin.graphics.shaders.GaussianBlurShader; import funkin.graphics.shaders.HSVShader; import funkin.graphics.shaders.PureColor; import funkin.graphics.shaders.StrokeShader; import funkin.input.Controls; import funkin.play.PlayStatePlaylist; +import funkin.play.scoring.Scoring; +import funkin.play.scoring.Scoring.ScoringRank; import funkin.play.song.Song; -import funkin.ui.story.Level; 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.freeplay.charselect.PlayableCharacter; +import funkin.ui.freeplay.SongMenuItem.FreeplayRank; import funkin.ui.mainmenu.MainMenuState; import funkin.ui.MusicBeatSubState; +import funkin.ui.story.Level; import funkin.ui.transition.LoadingState; import funkin.ui.transition.StickerSubState; import funkin.util.MathUtil; +import funkin.util.SortUtil; import lime.utils.Assets; -import flixel.tweens.misc.ShakeTween; -import funkin.effects.IntervalShake; -import funkin.ui.freeplay.SongMenuItem.FreeplayRank; -import funkin.ui.freeplay.charselect.PlayableCharacter; +import openfl.display.BlendMode; /** * Parameters used to initialize the FreeplayState. @@ -94,6 +95,7 @@ typedef FromResultsParams = /** * The state for the freeplay menu, allowing the player to select any song to play. */ +@:nullSafety class FreeplayState extends MusicBeatSubState { // @@ -164,10 +166,9 @@ class FreeplayState extends MusicBeatSubState var grpSongs:FlxTypedGroup; var grpCapsules:FlxTypedGroup; - var curCapsule:SongMenuItem; var curPlaying:Bool = false; - var dj:FreeplayDJ; + var dj:Null = null; var ostName:FlxText; var albumRoll:AlbumRoll; @@ -175,7 +176,7 @@ class FreeplayState extends MusicBeatSubState var letterSort:LetterSort; var exitMovers:ExitMoverData = new Map(); - var stickerSubState:StickerSubState; + var stickerSubState:Null = null; public static var rememberedDifficulty:Null = Constants.DEFAULT_DIFFICULTY; public static var rememberedSongId:Null = 'tutorial'; @@ -210,8 +211,12 @@ class FreeplayState extends MusicBeatSubState public function new(?params:FreeplayStateParams, ?stickers:StickerSubState) { currentCharacterId = params?.character ?? Constants.DEFAULT_CHARACTER; - currentCharacter = PlayerRegistry.instance.fetchEntry(currentCharacterId); - if (currentCharacter == null) throw 'Could not build Freeplay state for character: $currentCharacterId'; + var fetchPlayableCharacter = function():PlayableCharacter { + var result = PlayerRegistry.instance.fetchEntry(params?.character ?? Constants.DEFAULT_CHARACTER); + if (result == null) throw 'No valid playable character with id ${params?.character}'; + return result; + }; + currentCharacter = fetchPlayableCharacter(); fromResultsParams = params?.fromResults; @@ -220,12 +225,54 @@ class FreeplayState extends MusicBeatSubState prepForNewRank = true; } + super(FlxColor.TRANSPARENT); + if (stickers?.members != null) { stickerSubState = stickers; } - super(FlxColor.TRANSPARENT); + // We build a bunch of sprites BEFORE create() so we can guarantee they aren't null later on. + albumRoll = new AlbumRoll(); + fp = new FreeplayScore(460, 60, 7, 100); + cardGlow = new FlxSprite(-30, -30).loadGraphic(Paths.image('freeplay/cardGlow')); + confirmGlow = new FlxSprite(-30, 240).loadGraphic(Paths.image('freeplay/confirmGlow')); + confirmTextGlow = new FlxSprite(-8, 115).loadGraphic(Paths.image('freeplay/glowingText')); + rankCamera = new FunkinCamera('rankCamera', 0, 0, FlxG.width, FlxG.height); + funnyCam = new FunkinCamera('freeplayFunny', 0, 0, FlxG.width, FlxG.height); + funnyScroll = new BGScrollingText(0, 220, currentCharacter.getFreeplayDJText(1), FlxG.width / 2, false, 60); + funnyScroll2 = new BGScrollingText(0, 335, currentCharacter.getFreeplayDJText(1), FlxG.width / 2, false, 60); + grpCapsules = new FlxTypedGroup(); + grpDifficulties = new FlxTypedSpriteGroup(-300, 80); + letterSort = new LetterSort(400, 75); + grpSongs = new FlxTypedGroup(); + moreWays = new BGScrollingText(0, 160, currentCharacter.getFreeplayDJText(2), FlxG.width, true, 43); + moreWays2 = new BGScrollingText(0, 397, currentCharacter.getFreeplayDJText(2), FlxG.width, true, 43); + pinkBack = FunkinSprite.create('freeplay/pinkBack'); + rankBg = new FunkinSprite(0, 0); + rankVignette = new FlxSprite(0, 0).loadGraphic(Paths.image('freeplay/rankVignette')); + sparks = new FlxSprite(0, 0); + sparksADD = new FlxSprite(0, 0); + txtCompletion = new AtlasText(1185, 87, '69', AtlasFont.FREEPLAY_CLEAR); + txtNuts = new BGScrollingText(0, 285, currentCharacter.getFreeplayDJText(3), FlxG.width / 2, true, 43); + + ostName = new FlxText(8, 8, FlxG.width - 8 - 8, 'OFFICIAL OST', 48); + + orangeBackShit = new FunkinSprite(84, 440).makeSolidColor(Std.int(pinkBack.width), 75, 0xFFFEDA00); + + bgDad = new FlxSprite(pinkBack.width * 0.74, 0).loadGraphic(Paths.image('freeplay/freeplayBGdad')); + alsoOrangeLOL = new FunkinSprite(0, orangeBackShit.y).makeSolidColor(100, Std.int(orangeBackShit.height), 0xFFFFD400); + confirmGlow2 = new FlxSprite(confirmGlow.x, confirmGlow.y).loadGraphic(Paths.image('freeplay/confirmGlow2')); + funnyScroll3 = new BGScrollingText(0, orangeBackShit.y + 10, currentCharacter.getFreeplayDJText(1), FlxG.width / 2, 60); + 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), + }); } override function create():Void @@ -236,12 +283,6 @@ 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; @@ -277,7 +318,7 @@ class FreeplayState extends MusicBeatSubState // programmatically adds the songs via LevelRegistry and SongRegistry for (levelId in LevelRegistry.instance.listSortedLevelIds()) { - var level:Level = LevelRegistry.instance.fetchEntry(levelId); + var level:Null = LevelRegistry.instance.fetchEntry(levelId); if (level == null) { @@ -287,7 +328,7 @@ class FreeplayState extends MusicBeatSubState for (songId in level.getSongs()) { - var song:Song = SongRegistry.instance.fetchEntry(songId); + var song:Null = SongRegistry.instance.fetchEntry(songId); if (song == null) { @@ -319,17 +360,14 @@ class FreeplayState extends MusicBeatSubState trace(FlxG.camera.initialZoom); trace(FlxCamera.defaultZoom); - 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); - orangeBackShit = new FunkinSprite(84, 440).makeSolidColor(Std.int(pinkBack.width), 75, 0xFFFEDA00); add(orangeBackShit); - alsoOrangeLOL = new FunkinSprite(0, orangeBackShit.y).makeSolidColor(100, Std.int(orangeBackShit.height), 0xFFFFD400); add(alsoOrangeLOL); exitMovers.set([pinkBack, orangeBackShit, alsoOrangeLOL], @@ -344,15 +382,11 @@ 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; @@ -367,7 +401,6 @@ class FreeplayState extends MusicBeatSubState FlxG.debugger.addTrackerProfile(new TrackerProfile(BGScrollingText, ['x', 'y', 'speed', 'size'])); - 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); @@ -378,7 +411,6 @@ class FreeplayState extends MusicBeatSubState speed: 0.4, }); - funnyScroll = new BGScrollingText(0, 220, 'BOYFRIEND', FlxG.width / 2, false, 60); funnyScroll.funnyColor = 0xFFFF9963; funnyScroll.speed = -3.8; grpTxtScrolls.add(funnyScroll); @@ -391,7 +423,6 @@ class FreeplayState extends MusicBeatSubState wait: 0 }); - txtNuts = new BGScrollingText(0, 285, 'PROTECT YO NUTS', FlxG.width / 2, true, 43); txtNuts.speed = 3.5; grpTxtScrolls.add(txtNuts); exitMovers.set([txtNuts], @@ -400,7 +431,6 @@ class FreeplayState extends MusicBeatSubState speed: 0.4, }); - funnyScroll2 = new BGScrollingText(0, 335, 'BOYFRIEND', FlxG.width / 2, false, 60); funnyScroll2.funnyColor = 0xFFFF9963; funnyScroll2.speed = -3.8; grpTxtScrolls.add(funnyScroll2); @@ -411,7 +441,6 @@ class FreeplayState extends MusicBeatSubState speed: 0.5, }); - 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); @@ -422,7 +451,6 @@ class FreeplayState extends MusicBeatSubState speed: 0.4 }); - funnyScroll3 = new BGScrollingText(0, orangeBackShit.y + 10, 'BOYFRIEND', FlxG.width / 2, 60); funnyScroll3.funnyColor = 0xFFFEA400; funnyScroll3.speed = -3.8; grpTxtScrolls.add(funnyScroll3); @@ -433,19 +461,8 @@ 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; @@ -462,7 +479,6 @@ class FreeplayState extends MusicBeatSubState add(dj); } - bgDad = new FlxSprite(pinkBack.width * 0.74, 0).loadGraphic(Paths.image('freeplay/freeplayBGdad')); bgDad.shader = new AngleMask(); bgDad.visible = false; @@ -488,17 +504,13 @@ class FreeplayState extends MusicBeatSubState blackOverlayBullshitLOLXD.shader = bgDad.shader; - rankBg = new FunkinSprite(0, 0); rankBg.makeSolidColor(FlxG.width, FlxG.height, 0xD3000000); add(rankBg); - grpSongs = new FlxTypedGroup(); add(grpSongs); - grpCapsules = new FlxTypedGroup(); add(grpCapsules); - grpDifficulties = new FlxTypedSpriteGroup(-300, 80); add(grpDifficulties); exitMovers.set([grpDifficulties], @@ -525,7 +537,6 @@ class FreeplayState extends MusicBeatSubState if (diffSprite.difficultyId == currentDifficulty) diffSprite.visible = true; } - albumRoll = new AlbumRoll(); albumRoll.albumId = null; add(albumRoll); @@ -540,7 +551,6 @@ class FreeplayState extends MusicBeatSubState fnfFreeplay.font = 'VCR OSD Mono'; fnfFreeplay.visible = false; - ostName = new FlxText(8, 8, FlxG.width - 8 - 8, 'OFFICIAL OST', 48); ostName.font = 'VCR OSD Mono'; ostName.alignment = RIGHT; ostName.visible = false; @@ -572,7 +582,6 @@ class FreeplayState extends MusicBeatSubState tmr.time = FlxG.random.float(20, 60); }, 0); - fp = new FreeplayScore(460, 60, 7, 100); fp.visible = false; add(fp); @@ -580,11 +589,9 @@ class FreeplayState extends MusicBeatSubState clearBoxSprite.visible = false; add(clearBoxSprite); - txtCompletion = new AtlasText(1185, 87, '69', AtlasFont.FREEPLAY_CLEAR); txtCompletion.visible = false; add(txtCompletion); - letterSort = new LetterSort(400, 75); add(letterSort); letterSort.visible = false; @@ -632,7 +639,7 @@ class FreeplayState extends MusicBeatSubState // be careful not to "add()" things in here unless it's to a group that's already added to the state // otherwise it won't be properly attatched to funnyCamera (relavent code should be at the bottom of create()) - dj.onIntroDone.add(function() { + var onDJIntroDone = function() { // when boyfriend hits dat shiii albumRoll.playIntro(); @@ -679,20 +686,27 @@ 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) + if (prepForNewRank && fromResultsParams != null) { rankAnimStart(fromResultsParams); } - }); + }; + + if (dj != null) + { + dj.onIntroDone.add(onDJIntroDone); + } + else + { + onDJIntroDone(); + } 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); - rankVignette = new FlxSprite(0, 0).loadGraphic(Paths.image('freeplay/rankVignette')); rankVignette.scale.set(2, 2); rankVignette.updateHitbox(); rankVignette.blend = BlendMode.ADD; @@ -704,7 +718,6 @@ class FreeplayState extends MusicBeatSubState 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]; @@ -716,8 +729,8 @@ class FreeplayState extends MusicBeatSubState } } - var currentFilter:SongFilter = null; - var currentFilteredSongs:Array = []; + var currentFilter:Null = null; + var currentFilteredSongs:Array> = []; /** * Given the current filter, rebuild the current song list. @@ -728,7 +741,7 @@ class FreeplayState extends MusicBeatSubState */ public function generateSongList(filterStuff:Null, force:Bool = false, onlyIfChanged:Bool = true):Void { - var tempSongs:Array = songs; + var tempSongs:Array> = songs; // Remember just the difficulty because it's important for song sorting. if (rememberedDifficulty != null) @@ -790,11 +803,12 @@ class FreeplayState extends MusicBeatSubState for (i in 0...tempSongs.length) { - if (tempSongs[i] == null) continue; + var tempSong = tempSongs[i]; + if (tempSong == null) continue; var funnyMenu:SongMenuItem = grpCapsules.recycle(SongMenuItem); - funnyMenu.init(FlxG.width, 0, tempSongs[i]); + funnyMenu.init(FlxG.width, 0, tempSong); funnyMenu.onConfirm = function() { capsuleOnConfirmDefault(funnyMenu); }; @@ -803,8 +817,8 @@ class FreeplayState extends MusicBeatSubState funnyMenu.ID = i; funnyMenu.capsule.alpha = 0.5; funnyMenu.songText.visible = false; - funnyMenu.favIcon.visible = tempSongs[i].isFav; - funnyMenu.favIconBlurred.visible = tempSongs[i].isFav; + funnyMenu.favIcon.visible = tempSong.isFav; + funnyMenu.favIconBlurred.visible = tempSong.isFav; funnyMenu.hsvShader = hsvShader; funnyMenu.newText.animation.curAnim.curFrame = 45 - ((i * 4) % 45); @@ -828,13 +842,10 @@ class FreeplayState extends MusicBeatSubState * @param songFilter The filter to apply * @return Array */ - public function sortSongs(songsToFilter:Array, songFilter:SongFilter):Array + 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; + var filterAlphabetically = function(a:Null, b:Null):Int { + return SortUtil.alphabetically(a?.songName ?? '', b?.songName ?? ''); }; switch (songFilter.filterType) @@ -858,7 +869,7 @@ class FreeplayState extends MusicBeatSubState songsToFilter = songsToFilter.filter(str -> { if (str == null) return true; // Random - return str.songName.toLowerCase().startsWith(songFilter.filterData); + return str.songName.toLowerCase().startsWith(songFilter.filterData ?? ''); }); case ALL: // no filter! @@ -880,32 +891,28 @@ class FreeplayState extends MusicBeatSubState var sparks:FlxSprite; var sparksADD:FlxSprite; - function rankAnimStart(fromResults:Null):Void + function rankAnimStart(fromResults:FromResultsParams):Void { busy = true; grpCapsules.members[curSelected].sparkle.alpha = 0; // grpCapsules.members[curSelected].forcePosition(); - if (fromResults != null) - { - rememberedSongId = fromResults.songId; - rememberedDifficulty = fromResults.difficultyId; - changeSelection(); - changeDiff(); - } + rememberedSongId = fromResults.songId; + rememberedDifficulty = fromResults.difficultyId; + changeSelection(); + changeDiff(); - dj.fistPump(); + if (dj != null) dj.fistPump(); // rankCamera.fade(FlxColor.BLACK, 0.5, true); rankCamera.fade(0xFF000000, 0.5, true, null, true); if (FlxG.sound.music != null) FlxG.sound.music.volume = 0; rankBg.alpha = 1; - if (fromResults?.oldRank != null) + 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; @@ -915,7 +922,6 @@ class FreeplayState extends MusicBeatSubState 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); @@ -980,14 +986,14 @@ class FreeplayState extends MusicBeatSubState grpCapsules.members[curSelected].ranking.scale.set(20, 20); grpCapsules.members[curSelected].blurredRanking.scale.set(20, 20); - if (fromResults?.newRank != null) + if (fromResults != null && fromResults.newRank != null) { grpCapsules.members[curSelected].ranking.animation.play(fromResults.newRank.getFreeplayRankIconAsset(), true); } FlxTween.tween(grpCapsules.members[curSelected].ranking, {"scale.x": 1, "scale.y": 1}, 0.1); - if (fromResults?.newRank != null) + if (fromResults != null && fromResults.newRank != null) { grpCapsules.members[curSelected].blurredRanking.animation.play(fromResults.newRank.getFreeplayRankIconAsset(), true); } @@ -1078,11 +1084,11 @@ class FreeplayState extends MusicBeatSubState if (fromResultsParams?.newRank == SHIT) { - dj.pumpFistBad(); + if (dj != null) dj.pumpFistBad(); } else { - dj.pumpFist(); + if (dj != null) dj.pumpFist(); } rankCamera.zoom = 0.8; @@ -1196,7 +1202,13 @@ class FreeplayState extends MusicBeatSubState #if debug if (FlxG.keys.justPressed.T) { - rankAnimStart(fromResultsParams); + rankAnimStart(fromResultsParams ?? + { + playRankAnim: true, + newRank: PERFECT_GOLD, + songId: "tutorial", + difficultyId: "hard" + }); } if (FlxG.keys.justPressed.P) @@ -1427,7 +1439,7 @@ class FreeplayState extends MusicBeatSubState } spamTimer += elapsed; - dj.resetAFKTimer(); + if (dj != null) dj.resetAFKTimer(); } else { @@ -1438,31 +1450,31 @@ class FreeplayState extends MusicBeatSubState #if !html5 if (FlxG.mouse.wheel != 0) { - dj.resetAFKTimer(); + if (dj != null) dj.resetAFKTimer(); changeSelection(-Math.round(FlxG.mouse.wheel)); } #else if (FlxG.mouse.wheel < 0) { - dj.resetAFKTimer(); + if (dj != null) dj.resetAFKTimer(); changeSelection(-Math.round(FlxG.mouse.wheel / 8)); } else if (FlxG.mouse.wheel > 0) { - dj.resetAFKTimer(); + if (dj != null) dj.resetAFKTimer(); changeSelection(-Math.round(FlxG.mouse.wheel / 8)); } #end if (controls.UI_LEFT_P) { - dj.resetAFKTimer(); + if (dj != null) dj.resetAFKTimer(); changeDiff(-1); generateSongList(currentFilter, true); } if (controls.UI_RIGHT_P) { - dj.resetAFKTimer(); + if (dj != null) dj.resetAFKTimer(); changeDiff(1); generateSongList(currentFilter, true); } @@ -1472,7 +1484,7 @@ class FreeplayState extends MusicBeatSubState busy = true; FlxTween.globalManager.clear(); FlxTimer.globalManager.clear(); - dj.onIntroDone.removeAll(); + if (dj != null) dj.onIntroDone.removeAll(); FunkinSound.playOnce(Paths.sound('cancelMenu')); @@ -1498,7 +1510,8 @@ class FreeplayState extends MusicBeatSubState for (grpSpr in exitMovers.keys()) { - var moveData:MoveData = exitMovers.get(grpSpr); + var moveData:Null = exitMovers.get(grpSpr); + if (moveData == null) continue; for (spr in grpSpr) { @@ -1506,14 +1519,14 @@ class FreeplayState extends MusicBeatSubState var funnyMoveShit:MoveData = moveData; - if (moveData.x == null) funnyMoveShit.x = spr.x; - if (moveData.y == null) funnyMoveShit.y = spr.y; - if (moveData.speed == null) funnyMoveShit.speed = 0.2; - if (moveData.wait == null) funnyMoveShit.wait = 0; + var moveDataX = funnyMoveShit.x ?? spr.x; + var moveDataY = funnyMoveShit.y ?? spr.y; + var moveDataSpeed = funnyMoveShit.speed ?? 0.2; + var moveDataWait = funnyMoveShit.wait ?? 0; - FlxTween.tween(spr, {x: funnyMoveShit.x, y: funnyMoveShit.y}, funnyMoveShit.speed, {ease: FlxEase.expoIn}); + FlxTween.tween(spr, {x: moveDataX, y: moveDataY}, moveDataSpeed, {ease: FlxEase.expoIn}); - longestTimer = Math.max(longestTimer, funnyMoveShit.speed + funnyMoveShit.wait); + longestTimer = Math.max(longestTimer, moveDataSpeed + moveDataWait); } } @@ -1586,19 +1599,18 @@ class FreeplayState extends MusicBeatSubState var daSong:Null = grpCapsules.members[curSelected].songData; if (daSong != null) { - // TODO: Make this actually be the variation you're focused on. We don't need to fetch the song metadata just to calculate it. - var targetSong:Song = SongRegistry.instance.fetchEntry(grpCapsules.members[curSelected].songData.songId); + var targetSong:Null = SongRegistry.instance.fetchEntry(daSong.songId); if (targetSong == null) { - FlxG.log.warn('WARN: could not find song with id (${grpCapsules.members[curSelected].songData.songId})'); + FlxG.log.warn('WARN: could not find song with id (${daSong.songId})'); return; } - var targetVariation:String = targetSong.getFirstValidVariation(currentDifficulty); + var targetVariation:String = targetSong.getFirstValidVariation(currentDifficulty) ?? ''; // TODO: This line of code makes me sad, but you can't really fix it without a breaking migration. var suffixedDifficulty = (targetVariation != Constants.DEFAULT_VARIATION && targetVariation != 'erect') ? '$currentDifficulty-${targetVariation}' : currentDifficulty; - var songScore:SaveScoreData = Save.instance.getSongScore(grpCapsules.members[curSelected].songData.songId, suffixedDifficulty); + var songScore:Null = Save.instance.getSongScore(daSong.songId, suffixedDifficulty); intendedScore = songScore?.score ?? 0; intendedCompletion = songScore == null ? 0.0 : ((songScore.tallies.sick + songScore.tallies.good) / songScore.tallies.totalNotes); rememberedDifficulty = currentDifficulty; @@ -1660,7 +1672,7 @@ class FreeplayState extends MusicBeatSubState } // Set the album graphic and play the animation if relevant. - var newAlbumId:String = daSong?.albumId; + var newAlbumId:Null = daSong?.albumId; if (albumRoll.albumId != newAlbumId) { albumRoll.albumId = newAlbumId; @@ -1698,7 +1710,7 @@ class FreeplayState extends MusicBeatSubState }); trace('Available songs: ${availableSongCapsules.map(function(cap) { - return cap.songData.songName; + return cap?.songData?.songName; })}'); if (availableSongCapsules.length == 0) @@ -1727,17 +1739,20 @@ class FreeplayState extends MusicBeatSubState PlayStatePlaylist.isStoryMode = false; - var targetSong:Song = SongRegistry.instance.fetchEntry(cap.songData.songId); - if (targetSong == null) + var targetSongId:String = cap?.songData?.songId ?? 'unknown'; + var targetSongNullable:Null = SongRegistry.instance.fetchEntry(targetSongId); + if (targetSongNullable == null) { - FlxG.log.warn('WARN: could not find song with id (${cap.songData.songId})'); + FlxG.log.warn('WARN: could not find song with id (${targetSongId})'); return; } + var targetSong:Song = targetSongNullable; var targetDifficultyId:String = currentDifficulty; - var targetVariation:String = targetSong.getFirstValidVariation(targetDifficultyId, currentCharacter); - PlayStatePlaylist.campaignId = cap.songData.levelId; + var targetVariation:Null = targetSong.getFirstValidVariation(targetDifficultyId, currentCharacter); + var targetLevelId:Null = cap?.songData?.levelId; + PlayStatePlaylist.campaignId = targetLevelId ?? null; - var targetDifficulty:SongDifficulty = targetSong.getDifficulty(targetDifficultyId, targetVariation); + var targetDifficulty:Null = targetSong.getDifficulty(targetDifficultyId, targetVariation); if (targetDifficulty == null) { FlxG.log.warn('WARN: could not find difficulty with id (${targetDifficultyId})'); @@ -1759,7 +1774,7 @@ class FreeplayState extends MusicBeatSubState // Visual and audio effects. FunkinSound.playOnce(Paths.sound('confirmMenu')); - dj.confirm(); + if (dj != null) dj.confirm(); grpCapsules.members[curSelected].forcePosition(); grpCapsules.members[curSelected].confirm(); @@ -1801,7 +1816,7 @@ class FreeplayState extends MusicBeatSubState new FlxTimer().start(1, function(tmr:FlxTimer) { FunkinSound.emptyPartialQueue(); - Paths.setCurrentLevel(cap.songData.levelId); + Paths.setCurrentLevel(cap?.songData?.levelId); LoadingState.loadPlayState( { targetSong: targetSong, @@ -1856,7 +1871,7 @@ class FreeplayState extends MusicBeatSubState var daSongCapsule:SongMenuItem = grpCapsules.members[curSelected]; if (daSongCapsule.songData != null) { - var songScore:SaveScoreData = Save.instance.getSongScore(daSongCapsule.songData.songId, currentDifficulty); + var songScore:Null = Save.instance.getSongScore(daSongCapsule.songData.songId, currentDifficulty); intendedScore = songScore?.score ?? 0; intendedCompletion = songScore == null ? 0.0 : ((songScore.tallies.sick + songScore.tallies.good) / songScore.tallies.totalNotes); diffIdsCurrent = daSongCapsule.songData.songDifficulties; @@ -1906,7 +1921,10 @@ class FreeplayState extends MusicBeatSubState } else { - var previewSong:Null = SongRegistry.instance.fetchEntry(daSongCapsule.songData.songId); + var previewSongId:Null = daSongCapsule?.songData?.songId; + if (previewSongId == null) return; + + var previewSong:Null = SongRegistry.instance.fetchEntry(previewSongId); var songDifficulty = previewSong?.getDifficulty(currentDifficulty, previewSong?.getVariationsByCharacter(currentCharacter) ?? Constants.DEFAULT_VARIATION_LIST); var baseInstrumentalId:String = songDifficulty?.characters?.instrumental ?? ''; @@ -1924,7 +1942,9 @@ class FreeplayState extends MusicBeatSubState instSuffix = (instSuffix != '') ? '-$instSuffix' : ''; - FunkinSound.playMusic(daSongCapsule.songData.songId, + trace('Attempting to play partial preview: ${previewSongId}:${instSuffix}'); + + FunkinSound.playMusic(previewSongId, { startingVolume: 0.0, overrideExisting: true, @@ -1952,7 +1972,7 @@ class FreeplayState extends MusicBeatSubState public static function build(?params:FreeplayStateParams, ?stickers:StickerSubState):MusicBeatState { var result:MainMenuState; - if (params?.fromResults?.playRankAnim) result = new MainMenuState(true); + if (params?.fromResults?.playRankAnim ?? false) result = new MainMenuState(true); else result = new MainMenuState(false); diff --git a/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx b/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx index 282e35d7a..6d7b96c58 100644 --- a/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx +++ b/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx @@ -82,6 +82,11 @@ class PlayableCharacter implements IRegistryEntry return _data.freeplayDJ; } + public function getFreeplayDJText(index:Int):String + { + return _data.freeplayDJ.getFreeplayDJText(index); + } + /** * Returns whether this character is unlocked. */ diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index 2eba406d9..9bf465484 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -117,7 +117,10 @@ class MainMenuState extends MusicBeatState FlxTransitionableState.skipNextTransIn = true; FlxTransitionableState.skipNextTransOut = true; - openSubState(new FreeplayState()); + openSubState(new FreeplayState( + { + character: FlxG.keys.pressed.SHIFT ? 'pico' : 'bf', + })); }); #if CAN_OPEN_LINKS diff --git a/source/funkin/util/SortUtil.hx b/source/funkin/util/SortUtil.hx index c5ac175be..f6d3721f0 100644 --- a/source/funkin/util/SortUtil.hx +++ b/source/funkin/util/SortUtil.hx @@ -97,7 +97,7 @@ class SortUtil * @param b The second string to compare. * @return 1 if `a` comes before `b`, -1 if `b` comes before `a`, 0 if they are equal */ - public static function alphabetically(a:String, b:String):Int + public static function alphabetically(?a:String, ?b:String):Int { a = a.toUpperCase(); b = b.toUpperCase(); From bd17d965f57ef1a62638def0f0f5ff35e14613a2 Mon Sep 17 00:00:00 2001 From: AppleHair <95587502+AppleHair@users.noreply.github.com> Date: Fri, 14 Jun 2024 16:53:33 +0300 Subject: [PATCH 390/870] [BUGFIX] Fixed Ranks not appearing in freeplay for custom variations Freeplay tries to access a song's rank using the current difficulty name alone, but custom variation ranks are being saved with a variation prefix. This PR makes freeplay look for the variation prefix when necessary. --- source/funkin/ui/freeplay/FreeplayState.hx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 5725101cd..e36b6942f 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -2158,8 +2158,13 @@ class FreeplaySongData { this.albumId = songDifficulty.album; } + + // TODO: This line of code makes me sad, but you can't really fix it without a breaking migration. + // `easy`, `erect`, `normal-pico`, etc. + var suffixedDifficulty = (songDifficulty.variation != Constants.DEFAULT_VARIATION + && songDifficulty.variation != 'erect') ? '$currentDifficulty-${songDifficulty.variation}' : currentDifficulty; - this.scoringRank = Save.instance.getSongRank(songId, currentDifficulty); + this.scoringRank = Save.instance.getSongRank(songId, suffixedDifficulty); this.isNew = song.isSongNew(currentDifficulty); } From 05b57c88d3ff34ea36ce704678547a1f1ab3dd4a Mon Sep 17 00:00:00 2001 From: Punkinator7 Date: Wed, 3 Jul 2024 20:55:15 -0400 Subject: [PATCH 391/870] Add fixed Changelog There were several duplicate lines in the V4.0 Changelog, so I removed them --- changelog.md | 334 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 334 insertions(+) create mode 100644 changelog.md diff --git a/changelog.md b/changelog.md new file mode 100644 index 000000000..653ee203f --- /dev/null +++ b/changelog.md @@ -0,0 +1,334 @@ +# Changelog +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.1] - 2024-06-12 +### Added +- Pressing ESCAPE on the title screen on desktop now exits the game, allowing you to exit the game while in fullscreen on desktop +- Freeplay menu controls (favoriting and switching categories) are now rebindable from the Options menu, and now have default binds on controllers. +### Changed +- Highscores and ranks are now saved separately, which fixes the issue where people would overwrite their saves with higher scores, +which would remove their rank if they had a lower one. +- A-Bot speaker now reacts to the user's volume preference on desktop (thanks to [M7theguy for the issue report/suggestion](https://github.com/FunkinCrew/Funkin/issues/2744)!) +- On Freeplay, heart icons are shifted to the right when you favorite a song that has no rank on it. +- Only play `scrollMenu` sound effect when there's a real change on the freeplay menu ([thanks gamerbross for the PR!](https://github.com/FunkinCrew/Funkin/pull/2741)) +- Gave antialiasing to the edge of the dad graphic on Freeplay +- Rearranged some controls in the controls menu +- Made several chart revisions + - Re-enabled custom camera events in Roses (Erect/Nightmare) + - Tweaked the chart for Lit Up (Hard) + - Corrected the difficulty ratings for M.I.L.F. (Easy/Normal/Hard) +### Fixed +- Fixed an issue in the controls menu where some control binds would overlap their names +- Fixed crash when attempting to exit the gameover screen when also attempting to retry the song ([thanks DMMaster636 for the PR!](https://github.com/FunkinCrew/Funkin/pull/2709)) +- Fix botplay sustain release bug ([thanks Hundrec!](Fix botplay sustain release bug #2683)) +- Fix for the camera not pausing during a gameplay pause ([thanks gamerbross!](https://github.com/FunkinCrew/Funkin/pull/2684)) +- Fixed issue where Pico's gameplay sprite would unintentionally appear on the gameover screen when dying on 2Hot from an explosion +- Freeplay previews properly fade volume during the BF idle animation +- Fixed bug where Dadbattle incorrectly appeared as Dadbattle Erect when returning to freeplay on Hard +- Fixed 2Hot not appearing under the "#" category in Freeplay menu +- Fixed a bug where the Chart Editor would crash when attempting to select an event with the Event toolbox open +- Improved offsets for Pico and Tankman opponents so they don't slide around as much. +- Fixed the black "temp" graphic on freeplay from being incorrectly sized / masked, now it's identical to the dad freeplay graphic + +## [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. +- 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 burgerballs!) +### Changed +- Tweaked the charts for several songs: + - Tutorial (increased the note speed slightly) + - Spookeez + - Monster + - Winter Horrorland + - 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. +- 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!) + - Remember that for more complex behaviors such as animations or transitions, you should use an XML file to define each frame. +- Improved the Event Toolbox in the Chart Editor; dropdowns are now bigger, include search field, and display elements in alphabetical order rather than a random order. +### 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 +- 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 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!) +- Made improvements to compiling documentation (thanks gedehari!) +- 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 a bug where opening the game from the command line would crash the preloader (thanks NotHyper474!) +- 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 +### Changed +- Cleaned up some code in `PlayAnimationSongEvent.hx` (thanks BurgerBalls!) +### Fixed +- 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!) +- 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 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!) +- Fix a crash on Freeplay found on AMD graphics cards + +## [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. +- Implemented a blacklist to prevent mods from calling system functions. + - Added a couple utility functions to call useful stuff that got blacklisted. +- Added an `onSongLoad` script event which allows for mutation of notes and events. +- Added the current loaded modlist to crash logs. +- Added the `visible` attribute to Level JSON data. +- Enabled ZIP file system support for Polymod (make sure the metadata is in the root of the ZIP). +### Changed +- Songs in the mod folders will display in Freeplay without any extra scripting. +- Story levels in the mod folders will display in Story without any extra scripting. +- All audio should sound better in HTML5, less muddy +### Fixed +- Fixed a typo in the credits folder (`Custcene` -> `Cutscene`) +- Fixed an issue where health icon transition animations would loop and never finish properly. +- Fixed an issue where video cutscenes flagged as mid-song would crash the game when they finish. +- Fixed an issue where some substate lifecycle events were not being dispatched. +- Fixed a crash when trying to load into the Animation Offsets menu with an invalid character. +- Fixed an issue where the preloader would spam the logs when it was complete and waiting for user input. +- Should definitely have the fix for freeplay where it stops taking control of the main menu below it +- Changed the code for the story menu difficulties so that "normal" doesn't overlap the arrows after leaving Weekend 1 +### Removed +- Removed some unused `.txt` files in the `assets/data` folder. + +## [0.3.1] - 2024-05-01 +### Changed +- Ensure the Git commit hash always displays in the log files. +- Added whether the local Git repo was modified to the log files. +- Removed "PROTOTYPE" text on release builds only (it still shows on debug builds). +- Added additional credits and special thanks. +- Updated peepo in creds to peepo173 +### Fixed +- Fix a crash when retrieving system specs while handing a crash. +- Fix a crash triggered when pausing before the song started. +- Fix a crash triggered when dying before the song started. +- Fix a crash triggered when unloading certain graphics. +- Pico game over confirm plays correctly +- When exiting from a song into freeplay, main menu no longer takes inputs unintentionally (aka issues with merch links opening up when selecting songs) +- Fix for arrow keys causing web browser page scroll + +## [0.3.0] - 2024-04-30 +### Added +- New Story Level: Weekend 1, starting Pico, Darnell, and Nene. + - Beat the level in Story Mode to unlock the songs for Freeplay! +- 12 new Erect remixes, featuring Kawai Sprite, Saruky, Kohta Takahashi, and Saster + - Unlocked instantly in Freeplay +- New visually enhanced Freeplay menu. + - Sorting, favorites, and more. +- New Results screen upon completing any song or story level. +- New refactored Chart Editor prototype (accessible via `~` in the main menu or `7` in the Play State, rebindable). (VERY EARLY PROTOTYPE. EXPECT BUGS AND CRASHES) +- Implemented a new scripting system using HScript (an interpreted language with Haxe-like syntax) for incredible flexibility. + - All character-specific, stage-specific, or song-specific behaviors have been moved to HScript. +- New song events system allows for simple customization of camera behavior. + - Mods can implement custom song events via HScript, and new built-in song events will come in the future. +- New credits menu to list all the dozens of people who contributed. +### Changed +- Completely refactored the game's input system for higher reliability and accuracy. +- Reworked note rendering to massively reduce lag on larger charts. +- Reworks to scoring and health gain. +- Dedicated gamepad support with the ability to rebind buttons. +- Improvements to video cutscenes and dialogue, allowing them to be easily skipped or restarted. +- Updated Polymod by several major versions, allowing for fully dynamic asset replacement and support for scripted classes. +- Completely refactored almost every part of the game's code for performance, stability, and extensibility. + - This is not the Ludem Dare game held together with sticks and glue you played three years ago. +- Characters, stages, songs, story levels, and dialogue are now built from JSON data registries rather than being hardcoded. + - All of these also support attaching scripts for custom behavior, more documentation on this soon. + - You can forcibly reload the game's JSON data and scripts by pressing F5. +- Fully refactored the game's chart file format for extensibility and readability. + - You can migrate old charts using the Import FNF Legacy option in the chart editor. +- Various visual tweaks and improvements. +### Fixed +- 17 quadrillion bugs across hundreds of PRs. + +## [0.2.8] - 2021-04-18 (note, this one is iffy cuz we slacked wit it lol!) +### Added +- TANKMAN! 3 NEW SONGS BY KAWAISPRITE (UGH, GUNS, STRESS)! Charting help by MtH! +- Monster added into week 2, FINALLY (Charting help by MtH and ChaoticGamer!) +- Can now change song difficulty mid-game. +- Shows some song info on pause screen. +- Cute little icons onto freeplay menu +- Offset files for easier modification of characters +### Changed +- ASSET LOADING OVERHAUL, WAY FASTER LOAD TIMES ON WEB!!! (THANKS TO GEOKURELI WOKE KING) +- Made difficulty selector on freeplay menu more apparent +### Fixed +- That one random note on Bopeebo + +## [0.2.7.1] - 2021-02-14 +### Added +- Easter eggs +- readme's in desktop versions of the game +### Changed +- New icons, old one was placeholder since October woops! +- Made the transitions between the story mode levels more seamless. +- Offset of the Newgrounds logo on boot screen. +- Made the changelog txt so it can be opened easier by normal people who don't have a markdown reader (most normal people); +### Fixed +- Fixed crashes on Week 6 story mode dialogue if spam too fast ([Thanks to Lotusotho for the Pull Request!](https://github.com/ninjamuffin99/Funkin/pull/357)) +- Should show intro credits on desktop versions of the game more consistently +- Layering on Week 4 songs with GF and the LIMO LOL HOW TF I MISS THIS +- Chart's and chart editor now support changeBPM, GOD BLESS MTH FOR THIS ONE I BEEN STRUGGLIN WIT THAT SINCE OCTOBER LMAO ([GOD BLESS MTH](https://github.com/ninjamuffin99/Funkin/pull/382)) +- Fixed sustain note trails ALSO THANKS TO MTH U A REAL ONE ([MTH VERY POWERFUL](https://github.com/ninjamuffin99/Funkin/pull/415)) +- Antialiasing on the skyscraper lights + +## [0.2.7] - 2021-02-02 +### Added +- PIXEL DAY UPDATE LOL 1 WEEK LATER +- 3 New songs by Kawaisprite! +- COOL CUTSCENES +- WEEK 6 YOYOYOYOY +- Swaggy pixel art by Moawling! +### Changed +- Made it so you lose sliiiightly more health when you miss a note. +- Removed the default HaxeFlixel pause screen when the game window loses focus, can get screenshots of the game easier hehehe +### Fixed +- Idle animation bug with BF christmas and BF hair blow sprites ([Thanks to Injourn for the Pull Request!](https://github.com/ninjamuffin99/Funkin/pull/237)) + +## [0.2.6] - 2021-01-20 +### Added +- 3 NEW CHRISTMAS SONGS. 2 BY KAWAISPRITE, 1 BY BASSETFILMS!!!!! BF WITH DRIP! SANTA HANGIN OUT! +- Enemy icons change when they you are winning a lot ([Thanks to pahaze for the Pull Request!](https://github.com/ninjamuffin99/Funkin/pull/138)) +- Holding CTRL in charting editor places notes on both sides +- Q and E changes sustain lengths in note editor +- Other charting editor workflow improvements +- More hair physics +- Heads appear at top of chart editor to help show which side ur charting for +### Changed +- Tweaked code relating to inputs, hopefully making notes that are close together more fair to hit +### Removed +- Removed APE +### Fixed +- Maybe fixed double notes / jump notes. Need to tweak it for balance, but should open things up for cooler charts in the future. +- Old Verison popup screen weirdness ([Thanks to gedehari for the Pull Request!](https://github.com/ninjamuffin99/Funkin/pull/155)) +- Song no longer loops when finishing the song. ([Thanks Injourn for the Pull Request!](https://github.com/ninjamuffin99/Funkin/pull/132)) +- Screen wipe being cut off in the limo/mom stage. Should fill the whole screen now. +- Boyfriend animations on hold notes, and pressing on repeating notes should behave differently + +## [0.2.5] - 2020-12-27 +### Added +- MOMMY GF, 3 NEW ASS SONGS BY KAWAISPRITE, NEW ART BY PHANTOMARCADE,WOOOOOOAH!!!! +- Different icons depending on which character you are against, art by EVILSK8R!! +- Autosave to chart editor +- Clear section button to note editor +- Swap button in note editor +- a new boot text or two +- automatic check for when you're on an old version of the game! +### Changed +- Made Spookeez on Normal easier. +- Mouse is now visible in note editor +### Fixed +- Crash when playing Week 3 and then playing a non-week 3 song +- When pausing music at the start, it doesn't continue the song anyways. ([shoutouts gedehari for the Pull Request!](https://github.com/ninjamuffin99/Funkin/pull/48)) +- IDK i think backing out of song menu should play main menu songs again hehe ([shoutouts gedehari for the Pull Request!](https://github.com/ninjamuffin99/Funkin/pull/48)) + +## [0.2.4] - 2020-12-11 +### Added +- 3 NEW SONGS BY KAWAISPRITE. Pico, Philly, and Blammed. +- NEW CHARACTER, PICO. Based off the classic Flash game "Pico's School" by Tom Fulp +- NEW LEVEL WOW! PHILLY BABEEEE +### Changed +- Made it less punishing to ATTEMPT to hit a note and miss, rather than let it pass you +### Fixed +- Song desync of you paused and unpaused frequently ([shoutouts SonicBlam](https://github.com/ninjamuffin99/Funkin/issues/37)) +- Animation offsets when GF is scared + +## [0.2.3] - 2020-12-04 +### Added +- More intro texts +### Fixed +- Exploit where you could potentially give yourself a high score via the debug menu +- Issue/bug where you could spam the confirm button on the story menu ([shoutouts lotusotho for the CODE contribution/pull request!](https://github.com/ninjamuffin99/Funkin/pull/19)) +- Glitch where if you never would lose health if you missed a note on a fast song (shoutouts [MrDulfin](https://github.com/ninjamuffin99/Funkin/issues/10), [HotSauceBurritos](https://github.com/ninjamuffin99/Funkin/issues/13) and [LobsterMango](https://lobstermango.newgrounds.com)) +- Fixed tiny note bleed over thingies (shoutouts [lotusotho](https://github.com/ninjamuffin99/Funkin/pull/24)) + +## [0.2.2] - 2020-11-20 +### Added +- Music playing on the freeplay menu. +- UI sounds on freeplay menu +- Score now shows mid-song. +- Menu on pause screen! Can resume, and restart song, or go back to main menu. +- New music made for pause menu! + +### Changed +- Moved all the intro texts to its own txt file instead of being hardcoded, this allows for much easier customization. File is in the data folder, called "introText.txt", follow the format in there and you're probably good to go! +### Fixed +- Fixed soft lock when pausing on song finish ([shoutouts gedehari](https://github.com/ninjamuffin99/Funkin/issues/15)) +- Think I fixed issue that led to in-game scores being off by 2 ([shoutouts Mike](https://github.com/ninjamuffin99/Funkin/issues/4)) +- Should have fixed the 1 frame note appearance thing. ([shoutouts Mike](https://github.com/ninjamuffin99/Funkin/issues/6)) +- Cleaned up some charting on South on hard mode +- Fixed some animation timings, should feel both better to play, and watch. (shoutouts Dave/Ivan lol) +- Animation issue where GF would freak out on the title screen if you returned to it([shoutouts MultiXIII](https://github.com/ninjamuffin99/Funkin/issues/12)). + +## [0.2.1.2] - 2020-11-06 +### Fixed +- Story mode scores not properly resetting, leading to VERY inflated highscores on the leaderboards. This also requires me to clear the scores that are on the leaderboard right now, sorry! +- Difficulty on storymode and in freeplay scores +- Hard mode difficulty on campaign levels have been fixed + +## [0.2.1.1] - 2020-11-06 +### Fixed +- Week 2 not unlocking properly + +## [0.2.1] - 2020-11-06 +### Added +- Scores to the freeplay menu +- A few new intro boot messages. +- Lightning effect in Spooky stages +- Campaign scores, can now compete on scoreboards for campaign! +- Can now change difficulties in Freeplay mode + +### Changed +- Balanced out Normal mode for the harder songs(Dadbattle and Spookeez, not South yet). Should be much easier all around. +- Put tutorial in it's own 'week', so that if you want to play week 1, you don't have to play the tutorial. + +### Fixed +- One of the charting bits on South and Spookeez during the intro. + +## [0.2.0] - 2020-11-01 +### Added +- Uhh Newgrounds release lolol I always lose track of shit. + +## [0.1.0] - 2020-10-05 +### Added +- Uh, everything. This the game's initial gamejam release. We put it out From cd9400e898fc2b0edd07280c59fc73c3a8b03e64 Mon Sep 17 00:00:00 2001 From: Punkinator7 Date: Wed, 3 Jul 2024 20:56:19 -0400 Subject: [PATCH 392/870] Delete CHANGELOG.md --- CHANGELOG.md | 344 --------------------------------------------------- 1 file changed, 344 deletions(-) delete mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 755b3b3bc..000000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,344 +0,0 @@ -# Changelog -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.1] - 2024-06-12 -### Added -- Pressing ESCAPE on the title screen on desktop now exits the game, allowing you to exit the game while in fullscreen on desktop -- Freeplay menu controls (favoriting and switching categories) are now rebindable from the Options menu, and now have default binds on controllers. -### Changed -- Highscores and ranks are now saved separately, which fixes the issue where people would overwrite their saves with higher scores, -which would remove their rank if they had a lower one. -- A-Bot speaker now reacts to the user's volume preference on desktop (thanks to [M7theguy for the issue report/suggestion](https://github.com/FunkinCrew/Funkin/issues/2744)!) -- On Freeplay, heart icons are shifted to the right when you favorite a song that has no rank on it. -- Only play `scrollMenu` sound effect when there's a real change on the freeplay menu ([thanks gamerbross for the PR!](https://github.com/FunkinCrew/Funkin/pull/2741)) -- Gave antialiasing to the edge of the dad graphic on Freeplay -- Rearranged some controls in the controls menu -- Made several chart revisions - - Re-enabled custom camera events in Roses (Erect/Nightmare) - - Tweaked the chart for Lit Up (Hard) - - Corrected the difficulty ratings for M.I.L.F. (Easy/Normal/Hard) -### Fixed -- Fixed an issue in the controls menu where some control binds would overlap their names -- Fixed crash when attempting to exit the gameover screen when also attempting to retry the song ([thanks DMMaster636 for the PR!](https://github.com/FunkinCrew/Funkin/pull/2709)) -- Fix botplay sustain release bug ([thanks Hundrec!](Fix botplay sustain release bug #2683)) -- Fix for the camera not pausing during a gameplay pause ([thanks gamerbross!](https://github.com/FunkinCrew/Funkin/pull/2684)) -- Fixed issue where Pico's gameplay sprite would unintentionally appear on the gameover screen when dying on 2Hot from an explosion -- Freeplay previews properly fade volume during the BF idle animation -- Fixed bug where Dadbattle incorrectly appeared as Dadbattle Erect when returning to freeplay on Hard -- Fixed 2Hot not appearing under the "#" category in Freeplay menu -- Fixed a bug where the Chart Editor would crash when attempting to select an event with the Event toolbox open -- Improved offsets for Pico and Tankman opponents so they don't slide around as much. -- Fixed the black "temp" graphic on freeplay from being incorrectly sized / masked, now it's identical to the dad freeplay graphic - -## [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. -- 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 burgerballs!) -### Changed -- Tweaked the charts for several songs: - - Tutorial (increased the note speed slightly) - - Spookeez - - Monster - - Winter Horrorland - - 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. -- 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!) - - Remember that for more complex behaviors such as animations or transitions, you should use an XML file to define each frame. -- Improved the Event Toolbox in the Chart Editor; dropdowns are now bigger, include search field, and display elements in alphabetical order rather than a random order. -### 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 -- 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 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!) -- 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!) -- 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!) -- 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 -### Changed -- Cleaned up some code in `PlayAnimationSongEvent.hx` (thanks BurgerBalls!) -### Fixed -- 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!) -- 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 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!) -- Fix a crash on Freeplay found on AMD graphics cards - -## [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. -- Implemented a blacklist to prevent mods from calling system functions. - - Added a couple utility functions to call useful stuff that got blacklisted. -- Added an `onSongLoad` script event which allows for mutation of notes and events. -- Added the current loaded modlist to crash logs. -- Added the `visible` attribute to Level JSON data. -- Enabled ZIP file system support for Polymod (make sure the metadata is in the root of the ZIP). -### Changed -- Songs in the mod folders will display in Freeplay without any extra scripting. -- Story levels in the mod folders will display in Story without any extra scripting. -- All audio should sound better in HTML5, less muddy -### Fixed -- Fixed a typo in the credits folder (`Custcene` -> `Cutscene`) -- Fixed an issue where health icon transition animations would loop and never finish properly. -- Fixed an issue where video cutscenes flagged as mid-song would crash the game when they finish. -- Fixed an issue where some substate lifecycle events were not being dispatched. -- Fixed a crash when trying to load into the Animation Offsets menu with an invalid character. -- Fixed an issue where the preloader would spam the logs when it was complete and waiting for user input. -- Should definitely have the fix for freeplay where it stops taking control of the main menu below it -- Changed the code for the story menu difficulties so that "normal" doesn't overlap the arrows after leaving Weekend 1 -### Removed -- Removed some unused `.txt` files in the `assets/data` folder. - -## [0.3.1] - 2024-05-01 -### Changed -- Ensure the Git commit hash always displays in the log files. -- Added whether the local Git repo was modified to the log files. -- Removed "PROTOTYPE" text on release builds only (it still shows on debug builds). -- Added additional credits and special thanks. -- Updated peepo in creds to peepo173 -### Fixed -- Fix a crash when retrieving system specs while handing a crash. -- Fix a crash triggered when pausing before the song started. -- Fix a crash triggered when dying before the song started. -- Fix a crash triggered when unloading certain graphics. -- Pico game over confirm plays correctly -- When exiting from a song into freeplay, main menu no longer takes inputs unintentionally (aka issues with merch links opening up when selecting songs) -- Fix for arrow keys causing web browser page scroll - -## [0.3.0] - 2024-04-30 -### Added -- New Story Level: Weekend 1, starting Pico, Darnell, and Nene. - - Beat the level in Story Mode to unlock the songs for Freeplay! -- 12 new Erect remixes, featuring Kawai Sprite, Saruky, Kohta Takahashi, and Saster - - Unlocked instantly in Freeplay -- New visually enhanced Freeplay menu. - - Sorting, favorites, and more. -- New Results screen upon completing any song or story level. -- New refactored Chart Editor prototype (accessible via `~` in the main menu or `7` in the Play State, rebindable). (VERY EARLY PROTOTYPE. EXPECT BUGS AND CRASHES) -- Implemented a new scripting system using HScript (an interpreted language with Haxe-like syntax) for incredible flexibility. - - All character-specific, stage-specific, or song-specific behaviors have been moved to HScript. -- New song events system allows for simple customization of camera behavior. - - Mods can implement custom song events via HScript, and new built-in song events will come in the future. -- New credits menu to list all the dozens of people who contributed. -### Changed -- Completely refactored the game's input system for higher reliability and accuracy. -- Reworked note rendering to massively reduce lag on larger charts. -- Reworks to scoring and health gain. -- Dedicated gamepad support with the ability to rebind buttons. -- Improvements to video cutscenes and dialogue, allowing them to be easily skipped or restarted. -- Updated Polymod by several major versions, allowing for fully dynamic asset replacement and support for scripted classes. -- Completely refactored almost every part of the game's code for performance, stability, and extensibility. - - This is not the Ludem Dare game held together with sticks and glue you played three years ago. -- Characters, stages, songs, story levels, and dialogue are now built from JSON data registries rather than being hardcoded. - - All of these also support attaching scripts for custom behavior, more documentation on this soon. - - You can forcibly reload the game's JSON data and scripts by pressing F5. -- Fully refactored the game's chart file format for extensibility and readability. - - You can migrate old charts using the Import FNF Legacy option in the chart editor. -- Various visual tweaks and improvements. -### Fixed -- 17 quadrillion bugs across hundreds of PRs. - -## [0.2.8] - 2021-04-18 (note, this one is iffy cuz we slacked wit it lol!) -### Added -- TANKMAN! 3 NEW SONGS BY KAWAISPRITE (UGH, GUNS, STRESS)! Charting help by MtH! -- Monster added into week 2, FINALLY (Charting help by MtH and ChaoticGamer!) -- Can now change song difficulty mid-game. -- Shows some song info on pause screen. -- Cute little icons onto freeplay menu -- Offset files for easier modification of characters -### Changed -- ASSET LOADING OVERHAUL, WAY FASTER LOAD TIMES ON WEB!!! (THANKS TO GEOKURELI WOKE KING) -- Made difficulty selector on freeplay menu more apparent -### Fixed -- That one random note on Bopeebo - -## [0.2.7.1] - 2021-02-14 -### Added -- Easter eggs -- readme's in desktop versions of the game -### Changed -- New icons, old one was placeholder since October woops! -- Made the transitions between the story mode levels more seamless. -- Offset of the Newgrounds logo on boot screen. -- Made the changelog txt so it can be opened easier by normal people who don't have a markdown reader (most normal people); -### Fixed -- Fixed crashes on Week 6 story mode dialogue if spam too fast ([Thanks to Lotusotho for the Pull Request!](https://github.com/ninjamuffin99/Funkin/pull/357)) -- Should show intro credits on desktop versions of the game more consistently -- Layering on Week 4 songs with GF and the LIMO LOL HOW TF I MISS THIS -- Chart's and chart editor now support changeBPM, GOD BLESS MTH FOR THIS ONE I BEEN STRUGGLIN WIT THAT SINCE OCTOBER LMAO ([GOD BLESS MTH](https://github.com/ninjamuffin99/Funkin/pull/382)) -- Fixed sustain note trails ALSO THANKS TO MTH U A REAL ONE ([MTH VERY POWERFUL](https://github.com/ninjamuffin99/Funkin/pull/415)) -- Antialiasing on the skyscraper lights - -## [0.2.7] - 2021-02-02 -### Added -- PIXEL DAY UPDATE LOL 1 WEEK LATER -- 3 New songs by Kawaisprite! -- COOL CUTSCENES -- WEEK 6 YOYOYOYOY -- Swaggy pixel art by Moawling! -### Changed -- Made it so you lose sliiiightly more health when you miss a note. -- Removed the default HaxeFlixel pause screen when the game window loses focus, can get screenshots of the game easier hehehe -### Fixed -- Idle animation bug with BF christmas and BF hair blow sprites ([Thanks to Injourn for the Pull Request!](https://github.com/ninjamuffin99/Funkin/pull/237)) - -## [0.2.6] - 2021-01-20 -### Added -- 3 NEW CHRISTMAS SONGS. 2 BY KAWAISPRITE, 1 BY BASSETFILMS!!!!! BF WITH DRIP! SANTA HANGIN OUT! -- Enemy icons change when they you are winning a lot ([Thanks to pahaze for the Pull Request!](https://github.com/ninjamuffin99/Funkin/pull/138)) -- Holding CTRL in charting editor places notes on both sides -- Q and E changes sustain lengths in note editor -- Other charting editor workflow improvements -- More hair physics -- Heads appear at top of chart editor to help show which side ur charting for -### Changed -- Tweaked code relating to inputs, hopefully making notes that are close together more fair to hit -### Removed -- Removed APE -### Fixed -- Maybe fixed double notes / jump notes. Need to tweak it for balance, but should open things up for cooler charts in the future. -- Old Verison popup screen weirdness ([Thanks to gedehari for the Pull Request!](https://github.com/ninjamuffin99/Funkin/pull/155)) -- Song no longer loops when finishing the song. ([Thanks Injourn for the Pull Request!](https://github.com/ninjamuffin99/Funkin/pull/132)) -- Screen wipe being cut off in the limo/mom stage. Should fill the whole screen now. -- Boyfriend animations on hold notes, and pressing on repeating notes should behave differently - -## [0.2.5] - 2020-12-27 -### Added -- MOMMY GF, 3 NEW ASS SONGS BY KAWAISPRITE, NEW ART BY PHANTOMARCADE,WOOOOOOAH!!!! -- Different icons depending on which character you are against, art by EVILSK8R!! -- Autosave to chart editor -- Clear section button to note editor -- Swap button in note editor -- a new boot text or two -- automatic check for when you're on an old version of the game! -### Changed -- Made Spookeez on Normal easier. -- Mouse is now visible in note editor -### Fixed -- Crash when playing Week 3 and then playing a non-week 3 song -- When pausing music at the start, it doesn't continue the song anyways. ([shoutouts gedehari for the Pull Request!](https://github.com/ninjamuffin99/Funkin/pull/48)) -- IDK i think backing out of song menu should play main menu songs again hehe ([shoutouts gedehari for the Pull Request!](https://github.com/ninjamuffin99/Funkin/pull/48)) - -## [0.2.4] - 2020-12-11 -### Added -- 3 NEW SONGS BY KAWAISPRITE. Pico, Philly, and Blammed. -- NEW CHARACTER, PICO. Based off the classic Flash game "Pico's School" by Tom Fulp -- NEW LEVEL WOW! PHILLY BABEEEE -### Changed -- Made it less punishing to ATTEMPT to hit a note and miss, rather than let it pass you -### Fixed -- Song desync of you paused and unpaused frequently ([shoutouts SonicBlam](https://github.com/ninjamuffin99/Funkin/issues/37)) -- Animation offsets when GF is scared - -## [0.2.3] - 2020-12-04 -### Added -- More intro texts -### Fixed -- Exploit where you could potentially give yourself a high score via the debug menu -- Issue/bug where you could spam the confirm button on the story menu ([shoutouts lotusotho for the CODE contribution/pull request!](https://github.com/ninjamuffin99/Funkin/pull/19)) -- Glitch where if you never would lose health if you missed a note on a fast song (shoutouts [MrDulfin](https://github.com/ninjamuffin99/Funkin/issues/10), [HotSauceBurritos](https://github.com/ninjamuffin99/Funkin/issues/13) and [LobsterMango](https://lobstermango.newgrounds.com)) -- Fixed tiny note bleed over thingies (shoutouts [lotusotho](https://github.com/ninjamuffin99/Funkin/pull/24)) - -## [0.2.2] - 2020-11-20 -### Added -- Music playing on the freeplay menu. -- UI sounds on freeplay menu -- Score now shows mid-song. -- Menu on pause screen! Can resume, and restart song, or go back to main menu. -- New music made for pause menu! - -### Changed -- Moved all the intro texts to its own txt file instead of being hardcoded, this allows for much easier customization. File is in the data folder, called "introText.txt", follow the format in there and you're probably good to go! -### Fixed -- Fixed soft lock when pausing on song finish ([shoutouts gedehari](https://github.com/ninjamuffin99/Funkin/issues/15)) -- Think I fixed issue that led to in-game scores being off by 2 ([shoutouts Mike](https://github.com/ninjamuffin99/Funkin/issues/4)) -- Should have fixed the 1 frame note appearance thing. ([shoutouts Mike](https://github.com/ninjamuffin99/Funkin/issues/6)) -- Cleaned up some charting on South on hard mode -- Fixed some animation timings, should feel both better to play, and watch. (shoutouts Dave/Ivan lol) -- Animation issue where GF would freak out on the title screen if you returned to it([shoutouts MultiXIII](https://github.com/ninjamuffin99/Funkin/issues/12)). - -## [0.2.1.2] - 2020-11-06 -### Fixed -- Story mode scores not properly resetting, leading to VERY inflated highscores on the leaderboards. This also requires me to clear the scores that are on the leaderboard right now, sorry! -- Difficulty on storymode and in freeplay scores -- Hard mode difficulty on campaign levels have been fixed - -## [0.2.1.1] - 2020-11-06 -### Fixed -- Week 2 not unlocking properly - -## [0.2.1] - 2020-11-06 -### Added -- Scores to the freeplay menu -- A few new intro boot messages. -- Lightning effect in Spooky stages -- Campaign scores, can now compete on scoreboards for campaign! -- Can now change difficulties in Freeplay mode - -### Changed -- Balanced out Normal mode for the harder songs(Dadbattle and Spookeez, not South yet). Should be much easier all around. -- Put tutorial in it's own 'week', so that if you want to play week 1, you don't have to play the tutorial. - -### Fixed -- One of the charting bits on South and Spookeez during the intro. - -## [0.2.0] - 2020-11-01 -### Added -- Uhh Newgrounds release lolol I always lose track of shit. - -## [0.1.0] - 2020-10-05 -### Added -- Uh, everything. This the game's initial gamejam release. We put it out From f31d2f7bfc1ed5918816eda617bd385d0a4b8c94 Mon Sep 17 00:00:00 2001 From: Punkinator7 Date: Wed, 3 Jul 2024 20:57:01 -0400 Subject: [PATCH 393/870] Rename changelog.md to CHANGELOG.md replace the old one with the fixed version --- changelog.md => CHANGELOG.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename changelog.md => CHANGELOG.md (100%) diff --git a/changelog.md b/CHANGELOG.md similarity index 100% rename from changelog.md rename to CHANGELOG.md From e32fcee77c9b98e28d74f91b0be47b8c87b662bd Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 3 Jul 2024 22:50:39 -0400 Subject: [PATCH 394/870] Migrate results animations to JSON data so we can implement them per-character --- assets | 2 +- source/funkin/InitState.hx | 3 +- .../funkin/data/freeplay/player/PlayerData.hx | 66 +++- .../data/freeplay/player/PlayerRegistry.hx | 2 +- .../graphics/adobeanimate/FlxAtlasSprite.hx | 12 +- source/funkin/play/PlayState.hx | 1 + source/funkin/play/ResultState.hx | 344 ++++++------------ .../freeplay/charselect/PlayableCharacter.hx | 27 ++ 8 files changed, 201 insertions(+), 256 deletions(-) diff --git a/assets b/assets index bc1650ba7..0351610af 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit bc1650ba789d675683a8c0cc27b1e2a42cb686cf +Subproject commit 0351610af02b45eb25e4bbfef0380f6f1d8cf737 diff --git a/source/funkin/InitState.hx b/source/funkin/InitState.hx index c2a56bdc2..254165a95 100644 --- a/source/funkin/InitState.hx +++ b/source/funkin/InitState.hx @@ -223,6 +223,7 @@ class InitState extends FlxState storyMode: false, title: "Cum Song Erect by Kawai Sprite", songId: "cum", + characterId: "pico-playable", difficultyId: "nightmare", isNewHighscore: true, scoreData: @@ -238,7 +239,7 @@ class InitState extends FlxState combo: 69, maxCombo: 69, totalNotesHit: 140, - totalNotes: 200 // 0, + totalNotes: 240 // 0, } }, })); diff --git a/source/funkin/data/freeplay/player/PlayerData.hx b/source/funkin/data/freeplay/player/PlayerData.hx index c461c9555..caae2adc6 100644 --- a/source/funkin/data/freeplay/player/PlayerData.hx +++ b/source/funkin/data/freeplay/player/PlayerData.hx @@ -38,6 +38,8 @@ class PlayerData @:optional public var freeplayDJ:Null = null; + public var results:Null = null; + /** * Whether this character is unlocked by default. * Use a ScriptedPlayableCharacter to add custom logic. @@ -86,7 +88,6 @@ class PlayerFreeplayDJData @:default("PROTECT YO NUTS") var text3:String; - @:jignored var animationMap:Map; @@ -120,12 +121,18 @@ class PlayerFreeplayDJData return Paths.animateAtlas(assetPath); } - public function getFreeplayDJText(index:Int):String { - switch (index) { - case 1: return text1; - case 2: return text2; - case 3: return text3; - default: return ''; + public function getFreeplayDJText(index:Int):String + { + switch (index) + { + case 1: + return text1; + case 2: + return text2; + case 3: + return text3; + default: + return ''; } } @@ -178,6 +185,51 @@ class PlayerFreeplayDJData } } +typedef PlayerResultsData = +{ + var perfect:Array; + var excellent:Array; + var great:Array; + var good:Array; + var loss:Array; +}; + +typedef PlayerResultsAnimationData = +{ + /** + * `sparrow` or `animate` or whatever + */ + var renderType:String; + + var assetPath:String; + + @:optional + @:default([0, 0]) + var offsets:Array; + + @:optional + @:default(500) + var zIndex:Int; + + @:optional + @:default(0.0) + var delay:Float; + + @:optional + @:default(1.0) + var scale:Float; + + @:optional + @:default('') + var startFrameLabel:Null; + + @:optional + var loopFrame:Null; + + @:optional + var loopFrameLabel:Null; +}; + typedef PlayerFreeplayDJCartoonData = { var soundClickFrame:Int; diff --git a/source/funkin/data/freeplay/player/PlayerRegistry.hx b/source/funkin/data/freeplay/player/PlayerRegistry.hx index 3de9efd41..4656a1286 100644 --- a/source/funkin/data/freeplay/player/PlayerRegistry.hx +++ b/source/funkin/data/freeplay/player/PlayerRegistry.hx @@ -58,7 +58,7 @@ class PlayerRegistry extends BaseRegistry * @param characterId The stage character ID. * @return The playable character. */ - public function getCharacterOwnerId(characterId:String):String + public function getCharacterOwnerId(characterId:String):Null { return ownedCharacterIds[characterId]; } diff --git a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx index 8a77c1c85..1684e8b33 100644 --- a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx +++ b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx @@ -131,12 +131,14 @@ class FlxAtlasSprite extends FlxAnimate anim.play('', false, false); } } - - // Skip if the animation doesn't exist - if (!hasAnimation(id)) + else { - trace('Animation ' + id + ' not found'); - return; + // Skip if the animation doesn't exist + if (!hasAnimation(id)) + { + trace('Animation ' + id + ' not found'); + return; + } } anim.callback = function(_, frame:Int) { diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index f55cef388..61c2ad800 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -3156,6 +3156,7 @@ class PlayState extends MusicBeatSubState storyMode: PlayStatePlaylist.isStoryMode, songId: currentChart.song.id, difficultyId: currentDifficulty, + characterId: currentChart.characters.player, title: PlayStatePlaylist.isStoryMode ? ('${PlayStatePlaylist.campaignTitle}') : ('${currentChart.songName} by ${currentChart.songArtist}'), prevScoreData: prevScoreData, scoreData: diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index a2c5f7e62..ae1a9bcf8 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -14,6 +14,9 @@ import flixel.math.FlxRect; import flixel.text.FlxBitmapText; import funkin.ui.freeplay.FreeplayScore; import flixel.text.FlxText; +import funkin.data.freeplay.player.PlayerRegistry; +import funkin.data.freeplay.player.PlayerData; +import funkin.ui.freeplay.charselect.PlayableCharacter; import flixel.util.FlxColor; import flixel.tweens.FlxEase; import funkin.graphics.FunkinCamera; @@ -55,14 +58,16 @@ class ResultState extends MusicBeatSubState final highscoreNew:FlxSprite; 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; + var characterAtlasAnimations:Array< + { + sprite:FlxAtlasSprite, + delay:Float + }> = []; + var characterSparrowAnimations:Array< + { + sprite:FunkinSprite, + delay:Float + }> = []; var rankBg:FunkinSprite; final cameraBG:FunkinCamera; @@ -157,118 +162,84 @@ class ResultState extends MusicBeatSubState soundSystem.zIndex = 1100; add(soundSystem); - switch (rank) + // Fetch playable character data. Default to BF on the results screen if we can't find it. + var playerCharacterId:Null = PlayerRegistry.instance.getCharacterOwnerId(params.characterId); + var playerCharacter:Null = PlayerRegistry.instance.fetchEntry(playerCharacterId ?? 'bf'); + + trace('Got playable character: ${playerCharacter?.getName()}'); + // Query JSON data based on the rank, then use that to build the animation(s) the player sees. + var playerAnimationDatas:Array = playerCharacter != null ? playerCharacter.getResultsAnimationDatas(rank) : []; + + for (animData in playerAnimationDatas) { - case PERFECT | PERFECT_GOLD: - heartsPerfect = new FlxAtlasSprite(1342, 370, Paths.animateAtlas("resultScreen/results-bf/resultsPERFECT/hearts", "shared")); - heartsPerfect.visible = false; - heartsPerfect.zIndex = 501; - add(heartsPerfect); + if (animData == null) continue; - heartsPerfect.anim.onComplete = () -> { - if (heartsPerfect != null) + var animPath:String = Paths.stripLibrary(animData.assetPath); + var animLibrary:String = Paths.getLibrary(animData.assetPath); + var offsets = animData.offsets ?? [0, 0]; + switch (animData.renderType) + { + case 'animateatlas': + var animation:FlxAtlasSprite = new FlxAtlasSprite(offsets[0], offsets[1], Paths.animateAtlas(animPath, animLibrary)); + animation.zIndex = animData.zIndex ?? 500; + + animation.scale.set(animData.scale ?? 1.0, animData.scale ?? 1.0); + + if (animData.loopFrameLabel != null) { - // bfPerfect.anim.curFrame = 137; - heartsPerfect.anim.curFrame = 43; - heartsPerfect.anim.play(); // unpauses this anim, since it's on PlayOnce! + animation.anim.onComplete = () -> { + if (animation != null) + { + animation.playAnimation(animData.loopFrameLabel ?? ''); // 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); - - bfPerfect.anim.onComplete = () -> { - if (bfPerfect != null) + else if (animData.loopFrame != null) { - // bfPerfect.anim.curFrame = 137; - bfPerfect.anim.curFrame = 137; - bfPerfect.anim.play(); // unpauses this anim, since it's on PlayOnce! + animation.anim.onComplete = () -> { + if (animation != null) + { + animation.anim.curFrame = animData.loopFrame ?? 0; + animation.anim.play(); // unpauses this anim, since it's on PlayOnce! + } + } } - }; - case EXCELLENT: - bfExcellent = new FlxAtlasSprite(1329, 429, Paths.animateAtlas("resultScreen/results-bf/resultsEXCELLENT", "shared")); - bfExcellent.visible = false; - bfExcellent.zIndex = 500; - add(bfExcellent); + // Hide until ready to play. + animation.visible = false; + // Queue to play. + characterAtlasAnimations.push( + { + sprite: animation, + delay: animData.delay ?? 0.0 + }); + // Add to the scene. + add(animation); + case 'sparrow': + var animation:FunkinSprite = FunkinSprite.createSparrow(offsets[0], offsets[1], animPath); + animation.animation.addByPrefix('idle', '', 24, false, false, false); - bfExcellent.anim.onComplete = () -> { - if (bfExcellent != null) + if (animData.loopFrame != null) { - bfExcellent.anim.curFrame = 28; - bfExcellent.anim.play(); // unpauses this anim, since it's on PlayOnce! + animation.animation.finishCallback = (_name:String) -> { + if (animation != null) + { + animation.animation.play('idle', true, false, animData.loopFrame ?? 0); + } + } } - }; - case GREAT: - 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.scale.set(0.93, 0.93); - - bfGreat.anim.onComplete = () -> { - if (bfGreat != null) - { - 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'); - gfGood.animation.addByPrefix("clap", "Girlfriend Good Anim", 24, false); - gfGood.visible = false; - gfGood.zIndex = 500; - gfGood.animation.finishCallback = _ -> { - if (gfGood != null) - { - 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(_) { - if (bfGood != null) - { - 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) -> { - if (bfShit != null) - { - bfShit.playAnimation('Loop Start'); - } - }); + // Hide until ready to play. + animation.visible = false; + // Queue to play. + characterSparrowAnimations.push( + { + sprite: animation, + delay: animData.delay ?? 0.0 + }); + // Add to the scene. + add(animation); + } } var diffSpr:String = 'diff_${params?.difficultyId ?? 'Normal'}'; @@ -587,94 +558,22 @@ class ResultState extends MusicBeatSubState { showSmallClearPercent(); - switch (rank) + for (atlas in characterAtlasAnimations) { - case PERFECT | PERFECT_GOLD: - if (bfPerfect == null) - { - trace("Could not build PERFECT animation!"); - } - else - { - 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) - { - trace("Could not build EXCELLENT animation!"); - } - else - { - bfExcellent.visible = true; - bfExcellent.playAnimation(''); - } - case GREAT: - if (bfGreat == null) - { - trace("Could not build GREAT animation!"); - } - else - { - bfGreat.visible = true; - bfGreat.playAnimation(''); - } + new FlxTimer().start(atlas.delay, _ -> { + if (atlas.sprite == null) return; + atlas.sprite.visible = true; + atlas.sprite.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) - { - trace("Could not build SHIT animation!"); - } - else - { - bfShit.visible = true; - bfShit.playAnimation('Intro'); - } - case GOOD: - if (bfGood == null) - { - trace("Could not build GOOD animation!"); - } - else - { - 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) - { - gfGood.animation.play('clap', true); - gfGood.visible = true; - } - else - { - trace("Could not build GOOD animation!"); - } - }); - } - default: + for (sprite in characterSparrowAnimations) + { + new FlxTimer().start(sprite.delay, _ -> { + if (sprite.sprite == null) return; + sprite.sprite.visible = true; + sprite.sprite.animation.play('idle', true); + }); } } @@ -776,52 +675,6 @@ class ResultState extends MusicBeatSubState // })); // } - // 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; @@ -922,12 +775,21 @@ typedef ResultsStateParams = var storyMode:Bool; /** + * A readable title for the song we just played. * Either "Song Name by Artist Name" or "Week Name" */ var title:String; + /** + * The internal song ID for the song we just played. + */ var songId:String; + /** + * The character ID for the song we just played. + */ + var characterId:String; + /** * Whether the displayed score is a new highscore */ diff --git a/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx b/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx index 6d7b96c58..c46b4b930 100644 --- a/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx +++ b/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx @@ -3,6 +3,7 @@ package funkin.ui.freeplay.charselect; import funkin.data.IRegistryEntry; import funkin.data.freeplay.player.PlayerData; import funkin.data.freeplay.player.PlayerRegistry; +import funkin.play.scoring.Scoring.ScoringRank; /** * An object used to retrieve data about a playable character (also known as "weeks"). @@ -87,6 +88,32 @@ class PlayableCharacter implements IRegistryEntry return _data.freeplayDJ.getFreeplayDJText(index); } + /** + * @param rank Which rank to get info for + * @return An array of animations. For example, BF Great has two animations, one for BF and one for GF + */ + public function getResultsAnimationDatas(rank:ScoringRank):Array + { + if (_data.results == null) + { + return []; + } + + switch (rank) + { + case PERFECT | PERFECT_GOLD: + return _data.results.perfect; + case EXCELLENT: + return _data.results.excellent; + case GREAT: + return _data.results.great; + case GOOD: + return _data.results.good; + case SHIT: + return _data.results.loss; + } + } + /** * Returns whether this character is unlocked. */ From 7fbc7654032f6ae46abcccb120105f0015209319 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 4 Jul 2024 03:32:50 -0400 Subject: [PATCH 395/870] Implement Pico results (good animation) --- assets | 2 +- source/funkin/play/ResultState.hx | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/assets b/assets index 0351610af..859186eea 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 0351610af02b45eb25e4bbfef0380f6f1d8cf737 +Subproject commit 859186eea46c8b70deb3530c25304ba875b7b34a diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index ae1a9bcf8..042ab655d 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -187,22 +187,22 @@ class ResultState extends MusicBeatSubState if (animData.loopFrameLabel != null) { - animation.anim.onComplete = () -> { + animation.onAnimationFinish.add((_name:String) -> { if (animation != null) { animation.playAnimation(animData.loopFrameLabel ?? ''); // unpauses this anim, since it's on PlayOnce! } - } + }); } else if (animData.loopFrame != null) { - animation.anim.onComplete = () -> { + animation.onAnimationFinish.add((_name:String) -> { if (animation != null) { animation.anim.curFrame = animData.loopFrame ?? 0; animation.anim.play(); // unpauses this anim, since it's on PlayOnce! } - } + }); } // Hide until ready to play. From a7cfae85453adb0372141f211a5a9c85e8071e57 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 4 Jul 2024 14:48:24 -0400 Subject: [PATCH 396/870] mer --- .gitignore | 1 + .gitmodules | 4 +- assets | 2 +- hmm.json | 18 +- source/funkin/audio/FunkinSound.hx | 4 +- source/funkin/effects/RetroCameraFade.hx | 106 +++++ source/funkin/graphics/FunkinSprite.hx | 101 +++++ source/funkin/input/Controls.hx | 370 +++++++++++------- source/funkin/play/Countdown.hx | 19 +- source/funkin/play/GameOverSubState.hx | 26 +- source/funkin/play/ResultState.hx | 4 +- source/funkin/play/character/CharacterData.hx | 4 +- .../play/character/MultiSparrowCharacter.hx | 2 + .../funkin/play/character/PackerCharacter.hx | 2 + .../funkin/play/character/SparrowCharacter.hx | 2 + source/funkin/play/components/PopUpStuff.hx | 30 +- source/funkin/play/stage/Bopper.hx | 2 - source/funkin/play/stage/Stage.hx | 4 + source/funkin/ui/MenuItem.hx | 23 +- source/funkin/ui/freeplay/FreeplayState.hx | 17 +- source/funkin/ui/freeplay/SongMenuItem.hx | 46 ++- source/funkin/ui/mainmenu/MainMenuState.hx | 10 +- source/funkin/ui/story/LevelTitle.hx | 24 +- source/funkin/ui/story/StoryMenuState.hx | 2 +- source/funkin/ui/transition/LoadingState.hx | 2 +- source/funkin/util/logging/AnsiTrace.hx | 2 +- 26 files changed, 602 insertions(+), 225 deletions(-) create mode 100644 source/funkin/effects/RetroCameraFade.hx diff --git a/.gitignore b/.gitignore index 84585eee0..143cf08c9 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ shitAudio/ node_modules/ package.json package-lock.json +.aider.* diff --git a/.gitmodules b/.gitmodules index be5e0aaa8..452c0089b 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 diff --git a/assets b/assets index 8dd51cde0..d7ecd602d 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 8dd51cde0b9a3730abe9f97d0f50365c396ca784 +Subproject commit d7ecd602df733f0625763a2d7b6056f52147b9e6 diff --git a/hmm.json b/hmm.json index 68e0c5cb0..8eaf24212 100644 --- a/hmm.json +++ b/hmm.json @@ -5,7 +5,7 @@ "type": "git", "dir": null, "ref": "2d83fa863ef0c1eace5f1cf67c3ac315d1a3a8a5", - "url": "https://github.com/Aidan63/linc_discord-rpc" + "url": "https://github.com/FunkinCrew/linc_discord-rpc" }, { "name": "flixel", @@ -44,7 +44,7 @@ "name": "FlxPartialSound", "type": "git", "dir": null, - "ref": "f986332ba5ab02abd386ce662578baf04904604a", + "ref": "a1eab7b9bf507b87200a3341719054fe427f3b15", "url": "https://github.com/FunkinCrew/FlxPartialSound.git" }, { @@ -75,14 +75,14 @@ "name": "haxeui-core", "type": "git", "dir": null, - "ref": "0212d8fdfcafeb5f0d5a41e1ddba8ff21d0e183b", + "ref": "5dc4c933bdc029f6139a47962e3b8c754060f210", "url": "https://github.com/haxeui/haxeui-core" }, { "name": "haxeui-flixel", "type": "git", "dir": null, - "ref": "63a906a6148958dbfde8c7b48d90b0693767fd95", + "ref": "57c1604d6b5174839d7e0e012a4dd5dcbfc129da", "url": "https://github.com/haxeui/haxeui-flixel" }, { @@ -112,7 +112,7 @@ { "name": "hxp", "type": "haxelib", - "version": "1.2.2" + "version": "1.3.0" }, { "name": "json2object", @@ -174,15 +174,15 @@ "name": "thx.core", "type": "git", "dir": null, - "ref": "22605ff44f01971d599641790d6bae4869f7d9f4", - "url": "https://github.com/FunkinCrew/thx.core" + "ref": "6240b6e136f7490d9298edbe8c1891374bd7cdf2", + "url": "https://github.com/fponticelli/thx.core" }, { "name": "thx.semver", "type": "git", "dir": null, - "ref": "cf8d213589a2c7ce4a59b0fdba9e8ff36bc029fa", - "url": "https://github.com/FunkinCrew/thx.semver" + "ref": "bdb191fe7cf745c02a980749906dbf22719e200b", + "url": "https://github.com/fponticelli/thx.semver" } ] } diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index c70f195d2..11b713f4d 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -491,8 +491,10 @@ class FunkinSound extends FlxSound implements ICloneable 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 + // we are bypassing the openfl/lime asset library fuss on web only + #if web path = Paths.stripLibrary(path); + #end var soundRequest = FlxPartialSound.partialLoadFromFile(path, start, end); diff --git a/source/funkin/effects/RetroCameraFade.hx b/source/funkin/effects/RetroCameraFade.hx new file mode 100644 index 000000000..d4c1da5ef --- /dev/null +++ b/source/funkin/effects/RetroCameraFade.hx @@ -0,0 +1,106 @@ +package funkin.effects; + +import flixel.util.FlxTimer; +import flixel.FlxCamera; +import openfl.filters.ColorMatrixFilter; + +class RetroCameraFade +{ + // im lazy, but we only use this for week 6 + // and also sorta yoinked for djflixel, lol ! + public static function fadeWhite(camera:FlxCamera, camSteps:Int = 5, time:Float = 1):Void + { + var steps:Int = 0; + var stepsTotal:Int = camSteps; + + new FlxTimer().start(time / stepsTotal, _ -> { + var V:Float = (1 / stepsTotal) * steps; + if (steps == stepsTotal) V = 1; + + var matrix = [ + 1, 0, 0, 0, V * 255, + 0, 1, 0, 0, V * 255, + 0, 0, 1, 0, V * 255, + 0, 0, 0, 1, 0 + ]; + camera.filters = [new ColorMatrixFilter(matrix)]; + steps++; + }, stepsTotal + 1); + } + + public static function fadeFromWhite(camera:FlxCamera, camSteps:Int = 5, time:Float = 1):Void + { + var steps:Int = camSteps; + var stepsTotal:Int = camSteps; + + var matrixDerp = [ + 1, 0, 0, 0, 1.0 * 255, + 0, 1, 0, 0, 1.0 * 255, + 0, 0, 1, 0, 1.0 * 255, + 0, 0, 0, 1, 0 + ]; + camera.filters = [new ColorMatrixFilter(matrixDerp)]; + + new FlxTimer().start(time / stepsTotal, _ -> { + var V:Float = (1 / stepsTotal) * steps; + if (steps == stepsTotal) V = 1; + + var matrix = [ + 1, 0, 0, 0, V * 255, + 0, 1, 0, 0, V * 255, + 0, 0, 1, 0, V * 255, + 0, 0, 0, 1, 0 + ]; + camera.filters = [new ColorMatrixFilter(matrix)]; + steps--; + }, camSteps); + } + + public static function fadeToBlack(camera:FlxCamera, camSteps:Int = 5, time:Float = 1):Void + { + var steps:Int = 0; + var stepsTotal:Int = camSteps; + + new FlxTimer().start(time / stepsTotal, _ -> { + var V:Float = (1 / stepsTotal) * steps; + if (steps == stepsTotal) V = 1; + + var matrix = [ + 1, 0, 0, 0, -V * 255, + 0, 1, 0, 0, -V * 255, + 0, 0, 1, 0, -V * 255, + 0, 0, 0, 1, 0 + ]; + camera.filters = [new ColorMatrixFilter(matrix)]; + steps++; + }, camSteps); + } + + public static function fadeBlack(camera:FlxCamera, camSteps:Int = 5, time:Float = 1):Void + { + var steps:Int = camSteps; + var stepsTotal:Int = camSteps; + + var matrixDerp = [ + 1, 0, 0, 0, -1.0 * 255, + 0, 1, 0, 0, -1.0 * 255, + 0, 0, 1, 0, -1.0 * 255, + 0, 0, 0, 1, 0 + ]; + camera.filters = [new ColorMatrixFilter(matrixDerp)]; + + new FlxTimer().start(time / stepsTotal, _ -> { + var V:Float = (1 / stepsTotal) * steps; + if (steps == stepsTotal) V = 1; + + var matrix = [ + 1, 0, 0, 0, -V * 255, + 0, 1, 0, 0, -V * 255, + 0, 0, 1, 0, -V * 255, + 0, 0, 0, 1, 0 + ]; + camera.filters = [new ColorMatrixFilter(matrix)]; + steps--; + }, camSteps + 1); + } +} diff --git a/source/funkin/graphics/FunkinSprite.hx b/source/funkin/graphics/FunkinSprite.hx index bfd2e8028..521553527 100644 --- a/source/funkin/graphics/FunkinSprite.hx +++ b/source/funkin/graphics/FunkinSprite.hx @@ -7,6 +7,10 @@ import flixel.tweens.FlxTween; import openfl.display3D.textures.TextureBase; import funkin.graphics.framebuffer.FixedBitmapData; import openfl.display.BitmapData; +import flixel.math.FlxRect; +import flixel.math.FlxPoint; +import flixel.graphics.frames.FlxFrame; +import flixel.FlxCamera; /** * An FlxSprite with additional functionality. @@ -269,6 +273,103 @@ class FunkinSprite extends FlxSprite return result; } + @:access(flixel.FlxCamera) + override function getBoundingBox(camera:FlxCamera):FlxRect + { + getScreenPosition(_point, camera); + + _rect.set(_point.x, _point.y, width, height); + _rect = camera.transformRect(_rect); + + if (isPixelPerfectRender(camera)) + { + _rect.width = _rect.width / this.scale.x; + _rect.height = _rect.height / this.scale.y; + _rect.x = _rect.x / this.scale.x; + _rect.y = _rect.y / this.scale.y; + _rect.floor(); + _rect.x = _rect.x * this.scale.x; + _rect.y = _rect.y * this.scale.y; + _rect.width = _rect.width * this.scale.x; + _rect.height = _rect.height * this.scale.y; + } + + return _rect; + } + + /** + * Returns the screen position of this object. + * + * @param result Optional arg for the returning point + * @param camera The desired "screen" coordinate space. If `null`, `FlxG.camera` is used. + * @return The screen position of this object. + */ + public override function getScreenPosition(?result:FlxPoint, ?camera:FlxCamera):FlxPoint + { + if (result == null) result = FlxPoint.get(); + + if (camera == null) camera = FlxG.camera; + + result.set(x, y); + if (pixelPerfectPosition) + { + _rect.width = _rect.width / this.scale.x; + _rect.height = _rect.height / this.scale.y; + _rect.x = _rect.x / this.scale.x; + _rect.y = _rect.y / this.scale.y; + _rect.round(); + _rect.x = _rect.x * this.scale.x; + _rect.y = _rect.y * this.scale.y; + _rect.width = _rect.width * this.scale.x; + _rect.height = _rect.height * this.scale.y; + } + + return result.subtract(camera.scroll.x * scrollFactor.x, camera.scroll.y * scrollFactor.y); + } + + override function drawSimple(camera:FlxCamera):Void + { + getScreenPosition(_point, camera).subtractPoint(offset); + if (isPixelPerfectRender(camera)) + { + _point.x = _point.x / this.scale.x; + _point.y = _point.y / this.scale.y; + _point.round(); + + _point.x = _point.x * this.scale.x; + _point.y = _point.y * this.scale.y; + } + + _point.copyToFlash(_flashPoint); + camera.copyPixels(_frame, framePixels, _flashRect, _flashPoint, colorTransform, blend, antialiasing); + } + + override function drawComplex(camera:FlxCamera):Void + { + _frame.prepareMatrix(_matrix, FlxFrameAngle.ANGLE_0, checkFlipX(), checkFlipY()); + _matrix.translate(-origin.x, -origin.y); + _matrix.scale(scale.x, scale.y); + + if (bakedRotationAngle <= 0) + { + updateTrig(); + + if (angle != 0) _matrix.rotateWithTrig(_cosAngle, _sinAngle); + } + + getScreenPosition(_point, camera).subtractPoint(offset); + _point.add(origin.x, origin.y); + _matrix.translate(_point.x, _point.y); + + if (isPixelPerfectRender(camera)) + { + _matrix.tx = Math.round(_matrix.tx / this.scale.x) * this.scale.x; + _matrix.ty = Math.round(_matrix.ty / this.scale.y) * this.scale.y; + } + + camera.drawPixels(_frame, framePixels, _matrix, colorTransform, blend, antialiasing, shader); + } + public override function destroy():Void { frames = null; diff --git a/source/funkin/input/Controls.hx b/source/funkin/input/Controls.hx index e2cae5613..f6c881f6d 100644 --- a/source/funkin/input/Controls.hx +++ b/source/funkin/input/Controls.hx @@ -31,6 +31,7 @@ class Controls extends FlxActionSet * Uses FlxActions to funnel various inputs to a single action. */ var _ui_up = new FunkinAction(Action.UI_UP); + var _ui_left = new FunkinAction(Action.UI_LEFT); var _ui_right = new FunkinAction(Action.UI_RIGHT); var _ui_down = new FunkinAction(Action.UI_DOWN); @@ -325,19 +326,18 @@ class Controls extends FlxActionSet add(_volume_down); add(_volume_mute); - for (action in digitalActions) { - if (Std.isOfType(action, FunkinAction)) { + for (action in digitalActions) + { + if (Std.isOfType(action, FunkinAction)) + { var funkinAction:FunkinAction = cast action; byName[funkinAction.name] = funkinAction; - if (funkinAction.namePressed != null) - byName[funkinAction.namePressed] = funkinAction; - if (funkinAction.nameReleased != null) - byName[funkinAction.nameReleased] = funkinAction; + if (funkinAction.namePressed != null) byName[funkinAction.namePressed] = funkinAction; + if (funkinAction.nameReleased != null) byName[funkinAction.nameReleased] = funkinAction; } } - if (scheme == null) - scheme = None; + if (scheme == null) scheme = None; setKeyboardScheme(scheme, false); } @@ -350,38 +350,38 @@ class Controls extends FlxActionSet public function check(name:Action, trigger:FlxInputState = JUST_PRESSED, gamepadOnly:Bool = false):Bool { #if debug - if (!byName.exists(name)) - throw 'Invalid name: $name'; + if (!byName.exists(name)) throw 'Invalid name: $name'; #end var action = byName[name]; - if (gamepadOnly) - return action.checkFiltered(trigger, GAMEPAD); + if (gamepadOnly) return action.checkFiltered(trigger, GAMEPAD); else return action.checkFiltered(trigger); } - public function getKeysForAction(name:Action):Array { + public function getKeysForAction(name:Action):Array + { #if debug - if (!byName.exists(name)) - throw 'Invalid name: $name'; + if (!byName.exists(name)) throw 'Invalid name: $name'; #end // TODO: Revert to `.map().filter()` once HashLink doesn't complain anymore. var result:Array = []; - for (input in byName[name].inputs) { + for (input in byName[name].inputs) + { if (input.device == KEYBOARD) result.push(input.inputID); } return result; } - public function getButtonsForAction(name:Action):Array { + public function getButtonsForAction(name:Action):Array + { #if debug - if (!byName.exists(name)) - throw 'Invalid name: $name'; + if (!byName.exists(name)) throw 'Invalid name: $name'; #end var result:Array = []; - for (input in byName[name].inputs) { + for (input in byName[name].inputs) + { if (input.device == GAMEPAD) result.push(input.inputID); } return result; @@ -405,7 +405,7 @@ class Controls extends FlxActionSet function getActionFromControl(control:Control):FlxActionDigital { - return switch(control) + return switch (control) { case UI_UP: _ui_up; case UI_DOWN: _ui_down; @@ -448,7 +448,7 @@ class Controls extends FlxActionSet */ function forEachBound(control:Control, func:FlxActionDigital->FlxInputState->Void) { - switch(control) + switch (control) { case UI_UP: func(_ui_up, PRESSED); @@ -519,10 +519,9 @@ class Controls extends FlxActionSet public function replaceBinding(control:Control, device:Device, toAdd:Int, toRemove:Int) { - if (toAdd == toRemove) - return; + if (toAdd == toRemove) return; - switch(device) + switch (device) { case Keys: forEachBound(control, function(action, state) replaceKey(action, toAdd, toRemove, state)); @@ -534,7 +533,8 @@ class Controls extends FlxActionSet function replaceKey(action:FlxActionDigital, toAdd:FlxKey, toRemove:FlxKey, state:FlxInputState) { - if (action.inputs.length == 0) { + if (action.inputs.length == 0) + { // Add the keybind, don't replace. addKeys(action, [toAdd], state); return; @@ -548,34 +548,44 @@ class Controls extends FlxActionSet if (input.device == KEYBOARD && input.inputID == toRemove) { - if (toAdd == FlxKey.NONE) { + if (toAdd == FlxKey.NONE) + { // Remove the keybind, don't replace. action.inputs.remove(input); - } else { + } + else + { // Replace the keybind. @:privateAccess action.inputs[i].inputID = toAdd; } hasReplaced = true; - } else if (input.device == KEYBOARD && input.inputID == toAdd) { + } + else if (input.device == KEYBOARD && input.inputID == toAdd) + { // This key is already bound! - if (hasReplaced) { + if (hasReplaced) + { // Remove the duplicate keybind, don't replace. action.inputs.remove(input); - } else { + } + else + { hasReplaced = true; } } } - if (!hasReplaced) { + if (!hasReplaced) + { addKeys(action, [toAdd], state); } } function replaceButton(action:FlxActionDigital, deviceID:Int, toAdd:FlxGamepadInputID, toRemove:FlxGamepadInputID, state:FlxInputState) { - if (action.inputs.length == 0) { + if (action.inputs.length == 0) + { addButtons(action, [toAdd], state, deviceID); return; } @@ -594,7 +604,8 @@ class Controls extends FlxActionSet } } - if (!hasReplaced) { + if (!hasReplaced) + { addButtons(action, [toAdd], state, deviceID); } } @@ -606,18 +617,16 @@ class Controls extends FlxActionSet var action = controls.byName[name]; for (input in action.inputs) { - if (device == null || isDevice(input, device)) - byName[name].add(cast input); + if (device == null || isDevice(input, device)) byName[name].add(cast input); } } - switch(device) + switch (device) { case null: // add all for (gamepad in controls.gamepadsAdded) - if (gamepadsAdded.indexOf(gamepad) == -1) - gamepadsAdded.push(gamepad); + if (gamepadsAdded.indexOf(gamepad) == -1) gamepadsAdded.push(gamepad); mergeKeyboardScheme(controls.keyboardScheme); @@ -637,7 +646,7 @@ class Controls extends FlxActionSet { if (scheme != None) { - switch(keyboardScheme) + switch (keyboardScheme) { case None: keyboardScheme = scheme; @@ -672,7 +681,8 @@ class Controls extends FlxActionSet static function addKeys(action:FlxActionDigital, keys:Array, state:FlxInputState) { - for (key in keys) { + for (key in keys) + { if (key == FlxKey.NONE) continue; // Ignore unbound keys. action.addKey(key, state); } @@ -684,15 +694,13 @@ class Controls extends FlxActionSet while (i-- > 0) { var input = action.inputs[i]; - if (input.device == KEYBOARD && keys.indexOf(cast input.inputID) != -1) - action.remove(input); + if (input.device == KEYBOARD && keys.indexOf(cast input.inputID) != -1) action.remove(input); } } public function setKeyboardScheme(scheme:KeyboardScheme, reset = true) { - if (reset) - removeKeyboard(); + if (reset) removeKeyboard(); keyboardScheme = scheme; @@ -724,10 +732,13 @@ class Controls extends FlxActionSet bindMobileLol(); } - function getDefaultKeybinds(scheme:KeyboardScheme, control:Control):Array { - switch (scheme) { + function getDefaultKeybinds(scheme:KeyboardScheme, control:Control):Array + { + switch (scheme) + { case Solo: - switch (control) { + switch (control) + { case Control.UI_UP: return [W, FlxKey.UP]; case Control.UI_DOWN: return [S, FlxKey.DOWN]; case Control.UI_LEFT: return [A, FlxKey.LEFT]; @@ -754,7 +765,8 @@ class Controls extends FlxActionSet case Control.VOLUME_MUTE: return [ZERO, NUMPADZERO]; } case Duo(true): - switch (control) { + switch (control) + { case Control.UI_UP: return [W]; case Control.UI_DOWN: return [S]; case Control.UI_LEFT: return [A]; @@ -779,10 +791,10 @@ class Controls extends FlxActionSet case Control.VOLUME_UP: return [PLUS]; case Control.VOLUME_DOWN: return [MINUS]; case Control.VOLUME_MUTE: return [ZERO]; - } case Duo(false): - switch (control) { + switch (control) + { case Control.UI_UP: return [FlxKey.UP]; case Control.UI_DOWN: return [FlxKey.DOWN]; case Control.UI_LEFT: return [FlxKey.LEFT]; @@ -807,7 +819,6 @@ class Controls extends FlxActionSet case Control.VOLUME_UP: return [NUMPADPLUS]; case Control.VOLUME_DOWN: return [NUMPADMINUS]; case Control.VOLUME_MUTE: return [NUMPADZERO]; - } default: // Fallthrough. @@ -834,8 +845,7 @@ class Controls extends FlxActionSet #end #if android - forEachBound(Control.BACK, function(action, pres) - { + forEachBound(Control.BACK, function(action, pres) { action.add(new FlxActionInputDigitalAndroid(FlxAndroidKey.BACK, JUST_PRESSED)); }); #end @@ -849,8 +859,7 @@ class Controls extends FlxActionSet while (i-- > 0) { var input = action.inputs[i]; - if (input.device == KEYBOARD) - action.remove(input); + if (input.device == KEYBOARD) action.remove(input); } } } @@ -862,11 +871,13 @@ class Controls extends FlxActionSet fromSaveData(padData, Gamepad(id)); } - public function getGamepadIds():Array { + public function getGamepadIds():Array + { return gamepadsAdded; } - public function getGamepads():Array { + public function getGamepads():Array + { return [for (id in gamepadsAdded) FlxG.gamepads.getByID(id)]; } @@ -886,8 +897,7 @@ class Controls extends FlxActionSet while (i-- > 0) { var input = action.inputs[i]; - if (isGamepad(input, deviceID)) - action.remove(input); + if (isGamepad(input, deviceID)) action.remove(input); } } @@ -924,32 +934,58 @@ class Controls extends FlxActionSet ]); } - function getDefaultGamepadBinds(control:Control):Array { - switch(control) { - case Control.ACCEPT: return [#if switch B #else A #end]; - case Control.BACK: return [#if switch A #else B #end]; - case Control.UI_UP: return [DPAD_UP, LEFT_STICK_DIGITAL_UP]; - case Control.UI_DOWN: return [DPAD_DOWN, LEFT_STICK_DIGITAL_DOWN]; - case Control.UI_LEFT: return [DPAD_LEFT, LEFT_STICK_DIGITAL_LEFT]; - case Control.UI_RIGHT: return [DPAD_RIGHT, LEFT_STICK_DIGITAL_RIGHT]; - case Control.NOTE_UP: return [DPAD_UP, Y, LEFT_STICK_DIGITAL_UP, RIGHT_STICK_DIGITAL_UP]; - case Control.NOTE_DOWN: return [DPAD_DOWN, A, LEFT_STICK_DIGITAL_DOWN, RIGHT_STICK_DIGITAL_DOWN]; - case Control.NOTE_LEFT: return [DPAD_LEFT, X, LEFT_STICK_DIGITAL_LEFT, RIGHT_STICK_DIGITAL_LEFT]; - case Control.NOTE_RIGHT: return [DPAD_RIGHT, B, LEFT_STICK_DIGITAL_RIGHT, RIGHT_STICK_DIGITAL_RIGHT]; - case Control.PAUSE: return [START]; - case Control.RESET: return [FlxGamepadInputID.BACK]; // Back (i.e. Select) - case Control.WINDOW_FULLSCREEN: []; - case Control.WINDOW_SCREENSHOT: []; - case Control.CUTSCENE_ADVANCE: return [A]; - case Control.FREEPLAY_FAVORITE: [FlxGamepadInputID.BACK]; // Back (i.e. Select) - case Control.FREEPLAY_LEFT: [LEFT_SHOULDER]; - case Control.FREEPLAY_RIGHT: [RIGHT_SHOULDER]; - case Control.VOLUME_UP: []; - case Control.VOLUME_DOWN: []; - case Control.VOLUME_MUTE: []; - case Control.DEBUG_MENU: []; - case Control.DEBUG_CHART: []; - case Control.DEBUG_STAGE: []; + function getDefaultGamepadBinds(control:Control):Array + { + switch (control) + { + case Control.ACCEPT: + return [#if switch B #else A #end]; + case Control.BACK: + return [#if switch A #else B #end]; + case Control.UI_UP: + return [DPAD_UP, LEFT_STICK_DIGITAL_UP]; + case Control.UI_DOWN: + return [DPAD_DOWN, LEFT_STICK_DIGITAL_DOWN]; + case Control.UI_LEFT: + return [DPAD_LEFT, LEFT_STICK_DIGITAL_LEFT]; + case Control.UI_RIGHT: + return [DPAD_RIGHT, LEFT_STICK_DIGITAL_RIGHT]; + case Control.NOTE_UP: + return [DPAD_UP, Y, LEFT_STICK_DIGITAL_UP, RIGHT_STICK_DIGITAL_UP]; + case Control.NOTE_DOWN: + return [DPAD_DOWN, A, LEFT_STICK_DIGITAL_DOWN, RIGHT_STICK_DIGITAL_DOWN]; + case Control.NOTE_LEFT: + return [DPAD_LEFT, X, LEFT_STICK_DIGITAL_LEFT, RIGHT_STICK_DIGITAL_LEFT]; + case Control.NOTE_RIGHT: + return [DPAD_RIGHT, B, LEFT_STICK_DIGITAL_RIGHT, RIGHT_STICK_DIGITAL_RIGHT]; + case Control.PAUSE: + return [START]; + case Control.RESET: + return [FlxGamepadInputID.BACK]; // Back (i.e. Select) + case Control.WINDOW_FULLSCREEN: + []; + case Control.WINDOW_SCREENSHOT: + []; + case Control.CUTSCENE_ADVANCE: + return [A]; + case Control.FREEPLAY_FAVORITE: + [FlxGamepadInputID.BACK]; // Back (i.e. Select) + case Control.FREEPLAY_LEFT: + [LEFT_SHOULDER]; + case Control.FREEPLAY_RIGHT: + [RIGHT_SHOULDER]; + case Control.VOLUME_UP: + []; + case Control.VOLUME_DOWN: + []; + case Control.VOLUME_MUTE: + []; + case Control.DEBUG_MENU: + []; + case Control.DEBUG_CHART: + []; + case Control.DEBUG_STAGE: + []; default: // Fallthrough. } @@ -967,8 +1003,7 @@ class Controls extends FlxActionSet public function touchShit(control:Control, id) { - forEachBound(control, function(action, state) - { + forEachBound(control, function(action, state) { // action }); } @@ -984,7 +1019,8 @@ class Controls extends FlxActionSet inline static function addButtons(action:FlxActionDigital, buttons:Array, state, id) { - for (button in buttons) { + for (button in buttons) + { if (button == FlxGamepadInputID.NONE) continue; // Ignore unbound keys. action.addGamepad(button, state, id); } @@ -996,29 +1032,25 @@ class Controls extends FlxActionSet while (i-- > 0) { var input = action.inputs[i]; - if (isGamepad(input, gamepadID) && buttons.indexOf(cast input.inputID) != -1) - action.remove(input); + if (isGamepad(input, gamepadID) && buttons.indexOf(cast input.inputID) != -1) action.remove(input); } } public function getInputsFor(control:Control, device:Device, ?list:Array):Array { - if (list == null) - list = []; + if (list == null) list = []; - switch(device) + switch (device) { case Keys: for (input in getActionFromControl(control).inputs) { - if (input.device == KEYBOARD) - list.push(input.inputID); + if (input.device == KEYBOARD) list.push(input.inputID); } case Gamepad(id): for (input in getActionFromControl(control).inputs) { - if (isGamepad(input, id)) - list.push(input.inputID); + if (isGamepad(input, id)) list.push(input.inputID); } } return list; @@ -1026,7 +1058,7 @@ class Controls extends FlxActionSet public function removeDevice(device:Device) { - switch(device) + switch (device) { case Keys: setKeyboardScheme(None); @@ -1040,27 +1072,32 @@ class Controls extends FlxActionSet * An EMPTY array means the control is uninitialized and needs to be reset to default. * An array with a single FlxKey.NONE means the control was intentionally unbound by the user. */ - public function fromSaveData(data:Dynamic, device:Device) + public function fromSaveData(data:Dynamic, device:Device):Void { for (control in Control.createAll()) { var inputs:Array = Reflect.field(data, control.getName()); - inputs = inputs.distinct(); + inputs = inputs?.distinct(); if (inputs != null) { - if (inputs.length == 0) { + if (inputs.length == 0) + { trace('Control ${control} is missing bindings, resetting to default.'); - switch(device) + switch (device) { case Keys: bindKeys(control, getDefaultKeybinds(Solo, control)); case Gamepad(id): bindButtons(control, id, getDefaultGamepadBinds(control)); } - } else if (inputs == [FlxKey.NONE]) { + } + else if (inputs == [FlxKey.NONE]) + { trace('Control ${control} is unbound, leaving it be.'); - } else { - switch(device) + } + else + { + switch (device) { case Keys: bindKeys(control, inputs.copy()); @@ -1068,9 +1105,11 @@ class Controls extends FlxActionSet bindButtons(control, id, inputs.copy()); } } - } else { + } + else + { trace('Control ${control} is missing bindings, resetting to default.'); - switch(device) + switch (device) { case Keys: bindKeys(control, getDefaultKeybinds(Solo, control)); @@ -1095,9 +1134,12 @@ class Controls extends FlxActionSet var inputs = getInputsFor(control, device); isEmpty = isEmpty && inputs.length == 0; - if (inputs.length == 0) { + if (inputs.length == 0) + { inputs = [FlxKey.NONE]; - } else { + } + else + { inputs = inputs.distinct(); } @@ -1109,7 +1151,7 @@ class Controls extends FlxActionSet static function isDevice(input:FlxActionInput, device:Device) { - return switch(device) + return switch (device) { case Keys: input.device == KEYBOARD; case Gamepad(id): isGamepad(input, id); @@ -1141,7 +1183,8 @@ typedef Swipes = * - Combining `pressed` and `released` inputs into one action. * - Filtering by input method (`KEYBOARD`, `MOUSE`, `GAMEPAD`, etc). */ -class FunkinAction extends FlxActionDigital { +class FunkinAction extends FlxActionDigital +{ public var namePressed(default, null):Null; public var nameReleased(default, null):Null; @@ -1158,83 +1201,102 @@ class FunkinAction extends FlxActionDigital { /** * Input checks default to whether the input was just pressed, on any input device. */ - public override function check():Bool { + public override function check():Bool + { return checkFiltered(JUST_PRESSED); } /** * Check whether the input is currently being held. */ - public function checkPressed():Bool { + public function checkPressed():Bool + { return checkFiltered(PRESSED); } /** * Check whether the input is currently being held, and was not held last frame. */ - public function checkJustPressed():Bool { + public function checkJustPressed():Bool + { return checkFiltered(JUST_PRESSED); } /** * Check whether the input is not currently being held. */ - public function checkReleased():Bool { + public function checkReleased():Bool + { return checkFiltered(RELEASED); } /** * Check whether the input is not currently being held, and was held last frame. */ - public function checkJustReleased():Bool { + public function checkJustReleased():Bool + { return checkFiltered(JUST_RELEASED); } /** * Check whether the input is currently being held by a gamepad device. */ - public function checkPressedGamepad():Bool { + public function checkPressedGamepad():Bool + { return checkFiltered(PRESSED, GAMEPAD); } /** * Check whether the input is currently being held by a gamepad device, and was not held last frame. */ - public function checkJustPressedGamepad():Bool { + public function checkJustPressedGamepad():Bool + { return checkFiltered(JUST_PRESSED, GAMEPAD); } /** * Check whether the input is not currently being held by a gamepad device. */ - public function checkReleasedGamepad():Bool { + public function checkReleasedGamepad():Bool + { return checkFiltered(RELEASED, GAMEPAD); } /** * Check whether the input is not currently being held by a gamepad device, and was held last frame. */ - public function checkJustReleasedGamepad():Bool { + public function checkJustReleasedGamepad():Bool + { return checkFiltered(JUST_RELEASED, GAMEPAD); } - public function checkMultiFiltered(?filterTriggers:Array, ?filterDevices:Array):Bool { - if (filterTriggers == null) { + public function checkMultiFiltered(?filterTriggers:Array, ?filterDevices:Array):Bool + { + if (filterTriggers == null) + { filterTriggers = [PRESSED, JUST_PRESSED]; } - if (filterDevices == null) { + if (filterDevices == null) + { filterDevices = []; } // Perform checkFiltered for each combination. - for (i in filterTriggers) { - if (filterDevices.length == 0) { - if (checkFiltered(i)) { + for (i in filterTriggers) + { + if (filterDevices.length == 0) + { + if (checkFiltered(i)) + { return true; } - } else { - for (j in filterDevices) { - if (checkFiltered(i, j)) { + } + else + { + for (j in filterDevices) + { + if (checkFiltered(i, j)) + { return true; } } @@ -1249,52 +1311,56 @@ class FunkinAction extends FlxActionDigital { * @param filterTrigger Optionally filter by trigger condition (`JUST_PRESSED`, `PRESSED`, `JUST_RELEASED`, `RELEASED`). * @param filterDevice Optionally filter by device (`KEYBOARD`, `MOUSE`, `GAMEPAD`, `OTHER`). */ - public function checkFiltered(?filterTrigger:FlxInputState, ?filterDevice:FlxInputDevice):Bool { + public function checkFiltered(?filterTrigger:FlxInputState, ?filterDevice:FlxInputDevice):Bool + { // The normal // Make sure we only update the inputs once per frame. var key = '${filterTrigger}:${filterDevice}'; var cacheEntry = cache.get(key); - if (cacheEntry != null && cacheEntry.timestamp == FlxG.game.ticks) { + if (cacheEntry != null && cacheEntry.timestamp == FlxG.game.ticks) + { return cacheEntry.value; } // Use a for loop instead so we can remove inputs while iterating. // We don't return early because we need to call check() on ALL inputs. var result = false; - var len = inputs != null ? inputs.length : 0; - for (i in 0...len) - { - var j = len - i - 1; - var input = inputs[j]; + var len = inputs != null ? inputs.length : 0; + for (i in 0...len) + { + var j = len - i - 1; + var input = inputs[j]; // Filter out dead inputs. - if (input.destroyed) - { - inputs.splice(j, 1); - continue; - } + if (input.destroyed) + { + inputs.splice(j, 1); + continue; + } // Update the input. input.update(); // Check whether the input is the right trigger. - if (filterTrigger != null && input.trigger != filterTrigger) { + if (filterTrigger != null && input.trigger != filterTrigger) + { continue; } // Check whether the input is the right device. - if (filterDevice != null && input.device != filterDevice) { + if (filterDevice != null && input.device != filterDevice) + { continue; } // Check whether the input has triggered. - if (input.check(this)) - { - result = true; - } - } + if (input.check(this)) + { + result = true; + } + } // We need to cache this result. cache.set(key, {timestamp: FlxG.game.ticks, value: result}); @@ -1391,12 +1457,12 @@ class FlxActionInputDigitalMobileSwipeGameplay extends FlxActionInputDigital { var degAngle = FlxAngle.asDegrees(swp.touchAngle); - switch(trigger) + switch (trigger) { case JUST_PRESSED: if (swp.touchLength >= activateLength) { - switch(inputID) + switch (inputID) { case FlxDirectionFlags.UP: if (degAngle >= 45 && degAngle <= 90 + 45) return properTouch(swp); @@ -1440,7 +1506,7 @@ class FlxActionInputDigitalAndroid extends FlxActionInputDigital override public function check(Action:FlxAction):Bool { - return switch(trigger) + return switch (trigger) { #if android case PRESSED: FlxG.android.checkStatus(inputID, PRESSED) || FlxG.android.checkStatus(inputID, PRESSED); diff --git a/source/funkin/play/Countdown.hx b/source/funkin/play/Countdown.hx index 10636afdf..55c2a8992 100644 --- a/source/funkin/play/Countdown.hx +++ b/source/funkin/play/Countdown.hx @@ -9,6 +9,7 @@ import funkin.modding.module.ModuleHandler; import funkin.modding.events.ScriptEvent; import funkin.modding.events.ScriptEvent.CountdownScriptEvent; import flixel.util.FlxTimer; +import funkin.util.EaseUtil; import funkin.audio.FunkinSound; class Countdown @@ -117,7 +118,7 @@ class Countdown * * If you want to call this from a module, it's better to use the event system and cancel the onCountdownStep event. */ - public static function pauseCountdown() + public static function pauseCountdown():Void { if (countdownTimer != null && !countdownTimer.finished) { @@ -130,7 +131,7 @@ class Countdown * * If you want to call this from a module, it's better to use the event system and cancel the onCountdownStep event. */ - public static function resumeCountdown() + public static function resumeCountdown():Void { if (countdownTimer != null && !countdownTimer.finished) { @@ -143,7 +144,7 @@ class Countdown * * If you want to call this from a module, it's better to use the event system and cancel the onCountdownStart event. */ - public static function stopCountdown() + public static function stopCountdown():Void { if (countdownTimer != null) { @@ -156,7 +157,7 @@ class Countdown /** * Stops the current countdown, then starts the song for you. */ - public static function skipCountdown() + public static function skipCountdown():Void { stopCountdown(); // This will trigger PlayState.startSong() @@ -185,8 +186,11 @@ class Countdown { var spritePath:String = null; + var fadeEase = FlxEase.cubeInOut; + if (isPixelStyle) { + fadeEase = EaseUtil.stepped(8); switch (index) { case TWO: @@ -227,7 +231,7 @@ class Countdown countdownSprite.screenCenter(); // Fade sprite in, then out, then destroy it. - FlxTween.tween(countdownSprite, {y: countdownSprite.y += 100, alpha: 0}, Conductor.instance.beatLengthMs / 1000, + FlxTween.tween(countdownSprite, {y: countdownSprite.y += 100}, Conductor.instance.beatLengthMs / 1000, { ease: FlxEase.cubeInOut, onComplete: function(twn:FlxTween) { @@ -235,6 +239,11 @@ class Countdown } }); + FlxTween.tween(countdownSprite, {alpha: 0}, Conductor.instance.beatLengthMs / 1000, + { + ease: fadeEase + }); + PlayState.instance.add(countdownSprite); } diff --git a/source/funkin/play/GameOverSubState.hx b/source/funkin/play/GameOverSubState.hx index c84d5b154..6eb954c0f 100644 --- a/source/funkin/play/GameOverSubState.hx +++ b/source/funkin/play/GameOverSubState.hx @@ -16,6 +16,7 @@ import funkin.ui.MusicBeatSubState; import funkin.ui.story.StoryMenuState; import funkin.util.MathUtil; import openfl.utils.Assets; +import funkin.effects.RetroCameraFade; /** * A substate which renders over the PlayState when the player dies. @@ -144,6 +145,7 @@ class GameOverSubState extends MusicBeatSubState else { boyfriend = PlayState.instance.currentStage.getBoyfriend(true); + boyfriend.canPlayOtherAnims = true; boyfriend.isDead = true; add(boyfriend); boyfriend.resetCharacter(); @@ -331,9 +333,12 @@ class GameOverSubState extends MusicBeatSubState // After the animation finishes... new FlxTimer().start(0.7, function(tmr:FlxTimer) { // ...fade out the graphics. Then after that happens... - FlxG.camera.fade(FlxColor.BLACK, 2, false, function() { + + var resetPlaying = function(pixel:Bool = false) { // ...close the GameOverSubState. - FlxG.camera.fade(FlxColor.BLACK, 1, true, null, true); + if (pixel) RetroCameraFade.fadeBlack(FlxG.camera, 10, 1); + else + FlxG.camera.fade(FlxColor.BLACK, 1, true, null, true); PlayState.instance.needsReset = true; if (PlayState.instance.isMinimalMode || boyfriend == null) {} @@ -350,7 +355,22 @@ class GameOverSubState extends MusicBeatSubState // Close the substate. close(); - }); + }; + + if (musicSuffix == '-pixel') + { + RetroCameraFade.fadeToBlack(FlxG.camera, 10, 2); + new FlxTimer().start(2, _ -> { + FlxG.camera.filters = []; + resetPlaying(true); + }); + } + else + { + FlxG.camera.fade(FlxColor.BLACK, 2, false, function() { + resetPlaying(); + }); + } }); } } diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index 48fb3b04e..a2c5f7e62 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -464,7 +464,9 @@ class ResultState extends MusicBeatSubState { 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; + // NOTE: Only divide if totalNotes > 0 to prevent divide-by-zero errors. + var clearPercentFloat = params.scoreData.tallies.totalNotes == 0 ? 0.0 : (params.scoreData.tallies.sick + + params.scoreData.tallies.good) / params.scoreData.tallies.totalNotes * 100; clearPercentTarget = Math.floor(clearPercentFloat); // Prevent off-by-one errors. diff --git a/source/funkin/play/character/CharacterData.hx b/source/funkin/play/character/CharacterData.hx index 7d3d6cfb9..8b1649e26 100644 --- a/source/funkin/play/character/CharacterData.hx +++ b/source/funkin/play/character/CharacterData.hx @@ -305,8 +305,8 @@ class CharacterDataParser icon = "darnell"; case "senpai-angry": icon = "senpai"; - case "tankman" | "tankman-atlas": - icon = "tankmen"; + case "tankman-atlas": + icon = "tankman"; } var path = Paths.image("freeplay/icons/" + icon + "pixel"); diff --git a/source/funkin/play/character/MultiSparrowCharacter.hx b/source/funkin/play/character/MultiSparrowCharacter.hx index 48c5afb58..41c96fbfa 100644 --- a/source/funkin/play/character/MultiSparrowCharacter.hx +++ b/source/funkin/play/character/MultiSparrowCharacter.hx @@ -41,6 +41,8 @@ class MultiSparrowCharacter extends BaseCharacter { this.isPixel = true; this.antialiasing = false; + pixelPerfectRender = true; + pixelPerfectPosition = true; } else { diff --git a/source/funkin/play/character/PackerCharacter.hx b/source/funkin/play/character/PackerCharacter.hx index 2bfac800a..22edbe339 100644 --- a/source/funkin/play/character/PackerCharacter.hx +++ b/source/funkin/play/character/PackerCharacter.hx @@ -43,6 +43,8 @@ class PackerCharacter extends BaseCharacter { this.isPixel = true; this.antialiasing = false; + pixelPerfectRender = true; + pixelPerfectPosition = true; } else { diff --git a/source/funkin/play/character/SparrowCharacter.hx b/source/funkin/play/character/SparrowCharacter.hx index a36aed84d..81d98b138 100644 --- a/source/funkin/play/character/SparrowCharacter.hx +++ b/source/funkin/play/character/SparrowCharacter.hx @@ -46,6 +46,8 @@ class SparrowCharacter extends BaseCharacter { this.isPixel = true; this.antialiasing = false; + pixelPerfectRender = true; + pixelPerfectPosition = true; } else { diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx index b7e206e97..1bdfd98a8 100644 --- a/source/funkin/play/components/PopUpStuff.hx +++ b/source/funkin/play/components/PopUpStuff.hx @@ -7,8 +7,9 @@ import flixel.util.FlxDirection; import funkin.graphics.FunkinSprite; import funkin.play.PlayState; import funkin.util.TimerUtil; +import funkin.util.EaseUtil; -class PopUpStuff extends FlxTypedGroup +class PopUpStuff extends FlxTypedGroup { public var offsets:Array = [0, 0]; @@ -17,7 +18,7 @@ class PopUpStuff extends FlxTypedGroup super(); } - public function displayRating(daRating:String) + public function displayRating(daRating:String):Void { var perfStart:Float = TimerUtil.start(); @@ -40,10 +41,15 @@ class PopUpStuff extends FlxTypedGroup add(rating); + var fadeEase = null; + if (PlayState.instance.currentStageId.startsWith('school')) { rating.setGraphicSize(Std.int(rating.width * Constants.PIXEL_ART_SCALE * 0.7)); rating.antialiasing = false; + rating.pixelPerfectRender = true; + rating.pixelPerfectPosition = true; + fadeEase = EaseUtil.stepped(2); } else { @@ -61,7 +67,8 @@ class PopUpStuff extends FlxTypedGroup remove(rating, true); rating.destroy(); }, - startDelay: Conductor.instance.beatLengthMs * 0.001 + startDelay: Conductor.instance.beatLengthMs * 0.001, + ease: fadeEase }); trace('displayRating took: ${TimerUtil.seconds(perfStart)}'); @@ -92,10 +99,15 @@ class PopUpStuff extends FlxTypedGroup // add(comboSpr); + var fadeEase = null; + if (PlayState.instance.currentStageId.startsWith('school')) { - comboSpr.setGraphicSize(Std.int(comboSpr.width * Constants.PIXEL_ART_SCALE * 0.7)); + comboSpr.setGraphicSize(Std.int(comboSpr.width * Constants.PIXEL_ART_SCALE * 1)); comboSpr.antialiasing = false; + comboSpr.pixelPerfectRender = true; + comboSpr.pixelPerfectPosition = true; + fadeEase = EaseUtil.stepped(2); } else { @@ -110,7 +122,8 @@ class PopUpStuff extends FlxTypedGroup remove(comboSpr, true); comboSpr.destroy(); }, - startDelay: Conductor.instance.beatLengthMs * 0.001 + startDelay: Conductor.instance.beatLengthMs * 0.001, + ease: fadeEase }); var seperatedScore:Array = []; @@ -133,8 +146,10 @@ class PopUpStuff extends FlxTypedGroup if (PlayState.instance.currentStageId.startsWith('school')) { - numScore.setGraphicSize(Std.int(numScore.width * Constants.PIXEL_ART_SCALE * 0.7)); + numScore.setGraphicSize(Std.int(numScore.width * Constants.PIXEL_ART_SCALE * 1)); numScore.antialiasing = false; + numScore.pixelPerfectRender = true; + numScore.pixelPerfectPosition = true; } else { @@ -156,7 +171,8 @@ class PopUpStuff extends FlxTypedGroup remove(numScore, true); numScore.destroy(); }, - startDelay: Conductor.instance.beatLengthMs * 0.002 + startDelay: Conductor.instance.beatLengthMs * 0.002, + ease: fadeEase }); daLoop++; diff --git a/source/funkin/play/stage/Bopper.hx b/source/funkin/play/stage/Bopper.hx index 262aff7bc..11fb9e499 100644 --- a/source/funkin/play/stage/Bopper.hx +++ b/source/funkin/play/stage/Bopper.hx @@ -200,12 +200,10 @@ class Bopper extends StageProp implements IPlayStateScriptedClass { if (hasDanced) { - trace('DanceRight (alternate)'); playAnimation('danceRight$idleSuffix', forceRestart); } else { - trace('DanceLeft (alternate)'); playAnimation('danceLeft$idleSuffix', forceRestart); } hasDanced = !hasDanced; diff --git a/source/funkin/play/stage/Stage.hx b/source/funkin/play/stage/Stage.hx index 4f8ab4434..f4e22e380 100644 --- a/source/funkin/play/stage/Stage.hx +++ b/source/funkin/play/stage/Stage.hx @@ -249,6 +249,10 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements // If pixel, disable antialiasing. propSprite.antialiasing = !dataProp.isPixel; + // If pixel, we render it pixel perfect so there's less "mixels" + propSprite.pixelPerfectRender = dataProp.isPixel; + propSprite.pixelPerfectPosition = dataProp.isPixel; + propSprite.scrollFactor.x = dataProp.scroll[0]; propSprite.scrollFactor.y = dataProp.scroll[1]; diff --git a/source/funkin/ui/MenuItem.hx b/source/funkin/ui/MenuItem.hx index ba5cc066b..2a483ea78 100644 --- a/source/funkin/ui/MenuItem.hx +++ b/source/funkin/ui/MenuItem.hx @@ -11,7 +11,6 @@ class MenuItem extends FlxSpriteGroup { public var targetY:Float = 0; public var week:FlxSprite; - public var flashingInt:Int = 0; public function new(x:Float, y:Float, weekNum:Int = 0, weekType:WeekType) { @@ -30,28 +29,28 @@ class MenuItem extends FlxSpriteGroup } var isFlashing:Bool = false; + var flashTick:Float = 0; + final flashFramerate:Float = 20; public function startFlashing():Void { isFlashing = true; } - // if it runs at 60fps, fake framerate will be 6 - // if it runs at 144 fps, fake framerate will be like 14, and will update the graphic every 0.016666 * 3 seconds still??? - // so it runs basically every so many seconds, not dependant on framerate?? - // I'm still learning how math works thanks whoever is reading this lol - var fakeFramerate:Int = Math.round((1 / FlxG.elapsed) / 10); - override function update(elapsed:Float) { super.update(elapsed); y = MathUtil.coolLerp(y, (targetY * 120) + 480, 0.17); - if (isFlashing) flashingInt += 1; - - if (flashingInt % fakeFramerate >= Math.floor(fakeFramerate / 2)) week.color = 0xFF33ffff; - else - week.color = FlxColor.WHITE; + if (isFlashing) + { + flashTick += elapsed; + if (flashTick >= 1 / flashFramerate) + { + flashTick %= 1 / flashFramerate; + week.color = (week.color == FlxColor.WHITE) ? 0xFF33ffff : FlxColor.WHITE; + } + } } } diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 637c23c95..abbe2d6bd 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -227,7 +227,7 @@ class FreeplayState extends MusicBeatSubState super(FlxColor.TRANSPARENT); - if (stickers != null) + if (stickers?.members != null) { stickerSubState = stickers; } @@ -640,7 +640,6 @@ class FreeplayState extends MusicBeatSubState // be careful not to "add()" things in here unless it's to a group that's already added to the state // otherwise it won't be properly attatched to funnyCamera (relavent code should be at the bottom of create()) var onDJIntroDone = function() { - // when boyfriend hits dat shiii albumRoll.playIntro(); @@ -693,9 +692,12 @@ class FreeplayState extends MusicBeatSubState } }; - if (dj != null) { + if (dj != null) + { dj.onIntroDone.add(onDJIntroDone); - } else { + } + else + { onDJIntroDone(); } @@ -1775,7 +1777,7 @@ class FreeplayState extends MusicBeatSubState if (dj != null) dj.confirm(); grpCapsules.members[curSelected].forcePosition(); - grpCapsules.members[curSelected].songText.flickerText(); + grpCapsules.members[curSelected].confirm(); // FlxTween.color(bgDad, 0.33, 0xFFFFFFFF, 0xFF555555, {ease: FlxEase.quadOut}); FlxTween.color(pinkBack, 0.33, 0xFFFFD0D5, 0xFF171831, {ease: FlxEase.quadOut}); @@ -1947,6 +1949,7 @@ class FreeplayState extends MusicBeatSubState startingVolume: 0.0, overrideExisting: true, restartTrack: false, + mapTimeChanges: false, // The music metadata is not alongside the audio file so this won't work. pathsFunction: INST, suffix: instSuffix, partialParams: @@ -2097,6 +2100,8 @@ class FreeplaySongData function set_currentDifficulty(value:String):String { + if (currentDifficulty == value) return value; + currentDifficulty = value; updateValues(displayedVariations); return value; @@ -2153,7 +2158,7 @@ class FreeplaySongData { this.albumId = songDifficulty.album; } - + // TODO: This line of code makes me sad, but you can't really fix it without a breaking migration. // `easy`, `erect`, `normal-pico`, etc. var suffixedDifficulty = (songDifficulty.variation != Constants.DEFAULT_VARIATION diff --git a/source/funkin/ui/freeplay/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx index 7708b3bcf..68525a5f7 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -213,6 +213,7 @@ class SongMenuItem extends FlxSpriteGroup 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); @@ -516,6 +517,9 @@ class SongMenuItem extends FlxSpriteGroup updateDifficultyRating(songData?.difficultyRating ?? 0); updateScoringRank(songData?.scoringRank); newText.visible = songData?.isNew; + favIcon.animation.curAnim.curFrame = favIcon.animation.curAnim.numFrames - 1; + favIconBlurred.animation.curAnim.curFrame = favIconBlurred.animation.curAnim.numFrames - 1; + // Update opacity, offsets, etc. updateSelected(); @@ -539,8 +543,6 @@ class SongMenuItem extends FlxSpriteGroup charPath += 'monsterpixel'; case 'mom-car': charPath += 'mommypixel'; - case 'dad': - charPath += 'daddypixel'; case 'darnell-blazin': charPath += 'darnellpixel'; case 'senpai-angry': @@ -555,7 +557,17 @@ class SongMenuItem extends FlxSpriteGroup return; } - pixelIcon.loadGraphic(Paths.image(charPath)); + var isAnimated = openfl.utils.Assets.exists(Paths.file('images/$charPath.xml')); + + if (isAnimated) + { + pixelIcon.frames = Paths.getSparrowAtlas(charPath); + } + else + { + pixelIcon.loadGraphic(Paths.image(charPath)); + } + pixelIcon.scale.x = pixelIcon.scale.y = 2; switch (char) @@ -567,6 +579,22 @@ class SongMenuItem extends FlxSpriteGroup } // pixelIcon.origin.x = capsule.origin.x; // pixelIcon.offset.x -= pixelIcon.origin.x; + + if (isAnimated) + { + pixelIcon.active = true; + + pixelIcon.animation.addByPrefix('idle', 'idle0', 10, true); + pixelIcon.animation.addByPrefix('confirm', 'confirm0', 10, false); + pixelIcon.animation.addByPrefix('confirm-hold', 'confirm-hold0', 10, true); + + pixelIcon.animation.finishCallback = function(name:String):Void { + trace('Finish pixel animation: ${name}'); + if (name == 'confirm') pixelIcon.animation.play('confirm-hold'); + }; + + pixelIcon.animation.play('idle'); + } } var frameInTicker:Float = 0; @@ -707,6 +735,18 @@ class SongMenuItem extends FlxSpriteGroup super.update(elapsed); } + /** + * Play any animations associated with selecting this song. + */ + public function confirm():Void + { + if (songText != null) songText.flickerText(); + if (pixelIcon != null) + { + pixelIcon.animation.play('confirm'); + } + } + public function intendedY(index:Int):Float { return (index * ((height * realScaled) + 10)) + 120; diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index 56ffc9a27..9bf465484 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -156,6 +156,9 @@ class MainMenuState extends MusicBeatState resetCamStuff(); + // reset camera when debug menu is closed + subStateClosed.add(_ -> resetCamStuff(false)); + subStateOpened.add(sub -> { if (Type.getClass(sub) == FreeplayState) { @@ -185,10 +188,11 @@ class MainMenuState extends MusicBeatState }); } - function resetCamStuff():Void + function resetCamStuff(?snap:Bool = true):Void { FlxG.camera.follow(camFollow, null, 0.06); - FlxG.camera.snapToTarget(); + + if (snap) FlxG.camera.snapToTarget(); } function createMenuItem(name:String, atlas:String, callback:Void->Void, fireInstantly:Bool = false):Void @@ -347,8 +351,6 @@ class MainMenuState extends MusicBeatState persistentUpdate = false; FlxG.state.openSubState(new DebugMenuSubState()); - // reset camera when debug menu is closed - subStateClosed.addOnce(_ -> resetCamStuff()); } #end diff --git a/source/funkin/ui/story/LevelTitle.hx b/source/funkin/ui/story/LevelTitle.hx index e6f989016..2be2da154 100644 --- a/source/funkin/ui/story/LevelTitle.hx +++ b/source/funkin/ui/story/LevelTitle.hx @@ -13,13 +13,10 @@ class LevelTitle extends FlxSpriteGroup public final level:Level; public var targetY:Float; - public var isFlashing:Bool = false; var title:FlxSprite; var lock:FlxSprite; - var flashingInt:Int = 0; - public function new(x:Int, y:Int, level:Level) { super(x, y); @@ -46,20 +43,23 @@ class LevelTitle extends FlxSpriteGroup } } - // if it runs at 60fps, fake framerate will be 6 - // if it runs at 144 fps, fake framerate will be like 14, and will update the graphic every 0.016666 * 3 seconds still??? - // so it runs basically every so many seconds, not dependant on framerate?? - // I'm still learning how math works thanks whoever is reading this lol - var fakeFramerate:Int = Math.round((1 / FlxG.elapsed) / 10); + public var isFlashing:Bool = false; + var flashTick:Float = 0; + final flashFramerate:Float = 20; public override function update(elapsed:Float):Void { this.y = MathUtil.coolLerp(y, targetY, 0.17); - if (isFlashing) flashingInt += 1; - if (flashingInt % fakeFramerate >= Math.floor(fakeFramerate / 2)) title.color = 0xFF33ffff; - else - title.color = FlxColor.WHITE; + if (isFlashing) + { + flashTick += elapsed; + if (flashTick >= 1 / flashFramerate) + { + flashTick %= 1 / flashFramerate; + title.color = (title.color == FlxColor.WHITE) ? 0xFF33ffff : FlxColor.WHITE; + } + } } public function showLock():Void diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx index 06a83ab4d..7707850ce 100644 --- a/source/funkin/ui/story/StoryMenuState.hx +++ b/source/funkin/ui/story/StoryMenuState.hx @@ -113,7 +113,7 @@ class StoryMenuState extends MusicBeatState { super(); - if (stickers != null) + if (stickers?.members != null) { stickerSubState = stickers; } diff --git a/source/funkin/ui/transition/LoadingState.hx b/source/funkin/ui/transition/LoadingState.hx index bc26ad97a..0f2ce1076 100644 --- a/source/funkin/ui/transition/LoadingState.hx +++ b/source/funkin/ui/transition/LoadingState.hx @@ -346,7 +346,7 @@ class LoadingState extends MusicBeatSubState return 'Done precaching ${path}'; }, true); - trace("Queued ${path} for precaching"); + trace('Queued ${path} for precaching'); // FunkinSprite.cacheTexture(path); } diff --git a/source/funkin/util/logging/AnsiTrace.hx b/source/funkin/util/logging/AnsiTrace.hx index 9fdc19e1b..2c18d494d 100644 --- a/source/funkin/util/logging/AnsiTrace.hx +++ b/source/funkin/util/logging/AnsiTrace.hx @@ -51,7 +51,7 @@ class AnsiTrace public static function traceBF() { - #if sys + #if (sys && debug) if (colorSupported) { for (line in ansiBF) From c9c94a5fda5378effd0cf060696882a75d016b53 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 4 Jul 2024 15:55:19 -0400 Subject: [PATCH 397/870] note fadein fix --- .gitignore | 1 + source/funkin/play/PlayState.hx | 7 ++----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 143cf08c9..5c8cb5f55 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ node_modules/ package.json package-lock.json .aider.* +.aider* diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index de8492882..5ede97e6c 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1795,11 +1795,8 @@ class PlayState extends MusicBeatSubState opponentStrumline.zIndex = 1000; opponentStrumline.cameras = [camHUD]; - if (!PlayStatePlaylist.isStoryMode) - { - playerStrumline.fadeInArrows(); - opponentStrumline.fadeInArrows(); - } + playerStrumline.fadeInArrows(); + opponentStrumline.fadeInArrows(); } /** From a9aa142b8de9113961854842a45f3a8767fc29ea Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sun, 7 Jul 2024 04:10:37 -0400 Subject: [PATCH 398/870] Added more pico results + charts --- Project.xml | 2 +- assets | 2 +- source/funkin/InitState.hx | 7 ++++++- .../funkin/data/freeplay/player/PlayerData.hx | 4 ++++ .../graphics/adobeanimate/FlxAtlasSprite.hx | 4 ++++ source/funkin/play/ResultState.hx | 18 +++++++++++++++--- 6 files changed, 31 insertions(+), 6 deletions(-) diff --git a/Project.xml b/Project.xml index fae9c768b..8eb62bb1d 100644 --- a/Project.xml +++ b/Project.xml @@ -2,7 +2,7 @@ - + diff --git a/assets b/assets index 859186eea..94db49cd4 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 859186eea46c8b70deb3530c25304ba875b7b34a +Subproject commit 94db49cd4a2acacd5089628619104830a4f1ffce diff --git a/source/funkin/InitState.hx b/source/funkin/InitState.hx index 254165a95..6e370b5ff 100644 --- a/source/funkin/InitState.hx +++ b/source/funkin/InitState.hx @@ -239,8 +239,13 @@ class InitState extends FlxState combo: 69, maxCombo: 69, totalNotesHit: 140, - totalNotes: 240 // 0, + totalNotes: 190 } + // 2000 = loss + // 240 = good + // 230 = great + // 210 = excellent + // 190 = perfect }, })); #elseif ANIMDEBUG diff --git a/source/funkin/data/freeplay/player/PlayerData.hx b/source/funkin/data/freeplay/player/PlayerData.hx index caae2adc6..f6c085018 100644 --- a/source/funkin/data/freeplay/player/PlayerData.hx +++ b/source/funkin/data/freeplay/player/PlayerData.hx @@ -223,6 +223,10 @@ typedef PlayerResultsAnimationData = @:default('') var startFrameLabel:Null; + @:optional + @:default(true) + var looped:Bool; + @:optional var loopFrame:Null; diff --git a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx index 1684e8b33..eb331b9c3 100644 --- a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx +++ b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx @@ -158,6 +158,10 @@ class FlxAtlasSprite extends FlxAnimate } }; + anim.onComplete = function() { + onAnimationFinish.dispatch(id); + }; + // Prevent other animations from playing if `ignoreOther` is true. if (ignoreOther) canPlayOtherAnims = false; diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index 042ab655d..c2d9d42b3 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -61,7 +61,8 @@ class ResultState extends MusicBeatSubState var characterAtlasAnimations:Array< { sprite:FlxAtlasSprite, - delay:Float + delay:Float, + forceLoop:Bool }> = []; var characterSparrowAnimations:Array< { @@ -185,7 +186,17 @@ class ResultState extends MusicBeatSubState animation.scale.set(animData.scale ?? 1.0, animData.scale ?? 1.0); - if (animData.loopFrameLabel != null) + if (!(animData.looped ?? true)) + { + // Animation is not looped. + animation.onAnimationFinish.add((_name:String) -> { + if (animation != null) + { + animation.anim.pause(); + } + }); + } + else if (animData.loopFrameLabel != null) { animation.onAnimationFinish.add((_name:String) -> { if (animation != null) @@ -211,7 +222,8 @@ class ResultState extends MusicBeatSubState characterAtlasAnimations.push( { sprite: animation, - delay: animData.delay ?? 0.0 + delay: animData.delay ?? 0.0, + forceLoop: (animData.loopFrame ?? -1) == 0 }); // Add to the scene. add(animation); From f82f0d3b05f7ec03c4d80fe7a8abdf01667c0973 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Mon, 8 Jul 2024 03:17:28 +0200 Subject: [PATCH 399/870] Remove SustainTrail forced alpha --- source/funkin/play/notes/Strumline.hx | 1 - 1 file changed, 1 deletion(-) diff --git a/source/funkin/play/notes/Strumline.hx b/source/funkin/play/notes/Strumline.hx index 0e4b6645f..5784586ec 100644 --- a/source/funkin/play/notes/Strumline.hx +++ b/source/funkin/play/notes/Strumline.hx @@ -598,7 +598,6 @@ 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 d7105e8b8e26e2fe1337c14862f7968f5dcd7893 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 8 Jul 2024 16:22:38 -0400 Subject: [PATCH 400/870] change debug menu and add key for freeplay --- source/funkin/ui/debug/DebugMenuSubState.hx | 2 ++ source/funkin/ui/freeplay/FreeplayState.hx | 5 +++++ source/funkin/ui/mainmenu/MainMenuState.hx | 4 +--- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/source/funkin/ui/debug/DebugMenuSubState.hx b/source/funkin/ui/debug/DebugMenuSubState.hx index 22dc5dba6..590cce88b 100644 --- a/source/funkin/ui/debug/DebugMenuSubState.hx +++ b/source/funkin/ui/debug/DebugMenuSubState.hx @@ -54,7 +54,9 @@ class DebugMenuSubState extends MusicBeatSubState // Create each menu item. // Call onMenuChange when the first item is created to move the camera . + #if CHART_EDITOR_SUPPORTED onMenuChange(createItem("CHART EDITOR", openChartEditor)); + #end // createItem("Input Offset Testing", openInputOffsetTesting); createItem("CHARACTER SELECT", openCharSelect, true); createItem("ANIMATION EDITOR", openAnimationEditor); diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 3b003cf89..4b0ae7839 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1206,6 +1206,11 @@ class FreeplayState extends MusicBeatSubState // } #end + if (FlxG.keys.justPressed.TAB) + { + FlxG.switchState(new funkin.ui.charSelect.CharSelectSubState()); + } + if (controls.FREEPLAY_FAVORITE && !busy) { var targetSong = grpCapsules.members[curSelected]?.songData; diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index 2eba406d9..eab116c86 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -341,17 +341,15 @@ class MainMenuState extends MusicBeatState } } + #if (debug || FORCE_DEBUG_VERSION) // Open the debug menu, defaults to ` / ~ - #if CHART_EDITOR_SUPPORTED if (controls.DEBUG_MENU) { persistentUpdate = false; FlxG.state.openSubState(new DebugMenuSubState()); } - #end - #if (debug || FORCE_DEBUG_VERSION) if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.W) { // Give the user a score of 1 point on Weekend 1 story mode. From 57c995e19d0024335c2244c5868e355847e70872 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 8 Jul 2024 16:30:17 -0400 Subject: [PATCH 401/870] char select screen controls stuff --- source/funkin/ui/charSelect/CharSelectSubState.hx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index d73366390..14a5b36e0 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -1,5 +1,6 @@ package funkin.ui.charSelect; +import funkin.ui.freeplay.FreeplayState; import flixel.text.FlxText; import funkin.ui.PixelatedIcon; import flixel.system.debug.watch.Tracker.TrackerProfile; @@ -451,7 +452,12 @@ class CharSelectSubState extends MusicBeatSubState pressedSelect = true; selectTimer.start(1.5, (_) -> { pressedSelect = false; - close(); + FlxG.switchState(FreeplayState.build( + { + { + character: curChar + } + })); }); } From 3a37b79a55e0ddb940f18988372b77e11a03a010 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 8 Jul 2024 16:40:10 -0400 Subject: [PATCH 402/870] add TAB to controls stuff --- source/funkin/input/Controls.hx | 16 ++++++++++++++++ source/funkin/ui/freeplay/FreeplayState.hx | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/source/funkin/input/Controls.hx b/source/funkin/input/Controls.hx index f6c881f6d..6b8e9aa3e 100644 --- a/source/funkin/input/Controls.hx +++ b/source/funkin/input/Controls.hx @@ -64,6 +64,7 @@ class Controls extends FlxActionSet var _freeplay_favorite = new FunkinAction(Action.FREEPLAY_FAVORITE); var _freeplay_left = new FunkinAction(Action.FREEPLAY_LEFT); var _freeplay_right = new FunkinAction(Action.FREEPLAY_RIGHT); + var _freeplay_char_select = new FunkinAction(Action.FREEPLAY_CHAR_SELECT); var _cutscene_advance = new FunkinAction(Action.CUTSCENE_ADVANCE); var _debug_menu = new FunkinAction(Action.DEBUG_MENU); var _debug_chart = new FunkinAction(Action.DEBUG_CHART); @@ -262,6 +263,11 @@ class Controls extends FlxActionSet inline function get_FREEPLAY_RIGHT() return _freeplay_right.check(); + public var FREEPLAY_CHAR_SELECT(get, never):Bool; + + inline function get_FREEPLAY_CHAR_SELECT() + return _freeplay_char_select.check(); + public var CUTSCENE_ADVANCE(get, never):Bool; inline function get_CUTSCENE_ADVANCE() @@ -318,6 +324,7 @@ class Controls extends FlxActionSet add(_freeplay_favorite); add(_freeplay_left); add(_freeplay_right); + add(_freeplay_char_select); add(_cutscene_advance); add(_debug_menu); add(_debug_chart); @@ -424,6 +431,7 @@ class Controls extends FlxActionSet case FREEPLAY_FAVORITE: _freeplay_favorite; case FREEPLAY_LEFT: _freeplay_left; case FREEPLAY_RIGHT: _freeplay_right; + case FREEPLAY_CHAR_SELECT: _freeplay_char_select; case CUTSCENE_ADVANCE: _cutscene_advance; case DEBUG_MENU: _debug_menu; case DEBUG_CHART: _debug_chart; @@ -500,6 +508,8 @@ class Controls extends FlxActionSet func(_freeplay_left, JUST_PRESSED); case FREEPLAY_RIGHT: func(_freeplay_right, JUST_PRESSED); + case FREEPLAY_CHAR_SELECT: + func(_freeplay_char_select, JUST_PRESSED); case CUTSCENE_ADVANCE: func(_cutscene_advance, JUST_PRESSED); case DEBUG_MENU: @@ -721,6 +731,7 @@ class Controls extends FlxActionSet bindKeys(Control.FREEPLAY_FAVORITE, getDefaultKeybinds(scheme, Control.FREEPLAY_FAVORITE)); bindKeys(Control.FREEPLAY_LEFT, getDefaultKeybinds(scheme, Control.FREEPLAY_LEFT)); bindKeys(Control.FREEPLAY_RIGHT, getDefaultKeybinds(scheme, Control.FREEPLAY_RIGHT)); + bindKeys(Control.FREEPLAY_CHAR_SELECT, getDefaultKeybinds(scheme, Control.FREEPLAY_CHAR_SELECT)); bindKeys(Control.CUTSCENE_ADVANCE, getDefaultKeybinds(scheme, Control.CUTSCENE_ADVANCE)); bindKeys(Control.DEBUG_MENU, getDefaultKeybinds(scheme, Control.DEBUG_MENU)); bindKeys(Control.DEBUG_CHART, getDefaultKeybinds(scheme, Control.DEBUG_CHART)); @@ -756,6 +767,7 @@ class Controls extends FlxActionSet case Control.FREEPLAY_FAVORITE: return [F]; // Favorite a song on the menu case Control.FREEPLAY_LEFT: return [Q]; // Switch tabs on the menu case Control.FREEPLAY_RIGHT: return [E]; // Switch tabs on the menu + case Control.FREEPLAY_CHAR_SELECT: return [TAB]; case Control.CUTSCENE_ADVANCE: return [Z, ENTER]; case Control.DEBUG_MENU: return [GRAVEACCENT]; case Control.DEBUG_CHART: return []; @@ -784,6 +796,7 @@ class Controls extends FlxActionSet case Control.FREEPLAY_FAVORITE: return [F]; // Favorite a song on the menu case Control.FREEPLAY_LEFT: return [Q]; // Switch tabs on the menu case Control.FREEPLAY_RIGHT: return [E]; // Switch tabs on the menu + case Control.FREEPLAY_CHAR_SELECT: return [TAB]; case Control.CUTSCENE_ADVANCE: return [G, Z]; case Control.DEBUG_MENU: return [GRAVEACCENT]; case Control.DEBUG_CHART: return []; @@ -812,6 +825,7 @@ class Controls extends FlxActionSet case Control.FREEPLAY_FAVORITE: return []; case Control.FREEPLAY_LEFT: return []; case Control.FREEPLAY_RIGHT: return []; + case Control.FREEPLAY_CHAR_SELECT: return []; case Control.CUTSCENE_ADVANCE: return [ENTER]; case Control.DEBUG_MENU: return []; case Control.DEBUG_CHART: return []; @@ -1548,6 +1562,7 @@ enum Control FREEPLAY_FAVORITE; FREEPLAY_LEFT; FREEPLAY_RIGHT; + FREEPLAY_CHAR_SELECT; // WINDOW WINDOW_SCREENSHOT; WINDOW_FULLSCREEN; @@ -1602,6 +1617,7 @@ enum abstract Action(String) to String from String var FREEPLAY_FAVORITE = "freeplay_favorite"; var FREEPLAY_LEFT = "freeplay_left"; var FREEPLAY_RIGHT = "freeplay_right"; + var FREEPLAY_CHAR_SELECT = "freeplay_char_select"; // VOLUME var VOLUME_UP = "volume_up"; var VOLUME_DOWN = "volume_down"; diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index eef5d9e68..dc42bd651 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1232,7 +1232,7 @@ class FreeplayState extends MusicBeatSubState // } #end - if (FlxG.keys.justPressed.TAB) + if (controls.FREEPLAY_CHAR_SELECT && !busy) { FlxG.switchState(new funkin.ui.charSelect.CharSelectSubState()); } From 96aa0b3a59399efe3e298c3879d2f61d19be52a3 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 8 Jul 2024 21:51:27 -0400 Subject: [PATCH 403/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 94db49cd4..1b6502c3a 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 94db49cd4a2acacd5089628619104830a4f1ffce +Subproject commit 1b6502c3a4200cedb1195f926b09307722cbd347 From b4acfe8d954b8bc96c51702c860c95e72ea84482 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 8 Jul 2024 22:10:40 -0400 Subject: [PATCH 404/870] assets submod --- art | 2 +- assets | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/art b/art index 55c1b5682..faeba700c 160000 --- a/art +++ b/art @@ -1 +1 @@ -Subproject commit 55c1b56823d4d7a74397bab9aeab30f15126499c +Subproject commit faeba700c5526bd4fd57ccc927d875c82b9d3553 diff --git a/assets b/assets index fe7960dac..4e409880a 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit fe7960dac67af26572376ded5df8eb4527e22095 +Subproject commit 4e409880a2e25357ba755e816e237519d6d6adfb From ae03537676f5a1b4ba19eb15ed7a420353a6c2eb Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 9 Jul 2024 03:20:51 -0400 Subject: [PATCH 405/870] Fix an issue with Pico's death animation spritesheet --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 4e409880a..1c9c0986e 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 4e409880a2e25357ba755e816e237519d6d6adfb +Subproject commit 1c9c0986e5eb0a7b5faa81ecacc158d20429720d From cb4620d33aaeb5b1eb88f0f9d1a29d1fe5c8c662 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 9 Jul 2024 04:20:42 -0400 Subject: [PATCH 406/870] Fix background props not bopping on Week 5 --- source/funkin/play/stage/Bopper.hx | 2 +- source/funkin/play/stage/Stage.hx | 147 +++++++++++++++++++++++++---- 2 files changed, 130 insertions(+), 19 deletions(-) diff --git a/source/funkin/play/stage/Bopper.hx b/source/funkin/play/stage/Bopper.hx index 0061e85fb..7665d0de0 100644 --- a/source/funkin/play/stage/Bopper.hx +++ b/source/funkin/play/stage/Bopper.hx @@ -177,7 +177,7 @@ class Bopper extends StageProp implements IPlayStateScriptedClass */ public function onStepHit(event:SongTimeScriptEvent) { - if (danceEvery > 0) trace('step hit(${danceEvery}): ${event.step % (danceEvery * Constants.STEPS_PER_BEAT)} == 0?'); + if (danceEvery > 0) trace('step hit(${danceEvery}, ${shouldBop}): ${event.step % (danceEvery * Constants.STEPS_PER_BEAT)} == 0?'); if (danceEvery > 0 && (event.step % (danceEvery * Constants.STEPS_PER_BEAT)) == 0) { trace('dance onStepHit!'); diff --git a/source/funkin/play/stage/Stage.hx b/source/funkin/play/stage/Stage.hx index f4e22e380..85b0056ca 100644 --- a/source/funkin/play/stage/Stage.hx +++ b/source/funkin/play/stage/Stage.hx @@ -769,7 +769,16 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements * A function that gets called once per step in the song. * @param curStep The current step number. */ - public function onStepHit(event:SongTimeScriptEvent):Void {} + public function onStepHit(event:SongTimeScriptEvent):Void + { + // Override me in your scripted stage to perform custom behavior! + // Make sure to call super.onStepHit(event) if you want to keep the boppers dancing. + + for (bopper in boppers) + { + ScriptEventDispatcher.callEvent(bopper, event); + } + } /** * A function that gets called once per beat in the song (once every four steps). @@ -786,7 +795,13 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements } } - public function onUpdate(event:UpdateScriptEvent) {} + public function onUpdate(event:UpdateScriptEvent) + { + for (bopper in boppers) + { + ScriptEventDispatcher.callEvent(bopper, event); + } + } public override function kill() { @@ -866,35 +881,131 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements return StageRegistry.instance.parseEntryDataWithMigration(id, StageRegistry.instance.fetchEntryVersion(id)); } - public function onScriptEvent(event:ScriptEvent) {} + public function onScriptEvent(event:ScriptEvent) + { + for (bopper in boppers) + { + ScriptEventDispatcher.callEvent(bopper, event); + } + } - public function onPause(event:PauseScriptEvent) {} + public function onPause(event:PauseScriptEvent) + { + for (bopper in boppers) + { + ScriptEventDispatcher.callEvent(bopper, event); + } + } - public function onResume(event:ScriptEvent) {} + public function onResume(event:ScriptEvent) + { + for (bopper in boppers) + { + ScriptEventDispatcher.callEvent(bopper, event); + } + } - public function onSongStart(event:ScriptEvent) {} + public function onSongStart(event:ScriptEvent) + { + for (bopper in boppers) + { + ScriptEventDispatcher.callEvent(bopper, event); + } + } - public function onSongEnd(event:ScriptEvent) {} + public function onSongEnd(event:ScriptEvent) + { + for (bopper in boppers) + { + ScriptEventDispatcher.callEvent(bopper, event); + } + } - public function onGameOver(event:ScriptEvent) {} + public function onGameOver(event:ScriptEvent) + { + for (bopper in boppers) + { + ScriptEventDispatcher.callEvent(bopper, event); + } + } - public function onCountdownStart(event:CountdownScriptEvent) {} + public function onCountdownStart(event:CountdownScriptEvent) + { + for (bopper in boppers) + { + ScriptEventDispatcher.callEvent(bopper, event); + } + } - public function onCountdownStep(event:CountdownScriptEvent) {} + public function onCountdownStep(event:CountdownScriptEvent) + { + for (bopper in boppers) + { + ScriptEventDispatcher.callEvent(bopper, event); + } + } - public function onCountdownEnd(event:CountdownScriptEvent) {} + public function onCountdownEnd(event:CountdownScriptEvent) + { + for (bopper in boppers) + { + ScriptEventDispatcher.callEvent(bopper, event); + } + } - public function onNoteIncoming(event:NoteScriptEvent) {} + public function onNoteIncoming(event:NoteScriptEvent) + { + for (bopper in boppers) + { + ScriptEventDispatcher.callEvent(bopper, event); + } + } - public function onNoteHit(event:HitNoteScriptEvent) {} + public function onNoteHit(event:HitNoteScriptEvent) + { + for (bopper in boppers) + { + ScriptEventDispatcher.callEvent(bopper, event); + } + } - public function onNoteMiss(event:NoteScriptEvent) {} + public function onNoteMiss(event:NoteScriptEvent) + { + for (bopper in boppers) + { + ScriptEventDispatcher.callEvent(bopper, event); + } + } - public function onSongEvent(event:SongEventScriptEvent) {} + public function onSongEvent(event:SongEventScriptEvent) + { + for (bopper in boppers) + { + ScriptEventDispatcher.callEvent(bopper, event); + } + } - public function onNoteGhostMiss(event:GhostMissNoteScriptEvent) {} + public function onNoteGhostMiss(event:GhostMissNoteScriptEvent) + { + for (bopper in boppers) + { + ScriptEventDispatcher.callEvent(bopper, event); + } + } - public function onSongLoaded(event:SongLoadScriptEvent) {} + public function onSongLoaded(event:SongLoadScriptEvent) + { + for (bopper in boppers) + { + ScriptEventDispatcher.callEvent(bopper, event); + } + } - public function onSongRetry(event:ScriptEvent) {} + public function onSongRetry(event:ScriptEvent) + { + for (bopper in boppers) + { + ScriptEventDispatcher.callEvent(bopper, event); + } + } } From 98ed4bd843cd96162aa96d943c0779c3abd02ed8 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 9 Jul 2024 04:21:14 -0400 Subject: [PATCH 407/870] Implement Nene/GFXmas combo anims --- assets | 2 +- source/funkin/play/character/BaseCharacter.hx | 1 - source/funkin/play/stage/Bopper.hx | 2 -- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/assets b/assets index 4e409880a..240d0ff1d 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 4e409880a2e25357ba755e816e237519d6d6adfb +Subproject commit 240d0ff1dafd616551e6b6a2b048b7b6f602ac75 diff --git a/source/funkin/play/character/BaseCharacter.hx b/source/funkin/play/character/BaseCharacter.hx index c228d803a..0dab2101a 100644 --- a/source/funkin/play/character/BaseCharacter.hx +++ b/source/funkin/play/character/BaseCharacter.hx @@ -461,7 +461,6 @@ class BaseCharacter extends Bopper if (!currentAnimation.startsWith('dance') && !currentAnimation.startsWith('idle') && !isAnimationFinished()) return; } - trace('${characterId}: Actually dancing'); // Otherwise, fallback to the super dance() method, which handles playing the idle animation. super.dance(); } diff --git a/source/funkin/play/stage/Bopper.hx b/source/funkin/play/stage/Bopper.hx index 7665d0de0..87151de21 100644 --- a/source/funkin/play/stage/Bopper.hx +++ b/source/funkin/play/stage/Bopper.hx @@ -177,10 +177,8 @@ class Bopper extends StageProp implements IPlayStateScriptedClass */ public function onStepHit(event:SongTimeScriptEvent) { - if (danceEvery > 0) trace('step hit(${danceEvery}, ${shouldBop}): ${event.step % (danceEvery * Constants.STEPS_PER_BEAT)} == 0?'); if (danceEvery > 0 && (event.step % (danceEvery * Constants.STEPS_PER_BEAT)) == 0) { - trace('dance onStepHit!'); dance(shouldBop); } } From 39a774709e7a7ba9776e334837e58e2dde6ee0bd Mon Sep 17 00:00:00 2001 From: Hundrec Date: Tue, 9 Jul 2024 02:10:55 -0700 Subject: [PATCH 408/870] [DOCS] Add common troubleshooting steps to compiling guide Makes compiling easier for everyone --- docs/COMPILING.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index cc90bd348..db32defe5 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -8,10 +8,10 @@ 1. Run `git clone https://github.com/FunkinCrew/funkin.git` to clone the base repository. 2. Run `git submodule update --init --recursive` to download the game's assets. - NOTE: By performing this operation, you are downloading Content which is proprietary and protected by national and international copyright and trademark laws. See [the LICENSE.md file for the Funkin.assets](https://github.com/FunkinCrew/funkin.assets/blob/main/LICENSE.md) repo for more information. -2. Run `haxelib --global install hmm` and then `haxelib --global run hmm setup` to install hmm.json -3. Run `hmm install` to install all haxelibs of the current branch -4. Run `haxelib run lime setup` to set up lime -5. Platform setup +3. Run `haxelib --global install hmm` and then `haxelib --global run hmm setup` to install hmm.json +4. Run `hmm install` to install all haxelibs of the current branch +5. Run `haxelib run lime setup` to set up lime +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 @@ -19,10 +19,12 @@ - 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). -# Troubleshooting +# Troubleshooting +## GO THROUGH THESE STEPS BEFORE OPENING ISSUES ON GITHUB! - 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`. - +- Check that your `assets` folder is not empty! If it is, go back to **Step 2** and follow the guide from there. +- The compilation process often fails due to having the wrong versions of the required libraries. Many errors can be resolved by deleting the `.haxelib` folder and rerunning the commands listed in **Step 3** and onwards. From 717894300d6041e1a24b10682122d9feffb7d18a Mon Sep 17 00:00:00 2001 From: AppleHair Date: Tue, 9 Jul 2024 19:59:31 +0300 Subject: [PATCH 409/870] [BUGFIX] Fixed `cancelMenu` sound not playing after switching state. --- source/funkin/ui/mainmenu/MainMenuState.hx | 2 +- source/funkin/ui/options/OptionsState.hx | 2 +- source/funkin/ui/story/StoryMenuState.hx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index d09536eea..a2bdd23f8 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -409,8 +409,8 @@ class MainMenuState extends MusicBeatState if (controls.BACK && menuItems.enabled && !menuItems.busy) { - FunkinSound.playOnce(Paths.sound('cancelMenu')); FlxG.switchState(() -> new TitleState()); + FunkinSound.playOnce(Paths.sound('cancelMenu')); } } } diff --git a/source/funkin/ui/options/OptionsState.hx b/source/funkin/ui/options/OptionsState.hx index 40308d96b..a2301e6a3 100644 --- a/source/funkin/ui/options/OptionsState.hx +++ b/source/funkin/ui/options/OptionsState.hx @@ -145,8 +145,8 @@ class Page extends FlxGroup { if (canExit && controls.BACK) { - FunkinSound.playOnce(Paths.sound('cancelMenu')); exit(); + FunkinSound.playOnce(Paths.sound('cancelMenu')); } } diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx index 06a83ab4d..04d021256 100644 --- a/source/funkin/ui/story/StoryMenuState.hx +++ b/source/funkin/ui/story/StoryMenuState.hx @@ -374,9 +374,9 @@ class StoryMenuState extends MusicBeatState if (controls.BACK && !exitingMenu && !selectedLevel) { - FunkinSound.playOnce(Paths.sound('cancelMenu')); exitingMenu = true; FlxG.switchState(() -> new MainMenuState()); + FunkinSound.playOnce(Paths.sound('cancelMenu')); } } From 2d1d6eb19ec5afa157631be9802644b3baa8c145 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Tue, 9 Jul 2024 12:54:29 -0700 Subject: [PATCH 410/870] Add cd step for improved clarity --- docs/COMPILING.md | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index db32defe5..5784d9c7e 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -5,13 +5,15 @@ - Download Git from [git-scm.com](https://www.git-scm.com) - Do NOT download the repository using the Download ZIP button on GitHub or you may run into errors! - Instead, open a command prompt and do the following steps... -1. Run `git clone https://github.com/FunkinCrew/funkin.git` to clone the base repository. -2. Run `git submodule update --init --recursive` to download the game's assets. +1. Run `cd the/directory/you/want/the/source/code/in` to specify which folder the command prompt is working in. + - For example, `cd C:\Users\YOURNAME\Documents` would instruct the command prompt to perform the next steps in your Documents folder. +2. Run `git clone https://github.com/FunkinCrew/funkin.git` to clone the base repository. +3. Run `git submodule update --init --recursive` to download the game's assets. - NOTE: By performing this operation, you are downloading Content which is proprietary and protected by national and international copyright and trademark laws. See [the LICENSE.md file for the Funkin.assets](https://github.com/FunkinCrew/funkin.assets/blob/main/LICENSE.md) repo for more information. -3. Run `haxelib --global install hmm` and then `haxelib --global run hmm setup` to install hmm.json -4. Run `hmm install` to install all haxelibs of the current branch -5. Run `haxelib run lime setup` to set up lime -6. Platform setup +4. Run `haxelib --global install hmm` and then `haxelib --global run hmm setup` to install hmm.json +5. Run `hmm install` to install all haxelibs of the current branch +6. Run `haxelib run lime setup` to set up lime +7. 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 @@ -19,12 +21,12 @@ - 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 -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). +8. If you are targeting for native, you may need to run `lime rebuild PLATFORM` and `lime rebuild PLATFORM -debug` +9. `lime test PLATFORM` ! Add `-debug` to enable several debug features such as time travel (`PgUp`/`PgDn` in Play State). -# Troubleshooting -## GO THROUGH THESE STEPS BEFORE OPENING ISSUES ON GITHUB! +# Troubleshooting - GO THROUGH THESE STEPS BEFORE OPENING ISSUES ON GITHUB! - 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`. -- Check that your `assets` folder is not empty! If it is, go back to **Step 2** and follow the guide from there. -- The compilation process often fails due to having the wrong versions of the required libraries. Many errors can be resolved by deleting the `.haxelib` folder and rerunning the commands listed in **Step 3** and onwards. +- Make sure your game directory has an `assets` folder! If it's missing, make sure you're in the right directory by running **Step 1**. +- Check that your `assets` folder is not empty! If it is, go back to **Step 3** and follow the guide from there. +- The compilation process often fails due to having the wrong versions of the required libraries. Many errors can be resolved by deleting the `.haxelib` folder and rerunning the commands listed in **Step 4** and onwards. From ff770d6948caad68086caf597f4cc84dea3c5a91 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Tue, 9 Jul 2024 12:55:04 -0700 Subject: [PATCH 411/870] Wrong slashes lol --- docs/COMPILING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index 5784d9c7e..5a0c4dbd7 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -5,7 +5,7 @@ - Download Git from [git-scm.com](https://www.git-scm.com) - Do NOT download the repository using the Download ZIP button on GitHub or you may run into errors! - Instead, open a command prompt and do the following steps... -1. Run `cd the/directory/you/want/the/source/code/in` to specify which folder the command prompt is working in. +1. Run `cd the\directory\you\want\the\source\code\in` to specify which folder the command prompt is working in. - For example, `cd C:\Users\YOURNAME\Documents` would instruct the command prompt to perform the next steps in your Documents folder. 2. Run `git clone https://github.com/FunkinCrew/funkin.git` to clone the base repository. 3. Run `git submodule update --init --recursive` to download the game's assets. From 481f7ab61a6e206bc3aadfd2754cdc299116c087 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Wed, 10 Jul 2024 00:23:06 +0200 Subject: [PATCH 412/870] Fix F5 chart not reloading --- source/funkin/play/PlayState.hx | 59 ++----------------- source/funkin/ui/MusicBeatState.hx | 7 +-- source/funkin/ui/MusicBeatSubState.hx | 5 +- .../util/plugins/ReloadAssetsDebugPlugin.hx | 14 ++++- 4 files changed, 17 insertions(+), 68 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index f55cef388..8b6753035 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1335,64 +1335,13 @@ class PlayState extends MusicBeatSubState #end /** - * Removes any references to the current stage, then clears the stage cache, - * then reloads all the stages. - * - * This is useful for when you want to edit a stage without reloading the whole game. - * Reloading works on both the JSON and the HXC, if applicable. - * * Call this by pressing F5 on a debug build. */ - override function debug_refreshModules():Void + override function reloadAssets():Void { - // Prevent further gameplay updates, which will try to reference dead objects. - criticalFailure = true; - - // Remove the current stage. If the stage gets deleted while it's still in use, - // it'll probably crash the game or something. - if (this.currentStage != null) - { - remove(currentStage); - var event:ScriptEvent = new ScriptEvent(DESTROY, false); - ScriptEventDispatcher.callEvent(currentStage, event); - currentStage = null; - } - - if (!overrideMusic) - { - // Stop the instrumental. - if (FlxG.sound.music != null) - { - FlxG.sound.music.destroy(); - FlxG.sound.music = null; - } - - // Stop the vocals. - if (vocals != null && vocals.exists) - { - vocals.destroy(); - vocals = null; - } - } - else - { - // Stop the instrumental. - if (FlxG.sound.music != null) - { - FlxG.sound.music.stop(); - } - - // Stop the vocals. - if (vocals != null && vocals.exists) - { - vocals.stop(); - } - } - - super.debug_refreshModules(); - - var event:ScriptEvent = new ScriptEvent(CREATE, false); - ScriptEventDispatcher.callEvent(currentSong, event); + funkin.modding.PolymodHandler.forceReloadAssets(); + lastParams.targetSong = SongRegistry.instance.fetchEntry(currentSong.id); + LoadingState.loadPlayState(lastParams); } override function stepHit():Bool diff --git a/source/funkin/ui/MusicBeatState.hx b/source/funkin/ui/MusicBeatState.hx index 92169df75..8668b64c1 100644 --- a/source/funkin/ui/MusicBeatState.hx +++ b/source/funkin/ui/MusicBeatState.hx @@ -78,9 +78,6 @@ class MusicBeatState extends FlxTransitionableState implements IEventHandler { // Emergency exit button. if (FlxG.keys.justPressed.F4) FlxG.switchState(() -> new MainMenuState()); - - // This can now be used in EVERY STATE YAY! - if (FlxG.keys.justPressed.F5) debug_refreshModules(); } override function update(elapsed:Float) @@ -114,12 +111,10 @@ class MusicBeatState extends FlxTransitionableState implements IEventHandler ModuleHandler.callEvent(event); } - function debug_refreshModules() + function reloadAssets() { PolymodHandler.forceReloadAssets(); - this.destroy(); - // Create a new instance of the current state, so old data is cleared. FlxG.resetState(); } diff --git a/source/funkin/ui/MusicBeatSubState.hx b/source/funkin/ui/MusicBeatSubState.hx index 9035d12ff..5c40b37bc 100644 --- a/source/funkin/ui/MusicBeatSubState.hx +++ b/source/funkin/ui/MusicBeatSubState.hx @@ -72,9 +72,6 @@ class MusicBeatSubState extends FlxSubState implements IEventHandler // Emergency exit button. if (FlxG.keys.justPressed.F4) FlxG.switchState(() -> new MainMenuState()); - // This can now be used in EVERY STATE YAY! - if (FlxG.keys.justPressed.F5) debug_refreshModules(); - // Display Conductor info in the watch window. FlxG.watch.addQuick("musicTime", FlxG.sound.music?.time ?? 0.0); Conductor.watchQuick(conductorInUse); @@ -82,7 +79,7 @@ class MusicBeatSubState extends FlxSubState implements IEventHandler dispatchEvent(new UpdateScriptEvent(elapsed)); } - function debug_refreshModules() + function reloadAssets() { PolymodHandler.forceReloadAssets(); diff --git a/source/funkin/util/plugins/ReloadAssetsDebugPlugin.hx b/source/funkin/util/plugins/ReloadAssetsDebugPlugin.hx index f69609531..0e1e238ac 100644 --- a/source/funkin/util/plugins/ReloadAssetsDebugPlugin.hx +++ b/source/funkin/util/plugins/ReloadAssetsDebugPlugin.hx @@ -1,6 +1,9 @@ package funkin.util.plugins; +import flixel.FlxG; import flixel.FlxBasic; +import funkin.ui.MusicBeatState; +import funkin.ui.MusicBeatSubState; /** * A plugin which adds functionality to press `F5` to reload all game assets, then reload the current state. @@ -28,10 +31,15 @@ class ReloadAssetsDebugPlugin extends FlxBasic if (FlxG.keys.justPressed.F5) #end { - funkin.modding.PolymodHandler.forceReloadAssets(); + var state:Dynamic = FlxG.state; + if (state is MusicBeatState || state is MusicBeatSubState) state.reloadAssets(); + else + { + funkin.modding.PolymodHandler.forceReloadAssets(); - // Create a new instance of the current state, so old data is cleared. - FlxG.resetState(); + // Create a new instance of the current state, so old data is cleared. + FlxG.resetState(); + } } } From 6c077cad5f7dce27832f0e38b096a55d987284c2 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Tue, 9 Jul 2024 16:22:43 -0700 Subject: [PATCH 413/870] Add second cd step after cloning --- docs/COMPILING.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index 5a0c4dbd7..1fc0c51c6 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -8,12 +8,13 @@ 1. Run `cd the\directory\you\want\the\source\code\in` to specify which folder the command prompt is working in. - For example, `cd C:\Users\YOURNAME\Documents` would instruct the command prompt to perform the next steps in your Documents folder. 2. Run `git clone https://github.com/FunkinCrew/funkin.git` to clone the base repository. -3. Run `git submodule update --init --recursive` to download the game's assets. +3. Run `cd funkin` to enter the cloned repository's directory. +4. Run `git submodule update --init --recursive` to download the game's assets. - NOTE: By performing this operation, you are downloading Content which is proprietary and protected by national and international copyright and trademark laws. See [the LICENSE.md file for the Funkin.assets](https://github.com/FunkinCrew/funkin.assets/blob/main/LICENSE.md) repo for more information. -4. Run `haxelib --global install hmm` and then `haxelib --global run hmm setup` to install hmm.json -5. Run `hmm install` to install all haxelibs of the current branch -6. Run `haxelib run lime setup` to set up lime -7. Platform setup +5. Run `haxelib --global install hmm` and then `haxelib --global run hmm setup` to install hmm.json +6. Run `hmm install` to install all haxelibs of the current branch +7. Run `haxelib run lime setup` to set up lime +8. 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 @@ -21,12 +22,12 @@ - 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 -8. If you are targeting for native, you may need to run `lime rebuild PLATFORM` and `lime rebuild PLATFORM -debug` -9. `lime test PLATFORM` ! Add `-debug` to enable several debug features such as time travel (`PgUp`/`PgDn` in Play State). +9. If you are targeting for native, you may need to run `lime rebuild PLATFORM` and `lime rebuild PLATFORM -debug` +10. `lime test PLATFORM` ! Add `-debug` to enable several debug features such as time travel (`PgUp`/`PgDn` in Play State). # Troubleshooting - GO THROUGH THESE STEPS BEFORE OPENING ISSUES ON GITHUB! - 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`. -- Make sure your game directory has an `assets` folder! If it's missing, make sure you're in the right directory by running **Step 1**. -- Check that your `assets` folder is not empty! If it is, go back to **Step 3** and follow the guide from there. -- The compilation process often fails due to having the wrong versions of the required libraries. Many errors can be resolved by deleting the `.haxelib` folder and rerunning the commands listed in **Step 4** and onwards. +- Make sure your game directory has an `assets` folder! If it's missing, copy the path to your `funkin` folder and run `cd the\path\you\copied`. Then follow the guide starting from **Step 4**. +- Check that your `assets` folder is not empty! If it is, go back to **Step 4** and follow the guide from there. +- The compilation process often fails due to having the wrong versions of the required libraries. Many errors can be resolved by deleting the `.haxelib` folder and following the guide starting from **Step 5**. From 9ad2bb35f9b7f73b690a08b421fecd6a1eab0a8d Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Wed, 10 Jul 2024 01:26:16 +0200 Subject: [PATCH 414/870] ChartEditor Live Input Code Refactor + 6 key fix --- .../ui/debug/charting/ChartEditorState.hx | 57 ++++++------------- 1 file changed, 18 insertions(+), 39 deletions(-) diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index f72cca77f..5e7493840 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -282,6 +282,21 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState */ public static final WELCOME_MUSIC_FADE_IN_DURATION:Float = 10.0; + /** + * A map of the keys for every live input style. + */ + public static final LIVE_INPUT_KEYS:Map> = [ + NumberKeys => [ + FIVE, SIX, SEVEN, EIGHT, + ONE, TWO, THREE, FOUR + ], + WASDKeys => [ + LEFT, DOWN, UP, RIGHT, + A, S, W, D + ], + None => [] + ]; + /** * INSTANCE DATA */ @@ -5129,46 +5144,10 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState function handlePlayhead():Void { // Place notes at the playhead with the keyboard. - switch (currentLiveInputStyle) + for (note => key in LIVE_INPUT_KEYS[currentLiveInputStyle]) { - case ChartEditorLiveInputStyle.WASDKeys: - if (FlxG.keys.justPressed.A) placeNoteAtPlayhead(4); - if (FlxG.keys.justReleased.A) finishPlaceNoteAtPlayhead(4); - if (FlxG.keys.justPressed.S) placeNoteAtPlayhead(5); - if (FlxG.keys.justReleased.S) finishPlaceNoteAtPlayhead(5); - if (FlxG.keys.justPressed.W) placeNoteAtPlayhead(6); - if (FlxG.keys.justReleased.W) finishPlaceNoteAtPlayhead(6); - if (FlxG.keys.justPressed.D) placeNoteAtPlayhead(7); - if (FlxG.keys.justReleased.D) finishPlaceNoteAtPlayhead(7); - - if (FlxG.keys.justPressed.LEFT) placeNoteAtPlayhead(0); - if (FlxG.keys.justReleased.LEFT) finishPlaceNoteAtPlayhead(0); - if (FlxG.keys.justPressed.DOWN) placeNoteAtPlayhead(1); - if (FlxG.keys.justReleased.DOWN) finishPlaceNoteAtPlayhead(1); - if (FlxG.keys.justPressed.UP) placeNoteAtPlayhead(2); - if (FlxG.keys.justReleased.UP) finishPlaceNoteAtPlayhead(2); - if (FlxG.keys.justPressed.RIGHT) placeNoteAtPlayhead(3); - if (FlxG.keys.justReleased.RIGHT) finishPlaceNoteAtPlayhead(3); - case ChartEditorLiveInputStyle.NumberKeys: - // Flipped because Dad is on the left but represents data 0-3. - if (FlxG.keys.justPressed.ONE) placeNoteAtPlayhead(4); - if (FlxG.keys.justReleased.ONE) finishPlaceNoteAtPlayhead(4); - if (FlxG.keys.justPressed.TWO) placeNoteAtPlayhead(5); - if (FlxG.keys.justReleased.TWO) finishPlaceNoteAtPlayhead(5); - if (FlxG.keys.justPressed.THREE) placeNoteAtPlayhead(6); - if (FlxG.keys.justReleased.THREE) finishPlaceNoteAtPlayhead(6); - if (FlxG.keys.justPressed.FOUR) placeNoteAtPlayhead(7); - if (FlxG.keys.justReleased.FOUR) finishPlaceNoteAtPlayhead(7); - - if (FlxG.keys.justPressed.FIVE) placeNoteAtPlayhead(0); - if (FlxG.keys.justReleased.FIVE) finishPlaceNoteAtPlayhead(0); - if (FlxG.keys.justPressed.SIX) placeNoteAtPlayhead(1); - if (FlxG.keys.justPressed.SEVEN) placeNoteAtPlayhead(2); - if (FlxG.keys.justReleased.SEVEN) finishPlaceNoteAtPlayhead(2); - if (FlxG.keys.justPressed.EIGHT) placeNoteAtPlayhead(3); - if (FlxG.keys.justReleased.EIGHT) finishPlaceNoteAtPlayhead(3); - case ChartEditorLiveInputStyle.None: - // Do nothing. + if (FlxG.keys.checkStatus(key, JUST_PRESSED)) placeNoteAtPlayhead(note) + else if (FlxG.keys.checkStatus(key, JUST_RELEASED)) finishPlaceNoteAtPlayhead(note); } // Place events at playhead. From a93af43d637d15ec55dbd1a541ace8e4e31d81d3 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 9 Jul 2024 19:37:06 -0400 Subject: [PATCH 415/870] Song title fixes. --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 4e409880a..bc0beafa5 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 4e409880a2e25357ba755e816e237519d6d6adfb +Subproject commit bc0beafa58c484fe8d98ddadbbd963a43d895402 From d8572cd323d25044c78ddb8b5c870de63c01b7b1 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 10 Jul 2024 14:23:50 -0400 Subject: [PATCH 416/870] Thank you loggo --- source/funkin/play/PlayState.hx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index a4723611e..ddf100bfc 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -16,6 +16,7 @@ import flixel.tweens.FlxTween; import flixel.ui.FlxBar; import flixel.util.FlxColor; import flixel.util.FlxTimer; +import flixel.util.FlxStringUtil; import funkin.api.newgrounds.NGio; import funkin.audio.FunkinSound; import funkin.audio.VoicesGroup; @@ -2060,7 +2061,9 @@ class PlayState extends MusicBeatSubState } else { - scoreText.text = 'Score:' + songScore; + // TODO: Add an option for this maybe? + var commaSeparated:Bool = true; + scoreText.text = 'Score: ${FlxStringUtil.formatMoney(songScore, false, commaSeparated)}'; } } From 2ae68822415bd1a7309a3e81b69026c4a706ec0b Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 10 Jul 2024 17:25:52 -0400 Subject: [PATCH 417/870] Swappable album art and updated FlxAnimate --- assets | 2 +- hmm.json | 4 +- source/funkin/InitState.hx | 10 +- .../data/freeplay/player/PlayerRegistry.hx | 3 +- .../graphics/adobeanimate/FlxAtlasSprite.hx | 163 ++++++++++++++---- source/funkin/play/ResultState.hx | 14 +- .../play/character/AnimateAtlasCharacter.hx | 14 +- .../funkin/ui/charSelect/CharSelectPlayer.hx | 2 +- .../ui/charSelect/CharSelectSubState.hx | 4 +- source/funkin/ui/freeplay/AlbumRoll.hx | 66 ++++++- source/funkin/ui/freeplay/FreeplayDJ.hx | 37 ++-- source/funkin/ui/freeplay/FreeplayState.hx | 2 +- source/funkin/ui/freeplay/SongMenuItem.hx | 3 +- 13 files changed, 244 insertions(+), 80 deletions(-) diff --git a/assets b/assets index 4e409880a..902b12a0c 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 4e409880a2e25357ba755e816e237519d6d6adfb +Subproject commit 902b12a0cdd9b588cefe573e591530f088a77b4c diff --git a/hmm.json b/hmm.json index 8eaf24212..f1056c32c 100644 --- a/hmm.json +++ b/hmm.json @@ -37,8 +37,8 @@ "name": "flxanimate", "type": "git", "dir": null, - "ref": "17e0d59fdbc2b6283a5c0e4df41f1c7f27b71c49", - "url": "https://github.com/FunkinCrew/flxanimate" + "ref": "768740a56b26aa0c072720e0d1236b94afe68e3e", + "url": "https://github.com/Dot-Stuff/flxanimate" }, { "name": "FlxPartialSound", diff --git a/source/funkin/InitState.hx b/source/funkin/InitState.hx index 6e370b5ff..43ef3c0a5 100644 --- a/source/funkin/InitState.hx +++ b/source/funkin/InitState.hx @@ -241,11 +241,11 @@ class InitState extends FlxState totalNotesHit: 140, totalNotes: 190 } - // 2000 = loss - // 240 = good - // 230 = great - // 210 = excellent - // 190 = perfect + // 2400 total notes = 7% = LOSS + // 240 total notes = 79% = GOOD + // 230 total notes = 82% = GREAT + // 210 total notes = 91% = EXCELLENT + // 190 total notes = PERFECT }, })); #elseif ANIMDEBUG diff --git a/source/funkin/data/freeplay/player/PlayerRegistry.hx b/source/funkin/data/freeplay/player/PlayerRegistry.hx index 4656a1286..be8730ccd 100644 --- a/source/funkin/data/freeplay/player/PlayerRegistry.hx +++ b/source/funkin/data/freeplay/player/PlayerRegistry.hx @@ -58,8 +58,9 @@ class PlayerRegistry extends BaseRegistry * @param characterId The stage character ID. * @return The playable character. */ - public function getCharacterOwnerId(characterId:String):Null + public function getCharacterOwnerId(characterId:Null):Null { + if (characterId == null) return null; return ownedCharacterIds[characterId]; } diff --git a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx index eb331b9c3..049c6e206 100644 --- a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx +++ b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx @@ -4,8 +4,11 @@ import flixel.util.FlxSignal.FlxTypedSignal; import flxanimate.FlxAnimate; import flxanimate.FlxAnimate.Settings; import flxanimate.frames.FlxAnimateFrames; +import flixel.graphics.frames.FlxFrame; +import flixel.system.FlxAssets.FlxGraphicAsset; import openfl.display.BitmapData; import openfl.utils.Assets; +import flixel.math.FlxPoint; /** * A sprite which provides convenience functions for rendering a texture atlas with animations. @@ -25,9 +28,19 @@ class FlxAtlasSprite extends FlxAnimate }; /** - * Signal dispatched when an animation finishes playing. + * Signal dispatched when an animation advances to the next frame. */ - public var onAnimationFinish:FlxTypedSignalVoid> = new FlxTypedSignalVoid>(); + public var onAnimationFrame:FlxTypedSignalInt->Void> = new FlxTypedSignal(); + + /** + * Signal dispatched when a non-looping animation finishes playing. + */ + public var onAnimationComplete:FlxTypedSignalVoid> = new FlxTypedSignal(); + + /** + * Signal dispatched when a looping animation finishes playing + */ + public var onAnimationLoopComplete:FlxTypedSignalVoid> = new FlxTypedSignal(); var currentAnimation:String; @@ -44,17 +57,20 @@ class FlxAtlasSprite extends FlxAnimate super(x, y, path, settings); - if (this.anim.curInstance == null) + if (this.anim.stageInstance == null) { throw 'FlxAtlasSprite not initialized properly. Are you sure the path (${path}) exists?'; } - onAnimationFinish.add(cleanupAnimation); + onAnimationComplete.add(cleanupAnimation); // This defaults the sprite to play the first animation in the atlas, // then pauses it. This ensures symbols are intialized properly. this.anim.play(''); this.anim.pause(); + + this.anim.onComplete.add(_onAnimationComplete); + this.anim.onFrame.add(_onAnimationFrame); } /** @@ -62,9 +78,13 @@ class FlxAtlasSprite extends FlxAnimate */ public function listAnimations():Array { - if (this.anim == null) return []; - return this.anim.getFrameLabels(); - // return [""]; + var mainSymbol = this.anim.symbolDictionary[this.anim.stageInstance.symbol.name]; + if (mainSymbol == null) + { + FlxG.log.error('FlxAtlasSprite does not have its main symbol!'); + return []; + } + return mainSymbol.getFrameLabels().map(keyFrame -> keyFrame.name).filterNull(); } /** @@ -107,12 +127,11 @@ class FlxAtlasSprite extends FlxAnimate * @param restart Whether to restart the animation if it is already playing. * @param ignoreOther Whether to ignore all other animation inputs, until this one is done playing * @param loop Whether to loop the animation + * @param startFrame The frame to start the animation on * NOTE: `loop` and `ignoreOther` are not compatible with each other! */ - public function playAnimation(id:String, restart:Bool = false, ignoreOther:Bool = false, ?loop:Bool = false):Void + public function playAnimation(id:String, restart:Bool = false, ignoreOther:Bool = false, loop:Bool = false, startFrame:Int = 0):Void { - if (loop == null) loop = false; - // Skip if not allowed to play animations. if ((!canPlayOtherAnims && !ignoreOther)) return; @@ -128,7 +147,7 @@ class FlxAtlasSprite extends FlxAnimate else { // Resume animation if it's paused. - anim.play('', false, false); + anim.play('', restart, false, startFrame); } } else @@ -141,31 +160,27 @@ class FlxAtlasSprite extends FlxAnimate } } - anim.callback = function(_, frame:Int) { - var offset = loop ? 0 : -1; - - var frameLabel = anim.getFrameLabel(id); - if (frame == (frameLabel.duration + offset) + frameLabel.index) + anim.onComplete.removeAll(); + anim.onComplete.add(function() { + if (loop) { - if (loop) - { - playAnimation(id, true, false, true); - } - else - { - onAnimationFinish.dispatch(id); - } + onAnimationLoopComplete.dispatch(id); + this.anim.play(id, restart, false, startFrame); + this.currentAnimation = id; } - }; - - anim.onComplete = function() { - onAnimationFinish.dispatch(id); - }; + else + { + onAnimationComplete.dispatch(id); + } + }); // Prevent other animations from playing if `ignoreOther` is true. if (ignoreOther) canPlayOtherAnims = false; // Move to the first frame of the animation. + // goToFrameLabel(id); + trace('Playing animation $id'); + this.anim.play(id, restart, false, startFrame); goToFrameLabel(id); this.currentAnimation = id; } @@ -175,6 +190,24 @@ class FlxAtlasSprite extends FlxAnimate super.update(elapsed); } + /** + * Returns true if the animation has finished playing. + * Never true if animation is configured to loop. + */ + public function isAnimationFinished():Bool + { + return this.anim.finished; + } + + /** + * Returns true if the animation has reached the last frame. + * Can be true even if animation is configured to loop. + */ + public function isLoopComplete():Bool + { + return (anim.reversed && anim.curFrame == 0 || !(anim.reversed) && (anim.curFrame) >= (anim.length - 1)); + } + /** * Stops the current animation. */ @@ -219,4 +252,76 @@ class FlxAtlasSprite extends FlxAnimate // this.currentAnimation = null; this.anim.pause(); } + + function _onAnimationFrame(frame:Int):Void + { + if (currentAnimation != null) + { + onAnimationFrame.dispatch(currentAnimation, frame); + if (isLoopComplete()) onAnimationLoopComplete.dispatch(currentAnimation); + } + } + + function _onAnimationComplete():Void + { + if (currentAnimation != null) + { + onAnimationComplete.dispatch(currentAnimation); + } + } + + var prevFrames:Map = []; + + public function replaceFrameGraphic(index:Int, ?graphic:FlxGraphicAsset):Void + { + if (graphic == null || !Assets.exists(graphic)) + { + var prevFrame:Null = prevFrames.get(index); + if (prevFrame == null) return; + + prevFrame.copyTo(frames.getByIndex(index)); + return; + } + + var prevFrame:FlxFrame = prevFrames.get(index) ?? frames.getByIndex(index).copyTo(); + prevFrames.set(index, prevFrame); + + var frame = FlxG.bitmap.add(graphic).imageFrame.frame; + frame.copyTo(frames.getByIndex(index)); + + // Additional sizing fix. + @:privateAccess + if (true) + { + var frame = frames.getByIndex(index); + frame.tileMatrix[0] = prevFrame.frame.width / frame.frame.width; + frame.tileMatrix[3] = prevFrame.frame.height / frame.frame.height; + } + } + + public function getBasePosition():Null + { + var stagePos = new FlxPoint(anim.stageInstance.matrix.tx, anim.stageInstance.matrix.ty); + var instancePos = new FlxPoint(anim.curInstance.matrix.tx, anim.curInstance.matrix.ty); + var firstElement = anim.curSymbol.timeline?.get(0)?.get(0)?.get(0); + if (firstElement == null) return instancePos; + var firstElementPos = new FlxPoint(firstElement.matrix.tx, firstElement.matrix.ty); + + return instancePos + firstElementPos; + } + + public function getPivotPosition():Null + { + return anim.curInstance.symbol.transformationPoint; + } + + public override function destroy():Void + { + for (prevFrameId in prevFrames.keys()) + { + replaceFrameGraphic(prevFrameId, null); + } + + super.destroy(); + } } diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index c2d9d42b3..b1ff69a3a 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -70,6 +70,8 @@ class ResultState extends MusicBeatSubState delay:Float }> = []; + var playerCharacterId:Null; + var rankBg:FunkinSprite; final cameraBG:FunkinCamera; final cameraScroll:FunkinCamera; @@ -164,7 +166,7 @@ class ResultState extends MusicBeatSubState add(soundSystem); // Fetch playable character data. Default to BF on the results screen if we can't find it. - var playerCharacterId:Null = PlayerRegistry.instance.getCharacterOwnerId(params.characterId); + playerCharacterId = PlayerRegistry.instance.getCharacterOwnerId(params.characterId); var playerCharacter:Null = PlayerRegistry.instance.fetchEntry(playerCharacterId ?? 'bf'); trace('Got playable character: ${playerCharacter?.getName()}'); @@ -189,7 +191,7 @@ class ResultState extends MusicBeatSubState if (!(animData.looped ?? true)) { // Animation is not looped. - animation.onAnimationFinish.add((_name:String) -> { + animation.onAnimationComplete.add((_name:String) -> { if (animation != null) { animation.anim.pause(); @@ -198,7 +200,7 @@ class ResultState extends MusicBeatSubState } else if (animData.loopFrameLabel != null) { - animation.onAnimationFinish.add((_name:String) -> { + animation.onAnimationComplete.add((_name:String) -> { if (animation != null) { animation.playAnimation(animData.loopFrameLabel ?? ''); // unpauses this anim, since it's on PlayOnce! @@ -207,7 +209,7 @@ class ResultState extends MusicBeatSubState } else if (animData.loopFrame != null) { - animation.onAnimationFinish.add((_name:String) -> { + animation.onAnimationComplete.add((_name:String) -> { if (animation != null) { animation.anim.curFrame = animData.loopFrame ?? 0; @@ -742,6 +744,7 @@ class ResultState extends MusicBeatSubState FlxG.switchState(FreeplayState.build( { { + character: playerCharacterId ?? "bf", fromResults: { oldRank: Scoring.calculateRank(params?.prevScoreData), @@ -799,8 +802,9 @@ typedef ResultsStateParams = /** * The character ID for the song we just played. + * @default `bf` */ - var characterId:String; + var ?characterId:String; /** * Whether the displayed score is a new highscore diff --git a/source/funkin/play/character/AnimateAtlasCharacter.hx b/source/funkin/play/character/AnimateAtlasCharacter.hx index ed58b92b5..1d1672c9d 100644 --- a/source/funkin/play/character/AnimateAtlasCharacter.hx +++ b/source/funkin/play/character/AnimateAtlasCharacter.hx @@ -109,8 +109,6 @@ class AnimateAtlasCharacter extends BaseCharacter var loop:Bool = animData.looped; this.mainSprite.playAnimation(prefix, restart, ignoreOther, loop); - - animFinished = false; } public override function hasAnimation(name:String):Bool @@ -124,7 +122,7 @@ class AnimateAtlasCharacter extends BaseCharacter */ public override function isAnimationFinished():Bool { - return animFinished; + return mainSprite.isAnimationFinished(); } function loadAtlasSprite():FlxAtlasSprite @@ -133,8 +131,8 @@ class AnimateAtlasCharacter extends BaseCharacter var sprite:FlxAtlasSprite = new FlxAtlasSprite(0, 0, Paths.animateAtlas(_data.assetPath, 'shared')); - sprite.onAnimationFinish.removeAll(); - sprite.onAnimationFinish.add(this.onAnimationFinished); + // sprite.onAnimationComplete.removeAll(); + sprite.onAnimationComplete.add(this.onAnimationFinished); return sprite; } @@ -152,7 +150,6 @@ class AnimateAtlasCharacter extends BaseCharacter // Make the game hold on the last frame. this.mainSprite.cleanupAnimation(prefix); // currentAnimName = null; - animFinished = true; // Fallback to idle! // playAnimation('idle', true, false); @@ -165,6 +162,11 @@ class AnimateAtlasCharacter extends BaseCharacter this.mainSprite = sprite; + // This forces the atlas to recalcuate its width and height + this.mainSprite.alpha = 0.0001; + this.mainSprite.draw(); + this.mainSprite.alpha = 1.0; + var feetPos:FlxPoint = feetPosition; this.updateHitbox(); diff --git a/source/funkin/ui/charSelect/CharSelectPlayer.hx b/source/funkin/ui/charSelect/CharSelectPlayer.hx index 9322369ba..9052c60e9 100644 --- a/source/funkin/ui/charSelect/CharSelectPlayer.hx +++ b/source/funkin/ui/charSelect/CharSelectPlayer.hx @@ -9,7 +9,7 @@ class CharSelectPlayer extends FlxAtlasSprite { super(x, y, Paths.animateAtlas("charSelect/bfChill")); - onAnimationFinish.add(function(animLabel:String) { + onAnimationComplete.add(function(animLabel:String) { switch (animLabel) { case "slidein": diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index 14a5b36e0..8b1f050f5 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -600,7 +600,7 @@ class CharSelectSubState extends MusicBeatSubState playerChill.visible = false; playerChillOut.visible = true; playerChillOut.anim.goToFrameLabel("slideout"); - playerChillOut.anim.callback = (_, frame:Int) -> { + playerChillOut.onAnimationFrame.add((_, frame:Int) -> { if (frame == playerChillOut.anim.getFrameLabel("slideout").index + 1) { playerChill.visible = true; @@ -612,7 +612,7 @@ class CharSelectSubState extends MusicBeatSubState playerChillOut.switchChar(value); playerChillOut.visible = false; } - }; + }); return value; } diff --git a/source/funkin/ui/freeplay/AlbumRoll.hx b/source/funkin/ui/freeplay/AlbumRoll.hx index 49c588722..36dba0054 100644 --- a/source/funkin/ui/freeplay/AlbumRoll.hx +++ b/source/funkin/ui/freeplay/AlbumRoll.hx @@ -37,6 +37,7 @@ class AlbumRoll extends FlxSpriteGroup } var newAlbumArt:FlxAtlasSprite; + var albumTitle:FunkinSprite; var difficultyStars:DifficultyStars; var _exitMovers:Null; @@ -59,24 +60,27 @@ class AlbumRoll extends FlxSpriteGroup { super(); - newAlbumArt = new FlxAtlasSprite(0, 0, Paths.animateAtlas("freeplay/albumRoll/freeplayAlbum")); + newAlbumArt = new FlxAtlasSprite(640, 350, Paths.animateAtlas("freeplay/albumRoll/freeplayAlbum")); newAlbumArt.visible = false; - newAlbumArt.onAnimationFinish.add(onAlbumFinish); + newAlbumArt.onAnimationComplete.add(onAlbumFinish); add(newAlbumArt); difficultyStars = new DifficultyStars(140, 39); difficultyStars.visible = false; add(difficultyStars); + + buildAlbumTitle("freeplay/albumRoll/volume1-text"); + albumTitle.visible = false; } function onAlbumFinish(animName:String):Void { // Play the idle animation for the current album. - newAlbumArt.playAnimation(animNames.get('$albumId-idle'), false, false, true); - - // End on the last frame and don't continue until playAnimation is called again. - // newAlbumArt.anim.pause(); + if (animName != "idle") + { + // newAlbumArt.playAnimation('idle', true); + } } /** @@ -104,6 +108,12 @@ class AlbumRoll extends FlxSpriteGroup return; }; + // Update the album art. + var albumGraphic = Paths.image(albumData.getAlbumArtAssetKey()); + newAlbumArt.replaceFrameGraphic(0, albumGraphic); + + buildAlbumTitle(albumData.getAlbumTitleAssetKey()); + applyExitMovers(); refresh(); @@ -146,19 +156,57 @@ class AlbumRoll extends FlxSpriteGroup */ public function playIntro():Void { + albumTitle.visible = false; newAlbumArt.visible = true; - newAlbumArt.playAnimation(animNames.get('$albumId-active'), false, false, false); + newAlbumArt.playAnimation('intro', true); difficultyStars.visible = false; new FlxTimer().start(0.75, function(_) { - // showTitle(); + showTitle(); showStars(); + albumTitle.animation.play('switch'); }); } public function skipIntro():Void { - newAlbumArt.playAnimation(animNames.get('$albumId-trans'), false, false, false); + // Weird workaround + newAlbumArt.playAnimation('switch', true); + albumTitle.animation.play('switch'); + } + + public function showTitle():Void + { + albumTitle.visible = true; + } + + public function buildAlbumTitle(assetKey:String):Void + { + if (albumTitle != null) + { + remove(albumTitle); + albumTitle = null; + } + + albumTitle = FunkinSprite.createSparrow(925, 500, assetKey); + albumTitle.visible = albumTitle.frames != null && newAlbumArt.visible; + albumTitle.animation.addByPrefix('idle', 'idle0', 24, true); + albumTitle.animation.addByPrefix('switch', 'switch0', 24, false); + add(albumTitle); + + albumTitle.animation.finishCallback = (function(name) { + if (name == 'switch') albumTitle.animation.play('idle'); + }); + albumTitle.animation.play('idle'); + + albumTitle.zIndex = 1000; + + if (_exitMovers != null) _exitMovers.set([albumTitle], + { + x: FlxG.width, + speed: 0.4, + wait: 0 + }); } public function setDifficultyStars(?difficulty:Int):Void diff --git a/source/funkin/ui/freeplay/FreeplayDJ.hx b/source/funkin/ui/freeplay/FreeplayDJ.hx index 72eddd0ca..317a52308 100644 --- a/source/funkin/ui/freeplay/FreeplayDJ.hx +++ b/source/funkin/ui/freeplay/FreeplayDJ.hx @@ -43,7 +43,7 @@ class FreeplayDJ extends FlxAtlasSprite super(x, y, playableCharData.getAtlasPath()); - anim.callback = function(name, number) { + onAnimationFrame.add(function(name, number) { if (name == playableCharData.getAnimationPrefix('cartoon')) { if (number == playableCharData.getCartoonSoundClickFrame()) @@ -55,12 +55,12 @@ class FreeplayDJ extends FlxAtlasSprite runTvLogic(); } } - }; + }); FlxG.debugger.track(this); FlxG.console.registerObject("dj", this); - anim.onComplete = onFinishAnim; + onAnimationComplete.add(onFinishAnim); FlxG.console.registerFunction("freeplayCartoon", function() { currentState = Cartoon; @@ -96,7 +96,7 @@ class FreeplayDJ extends FlxAtlasSprite var animPrefix = playableCharData.getAnimationPrefix('idle'); if (getCurrentAnimation() != animPrefix) { - playFlashAnimation(animPrefix, true); + playFlashAnimation(animPrefix, true, false, true); } if (getCurrentAnimation() == animPrefix && this.isLoopFinished()) @@ -120,7 +120,7 @@ class FreeplayDJ extends FlxAtlasSprite if (getCurrentAnimation() != animPrefix) playFlashAnimation('Boyfriend DJ fist pump', false); if (getCurrentAnimation() == animPrefix && anim.curFrame >= 4) { - anim.play("Boyfriend DJ fist pump", true, false, 0); + playAnimation("Boyfriend DJ fist pump", true, false, false, 0); } case FistPump: @@ -135,9 +135,12 @@ class FreeplayDJ extends FlxAtlasSprite timeIdling = 0; case Cartoon: var animPrefix = playableCharData.getAnimationPrefix('cartoon'); - if (animPrefix == null) { + if (animPrefix == null) + { currentState = IdleEasterEgg; - } else { + } + else + { if (getCurrentAnimation() != animPrefix) playFlashAnimation(animPrefix, true); timeIdling = 0; } @@ -145,6 +148,7 @@ class FreeplayDJ extends FlxAtlasSprite // I shit myself. } + #if debug if (FlxG.keys.pressed.CONTROL) { if (FlxG.keys.justPressed.LEFT) @@ -167,16 +171,17 @@ class FreeplayDJ extends FlxAtlasSprite this.offsetY += FlxG.keys.pressed.ALT ? 0.1 : (FlxG.keys.pressed.SHIFT ? 10.0 : 1.0); } - if (FlxG.keys.justPressed.SPACE) + if (FlxG.keys.justPressed.C) { currentState = (currentState == Idle ? Cartoon : Idle); } } + #end } - function onFinishAnim():Void + function onFinishAnim(name:String):Void { - var name = anim.curSymbol.name; + // var name = anim.curSymbol.name; if (name == playableCharData.getAnimationPrefix('intro')) { @@ -220,7 +225,7 @@ class FreeplayDJ extends FlxAtlasSprite // runTvLogic(); } trace('Replay idle: ${frame}'); - anim.play(playableCharData.getAnimationPrefix('cartoon'), true, false, frame); + playAnimation(playableCharData.getAnimationPrefix('cartoon'), true, false, false, frame); // trace('Finished confirm'); } else @@ -266,7 +271,7 @@ class FreeplayDJ extends FlxAtlasSprite function loadCartoon() { cartoonSnd = FunkinSound.load(Paths.sound(getRandomFlashToon()), 1.0, false, true, true, function() { - anim.play("Boyfriend DJ watchin tv OG", true, false, 60); + playAnimation("Boyfriend DJ watchin tv OG", true, false, false, 60); }); // Fade out music to 40% volume over 1 second. @@ -304,13 +309,13 @@ class FreeplayDJ extends FlxAtlasSprite public function pumpFist():Void { currentState = FistPump; - anim.play("Boyfriend DJ fist pump", true, false, 4); + playAnimation("Boyfriend DJ fist pump", true, false, false, 4); } public function pumpFistBad():Void { currentState = FistPump; - anim.play("Boyfriend DJ loss reaction 1", true, false, 4); + playAnimation("Boyfriend DJ loss reaction 1", true, false, false, 4); } override public function getCurrentAnimation():String @@ -319,9 +324,9 @@ class FreeplayDJ extends FlxAtlasSprite return this.anim.curSymbol.name; } - public function playFlashAnimation(id:String, ?Force:Bool = false, ?Reverse:Bool = false, ?Frame:Int = 0):Void + public function playFlashAnimation(id:String, Force:Bool = false, Reverse:Bool = false, Loop:Bool = false, Frame:Int = 0):Void { - anim.play(id, Force, Reverse, Frame); + playAnimation(id, Force, Reverse, Loop, Frame); applyAnimOffset(); } diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index dc42bd651..284f41bb6 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1792,7 +1792,7 @@ class FreeplayState extends MusicBeatSubState confirmGlow.visible = true; confirmGlow2.visible = true; - backingTextYeah.anim.play("BF back card confirm raw", false, false, 0); + backingTextYeah.playAnimation("BF back card confirm raw", false, false, false, 0); confirmGlow2.alpha = 0; confirmGlow.alpha = 0; diff --git a/source/funkin/ui/freeplay/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx index 2eec83223..b4409d377 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -162,7 +162,7 @@ class SongMenuItem extends FlxSpriteGroup sparkle = new FlxSprite(ranking.x, ranking.y); sparkle.frames = Paths.getSparrowAtlas('freeplay/sparkle'); - sparkle.animation.addByPrefix('sparkle', 'sparkle', 24, false); + sparkle.animation.addByPrefix('sparkle', 'sparkle Export0', 24, false); sparkle.animation.play('sparkle', true); sparkle.scale.set(0.8, 0.8); sparkle.blend = BlendMode.ADD; @@ -523,7 +523,6 @@ class SongMenuItem extends FlxSpriteGroup checkWeek(songData?.songId); } - var frameInTicker:Float = 0; var frameInTypeBeat:Int = 0; From 81680694e3a1bd7d020de70c9980736d2d5f5e97 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Fri, 14 Jun 2024 21:52:52 -0700 Subject: [PATCH 418/870] Reorder download Git step in compiling guide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moved “download Git” from the middle of the guide to the setup step Should prevent errors with Git before installing Git --- docs/COMPILING.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index e7c19875a..b8ddee4a7 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -2,14 +2,14 @@ 0. Setup - Download Haxe from [Haxe.org](https://haxe.org) + - Download Git from [git-scm.com](https://www.git-scm.com) 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. 2. Install `hmm` (run `haxelib --global install hmm` and then `haxelib --global run hmm 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 +3. Install all haxelibs of the current branch by running `hmm install` +4. Setup lime: `haxelib run lime setup` +5. 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 @@ -17,8 +17,8 @@ - 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 -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). +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 From 9f17478a3afd007e4d164adc14cf758675e620c6 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Sat, 15 Jun 2024 13:37:21 -0400 Subject: [PATCH 419/870] Add ZIP button warning and restructured sentences Each step should be easier to follow with this structure --- docs/COMPILING.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index b8ddee4a7..b2a106c86 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -3,12 +3,13 @@ 0. Setup - Download Haxe from [Haxe.org](https://haxe.org) - Download Git from [git-scm.com](https://www.git-scm.com) -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. -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` + - Do NOT download the repository using the Download ZIP button on GitHub or you may run into errors! + - Instead, open a command prompt and do the following steps... +1. Run `git clone --recurse-submodules https://github.com/FunkinCrew/funkin.git` to clone the repository with the necessary assets submodule + - _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. Run `haxelib --global install hmm` and then `haxelib --global run hmm setup` to install hmm.json +3. Run `hmm install` to install all haxelibs of the current branch +4. Run `haxelib run lime setup` to set up lime 5. 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: From 87d8d4043e39e2302479a6f384d8cd289e4c8b79 Mon Sep 17 00:00:00 2001 From: Eric Date: Sun, 16 Jun 2024 18:48:01 -0400 Subject: [PATCH 420/870] Make downloading the assets submodule a separate step. --- docs/COMPILING.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index b2a106c86..cc90bd348 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -5,8 +5,9 @@ - Download Git from [git-scm.com](https://www.git-scm.com) - Do NOT download the repository using the Download ZIP button on GitHub or you may run into errors! - Instead, open a command prompt and do the following steps... -1. Run `git clone --recurse-submodules https://github.com/FunkinCrew/funkin.git` to clone the repository with the necessary assets submodule - - _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._ +1. Run `git clone https://github.com/FunkinCrew/funkin.git` to clone the base repository. +2. Run `git submodule update --init --recursive` to download the game's assets. + - NOTE: By performing this operation, you are downloading Content which is proprietary and protected by national and international copyright and trademark laws. See [the LICENSE.md file for the Funkin.assets](https://github.com/FunkinCrew/funkin.assets/blob/main/LICENSE.md) repo for more information. 2. Run `haxelib --global install hmm` and then `haxelib --global run hmm setup` to install hmm.json 3. Run `hmm install` to install all haxelibs of the current branch 4. Run `haxelib run lime setup` to set up lime From 242ab6e922ede547bb6c6babefccd41ed0f10962 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 25 Jun 2024 18:22:30 -0400 Subject: [PATCH 421/870] Add change counts labels to Actions labeler --- .github/changed-lines-count-labeler.yml | 12 ++++++++++++ .github/workflows/labeler.yml | 15 ++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 .github/changed-lines-count-labeler.yml diff --git a/.github/changed-lines-count-labeler.yml b/.github/changed-lines-count-labeler.yml new file mode 100644 index 000000000..6f890f534 --- /dev/null +++ b/.github/changed-lines-count-labeler.yml @@ -0,0 +1,12 @@ +# Add 'small' to any changes below 10 lines +small: + max: 9 + +# Add 'medium' to any changes between 10 and 100 lines +medium: + min: 10 + max: 99 + +# Add 'large' to any changes for more than 100 lines +large: + min: 100 diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 0bcc420d3..a861af578 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -9,6 +9,19 @@ jobs: pull-requests: write runs-on: ubuntu-latest steps: - - uses: actions/labeler@v5 + - name: Set basic labels + uses: actions/labeler@v5 with: sync-labels: true + changed-lines-count-labeler: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + name: An action for automatically labelling pull requests based on the changed lines count + steps: + - name: Set change count labels + uses: vkirilichev/changed-lines-count-labeler@v0.2 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + configuration-path: .github/changed-lines-count-labeler.yml From 34a19ef5832aa98c9edae98823faf2537f2abc59 Mon Sep 17 00:00:00 2001 From: AppleHair Date: Tue, 9 Jul 2024 19:59:31 +0300 Subject: [PATCH 422/870] [BUGFIX] Fixed `cancelMenu` sound not playing after switching state. --- source/funkin/ui/mainmenu/MainMenuState.hx | 2 +- source/funkin/ui/options/OptionsState.hx | 2 +- source/funkin/ui/story/StoryMenuState.hx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index 1dcf57743..d219bfbcf 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -412,8 +412,8 @@ class MainMenuState extends MusicBeatState if (controls.BACK && menuItems.enabled && !menuItems.busy) { - FunkinSound.playOnce(Paths.sound('cancelMenu')); FlxG.switchState(() -> new TitleState()); + FunkinSound.playOnce(Paths.sound('cancelMenu')); } } } diff --git a/source/funkin/ui/options/OptionsState.hx b/source/funkin/ui/options/OptionsState.hx index 40308d96b..a2301e6a3 100644 --- a/source/funkin/ui/options/OptionsState.hx +++ b/source/funkin/ui/options/OptionsState.hx @@ -145,8 +145,8 @@ class Page extends FlxGroup { if (canExit && controls.BACK) { - FunkinSound.playOnce(Paths.sound('cancelMenu')); exit(); + FunkinSound.playOnce(Paths.sound('cancelMenu')); } } diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx index 4da467db7..4e51fb229 100644 --- a/source/funkin/ui/story/StoryMenuState.hx +++ b/source/funkin/ui/story/StoryMenuState.hx @@ -390,9 +390,9 @@ class StoryMenuState extends MusicBeatState if (controls.BACK && !exitingMenu && !selectedLevel) { - FunkinSound.playOnce(Paths.sound('cancelMenu')); exitingMenu = true; FlxG.switchState(() -> new MainMenuState()); + FunkinSound.playOnce(Paths.sound('cancelMenu')); } } From 2a5a24af708b738154718faab85f318ff1f41f96 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Wed, 10 Jul 2024 15:54:54 -0700 Subject: [PATCH 423/870] Polish and add triage label to bug template --- .github/ISSUE_TEMPLATE/bug.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md index 82c121b5a..d9b5bc34b 100644 --- a/.github/ISSUE_TEMPLATE/bug.md +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -2,7 +2,7 @@ name: Bug Report about: Report a bug or critical performance issue title: 'Bug Report: [DESCRIBE YOUR BUG IN DETAIL HERE]' -labels: bug +labels: 'status: pending triage' --- -## Describe the bug +## Describe the Bug ## To Reproduce - -## Expected behavior + + +## Expected Behavior ## Screenshots/Video +Remember to mark the area in the application that's impacted. --> ## Desktop - OS: - - Browser - + - Browser: + - Version: ## Additional context - + From 6b2ab64e97e656fda98da0b81cf0859410c9e050 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Wed, 10 Jul 2024 15:58:42 -0700 Subject: [PATCH 424/870] Add triage label to enhancement template --- .github/ISSUE_TEMPLATE/enhancement.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md index e1cc3ae0d..0bdaa953a 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.md +++ b/.github/ISSUE_TEMPLATE/enhancement.md @@ -2,7 +2,7 @@ name: Enhancement about: Suggest a new feature title: 'Enhancement: ' -labels: enhancement +labels: 'status: pending triage' --- -#### Please check for duplicates or similar issues before creating this issue. +#### Please check for duplicates or similar issues before submitting this suggestion. ## What is your suggestion, and why should it be implemented? From 2ba71e78bb3f73ca40a53d754ec8c1732c78c625 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Wed, 10 Jul 2024 16:00:28 -0700 Subject: [PATCH 425/870] Add triage label to PR bugfix template --- .github/PULL_REQUEST_TEMPLATE/bug.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE/bug.md b/.github/PULL_REQUEST_TEMPLATE/bug.md index 41914c5ed..db42b51eb 100644 --- a/.github/PULL_REQUEST_TEMPLATE/bug.md +++ b/.github/PULL_REQUEST_TEMPLATE/bug.md @@ -2,9 +2,9 @@ name: Bug Fix about: Fix a bug or critical performance issue title: 'Bug Fix: ' -labels: bug +labels: 'status: pending triage' --- -#### Please check for duplicates or similar PRs before creating this issue. -## Does this PR close any issue(s)? If so, link them below. +#### Please check for duplicates or similar PRs before submitting this PR. +## Does this PR close any issues? If so, link them below. ## Briefly describe the issue(s) fixed. From fd7cdca333ccd9244231dd6d742188a486e51145 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Wed, 10 Jul 2024 16:01:52 -0700 Subject: [PATCH 426/870] Add triage label to PR enhancement template --- .github/PULL_REQUEST_TEMPLATE/enhancement.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE/enhancement.md b/.github/PULL_REQUEST_TEMPLATE/enhancement.md index e208deefe..192d31c48 100644 --- a/.github/PULL_REQUEST_TEMPLATE/enhancement.md +++ b/.github/PULL_REQUEST_TEMPLATE/enhancement.md @@ -2,9 +2,9 @@ name: Enhancement about: Add a new feature title: 'Enhancement: ' -labels: enhancement +labels: 'status: pending triage" --- -#### Please check for duplicates or similar PRs before creating this issue. -## Does this PR close any issue(s)? If so, link them below. +#### Please check for duplicates or similar PRs before submitting this PR. +## Does this PR close any issues? If so, link them below. -## What do your change(s) add, and why should they be implemented? +## What do your changes add, and why should they be implemented? From 5a534e210b06bc97b01ddca7cf7fb0b713496d22 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Wed, 10 Jul 2024 16:02:18 -0700 Subject: [PATCH 427/870] Wrong quote whoops --- .github/PULL_REQUEST_TEMPLATE/enhancement.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE/enhancement.md b/.github/PULL_REQUEST_TEMPLATE/enhancement.md index 192d31c48..439068598 100644 --- a/.github/PULL_REQUEST_TEMPLATE/enhancement.md +++ b/.github/PULL_REQUEST_TEMPLATE/enhancement.md @@ -2,7 +2,7 @@ name: Enhancement about: Add a new feature title: 'Enhancement: ' -labels: 'status: pending triage" +labels: 'status: pending triage' --- #### Please check for duplicates or similar PRs before submitting this PR. ## Does this PR close any issues? If so, link them below. From 56948507e81939c77e7d7aad4d9bc11eca60bac2 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Wed, 10 Jul 2024 16:04:21 -0700 Subject: [PATCH 428/870] Capitalize C in "context" --- .github/ISSUE_TEMPLATE/bug.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md index d9b5bc34b..fcbfacfaa 100644 --- a/.github/ISSUE_TEMPLATE/bug.md +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -45,7 +45,7 @@ Remember to mark the area in the application that's impacted. --> - Version: -## Additional context +## Additional Context From db0bb4d9c23d42e5121a87a4ddfcc759b89f8498 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Wed, 10 Jul 2024 16:14:29 -0700 Subject: [PATCH 429/870] Final bug template polish --- .github/ISSUE_TEMPLATE/bug.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md index fcbfacfaa..bae88b132 100644 --- a/.github/ISSUE_TEMPLATE/bug.md +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -10,7 +10,7 @@ OR ELSE YOUR ISSUE WILL BE LESS LIKELY TO BE SOLVED! Do not post about issues from other FNF mod engines! We cannot and probably won't solve those! -You can hopefully go to their respective GitHub issues and report them there, thank you :) +You can hopefully go to their respective GitHub issues pages and report them there, thank you :) Please check for duplicates or similar issues, as well as performing simple troubleshooting steps (such as clearing cookies, clearing AppData, trying another browser) before submitting an issue. @@ -48,4 +48,4 @@ Remember to mark the area in the application that's impacted. --> ## Additional Context - + From 2d5be92882698336194696a2f20ee1984a756aa5 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Fri, 14 Jun 2024 21:52:52 -0700 Subject: [PATCH 430/870] Reorder download Git step in compiling guide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moved “download Git” from the middle of the guide to the setup step Should prevent errors with Git before installing Git --- docs/COMPILING.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index e7c19875a..b8ddee4a7 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -2,14 +2,14 @@ 0. Setup - Download Haxe from [Haxe.org](https://haxe.org) + - Download Git from [git-scm.com](https://www.git-scm.com) 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. 2. Install `hmm` (run `haxelib --global install hmm` and then `haxelib --global run hmm 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 +3. Install all haxelibs of the current branch by running `hmm install` +4. Setup lime: `haxelib run lime setup` +5. 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 @@ -17,8 +17,8 @@ - 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 -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). +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 From 33bfe34f098cd7e7f0d6e7c8af6f9b6161344537 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Sat, 15 Jun 2024 13:37:21 -0400 Subject: [PATCH 431/870] Add ZIP button warning and restructured sentences Each step should be easier to follow with this structure --- docs/COMPILING.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index b8ddee4a7..b2a106c86 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -3,12 +3,13 @@ 0. Setup - Download Haxe from [Haxe.org](https://haxe.org) - Download Git from [git-scm.com](https://www.git-scm.com) -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. -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` + - Do NOT download the repository using the Download ZIP button on GitHub or you may run into errors! + - Instead, open a command prompt and do the following steps... +1. Run `git clone --recurse-submodules https://github.com/FunkinCrew/funkin.git` to clone the repository with the necessary assets submodule + - _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. Run `haxelib --global install hmm` and then `haxelib --global run hmm setup` to install hmm.json +3. Run `hmm install` to install all haxelibs of the current branch +4. Run `haxelib run lime setup` to set up lime 5. 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: From abf898ff01a5981778143a1aed75264d7d7bdcdb Mon Sep 17 00:00:00 2001 From: Eric Date: Sun, 16 Jun 2024 18:48:01 -0400 Subject: [PATCH 432/870] Make downloading the assets submodule a separate step. --- docs/COMPILING.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index b2a106c86..cc90bd348 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -5,8 +5,9 @@ - Download Git from [git-scm.com](https://www.git-scm.com) - Do NOT download the repository using the Download ZIP button on GitHub or you may run into errors! - Instead, open a command prompt and do the following steps... -1. Run `git clone --recurse-submodules https://github.com/FunkinCrew/funkin.git` to clone the repository with the necessary assets submodule - - _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._ +1. Run `git clone https://github.com/FunkinCrew/funkin.git` to clone the base repository. +2. Run `git submodule update --init --recursive` to download the game's assets. + - NOTE: By performing this operation, you are downloading Content which is proprietary and protected by national and international copyright and trademark laws. See [the LICENSE.md file for the Funkin.assets](https://github.com/FunkinCrew/funkin.assets/blob/main/LICENSE.md) repo for more information. 2. Run `haxelib --global install hmm` and then `haxelib --global run hmm setup` to install hmm.json 3. Run `hmm install` to install all haxelibs of the current branch 4. Run `haxelib run lime setup` to set up lime From 49b7876b5a60cf5627fd137a75c773c508aa4513 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 25 Jun 2024 18:22:30 -0400 Subject: [PATCH 433/870] Add change counts labels to Actions labeler --- .github/changed-lines-count-labeler.yml | 12 ++++++++++++ .github/workflows/labeler.yml | 15 ++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 .github/changed-lines-count-labeler.yml diff --git a/.github/changed-lines-count-labeler.yml b/.github/changed-lines-count-labeler.yml new file mode 100644 index 000000000..6f890f534 --- /dev/null +++ b/.github/changed-lines-count-labeler.yml @@ -0,0 +1,12 @@ +# Add 'small' to any changes below 10 lines +small: + max: 9 + +# Add 'medium' to any changes between 10 and 100 lines +medium: + min: 10 + max: 99 + +# Add 'large' to any changes for more than 100 lines +large: + min: 100 diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 0bcc420d3..a861af578 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -9,6 +9,19 @@ jobs: pull-requests: write runs-on: ubuntu-latest steps: - - uses: actions/labeler@v5 + - name: Set basic labels + uses: actions/labeler@v5 with: sync-labels: true + changed-lines-count-labeler: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + name: An action for automatically labelling pull requests based on the changed lines count + steps: + - name: Set change count labels + uses: vkirilichev/changed-lines-count-labeler@v0.2 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + configuration-path: .github/changed-lines-count-labeler.yml From 8107d1a29096467acf207d4b12760c41bd17495c Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Mon, 8 Jul 2024 03:17:28 +0200 Subject: [PATCH 434/870] Remove SustainTrail forced alpha --- source/funkin/play/notes/Strumline.hx | 1 - 1 file changed, 1 deletion(-) diff --git a/source/funkin/play/notes/Strumline.hx b/source/funkin/play/notes/Strumline.hx index 3c114b5e0..fdb32bb85 100644 --- a/source/funkin/play/notes/Strumline.hx +++ b/source/funkin/play/notes/Strumline.hx @@ -598,7 +598,6 @@ 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 738a21eeb63611e555b6e45cb8f9baf11c3274e3 Mon Sep 17 00:00:00 2001 From: tposejank <81495861+tposejank@users.noreply.github.com> Date: Wed, 10 Jul 2024 20:41:40 -0400 Subject: [PATCH 435/870] abcd --- .github/ISSUE_TEMPLATE/bug.md | 52 +------------------ .github/ISSUE_TEMPLATE/enhancement.md | 9 +--- .github/PULL_REQUEST_TEMPLATE.md | 10 ++++ .github/PULL_REQUEST_TEMPLATE/bug.md | 11 +--- .github/PULL_REQUEST_TEMPLATE/bug.yml | 19 +------ .github/PULL_REQUEST_TEMPLATE/enhancement.md | 11 +--- .github/PULL_REQUEST_TEMPLATE/enhancement.yml | 19 +------ 7 files changed, 16 insertions(+), 115 deletions(-) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md index bae88b132..89fb11fad 100644 --- a/.github/ISSUE_TEMPLATE/bug.md +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -1,51 +1 @@ ---- -name: Bug Report -about: Report a bug or critical performance issue -title: 'Bug Report: [DESCRIBE YOUR BUG IN DETAIL HERE]' -labels: 'status: pending triage' ---- - - - -## Describe the Bug - - -## To Reproduce - - -## Expected Behavior - - -## Screenshots/Video - - -## Desktop - - OS: - - - Browser: - - - Version: - - -## Additional Context - - - +do not give me merge conflicts. diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md index 0bdaa953a..89fb11fad 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.md +++ b/.github/ISSUE_TEMPLATE/enhancement.md @@ -1,8 +1 @@ ---- -name: Enhancement -about: Suggest a new feature -title: 'Enhancement: ' -labels: 'status: pending triage' ---- -#### Please check for duplicates or similar issues before submitting this suggestion. -## What is your suggestion, and why should it be implemented? +do not give me merge conflicts. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..db42b51eb --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,10 @@ +--- +name: Bug Fix +about: Fix a bug or critical performance issue +title: 'Bug Fix: ' +labels: 'status: pending triage' +--- +#### Please check for duplicates or similar PRs before submitting this PR. +## Does this PR close any issues? If so, link them below. + +## Briefly describe the issue(s) fixed. diff --git a/.github/PULL_REQUEST_TEMPLATE/bug.md b/.github/PULL_REQUEST_TEMPLATE/bug.md index db42b51eb..89fb11fad 100644 --- a/.github/PULL_REQUEST_TEMPLATE/bug.md +++ b/.github/PULL_REQUEST_TEMPLATE/bug.md @@ -1,10 +1 @@ ---- -name: Bug Fix -about: Fix a bug or critical performance issue -title: 'Bug Fix: ' -labels: 'status: pending triage' ---- -#### Please check for duplicates or similar PRs before submitting this PR. -## Does this PR close any issues? If so, link them below. - -## Briefly describe the issue(s) fixed. +do not give me merge conflicts. diff --git a/.github/PULL_REQUEST_TEMPLATE/bug.yml b/.github/PULL_REQUEST_TEMPLATE/bug.yml index ca17d0168..89fb11fad 100644 --- a/.github/PULL_REQUEST_TEMPLATE/bug.yml +++ b/.github/PULL_REQUEST_TEMPLATE/bug.yml @@ -1,18 +1 @@ -name: Bug Fix -description: Fix a bug or critical performance issue -labels: ["type: minor bug", "status: pending triage"] -title: "Bug Fix: " -body: - - type: checkboxes - attributes: - label: Issue Checklist - options: - - label: I have checked if this PR isn't a duplicate - - - type: textarea - attributes: - label: Does this PR fix any issues? Please link them below if so. - - - type: textarea - attributes: - label: Briefly describe the issue(s) fixed. +do not give me merge conflicts. diff --git a/.github/PULL_REQUEST_TEMPLATE/enhancement.md b/.github/PULL_REQUEST_TEMPLATE/enhancement.md index 439068598..89fb11fad 100644 --- a/.github/PULL_REQUEST_TEMPLATE/enhancement.md +++ b/.github/PULL_REQUEST_TEMPLATE/enhancement.md @@ -1,10 +1 @@ ---- -name: Enhancement -about: Add a new feature -title: 'Enhancement: ' -labels: 'status: pending triage' ---- -#### Please check for duplicates or similar PRs before submitting this PR. -## Does this PR close any issues? If so, link them below. - -## What do your changes add, and why should they be implemented? +do not give me merge conflicts. diff --git a/.github/PULL_REQUEST_TEMPLATE/enhancement.yml b/.github/PULL_REQUEST_TEMPLATE/enhancement.yml index c39bd3e4a..89fb11fad 100644 --- a/.github/PULL_REQUEST_TEMPLATE/enhancement.yml +++ b/.github/PULL_REQUEST_TEMPLATE/enhancement.yml @@ -1,18 +1 @@ -name: Enhancement -description: Add a new feature -labels: ["type: enhancement", "status: pending triage"] -title: "Enhancement: " -body: - - type: checkboxes - attributes: - label: Issue Checklist - options: - - label: I have checked if this PR isn't a duplicate - - - type: textarea - attributes: - label: Does this PR fix any issues? Please link them below if so. - - - type: textarea - attributes: - label: What do your change(s) add, and why should they be implemented? +do not give me merge conflicts. From 2915fd7717669dd1152b13dac8c562cb0794ff08 Mon Sep 17 00:00:00 2001 From: tposejank <81495861+tposejank@users.noreply.github.com> Date: Wed, 10 Jul 2024 20:42:08 -0400 Subject: [PATCH 436/870] efgh --- .github/ISSUE_TEMPLATE/bug.md | 1 - .github/ISSUE_TEMPLATE/enhancement.md | 1 - .github/PULL_REQUEST_TEMPLATE/bug.md | 1 - .github/PULL_REQUEST_TEMPLATE/bug.yml | 1 - .github/PULL_REQUEST_TEMPLATE/enhancement.md | 1 - .github/PULL_REQUEST_TEMPLATE/enhancement.yml | 1 - 6 files changed, 6 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug.md delete mode 100644 .github/ISSUE_TEMPLATE/enhancement.md delete mode 100644 .github/PULL_REQUEST_TEMPLATE/bug.md delete mode 100644 .github/PULL_REQUEST_TEMPLATE/bug.yml delete mode 100644 .github/PULL_REQUEST_TEMPLATE/enhancement.md delete mode 100644 .github/PULL_REQUEST_TEMPLATE/enhancement.yml diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md deleted file mode 100644 index 89fb11fad..000000000 --- a/.github/ISSUE_TEMPLATE/bug.md +++ /dev/null @@ -1 +0,0 @@ -do not give me merge conflicts. diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md deleted file mode 100644 index 89fb11fad..000000000 --- a/.github/ISSUE_TEMPLATE/enhancement.md +++ /dev/null @@ -1 +0,0 @@ -do not give me merge conflicts. diff --git a/.github/PULL_REQUEST_TEMPLATE/bug.md b/.github/PULL_REQUEST_TEMPLATE/bug.md deleted file mode 100644 index 89fb11fad..000000000 --- a/.github/PULL_REQUEST_TEMPLATE/bug.md +++ /dev/null @@ -1 +0,0 @@ -do not give me merge conflicts. diff --git a/.github/PULL_REQUEST_TEMPLATE/bug.yml b/.github/PULL_REQUEST_TEMPLATE/bug.yml deleted file mode 100644 index 89fb11fad..000000000 --- a/.github/PULL_REQUEST_TEMPLATE/bug.yml +++ /dev/null @@ -1 +0,0 @@ -do not give me merge conflicts. diff --git a/.github/PULL_REQUEST_TEMPLATE/enhancement.md b/.github/PULL_REQUEST_TEMPLATE/enhancement.md deleted file mode 100644 index 89fb11fad..000000000 --- a/.github/PULL_REQUEST_TEMPLATE/enhancement.md +++ /dev/null @@ -1 +0,0 @@ -do not give me merge conflicts. diff --git a/.github/PULL_REQUEST_TEMPLATE/enhancement.yml b/.github/PULL_REQUEST_TEMPLATE/enhancement.yml deleted file mode 100644 index 89fb11fad..000000000 --- a/.github/PULL_REQUEST_TEMPLATE/enhancement.yml +++ /dev/null @@ -1 +0,0 @@ -do not give me merge conflicts. From fd37e2121ce9ea14494fdb5393ad5a3bf7ce5464 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Wed, 10 Jul 2024 18:13:27 -0700 Subject: [PATCH 437/870] PR template rename --- .github/{PULL_REQUEST_TEMPLATE.md => pull_request_template.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/{PULL_REQUEST_TEMPLATE.md => pull_request_template.md} (100%) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/pull_request_template.md similarity index 100% rename from .github/PULL_REQUEST_TEMPLATE.md rename to .github/pull_request_template.md From 7353747ca593901d9fbc5ec44e5aac5c638ad44b Mon Sep 17 00:00:00 2001 From: Hundrec Date: Wed, 10 Jul 2024 18:25:32 -0700 Subject: [PATCH 438/870] Simplify PR template --- .github/pull_request_template.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index db42b51eb..b1bd09a8f 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,10 +1,6 @@ ---- -name: Bug Fix -about: Fix a bug or critical performance issue -title: 'Bug Fix: ' -labels: 'status: pending triage' ---- -#### Please check for duplicates or similar PRs before submitting this PR. + ## Does this PR close any issues? If so, link them below. ## Briefly describe the issue(s) fixed. + +## Screenshots/Videos From 88b35ce8c2c9db037aca5df03535eead0b38f659 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Wed, 10 Jul 2024 18:37:19 -0700 Subject: [PATCH 439/870] Tweak Bug Report Template --- .github/ISSUE_TEMPLATE/bug.yml | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index ffbc02fbc..6be3f1245 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -1,5 +1,5 @@ name: Bug Report -description: Report a bug or an issue in the game +description: Report a bug or an issue in the game. labels: ["type: minor bug", "status: pending triage"] title: "Bug Report: " body: @@ -8,22 +8,23 @@ body: label: Issue Checklist options: - label: I have properly named the issue - - label: I looked in issues/discussions, if it has been previously reported + - label: I have checked the issues/discussions pages to see if the issue has been previously reported - type: dropdown attributes: label: What platform are you using? options: - - Itch.io - Windows - - Itch.io - MacOS - - Itch.io - Linux - Newgrounds (Web) + - Itch.io (Web) + - Itch.io (Downloadable Build) - Windows + - Itch.io (Downloadable Build) - MacOS + - Itch.io (Downloadable Build) - Linux validations: required: true - type: dropdown attributes: - label: If you were playing on a browser, which one were you using? + label: If you are playing on a browser, which one are you using? options: - Google Chrome - Microsoft Edge @@ -35,7 +36,7 @@ body: - type: input attributes: label: Version - description: What version were you using? + description: What version are you using? placeholder: ex. 0.4.1 validations: required: true @@ -46,7 +47,7 @@ body: - type: markdown attributes: - value: "### Please do not report issues from other engines. These must be reported in their repositories." + value: "### Please do not report issues from other engines. These must be reported in their respective repositories." - type: markdown attributes: From ac11e5238d75deb789aee096904577772faaf022 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Wed, 10 Jul 2024 18:40:38 -0700 Subject: [PATCH 440/870] Tweak Crash Report Template --- .github/ISSUE_TEMPLATE/crash.yml | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/crash.yml b/.github/ISSUE_TEMPLATE/crash.yml index 7c160244d..74d2d628f 100644 --- a/.github/ISSUE_TEMPLATE/crash.yml +++ b/.github/ISSUE_TEMPLATE/crash.yml @@ -1,5 +1,5 @@ name: Crash Report -description: Report a crash that occurred while playing. +description: Report a crash that occurred while playing the game. labels: ["type: major bug", "status: pending triage"] title: "Crash: " body: @@ -8,22 +8,23 @@ body: label: Issue Checklist options: - label: I have properly named the issue - - label: I looked in issues/discussions, if it has been previously reported + - label: I have checked the issues/discussions pages to see if the issue has been previously reported - type: dropdown attributes: label: What platform are you using? options: - - Itch.io - Windows - - Itch.io - MacOS - - Itch.io - Linux - Newgrounds (Web) + - Itch.io (Web) + - Itch.io (Downloadable Build) - Windows + - Itch.io (Downloadable Build) - MacOS + - Itch.io (Downloadable Build) - Linux validations: required: true - type: dropdown attributes: - label: If you were playing on a browser, which one were you using? + label: If you are playing on a browser, which one are you using? options: - Google Chrome - Microsoft Edge @@ -35,18 +36,18 @@ body: - type: input attributes: label: Version - description: What version were you using? + description: What version are you using? placeholder: ex. 0.4.1 validations: required: true - type: markdown attributes: - value: "## Describe the issue." + value: "## Describe your bug." - type: markdown attributes: - value: "### Please do not report issues from other engines. These must be reported in their repositories." + value: "### Please do not report issues from other engines. These must be reported in their respective repositories." - type: markdown attributes: From ce24a6f7a3d5bfcc3eee48193c1972c052922a94 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Wed, 10 Jul 2024 18:42:25 -0700 Subject: [PATCH 441/870] Tweak Enhancement Template --- .github/ISSUE_TEMPLATE/enhancement.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/enhancement.yml b/.github/ISSUE_TEMPLATE/enhancement.yml index 327a91fec..c3ac345db 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.yml +++ b/.github/ISSUE_TEMPLATE/enhancement.yml @@ -7,8 +7,8 @@ body: attributes: label: Issue Checklist options: - - label: I have properly named the issue - - label: I looked in issues/discussions, if it has been previously reported + - label: I have properly named the enhancement + - label: I have checked the issues/discussions pages to see if the enhancement has been previously suggested - type: textarea attributes: From 0f35618a1597e599c4ff1804baf716831d91c035 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Wed, 10 Jul 2024 18:43:15 -0700 Subject: [PATCH 442/870] PR template tweak --- .github/pull_request_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index b1bd09a8f..8e8a45e19 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -3,4 +3,4 @@ ## Briefly describe the issue(s) fixed. -## Screenshots/Videos +## Include any relevant screenshots or videos. From ca5e08f967d3aa43a34895170b3c97aa04794cba Mon Sep 17 00:00:00 2001 From: Hundrec Date: Wed, 10 Jul 2024 18:47:34 -0700 Subject: [PATCH 443/870] Specify crash log location --- .github/ISSUE_TEMPLATE/crash.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/crash.yml b/.github/ISSUE_TEMPLATE/crash.yml index 74d2d628f..7690e8308 100644 --- a/.github/ISSUE_TEMPLATE/crash.yml +++ b/.github/ISSUE_TEMPLATE/crash.yml @@ -65,6 +65,6 @@ body: - type: textarea attributes: - label: Crash Logs (can be found in the crash folder) + label: Crash logs (can be found in the logs folder where Funkin.exe is) validations: required: true From ffadce45e0901ec8ef9f19e5ac1b9047867fd790 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Wed, 10 Jul 2024 18:50:12 -0700 Subject: [PATCH 444/870] More crash report tweaks --- .github/ISSUE_TEMPLATE/crash.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/crash.yml b/.github/ISSUE_TEMPLATE/crash.yml index 7690e8308..c5240495d 100644 --- a/.github/ISSUE_TEMPLATE/crash.yml +++ b/.github/ISSUE_TEMPLATE/crash.yml @@ -1,7 +1,7 @@ name: Crash Report description: Report a crash that occurred while playing the game. labels: ["type: major bug", "status: pending triage"] -title: "Crash: " +title: "Crash Report: " body: - type: checkboxes attributes: @@ -55,7 +55,7 @@ body: - type: textarea attributes: - label: Context (Provide images, videos, etc. of the crash happening) + label: Context (Provide screenshots or videos of the crash happening) - type: textarea attributes: From 6698ee6770aa2525c861d8966e259f4f62777dd1 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Wed, 10 Jul 2024 20:31:06 -0700 Subject: [PATCH 445/870] . --- .github/ISSUE_TEMPLATE/enhancement.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/enhancement.yml b/.github/ISSUE_TEMPLATE/enhancement.yml index c3ac345db..816e4a12b 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.yml +++ b/.github/ISSUE_TEMPLATE/enhancement.yml @@ -1,5 +1,5 @@ name: Enhancement -description: Suggest a new feature +description: Suggest a new feature. labels: ["type: enhancement", "status: pending triage"] title: "Enhancement: " body: From 25a90d841980c29e4007ce12818c294db431557e Mon Sep 17 00:00:00 2001 From: Hundrec Date: Wed, 10 Jul 2024 20:33:12 -0700 Subject: [PATCH 446/870] Reword in crash report --- .github/ISSUE_TEMPLATE/crash.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/crash.yml b/.github/ISSUE_TEMPLATE/crash.yml index c5240495d..6fb7c9437 100644 --- a/.github/ISSUE_TEMPLATE/crash.yml +++ b/.github/ISSUE_TEMPLATE/crash.yml @@ -43,7 +43,7 @@ body: - type: markdown attributes: - value: "## Describe your bug." + value: "## Describe your issue." - type: markdown attributes: From 2fb55ba3edf4e84a46dc6e451922af0a2ca63326 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Thu, 11 Jul 2024 06:59:22 +0200 Subject: [PATCH 447/870] Fix default health icon not used --- source/funkin/play/components/HealthIcon.hx | 29 +++++++-------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/source/funkin/play/components/HealthIcon.hx b/source/funkin/play/components/HealthIcon.hx index 2442b0dc5..682334db3 100644 --- a/source/funkin/play/components/HealthIcon.hx +++ b/source/funkin/play/components/HealthIcon.hx @@ -33,7 +33,7 @@ class HealthIcon extends FunkinSprite * The character this icon is representing. * Setting this variable will automatically update the graphic. */ - public var characterId(default, set):Null; + public var characterId(default, set):String = Constants.DEFAULT_HEALTH_ICON; /** * Whether this health icon should automatically update its state based on the character's health. @@ -116,7 +116,7 @@ class HealthIcon extends FunkinSprite */ static final POSITION_OFFSET:Int = 26; - public function new(char:String = 'bf', playerId:Int = 0) + public function new(char:Null, playerId:Int = 0) { super(0, 0); this.playerId = playerId; @@ -127,7 +127,7 @@ class HealthIcon extends FunkinSprite initTargetSize(); } - function set_characterId(value:Null):Null + function set_characterId(value:Null):String { if (value == characterId) return value; @@ -380,20 +380,9 @@ class HealthIcon extends FunkinSprite } } - function correctCharacterId(charId:Null):String + function iconExists(charId:String):Bool { - if (charId == null) - { - return Constants.DEFAULT_HEALTH_ICON; - } - - if (!Assets.exists(Paths.image('icons/icon-$charId'))) - { - FlxG.log.warn('No icon for character: $charId : using default placeholder face instead!'); - return Constants.DEFAULT_HEALTH_ICON; - } - - return charId; + return Assets.exists(Paths.image('icons/icon-$charId')); } function isNewSpritesheet(charId:String):Bool @@ -403,11 +392,11 @@ class HealthIcon extends FunkinSprite function loadCharacter(charId:Null):Void { - if (charId == null || correctCharacterId(charId) != charId) + if (charId == null || !iconExists(charId)) { - // This will recursively trigger loadCharacter to be called again. - characterId = correctCharacterId(charId); - return; + FlxG.log.warn('No icon for character: $charId : using default placeholder face instead!'); + characterId = Constants.DEFAULT_HEALTH_ICON; + charId = characterId; } isLegacyStyle = !isNewSpritesheet(charId); From 4044a7d9360a391c59878bbca65ab65e5b69e16d Mon Sep 17 00:00:00 2001 From: Hundrec Date: Fri, 14 Jun 2024 21:52:52 -0700 Subject: [PATCH 448/870] Reorder download Git step in compiling guide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moved “download Git” from the middle of the guide to the setup step Should prevent errors with Git before installing Git --- docs/COMPILING.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index e7c19875a..b8ddee4a7 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -2,14 +2,14 @@ 0. Setup - Download Haxe from [Haxe.org](https://haxe.org) + - Download Git from [git-scm.com](https://www.git-scm.com) 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. 2. Install `hmm` (run `haxelib --global install hmm` and then `haxelib --global run hmm 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 +3. Install all haxelibs of the current branch by running `hmm install` +4. Setup lime: `haxelib run lime setup` +5. 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 @@ -17,8 +17,8 @@ - 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 -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). +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 From 562136ed554d73e04a015c32f9cb34b790b9cc07 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Sat, 15 Jun 2024 13:37:21 -0400 Subject: [PATCH 449/870] Add ZIP button warning and restructured sentences Each step should be easier to follow with this structure --- docs/COMPILING.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index b8ddee4a7..b2a106c86 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -3,12 +3,13 @@ 0. Setup - Download Haxe from [Haxe.org](https://haxe.org) - Download Git from [git-scm.com](https://www.git-scm.com) -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. -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` + - Do NOT download the repository using the Download ZIP button on GitHub or you may run into errors! + - Instead, open a command prompt and do the following steps... +1. Run `git clone --recurse-submodules https://github.com/FunkinCrew/funkin.git` to clone the repository with the necessary assets submodule + - _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. Run `haxelib --global install hmm` and then `haxelib --global run hmm setup` to install hmm.json +3. Run `hmm install` to install all haxelibs of the current branch +4. Run `haxelib run lime setup` to set up lime 5. 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: From 6e65996180de85c42b74f6730773975f819e2efa Mon Sep 17 00:00:00 2001 From: Eric Date: Sun, 16 Jun 2024 18:48:01 -0400 Subject: [PATCH 450/870] Make downloading the assets submodule a separate step. --- docs/COMPILING.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index b2a106c86..cc90bd348 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -5,8 +5,9 @@ - Download Git from [git-scm.com](https://www.git-scm.com) - Do NOT download the repository using the Download ZIP button on GitHub or you may run into errors! - Instead, open a command prompt and do the following steps... -1. Run `git clone --recurse-submodules https://github.com/FunkinCrew/funkin.git` to clone the repository with the necessary assets submodule - - _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._ +1. Run `git clone https://github.com/FunkinCrew/funkin.git` to clone the base repository. +2. Run `git submodule update --init --recursive` to download the game's assets. + - NOTE: By performing this operation, you are downloading Content which is proprietary and protected by national and international copyright and trademark laws. See [the LICENSE.md file for the Funkin.assets](https://github.com/FunkinCrew/funkin.assets/blob/main/LICENSE.md) repo for more information. 2. Run `haxelib --global install hmm` and then `haxelib --global run hmm setup` to install hmm.json 3. Run `hmm install` to install all haxelibs of the current branch 4. Run `haxelib run lime setup` to set up lime From 3f63bc35a4f27a51f07a5c1ac8053de2512d1757 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 25 Jun 2024 18:22:30 -0400 Subject: [PATCH 451/870] Add change counts labels to Actions labeler --- .github/changed-lines-count-labeler.yml | 12 ++++++++++++ .github/workflows/labeler.yml | 15 ++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 .github/changed-lines-count-labeler.yml diff --git a/.github/changed-lines-count-labeler.yml b/.github/changed-lines-count-labeler.yml new file mode 100644 index 000000000..6f890f534 --- /dev/null +++ b/.github/changed-lines-count-labeler.yml @@ -0,0 +1,12 @@ +# Add 'small' to any changes below 10 lines +small: + max: 9 + +# Add 'medium' to any changes between 10 and 100 lines +medium: + min: 10 + max: 99 + +# Add 'large' to any changes for more than 100 lines +large: + min: 100 diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 0bcc420d3..a861af578 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -9,6 +9,19 @@ jobs: pull-requests: write runs-on: ubuntu-latest steps: - - uses: actions/labeler@v5 + - name: Set basic labels + uses: actions/labeler@v5 with: sync-labels: true + changed-lines-count-labeler: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + name: An action for automatically labelling pull requests based on the changed lines count + steps: + - name: Set change count labels + uses: vkirilichev/changed-lines-count-labeler@v0.2 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + configuration-path: .github/changed-lines-count-labeler.yml From 7b9e4a054284dbe6e69c1659e04571247276a599 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Wed, 10 Jul 2024 00:23:06 +0200 Subject: [PATCH 452/870] Fix F5 chart not reloading --- source/funkin/play/PlayState.hx | 59 ++----------------- source/funkin/ui/MusicBeatState.hx | 7 +-- source/funkin/ui/MusicBeatSubState.hx | 5 +- .../util/plugins/ReloadAssetsDebugPlugin.hx | 14 ++++- 4 files changed, 17 insertions(+), 68 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index a4723611e..86e8e0241 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1347,64 +1347,13 @@ class PlayState extends MusicBeatSubState } /** - * Removes any references to the current stage, then clears the stage cache, - * then reloads all the stages. - * - * This is useful for when you want to edit a stage without reloading the whole game. - * Reloading works on both the JSON and the HXC, if applicable. - * * Call this by pressing F5 on a debug build. */ - override function debug_refreshModules():Void + override function reloadAssets():Void { - // Prevent further gameplay updates, which will try to reference dead objects. - criticalFailure = true; - - // Remove the current stage. If the stage gets deleted while it's still in use, - // it'll probably crash the game or something. - if (this.currentStage != null) - { - remove(currentStage); - var event:ScriptEvent = new ScriptEvent(DESTROY, false); - ScriptEventDispatcher.callEvent(currentStage, event); - currentStage = null; - } - - if (!overrideMusic) - { - // Stop the instrumental. - if (FlxG.sound.music != null) - { - FlxG.sound.music.destroy(); - FlxG.sound.music = null; - } - - // Stop the vocals. - if (vocals != null && vocals.exists) - { - vocals.destroy(); - vocals = null; - } - } - else - { - // Stop the instrumental. - if (FlxG.sound.music != null) - { - FlxG.sound.music.stop(); - } - - // Stop the vocals. - if (vocals != null && vocals.exists) - { - vocals.stop(); - } - } - - super.debug_refreshModules(); - - var event:ScriptEvent = new ScriptEvent(CREATE, false); - ScriptEventDispatcher.callEvent(currentSong, event); + funkin.modding.PolymodHandler.forceReloadAssets(); + lastParams.targetSong = SongRegistry.instance.fetchEntry(currentSong.id); + LoadingState.loadPlayState(lastParams); } override function stepHit():Bool diff --git a/source/funkin/ui/MusicBeatState.hx b/source/funkin/ui/MusicBeatState.hx index 92169df75..8668b64c1 100644 --- a/source/funkin/ui/MusicBeatState.hx +++ b/source/funkin/ui/MusicBeatState.hx @@ -78,9 +78,6 @@ class MusicBeatState extends FlxTransitionableState implements IEventHandler { // Emergency exit button. if (FlxG.keys.justPressed.F4) FlxG.switchState(() -> new MainMenuState()); - - // This can now be used in EVERY STATE YAY! - if (FlxG.keys.justPressed.F5) debug_refreshModules(); } override function update(elapsed:Float) @@ -114,12 +111,10 @@ class MusicBeatState extends FlxTransitionableState implements IEventHandler ModuleHandler.callEvent(event); } - function debug_refreshModules() + function reloadAssets() { PolymodHandler.forceReloadAssets(); - this.destroy(); - // Create a new instance of the current state, so old data is cleared. FlxG.resetState(); } diff --git a/source/funkin/ui/MusicBeatSubState.hx b/source/funkin/ui/MusicBeatSubState.hx index 9035d12ff..5c40b37bc 100644 --- a/source/funkin/ui/MusicBeatSubState.hx +++ b/source/funkin/ui/MusicBeatSubState.hx @@ -72,9 +72,6 @@ class MusicBeatSubState extends FlxSubState implements IEventHandler // Emergency exit button. if (FlxG.keys.justPressed.F4) FlxG.switchState(() -> new MainMenuState()); - // This can now be used in EVERY STATE YAY! - if (FlxG.keys.justPressed.F5) debug_refreshModules(); - // Display Conductor info in the watch window. FlxG.watch.addQuick("musicTime", FlxG.sound.music?.time ?? 0.0); Conductor.watchQuick(conductorInUse); @@ -82,7 +79,7 @@ class MusicBeatSubState extends FlxSubState implements IEventHandler dispatchEvent(new UpdateScriptEvent(elapsed)); } - function debug_refreshModules() + function reloadAssets() { PolymodHandler.forceReloadAssets(); diff --git a/source/funkin/util/plugins/ReloadAssetsDebugPlugin.hx b/source/funkin/util/plugins/ReloadAssetsDebugPlugin.hx index f69609531..0e1e238ac 100644 --- a/source/funkin/util/plugins/ReloadAssetsDebugPlugin.hx +++ b/source/funkin/util/plugins/ReloadAssetsDebugPlugin.hx @@ -1,6 +1,9 @@ package funkin.util.plugins; +import flixel.FlxG; import flixel.FlxBasic; +import funkin.ui.MusicBeatState; +import funkin.ui.MusicBeatSubState; /** * A plugin which adds functionality to press `F5` to reload all game assets, then reload the current state. @@ -28,10 +31,15 @@ class ReloadAssetsDebugPlugin extends FlxBasic if (FlxG.keys.justPressed.F5) #end { - funkin.modding.PolymodHandler.forceReloadAssets(); + var state:Dynamic = FlxG.state; + if (state is MusicBeatState || state is MusicBeatSubState) state.reloadAssets(); + else + { + funkin.modding.PolymodHandler.forceReloadAssets(); - // Create a new instance of the current state, so old data is cleared. - FlxG.resetState(); + // Create a new instance of the current state, so old data is cleared. + FlxG.resetState(); + } } } From a12b0e6ec36c45f0ec2c1516826cdfde2b8899e6 Mon Sep 17 00:00:00 2001 From: anysad Date: Thu, 11 Jul 2024 18:10:45 +0300 Subject: [PATCH 453/870] Add HEY! song events to Tutorial --- source/funkin/play/PlayState.hx | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index f55cef388..ff55a79fd 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1489,7 +1489,7 @@ class PlayState extends MusicBeatSubState if (opponentStrumline != null) opponentStrumline.onBeatHit(); // Make the characters dance on the beat - danceOnBeat(); + //danceOnBeat(); return true; } @@ -1509,16 +1509,6 @@ class PlayState extends MusicBeatSubState function danceOnBeat():Void { if (currentStage == null) return; - - // TODO: Add HEY! song events to Tutorial. - if (Conductor.instance.currentBeat % 16 == 15 - && currentStage.getDad().characterId == 'gf' - && Conductor.instance.currentBeat > 16 - && Conductor.instance.currentBeat < 48) - { - currentStage.getBoyfriend().playAnimation('hey', true); - currentStage.getDad().playAnimation('cheer', true); - } } /** From 47a2cf4e5db9a36fb39e49500d85d2aca3961a06 Mon Sep 17 00:00:00 2001 From: anysad Date: Thu, 11 Jul 2024 18:12:50 +0300 Subject: [PATCH 454/870] Add HEY! song events to Tutorial --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 2e1594ee4..9ef18cde0 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 2e1594ee4c04c7148628bae471bdd061c9deb6b7 +Subproject commit 9ef18cde0b9802295118b922b76b851e96af2fbf From cfb2cf36de0eb77f14412506f090cf16250ecdc2 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 11 Jul 2024 18:38:29 -0400 Subject: [PATCH 455/870] assets submod merge --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 1c9c0986e..e0d719c18 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 1c9c0986e5eb0a7b5faa81ecacc158d20429720d +Subproject commit e0d719c18f87c762e09b054123bb99e4b5f7fcd3 From 66b103c65030706d7a6b3f586df5026a19314450 Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 11 Jul 2024 19:34:34 -0400 Subject: [PATCH 456/870] [PUBLIC PR] Remove 5 duplicate audio files from the DadBattle folder. (#657) * Remove 5 duplicate audio files from the DadBattle folder. * assets submod merge --------- Co-authored-by: Cameron Taylor --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index e0d719c18..361f696ce 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit e0d719c18f87c762e09b054123bb99e4b5f7fcd3 +Subproject commit 361f696cec5c4027ebcfa6f7cec5ba718eaab0d2 From 71947c581e78891233dd2c97cbe60d5cdc23d8b5 Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 11 Jul 2024 19:35:41 -0400 Subject: [PATCH 457/870] [PUBLIC PR] Fix a bug where the memory counter would overflow into the negatives (#662) * get Float instead of Int in cpp (Float is 64-bit in so it works easier than Int64) * use Math.fround instead of Math.round --------- Co-authored-by: Karim Akra <144803230+KarimAkra@users.noreply.github.com> --- source/funkin/ui/debug/MemoryCounter.hx | 2 +- source/funkin/util/MemoryUtil.hx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/funkin/ui/debug/MemoryCounter.hx b/source/funkin/ui/debug/MemoryCounter.hx index b25b55645..50421f398 100644 --- a/source/funkin/ui/debug/MemoryCounter.hx +++ b/source/funkin/ui/debug/MemoryCounter.hx @@ -36,7 +36,7 @@ class MemoryCounter extends TextField @:noCompletion #if !flash override #end function __enterFrame(deltaTime:Float):Void { - var mem:Float = Math.round(MemoryUtil.getMemoryUsed() / BYTES_PER_MEG / ROUND_TO) * ROUND_TO; + var mem:Float = Math.fround(MemoryUtil.getMemoryUsed() / BYTES_PER_MEG / ROUND_TO) * ROUND_TO; if (mem > memPeak) memPeak = mem; diff --git a/source/funkin/util/MemoryUtil.hx b/source/funkin/util/MemoryUtil.hx index f5935ed67..18fd41472 100644 --- a/source/funkin/util/MemoryUtil.hx +++ b/source/funkin/util/MemoryUtil.hx @@ -48,11 +48,11 @@ class MemoryUtil * Calculate the total memory usage of the program, in bytes. * @return Int */ - public static function getMemoryUsed():Int + public static function getMemoryUsed():#if cpp Float #else Int #end { #if cpp // There is also Gc.MEM_INFO_RESERVED, MEM_INFO_CURRENT, and MEM_INFO_LARGE. - return cpp.vm.Gc.memInfo(cpp.vm.Gc.MEM_INFO_USAGE); + return cpp.vm.Gc.memInfo64(cpp.vm.Gc.MEM_INFO_USAGE); #else return openfl.system.System.totalMemory; #end From 261d68c410777e97a44b4ba13ca0495957765c13 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 11 Jul 2024 19:51:00 -0400 Subject: [PATCH 458/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 240d0ff1d..005c96f85 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 240d0ff1dafd616551e6b6a2b048b7b6f602ac75 +Subproject commit 005c96f85f4304865acb196e7cc4d6d83f9d76d8 From 18b795d4f74e81e8f9bbabd3e3e3e0fe7930a167 Mon Sep 17 00:00:00 2001 From: anysad Date: Thu, 11 Jul 2024 18:10:45 +0300 Subject: [PATCH 459/870] Add HEY! song events to Tutorial --- source/funkin/play/PlayState.hx | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 8d7d82aab..216acca71 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1502,7 +1502,7 @@ class PlayState extends MusicBeatSubState if (opponentStrumline != null) opponentStrumline.onBeatHit(); // Make the characters dance on the beat - danceOnBeat(); + //danceOnBeat(); return true; } @@ -1522,16 +1522,6 @@ class PlayState extends MusicBeatSubState function danceOnBeat():Void { if (currentStage == null) return; - - // TODO: Add HEY! song events to Tutorial. - if (Conductor.instance.currentBeat % 16 == 15 - && currentStage.getDad().characterId == 'gf' - && Conductor.instance.currentBeat > 16 - && Conductor.instance.currentBeat < 48) - { - currentStage.getBoyfriend().playAnimation('hey', true); - currentStage.getDad().playAnimation('cheer', true); - } } /** From 305ab3146fe8891e925d34f5f2aafd9006ce1288 Mon Sep 17 00:00:00 2001 From: anysad Date: Thu, 11 Jul 2024 18:12:50 +0300 Subject: [PATCH 460/870] Add HEY! song events to Tutorial --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 005c96f85..81e61c287 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 005c96f85f4304865acb196e7cc4d6d83f9d76d8 +Subproject commit 81e61c287670f6aa8b7faf2c27561df57361f1ad From 4a7545a0dbdf7e8e1f1acca59940c87d59151646 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 11 Jul 2024 21:45:06 -0400 Subject: [PATCH 461/870] Remove empty function. --- source/funkin/play/PlayState.hx | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 216acca71..309c21438 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1501,9 +1501,6 @@ class PlayState extends MusicBeatSubState if (playerStrumline != null) playerStrumline.onBeatHit(); if (opponentStrumline != null) opponentStrumline.onBeatHit(); - // Make the characters dance on the beat - //danceOnBeat(); - return true; } @@ -1514,16 +1511,6 @@ class PlayState extends MusicBeatSubState super.destroy(); } - /** - * Handles characters dancing to the beat of the current song. - * - * TODO: Move some of this logic into `Bopper.hx`, or individual character scripts. - */ - function danceOnBeat():Void - { - if (currentStage == null) return; - } - /** * Initializes the game and HUD cameras. */ From 90155bcfbfa86561571b7c556b1f63486c18877d Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Wed, 10 Jul 2024 01:26:16 +0200 Subject: [PATCH 462/870] ChartEditor Live Input Code Refactor + 6 key fix --- .../ui/debug/charting/ChartEditorState.hx | 57 ++++++------------- 1 file changed, 18 insertions(+), 39 deletions(-) diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index f72cca77f..5e7493840 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -282,6 +282,21 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState */ public static final WELCOME_MUSIC_FADE_IN_DURATION:Float = 10.0; + /** + * A map of the keys for every live input style. + */ + public static final LIVE_INPUT_KEYS:Map> = [ + NumberKeys => [ + FIVE, SIX, SEVEN, EIGHT, + ONE, TWO, THREE, FOUR + ], + WASDKeys => [ + LEFT, DOWN, UP, RIGHT, + A, S, W, D + ], + None => [] + ]; + /** * INSTANCE DATA */ @@ -5129,46 +5144,10 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState function handlePlayhead():Void { // Place notes at the playhead with the keyboard. - switch (currentLiveInputStyle) + for (note => key in LIVE_INPUT_KEYS[currentLiveInputStyle]) { - case ChartEditorLiveInputStyle.WASDKeys: - if (FlxG.keys.justPressed.A) placeNoteAtPlayhead(4); - if (FlxG.keys.justReleased.A) finishPlaceNoteAtPlayhead(4); - if (FlxG.keys.justPressed.S) placeNoteAtPlayhead(5); - if (FlxG.keys.justReleased.S) finishPlaceNoteAtPlayhead(5); - if (FlxG.keys.justPressed.W) placeNoteAtPlayhead(6); - if (FlxG.keys.justReleased.W) finishPlaceNoteAtPlayhead(6); - if (FlxG.keys.justPressed.D) placeNoteAtPlayhead(7); - if (FlxG.keys.justReleased.D) finishPlaceNoteAtPlayhead(7); - - if (FlxG.keys.justPressed.LEFT) placeNoteAtPlayhead(0); - if (FlxG.keys.justReleased.LEFT) finishPlaceNoteAtPlayhead(0); - if (FlxG.keys.justPressed.DOWN) placeNoteAtPlayhead(1); - if (FlxG.keys.justReleased.DOWN) finishPlaceNoteAtPlayhead(1); - if (FlxG.keys.justPressed.UP) placeNoteAtPlayhead(2); - if (FlxG.keys.justReleased.UP) finishPlaceNoteAtPlayhead(2); - if (FlxG.keys.justPressed.RIGHT) placeNoteAtPlayhead(3); - if (FlxG.keys.justReleased.RIGHT) finishPlaceNoteAtPlayhead(3); - case ChartEditorLiveInputStyle.NumberKeys: - // Flipped because Dad is on the left but represents data 0-3. - if (FlxG.keys.justPressed.ONE) placeNoteAtPlayhead(4); - if (FlxG.keys.justReleased.ONE) finishPlaceNoteAtPlayhead(4); - if (FlxG.keys.justPressed.TWO) placeNoteAtPlayhead(5); - if (FlxG.keys.justReleased.TWO) finishPlaceNoteAtPlayhead(5); - if (FlxG.keys.justPressed.THREE) placeNoteAtPlayhead(6); - if (FlxG.keys.justReleased.THREE) finishPlaceNoteAtPlayhead(6); - if (FlxG.keys.justPressed.FOUR) placeNoteAtPlayhead(7); - if (FlxG.keys.justReleased.FOUR) finishPlaceNoteAtPlayhead(7); - - if (FlxG.keys.justPressed.FIVE) placeNoteAtPlayhead(0); - if (FlxG.keys.justReleased.FIVE) finishPlaceNoteAtPlayhead(0); - if (FlxG.keys.justPressed.SIX) placeNoteAtPlayhead(1); - if (FlxG.keys.justPressed.SEVEN) placeNoteAtPlayhead(2); - if (FlxG.keys.justReleased.SEVEN) finishPlaceNoteAtPlayhead(2); - if (FlxG.keys.justPressed.EIGHT) placeNoteAtPlayhead(3); - if (FlxG.keys.justReleased.EIGHT) finishPlaceNoteAtPlayhead(3); - case ChartEditorLiveInputStyle.None: - // Do nothing. + if (FlxG.keys.checkStatus(key, JUST_PRESSED)) placeNoteAtPlayhead(note) + else if (FlxG.keys.checkStatus(key, JUST_RELEASED)) finishPlaceNoteAtPlayhead(note); } // Place events at playhead. From 17f5a06256b34ff5224fde5b893cdac7c5086a5f Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Mon, 20 May 2024 02:56:57 +0200 Subject: [PATCH 463/870] Add camOther to fix zooms on pause and stickers --- source/funkin/play/PlayState.hx | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 8d7d82aab..e87fde90c 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -503,9 +503,9 @@ class PlayState extends MusicBeatSubState public var camGame:FlxCamera; /** - * The camera which contains, and controls visibility of, a video cutscene. + * The camera which contains, and controls visibility of, a video cutscene, dialogue, pause menu and sticker transition. */ - public var camCutscene:FlxCamera; + public var camOther:FlxCamera; /** * The combo popups. Includes the real-time combo counter and the rating. @@ -975,7 +975,7 @@ class PlayState extends MusicBeatSubState FlxTransitionableState.skipNextTransIn = true; FlxTransitionableState.skipNextTransOut = true; - pauseSubState.camera = camHUD; + pauseSubState.camera = camOther; openSubState(pauseSubState); // boyfriendPos.put(); // TODO: Why is this here? } @@ -1543,12 +1543,12 @@ class PlayState extends MusicBeatSubState camGame.bgColor = BACKGROUND_COLOR; // Show a pink background behind the stage. camHUD = new FlxCamera(); camHUD.bgColor.alpha = 0; // Show the game scene behind the camera. - camCutscene = new FlxCamera(); - camCutscene.bgColor.alpha = 0; // Show the game scene behind the camera. + camOther = new FlxCamera(); + camOther.bgColor.alpha = 0; // Show the game scene behind the camera. FlxG.cameras.reset(camGame); FlxG.cameras.add(camHUD, false); - FlxG.cameras.add(camCutscene, false); + FlxG.cameras.add(camOther, false); // Configure camera follow point. if (previousCameraFollowPoint != null) @@ -1934,7 +1934,6 @@ class PlayState extends MusicBeatSubState if (!result) return; isInCutscene = false; - camCutscene.visible = false; // TODO: Maybe tween in the camera after any cutscenes. camHUD.visible = true; @@ -1953,7 +1952,7 @@ class PlayState extends MusicBeatSubState if (!currentConversation.alive) currentConversation.revive(); currentConversation.completeCallback = onConversationComplete; - currentConversation.cameras = [camCutscene]; + currentConversation.cameras = [camOther]; currentConversation.zIndex = 1000; add(currentConversation); refresh(); @@ -2788,7 +2787,7 @@ class PlayState extends MusicBeatSubState persistentUpdate = false; FlxTransitionableState.skipNextTransIn = true; FlxTransitionableState.skipNextTransOut = true; - pauseSubState.camera = camCutscene; + pauseSubState.camera = camOther; openSubState(pauseSubState); } } @@ -2804,7 +2803,7 @@ class PlayState extends MusicBeatSubState persistentUpdate = false; FlxTransitionableState.skipNextTransIn = true; FlxTransitionableState.skipNextTransOut = true; - pauseSubState.camera = camCutscene; + pauseSubState.camera = camOther; openSubState(pauseSubState); } } From e23e6c160d9ed9243a380c4b6842a059a3954768 Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Mon, 20 May 2024 23:52:45 +0200 Subject: [PATCH 464/870] Fix references to camCutscene --- source/funkin/play/cutscene/VideoCutscene.hx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/source/funkin/play/cutscene/VideoCutscene.hx b/source/funkin/play/cutscene/VideoCutscene.hx index abbcd4f54..7dac97885 100644 --- a/source/funkin/play/cutscene/VideoCutscene.hx +++ b/source/funkin/play/cutscene/VideoCutscene.hx @@ -81,12 +81,11 @@ class VideoCutscene // Trigger the cutscene. Don't play the song in the background. PlayState.instance.isInCutscene = true; PlayState.instance.camHUD.visible = false; - PlayState.instance.camCutscene.visible = true; // Display a black screen to hide the game while the video is playing. blackScreen = new FlxSprite(-200, -200).makeGraphic(FlxG.width * 2, FlxG.height * 2, FlxColor.BLACK); blackScreen.scrollFactor.set(0, 0); - blackScreen.cameras = [PlayState.instance.camCutscene]; + blackScreen.cameras = [PlayState.instance.camOther]; PlayState.instance.add(blackScreen); VideoCutscene.cutsceneType = cutsceneType; @@ -120,7 +119,7 @@ class VideoCutscene vid.finishCallback = finishVideo.bind(0.5); - vid.cameras = [PlayState.instance.camCutscene]; + vid.cameras = [PlayState.instance.camOther]; PlayState.instance.add(vid); @@ -147,7 +146,7 @@ class VideoCutscene vid.bitmap.onEndReached.add(finishVideo.bind(0.5)); vid.autoPause = FlxG.autoPause; - vid.cameras = [PlayState.instance.camCutscene]; + vid.cameras = [PlayState.instance.camOther]; PlayState.instance.add(vid); @@ -305,7 +304,6 @@ class VideoCutscene vid = null; #end - PlayState.instance.camCutscene.visible = true; PlayState.instance.camHUD.visible = true; FlxTween.tween(blackScreen, {alpha: 0}, transitionTime, From e6c97678002e1b4ba823b71471ec0d6052d96c0a Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Wed, 12 Jun 2024 00:34:04 +0200 Subject: [PATCH 465/870] Revert camCutscene rename --- source/funkin/play/PlayState.hx | 16 ++++++++-------- source/funkin/play/cutscene/VideoCutscene.hx | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index e87fde90c..0bb57b8cb 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -505,7 +505,7 @@ class PlayState extends MusicBeatSubState /** * The camera which contains, and controls visibility of, a video cutscene, dialogue, pause menu and sticker transition. */ - public var camOther:FlxCamera; + public var camCutscene:FlxCamera; /** * The combo popups. Includes the real-time combo counter and the rating. @@ -975,7 +975,7 @@ class PlayState extends MusicBeatSubState FlxTransitionableState.skipNextTransIn = true; FlxTransitionableState.skipNextTransOut = true; - pauseSubState.camera = camOther; + pauseSubState.camera = camCutscene; openSubState(pauseSubState); // boyfriendPos.put(); // TODO: Why is this here? } @@ -1543,12 +1543,12 @@ class PlayState extends MusicBeatSubState camGame.bgColor = BACKGROUND_COLOR; // Show a pink background behind the stage. camHUD = new FlxCamera(); camHUD.bgColor.alpha = 0; // Show the game scene behind the camera. - camOther = new FlxCamera(); - camOther.bgColor.alpha = 0; // Show the game scene behind the camera. + camCutscene = new FlxCamera(); + camCutscene.bgColor.alpha = 0; // Show the game scene behind the camera. FlxG.cameras.reset(camGame); FlxG.cameras.add(camHUD, false); - FlxG.cameras.add(camOther, false); + FlxG.cameras.add(camCutscene, false); // Configure camera follow point. if (previousCameraFollowPoint != null) @@ -1952,7 +1952,7 @@ class PlayState extends MusicBeatSubState if (!currentConversation.alive) currentConversation.revive(); currentConversation.completeCallback = onConversationComplete; - currentConversation.cameras = [camOther]; + currentConversation.cameras = [camCutscene]; currentConversation.zIndex = 1000; add(currentConversation); refresh(); @@ -2787,7 +2787,7 @@ class PlayState extends MusicBeatSubState persistentUpdate = false; FlxTransitionableState.skipNextTransIn = true; FlxTransitionableState.skipNextTransOut = true; - pauseSubState.camera = camOther; + pauseSubState.camera = camCutscene; openSubState(pauseSubState); } } @@ -2803,7 +2803,7 @@ class PlayState extends MusicBeatSubState persistentUpdate = false; FlxTransitionableState.skipNextTransIn = true; FlxTransitionableState.skipNextTransOut = true; - pauseSubState.camera = camOther; + pauseSubState.camera = camCutscene; openSubState(pauseSubState); } } diff --git a/source/funkin/play/cutscene/VideoCutscene.hx b/source/funkin/play/cutscene/VideoCutscene.hx index 7dac97885..60454b881 100644 --- a/source/funkin/play/cutscene/VideoCutscene.hx +++ b/source/funkin/play/cutscene/VideoCutscene.hx @@ -85,7 +85,7 @@ class VideoCutscene // Display a black screen to hide the game while the video is playing. blackScreen = new FlxSprite(-200, -200).makeGraphic(FlxG.width * 2, FlxG.height * 2, FlxColor.BLACK); blackScreen.scrollFactor.set(0, 0); - blackScreen.cameras = [PlayState.instance.camOther]; + blackScreen.cameras = [PlayState.instance.camCutscene]; PlayState.instance.add(blackScreen); VideoCutscene.cutsceneType = cutsceneType; @@ -119,7 +119,7 @@ class VideoCutscene vid.finishCallback = finishVideo.bind(0.5); - vid.cameras = [PlayState.instance.camOther]; + vid.cameras = [PlayState.instance.camCutscene]; PlayState.instance.add(vid); @@ -146,7 +146,7 @@ class VideoCutscene vid.bitmap.onEndReached.add(finishVideo.bind(0.5)); vid.autoPause = FlxG.autoPause; - vid.cameras = [PlayState.instance.camOther]; + vid.cameras = [PlayState.instance.camCutscene]; PlayState.instance.add(vid); From c3f8075b5f655b68e8dc7fb8615be3adc869ab7f Mon Sep 17 00:00:00 2001 From: gamerbross <55158797+gamerbross@users.noreply.github.com> Date: Sat, 15 Jun 2024 20:23:55 +0200 Subject: [PATCH 466/870] Few animation editor bugfixes --- hmm.json | 2 +- .../ui/debug/anim/DebugBoundingState.hx | 23 ++++++++++++------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/hmm.json b/hmm.json index 8eaf24212..324c6d246 100644 --- a/hmm.json +++ b/hmm.json @@ -30,7 +30,7 @@ "name": "flixel-ui", "type": "git", "dir": null, - "ref": "719b4f10d94186ed55f6fef1b6618d32abec8c15", + "ref": "d0afed7293c71ffdb1184751317fc709b44c9056", "url": "https://github.com/HaxeFlixel/flixel-ui" }, { diff --git a/source/funkin/ui/debug/anim/DebugBoundingState.hx b/source/funkin/ui/debug/anim/DebugBoundingState.hx index 04784a5b7..d82bcc612 100644 --- a/source/funkin/ui/debug/anim/DebugBoundingState.hx +++ b/source/funkin/ui/debug/anim/DebugBoundingState.hx @@ -1,6 +1,7 @@ package funkin.ui.debug.anim; import flixel.addons.display.FlxGridOverlay; +import flixel.addons.display.FlxBackdrop; import flixel.addons.ui.FlxInputText; import flixel.addons.ui.FlxUIDropDownMenu; import flixel.FlxCamera; @@ -55,7 +56,7 @@ class DebugBoundingState extends FlxState TODAY'S TO-DO - Cleaner UI */ - var bg:FlxSprite; + var bg:FlxBackdrop; var fileInfo:FlxText; var txtGrp:FlxGroup; @@ -80,7 +81,7 @@ class DebugBoundingState extends FlxState { // get the screen position, according to the HUD camera, temp default to FlxG.camera juuust in case? var hudMousePos:FlxPoint = FlxG.mouse.getScreenPosition(hudCam ?? FlxG.camera); - return Screen.instance.hasSolidComponentUnderPoint(hudMousePos.x, hudMousePos.y); + return Screen.instance.hasSolidComponentUnderPoint(hudMousePos.x, hudMousePos.y) || FlxG.mouse.overlaps(animDropDownMenu, hudCam); } override function create() @@ -103,10 +104,7 @@ class DebugBoundingState extends FlxState hudCam = new FlxCamera(); hudCam.bgColor.alpha = 0; - bg = FlxGridOverlay.create(10, 10); - // bg = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.GREEN); - - bg.scrollFactor.set(); + bg = new FlxBackdrop(FlxGridOverlay.createGrid(10, 10, FlxG.width, FlxG.height, true, 0xffe7e6e6, 0xffd9d5d5)); add(bg); // we are setting this as the default draw camera only temporarily, to trick haxeui @@ -289,16 +287,20 @@ class DebugBoundingState extends FlxState public var mouseOffset:FlxPoint = FlxPoint.get(0, 0); public var oldPos:FlxPoint = FlxPoint.get(0, 0); + public var movingCharacter:Bool = false; function mouseOffsetMovement() { if (swagChar != null) { - if (FlxG.mouse.justPressed) + if (FlxG.mouse.justPressed && !haxeUIFocused) { + movingCharacter = true; mouseOffset.set(FlxG.mouse.x - -swagChar.animOffsets[0], FlxG.mouse.y - -swagChar.animOffsets[1]); } + if (!movingCharacter) return; + if (FlxG.mouse.pressed) { swagChar.animOffsets = [(FlxG.mouse.x - mouseOffset.x) * -1, (FlxG.mouse.y - mouseOffset.y) * -1]; @@ -307,6 +309,11 @@ class DebugBoundingState extends FlxState txtOffsetShit.text = 'Offset: ' + swagChar.animOffsets; } + + if (FlxG.mouse.justReleased) + { + movingCharacter = false; + } } } @@ -373,7 +380,7 @@ class DebugBoundingState extends FlxState offsetView.visible = true; offsetView.active = true; offsetControls(); - if (!haxeUIFocused) mouseOffsetMovement(); + mouseOffsetMovement(); } if (FlxG.keys.justPressed.H) hudCam.visible = !hudCam.visible; From 03d1f858ec19a8025cbcf3e63f7bf6e23c8ef46b Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 12 Jul 2024 00:57:08 -0400 Subject: [PATCH 467/870] Remove flixel-ui and add a new dropdown to the animation offset editor --- Project.xml | 3 - assets | 2 +- hmm.json | 9 +- .../funkin/modding/base/ScriptedFlxUIState.hx | 8 - .../ui/debug/anim/DebugBoundingState.hx | 162 +++++++++++------- source/funkin/ui/freeplay/FreeplayState.hx | 1 - 6 files changed, 101 insertions(+), 84 deletions(-) delete mode 100644 source/funkin/modding/base/ScriptedFlxUIState.hx diff --git a/Project.xml b/Project.xml index 8eb62bb1d..656590aec 100644 --- a/Project.xml +++ b/Project.xml @@ -114,11 +114,8 @@ xsi:schemaLocation="http://lime.openfl.org/project/1.0.4 http://lime.openfl.org/ - - - diff --git a/assets b/assets index 005c96f85..f3231b140 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 005c96f85f4304865acb196e7cc4d6d83f9d76d8 +Subproject commit f3231b1404f733c909f970d639fb11c56a7ca7f0 diff --git a/hmm.json b/hmm.json index 324c6d246..d7171dfb2 100644 --- a/hmm.json +++ b/hmm.json @@ -23,15 +23,10 @@ }, { "name": "flixel-text-input", - "type": "haxelib", - "version": "1.1.0" - }, - { - "name": "flixel-ui", "type": "git", "dir": null, - "ref": "d0afed7293c71ffdb1184751317fc709b44c9056", - "url": "https://github.com/HaxeFlixel/flixel-ui" + "ref": "951a0103a17bfa55eed86703ce50b4fb0d7590bc", + "url": "https://github.com/Starmapo/flixel-text-input" }, { "name": "flxanimate", diff --git a/source/funkin/modding/base/ScriptedFlxUIState.hx b/source/funkin/modding/base/ScriptedFlxUIState.hx deleted file mode 100644 index c58fc294f..000000000 --- a/source/funkin/modding/base/ScriptedFlxUIState.hx +++ /dev/null @@ -1,8 +0,0 @@ -package funkin.modding.base; - -/** - * A script that can be tied to an FlxUIState. - * Create a scripted class that extends FlxUIState to use this. - */ -@:hscriptClass -class ScriptedFlxUIState extends flixel.addons.ui.FlxUIState implements HScriptedClass {} diff --git a/source/funkin/ui/debug/anim/DebugBoundingState.hx b/source/funkin/ui/debug/anim/DebugBoundingState.hx index d82bcc612..ed2f5870f 100644 --- a/source/funkin/ui/debug/anim/DebugBoundingState.hx +++ b/source/funkin/ui/debug/anim/DebugBoundingState.hx @@ -1,9 +1,7 @@ package funkin.ui.debug.anim; -import flixel.addons.display.FlxGridOverlay; import flixel.addons.display.FlxBackdrop; -import flixel.addons.ui.FlxInputText; -import flixel.addons.ui.FlxUIDropDownMenu; +import flixel.addons.display.FlxGridOverlay; import flixel.FlxCamera; import flixel.FlxSprite; import flixel.FlxState; @@ -26,6 +24,7 @@ import funkin.util.MouseUtil; import funkin.util.SerializerUtil; import funkin.util.SortUtil; import haxe.ui.components.DropDown; +import haxe.ui.containers.dialogs.CollapsibleDialog; import haxe.ui.core.Component; import haxe.ui.core.Screen; import haxe.ui.events.ItemEvent; @@ -59,7 +58,7 @@ class DebugBoundingState extends FlxState var bg:FlxBackdrop; var fileInfo:FlxText; - var txtGrp:FlxGroup; + var txtGrp:FlxTypedGroup; var hudCam:FlxCamera; @@ -67,40 +66,34 @@ class DebugBoundingState extends FlxState var spriteSheetView:FlxGroup; var offsetView:FlxGroup; - var animDropDownMenu:FlxUIDropDownMenu; var dropDownSetup:Bool = false; var onionSkinChar:FlxSprite; var txtOffsetShit:FlxText; - var uiStuff:Component; + var offsetEditorDialog:CollapsibleDialog; + var offsetAnimationDropdown:DropDown; var haxeUIFocused(get, default):Bool = false; + var currentAnimationName(get, never):String; + + function get_currentAnimationName():String + { + return offsetAnimationDropdown?.value?.id ?? "idle"; + } + function get_haxeUIFocused():Bool { // get the screen position, according to the HUD camera, temp default to FlxG.camera juuust in case? var hudMousePos:FlxPoint = FlxG.mouse.getScreenPosition(hudCam ?? FlxG.camera); - return Screen.instance.hasSolidComponentUnderPoint(hudMousePos.x, hudMousePos.y) || FlxG.mouse.overlaps(animDropDownMenu, hudCam); + return Screen.instance.hasSolidComponentUnderPoint(hudMousePos.x, hudMousePos.y); } override function create() { Paths.setCurrentLevel('week1'); - // lv. - // lv.onChange = function(e:UIEvent) - // { - // trace(e.type); - // // trace(e.data.curView); - // // var item:haxe.ui.core.ItemRenderer = cast e.target; - // trace(e.target); - // // if (e.type == "change") - // // { - // // curView = cast e.data; - // // } - // }; - hudCam = new FlxCamera(); hudCam.bgColor.alpha = 0; @@ -111,20 +104,25 @@ class DebugBoundingState extends FlxState FlxG.cameras.add(hudCam); var str = Paths.xml('ui/animation-editor/offset-editor-view'); - uiStuff = RuntimeComponentBuilder.fromAsset(str); + offsetEditorDialog = cast RuntimeComponentBuilder.fromAsset(str); - // uiStuff.findComponent("btnViewSpriteSheet").onClick = _ -> curView = SPRITESHEET; - var dropdown:DropDown = cast uiStuff.findComponent("swapper"); - dropdown.onChange = function(e:UIEvent) { + // offsetEditorDialog.findComponent("btnViewSpriteSheet").onClick = _ -> curView = SPRITESHEET; + var viewDropdown:DropDown = offsetEditorDialog.findComponent("swapper", DropDown); + viewDropdown.onChange = function(e:UIEvent) { trace(e.type); curView = cast e.data.curView; trace(e.data); // trace(e.data); }; - uiStuff.cameras = [hudCam]; + offsetAnimationDropdown = offsetEditorDialog.findComponent("animationDropdown", DropDown); - add(uiStuff); + offsetEditorDialog.cameras = [hudCam]; + + add(offsetEditorDialog); + + // Anchor to the right side by default + // offsetEditorDialog.x = FlxG.width - offsetEditorDialog.width; // sets the default camera back to FlxG.camera, since we set it to hudCamera for haxeui stuf FlxG.cameras.setDefaultDrawTarget(FlxG.camera, true); @@ -157,7 +155,7 @@ class DebugBoundingState extends FlxState generateOutlines(tex.frames); - txtGrp = new FlxGroup(); + txtGrp = new FlxTypedGroup(); txtGrp.cameras = [hudCam]; spriteSheetView.add(txtGrp); @@ -258,15 +256,9 @@ class DebugBoundingState extends FlxState txtOffsetShit = new FlxText(20, 20, 0, "", 20); txtOffsetShit.setFormat(Paths.font("vcr.ttf"), 26, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); txtOffsetShit.cameras = [hudCam]; + txtOffsetShit.y = FlxG.height - 20 - txtOffsetShit.height; offsetView.add(txtOffsetShit); - animDropDownMenu = new FlxUIDropDownMenu(0, 0, FlxUIDropDownMenu.makeStrIdLabelArray(['weed'], true)); - animDropDownMenu.cameras = [hudCam]; - // Move to bottom right corner - animDropDownMenu.x = FlxG.width - animDropDownMenu.width - 20; - animDropDownMenu.y = FlxG.height - animDropDownMenu.height - 20; - offsetView.add(animDropDownMenu); - var characters:Array = CharacterDataParser.listCharacterIds(); characters = characters.filter(function(charId:String) { var char = CharacterDataParser.fetchCharacterData(charId); @@ -274,7 +266,7 @@ class DebugBoundingState extends FlxState }); characters.sort(SortUtil.alphabetically); - var charDropdown:DropDown = cast uiStuff.findComponent('characterDropdown'); + var charDropdown:DropDown = offsetEditorDialog.findComponent('characterDropdown', DropDown); for (char in characters) { charDropdown.dataSource.add({text: char}); @@ -305,9 +297,10 @@ class DebugBoundingState extends FlxState { swagChar.animOffsets = [(FlxG.mouse.x - mouseOffset.x) * -1, (FlxG.mouse.y - mouseOffset.y) * -1]; - swagChar.animationOffsets.set(animDropDownMenu.selectedLabel, swagChar.animOffsets); + swagChar.animationOffsets.set(offsetAnimationDropdown.value.id, swagChar.animOffsets); txtOffsetShit.text = 'Offset: ' + swagChar.animOffsets; + txtOffsetShit.y = FlxG.height - 20 - txtOffsetShit.height; } if (FlxG.mouse.justReleased) @@ -319,9 +312,14 @@ class DebugBoundingState extends FlxState function addInfo(str:String, value:Dynamic) { - var swagText:FlxText = new FlxText(10, 10 + (28 * txtGrp.length)); + var swagText:FlxText = new FlxText(10, FlxG.height - 32); swagText.setFormat(Paths.font("vcr.ttf"), 26, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); swagText.scrollFactor.set(); + + for (text in txtGrp.members) + { + text.y -= swagText.height; + } txtGrp.add(swagText); swagText.text = str + ": " + Std.string(value); @@ -352,14 +350,14 @@ class DebugBoundingState extends FlxState { if (FlxG.keys.justPressed.ONE) { - var lv:DropDown = cast uiStuff.findComponent("swapper"); + var lv:DropDown = offsetEditorDialog.findComponent("swapper", DropDown); lv.selectedIndex = 0; curView = SPRITESHEET; } if (FlxG.keys.justReleased.TWO) { - var lv:DropDown = cast uiStuff.findComponent("swapper"); + var lv:DropDown = offsetEditorDialog.findComponent("swapper", DropDown); lv.selectedIndex = 1; curView = ANIMATIONS; if (swagChar != null) @@ -375,10 +373,12 @@ class DebugBoundingState extends FlxState spriteSheetView.visible = true; offsetView.visible = false; offsetView.active = false; + offsetAnimationDropdown.visible = false; case ANIMATIONS: spriteSheetView.visible = false; offsetView.visible = true; offsetView.active = true; + offsetAnimationDropdown.visible = true; offsetControls(); mouseOffsetMovement(); } @@ -402,24 +402,36 @@ class DebugBoundingState extends FlxState { if (FlxG.keys.justPressed.RBRACKET || FlxG.keys.justPressed.E) { - if (Std.parseInt(animDropDownMenu.selectedId) + 1 <= animDropDownMenu.length) - animDropDownMenu.selectedId = Std.string(Std.parseInt(animDropDownMenu.selectedId) - + 1); + if (offsetAnimationDropdown.selectedIndex + 1 <= offsetAnimationDropdown.dataSource.size) + { + offsetAnimationDropdown.selectedIndex += 1; + } else - animDropDownMenu.selectedId = Std.string(0); - playCharacterAnimation(animDropDownMenu.selectedId, true); + { + offsetAnimationDropdown.selectedIndex = 0; + } + trace(offsetAnimationDropdown.selectedIndex); + trace(offsetAnimationDropdown.dataSource.size); + trace(offsetAnimationDropdown.value); + trace(currentAnimationName); + playCharacterAnimation(currentAnimationName, true); } if (FlxG.keys.justPressed.LBRACKET || FlxG.keys.justPressed.Q) { - if (Std.parseInt(animDropDownMenu.selectedId) - 1 >= 0) animDropDownMenu.selectedId = Std.string(Std.parseInt(animDropDownMenu.selectedId) - 1); + if (offsetAnimationDropdown.selectedIndex - 1 >= 0) + { + offsetAnimationDropdown.selectedIndex -= 1; + } else - animDropDownMenu.selectedId = Std.string(animDropDownMenu.length - 1); - playCharacterAnimation(animDropDownMenu.selectedId, true); + { + offsetAnimationDropdown.selectedIndex = offsetAnimationDropdown.dataSource.size - 1; + } + playCharacterAnimation(currentAnimationName, true); } // Keyboards controls for general WASD "movement" - // modifies the animDropDownMenu so that it's properly updated and shit - // and then it's just played and updated from the animDropDownMenu callback, which is set in the loadAnimShit() function probabbly + // modifies the animDrooffsetAnimationDropdownpDownMenu so that it's properly updated and shit + // and then it's just played and updated from the offsetAnimationDropdown callback, which is set in the loadAnimShit() function probabbly if (FlxG.keys.justPressed.W || FlxG.keys.justPressed.S || FlxG.keys.justPressed.D || FlxG.keys.justPressed.A) { var suffix:String = ''; @@ -432,18 +444,19 @@ class DebugBoundingState extends FlxState if (FlxG.keys.justPressed.A) targetLabel = 'singLEFT$suffix'; if (FlxG.keys.justPressed.D) targetLabel = 'singRIGHT$suffix'; - if (targetLabel != animDropDownMenu.selectedLabel) + if (targetLabel != currentAnimationName) { + offsetAnimationDropdown.value = {id: targetLabel, text: targetLabel}; + // Play the new animation if the IDs are the different. // Override the onion skin. - animDropDownMenu.selectedLabel = targetLabel; - playCharacterAnimation(animDropDownMenu.selectedId, true); + playCharacterAnimation(currentAnimationName, true); } else { // Replay the current animation if the IDs are the same. // Don't override the onion skin. - playCharacterAnimation(animDropDownMenu.selectedId, false); + playCharacterAnimation(currentAnimationName, false); } } @@ -455,16 +468,20 @@ class DebugBoundingState extends FlxState // Plays the idle animation if (FlxG.keys.justPressed.SPACE) { - animDropDownMenu.selectedLabel = 'idle'; - playCharacterAnimation(animDropDownMenu.selectedId, true); + offsetAnimationDropdown.value = {id: 'idle', text: 'idle'}; + + playCharacterAnimation(currentAnimationName, true); } // Playback the animation - if (FlxG.keys.justPressed.ENTER) playCharacterAnimation(animDropDownMenu.selectedId, false); + if (FlxG.keys.justPressed.ENTER) + { + playCharacterAnimation(currentAnimationName, false); + } if (FlxG.keys.justPressed.RIGHT || FlxG.keys.justPressed.LEFT || FlxG.keys.justPressed.UP || FlxG.keys.justPressed.DOWN) { - var animName = animDropDownMenu.selectedLabel; + var animName = currentAnimationName; var coolValues:Array = swagChar.animationOffsets.get(animName).copy(); var multiplier:Int = 5; @@ -478,10 +495,11 @@ class DebugBoundingState extends FlxState else if (FlxG.keys.justPressed.UP) coolValues[1] += 1 * multiplier; else if (FlxG.keys.justPressed.DOWN) coolValues[1] -= 1 * multiplier; - swagChar.animationOffsets.set(animDropDownMenu.selectedLabel, coolValues); + swagChar.animationOffsets.set(currentAnimationName, coolValues); swagChar.playAnimation(animName); txtOffsetShit.text = 'Offset: ' + coolValues; + txtOffsetShit.y = FlxG.height - 20 - txtOffsetShit.height; trace(animName); } @@ -536,7 +554,7 @@ class DebugBoundingState extends FlxState swagChar = CharacterDataParser.fetchCharacter(char); swagChar.x = 100; swagChar.y = 100; - // swagChar.debugMode = true; + swagChar.debug = true; offsetView.add(swagChar); if (swagChar == null || swagChar.frames == null) @@ -561,11 +579,25 @@ class DebugBoundingState extends FlxState trace(swagChar.animationOffsets[i]); } - animDropDownMenu.setData(FlxUIDropDownMenu.makeStrIdLabelArray(characterAnimNames, true)); - animDropDownMenu.callback = function(str:String) { - playCharacterAnimation(str, true); - }; + offsetAnimationDropdown.dataSource.clear(); + + for (charAnim in characterAnimNames) + { + trace('Adding ${charAnim} to HaxeUI dropdown'); + offsetAnimationDropdown.dataSource.add({id: charAnim, text: charAnim}); + } + + offsetAnimationDropdown.selectedIndex = 0; + + trace('Added ${offsetAnimationDropdown.dataSource.size} to HaxeUI dropdown'); + + offsetAnimationDropdown.onChange = function(event:UIEvent) { + trace('Selected animation ${event?.data?.id}'); + playCharacterAnimation(event.data.id, true); + } + txtOffsetShit.text = 'Offset: ' + swagChar.animOffsets; + txtOffsetShit.y = FlxG.height - 20 - txtOffsetShit.height; dropDownSetup = true; } @@ -582,11 +614,13 @@ class DebugBoundingState extends FlxState onionSkinChar.alpha = 0.6; } - var animName = characterAnimNames[Std.parseInt(str)]; + // var animName = characterAnimNames[Std.parseInt(str)]; + var animName = str; swagChar.playAnimation(animName, true); // trace(); trace(swagChar.animationOffsets.get(animName)); txtOffsetShit.text = 'Offset: ' + swagChar.animOffsets; + txtOffsetShit.y = FlxG.height - 20 - txtOffsetShit.height; } var _file:FileReference; diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index dc42bd651..f9d5a36d4 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1,7 +1,6 @@ package funkin.ui.freeplay; import flixel.addons.transition.FlxTransitionableState; -import flixel.addons.ui.FlxInputText; import flixel.FlxCamera; import flixel.FlxSprite; import flixel.group.FlxGroup; From a7482410b91e82fbd7b7cf37a123b0e7aaa72fec Mon Sep 17 00:00:00 2001 From: lemz Date: Fri, 31 May 2024 14:02:28 +0200 Subject: [PATCH 468/870] add note kind scripts --- source/funkin/InitState.hx | 3 ++ source/funkin/play/PlayState.hx | 8 +++- .../play/notes/notekind/NoteKindScript.hx | 45 ++++++++++++++++++ .../notes/notekind/NoteKindScriptManager.hx | 46 +++++++++++++++++++ .../notes/notekind/ScriptedNoteKindScript.hx | 9 ++++ .../charting/util/ChartEditorDropdowns.hx | 2 +- 6 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 source/funkin/play/notes/notekind/NoteKindScript.hx create mode 100644 source/funkin/play/notes/notekind/NoteKindScriptManager.hx create mode 100644 source/funkin/play/notes/notekind/ScriptedNoteKindScript.hx diff --git a/source/funkin/InitState.hx b/source/funkin/InitState.hx index 6e370b5ff..a339d2655 100644 --- a/source/funkin/InitState.hx +++ b/source/funkin/InitState.hx @@ -27,6 +27,7 @@ import funkin.data.dialogue.speaker.SpeakerRegistry; import funkin.data.freeplay.album.AlbumRegistry; import funkin.data.song.SongRegistry; import funkin.play.character.CharacterData.CharacterDataParser; +import funkin.play.notes.notekind.NoteKindScriptManager; import funkin.modding.module.ModuleHandler; import funkin.ui.title.TitleState; import funkin.util.CLIUtil; @@ -176,6 +177,8 @@ class InitState extends FlxState // Move it to use a BaseRegistry. CharacterDataParser.loadCharacterCache(); + NoteKindScriptManager.loadScripts(); + ModuleHandler.buildModuleCallbacks(); ModuleHandler.loadModuleCache(); ModuleHandler.callOnCreate(); diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 8d7d82aab..93306e9d5 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -49,6 +49,7 @@ import funkin.play.notes.NoteSprite; import funkin.play.notes.notestyle.NoteStyle; import funkin.play.notes.Strumline; import funkin.play.notes.SustainTrail; +import funkin.play.notes.notekind.NoteKindScriptManager; import funkin.play.scoring.Scoring; import funkin.play.song.Song; import funkin.play.stage.Stage; @@ -1177,7 +1178,12 @@ class PlayState extends MusicBeatSubState // Dispatch event to conversation script. ScriptEventDispatcher.callEvent(currentConversation, event); - // TODO: Dispatch event to note scripts + // Dispatch event to note script + if (Std.isOfType(event, NoteScriptEvent)) + { + var noteEvent:NoteScriptEvent = cast(event, NoteScriptEvent); + NoteKindScriptManager.callEvent(noteEvent.note.noteData.kind, noteEvent); + } } /** diff --git a/source/funkin/play/notes/notekind/NoteKindScript.hx b/source/funkin/play/notes/notekind/NoteKindScript.hx new file mode 100644 index 000000000..baa57b146 --- /dev/null +++ b/source/funkin/play/notes/notekind/NoteKindScript.hx @@ -0,0 +1,45 @@ +package funkin.play.notes.notekind; + +import funkin.modding.IScriptedClass.INoteScriptedClass; +import funkin.modding.events.ScriptEvent; + +/** + * Class for note scripts + */ +class NoteKindScript implements INoteScriptedClass +{ + /** + * the name of the note kind + */ + public var noteKind:String; + + /** + * description used in chart editor + */ + public var description:String = ""; + + public function new(noteKind:String, description:String = "") + { + this.noteKind = noteKind; + this.description = description; + } + + public function toString():String + { + return noteKind; + } + + public function onScriptEvent(event:ScriptEvent):Void {} + + public function onCreate(event:ScriptEvent):Void {} + + public function onDestroy(event:ScriptEvent):Void {} + + public function onUpdate(event:UpdateScriptEvent):Void {} + + public function onNoteIncoming(event:NoteScriptEvent):Void {} + + public function onNoteHit(event:HitNoteScriptEvent):Void {} + + public function onNoteMiss(event:NoteScriptEvent):Void {} +} diff --git a/source/funkin/play/notes/notekind/NoteKindScriptManager.hx b/source/funkin/play/notes/notekind/NoteKindScriptManager.hx new file mode 100644 index 000000000..dc22732b6 --- /dev/null +++ b/source/funkin/play/notes/notekind/NoteKindScriptManager.hx @@ -0,0 +1,46 @@ +package funkin.play.notes.notekind; + +import funkin.modding.events.ScriptEventDispatcher; +import funkin.modding.events.ScriptEvent; +import funkin.ui.debug.charting.util.ChartEditorDropdowns; + +class NoteKindScriptManager +{ + static var noteKindScripts:Map = []; + + public static function loadScripts():Void + { + var scriptedClassName:Array = ScriptedNoteKindScript.listScriptClasses(); + if (scriptedClassName.length > 0) + { + trace('Instantiating ${scriptedClassName.length} scripted note kind...'); + for (scriptedClass in scriptedClassName) + { + try + { + var script:NoteKindScript = ScriptedNoteKindScript.init(scriptedClass, "unknown"); + trace(' Initialized scripted note kind: ${script.noteKind}'); + noteKindScripts.set(script.noteKind, script); + ChartEditorDropdowns.NOTE_KINDS.set(script.noteKind, script.description); + } + catch (e) + { + trace(' FAILED to instantiate scripted note kind: ${scriptedClass}'); + trace(e); + } + } + } + } + + public static function callEvent(noteKind:String, event:ScriptEvent):Void + { + var noteKindScript:NoteKindScript = noteKindScripts.get(noteKind); + + if (noteKindScript == null) + { + return; + } + + ScriptEventDispatcher.callEvent(noteKindScript, event); + } +} diff --git a/source/funkin/play/notes/notekind/ScriptedNoteKindScript.hx b/source/funkin/play/notes/notekind/ScriptedNoteKindScript.hx new file mode 100644 index 000000000..d54a0cde2 --- /dev/null +++ b/source/funkin/play/notes/notekind/ScriptedNoteKindScript.hx @@ -0,0 +1,9 @@ +package funkin.play.notes.notekind; + +/** + * A script that can be tied to a NoteKindScript. + * Create a scripted class that extends NoteKindScript, + * then call `super('noteKind')` in the constructor to use this. + */ +@:hscriptClass +class ScriptedNoteKindScript extends NoteKindScript implements polymod.hscript.HScriptedClass {} diff --git a/source/funkin/ui/debug/charting/util/ChartEditorDropdowns.hx b/source/funkin/ui/debug/charting/util/ChartEditorDropdowns.hx index 55aab0ab0..f20b75650 100644 --- a/source/funkin/ui/debug/charting/util/ChartEditorDropdowns.hx +++ b/source/funkin/ui/debug/charting/util/ChartEditorDropdowns.hx @@ -146,7 +146,7 @@ class ChartEditorDropdowns return returnValue; } - static final NOTE_KINDS:Map = [ + public static final NOTE_KINDS:Map = [ // Base "" => "Default", "~CUSTOM~" => "Custom", From 134b4678769de803b245c182fed9afe07fc29049 Mon Sep 17 00:00:00 2001 From: lemz Date: Fri, 31 May 2024 16:55:42 +0200 Subject: [PATCH 469/870] rename stuff --- source/funkin/InitState.hx | 4 ++-- source/funkin/play/PlayState.hx | 4 ++-- .../notekind/{NoteKindScript.hx => NoteKind.hx} | 2 +- ...teKindScriptManager.hx => NoteKindManager.hx} | 16 ++++++++-------- .../play/notes/notekind/ScriptedNoteKind.hx | 9 +++++++++ .../notes/notekind/ScriptedNoteKindScript.hx | 9 --------- 6 files changed, 22 insertions(+), 22 deletions(-) rename source/funkin/play/notes/notekind/{NoteKindScript.hx => NoteKind.hx} (94%) rename source/funkin/play/notes/notekind/{NoteKindScriptManager.hx => NoteKindManager.hx} (64%) create mode 100644 source/funkin/play/notes/notekind/ScriptedNoteKind.hx delete mode 100644 source/funkin/play/notes/notekind/ScriptedNoteKindScript.hx diff --git a/source/funkin/InitState.hx b/source/funkin/InitState.hx index a339d2655..34516dee1 100644 --- a/source/funkin/InitState.hx +++ b/source/funkin/InitState.hx @@ -27,7 +27,7 @@ import funkin.data.dialogue.speaker.SpeakerRegistry; import funkin.data.freeplay.album.AlbumRegistry; import funkin.data.song.SongRegistry; import funkin.play.character.CharacterData.CharacterDataParser; -import funkin.play.notes.notekind.NoteKindScriptManager; +import funkin.play.notes.notekind.NoteKindManager; import funkin.modding.module.ModuleHandler; import funkin.ui.title.TitleState; import funkin.util.CLIUtil; @@ -177,7 +177,7 @@ class InitState extends FlxState // Move it to use a BaseRegistry. CharacterDataParser.loadCharacterCache(); - NoteKindScriptManager.loadScripts(); + NoteKindManager.loadScripts(); ModuleHandler.buildModuleCallbacks(); ModuleHandler.loadModuleCache(); diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 93306e9d5..bc441a7d5 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -49,7 +49,7 @@ import funkin.play.notes.NoteSprite; import funkin.play.notes.notestyle.NoteStyle; import funkin.play.notes.Strumline; import funkin.play.notes.SustainTrail; -import funkin.play.notes.notekind.NoteKindScriptManager; +import funkin.play.notes.notekind.NoteKindManager; import funkin.play.scoring.Scoring; import funkin.play.song.Song; import funkin.play.stage.Stage; @@ -1182,7 +1182,7 @@ class PlayState extends MusicBeatSubState if (Std.isOfType(event, NoteScriptEvent)) { var noteEvent:NoteScriptEvent = cast(event, NoteScriptEvent); - NoteKindScriptManager.callEvent(noteEvent.note.noteData.kind, noteEvent); + NoteKindManager.callEvent(noteEvent.note.noteData.kind, noteEvent); } } diff --git a/source/funkin/play/notes/notekind/NoteKindScript.hx b/source/funkin/play/notes/notekind/NoteKind.hx similarity index 94% rename from source/funkin/play/notes/notekind/NoteKindScript.hx rename to source/funkin/play/notes/notekind/NoteKind.hx index baa57b146..77b2bbc45 100644 --- a/source/funkin/play/notes/notekind/NoteKindScript.hx +++ b/source/funkin/play/notes/notekind/NoteKind.hx @@ -6,7 +6,7 @@ import funkin.modding.events.ScriptEvent; /** * Class for note scripts */ -class NoteKindScript implements INoteScriptedClass +class NoteKind implements INoteScriptedClass { /** * the name of the note kind diff --git a/source/funkin/play/notes/notekind/NoteKindScriptManager.hx b/source/funkin/play/notes/notekind/NoteKindManager.hx similarity index 64% rename from source/funkin/play/notes/notekind/NoteKindScriptManager.hx rename to source/funkin/play/notes/notekind/NoteKindManager.hx index dc22732b6..eaee0d319 100644 --- a/source/funkin/play/notes/notekind/NoteKindScriptManager.hx +++ b/source/funkin/play/notes/notekind/NoteKindManager.hx @@ -4,13 +4,13 @@ import funkin.modding.events.ScriptEventDispatcher; import funkin.modding.events.ScriptEvent; import funkin.ui.debug.charting.util.ChartEditorDropdowns; -class NoteKindScriptManager +class NoteKindManager { - static var noteKindScripts:Map = []; + static var noteKinds:Map = []; public static function loadScripts():Void { - var scriptedClassName:Array = ScriptedNoteKindScript.listScriptClasses(); + var scriptedClassName:Array = ScriptedNoteKind.listScriptClasses(); if (scriptedClassName.length > 0) { trace('Instantiating ${scriptedClassName.length} scripted note kind...'); @@ -18,9 +18,9 @@ class NoteKindScriptManager { try { - var script:NoteKindScript = ScriptedNoteKindScript.init(scriptedClass, "unknown"); + var script:NoteKind = ScriptedNoteKind.init(scriptedClass, "unknown"); trace(' Initialized scripted note kind: ${script.noteKind}'); - noteKindScripts.set(script.noteKind, script); + noteKinds.set(script.noteKind, script); ChartEditorDropdowns.NOTE_KINDS.set(script.noteKind, script.description); } catch (e) @@ -34,13 +34,13 @@ class NoteKindScriptManager public static function callEvent(noteKind:String, event:ScriptEvent):Void { - var noteKindScript:NoteKindScript = noteKindScripts.get(noteKind); + var noteKind:NoteKind = noteKinds.get(noteKind); - if (noteKindScript == null) + if (noteKind == null) { return; } - ScriptEventDispatcher.callEvent(noteKindScript, event); + ScriptEventDispatcher.callEvent(noteKind, event); } } diff --git a/source/funkin/play/notes/notekind/ScriptedNoteKind.hx b/source/funkin/play/notes/notekind/ScriptedNoteKind.hx new file mode 100644 index 000000000..cd1781394 --- /dev/null +++ b/source/funkin/play/notes/notekind/ScriptedNoteKind.hx @@ -0,0 +1,9 @@ +package funkin.play.notes.notekind; + +/** + * A script that can be tied to a NoteKind. + * Create a scripted class that extends NoteKind, + * then call `super('noteKind')` in the constructor to use this. + */ +@:hscriptClass +class ScriptedNoteKind extends NoteKind implements polymod.hscript.HScriptedClass {} diff --git a/source/funkin/play/notes/notekind/ScriptedNoteKindScript.hx b/source/funkin/play/notes/notekind/ScriptedNoteKindScript.hx deleted file mode 100644 index d54a0cde2..000000000 --- a/source/funkin/play/notes/notekind/ScriptedNoteKindScript.hx +++ /dev/null @@ -1,9 +0,0 @@ -package funkin.play.notes.notekind; - -/** - * A script that can be tied to a NoteKindScript. - * Create a scripted class that extends NoteKindScript, - * then call `super('noteKind')` in the constructor to use this. - */ -@:hscriptClass -class ScriptedNoteKindScript extends NoteKindScript implements polymod.hscript.HScriptedClass {} From 606d9d4af47ea50a89e921ef369aaa73b5dc3c7b Mon Sep 17 00:00:00 2001 From: lemz Date: Fri, 31 May 2024 17:24:51 +0200 Subject: [PATCH 470/870] Update NoteKindManager.hx --- source/funkin/play/notes/notekind/NoteKindManager.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/play/notes/notekind/NoteKindManager.hx b/source/funkin/play/notes/notekind/NoteKindManager.hx index eaee0d319..99502af08 100644 --- a/source/funkin/play/notes/notekind/NoteKindManager.hx +++ b/source/funkin/play/notes/notekind/NoteKindManager.hx @@ -13,7 +13,7 @@ class NoteKindManager var scriptedClassName:Array = ScriptedNoteKind.listScriptClasses(); if (scriptedClassName.length > 0) { - trace('Instantiating ${scriptedClassName.length} scripted note kind...'); + trace('Instantiating ${scriptedClassName.length} scripted note kind(s)...'); for (scriptedClass in scriptedClassName) { try From c83e505f5bae0e1a61a1d010aec8765d53cab36d Mon Sep 17 00:00:00 2001 From: lemz Date: Fri, 31 May 2024 17:49:25 +0200 Subject: [PATCH 471/870] onUpdate, etc. works now too --- source/funkin/play/PlayState.hx | 6 +++++- source/funkin/play/notes/notekind/NoteKindManager.hx | 8 ++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index bc441a7d5..3b098be14 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1178,12 +1178,16 @@ class PlayState extends MusicBeatSubState // Dispatch event to conversation script. ScriptEventDispatcher.callEvent(currentConversation, event); - // Dispatch event to note script + // Dispatch event to only the specific note script if (Std.isOfType(event, NoteScriptEvent)) { var noteEvent:NoteScriptEvent = cast(event, NoteScriptEvent); NoteKindManager.callEvent(noteEvent.note.noteData.kind, noteEvent); } + else // Dispatch event to all note scripts + { + NoteKindManager.callEventForAll(event); + } } /** diff --git a/source/funkin/play/notes/notekind/NoteKindManager.hx b/source/funkin/play/notes/notekind/NoteKindManager.hx index 99502af08..0de1a0a33 100644 --- a/source/funkin/play/notes/notekind/NoteKindManager.hx +++ b/source/funkin/play/notes/notekind/NoteKindManager.hx @@ -43,4 +43,12 @@ class NoteKindManager ScriptEventDispatcher.callEvent(noteKind, event); } + + public static function callEventForAll(event:ScriptEvent):Void + { + for (noteKind in noteKinds.iterator()) + { + ScriptEventDispatcher.callEvent(noteKind, event); + } + } } From e3e4e9fac01844a807ecd54e34fc162205c59ed9 Mon Sep 17 00:00:00 2001 From: lemz Date: Fri, 31 May 2024 20:28:56 +0200 Subject: [PATCH 472/870] helper function --- source/funkin/play/notes/notekind/NoteKind.hx | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/source/funkin/play/notes/notekind/NoteKind.hx b/source/funkin/play/notes/notekind/NoteKind.hx index 77b2bbc45..8b87e0442 100644 --- a/source/funkin/play/notes/notekind/NoteKind.hx +++ b/source/funkin/play/notes/notekind/NoteKind.hx @@ -18,6 +18,16 @@ class NoteKind implements INoteScriptedClass */ public var description:String = ""; + /** + * this only exists for people that don't like calling functions + */ + var notes(get, never):Array; + + function get_notes():Array + { + return this.getNotes(); + } + public function new(noteKind:String, description:String = "") { this.noteKind = noteKind; @@ -29,6 +39,18 @@ class NoteKind implements INoteScriptedClass return noteKind; } + /** + * Retrieve all notes of this kind + * @return Array + */ + function getNotes():Array + { + var allNotes:Array = PlayState.instance.playerStrumline.notes.members.concat(PlayState.instance.opponentStrumline.notes.members); + return allNotes.filter(function(note:NoteSprite) { + return note != null && note.noteData.kind == this.noteKind; + }); + } + public function onScriptEvent(event:ScriptEvent):Void {} public function onCreate(event:ScriptEvent):Void {} From 3f39d9509c1e2a02d4ace85553991b6679a83d14 Mon Sep 17 00:00:00 2001 From: lemz Date: Fri, 31 May 2024 23:56:57 +0200 Subject: [PATCH 473/870] make custom note style less clunky --- source/funkin/play/notes/notekind/NoteKind.hx | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/source/funkin/play/notes/notekind/NoteKind.hx b/source/funkin/play/notes/notekind/NoteKind.hx index 8b87e0442..f4936c59e 100644 --- a/source/funkin/play/notes/notekind/NoteKind.hx +++ b/source/funkin/play/notes/notekind/NoteKind.hx @@ -1,5 +1,7 @@ package funkin.play.notes.notekind; +import funkin.data.notestyle.NoteStyleRegistry; +import funkin.play.notes.notestyle.NoteStyle; import funkin.modding.IScriptedClass.INoteScriptedClass; import funkin.modding.events.ScriptEvent; @@ -39,6 +41,23 @@ class NoteKind implements INoteScriptedClass return noteKind; } + /** + * Changes the note style of the given note. Use this in `onNoteIncoming` + * @param note + * @param noteStyle + */ + function setNoteStyle(note:NoteSprite, noteStyleId:String):Void + { + var noteStyle:NoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyleId); + noteStyle.buildNoteSprite(note); + + note.setGraphicSize(Strumline.STRUMLINE_SIZE); + note.updateHitbox(); + + // this calls the setter for playing the correct animation + note.direction = note.direction; + } + /** * Retrieve all notes of this kind * @return Array From 14771e72deb7f08b9658e0801c9e088bb5d1aa96 Mon Sep 17 00:00:00 2001 From: lemz Date: Fri, 31 May 2024 23:59:40 +0200 Subject: [PATCH 474/870] no more note getter --- source/funkin/play/notes/notekind/NoteKind.hx | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/source/funkin/play/notes/notekind/NoteKind.hx b/source/funkin/play/notes/notekind/NoteKind.hx index f4936c59e..262660eea 100644 --- a/source/funkin/play/notes/notekind/NoteKind.hx +++ b/source/funkin/play/notes/notekind/NoteKind.hx @@ -20,16 +20,6 @@ class NoteKind implements INoteScriptedClass */ public var description:String = ""; - /** - * this only exists for people that don't like calling functions - */ - var notes(get, never):Array; - - function get_notes():Array - { - return this.getNotes(); - } - public function new(noteKind:String, description:String = "") { this.noteKind = noteKind; From b6eda8e498be12f40c6086678a48c7c038e4b69e Mon Sep 17 00:00:00 2001 From: lemz Date: Sat, 1 Jun 2024 18:25:46 +0200 Subject: [PATCH 475/870] remove note kind logic from playstate --- source/funkin/play/PlayState.hx | 12 ++----- .../play/notes/notekind/NoteKindManager.hx | 34 ++++++++++++------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 3b098be14..da343f43f 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1178,16 +1178,8 @@ class PlayState extends MusicBeatSubState // Dispatch event to conversation script. ScriptEventDispatcher.callEvent(currentConversation, event); - // Dispatch event to only the specific note script - if (Std.isOfType(event, NoteScriptEvent)) - { - var noteEvent:NoteScriptEvent = cast(event, NoteScriptEvent); - NoteKindManager.callEvent(noteEvent.note.noteData.kind, noteEvent); - } - else // Dispatch event to all note scripts - { - NoteKindManager.callEventForAll(event); - } + // Dispatch event to note kind scripts + NoteKindManager.callEvent(event); } /** diff --git a/source/funkin/play/notes/notekind/NoteKindManager.hx b/source/funkin/play/notes/notekind/NoteKindManager.hx index 0de1a0a33..6efd601c7 100644 --- a/source/funkin/play/notes/notekind/NoteKindManager.hx +++ b/source/funkin/play/notes/notekind/NoteKindManager.hx @@ -32,23 +32,31 @@ class NoteKindManager } } - public static function callEvent(noteKind:String, event:ScriptEvent):Void + /** + * Calls the given event for note kind scripts + * @param event The event + */ + public static function callEvent(event:ScriptEvent):Void { - var noteKind:NoteKind = noteKinds.get(noteKind); - - if (noteKind == null) + // if it is a note script event, + // then only call the event for the specific note kind script + if (Std.isOfType(event, NoteScriptEvent)) { - return; + var noteEvent:NoteScriptEvent = cast(event, NoteScriptEvent); + + var noteKind:NoteKind = noteKinds.get(noteEvent.note.noteData.kind); + + if (noteKind != null) + { + ScriptEventDispatcher.callEvent(noteKind, event); + } } - - ScriptEventDispatcher.callEvent(noteKind, event); - } - - public static function callEventForAll(event:ScriptEvent):Void - { - for (noteKind in noteKinds.iterator()) + else // call the event for all note kind scripts { - ScriptEventDispatcher.callEvent(noteKind, event); + for (noteKind in noteKinds.iterator()) + { + ScriptEventDispatcher.callEvent(noteKind, event); + } } } } From 328e590f92901f3dab711a725af02cc40763f359 Mon Sep 17 00:00:00 2001 From: lemz Date: Sat, 1 Jun 2024 19:47:45 +0200 Subject: [PATCH 476/870] hold assets are updated aswell --- source/funkin/play/notes/NoteSprite.hx | 6 ++- source/funkin/play/notes/Strumline.hx | 7 ++++ source/funkin/play/notes/SustainTrail.hx | 38 ++++++++++++++----- source/funkin/play/notes/notekind/NoteKind.hx | 33 +++++----------- .../play/notes/notekind/NoteKindManager.hx | 16 +++++++- 5 files changed, 65 insertions(+), 35 deletions(-) diff --git a/source/funkin/play/notes/NoteSprite.hx b/source/funkin/play/notes/NoteSprite.hx index b16b88466..17a5e57fc 100644 --- a/source/funkin/play/notes/NoteSprite.hx +++ b/source/funkin/play/notes/NoteSprite.hx @@ -140,7 +140,11 @@ class NoteSprite extends FunkinSprite this.active = false; } - function setupNoteGraphic(noteStyle:NoteStyle):Void + /** + * Creates frames and animations + * @param noteStyle The `NoteStyle` instance + */ + public function setupNoteGraphic(noteStyle:NoteStyle):Void { noteStyle.buildNoteSprite(this); diff --git a/source/funkin/play/notes/Strumline.hx b/source/funkin/play/notes/Strumline.hx index fdb32bb85..ebc48a8c7 100644 --- a/source/funkin/play/notes/Strumline.hx +++ b/source/funkin/play/notes/Strumline.hx @@ -16,6 +16,7 @@ import funkin.data.song.SongData.SongNoteData; import funkin.ui.options.PreferencesMenu; import funkin.util.SortUtil; import funkin.modding.events.ScriptEvent; +import funkin.play.notes.notekind.NoteKindManager; /** * A group of sprites which handles the receptor, the note splashes, and the notes (with sustains) for a given player. @@ -708,6 +709,9 @@ class Strumline extends FlxSpriteGroup if (noteSprite != null) { + var noteKindStyle:NoteStyle = NoteKindManager.getNoteStyle(note.kind) ?? this.noteStyle; + noteSprite.setupNoteGraphic(noteKindStyle); + noteSprite.direction = note.getDirection(); noteSprite.noteData = note; @@ -727,6 +731,9 @@ class Strumline extends FlxSpriteGroup if (holdNoteSprite != null) { + var noteKindStyle:NoteStyle = NoteKindManager.getNoteStyle(note.kind) ?? this.noteStyle; + holdNoteSprite.setupHoldNoteGraphic(noteKindStyle); + holdNoteSprite.parentStrumline = this; holdNoteSprite.noteData = note; holdNoteSprite.strumTime = note.time; diff --git a/source/funkin/play/notes/SustainTrail.hx b/source/funkin/play/notes/SustainTrail.hx index f6d43b33f..570c05190 100644 --- a/source/funkin/play/notes/SustainTrail.hx +++ b/source/funkin/play/notes/SustainTrail.hx @@ -99,7 +99,27 @@ class SustainTrail extends FlxSprite */ public function new(noteDirection:NoteDirection, sustainLength:Float, noteStyle:NoteStyle) { - super(0, 0, noteStyle.getHoldNoteAssetPath()); + super(0, 0); + + // BASIC SETUP + this.sustainLength = sustainLength; + this.fullSustainLength = sustainLength; + this.noteDirection = noteDirection; + + setupHoldNoteGraphic(noteStyle); + + indices = new DrawData(12, true, TRIANGLE_VERTEX_INDICES); + + this.active = true; // This NEEDS to be true for the note to be drawn! + } + + /** + * Creates hold note graphic and applies correct zooming + * @param noteStyle The note style + */ + public function setupHoldNoteGraphic(noteStyle:NoteStyle):Void + { + loadGraphic(noteStyle.getHoldNoteAssetPath()); antialiasing = true; @@ -109,13 +129,9 @@ class SustainTrail extends FlxSprite endOffset = bottomClip = 1; antialiasing = false; } + + zoom = 1.0; zoom *= noteStyle.fetchHoldNoteScale(); - - // BASIC SETUP - this.sustainLength = sustainLength; - this.fullSustainLength = sustainLength; - this.noteDirection = noteDirection; - zoom *= 0.7; // CALCULATE SIZE @@ -131,9 +147,6 @@ class SustainTrail extends FlxSprite updateColorTransform(); updateClipping(); - indices = new DrawData(12, true, TRIANGLE_VERTEX_INDICES); - - this.active = true; // This NEEDS to be true for the note to be drawn! } function getBaseScrollSpeed() @@ -195,6 +208,11 @@ class SustainTrail extends FlxSprite */ public function updateClipping(songTime:Float = 0):Void { + if (graphic == null) + { + return; + } + var clipHeight:Float = FlxMath.bound(sustainHeight(sustainLength - (songTime - strumTime), parentStrumline?.scrollSpeed ?? 1.0), 0, graphicHeight); if (clipHeight <= 0.1) { diff --git a/source/funkin/play/notes/notekind/NoteKind.hx b/source/funkin/play/notes/notekind/NoteKind.hx index 262660eea..53393623a 100644 --- a/source/funkin/play/notes/notekind/NoteKind.hx +++ b/source/funkin/play/notes/notekind/NoteKind.hx @@ -1,7 +1,5 @@ package funkin.play.notes.notekind; -import funkin.data.notestyle.NoteStyleRegistry; -import funkin.play.notes.notestyle.NoteStyle; import funkin.modding.IScriptedClass.INoteScriptedClass; import funkin.modding.events.ScriptEvent; @@ -11,19 +9,25 @@ import funkin.modding.events.ScriptEvent; class NoteKind implements INoteScriptedClass { /** - * the name of the note kind + * The name of the note kind */ public var noteKind:String; /** - * description used in chart editor + * Description used in chart editor */ - public var description:String = ""; + public var description:String; - public function new(noteKind:String, description:String = "") + /** + * Custom note style + */ + public var noteStyleId:String; + + public function new(noteKind:String, description:String = "", noteStyleId:String = "") { this.noteKind = noteKind; this.description = description; + this.noteStyleId = noteStyleId; } public function toString():String @@ -31,23 +35,6 @@ class NoteKind implements INoteScriptedClass return noteKind; } - /** - * Changes the note style of the given note. Use this in `onNoteIncoming` - * @param note - * @param noteStyle - */ - function setNoteStyle(note:NoteSprite, noteStyleId:String):Void - { - var noteStyle:NoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyleId); - noteStyle.buildNoteSprite(note); - - note.setGraphicSize(Strumline.STRUMLINE_SIZE); - note.updateHitbox(); - - // this calls the setter for playing the correct animation - note.direction = note.direction; - } - /** * Retrieve all notes of this kind * @return Array diff --git a/source/funkin/play/notes/notekind/NoteKindManager.hx b/source/funkin/play/notes/notekind/NoteKindManager.hx index 6efd601c7..849034fc4 100644 --- a/source/funkin/play/notes/notekind/NoteKindManager.hx +++ b/source/funkin/play/notes/notekind/NoteKindManager.hx @@ -3,6 +3,8 @@ package funkin.play.notes.notekind; import funkin.modding.events.ScriptEventDispatcher; import funkin.modding.events.ScriptEvent; import funkin.ui.debug.charting.util.ChartEditorDropdowns; +import funkin.data.notestyle.NoteStyleRegistry; +import funkin.play.notes.notestyle.NoteStyle; class NoteKindManager { @@ -44,7 +46,7 @@ class NoteKindManager { var noteEvent:NoteScriptEvent = cast(event, NoteScriptEvent); - var noteKind:NoteKind = noteKinds.get(noteEvent.note.noteData.kind); + var noteKind:NoteKind = noteKinds.get(noteEvent.note.kind); if (noteKind != null) { @@ -59,4 +61,16 @@ class NoteKindManager } } } + + /** + * Retrieve the note style from the given note kind + * @param noteKind note kind name + * @return NoteStyle + */ + public static function getNoteStyle(noteKind:String):Null + { + var noteStyleId:String = noteKinds.get(noteKind)?.noteStyleId ?? ""; + + return NoteStyleRegistry.instance.fetchEntry(noteStyleId); + } } From ca69e7b850332e0aa4a35574566867cca649cdbf Mon Sep 17 00:00:00 2001 From: lemz Date: Sun, 2 Jun 2024 02:44:16 +0200 Subject: [PATCH 477/870] custom note styles in chart editor --- .../ui/debug/charting/ChartEditorState.hx | 2 + .../components/ChartEditorNoteSprite.hx | 106 ++++++++++-------- .../toolboxes/ChartEditorNoteDataToolbox.hx | 5 + 3 files changed, 64 insertions(+), 49 deletions(-) diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index f72cca77f..0117d8a51 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -1663,6 +1663,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState return currentSongMetadata.playData.characters.instrumental = value; } + var currentCustomNoteKindStyle:Null; + /** * HAXEUI COMPONENTS */ diff --git a/source/funkin/ui/debug/charting/components/ChartEditorNoteSprite.hx b/source/funkin/ui/debug/charting/components/ChartEditorNoteSprite.hx index 98f5a47aa..c97aee1f8 100644 --- a/source/funkin/ui/debug/charting/components/ChartEditorNoteSprite.hx +++ b/source/funkin/ui/debug/charting/components/ChartEditorNoteSprite.hx @@ -7,7 +7,11 @@ import flixel.graphics.frames.FlxAtlasFrames; import flixel.graphics.frames.FlxFrame; import flixel.graphics.frames.FlxTileFrames; import flixel.math.FlxPoint; +import funkin.data.animation.AnimationData; import funkin.data.song.SongData.SongNoteData; +import funkin.data.notestyle.NoteStyleRegistry; +import funkin.play.notes.notestyle.NoteStyle; +import funkin.play.notes.NoteDirection; /** * A sprite that can be used to display a note in a chart. @@ -68,68 +72,62 @@ class ChartEditorNoteSprite extends FlxSprite if (noteFrameCollection == null) { - initFrameCollection(); + buildEmptyFrameCollection(); + + addNoteStyleFrames(fetchNoteStyle('funkin')); + addNoteStyleFrames(fetchNoteStyle('pixel')); } if (noteFrameCollection == null) throw 'ERROR: Could not initialize note sprite animations.'; this.frames = noteFrameCollection; - // Initialize all the animations, not just the one we're going to use immediately, - // so that later we can reuse the sprite without having to initialize more animations during scrolling. - this.animation.addByPrefix('tapLeftFunkin', 'purple instance'); - this.animation.addByPrefix('tapDownFunkin', 'blue instance'); - this.animation.addByPrefix('tapUpFunkin', 'green instance'); - this.animation.addByPrefix('tapRightFunkin', 'red instance'); - - this.animation.addByPrefix('holdLeftFunkin', 'LeftHoldPiece'); - this.animation.addByPrefix('holdDownFunkin', 'DownHoldPiece'); - this.animation.addByPrefix('holdUpFunkin', 'UpHoldPiece'); - this.animation.addByPrefix('holdRightFunkin', 'RightHoldPiece'); - - this.animation.addByPrefix('holdEndLeftFunkin', 'LeftHoldEnd'); - this.animation.addByPrefix('holdEndDownFunkin', 'DownHoldEnd'); - this.animation.addByPrefix('holdEndUpFunkin', 'UpHoldEnd'); - this.animation.addByPrefix('holdEndRightFunkin', 'RightHoldEnd'); - - this.animation.addByPrefix('tapLeftPixel', 'pixel4'); - this.animation.addByPrefix('tapDownPixel', 'pixel5'); - this.animation.addByPrefix('tapUpPixel', 'pixel6'); - this.animation.addByPrefix('tapRightPixel', 'pixel7'); + addNoteStyleAnimations(fetchNoteStyle('funkin')); + addNoteStyleAnimations(fetchNoteStyle('pixel')); } static var noteFrameCollection:Null = null; - /** - * We load all the note frames once, then reuse them. - */ - static function initFrameCollection():Void + function fetchNoteStyle(noteStyleId:String):NoteStyle { - buildEmptyFrameCollection(); - if (noteFrameCollection == null) return; + return NoteStyleRegistry.instance.fetchEntry(noteStyleId) ?? NoteStyleRegistry.instance.fetchDefault(); + } - // TODO: Automatically iterate over the list of note skins. + @:access(funkin.play.notes.notestyle.NoteStyle) + @:nullSafety(Off) + static function addNoteStyleFrames(noteStyle:NoteStyle):Void + { + var prefix:String = noteStyle.id.toTitleCase(); - // Normal notes - var frameCollectionNormal:FlxAtlasFrames = Paths.getSparrowAtlas('NOTE_assets'); - - for (frame in frameCollectionNormal.frames) + var frameCollection:FlxAtlasFrames = Paths.getSparrowAtlas(noteStyle.getNoteAssetPath(), noteStyle.getNoteAssetLibrary()); + for (frame in frameCollection.frames) { - noteFrameCollection.pushFrame(frame); + // cloning the frame because else + // we will fuck up the frame data used in game + var clonedFrame:FlxFrame = frame.copyTo(); + clonedFrame.name = '$prefix${clonedFrame.name}'; + noteFrameCollection.pushFrame(clonedFrame); } + } - // Pixel notes - var graphicPixel = FlxG.bitmap.add(Paths.image('weeb/pixelUI/arrows-pixels', 'week6'), false, null); - if (graphicPixel == null) trace('ERROR: Could not load graphic: ' + Paths.image('weeb/pixelUI/arrows-pixels', 'week6')); - var frameCollectionPixel = FlxTileFrames.fromGraphic(graphicPixel, new FlxPoint(17, 17)); - for (i in 0...frameCollectionPixel.frames.length) - { - var frame:Null = frameCollectionPixel.frames[i]; - if (frame == null) continue; + @:access(funkin.play.notes.notestyle.NoteStyle) + @:nullSafety(Off) + function addNoteStyleAnimations(noteStyle:NoteStyle):Void + { + var prefix:String = noteStyle.id.toTitleCase(); + var suffix:String = noteStyle.id.toTitleCase(); - frame.name = 'pixel' + i; - noteFrameCollection.pushFrame(frame); - } + var leftData:AnimationData = noteStyle.fetchNoteAnimationData(NoteDirection.LEFT); + this.animation.addByPrefix('tapLeft$suffix', '$prefix${leftData.prefix}', leftData.frameRate, leftData.looped, leftData.flipX, leftData.flipY); + + var downData:AnimationData = noteStyle.fetchNoteAnimationData(NoteDirection.DOWN); + this.animation.addByPrefix('tapDown$suffix', '$prefix${downData.prefix}', downData.frameRate, downData.looped, downData.flipX, downData.flipY); + + var upData:AnimationData = noteStyle.fetchNoteAnimationData(NoteDirection.UP); + this.animation.addByPrefix('tapUp$suffix', '$prefix${upData.prefix}', upData.frameRate, upData.looped, upData.flipX, upData.flipY); + + var rightData:AnimationData = noteStyle.fetchNoteAnimationData(NoteDirection.RIGHT); + this.animation.addByPrefix('tapRight$suffix', '$prefix${rightData.prefix}', rightData.frameRate, rightData.looped, rightData.flipX, rightData.flipY); } @:nullSafety(Off) @@ -187,10 +185,20 @@ class ChartEditorNoteSprite extends FlxSprite function get_noteStyle():String { - // Fall back to Funkin' if it's not a valid note style. - return if (NOTE_STYLES.contains(this.parentState.currentSongNoteStyle)) this.parentState.currentSongNoteStyle else 'funkin'; + if (this.parentState.currentCustomNoteKindStyle != null) + { + return this.parentState.currentCustomNoteKindStyle; + } + + if (NOTE_STYLES.contains(this.parentState.currentSongNoteStyle)) + { + return this.parentState.currentSongNoteStyle; + } + + return 'funkin'; } + @:nullSafety(Off) public function playNoteAnimation():Void { if (this.noteData == null) return; @@ -213,8 +221,8 @@ class ChartEditorNoteSprite extends FlxSprite } this.updateHitbox(); - // TODO: Make this an attribute of the note skin. - this.antialiasing = (this.parentState.currentSongNoteStyle != 'Pixel'); + var bruhStyle:NoteStyle = fetchNoteStyle(this.noteStyle); + this.antialiasing = !bruhStyle._data?.assets?.note?.isPixel ?? true; } /** diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx index d4fc69fc1..952513f0e 100644 --- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx @@ -4,6 +4,8 @@ import haxe.ui.components.DropDown; import haxe.ui.components.TextField; import haxe.ui.events.UIEvent; import funkin.ui.debug.charting.util.ChartEditorDropdowns; +import funkin.play.notes.notestyle.NoteStyle; +import funkin.play.notes.notekind.NoteKindManager; /** * The toolbox which allows modifying information like Note Kind. @@ -73,6 +75,9 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox var customKind:Null = event?.target?.text; chartEditorState.noteKindToPlace = customKind; + var noteStyle:Null = NoteKindManager.getNoteStyle(customKind); + chartEditorState.currentCustomNoteKindStyle = noteStyle?.id; + if (chartEditorState.currentEventSelection.length > 0) { // Edit the note data of any selected notes. From 9d7846a0d551a005897f1ea0ca099d19f4ac359f Mon Sep 17 00:00:00 2001 From: lemz Date: Sun, 2 Jun 2024 02:58:56 +0200 Subject: [PATCH 478/870] loop through all note style entries --- .../charting/components/ChartEditorNoteSprite.hx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/source/funkin/ui/debug/charting/components/ChartEditorNoteSprite.hx b/source/funkin/ui/debug/charting/components/ChartEditorNoteSprite.hx index c97aee1f8..6517b61c2 100644 --- a/source/funkin/ui/debug/charting/components/ChartEditorNoteSprite.hx +++ b/source/funkin/ui/debug/charting/components/ChartEditorNoteSprite.hx @@ -70,20 +70,26 @@ class ChartEditorNoteSprite extends FlxSprite this.parentState = parent; + var entries:Array = NoteStyleRegistry.instance.listEntryIds(); + if (noteFrameCollection == null) { buildEmptyFrameCollection(); - addNoteStyleFrames(fetchNoteStyle('funkin')); - addNoteStyleFrames(fetchNoteStyle('pixel')); + for (entry in entries) + { + addNoteStyleFrames(fetchNoteStyle(entry)); + } } if (noteFrameCollection == null) throw 'ERROR: Could not initialize note sprite animations.'; this.frames = noteFrameCollection; - addNoteStyleAnimations(fetchNoteStyle('funkin')); - addNoteStyleAnimations(fetchNoteStyle('pixel')); + for (entry in entries) + { + addNoteStyleAnimations(fetchNoteStyle(entry)); + } } static var noteFrameCollection:Null = null; From ca2cbb44f520361b73c60378e0beaf0459e308c2 Mon Sep 17 00:00:00 2001 From: lemz Date: Sun, 2 Jun 2024 22:11:17 +0200 Subject: [PATCH 479/870] display custom note style in chart editor --- .../play/notes/notekind/NoteKindManager.hx | 10 ++++++ .../ui/debug/charting/ChartEditorState.hx | 10 ++++-- .../components/ChartEditorHoldNoteSprite.hx | 34 +++++++++++++++++++ .../components/ChartEditorNoteSprite.hx | 22 ++++++------ .../toolboxes/ChartEditorNoteDataToolbox.hx | 3 -- 5 files changed, 61 insertions(+), 18 deletions(-) diff --git a/source/funkin/play/notes/notekind/NoteKindManager.hx b/source/funkin/play/notes/notekind/NoteKindManager.hx index 849034fc4..82b2c4d39 100644 --- a/source/funkin/play/notes/notekind/NoteKindManager.hx +++ b/source/funkin/play/notes/notekind/NoteKindManager.hx @@ -73,4 +73,14 @@ class NoteKindManager return NoteStyleRegistry.instance.fetchEntry(noteStyleId); } + + /** + * Retrieve the note style id from the given note kind + * @param noteKind note kind name + * @return Null + */ + public static function getNoteStyleId(noteKind:String):Null + { + return noteKinds.get(noteKind)?.noteStyleId; + } } diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 0117d8a51..bc0acc6d6 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -45,6 +45,7 @@ import funkin.input.TurboActionHandler; import funkin.input.TurboButtonHandler; import funkin.input.TurboKeyHandler; import funkin.modding.events.ScriptEvent; +import funkin.play.notes.notekind.NoteKindManager; import funkin.play.character.BaseCharacter.CharacterType; import funkin.play.character.CharacterData; import funkin.play.character.CharacterData.CharacterDataParser; @@ -1663,8 +1664,6 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState return currentSongMetadata.playData.characters.instrumental = value; } - var currentCustomNoteKindStyle:Null; - /** * HAXEUI COMPONENTS */ @@ -3586,6 +3585,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState // The note sprite handles animation playback and positioning. noteSprite.noteData = noteData; + noteSprite.noteStyle = NoteKindManager.getNoteStyleId(noteData.kind) ?? currentSongNoteStyle; noteSprite.overrideStepTime = null; noteSprite.overrideData = null; @@ -3606,6 +3606,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState holdNoteSprite.noteData = noteSprite.noteData; holdNoteSprite.noteDirection = noteSprite.noteData.getDirection(); + holdNoteSprite.noteStyle = NoteKindManager.getNoteStyleId(noteSprite.noteData.kind) ?? currentSongNoteStyle; holdNoteSprite.setHeightDirectly(noteLengthPixels); @@ -3671,7 +3672,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState holdNoteSprite.noteData = noteData; holdNoteSprite.noteDirection = noteData.getDirection(); - + holdNoteSprite.noteStyle = NoteKindManager.getNoteStyleId(noteData.kind) ?? currentSongNoteStyle; holdNoteSprite.setHeightDirectly(noteLengthPixels); holdNoteSprite.updateHoldNotePosition(renderedHoldNotes); @@ -4570,6 +4571,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState gridGhostHoldNote.visible = true; gridGhostHoldNote.noteData = currentPlaceNoteData; gridGhostHoldNote.noteDirection = currentPlaceNoteData.getDirection(); + gridGhostHoldNote.noteStyle = NoteKindManager.getNoteStyleId(currentPlaceNoteData.kind) ?? currentSongNoteStyle; gridGhostHoldNote.setHeightDirectly(dragLengthPixels, true); gridGhostHoldNote.updateHoldNotePosition(renderedHoldNotes); @@ -4893,6 +4895,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState { noteData.kind = noteKindToPlace; noteData.data = cursorColumn; + gridGhostNote.noteStyle = NoteKindManager.getNoteStyleId(noteData.kind) ?? currentSongNoteStyle; gridGhostNote.playNoteAnimation(); } noteData.time = cursorSnappedMs; @@ -5281,6 +5284,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState // Readd the new ghost hold note. ghostHold.noteData = targetNoteData.clone(); ghostHold.noteDirection = ghostHold.noteData.getDirection(); + ghostHold.noteStyle = NoteKindManager.getNoteStyleId(ghostHold.noteData.kind) ?? currentSongNoteStyle; ghostHold.visible = true; ghostHold.alpha = 0.6; ghostHold.setHeightDirectly(0); diff --git a/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx b/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx index ded48abe3..ccf462c56 100644 --- a/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx +++ b/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx @@ -2,6 +2,7 @@ package funkin.ui.debug.charting.components; import funkin.play.notes.Strumline; import funkin.data.notestyle.NoteStyleRegistry; +import funkin.play.notes.notestyle.NoteStyle; import flixel.FlxObject; import flixel.FlxSprite; import flixel.graphics.frames.FlxFramesCollection; @@ -15,6 +16,7 @@ import flixel.math.FlxMath; * A sprite that can be used to display the trail of a hold note in a chart. * Designed to be used and reused efficiently. Has no gameplay functionality. */ +@:access(funkin.ui.debug.charting.ChartEditorState) @:nullSafety class ChartEditorHoldNoteSprite extends SustainTrail { @@ -23,6 +25,22 @@ class ChartEditorHoldNoteSprite extends SustainTrail */ public var parentState:ChartEditorState; + @:isVar + public var noteStyle(get, set):Null; + + function get_noteStyle():Null + { + return this.noteStyle ?? this.parentState.currentSongNoteStyle; + } + + @:nullSafety(Off) + function set_noteStyle(value:Null):Null + { + this.noteStyle = value; + this.updateHoldNoteGraphic(); + return value; + } + public function new(parent:ChartEditorState) { var noteStyle = NoteStyleRegistry.instance.fetchDefault(); @@ -41,6 +59,22 @@ class ChartEditorHoldNoteSprite extends SustainTrail setup(); } + @:nullSafety(Off) + function updateHoldNoteGraphic():Void + { + var bruhStyle:NoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyle); + this.setupHoldNoteGraphic(bruhStyle); + + zoom = 1.0; + zoom *= bruhStyle.fetchHoldNoteScale(); + zoom *= 0.7; + zoom *= ChartEditorState.GRID_SIZE / Strumline.STRUMLINE_SIZE; + + flipY = false; + + setup(); + } + public override function updateHitbox():Void { // Expand the clickable hitbox to the full column width, then nudge to the left to re-center it. diff --git a/source/funkin/ui/debug/charting/components/ChartEditorNoteSprite.hx b/source/funkin/ui/debug/charting/components/ChartEditorNoteSprite.hx index 6517b61c2..009532401 100644 --- a/source/funkin/ui/debug/charting/components/ChartEditorNoteSprite.hx +++ b/source/funkin/ui/debug/charting/components/ChartEditorNoteSprite.hx @@ -40,7 +40,8 @@ class ChartEditorNoteSprite extends FlxSprite /** * The name of the note style currently in use. */ - public var noteStyle(get, never):String; + @:isVar + public var noteStyle(get, set):Null; public var overrideStepTime(default, set):Null = null; @@ -189,19 +190,16 @@ class ChartEditorNoteSprite extends FlxSprite } } - function get_noteStyle():String + function get_noteStyle():Null { - if (this.parentState.currentCustomNoteKindStyle != null) - { - return this.parentState.currentCustomNoteKindStyle; - } + return this.noteStyle ?? this.parentState.currentSongNoteStyle; + } - if (NOTE_STYLES.contains(this.parentState.currentSongNoteStyle)) - { - return this.parentState.currentSongNoteStyle; - } - - return 'funkin'; + function set_noteStyle(value:Null):Null + { + this.noteStyle = value; + this.playNoteAnimation(); + return value; } @:nullSafety(Off) diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx index 952513f0e..f1223eb9c 100644 --- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx @@ -75,9 +75,6 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox var customKind:Null = event?.target?.text; chartEditorState.noteKindToPlace = customKind; - var noteStyle:Null = NoteKindManager.getNoteStyle(customKind); - chartEditorState.currentCustomNoteKindStyle = noteStyle?.id; - if (chartEditorState.currentEventSelection.length > 0) { // Edit the note data of any selected notes. From 040fc85a6263408646e6cac60c1a25da2c99fcaf Mon Sep 17 00:00:00 2001 From: lemz Date: Sun, 2 Jun 2024 23:31:49 +0200 Subject: [PATCH 480/870] change note style on change --- .../components/ChartEditorHoldNoteSprite.hx | 2 +- .../toolboxes/ChartEditorNoteDataToolbox.hx | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx b/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx index ccf462c56..26322c6f9 100644 --- a/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx +++ b/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx @@ -63,7 +63,7 @@ class ChartEditorHoldNoteSprite extends SustainTrail function updateHoldNoteGraphic():Void { var bruhStyle:NoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyle); - this.setupHoldNoteGraphic(bruhStyle); + setupHoldNoteGraphic(bruhStyle); zoom = 1.0; zoom *= bruhStyle.fetchHoldNoteScale(); diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx index f1223eb9c..d872eda38 100644 --- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx @@ -4,6 +4,8 @@ import haxe.ui.components.DropDown; import haxe.ui.components.TextField; import haxe.ui.events.UIEvent; import funkin.ui.debug.charting.util.ChartEditorDropdowns; +import funkin.ui.debug.charting.components.ChartEditorNoteSprite; +import funkin.ui.debug.charting.components.ChartEditorHoldNoteSprite; import funkin.play.notes.notestyle.NoteStyle; import funkin.play.notes.notekind.NoteKindManager; @@ -59,8 +61,32 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox if (!_initializing && chartEditorState.currentNoteSelection.length > 0) { // Edit the note data of any selected notes. + var noteSprites:Array = chartEditorState.renderedNotes.members.copy(); + var holdNoteSprites:Array = chartEditorState.renderedHoldNotes.members.copy(); for (note in chartEditorState.currentNoteSelection) { + // update note sprites + for (noteSprite in noteSprites) + { + if (noteSprite.noteData == note) + { + noteSprite.noteStyle = NoteKindManager.getNoteStyleId(chartEditorState.noteKindToPlace) ?? chartEditorState.currentSongNoteStyle; + noteSprites.remove(noteSprite); + break; + } + } + + // update hold note sprites + for (holdNoteSprite in holdNoteSprites) + { + if (holdNoteSprite.noteData == note) + { + holdNoteSprite.noteStyle = NoteKindManager.getNoteStyleId(chartEditorState.noteKindToPlace) ?? chartEditorState.currentSongNoteStyle; + holdNoteSprites.remove(holdNoteSprite); + break; + } + } + note.kind = chartEditorState.noteKindToPlace; } chartEditorState.saveDataDirty = true; From bb975491712445a272f5e8817e34dacbd62a0d03 Mon Sep 17 00:00:00 2001 From: lemz Date: Mon, 3 Jun 2024 00:03:47 +0200 Subject: [PATCH 481/870] fixed a bit --- .../ui/debug/charting/ChartEditorState.hx | 11 ++++++----- .../components/ChartEditorHoldNoteSprite.hx | 2 ++ .../toolboxes/ChartEditorNoteDataToolbox.hx | 18 +++++++----------- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index bc0acc6d6..c867ddfd2 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -3606,10 +3606,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState holdNoteSprite.noteData = noteSprite.noteData; holdNoteSprite.noteDirection = noteSprite.noteData.getDirection(); - holdNoteSprite.noteStyle = NoteKindManager.getNoteStyleId(noteSprite.noteData.kind) ?? currentSongNoteStyle; holdNoteSprite.setHeightDirectly(noteLengthPixels); + holdNoteSprite.noteStyle = NoteKindManager.getNoteStyleId(noteSprite.noteData.kind) ?? currentSongNoteStyle; + holdNoteSprite.updateHoldNotePosition(renderedHoldNotes); trace(holdNoteSprite.x + ', ' + holdNoteSprite.y + ', ' + holdNoteSprite.width + ', ' + holdNoteSprite.height); @@ -3672,9 +3673,10 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState holdNoteSprite.noteData = noteData; holdNoteSprite.noteDirection = noteData.getDirection(); - holdNoteSprite.noteStyle = NoteKindManager.getNoteStyleId(noteData.kind) ?? currentSongNoteStyle; holdNoteSprite.setHeightDirectly(noteLengthPixels); + holdNoteSprite.noteStyle = NoteKindManager.getNoteStyleId(noteData.kind) ?? currentSongNoteStyle; + holdNoteSprite.updateHoldNotePosition(renderedHoldNotes); displayedHoldNoteData.push(noteData); @@ -4571,9 +4573,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState gridGhostHoldNote.visible = true; gridGhostHoldNote.noteData = currentPlaceNoteData; gridGhostHoldNote.noteDirection = currentPlaceNoteData.getDirection(); - gridGhostHoldNote.noteStyle = NoteKindManager.getNoteStyleId(currentPlaceNoteData.kind) ?? currentSongNoteStyle; gridGhostHoldNote.setHeightDirectly(dragLengthPixels, true); - + gridGhostHoldNote.noteStyle = NoteKindManager.getNoteStyleId(currentPlaceNoteData.kind) ?? currentSongNoteStyle; gridGhostHoldNote.updateHoldNotePosition(renderedHoldNotes); } else @@ -5284,10 +5285,10 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState // Readd the new ghost hold note. ghostHold.noteData = targetNoteData.clone(); ghostHold.noteDirection = ghostHold.noteData.getDirection(); - ghostHold.noteStyle = NoteKindManager.getNoteStyleId(ghostHold.noteData.kind) ?? currentSongNoteStyle; ghostHold.visible = true; ghostHold.alpha = 0.6; ghostHold.setHeightDirectly(0); + ghostHold.noteStyle = NoteKindManager.getNoteStyleId(ghostHold.noteData.kind) ?? currentSongNoteStyle; ghostHold.updateHoldNotePosition(renderedHoldNotes); } diff --git a/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx b/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx index 26322c6f9..e8ca991b6 100644 --- a/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx +++ b/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx @@ -73,6 +73,8 @@ class ChartEditorHoldNoteSprite extends SustainTrail flipY = false; setup(); + + triggerRedraw(); } public override function updateHitbox():Void diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx index d872eda38..531bce255 100644 --- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx @@ -60,34 +60,30 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox if (!_initializing && chartEditorState.currentNoteSelection.length > 0) { - // Edit the note data of any selected notes. - var noteSprites:Array = chartEditorState.renderedNotes.members.copy(); - var holdNoteSprites:Array = chartEditorState.renderedHoldNotes.members.copy(); for (note in chartEditorState.currentNoteSelection) { + // Edit the note data of any selected notes. + note.kind = chartEditorState.noteKindToPlace; + // update note sprites - for (noteSprite in noteSprites) + for (noteSprite in chartEditorState.renderedNotes.members) { if (noteSprite.noteData == note) { - noteSprite.noteStyle = NoteKindManager.getNoteStyleId(chartEditorState.noteKindToPlace) ?? chartEditorState.currentSongNoteStyle; - noteSprites.remove(noteSprite); + noteSprite.noteStyle = NoteKindManager.getNoteStyleId(note.kind) ?? chartEditorState.currentSongNoteStyle; break; } } // update hold note sprites - for (holdNoteSprite in holdNoteSprites) + for (holdNoteSprite in chartEditorState.renderedHoldNotes.members) { if (holdNoteSprite.noteData == note) { - holdNoteSprite.noteStyle = NoteKindManager.getNoteStyleId(chartEditorState.noteKindToPlace) ?? chartEditorState.currentSongNoteStyle; - holdNoteSprites.remove(holdNoteSprite); + holdNoteSprite.noteStyle = NoteKindManager.getNoteStyleId(note.kind) ?? chartEditorState.currentSongNoteStyle; break; } } - - note.kind = chartEditorState.noteKindToPlace; } chartEditorState.saveDataDirty = true; chartEditorState.noteDisplayDirty = true; From 49d302be956edb19d470ccfdee3792d3fcdae324 Mon Sep 17 00:00:00 2001 From: lemz Date: Wed, 5 Jun 2024 19:47:34 +0200 Subject: [PATCH 482/870] make code a bit simpler --- .../components/ChartEditorHoldNoteSprite.hx | 36 ++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx b/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx index e8ca991b6..e474ee93d 100644 --- a/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx +++ b/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx @@ -48,15 +48,6 @@ class ChartEditorHoldNoteSprite extends SustainTrail super(0, 100, noteStyle); this.parentState = parent; - - zoom = 1.0; - zoom *= noteStyle.fetchHoldNoteScale(); - zoom *= 0.7; - zoom *= ChartEditorState.GRID_SIZE / Strumline.STRUMLINE_SIZE; - - flipY = false; - - setup(); } @:nullSafety(Off) @@ -64,17 +55,38 @@ class ChartEditorHoldNoteSprite extends SustainTrail { var bruhStyle:NoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyle); setupHoldNoteGraphic(bruhStyle); + } + + override function setupHoldNoteGraphic(noteStyle:NoteStyle):Void + { + loadGraphic(noteStyle.getHoldNoteAssetPath()); + + antialiasing = true; + + this.isPixel = noteStyle.isHoldNotePixel(); + if (isPixel) + { + endOffset = bottomClip = 1; + antialiasing = false; + } zoom = 1.0; - zoom *= bruhStyle.fetchHoldNoteScale(); + zoom *= noteStyle.fetchHoldNoteScale(); zoom *= 0.7; zoom *= ChartEditorState.GRID_SIZE / Strumline.STRUMLINE_SIZE; + graphicWidth = graphic.width / 8 * zoom; // amount of notes * 2 + graphicHeight = sustainLength * 0.45; // sustainHeight + flipY = false; - setup(); + alpha = 1.0; - triggerRedraw(); + updateColorTransform(); + + updateClipping(); + + setup(); } public override function updateHitbox():Void From c4855c0ca8e6e77d62b32b705c40ab0a0e106c11 Mon Sep 17 00:00:00 2001 From: lemz Date: Tue, 11 Jun 2024 20:52:08 +0200 Subject: [PATCH 483/870] fix hold note --- source/funkin/play/notes/SustainTrail.hx | 5 +++++ .../debug/charting/components/ChartEditorHoldNoteSprite.hx | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/source/funkin/play/notes/SustainTrail.hx b/source/funkin/play/notes/SustainTrail.hx index 570c05190..90b36b009 100644 --- a/source/funkin/play/notes/SustainTrail.hx +++ b/source/funkin/play/notes/SustainTrail.hx @@ -129,6 +129,11 @@ class SustainTrail extends FlxSprite endOffset = bottomClip = 1; antialiasing = false; } + else + { + endOffset = 0.5; + bottomClip = 0.9; + } zoom = 1.0; zoom *= noteStyle.fetchHoldNoteScale(); diff --git a/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx b/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx index e474ee93d..b8d6ee22e 100644 --- a/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx +++ b/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx @@ -69,6 +69,11 @@ class ChartEditorHoldNoteSprite extends SustainTrail endOffset = bottomClip = 1; antialiasing = false; } + else + { + endOffset = 0.5; + bottomClip = 0.9; + } zoom = 1.0; zoom *= noteStyle.fetchHoldNoteScale(); From 928de7b8eb8861878b2e78a3502a8ee64b2784d9 Mon Sep 17 00:00:00 2001 From: lemz Date: Tue, 11 Jun 2024 23:45:08 +0200 Subject: [PATCH 484/870] check for pixel style if necessary --- source/funkin/play/notes/Strumline.hx | 4 ++-- source/funkin/play/notes/notekind/NoteKind.hx | 4 ++-- .../play/notes/notekind/NoteKindManager.hx | 21 +++++++++++++++---- .../ui/debug/charting/ChartEditorState.hx | 17 +++++++++------ 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/source/funkin/play/notes/Strumline.hx b/source/funkin/play/notes/Strumline.hx index ebc48a8c7..86b7a3ee1 100644 --- a/source/funkin/play/notes/Strumline.hx +++ b/source/funkin/play/notes/Strumline.hx @@ -709,7 +709,7 @@ class Strumline extends FlxSpriteGroup if (noteSprite != null) { - var noteKindStyle:NoteStyle = NoteKindManager.getNoteStyle(note.kind) ?? this.noteStyle; + var noteKindStyle:NoteStyle = NoteKindManager.getNoteStyle(note.kind, this.noteStyle.isHoldNotePixel()) ?? this.noteStyle; noteSprite.setupNoteGraphic(noteKindStyle); noteSprite.direction = note.getDirection(); @@ -731,7 +731,7 @@ class Strumline extends FlxSpriteGroup if (holdNoteSprite != null) { - var noteKindStyle:NoteStyle = NoteKindManager.getNoteStyle(note.kind) ?? this.noteStyle; + var noteKindStyle:NoteStyle = NoteKindManager.getNoteStyle(note.kind, this.noteStyle.isHoldNotePixel()) ?? this.noteStyle; holdNoteSprite.setupHoldNoteGraphic(noteKindStyle); holdNoteSprite.parentStrumline = this; diff --git a/source/funkin/play/notes/notekind/NoteKind.hx b/source/funkin/play/notes/notekind/NoteKind.hx index 53393623a..6d7bad77f 100644 --- a/source/funkin/play/notes/notekind/NoteKind.hx +++ b/source/funkin/play/notes/notekind/NoteKind.hx @@ -21,9 +21,9 @@ class NoteKind implements INoteScriptedClass /** * Custom note style */ - public var noteStyleId:String; + public var noteStyleId:Null; - public function new(noteKind:String, description:String = "", noteStyleId:String = "") + public function new(noteKind:String, description:String = "", ?noteStyleId:String) { this.noteKind = noteKind; this.description = description; diff --git a/source/funkin/play/notes/notekind/NoteKindManager.hx b/source/funkin/play/notes/notekind/NoteKindManager.hx index 82b2c4d39..110e1859b 100644 --- a/source/funkin/play/notes/notekind/NoteKindManager.hx +++ b/source/funkin/play/notes/notekind/NoteKindManager.hx @@ -65,11 +65,17 @@ class NoteKindManager /** * Retrieve the note style from the given note kind * @param noteKind note kind name + * @param isPixel whether to use pixel style * @return NoteStyle */ - public static function getNoteStyle(noteKind:String):Null + public static function getNoteStyle(noteKind:String, isPixel:Bool = false):Null { - var noteStyleId:String = noteKinds.get(noteKind)?.noteStyleId ?? ""; + var noteStyleId:Null = getNoteStyleId(noteKind, isPixel); + + if (noteStyleId == null) + { + return null; + } return NoteStyleRegistry.instance.fetchEntry(noteStyleId); } @@ -77,10 +83,17 @@ class NoteKindManager /** * Retrieve the note style id from the given note kind * @param noteKind note kind name + * @param isPixel whether to use pixel style * @return Null */ - public static function getNoteStyleId(noteKind:String):Null + public static function getNoteStyleId(noteKind:String, isPixel:Bool = false):Null { - return noteKinds.get(noteKind)?.noteStyleId; + var noteStyleId:Null = noteKinds.get(noteKind)?.noteStyleId; + if (isPixel && noteStyleId != null) + { + noteStyleId = NoteStyleRegistry.instance.hasEntry('$noteStyleId-pixel') ? '$noteStyleId-pixel' : noteStyleId; + } + + return noteStyleId; } } diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index c867ddfd2..2a07be52d 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -3585,7 +3585,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState // The note sprite handles animation playback and positioning. noteSprite.noteData = noteData; - noteSprite.noteStyle = NoteKindManager.getNoteStyleId(noteData.kind) ?? currentSongNoteStyle; + noteSprite.noteStyle = NoteKindManager.getNoteStyleId(noteData.kind, isPixelStyle()) ?? currentSongNoteStyle; noteSprite.overrideStepTime = null; noteSprite.overrideData = null; @@ -3609,7 +3609,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState holdNoteSprite.setHeightDirectly(noteLengthPixels); - holdNoteSprite.noteStyle = NoteKindManager.getNoteStyleId(noteSprite.noteData.kind) ?? currentSongNoteStyle; + holdNoteSprite.noteStyle = NoteKindManager.getNoteStyleId(noteSprite.noteData.kind, isPixelStyle()) ?? currentSongNoteStyle; holdNoteSprite.updateHoldNotePosition(renderedHoldNotes); @@ -3675,7 +3675,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState holdNoteSprite.noteDirection = noteData.getDirection(); holdNoteSprite.setHeightDirectly(noteLengthPixels); - holdNoteSprite.noteStyle = NoteKindManager.getNoteStyleId(noteData.kind) ?? currentSongNoteStyle; + holdNoteSprite.noteStyle = NoteKindManager.getNoteStyleId(noteData.kind, isPixelStyle()) ?? currentSongNoteStyle; holdNoteSprite.updateHoldNotePosition(renderedHoldNotes); @@ -4574,7 +4574,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState gridGhostHoldNote.noteData = currentPlaceNoteData; gridGhostHoldNote.noteDirection = currentPlaceNoteData.getDirection(); gridGhostHoldNote.setHeightDirectly(dragLengthPixels, true); - gridGhostHoldNote.noteStyle = NoteKindManager.getNoteStyleId(currentPlaceNoteData.kind) ?? currentSongNoteStyle; + gridGhostHoldNote.noteStyle = NoteKindManager.getNoteStyleId(currentPlaceNoteData.kind, isPixelStyle()) ?? currentSongNoteStyle; gridGhostHoldNote.updateHoldNotePosition(renderedHoldNotes); } else @@ -4896,7 +4896,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState { noteData.kind = noteKindToPlace; noteData.data = cursorColumn; - gridGhostNote.noteStyle = NoteKindManager.getNoteStyleId(noteData.kind) ?? currentSongNoteStyle; + gridGhostNote.noteStyle = NoteKindManager.getNoteStyleId(noteData.kind, isPixelStyle()) ?? currentSongNoteStyle; gridGhostNote.playNoteAnimation(); } noteData.time = cursorSnappedMs; @@ -5288,7 +5288,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState ghostHold.visible = true; ghostHold.alpha = 0.6; ghostHold.setHeightDirectly(0); - ghostHold.noteStyle = NoteKindManager.getNoteStyleId(ghostHold.noteData.kind) ?? currentSongNoteStyle; + ghostHold.noteStyle = NoteKindManager.getNoteStyleId(ghostHold.noteData.kind, isPixelStyle()) ?? currentSongNoteStyle; ghostHold.updateHoldNotePosition(renderedHoldNotes); } @@ -6413,6 +6413,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState return note != null && currentNoteSelection.indexOf(note) != -1; } + function isPixelStyle():Bool + { + return currentSongNoteStyle == 'pixel'; + } + override function destroy():Void { super.destroy(); From 7a0c7ade357a7e6151295b182650dd807e52390f Mon Sep 17 00:00:00 2001 From: lemz Date: Tue, 11 Jun 2024 23:48:05 +0200 Subject: [PATCH 485/870] Update ChartEditorDropdowns.hx --- source/funkin/ui/debug/charting/util/ChartEditorDropdowns.hx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/funkin/ui/debug/charting/util/ChartEditorDropdowns.hx b/source/funkin/ui/debug/charting/util/ChartEditorDropdowns.hx index f20b75650..65ec2a0c3 100644 --- a/source/funkin/ui/debug/charting/util/ChartEditorDropdowns.hx +++ b/source/funkin/ui/debug/charting/util/ChartEditorDropdowns.hx @@ -126,7 +126,10 @@ class ChartEditorDropdowns { dropDown.dataSource.clear(); - var noteStyleIds:Array = NoteStyleRegistry.instance.listEntryIds(); + // hardcoding this because i dont want note kind styles to be shown as well + // there is probably a better solution + // var noteStyleIds:Array = NoteStyleRegistry.instance.listEntryIds(); + var noteStyleIds:Array = ['funkin', 'pixel']; var returnValue:DropDownEntry = {id: "funkin", text: "Funkin'"}; From fbcc73dceebdcfcba2b14922c6b7c38adae0b086 Mon Sep 17 00:00:00 2001 From: lemz Date: Mon, 17 Jun 2024 17:21:52 +0200 Subject: [PATCH 486/870] unhardcode notestyledropdown --- .../ui/debug/charting/util/ChartEditorDropdowns.hx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/source/funkin/ui/debug/charting/util/ChartEditorDropdowns.hx b/source/funkin/ui/debug/charting/util/ChartEditorDropdowns.hx index 65ec2a0c3..6a426c391 100644 --- a/source/funkin/ui/debug/charting/util/ChartEditorDropdowns.hx +++ b/source/funkin/ui/debug/charting/util/ChartEditorDropdowns.hx @@ -126,10 +126,7 @@ class ChartEditorDropdowns { dropDown.dataSource.clear(); - // hardcoding this because i dont want note kind styles to be shown as well - // there is probably a better solution - // var noteStyleIds:Array = NoteStyleRegistry.instance.listEntryIds(); - var noteStyleIds:Array = ['funkin', 'pixel']; + var noteStyleIds:Array = NoteStyleRegistry.instance.listEntryIds(); var returnValue:DropDownEntry = {id: "funkin", text: "Funkin'"}; @@ -138,6 +135,14 @@ class ChartEditorDropdowns var noteStyle:Null = NoteStyleRegistry.instance.fetchEntry(noteStyleId); if (noteStyle == null) continue; + // check if the note style has all necessary assets (strums, notes, holdNotes) + if (noteStyle._data?.assets?.noteStrumline == null + || noteStyle._data?.assets?.note == null + || noteStyle._data?.assets?.holdNote == null) + { + continue; + } + var value = {id: noteStyleId, text: noteStyle.getName()}; if (startingStyleId == noteStyleId) returnValue = value; From acd8912d162d71b3dd11d97e112e64da06815ec9 Mon Sep 17 00:00:00 2001 From: lemz Date: Fri, 21 Jun 2024 23:54:29 +0200 Subject: [PATCH 487/870] Add Custom Params For NoteKind still need to implement the chart editor stuff --- source/funkin/play/notes/notekind/NoteKind.hx | 70 ++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/source/funkin/play/notes/notekind/NoteKind.hx b/source/funkin/play/notes/notekind/NoteKind.hx index 6d7bad77f..6d7ddcd1b 100644 --- a/source/funkin/play/notes/notekind/NoteKind.hx +++ b/source/funkin/play/notes/notekind/NoteKind.hx @@ -23,11 +23,17 @@ class NoteKind implements INoteScriptedClass */ public var noteStyleId:Null; - public function new(noteKind:String, description:String = "", ?noteStyleId:String) + /** + * Custom parameters for the chart editor + */ + public var params:Array; + + public function new(noteKind:String, description:String = "", ?noteStyleId:String, ?params:Array) { this.noteKind = noteKind; this.description = description; this.noteStyleId = noteStyleId; + this.params = params ?? []; } public function toString():String @@ -35,6 +41,25 @@ class NoteKind implements INoteScriptedClass return noteKind; } + /** + * Retrieve the param with the given name + * If there exists no param with the given name then `null` is returned + * @param name Name of the param + * @return Null + */ + public function getParam(name:String):Null + { + for (param in params) + { + if (param.name == name) + { + return param; + } + } + + return null; + } + /** * Retrieve all notes of this kind * @return Array @@ -61,3 +86,46 @@ class NoteKind implements INoteScriptedClass public function onNoteMiss(event:NoteScriptEvent):Void {} } + +/** + * Abstract for setting the type of the `NoteKindParam` + * This was supposed to be an enum but polymod kept being annoying + */ +abstract NoteKindParamType(String) +{ + public static var STRING:String = "String"; + + public static var INT:String = "Int"; + + public static var RANGED_INT:String = "RangedInt"; + + public static var FLOAT:String = "Float"; + + public static var RANGED_FLOAT:String = "RangedFloat"; +} + +typedef NoteKindParamData = +{ + /** + * Only used for `RangedInt` and `RangedFloat` + */ + var min:Null; + + /** + * Only used for `RangedInt` and `RangedFloat` + */ + var max:Null; + + var value:Dynamic; +} + +/** + * Typedef for creating custom parameters in the chart editor + */ +typedef NoteKindParam = +{ + var name:String; + var description:String; + var type:NoteKindParamType; + var data:NoteKindParamData; +} From c8d019da2fdcc22627dbfb78c587a5374273f6b6 Mon Sep 17 00:00:00 2001 From: lemz Date: Sat, 22 Jun 2024 00:20:58 +0200 Subject: [PATCH 488/870] Update NoteKind.hx --- source/funkin/play/notes/notekind/NoteKind.hx | 38 ++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/source/funkin/play/notes/notekind/NoteKind.hx b/source/funkin/play/notes/notekind/NoteKind.hx index 6d7ddcd1b..3aa02088b 100644 --- a/source/funkin/play/notes/notekind/NoteKind.hx +++ b/source/funkin/play/notes/notekind/NoteKind.hx @@ -2,6 +2,7 @@ package funkin.play.notes.notekind; import funkin.modding.IScriptedClass.INoteScriptedClass; import funkin.modding.events.ScriptEvent; +import flixel.math.FlxMath; /** * Class for note scripts @@ -42,24 +43,49 @@ class NoteKind implements INoteScriptedClass } /** - * Retrieve the param with the given name + * Retrieve the value of the param with the given name * If there exists no param with the given name then `null` is returned * @param name Name of the param - * @return Null + * @return Null */ - public function getParam(name:String):Null + public function getParam(name:String):Null { for (param in params) { if (param.name == name) { - return param; + return param.data.value; } } return null; } + /** + * Set the value of the param with the given name + * @param name Name of the param + * @param value New value + */ + public function setParam(name:String, value:Dynamic):Void + { + for (param in params) + { + if (param.name == name) + { + if (param.type == NoteKindParamType.RANGED_INT || param.type == NoteKindParamType.RANGED_FLOAT) + { + param.data.value = FlxMath.bound(value, param.data.min, param.data.max); + } + else + { + param.data.value = value; + } + + break; + } + } + } + /** * Retrieve all notes of this kind * @return Array @@ -91,7 +117,7 @@ class NoteKind implements INoteScriptedClass * Abstract for setting the type of the `NoteKindParam` * This was supposed to be an enum but polymod kept being annoying */ -abstract NoteKindParamType(String) +abstract NoteKindParamType(String) to String { public static var STRING:String = "String"; @@ -108,11 +134,13 @@ typedef NoteKindParamData = { /** * Only used for `RangedInt` and `RangedFloat` + * If `min` is null, there is no minimum */ var min:Null; /** * Only used for `RangedInt` and `RangedFloat` + * If `max` is null, there is no maximum */ var max:Null; From 94fe4a06b90089fb8187c177c39cb255c90609fb Mon Sep 17 00:00:00 2001 From: lemz Date: Sat, 22 Jun 2024 10:44:12 +0200 Subject: [PATCH 489/870] Update NoteKind.hx --- source/funkin/play/notes/notekind/NoteKind.hx | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/source/funkin/play/notes/notekind/NoteKind.hx b/source/funkin/play/notes/notekind/NoteKind.hx index 3aa02088b..a0f759949 100644 --- a/source/funkin/play/notes/notekind/NoteKind.hx +++ b/source/funkin/play/notes/notekind/NoteKind.hx @@ -72,13 +72,12 @@ class NoteKind implements INoteScriptedClass { if (param.name == name) { - if (param.type == NoteKindParamType.RANGED_INT || param.type == NoteKindParamType.RANGED_FLOAT) + switch (param.type) { - param.data.value = FlxMath.bound(value, param.data.min, param.data.max); - } - else - { - param.data.value = value; + case NoteKindParamType.INT | NoteKindParamType.FLOAT: + param.data.value = FlxMath.bound(value, param.data.min, param.data.max); + default: + param.data.value = value; } break; @@ -123,23 +122,17 @@ abstract NoteKindParamType(String) to String public static var INT:String = "Int"; - public static var RANGED_INT:String = "RangedInt"; - public static var FLOAT:String = "Float"; - - public static var RANGED_FLOAT:String = "RangedFloat"; } typedef NoteKindParamData = { /** - * Only used for `RangedInt` and `RangedFloat` * If `min` is null, there is no minimum */ var min:Null; /** - * Only used for `RangedInt` and `RangedFloat` * If `max` is null, there is no maximum */ var max:Null; From 9a563ec46b56e4daacd70f301c1d107347e6738f Mon Sep 17 00:00:00 2001 From: lemz Date: Sat, 22 Jun 2024 10:52:26 +0200 Subject: [PATCH 490/870] switch seemingly doesnt work --- source/funkin/play/notes/notekind/NoteKind.hx | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/source/funkin/play/notes/notekind/NoteKind.hx b/source/funkin/play/notes/notekind/NoteKind.hx index a0f759949..f2a44dc8a 100644 --- a/source/funkin/play/notes/notekind/NoteKind.hx +++ b/source/funkin/play/notes/notekind/NoteKind.hx @@ -72,12 +72,13 @@ class NoteKind implements INoteScriptedClass { if (param.name == name) { - switch (param.type) + if (param.type == NoteKindParamType.INT || param.type == NoteKindParamType.FLOAT) { - case NoteKindParamType.INT | NoteKindParamType.FLOAT: - param.data.value = FlxMath.bound(value, param.data.min, param.data.max); - default: - param.data.value = value; + param.data.value = FlxMath.bound(value, param.data.min, param.data.max); + } + else + { + param.data.value = value; } break; @@ -118,11 +119,11 @@ class NoteKind implements INoteScriptedClass */ abstract NoteKindParamType(String) to String { - public static var STRING:String = "String"; + public static final STRING:String = 'String'; - public static var INT:String = "Int"; + public static final INT:String = 'Int'; - public static var FLOAT:String = "Float"; + public static final FLOAT:String = 'Float'; } typedef NoteKindParamData = From d9b9854d9106d20d2ea7ec75468fcc315b281e98 Mon Sep 17 00:00:00 2001 From: lemz Date: Sat, 22 Jun 2024 14:17:07 +0200 Subject: [PATCH 491/870] add params to toolbox not completely finished --- .../play/notes/notekind/NoteKindManager.hx | 10 +++ .../toolboxes/ChartEditorNoteDataToolbox.hx | 73 ++++++++++++++++++- 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/source/funkin/play/notes/notekind/NoteKindManager.hx b/source/funkin/play/notes/notekind/NoteKindManager.hx index 110e1859b..3e2174a66 100644 --- a/source/funkin/play/notes/notekind/NoteKindManager.hx +++ b/source/funkin/play/notes/notekind/NoteKindManager.hx @@ -96,4 +96,14 @@ class NoteKindManager return noteStyleId; } + + /** + * Retrive custom params of the given note kind + * @param noteKind Name of the note kind + * @return Array + */ + public static function getParams(noteKind:String):Array + { + return noteKinds.get(noteKind)?.params ?? []; + } } diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx index 531bce255..472372a6e 100644 --- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx @@ -2,11 +2,12 @@ package funkin.ui.debug.charting.toolboxes; import haxe.ui.components.DropDown; import haxe.ui.components.TextField; +import haxe.ui.components.Label; +import haxe.ui.components.NumberStepper; +import haxe.ui.containers.Grid; +import haxe.ui.core.Component; import haxe.ui.events.UIEvent; import funkin.ui.debug.charting.util.ChartEditorDropdowns; -import funkin.ui.debug.charting.components.ChartEditorNoteSprite; -import funkin.ui.debug.charting.components.ChartEditorHoldNoteSprite; -import funkin.play.notes.notestyle.NoteStyle; import funkin.play.notes.notekind.NoteKindManager; /** @@ -16,8 +17,12 @@ import funkin.play.notes.notekind.NoteKindManager; @:build(haxe.ui.ComponentBuilder.build("assets/exclude/data/ui/chart-editor/toolboxes/note-data.xml")) class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox { + static final DIALOG_HEIGHT:Int = 100; + + var toolboxNotesGrid:Grid; var toolboxNotesNoteKind:DropDown; var toolboxNotesCustomKind:TextField; + var toolboxNotesParams:Array = []; var _initializing:Bool = true; @@ -49,6 +54,7 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox if (noteKind == '~CUSTOM~') { showCustom(); + clearNoteKindParams(); toolboxNotesCustomKind.value = chartEditorState.noteKindToPlace; } else @@ -56,6 +62,25 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox hideCustom(); chartEditorState.noteKindToPlace = noteKind; toolboxNotesCustomKind.value = chartEditorState.noteKindToPlace; + + clearNoteKindParams(); + for (param in NoteKindManager.getParams(noteKind)) + { + var paramLabel:Label = new Label(); + paramLabel.value = param.description; + paramLabel.verticalAlign = "center"; + paramLabel.horizontalAlign = "right"; + + var paramStepper:NumberStepper = new NumberStepper(); + paramStepper.min = param.data.min; + paramStepper.max = param.data.max; + paramStepper.value = param.data.value; + paramStepper.precision = 1; + paramStepper.step = 0.1; + paramStepper.percentWidth = 100; + + addNoteKindParam(paramLabel, paramStepper); + } } if (!_initializing && chartEditorState.currentNoteSelection.length > 0) @@ -110,6 +135,9 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox } }; toolboxNotesCustomKind.value = chartEditorState.noteKindToPlace; + + // just to be safe + clearNoteKindParams(); } public override function refresh():Void @@ -132,8 +160,47 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox toolboxNotesCustomKind.hidden = true; } + function addNoteKindParam(label:Label, component:Component):Void + { + toolboxNotesParams.push({label: label, component: component}); + toolboxNotesGrid.addComponent(label); + toolboxNotesGrid.addComponent(component); + + this.height = Math.max(DIALOG_HEIGHT, DIALOG_HEIGHT - 30 + toolboxNotesParams.length * 30); + } + + override function update(elapsed:Float):Void + { + super.update(elapsed); + + // toolboxNotesGrid.height + 45 + // this is what i found out is the calculation by printing this.height and grid.height + var heightToSet:Int = Std.int(Math.max(DIALOG_HEIGHT, toolboxNotesGrid.height + 45)); + if (this.height != heightToSet) + { + this.height = heightToSet; + } + } + + function clearNoteKindParams():Void + { + for (param in toolboxNotesParams) + { + toolboxNotesGrid.removeComponent(param.component); + toolboxNotesGrid.removeComponent(param.label); + } + toolboxNotesParams = []; + this.height = DIALOG_HEIGHT; + } + public static function build(chartEditorState:ChartEditorState):ChartEditorNoteDataToolbox { return new ChartEditorNoteDataToolbox(chartEditorState); } } + +typedef ToolboxNoteKindParam = +{ + var label:Label; + var component:Component; +} From 93475ae8aa94ff5d12872dd5ebe4b1e207d3d85e Mon Sep 17 00:00:00 2001 From: lemz Date: Sat, 22 Jun 2024 14:31:07 +0200 Subject: [PATCH 492/870] minimized check --- .../charting/toolboxes/ChartEditorNoteDataToolbox.hx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx index 472372a6e..c557eef1f 100644 --- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx @@ -135,9 +135,6 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox } }; toolboxNotesCustomKind.value = chartEditorState.noteKindToPlace; - - // just to be safe - clearNoteKindParams(); } public override function refresh():Void @@ -173,6 +170,12 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox { super.update(elapsed); + // current dialog is minimized, dont change the height + if (this.minimized) + { + return; + } + // toolboxNotesGrid.height + 45 // this is what i found out is the calculation by printing this.height and grid.height var heightToSet:Int = Std.int(Math.max(DIALOG_HEIGHT, toolboxNotesGrid.height + 45)); From 437cc68ba7af70f4060efc739dfc6d3ff21bbeed Mon Sep 17 00:00:00 2001 From: lemz Date: Sat, 22 Jun 2024 14:49:04 +0200 Subject: [PATCH 493/870] adapt to minimize problem --- .../toolboxes/ChartEditorNoteDataToolbox.hx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx index c557eef1f..278fc1fd6 100644 --- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx @@ -17,8 +17,18 @@ import funkin.play.notes.notekind.NoteKindManager; @:build(haxe.ui.ComponentBuilder.build("assets/exclude/data/ui/chart-editor/toolboxes/note-data.xml")) class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox { + // 100 is the height used in note-data.xml static final DIALOG_HEIGHT:Int = 100; + // toolboxNotesGrid.height + 45 + // this is what i found out by printing this.height and grid.height + // and then seeing that this.height is 100 and grid.height is 55 + static final HEIGHT_OFFSET:Int = 45; + + // minimizing creates a gray bar the bottom, which would obscure the components, + // which is why we use an extra offset of 20 + static final MINIMIZE_FIX:Int = 20; + var toolboxNotesGrid:Grid; var toolboxNotesNoteKind:DropDown; var toolboxNotesCustomKind:TextField; @@ -176,9 +186,7 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox return; } - // toolboxNotesGrid.height + 45 - // this is what i found out is the calculation by printing this.height and grid.height - var heightToSet:Int = Std.int(Math.max(DIALOG_HEIGHT, toolboxNotesGrid.height + 45)); + var heightToSet:Int = Std.int(Math.max(DIALOG_HEIGHT, toolboxNotesGrid.height + HEIGHT_OFFSET)) + MINIMIZE_FIX; if (this.height != heightToSet) { this.height = heightToSet; From 0fe726cefa926b2e4de6963acc0284090e2fed99 Mon Sep 17 00:00:00 2001 From: lemz Date: Sat, 22 Jun 2024 15:38:04 +0200 Subject: [PATCH 494/870] fix min, max --- source/funkin/play/notes/notekind/NoteKind.hx | 58 +++---------------- .../toolboxes/ChartEditorNoteDataToolbox.hx | 14 ++++- 2 files changed, 18 insertions(+), 54 deletions(-) diff --git a/source/funkin/play/notes/notekind/NoteKind.hx b/source/funkin/play/notes/notekind/NoteKind.hx index f2a44dc8a..7efa93de6 100644 --- a/source/funkin/play/notes/notekind/NoteKind.hx +++ b/source/funkin/play/notes/notekind/NoteKind.hx @@ -42,50 +42,6 @@ class NoteKind implements INoteScriptedClass return noteKind; } - /** - * Retrieve the value of the param with the given name - * If there exists no param with the given name then `null` is returned - * @param name Name of the param - * @return Null - */ - public function getParam(name:String):Null - { - for (param in params) - { - if (param.name == name) - { - return param.data.value; - } - } - - return null; - } - - /** - * Set the value of the param with the given name - * @param name Name of the param - * @param value New value - */ - public function setParam(name:String, value:Dynamic):Void - { - for (param in params) - { - if (param.name == name) - { - if (param.type == NoteKindParamType.INT || param.type == NoteKindParamType.FLOAT) - { - param.data.value = FlxMath.bound(value, param.data.min, param.data.max); - } - else - { - param.data.value = value; - } - - break; - } - } - } - /** * Retrieve all notes of this kind * @return Array @@ -131,14 +87,14 @@ typedef NoteKindParamData = /** * If `min` is null, there is no minimum */ - var min:Null; + ?min:Null, /** * If `max` is null, there is no maximum */ - var max:Null; + ?max:Null, - var value:Dynamic; + defaultValue:Dynamic } /** @@ -146,8 +102,8 @@ typedef NoteKindParamData = */ typedef NoteKindParam = { - var name:String; - var description:String; - var type:NoteKindParamType; - var data:NoteKindParamData; + name:String, + description:String, + type:NoteKindParamType, + data:NoteKindParamData } diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx index 278fc1fd6..751af5dff 100644 --- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx @@ -82,13 +82,21 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox paramLabel.horizontalAlign = "right"; var paramStepper:NumberStepper = new NumberStepper(); - paramStepper.min = param.data.min; - paramStepper.max = param.data.max; - paramStepper.value = param.data.value; + paramStepper.value = param.data.defaultValue; paramStepper.precision = 1; paramStepper.step = 0.1; paramStepper.percentWidth = 100; + // this check should be unnecessary but for some reason even when min or max is null it will set it to 0 + if (param.data.min != null) + { + paramStepper.min = param.data.min; + } + if (param.data.max != null) + { + paramStepper.max = param.data.max; + } + addNoteKindParam(paramLabel, paramStepper); } } From 764cdee63de762395f070916369a99bc6d81c80d Mon Sep 17 00:00:00 2001 From: lemz Date: Sat, 22 Jun 2024 15:48:07 +0200 Subject: [PATCH 495/870] add more options --- source/funkin/play/notes/notekind/NoteKind.hx | 10 ++++++++++ .../charting/toolboxes/ChartEditorNoteDataToolbox.hx | 10 +++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/source/funkin/play/notes/notekind/NoteKind.hx b/source/funkin/play/notes/notekind/NoteKind.hx index 7efa93de6..a06670503 100644 --- a/source/funkin/play/notes/notekind/NoteKind.hx +++ b/source/funkin/play/notes/notekind/NoteKind.hx @@ -94,6 +94,16 @@ typedef NoteKindParamData = */ ?max:Null, + /** + * If `step` is null, it will use 1.0 + */ + ?step:Null, + + /** + * If `precision` is null, there will be 0 decimal places + */ + ?precision:Null, + defaultValue:Dynamic } diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx index 751af5dff..26e495dcc 100644 --- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx @@ -83,11 +83,11 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox var paramStepper:NumberStepper = new NumberStepper(); paramStepper.value = param.data.defaultValue; - paramStepper.precision = 1; - paramStepper.step = 0.1; paramStepper.percentWidth = 100; + paramStepper.step = param.data.step ?? 1; - // this check should be unnecessary but for some reason even when min or max is null it will set it to 0 + // this check should be unnecessary but for some reason + // even when these are null it will set it to 0 if (param.data.min != null) { paramStepper.min = param.data.min; @@ -96,6 +96,10 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox { paramStepper.max = param.data.max; } + if (param.data.precision != null) + { + paramStepper.precision = param.data.precision; + } addNoteKindParam(paramLabel, paramStepper); } From c41d846df5dfd5331dad37e71aa4d2b18595b3a9 Mon Sep 17 00:00:00 2001 From: lemz Date: Sat, 22 Jun 2024 20:49:30 +0200 Subject: [PATCH 496/870] store params in chart chart editor still doesnt fully work --- source/funkin/data/song/SongData.hx | 41 +++++++++++++++++-- source/funkin/play/notes/NoteSprite.hx | 34 +++++++++++++++ .../play/notes/notekind/NoteKindManager.hx | 5 ++- .../ui/debug/charting/ChartEditorState.hx | 19 ++++++--- .../toolboxes/ChartEditorNoteDataToolbox.hx | 24 ++++++++++- 5 files changed, 111 insertions(+), 12 deletions(-) diff --git a/source/funkin/data/song/SongData.hx b/source/funkin/data/song/SongData.hx index 769af8f08..6bbeb4435 100644 --- a/source/funkin/data/song/SongData.hx +++ b/source/funkin/data/song/SongData.hx @@ -951,12 +951,18 @@ class SongNoteDataRaw implements ICloneable return this.kind = value; } - public function new(time:Float, data:Int, length:Float = 0, kind:String = '') + @:alias("p") + @:default([]) + @:optional + public var params:Array; + + public function new(time:Float, data:Int, length:Float = 0, kind:String = '', ?params:Array) { this.time = time; this.data = data; this.length = length; this.kind = kind; + this.params = params ?? []; } /** @@ -1053,7 +1059,7 @@ class SongNoteDataRaw implements ICloneable public function clone():SongNoteDataRaw { - return new SongNoteDataRaw(this.time, this.data, this.length, this.kind); + return new SongNoteDataRaw(this.time, this.data, this.length, this.kind, this.params); } public function toString():String @@ -1069,9 +1075,9 @@ class SongNoteDataRaw implements ICloneable @:forward abstract SongNoteData(SongNoteDataRaw) from SongNoteDataRaw to SongNoteDataRaw { - public function new(time:Float, data:Int, length:Float = 0, kind:String = '') + public function new(time:Float, data:Int, length:Float = 0, kind:String = '', ?params:Array) { - this = new SongNoteDataRaw(time, data, length, kind); + this = new SongNoteDataRaw(time, data, length, kind, params); } public static function buildDirectionName(data:Int, strumlineSize:Int = 4):String @@ -1183,3 +1189,30 @@ abstract SongNoteData(SongNoteDataRaw) from SongNoteDataRaw to SongNoteDataRaw + (this.kind != '' ? ' [kind: ${this.kind}])' : ')'); } } + +class NoteParamData implements ICloneable +{ + @:alias("n") + public var name:String; + + @:alias("v") + @:jcustomparse(funkin.data.DataParse.dynamicValue) + @:jcustomwrite(funkin.data.DataWrite.dynamicValue) + public var value:Dynamic; + + public function new(name:String, value:Dynamic) + { + this.name = name; + this.value = value; + } + + public function clone():NoteParamData + { + return new NoteParamData(this.name, this.value); + } + + public function toString():String + { + return 'NoteParamData(${this.name}, ${this.value})'; + } +} diff --git a/source/funkin/play/notes/NoteSprite.hx b/source/funkin/play/notes/NoteSprite.hx index 17a5e57fc..d8d471496 100644 --- a/source/funkin/play/notes/NoteSprite.hx +++ b/source/funkin/play/notes/NoteSprite.hx @@ -1,6 +1,7 @@ package funkin.play.notes; import funkin.data.song.SongData.SongNoteData; +import funkin.data.song.SongData.NoteParamData; import funkin.play.notes.notestyle.NoteStyle; import flixel.graphics.frames.FlxAtlasFrames; import flixel.FlxSprite; @@ -65,6 +66,22 @@ class NoteSprite extends FunkinSprite return this.noteData.kind = value; } + /** + * An array of custom parameters for this note + */ + public var params(get, set):Array; + + function get_params():Array + { + return this.noteData?.params ?? []; + } + + function set_params(value:Array):Array + { + if (this.noteData == null) return value; + return this.noteData.params = value; + } + /** * The data of the note (i.e. the direction.) */ @@ -154,6 +171,23 @@ class NoteSprite extends FunkinSprite this.shader = hsvShader; } + /** + * Retrieve the value of the param with the given name + * @param name Name of the param + * @return Null + */ + public function getParam(name:String):Null + { + for (param in params) + { + if (param.name == name) + { + return param.value; + } + } + return null; + } + #if FLX_DEBUG /** * Call this to override how debug bounding boxes are drawn for this sprite. diff --git a/source/funkin/play/notes/notekind/NoteKindManager.hx b/source/funkin/play/notes/notekind/NoteKindManager.hx index 3e2174a66..30eede978 100644 --- a/source/funkin/play/notes/notekind/NoteKindManager.hx +++ b/source/funkin/play/notes/notekind/NoteKindManager.hx @@ -5,6 +5,7 @@ import funkin.modding.events.ScriptEvent; import funkin.ui.debug.charting.util.ChartEditorDropdowns; import funkin.data.notestyle.NoteStyleRegistry; import funkin.play.notes.notestyle.NoteStyle; +import funkin.play.notes.notekind.NoteKind.NoteKindParam; class NoteKindManager { @@ -100,9 +101,9 @@ class NoteKindManager /** * Retrive custom params of the given note kind * @param noteKind Name of the note kind - * @return Array + * @return Array */ - public static function getParams(noteKind:String):Array + public static function getParams(noteKind:String):Array { return noteKinds.get(noteKind)?.params ?? []; } diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 2a07be52d..22de29849 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -35,6 +35,7 @@ import funkin.data.song.SongData.SongEventData; import funkin.data.song.SongData.SongMetadata; import funkin.data.song.SongData.SongNoteData; import funkin.data.song.SongData.SongOffsets; +import funkin.data.song.SongData.NoteParamData; import funkin.data.song.SongDataUtils; import funkin.data.song.SongRegistry; import funkin.data.stage.StageData; @@ -539,6 +540,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState */ var noteKindToPlace:Null = null; + /** + * The note params to use for notes being placed in the chart. Defaults to `[]`. + */ + var noteParamsToPlace:Array = []; + /** * The event type to use for events being placed in the chart. Defaults to `''`. */ @@ -2437,7 +2443,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState gridGhostNote = new ChartEditorNoteSprite(this); gridGhostNote.alpha = 0.6; - gridGhostNote.noteData = new SongNoteData(0, 0, 0, ""); + gridGhostNote.noteData = new SongNoteData(0, 0, 0, "", []); gridGhostNote.visible = false; add(gridGhostNote); gridGhostNote.zIndex = 11; @@ -4731,7 +4737,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState else { // Create a note and place it in the chart. - var newNoteData:SongNoteData = new SongNoteData(cursorSnappedMs, cursorColumn, 0, noteKindToPlace); + var newNoteData:SongNoteData = new SongNoteData(cursorSnappedMs, cursorColumn, 0, noteKindToPlace, noteParamsToPlace.clone()); performCommand(new AddNotesCommand([newNoteData], FlxG.keys.pressed.CONTROL)); @@ -4890,11 +4896,13 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState if (gridGhostNote == null) throw "ERROR: Tried to handle cursor, but gridGhostNote is null! Check ChartEditorState.buildGrid()"; - var noteData:SongNoteData = gridGhostNote.noteData != null ? gridGhostNote.noteData : new SongNoteData(cursorMs, cursorColumn, 0, noteKindToPlace); + var noteData:SongNoteData = gridGhostNote.noteData != null ? gridGhostNote.noteData : new SongNoteData(cursorMs, cursorColumn, 0, noteKindToPlace, + noteParamsToPlace.clone()); - if (cursorColumn != noteData.data || noteKindToPlace != noteData.kind) + if (cursorColumn != noteData.data || noteKindToPlace != noteData.kind || noteParamsToPlace != noteData.params) { noteData.kind = noteKindToPlace; + noteData.params = noteParamsToPlace; noteData.data = cursorColumn; gridGhostNote.noteStyle = NoteKindManager.getNoteStyleId(noteData.kind, isPixelStyle()) ?? currentSongNoteStyle; gridGhostNote.playNoteAnimation(); @@ -5202,7 +5210,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState if (notesAtPos.length == 0 && !removeNoteInstead) { trace('Placing note. ${column}'); - var newNoteData:SongNoteData = new SongNoteData(playheadPosSnappedMs, column, 0, noteKindToPlace); + var newNoteData:SongNoteData = new SongNoteData(playheadPosSnappedMs, column, 0, noteKindToPlace, noteParamsToPlace.clone()); performCommand(new AddNotesCommand([newNoteData], FlxG.keys.pressed.CONTROL)); currentLiveInputPlaceNoteData[column] = newNoteData; } @@ -5655,6 +5663,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState FlxG.watch.addQuick('musicTime', audioInstTrack?.time ?? 0.0); FlxG.watch.addQuick('noteKindToPlace', noteKindToPlace); + FlxG.watch.addQuick('noteParamsToPlace', noteParamsToPlace); FlxG.watch.addQuick('eventKindToPlace', eventKindToPlace); FlxG.watch.addQuick('scrollPosInPixels', scrollPositionInPixels); diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx index 26e495dcc..027ffdf81 100644 --- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx @@ -9,6 +9,8 @@ import haxe.ui.core.Component; import haxe.ui.events.UIEvent; import funkin.ui.debug.charting.util.ChartEditorDropdowns; import funkin.play.notes.notekind.NoteKindManager; +import funkin.play.notes.notekind.NoteKind.NoteKindParam; +import funkin.data.song.SongData.NoteParamData; /** * The toolbox which allows modifying information like Note Kind. @@ -60,6 +62,13 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox trace('ChartEditorToolboxHandler.buildToolboxNoteDataLayout() - Note kind changed: $noteKind'); + var noteKindParams:Array = NoteKindManager.getParams(noteKind); + var noteParamData:Array = []; + for (noteKindParam in noteKindParams) + { + noteParamData.push(new NoteParamData(noteKindParam.name, noteKindParam.data.defaultValue)); + } + // Edit the note data to place. if (noteKind == '~CUSTOM~') { @@ -71,10 +80,11 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox { hideCustom(); chartEditorState.noteKindToPlace = noteKind; + chartEditorState.noteParamsToPlace = noteParamData; toolboxNotesCustomKind.value = chartEditorState.noteKindToPlace; clearNoteKindParams(); - for (param in NoteKindManager.getParams(noteKind)) + for (param in noteKindParams) { var paramLabel:Label = new Label(); paramLabel.value = param.description; @@ -107,10 +117,22 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox if (!_initializing && chartEditorState.currentNoteSelection.length > 0) { + for (i in 0...toolboxNotesParams.length) + { + var toolboxComponent:Component = toolboxNotesParams[i].component; + toolboxComponent.onChange = function(event:UIEvent) { + for (note in chartEditorState.currentNoteSelection) + { + note.params[i].value = toolboxComponent.value; + } + } + } + for (note in chartEditorState.currentNoteSelection) { // Edit the note data of any selected notes. note.kind = chartEditorState.noteKindToPlace; + note.params = noteParamData.clone(); // update note sprites for (noteSprite in chartEditorState.renderedNotes.members) From 44d978531727eba19e694ac0bed8e0f1f9c76306 Mon Sep 17 00:00:00 2001 From: lemz Date: Sat, 22 Jun 2024 22:36:39 +0200 Subject: [PATCH 497/870] editing them works now still need to implement String and do some testing --- source/funkin/data/song/SongData.hx | 18 +- .../play/notes/notekind/NoteKindManager.hx | 7 +- .../ui/debug/charting/ChartEditorState.hx | 17 +- .../toolboxes/ChartEditorNoteDataToolbox.hx | 157 +++++++++++------- 4 files changed, 128 insertions(+), 71 deletions(-) diff --git a/source/funkin/data/song/SongData.hx b/source/funkin/data/song/SongData.hx index 6bbeb4435..7bf3f8f19 100644 --- a/source/funkin/data/song/SongData.hx +++ b/source/funkin/data/song/SongData.hx @@ -1057,9 +1057,19 @@ class SongNoteDataRaw implements ICloneable _stepLength = null; } + public function cloneParams():Array + { + var params:Array = []; + for (param in this.params) + { + params.push(param.clone()); + } + return params; + } + public function clone():SongNoteDataRaw { - return new SongNoteDataRaw(this.time, this.data, this.length, this.kind, this.params); + return new SongNoteDataRaw(this.time, this.data, this.length, this.kind, cloneParams()); } public function toString():String @@ -1121,7 +1131,7 @@ abstract SongNoteData(SongNoteDataRaw) from SongNoteDataRaw to SongNoteDataRaw if (other.kind == '' || this.kind == null) return false; } - return this.time == other.time && this.data == other.data && this.length == other.length; + return this.time == other.time && this.data == other.data && this.length == other.length && this.params == other.params; } @:op(A != B) @@ -1140,7 +1150,7 @@ abstract SongNoteData(SongNoteDataRaw) from SongNoteDataRaw to SongNoteDataRaw if (other.kind == '') return true; } - return this.time != other.time || this.data != other.data || this.length != other.length; + return this.time != other.time || this.data != other.data || this.length != other.length || this.params != other.params; } @:op(A > B) @@ -1177,7 +1187,7 @@ abstract SongNoteData(SongNoteDataRaw) from SongNoteDataRaw to SongNoteDataRaw public function clone():SongNoteData { - return new SongNoteData(this.time, this.data, this.length, this.kind); + return new SongNoteData(this.time, this.data, this.length, this.kind, this.params); } /** diff --git a/source/funkin/play/notes/notekind/NoteKindManager.hx b/source/funkin/play/notes/notekind/NoteKindManager.hx index 30eede978..8de3cdcca 100644 --- a/source/funkin/play/notes/notekind/NoteKindManager.hx +++ b/source/funkin/play/notes/notekind/NoteKindManager.hx @@ -103,8 +103,13 @@ class NoteKindManager * @param noteKind Name of the note kind * @return Array */ - public static function getParams(noteKind:String):Array + public static function getParams(noteKind:Null):Array { + if (noteKind == null) + { + return []; + } + return noteKinds.get(noteKind)?.params ?? []; } } diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 22de29849..f7abfba89 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -4737,7 +4737,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState else { // Create a note and place it in the chart. - var newNoteData:SongNoteData = new SongNoteData(cursorSnappedMs, cursorColumn, 0, noteKindToPlace, noteParamsToPlace.clone()); + var newNoteData:SongNoteData = new SongNoteData(cursorSnappedMs, cursorColumn, 0, noteKindToPlace, + ChartEditorState.cloneNoteParams(noteParamsToPlace)); performCommand(new AddNotesCommand([newNoteData], FlxG.keys.pressed.CONTROL)); @@ -4897,7 +4898,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState if (gridGhostNote == null) throw "ERROR: Tried to handle cursor, but gridGhostNote is null! Check ChartEditorState.buildGrid()"; var noteData:SongNoteData = gridGhostNote.noteData != null ? gridGhostNote.noteData : new SongNoteData(cursorMs, cursorColumn, 0, noteKindToPlace, - noteParamsToPlace.clone()); + ChartEditorState.cloneNoteParams(noteParamsToPlace)); if (cursorColumn != noteData.data || noteKindToPlace != noteData.kind || noteParamsToPlace != noteData.params) { @@ -5210,7 +5211,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState if (notesAtPos.length == 0 && !removeNoteInstead) { trace('Placing note. ${column}'); - var newNoteData:SongNoteData = new SongNoteData(playheadPosSnappedMs, column, 0, noteKindToPlace, noteParamsToPlace.clone()); + var newNoteData:SongNoteData = new SongNoteData(playheadPosSnappedMs, column, 0, noteKindToPlace, ChartEditorState.cloneNoteParams(noteParamsToPlace)); performCommand(new AddNotesCommand([newNoteData], FlxG.keys.pressed.CONTROL)); currentLiveInputPlaceNoteData[column] = newNoteData; } @@ -6532,6 +6533,16 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState } return input; } + + public static function cloneNoteParams(paramsToClone:Array):Array + { + var params:Array = []; + for (param in paramsToClone) + { + params.push(param.clone()); + } + return params; + } } /** diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx index 027ffdf81..a81cac5c2 100644 --- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx @@ -62,77 +62,30 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox trace('ChartEditorToolboxHandler.buildToolboxNoteDataLayout() - Note kind changed: $noteKind'); - var noteKindParams:Array = NoteKindManager.getParams(noteKind); - var noteParamData:Array = []; - for (noteKindParam in noteKindParams) - { - noteParamData.push(new NoteParamData(noteKindParam.name, noteKindParam.data.defaultValue)); - } - // Edit the note data to place. if (noteKind == '~CUSTOM~') { showCustom(); - clearNoteKindParams(); toolboxNotesCustomKind.value = chartEditorState.noteKindToPlace; } else { hideCustom(); chartEditorState.noteKindToPlace = noteKind; - chartEditorState.noteParamsToPlace = noteParamData; toolboxNotesCustomKind.value = chartEditorState.noteKindToPlace; - - clearNoteKindParams(); - for (param in noteKindParams) - { - var paramLabel:Label = new Label(); - paramLabel.value = param.description; - paramLabel.verticalAlign = "center"; - paramLabel.horizontalAlign = "right"; - - var paramStepper:NumberStepper = new NumberStepper(); - paramStepper.value = param.data.defaultValue; - paramStepper.percentWidth = 100; - paramStepper.step = param.data.step ?? 1; - - // this check should be unnecessary but for some reason - // even when these are null it will set it to 0 - if (param.data.min != null) - { - paramStepper.min = param.data.min; - } - if (param.data.max != null) - { - paramStepper.max = param.data.max; - } - if (param.data.precision != null) - { - paramStepper.precision = param.data.precision; - } - - addNoteKindParam(paramLabel, paramStepper); - } } + createNoteKindParams(noteKind); + if (!_initializing && chartEditorState.currentNoteSelection.length > 0) { - for (i in 0...toolboxNotesParams.length) - { - var toolboxComponent:Component = toolboxNotesParams[i].component; - toolboxComponent.onChange = function(event:UIEvent) { - for (note in chartEditorState.currentNoteSelection) - { - note.params[i].value = toolboxComponent.value; - } - } - } - for (note in chartEditorState.currentNoteSelection) { // Edit the note data of any selected notes. note.kind = chartEditorState.noteKindToPlace; - note.params = noteParamData.clone(); + trace(note.params); + note.params = ChartEditorState.cloneNoteParams(chartEditorState.noteParamsToPlace); + trace(note.params); // update note sprites for (noteSprite in chartEditorState.renderedNotes.members) @@ -187,6 +140,8 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox toolboxNotesNoteKind.value = ChartEditorDropdowns.lookupNoteKind(chartEditorState.noteKindToPlace); toolboxNotesCustomKind.value = chartEditorState.noteKindToPlace; + + createNoteKindParams(chartEditorState.noteKindToPlace); } function showCustom():Void @@ -201,6 +156,82 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox toolboxNotesCustomKind.hidden = true; } + function createNoteKindParams(noteKind:Null):Void + { + clearNoteKindParams(); + + var setParamsToPlace:Bool = false; + if (!_initializing) + { + for (note in chartEditorState.currentNoteSelection) + { + if (note.kind == chartEditorState.noteKindToPlace) + { + chartEditorState.noteParamsToPlace = ChartEditorState.cloneNoteParams(note.params); + setParamsToPlace = true; + break; + } + } + } + + var noteKindParams:Array = NoteKindManager.getParams(noteKind); + + for (i in 0...noteKindParams.length) + { + var param:NoteKindParam = noteKindParams[i]; + + var paramLabel:Label = new Label(); + paramLabel.value = param.description; + paramLabel.verticalAlign = "center"; + paramLabel.horizontalAlign = "right"; + + var paramStepper:NumberStepper = new NumberStepper(); + paramStepper.value = (setParamsToPlace ? chartEditorState.noteParamsToPlace[i].value : param.data.defaultValue); + paramStepper.percentWidth = 100; + paramStepper.step = param.data.step ?? 1; + + // this check should be unnecessary but for some reason + // even when these are null it will set it to 0 + if (param.data.min != null) + { + paramStepper.min = param.data.min; + } + if (param.data.max != null) + { + paramStepper.max = param.data.max; + } + if (param.data.precision != null) + { + paramStepper.precision = param.data.precision; + } + + paramStepper.onChange = function(event:UIEvent) { + chartEditorState.noteParamsToPlace[i].value = paramStepper.value; + + for (note in chartEditorState.currentNoteSelection) + { + if (note.params[i].name == param.name) + { + note.params[i].value = paramStepper.value; + trace(note.params[i]); + } + } + } + + addNoteKindParam(paramLabel, paramStepper); + } + + if (!setParamsToPlace) + { + var noteParamData:Array = []; + for (param in noteKindParams) + { + noteParamData.push(new NoteParamData(param.name, param.data.defaultValue)); + } + chartEditorState.noteParamsToPlace = noteParamData; + } + } + function addNoteKindParam(label:Label, component:Component):Void { toolboxNotesParams.push({label: label, component: component}); @@ -210,6 +241,17 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox this.height = Math.max(DIALOG_HEIGHT, DIALOG_HEIGHT - 30 + toolboxNotesParams.length * 30); } + function clearNoteKindParams():Void + { + for (param in toolboxNotesParams) + { + toolboxNotesGrid.removeComponent(param.component); + toolboxNotesGrid.removeComponent(param.label); + } + toolboxNotesParams = []; + this.height = DIALOG_HEIGHT; + } + override function update(elapsed:Float):Void { super.update(elapsed); @@ -227,17 +269,6 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox } } - function clearNoteKindParams():Void - { - for (param in toolboxNotesParams) - { - toolboxNotesGrid.removeComponent(param.component); - toolboxNotesGrid.removeComponent(param.label); - } - toolboxNotesParams = []; - this.height = DIALOG_HEIGHT; - } - public static function build(chartEditorState:ChartEditorState):ChartEditorNoteDataToolbox { return new ChartEditorNoteDataToolbox(chartEditorState); From 492af8add4e575d7e648f67911d2fafb006c9219 Mon Sep 17 00:00:00 2001 From: lemz Date: Sun, 23 Jun 2024 15:25:53 +0200 Subject: [PATCH 498/870] String works now --- source/funkin/play/notes/notekind/NoteKind.hx | 4 +- .../toolboxes/ChartEditorNoteDataToolbox.hx | 72 ++++++++++++------- 2 files changed, 49 insertions(+), 27 deletions(-) diff --git a/source/funkin/play/notes/notekind/NoteKind.hx b/source/funkin/play/notes/notekind/NoteKind.hx index a06670503..89c175e54 100644 --- a/source/funkin/play/notes/notekind/NoteKind.hx +++ b/source/funkin/play/notes/notekind/NoteKind.hx @@ -104,7 +104,7 @@ typedef NoteKindParamData = */ ?precision:Null, - defaultValue:Dynamic + ?defaultValue:Dynamic } /** @@ -115,5 +115,5 @@ typedef NoteKindParam = name:String, description:String, type:NoteKindParamType, - data:NoteKindParamData + ?data:NoteKindParamData } diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx index a81cac5c2..264e62c5a 100644 --- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx @@ -10,6 +10,7 @@ import haxe.ui.events.UIEvent; import funkin.ui.debug.charting.util.ChartEditorDropdowns; import funkin.play.notes.notekind.NoteKindManager; import funkin.play.notes.notekind.NoteKind.NoteKindParam; +import funkin.play.notes.notekind.NoteKind.NoteKindParamType; import funkin.data.song.SongData.NoteParamData; /** @@ -83,9 +84,7 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox { // Edit the note data of any selected notes. note.kind = chartEditorState.noteKindToPlace; - trace(note.params); note.params = ChartEditorState.cloneNoteParams(chartEditorState.noteParamsToPlace); - trace(note.params); // update note sprites for (noteSprite in chartEditorState.renderedNotes.members) @@ -185,48 +184,71 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox paramLabel.verticalAlign = "center"; paramLabel.horizontalAlign = "right"; - var paramStepper:NumberStepper = new NumberStepper(); - paramStepper.value = (setParamsToPlace ? chartEditorState.noteParamsToPlace[i].value : param.data.defaultValue); - paramStepper.percentWidth = 100; - paramStepper.step = param.data.step ?? 1; + var paramComponent:Component = null; - // this check should be unnecessary but for some reason - // even when these are null it will set it to 0 - if (param.data.min != null) + final paramType:String = param.type; + switch (paramType) { - paramStepper.min = param.data.min; - } - if (param.data.max != null) - { - paramStepper.max = param.data.max; - } - if (param.data.precision != null) - { - paramStepper.precision = param.data.precision; + case NoteKindParamType.INT | NoteKindParamType.FLOAT: + var paramStepper:NumberStepper = new NumberStepper(); + paramStepper.value = (setParamsToPlace ? chartEditorState.noteParamsToPlace[i].value : param.data?.defaultValue) ?? 0.0; + paramStepper.percentWidth = 100; + paramStepper.step = param.data?.step ?? 1; + + // this check should be unnecessary but for some reason + // even when these are null it will set it to 0 + if (param.data?.min != null) + { + paramStepper.min = param.data.min; + } + if (param.data?.max != null) + { + paramStepper.max = param.data.max; + } + if (param.data?.precision != null) + { + paramStepper.precision = param.data.precision; + } + paramComponent = paramStepper; + + case NoteKindParamType.STRING: + var paramTextField:TextField = new TextField(); + paramTextField.value = (setParamsToPlace ? chartEditorState.noteParamsToPlace[i].value : param.data?.defaultValue) ?? ''; + paramTextField.percentWidth = 100; + paramComponent = paramTextField; } - paramStepper.onChange = function(event:UIEvent) { - chartEditorState.noteParamsToPlace[i].value = paramStepper.value; + if (paramComponent == null) + { + continue; + } + + paramComponent.onChange = function(event:UIEvent) { + chartEditorState.noteParamsToPlace[i].value = paramComponent.value; for (note in chartEditorState.currentNoteSelection) { + if (note.params.length != noteKindParams.length) + { + break; + } + if (note.params[i].name == param.name) { - note.params[i].value = paramStepper.value; - trace(note.params[i]); + note.params[i].value = paramComponent.value; } } } - addNoteKindParam(paramLabel, paramStepper); + addNoteKindParam(paramLabel, paramComponent); } if (!setParamsToPlace) { var noteParamData:Array = []; - for (param in noteKindParams) + for (i in 0...noteKindParams.length) { - noteParamData.push(new NoteParamData(param.name, param.data.defaultValue)); + noteParamData.push(new NoteParamData(noteKindParams[i].name, toolboxNotesParams[i].component.value)); } chartEditorState.noteParamsToPlace = noteParamData; } From f9bccb057a129443148e6031c907045c2ff8fb31 Mon Sep 17 00:00:00 2001 From: lemz Date: Mon, 24 Jun 2024 21:45:58 +0200 Subject: [PATCH 499/870] use suffixes instead of pixel boolean --- source/funkin/play/notes/Strumline.hx | 4 ++-- .../play/notes/notekind/NoteKindManager.hx | 23 +++++++++++-------- .../ui/debug/charting/ChartEditorState.hx | 17 +++++--------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/source/funkin/play/notes/Strumline.hx b/source/funkin/play/notes/Strumline.hx index 86b7a3ee1..5e76afa51 100644 --- a/source/funkin/play/notes/Strumline.hx +++ b/source/funkin/play/notes/Strumline.hx @@ -709,7 +709,7 @@ class Strumline extends FlxSpriteGroup if (noteSprite != null) { - var noteKindStyle:NoteStyle = NoteKindManager.getNoteStyle(note.kind, this.noteStyle.isHoldNotePixel()) ?? this.noteStyle; + var noteKindStyle:NoteStyle = NoteKindManager.getNoteStyle(note.kind, this.noteStyle.id) ?? this.noteStyle; noteSprite.setupNoteGraphic(noteKindStyle); noteSprite.direction = note.getDirection(); @@ -731,7 +731,7 @@ class Strumline extends FlxSpriteGroup if (holdNoteSprite != null) { - var noteKindStyle:NoteStyle = NoteKindManager.getNoteStyle(note.kind, this.noteStyle.isHoldNotePixel()) ?? this.noteStyle; + var noteKindStyle:NoteStyle = NoteKindManager.getNoteStyle(note.kind, this.noteStyle.id) ?? this.noteStyle; holdNoteSprite.setupHoldNoteGraphic(noteKindStyle); holdNoteSprite.parentStrumline = this; diff --git a/source/funkin/play/notes/notekind/NoteKindManager.hx b/source/funkin/play/notes/notekind/NoteKindManager.hx index 8de3cdcca..d97eefcf8 100644 --- a/source/funkin/play/notes/notekind/NoteKindManager.hx +++ b/source/funkin/play/notes/notekind/NoteKindManager.hx @@ -66,12 +66,12 @@ class NoteKindManager /** * Retrieve the note style from the given note kind * @param noteKind note kind name - * @param isPixel whether to use pixel style + * @param suffix Used for song note styles * @return NoteStyle */ - public static function getNoteStyle(noteKind:String, isPixel:Bool = false):Null + public static function getNoteStyle(noteKind:String, ?suffix:String):Null { - var noteStyleId:Null = getNoteStyleId(noteKind, isPixel); + var noteStyleId:Null = getNoteStyleId(noteKind, suffix); if (noteStyleId == null) { @@ -83,16 +83,21 @@ class NoteKindManager /** * Retrieve the note style id from the given note kind - * @param noteKind note kind name - * @param isPixel whether to use pixel style + * @param noteKind Note kind name + * @param suffix Used for song note styles * @return Null */ - public static function getNoteStyleId(noteKind:String, isPixel:Bool = false):Null + public static function getNoteStyleId(noteKind:String, ?suffix:String):Null { - var noteStyleId:Null = noteKinds.get(noteKind)?.noteStyleId; - if (isPixel && noteStyleId != null) + if (suffix == null) { - noteStyleId = NoteStyleRegistry.instance.hasEntry('$noteStyleId-pixel') ? '$noteStyleId-pixel' : noteStyleId; + suffix = ''; + } + + var noteStyleId:Null = noteKinds.get(noteKind)?.noteStyleId; + if (noteStyleId != null) + { + noteStyleId = NoteStyleRegistry.instance.hasEntry('$noteStyleId-$suffix') ? '$noteStyleId-$suffix' : noteStyleId; } return noteStyleId; diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index f7abfba89..d3ddb1bca 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -3591,7 +3591,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState // The note sprite handles animation playback and positioning. noteSprite.noteData = noteData; - noteSprite.noteStyle = NoteKindManager.getNoteStyleId(noteData.kind, isPixelStyle()) ?? currentSongNoteStyle; + noteSprite.noteStyle = NoteKindManager.getNoteStyleId(noteData.kind, currentSongNoteStyle) ?? currentSongNoteStyle; noteSprite.overrideStepTime = null; noteSprite.overrideData = null; @@ -3615,7 +3615,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState holdNoteSprite.setHeightDirectly(noteLengthPixels); - holdNoteSprite.noteStyle = NoteKindManager.getNoteStyleId(noteSprite.noteData.kind, isPixelStyle()) ?? currentSongNoteStyle; + holdNoteSprite.noteStyle = NoteKindManager.getNoteStyleId(noteSprite.noteData.kind, currentSongNoteStyle) ?? currentSongNoteStyle; holdNoteSprite.updateHoldNotePosition(renderedHoldNotes); @@ -3681,7 +3681,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState holdNoteSprite.noteDirection = noteData.getDirection(); holdNoteSprite.setHeightDirectly(noteLengthPixels); - holdNoteSprite.noteStyle = NoteKindManager.getNoteStyleId(noteData.kind, isPixelStyle()) ?? currentSongNoteStyle; + holdNoteSprite.noteStyle = NoteKindManager.getNoteStyleId(noteData.kind, currentSongNoteStyle) ?? currentSongNoteStyle; holdNoteSprite.updateHoldNotePosition(renderedHoldNotes); @@ -4580,7 +4580,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState gridGhostHoldNote.noteData = currentPlaceNoteData; gridGhostHoldNote.noteDirection = currentPlaceNoteData.getDirection(); gridGhostHoldNote.setHeightDirectly(dragLengthPixels, true); - gridGhostHoldNote.noteStyle = NoteKindManager.getNoteStyleId(currentPlaceNoteData.kind, isPixelStyle()) ?? currentSongNoteStyle; + gridGhostHoldNote.noteStyle = NoteKindManager.getNoteStyleId(currentPlaceNoteData.kind, currentSongNoteStyle) ?? currentSongNoteStyle; gridGhostHoldNote.updateHoldNotePosition(renderedHoldNotes); } else @@ -4905,7 +4905,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState noteData.kind = noteKindToPlace; noteData.params = noteParamsToPlace; noteData.data = cursorColumn; - gridGhostNote.noteStyle = NoteKindManager.getNoteStyleId(noteData.kind, isPixelStyle()) ?? currentSongNoteStyle; + gridGhostNote.noteStyle = NoteKindManager.getNoteStyleId(noteData.kind, currentSongNoteStyle) ?? currentSongNoteStyle; gridGhostNote.playNoteAnimation(); } noteData.time = cursorSnappedMs; @@ -5297,7 +5297,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState ghostHold.visible = true; ghostHold.alpha = 0.6; ghostHold.setHeightDirectly(0); - ghostHold.noteStyle = NoteKindManager.getNoteStyleId(ghostHold.noteData.kind, isPixelStyle()) ?? currentSongNoteStyle; + ghostHold.noteStyle = NoteKindManager.getNoteStyleId(ghostHold.noteData.kind, currentSongNoteStyle) ?? currentSongNoteStyle; ghostHold.updateHoldNotePosition(renderedHoldNotes); } @@ -6423,11 +6423,6 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState return note != null && currentNoteSelection.indexOf(note) != -1; } - function isPixelStyle():Bool - { - return currentSongNoteStyle == 'pixel'; - } - override function destroy():Void { super.destroy(); From 4746c1da0eed756e2af8630d572ad9770a5185f1 Mon Sep 17 00:00:00 2001 From: lemz Date: Mon, 24 Jun 2024 21:48:09 +0200 Subject: [PATCH 500/870] checking empty suffix is stupid --- source/funkin/play/notes/notekind/NoteKindManager.hx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/funkin/play/notes/notekind/NoteKindManager.hx b/source/funkin/play/notes/notekind/NoteKindManager.hx index d97eefcf8..3040c0a96 100644 --- a/source/funkin/play/notes/notekind/NoteKindManager.hx +++ b/source/funkin/play/notes/notekind/NoteKindManager.hx @@ -89,13 +89,13 @@ class NoteKindManager */ public static function getNoteStyleId(noteKind:String, ?suffix:String):Null { - if (suffix == null) + if (suffix == '') { - suffix = ''; + suffix = null; } var noteStyleId:Null = noteKinds.get(noteKind)?.noteStyleId; - if (noteStyleId != null) + if (noteStyleId != null && suffix != null) { noteStyleId = NoteStyleRegistry.instance.hasEntry('$noteStyleId-$suffix') ? '$noteStyleId-$suffix' : noteStyleId; } From 1fe44fa3686b33f91b99efdb00070e4c59fdee45 Mon Sep 17 00:00:00 2001 From: lemz Date: Sat, 29 Jun 2024 15:33:41 +0200 Subject: [PATCH 501/870] add from --- source/funkin/play/notes/notekind/NoteKind.hx | 2 +- .../ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/source/funkin/play/notes/notekind/NoteKind.hx b/source/funkin/play/notes/notekind/NoteKind.hx index 89c175e54..c1c6e815a 100644 --- a/source/funkin/play/notes/notekind/NoteKind.hx +++ b/source/funkin/play/notes/notekind/NoteKind.hx @@ -73,7 +73,7 @@ class NoteKind implements INoteScriptedClass * Abstract for setting the type of the `NoteKindParam` * This was supposed to be an enum but polymod kept being annoying */ -abstract NoteKindParamType(String) to String +abstract NoteKindParamType(String) from String to String { public static final STRING:String = 'String'; diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx index 264e62c5a..ea46cf72a 100644 --- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx @@ -186,8 +186,7 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox var paramComponent:Component = null; - final paramType:String = param.type; - switch (paramType) + switch (param.type) { case NoteKindParamType.INT | NoteKindParamType.FLOAT: var paramStepper:NumberStepper = new NumberStepper(); From f76309c91ec2cd0ca4bad6163b47fefa2e57228c Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 12 Jul 2024 04:13:20 -0400 Subject: [PATCH 502/870] Update rendering for custom note styles --- source/funkin/data/notestyle/NoteStyleData.hx | 8 ++++++++ source/funkin/play/notes/NoteSprite.hx | 16 +++++++++------- source/funkin/play/notes/Strumline.hx | 1 + source/funkin/play/notes/notestyle/NoteStyle.hx | 16 ++++++++++++++-- .../charting/components/ChartEditorNoteSprite.hx | 10 ++++++++-- .../toolboxes/ChartEditorNoteDataToolbox.hx | 2 +- .../debug/charting/util/ChartEditorDropdowns.hx | 6 +++--- 7 files changed, 44 insertions(+), 15 deletions(-) diff --git a/source/funkin/data/notestyle/NoteStyleData.hx b/source/funkin/data/notestyle/NoteStyleData.hx index 04fda67ca..fcdb3b4f9 100644 --- a/source/funkin/data/notestyle/NoteStyleData.hx +++ b/source/funkin/data/notestyle/NoteStyleData.hx @@ -109,6 +109,14 @@ typedef NoteStyleAssetData = @:optional var isPixel:Bool; + /** + * If true, animations will be played on the graphic. + * @default `false` to save performance. + */ + @:default(false) + @:optional + var animated:Bool; + /** * The structure of this data depends on the asset. */ diff --git a/source/funkin/play/notes/NoteSprite.hx b/source/funkin/play/notes/NoteSprite.hx index d8d471496..e8cacaa4d 100644 --- a/source/funkin/play/notes/NoteSprite.hx +++ b/source/funkin/play/notes/NoteSprite.hx @@ -91,7 +91,7 @@ class NoteSprite extends FunkinSprite { if (frames == null) return value; - animation.play(DIRECTION_COLORS[value] + 'Scroll'); + playNoteAnimation(value); this.direction = value; return this.direction; @@ -152,9 +152,6 @@ class NoteSprite extends FunkinSprite this.hsvShader = new HSVShader(); setupNoteGraphic(noteStyle); - - // Disables the update() function for performance. - this.active = false; } /** @@ -165,10 +162,10 @@ class NoteSprite extends FunkinSprite { noteStyle.buildNoteSprite(this); - setGraphicSize(Strumline.STRUMLINE_SIZE); - updateHitbox(); - this.shader = hsvShader; + + // `false` disables the update() function for performance. + this.active = noteStyle.isNoteAnimated(); } /** @@ -211,6 +208,11 @@ class NoteSprite extends FunkinSprite } #end + function playNoteAnimation(value:Int):Void + { + animation.play(DIRECTION_COLORS[value] + 'Scroll'); + } + public function desaturate():Void { this.hsvShader.saturation = 0.2; diff --git a/source/funkin/play/notes/Strumline.hx b/source/funkin/play/notes/Strumline.hx index 5e76afa51..1e5782ad2 100644 --- a/source/funkin/play/notes/Strumline.hx +++ b/source/funkin/play/notes/Strumline.hx @@ -717,6 +717,7 @@ class Strumline extends FlxSpriteGroup noteSprite.x = this.x; noteSprite.x += getXPos(DIRECTIONS[note.getDirection() % KEY_COUNT]); + noteSprite.x -= (noteSprite.width - Strumline.STRUMLINE_SIZE) / 2; // Center it noteSprite.x -= NUDGE; // noteSprite.x += INITIAL_OFFSET; noteSprite.y = -9999; diff --git a/source/funkin/play/notes/notestyle/NoteStyle.hx b/source/funkin/play/notes/notestyle/NoteStyle.hx index d0cc09f6a..3993cce52 100644 --- a/source/funkin/play/notes/notestyle/NoteStyle.hx +++ b/source/funkin/play/notes/notestyle/NoteStyle.hx @@ -89,12 +89,14 @@ class NoteStyle implements IRegistryEntry target.frames = atlas; - target.scale.x = _data.assets.note.scale; - target.scale.y = _data.assets.note.scale; target.antialiasing = !_data.assets.note.isPixel; // Apply the animations. buildNoteAnimations(target); + + // Set the scale. + target.setGraphicSize(Strumline.STRUMLINE_SIZE * getNoteScale()); + target.updateHitbox(); } var noteFrames:FlxAtlasFrames = null; @@ -156,6 +158,16 @@ class NoteStyle implements IRegistryEntry target.animation.addByPrefix('redScroll', rightData.prefix, rightData.frameRate, rightData.looped, rightData.flipX, rightData.flipY); } + public function isNoteAnimated():Bool + { + return _data.assets.note.animated; + } + + public function getNoteScale():Float + { + return _data.assets.note.scale; + } + function fetchNoteAnimationData(dir:NoteDirection):AnimationData { var result:Null = switch (dir) diff --git a/source/funkin/ui/debug/charting/components/ChartEditorNoteSprite.hx b/source/funkin/ui/debug/charting/components/ChartEditorNoteSprite.hx index 009532401..5fd0c74aa 100644 --- a/source/funkin/ui/debug/charting/components/ChartEditorNoteSprite.hx +++ b/source/funkin/ui/debug/charting/components/ChartEditorNoteSprite.hx @@ -107,6 +107,12 @@ class ChartEditorNoteSprite extends FlxSprite var prefix:String = noteStyle.id.toTitleCase(); var frameCollection:FlxAtlasFrames = Paths.getSparrowAtlas(noteStyle.getNoteAssetPath(), noteStyle.getNoteAssetLibrary()); + if (frameCollection == null) + { + trace('Could not retrieve frame collection for ${noteStyle}: ${Paths.image(noteStyle.getNoteAssetPath(), noteStyle.getNoteAssetLibrary())}'); + FlxG.log.error('Could not retrieve frame collection for ${noteStyle}: ${Paths.image(noteStyle.getNoteAssetPath(), noteStyle.getNoteAssetLibrary())}'); + return; + } for (frame in frameCollection.frames) { // cloning the frame because else @@ -221,9 +227,9 @@ class ChartEditorNoteSprite extends FlxSprite switch (baseAnimationName) { case 'tap': - this.setGraphicSize(0, ChartEditorState.GRID_SIZE); + this.setGraphicSize(ChartEditorState.GRID_SIZE, 0); + this.updateHitbox(); } - this.updateHitbox(); var bruhStyle:NoteStyle = fetchNoteStyle(this.noteStyle); this.antialiasing = !bruhStyle._data?.assets?.note?.isPixel ?? true; diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx index ea46cf72a..12f7f7d63 100644 --- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx @@ -283,7 +283,7 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox return; } - var heightToSet:Int = Std.int(Math.max(DIALOG_HEIGHT, toolboxNotesGrid.height + HEIGHT_OFFSET)) + MINIMIZE_FIX; + var heightToSet:Int = Std.int(Math.max(DIALOG_HEIGHT, (toolboxNotesGrid?.height ?? 50) + HEIGHT_OFFSET)) + MINIMIZE_FIX; if (this.height != heightToSet) { this.height = heightToSet; diff --git a/source/funkin/ui/debug/charting/util/ChartEditorDropdowns.hx b/source/funkin/ui/debug/charting/util/ChartEditorDropdowns.hx index 6a426c391..21938b005 100644 --- a/source/funkin/ui/debug/charting/util/ChartEditorDropdowns.hx +++ b/source/funkin/ui/debug/charting/util/ChartEditorDropdowns.hx @@ -195,11 +195,11 @@ class ChartEditorDropdowns { dropDown.dataSource.clear(); - var returnValue:DropDownEntry = lookupNoteKind('~CUSTOM'); + var returnValue:DropDownEntry = lookupNoteKind(''); for (noteKindId in NOTE_KINDS.keys()) { - var noteKind:String = NOTE_KINDS.get(noteKindId) ?? 'Default'; + var noteKind:String = NOTE_KINDS.get(noteKindId) ?? 'Unknown'; var value:DropDownEntry = {id: noteKindId, text: noteKind}; if (startingKindId == noteKindId) returnValue = value; @@ -216,7 +216,7 @@ class ChartEditorDropdowns { if (noteKindId == null) return lookupNoteKind(''); if (!NOTE_KINDS.exists(noteKindId)) return {id: '~CUSTOM~', text: 'Custom'}; - return {id: noteKindId ?? '', text: NOTE_KINDS.get(noteKindId) ?? 'Default'}; + return {id: noteKindId ?? '', text: NOTE_KINDS.get(noteKindId) ?? 'Unknown'}; } /** From ace762413e42a211a92ad37544ec22f1c2f3da8d Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 12 Jul 2024 16:39:42 -0400 Subject: [PATCH 503/870] Fix an issue where display would break on invalid note styles. --- assets | 2 +- source/funkin/ui/debug/charting/ChartEditorState.hx | 4 +++- .../charting/components/ChartEditorHoldNoteSprite.hx | 3 ++- .../charting/components/ChartEditorNoteSprite.hx | 12 ++++++++++-- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/assets b/assets index 005c96f85..4af95a506 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 005c96f85f4304865acb196e7cc4d6d83f9d76d8 +Subproject commit 4af95a506fc62cd683422dfb9c599877b26c27db diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index d3ddb1bca..6f5979c90 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -1408,7 +1408,9 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState function get_currentSongNoteStyle():String { - if (currentSongMetadata.playData.noteStyle == null) + if (currentSongMetadata.playData.noteStyle == null + || currentSongMetadata.playData.noteStyle == '' + || currentSongMetadata.playData.noteStyle == 'item') { // Initialize to the default value if not set. currentSongMetadata.playData.noteStyle = Constants.DEFAULT_NOTE_STYLE; diff --git a/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx b/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx index b8d6ee22e..1e631f2cf 100644 --- a/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx +++ b/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx @@ -53,7 +53,8 @@ class ChartEditorHoldNoteSprite extends SustainTrail @:nullSafety(Off) function updateHoldNoteGraphic():Void { - var bruhStyle:NoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyle); + var bruhStyle:Null = NoteStyleRegistry.instance.fetchEntry(noteStyle); + if (bruhStyle == null) bruhStyle = NoteStyleRegistry.instance.fetchDefault(); setupHoldNoteGraphic(bruhStyle); } diff --git a/source/funkin/ui/debug/charting/components/ChartEditorNoteSprite.hx b/source/funkin/ui/debug/charting/components/ChartEditorNoteSprite.hx index 5fd0c74aa..c8f40da62 100644 --- a/source/funkin/ui/debug/charting/components/ChartEditorNoteSprite.hx +++ b/source/funkin/ui/debug/charting/components/ChartEditorNoteSprite.hx @@ -97,7 +97,9 @@ class ChartEditorNoteSprite extends FlxSprite function fetchNoteStyle(noteStyleId:String):NoteStyle { - return NoteStyleRegistry.instance.fetchEntry(noteStyleId) ?? NoteStyleRegistry.instance.fetchDefault(); + var result = NoteStyleRegistry.instance.fetchEntry(noteStyleId); + if (result != null) return result; + return NoteStyleRegistry.instance.fetchDefault(); } @:access(funkin.play.notes.notestyle.NoteStyle) @@ -198,7 +200,12 @@ class ChartEditorNoteSprite extends FlxSprite function get_noteStyle():Null { - return this.noteStyle ?? this.parentState.currentSongNoteStyle; + if (this.noteStyle == null) + { + var result = this.parentState.currentSongNoteStyle; + return result; + } + return this.noteStyle; } function set_noteStyle(value:Null):Null @@ -218,6 +225,7 @@ class ChartEditorNoteSprite extends FlxSprite // Play the appropriate animation for the type, direction, and skin. var dirName:String = overrideData != null ? SongNoteData.buildDirectionName(overrideData) : this.noteData.getDirectionName(); + var noteStyleSuffix:String = this.noteStyle?.toTitleCase() ?? Constants.DEFAULT_NOTE_STYLE.toTitleCase(); var animationName:String = '${baseAnimationName}${dirName}${this.noteStyle.toTitleCase()}'; this.animation.play(animationName); From d4cbe74939425c5a86f0ad752e2620e560380e27 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 12 Jul 2024 21:40:46 -0400 Subject: [PATCH 504/870] Smaller fixes tied to note kinds --- source/funkin/data/song/importer/FNFLegacyImporter.hx | 2 ++ source/funkin/modding/PolymodHandler.hx | 2 ++ source/funkin/play/PlayState.hx | 6 +++--- source/funkin/play/character/BaseCharacter.hx | 6 ++++++ source/funkin/play/notes/notekind/NoteKindManager.hx | 1 + source/funkin/play/stage/Bopper.hx | 4 ++-- 6 files changed, 16 insertions(+), 5 deletions(-) diff --git a/source/funkin/data/song/importer/FNFLegacyImporter.hx b/source/funkin/data/song/importer/FNFLegacyImporter.hx index acbb99342..96a1051cc 100644 --- a/source/funkin/data/song/importer/FNFLegacyImporter.hx +++ b/source/funkin/data/song/importer/FNFLegacyImporter.hx @@ -199,6 +199,8 @@ class FNFLegacyImporter { // Handle the dumb logic for mustHitSection. var noteData = note.data; + if (noteData < 0) continue; // Exclude Psych event notes. + if (noteData > (STRUMLINE_SIZE * 2)) noteData = noteData % (2 * STRUMLINE_SIZE); // Handle other engine event notes. // Flip notes if mustHitSection is FALSE (not true lol). if (!mustHitSection) diff --git a/source/funkin/modding/PolymodHandler.hx b/source/funkin/modding/PolymodHandler.hx index c352aa606..59c8707f7 100644 --- a/source/funkin/modding/PolymodHandler.hx +++ b/source/funkin/modding/PolymodHandler.hx @@ -7,6 +7,7 @@ import funkin.data.dialogue.speaker.SpeakerRegistry; import funkin.data.event.SongEventRegistry; import funkin.data.story.level.LevelRegistry; import funkin.data.notestyle.NoteStyleRegistry; +import funkin.play.notes.notekind.NoteKindManager; import funkin.data.song.SongRegistry; import funkin.data.freeplay.player.PlayerRegistry; import funkin.data.stage.StageRegistry; @@ -383,6 +384,7 @@ class PolymodHandler StageRegistry.instance.loadEntries(); CharacterDataParser.loadCharacterCache(); // TODO: Migrate characters to BaseRegistry. + NoteKindManager.loadScripts(); ModuleHandler.loadModuleCache(); } } diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index da343f43f..10546cdbd 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1166,6 +1166,9 @@ class PlayState extends MusicBeatSubState // super.dispatchEvent(event) dispatches event to module scripts. super.dispatchEvent(event); + // Dispatch event to note kind scripts + NoteKindManager.callEvent(event); + // Dispatch event to stage script. ScriptEventDispatcher.callEvent(currentStage, event); @@ -1177,9 +1180,6 @@ class PlayState extends MusicBeatSubState // Dispatch event to conversation script. ScriptEventDispatcher.callEvent(currentConversation, event); - - // Dispatch event to note kind scripts - NoteKindManager.callEvent(event); } /** diff --git a/source/funkin/play/character/BaseCharacter.hx b/source/funkin/play/character/BaseCharacter.hx index 0dab2101a..432881164 100644 --- a/source/funkin/play/character/BaseCharacter.hx +++ b/source/funkin/play/character/BaseCharacter.hx @@ -521,6 +521,9 @@ class BaseCharacter extends Bopper { super.onNoteHit(event); + // If another script cancelled the event, don't do anything. + if (event.eventCanceled) return; + if (event.note.noteData.getMustHitNote() && characterType == BF) { // If the note is from the same strumline, play the sing animation. @@ -553,6 +556,9 @@ class BaseCharacter extends Bopper { super.onNoteMiss(event); + // If another script cancelled the event, don't do anything. + if (event.eventCanceled) return; + if (event.note.noteData.getMustHitNote() && characterType == BF) { // If the note is from the same strumline, play the sing animation. diff --git a/source/funkin/play/notes/notekind/NoteKindManager.hx b/source/funkin/play/notes/notekind/NoteKindManager.hx index 3040c0a96..e17e103d1 100644 --- a/source/funkin/play/notes/notekind/NoteKindManager.hx +++ b/source/funkin/play/notes/notekind/NoteKindManager.hx @@ -5,6 +5,7 @@ import funkin.modding.events.ScriptEvent; import funkin.ui.debug.charting.util.ChartEditorDropdowns; import funkin.data.notestyle.NoteStyleRegistry; import funkin.play.notes.notestyle.NoteStyle; +import funkin.play.notes.notekind.ScriptedNoteKind; import funkin.play.notes.notekind.NoteKind.NoteKindParam; class NoteKindManager diff --git a/source/funkin/play/stage/Bopper.hx b/source/funkin/play/stage/Bopper.hx index 87151de21..fa35b4e15 100644 --- a/source/funkin/play/stage/Bopper.hx +++ b/source/funkin/play/stage/Bopper.hx @@ -45,8 +45,8 @@ class Bopper extends StageProp implements IPlayStateScriptedClass public var idleSuffix(default, set):String = ''; /** - * If this bopper is rendered with pixel art, - * disable anti-aliasing and render at 6x scale. + * If this bopper is rendered with pixel art, disable anti-aliasing. + * @default `false` */ public var isPixel(default, set):Bool = false; From 6116ec3639b3720c3b2453be6a76adaa6998e447 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 12 Jul 2024 22:31:04 -0400 Subject: [PATCH 505/870] Some more fixes for offsets handling and stuffs --- source/funkin/play/PauseSubState.hx | 2 +- source/funkin/play/song/Song.hx | 3 ++- source/funkin/play/stage/Bopper.hx | 18 +++--------------- 3 files changed, 6 insertions(+), 17 deletions(-) diff --git a/source/funkin/play/PauseSubState.hx b/source/funkin/play/PauseSubState.hx index d0c759b16..6f8908eea 100644 --- a/source/funkin/play/PauseSubState.hx +++ b/source/funkin/play/PauseSubState.hx @@ -306,7 +306,7 @@ class PauseSubState extends MusicBeatSubState metadataDifficulty.setFormat(Paths.font('vcr.ttf'), 32, FlxColor.WHITE, FlxTextAlign.RIGHT); if (PlayState.instance?.currentDifficulty != null) { - metadataDifficulty.text += PlayState.instance.currentDifficulty.toTitleCase(); + metadataDifficulty.text += PlayState.instance.currentDifficulty.replace('-', ' ').toTitleCase(); } metadataDifficulty.scrollFactor.set(0, 0); metadata.add(metadataDifficulty); diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx index 91d35d8fa..4e9f70920 100644 --- a/source/funkin/play/song/Song.hx +++ b/source/funkin/play/song/Song.hx @@ -277,7 +277,8 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry Date: Sat, 13 Jul 2024 22:45:58 +0300 Subject: [PATCH 506/870] custom popups and countdowns yay!!! --- assets | 2 +- source/funkin/play/Countdown.hx | 154 ++++++++++---------- source/funkin/play/PlayState.hx | 6 +- source/funkin/play/components/PopUpStuff.hx | 58 ++++++-- 4 files changed, 124 insertions(+), 96 deletions(-) diff --git a/assets b/assets index 2e1594ee4..514a987ee 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 2e1594ee4c04c7148628bae471bdd061c9deb6b7 +Subproject commit 514a987ee57827b097ed035a1c2fdd1377a53b17 diff --git a/source/funkin/play/Countdown.hx b/source/funkin/play/Countdown.hx index 10636afdf..7686e5b75 100644 --- a/source/funkin/play/Countdown.hx +++ b/source/funkin/play/Countdown.hx @@ -10,6 +10,7 @@ import funkin.modding.events.ScriptEvent; import funkin.modding.events.ScriptEvent.CountdownScriptEvent; import flixel.util.FlxTimer; import funkin.audio.FunkinSound; +import openfl.utils.Assets; class Countdown { @@ -18,6 +19,22 @@ class Countdown */ public static var countdownStep(default, null):CountdownStep = BEFORE; + /** + * Which alternate countdown sound effect to use. + * You can set this via script. + * For example, in Week 6 it is `-pixel`. + */ + public static var soundSuffix:String = ''; + + /** + * Which alternate graphic on countdown to use. + * You can set this via script. + * For example, in Week 6 it is `-pixel`. + */ + public static var graphicSuffix:String = ''; + + + /** * The currently running countdown. This will be null if there is no countdown running. */ @@ -29,7 +46,7 @@ class Countdown * This will automatically stop and restart the countdown if it is already running. * @returns `false` if the countdown was cancelled by a script. */ - public static function performCountdown(isPixelStyle:Bool):Bool + public static function performCountdown():Bool { countdownStep = BEFORE; var cancelled:Bool = propagateCountdownEvent(countdownStep); @@ -64,10 +81,10 @@ class Countdown // PlayState.instance.dispatchEvent(new SongTimeScriptEvent(SONG_BEAT_HIT, 0, 0)); // Countdown graphic. - showCountdownGraphic(countdownStep, isPixelStyle); + showCountdownGraphic(countdownStep, graphicSuffix.toLowerCase().contains('pixel')); // Countdown sound. - playCountdownSound(countdownStep, isPixelStyle); + playCountdownSound(countdownStep); // Event handling bullshit. var cancelled:Bool = propagateCountdownEvent(countdownStep); @@ -176,52 +193,30 @@ class Countdown } /** - * Retrieves the graphic to use for this step of the countdown. - * TODO: Make this less dumb. Unhardcode it? Use modules? Use notestyles? - * - * This is public so modules can do lol funny shit. + * Reset the countdown configuration to the default. */ - public static function showCountdownGraphic(index:CountdownStep, isPixelStyle:Bool):Void + public static function reset() + { + soundSuffix = ''; + graphicSuffix = ''; + } + + /** + * Retrieves the graphic to use for this step of the countdown. + */ + public static function showCountdownGraphic(index:CountdownStep, isGraphicPixel:Bool):Void { var spritePath:String = null; - - if (isPixelStyle) - { - switch (index) - { - case TWO: - spritePath = 'weeb/pixelUI/ready-pixel'; - case ONE: - spritePath = 'weeb/pixelUI/set-pixel'; - case GO: - spritePath = 'weeb/pixelUI/date-pixel'; - default: - // null - } - } - else - { - switch (index) - { - case TWO: - spritePath = 'ready'; - case ONE: - spritePath = 'set'; - case GO: - spritePath = 'go'; - default: - // null - } - } + spritePath = resolveGraphicPath(graphicSuffix, index); if (spritePath == null) return; var countdownSprite:FunkinSprite = FunkinSprite.create(spritePath); countdownSprite.scrollFactor.set(0, 0); - if (isPixelStyle) countdownSprite.setGraphicSize(Std.int(countdownSprite.width * Constants.PIXEL_ART_SCALE)); + if (isGraphicPixel) countdownSprite.setGraphicSize(Std.int(countdownSprite.width * Constants.PIXEL_ART_SCALE)); - countdownSprite.antialiasing = !isPixelStyle; + countdownSprite.antialiasing = !isGraphicPixel; countdownSprite.updateHitbox(); countdownSprite.screenCenter(); @@ -238,52 +233,55 @@ class Countdown PlayState.instance.add(countdownSprite); } + static function resolveGraphicPath(suffix:String, index:CountdownStep):Null + { + var basePath:String = 'ui/countdown/'; + var indexString:String = null; + switch (index) + { + case TWO: + indexString = 'ready'; + case ONE: + indexString = 'set'; + case GO: + indexString = 'go'; + default: + // null + } + basePath += indexString; + var spritePath:String = basePath + suffix; + while (!Assets.exists(Paths.image(spritePath)) && suffix.length > 0) + { + suffix = suffix.split('-').slice(0, -1).join('-'); + spritePath = basePath + suffix; + } + if (!Assets.exists(Paths.image(spritePath))) return null; + trace('Resolved sprite path: ' + Paths.image(spritePath)); + return spritePath; + } + /** * Retrieves the sound file to use for this step of the countdown. - * TODO: Make this less dumb. Unhardcode it? Use modules? Use notestyles? - * - * This is public so modules can do lol funny shit. */ - public static function playCountdownSound(index:CountdownStep, isPixelStyle:Bool):Void + public static function playCountdownSound(index:CountdownStep):Void { - var soundPath:String = null; + FunkinSound.playOnce(resolveSoundPath(soundSuffix, index), Constants.COUNTDOWN_VOLUME); + } - if (isPixelStyle) + static function resolveSoundPath(suffix:String, step:CountdownStep):Null + { + var basePath:String = 'gameplay/countdown/intro'; + if (step != CountdownStep.BEFORE || step != CountdownStep.AFTER) basePath += step; + + var soundPath:String = Paths.sound(basePath + suffix); + while (!Assets.exists(soundPath) && suffix.length > 0) { - switch (index) - { - case THREE: - soundPath = 'intro3-pixel'; - case TWO: - soundPath = 'intro2-pixel'; - case ONE: - soundPath = 'intro1-pixel'; - case GO: - soundPath = 'introGo-pixel'; - default: - // null - } + suffix = suffix.split('-').slice(0, -1).join('-'); + soundPath = Paths.sound(basePath + suffix); } - else - { - switch (index) - { - case THREE: - soundPath = 'intro3'; - case TWO: - soundPath = 'intro2'; - case ONE: - soundPath = 'intro1'; - case GO: - soundPath = 'introGo'; - default: - // null - } - } - - if (soundPath == null) return; - - FunkinSound.playOnce(Paths.sound(soundPath), Constants.COUNTDOWN_VOLUME); + if (!Assets.exists(soundPath)) return null; + trace('Resolved sound path: ' + soundPath); + return soundPath; } public static function decrement(step:CountdownStep):CountdownStep diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index f55cef388..bf401ece2 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -899,7 +899,7 @@ class PlayState extends MusicBeatSubState health = Constants.HEALTH_STARTING; songScore = 0; Highscore.tallies.combo = 0; - Countdown.performCountdown(currentStageId.startsWith('school')); + Countdown.performCountdown(); needsReset = false; } @@ -1920,7 +1920,7 @@ class PlayState extends MusicBeatSubState public function startCountdown():Void { // If Countdown.performCountdown returns false, then the countdown was canceled by a script. - var result:Bool = Countdown.performCountdown(currentStageId.startsWith('school')); + var result:Bool = Countdown.performCountdown(); if (!result) return; isInCutscene = false; @@ -3061,6 +3061,8 @@ class PlayState extends MusicBeatSubState GameOverSubState.reset(); PauseSubState.reset(); + Countdown.reset(); + PopUpStuff.reset(); // Clear the static reference to this state. instance = null; diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx index b7e206e97..ddf24d24b 100644 --- a/source/funkin/play/components/PopUpStuff.hx +++ b/source/funkin/play/components/PopUpStuff.hx @@ -7,25 +7,52 @@ import flixel.util.FlxDirection; import funkin.graphics.FunkinSprite; import funkin.play.PlayState; import funkin.util.TimerUtil; +import openfl.utils.Assets; class PopUpStuff extends FlxTypedGroup { public var offsets:Array = [0, 0]; + /** + * Which alternate graphic on popup to use. + * You can set this via script. + * For example, in Week 6 it is `-pixel`. + */ + public static var graphicSuffix:String = ''; + override public function new() { super(); } + static function resolveGraphicPath(suffix:String, index:String):Null + { + var folder:String; + if (suffix != '') + folder = suffix.substring(0, suffix.indexOf("-")) + suffix.substring(suffix.indexOf("-") + 1); + else + folder = 'normal'; + var basePath:String = 'gameplay/popup/$folder/$index'; + var spritePath:String = basePath + suffix; + trace(spritePath); + while (!Assets.exists(Paths.image(spritePath)) && suffix.length > 0) + { + suffix = suffix.split('-').slice(0, -1).join('-'); + spritePath = basePath + suffix; + } + if (!Assets.exists(Paths.image(spritePath))) return null; + return spritePath; + } + public function displayRating(daRating:String) { var perfStart:Float = TimerUtil.start(); if (daRating == null) daRating = "good"; - var ratingPath:String = daRating; + var ratingPath:String = resolveGraphicPath(graphicSuffix, daRating); - if (PlayState.instance.currentStageId.startsWith('school')) ratingPath = "weeb/pixelUI/" + ratingPath + "-pixel"; + //if (PlayState.instance.currentStageId.startsWith('school')) ratingPath = "weeb/pixelUI/" + ratingPath + "-pixel"; var rating:FunkinSprite = FunkinSprite.create(0, 0, ratingPath); rating.scrollFactor.set(0.2, 0.2); @@ -40,7 +67,7 @@ class PopUpStuff extends FlxTypedGroup add(rating); - if (PlayState.instance.currentStageId.startsWith('school')) + if (graphicSuffix.toLowerCase().contains('pixel')) { rating.setGraphicSize(Std.int(rating.width * Constants.PIXEL_ART_SCALE * 0.7)); rating.antialiasing = false; @@ -73,15 +100,8 @@ class PopUpStuff extends FlxTypedGroup if (combo == null) combo = 0; - var pixelShitPart1:String = ""; - var pixelShitPart2:String = ''; - - if (PlayState.instance.currentStageId.startsWith('school')) - { - pixelShitPart1 = 'weeb/pixelUI/'; - pixelShitPart2 = '-pixel'; - } - var comboSpr:FunkinSprite = FunkinSprite.create(pixelShitPart1 + 'combo' + pixelShitPart2); + var comboPath:String = resolveGraphicPath(graphicSuffix, Std.string(combo)); + var comboSpr:FunkinSprite = FunkinSprite.create(comboPath); comboSpr.y = (FlxG.camera.height * 0.44) + offsets[1]; comboSpr.x = (FlxG.width * 0.507) + offsets[0]; // comboSpr.x -= FlxG.camera.scroll.x * 0.2; @@ -92,7 +112,7 @@ class PopUpStuff extends FlxTypedGroup // add(comboSpr); - if (PlayState.instance.currentStageId.startsWith('school')) + if (graphicSuffix.toLowerCase().contains('pixel')) { comboSpr.setGraphicSize(Std.int(comboSpr.width * Constants.PIXEL_ART_SCALE * 0.7)); comboSpr.antialiasing = false; @@ -129,9 +149,9 @@ class PopUpStuff extends FlxTypedGroup var daLoop:Int = 1; for (i in seperatedScore) { - var numScore:FunkinSprite = FunkinSprite.create(0, comboSpr.y, pixelShitPart1 + 'num' + Std.int(i) + pixelShitPart2); + var numScore:FunkinSprite = FunkinSprite.create(0, comboSpr.y, resolveGraphicPath(graphicSuffix, 'num' + Std.int(i))); - if (PlayState.instance.currentStageId.startsWith('school')) + if (graphicSuffix.toLowerCase().contains('pixel')) { numScore.setGraphicSize(Std.int(numScore.width * Constants.PIXEL_ART_SCALE * 0.7)); numScore.antialiasing = false; @@ -166,4 +186,12 @@ class PopUpStuff extends FlxTypedGroup return combo; } + + /** + * Reset the popup configuration to the default. + */ + public static function reset() + { + graphicSuffix = ''; + } } From 2547fbb8f4033f815d3d8d5cef9eb9ddc02c2832 Mon Sep 17 00:00:00 2001 From: anysad Date: Sat, 13 Jul 2024 23:08:16 +0300 Subject: [PATCH 507/870] remove trace --- assets | 2 +- source/funkin/play/components/PopUpStuff.hx | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/assets b/assets index 514a987ee..e414ee618 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 514a987ee57827b097ed035a1c2fdd1377a53b17 +Subproject commit e414ee618b4fa577dc3c3df4e156488e91c6348d diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx index ddf24d24b..0a4d6b019 100644 --- a/source/funkin/play/components/PopUpStuff.hx +++ b/source/funkin/play/components/PopUpStuff.hx @@ -34,7 +34,6 @@ class PopUpStuff extends FlxTypedGroup folder = 'normal'; var basePath:String = 'gameplay/popup/$folder/$index'; var spritePath:String = basePath + suffix; - trace(spritePath); while (!Assets.exists(Paths.image(spritePath)) && suffix.length > 0) { suffix = suffix.split('-').slice(0, -1).join('-'); From 9d3c043f8ab462973a1e760336581dee89326e42 Mon Sep 17 00:00:00 2001 From: anysad Date: Sat, 13 Jul 2024 23:29:26 +0300 Subject: [PATCH 508/870] cache textures at their new locations! --- source/funkin/ui/transition/LoadingState.hx | 33 ++++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/source/funkin/ui/transition/LoadingState.hx b/source/funkin/ui/transition/LoadingState.hx index bc26ad97a..d0b8cfbe8 100644 --- a/source/funkin/ui/transition/LoadingState.hx +++ b/source/funkin/ui/transition/LoadingState.hx @@ -291,17 +291,28 @@ class LoadingState extends MusicBeatSubState FunkinSprite.preparePurgeCache(); FunkinSprite.cacheTexture(Paths.image('healthBar')); FunkinSprite.cacheTexture(Paths.image('menuDesat')); - FunkinSprite.cacheTexture(Paths.image('combo')); - FunkinSprite.cacheTexture(Paths.image('num0')); - FunkinSprite.cacheTexture(Paths.image('num1')); - FunkinSprite.cacheTexture(Paths.image('num2')); - FunkinSprite.cacheTexture(Paths.image('num3')); - FunkinSprite.cacheTexture(Paths.image('num4')); - FunkinSprite.cacheTexture(Paths.image('num5')); - FunkinSprite.cacheTexture(Paths.image('num6')); - FunkinSprite.cacheTexture(Paths.image('num7')); - FunkinSprite.cacheTexture(Paths.image('num8')); - FunkinSprite.cacheTexture(Paths.image('num9')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/combo')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num0')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num1')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num2')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num3')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num4')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num5')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num6')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num7')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num8')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num9')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/combo-pixel')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num0-pixel')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num1-pixel')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num2-pixel')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num3-pixel')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num4-pixel')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num5-pixel')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num6-pixel')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num7-pixel')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num8-pixel')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num9-pixel')); FunkinSprite.cacheTexture(Paths.image('notes', 'shared')); FunkinSprite.cacheTexture(Paths.image('noteSplashes', 'shared')); FunkinSprite.cacheTexture(Paths.image('noteStrumline', 'shared')); From aed100df476df55d38e820cc86f643ed62117284 Mon Sep 17 00:00:00 2001 From: anysad Date: Sat, 13 Jul 2024 23:39:56 +0300 Subject: [PATCH 509/870] how the hell did I miss these? --- source/funkin/ui/transition/LoadingState.hx | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/source/funkin/ui/transition/LoadingState.hx b/source/funkin/ui/transition/LoadingState.hx index d0b8cfbe8..a571126fe 100644 --- a/source/funkin/ui/transition/LoadingState.hx +++ b/source/funkin/ui/transition/LoadingState.hx @@ -317,13 +317,20 @@ class LoadingState extends MusicBeatSubState FunkinSprite.cacheTexture(Paths.image('noteSplashes', 'shared')); FunkinSprite.cacheTexture(Paths.image('noteStrumline', 'shared')); FunkinSprite.cacheTexture(Paths.image('NOTE_hold_assets')); - FunkinSprite.cacheTexture(Paths.image('ready', 'shared')); - FunkinSprite.cacheTexture(Paths.image('set', 'shared')); - FunkinSprite.cacheTexture(Paths.image('go', 'shared')); - FunkinSprite.cacheTexture(Paths.image('sick', 'shared')); - FunkinSprite.cacheTexture(Paths.image('good', 'shared')); - FunkinSprite.cacheTexture(Paths.image('bad', 'shared')); - FunkinSprite.cacheTexture(Paths.image('shit', 'shared')); + FunkinSprite.cacheTexture(Paths.image('ui/countdown/ready', 'shared')); + FunkinSprite.cacheTexture(Paths.image('ui/countdown/set', 'shared')); + FunkinSprite.cacheTexture(Paths.image('ui/countdown/go', 'shared')); + FunkinSprite.cacheTexture(Paths.image('ui/countdown/ready-pixel', 'shared')); + FunkinSprite.cacheTexture(Paths.image('ui/countdown/set-pixel', 'shared')); + FunkinSprite.cacheTexture(Paths.image('ui/countdown/go-pixel', 'shared')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/sick')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/good')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/bad')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/shit')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/sick-pixel')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/good-pixel')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/bad-pixel')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/shit-pixel')); FunkinSprite.cacheTexture(Paths.image('miss', 'shared')); // TODO: remove this // List all image assets in the level's library. From 416d60000f369620a4a1c5b744fd3f0a1c25ea95 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 15 Jul 2024 06:30:10 -0400 Subject: [PATCH 510/870] Implement Nene Christmas, and fix Nene offsets on other stages. --- assets | 2 +- source/funkin/play/character/BaseCharacter.hx | 16 +++++++--- source/funkin/ui/freeplay/FreeplayState.hx | 30 +++++++++++++------ source/funkin/ui/freeplay/SongMenuItem.hx | 3 +- source/funkin/ui/mainmenu/MainMenuState.hx | 5 +++- 5 files changed, 39 insertions(+), 17 deletions(-) diff --git a/assets b/assets index 005c96f85..d5b2d05df 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 005c96f85f4304865acb196e7cc4d6d83f9d76d8 +Subproject commit d5b2d05df6d197f90a1b93f5b50835209c21adf7 diff --git a/source/funkin/play/character/BaseCharacter.hx b/source/funkin/play/character/BaseCharacter.hx index 0dab2101a..4778e0c1c 100644 --- a/source/funkin/play/character/BaseCharacter.hx +++ b/source/funkin/play/character/BaseCharacter.hx @@ -382,12 +382,19 @@ class BaseCharacter extends Bopper // and Darnell (this keeps the flame on his lighter flickering). // Works for idle, singLEFT/RIGHT/UP/DOWN, alt singing animations, and anything else really. - if (!getCurrentAnimation().endsWith(Constants.ANIMATION_HOLD_SUFFIX) - && hasAnimation(getCurrentAnimation() + Constants.ANIMATION_HOLD_SUFFIX) - && isAnimationFinished()) + if (isAnimationFinished() + && !getCurrentAnimation().endsWith(Constants.ANIMATION_HOLD_SUFFIX) + && hasAnimation(getCurrentAnimation() + Constants.ANIMATION_HOLD_SUFFIX)) { playAnimation(getCurrentAnimation() + Constants.ANIMATION_HOLD_SUFFIX); } + else + { + if (isAnimationFinished()) + { + trace('Not playing hold (${getCurrentAnimation()}) (${isAnimationFinished()}, ${getCurrentAnimation().endsWith(Constants.ANIMATION_HOLD_SUFFIX)}, ${hasAnimation(getCurrentAnimation() + Constants.ANIMATION_HOLD_SUFFIX)})'); + } + } // Handle character note hold time. if (isSinging()) @@ -427,7 +434,7 @@ class BaseCharacter extends Bopper else { // Play the idle animation. - trace('${characterId}: attempting dance'); + // trace('${characterId}: attempting dance'); dance(true); } } @@ -638,6 +645,7 @@ class BaseCharacter extends Bopper var anim:String = 'sing${dir.nameUpper}${miss ? 'miss' : ''}${suffix != '' ? '-${suffix}' : ''}'; // restart even if already playing, because the character might sing the same note twice. + trace('Playing ${anim}...'); playAnimation(anim, true); } diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index dc42bd651..416e79df6 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -178,9 +178,22 @@ class FreeplayState extends MusicBeatSubState var stickerSubState:Null = null; - public static var rememberedDifficulty:Null = Constants.DEFAULT_DIFFICULTY; + /** + * The difficulty we were on when this menu was last accessed. + */ + public static var rememberedDifficulty:String = Constants.DEFAULT_DIFFICULTY; + + /** + * The song we were on when this menu was last accessed. + * NOTE: `null` if the last song was `Random`. + */ public static var rememberedSongId:Null = 'tutorial'; + /** + * The character we were on when this menu was last accessed. + */ + public static var rememberedCharacterId:String = Constants.DEFAULT_CHARACTER; + var funnyCam:FunkinCamera; var rankCamera:FunkinCamera; var rankBg:FunkinSprite; @@ -210,14 +223,16 @@ class FreeplayState extends MusicBeatSubState public function new(?params:FreeplayStateParams, ?stickers:StickerSubState) { - currentCharacterId = params?.character ?? Constants.DEFAULT_CHARACTER; + currentCharacterId = params?.character ?? rememberedCharacterId; var fetchPlayableCharacter = function():PlayableCharacter { - var result = PlayerRegistry.instance.fetchEntry(params?.character ?? Constants.DEFAULT_CHARACTER); + var result = PlayerRegistry.instance.fetchEntry(params?.character ?? rememberedCharacterId); if (result == null) throw 'No valid playable character with id ${params?.character}'; return result; }; currentCharacter = fetchPlayableCharacter(); + rememberedCharacterId = currentCharacter?.id ?? Constants.DEFAULT_CHARACTER; + fromResultsParams = params?.fromResults; if (fromResultsParams?.playRankAnim == true) @@ -744,10 +759,7 @@ class FreeplayState extends MusicBeatSubState var tempSongs:Array> = songs; // Remember just the difficulty because it's important for song sorting. - if (rememberedDifficulty != null) - { - currentDifficulty = rememberedDifficulty; - } + currentDifficulty = rememberedDifficulty; if (filterStuff != null) tempSongs = sortSongs(tempSongs, filterStuff); @@ -1216,7 +1228,7 @@ class FreeplayState extends MusicBeatSubState FlxG.switchState(FreeplayState.build( { { - character: currentCharacterId == "pico" ? "bf" : "pico", + character: currentCharacterId == "pico" ? Constants.DEFAULT_CHARACTER : "pico", } })); } @@ -1889,7 +1901,7 @@ class FreeplayState extends MusicBeatSubState intendedCompletion = 0.0; diffIdsCurrent = diffIdsTotal; rememberedSongId = null; - rememberedDifficulty = null; + rememberedDifficulty = Constants.DEFAULT_DIFFICULTY; albumRoll.albumId = null; } diff --git a/source/funkin/ui/freeplay/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx index 2eec83223..b4409d377 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -162,7 +162,7 @@ class SongMenuItem extends FlxSpriteGroup sparkle = new FlxSprite(ranking.x, ranking.y); sparkle.frames = Paths.getSparrowAtlas('freeplay/sparkle'); - sparkle.animation.addByPrefix('sparkle', 'sparkle', 24, false); + sparkle.animation.addByPrefix('sparkle', 'sparkle Export0', 24, false); sparkle.animation.play('sparkle', true); sparkle.scale.set(0.8, 0.8); sparkle.blend = BlendMode.ADD; @@ -523,7 +523,6 @@ class SongMenuItem extends FlxSpriteGroup checkWeek(songData?.songId); } - var frameInTicker:Float = 0; var frameInTypeBeat:Int = 0; diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index d219bfbcf..3f532d33c 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -119,7 +119,10 @@ class MainMenuState extends MusicBeatState openSubState(new FreeplayState( { - character: FlxG.keys.pressed.SHIFT ? 'pico' : 'bf', + #if debug + // If SHIFT is held, toggle the selected character, else use the remembered character + character: (FlxG.keys.pressed.SHIFT) ? (FreeplayState.rememberedCharacterId == Constants.DEFAULT_CHARACTER ? 'pico' : 'bf') : null, + #end })); }); From 35ba5663a1ff9b9d95bf2c10e843156c17be4801 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 15 Jul 2024 23:10:08 -0400 Subject: [PATCH 511/870] uncapped framerate on web --- source/Main.hx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/source/Main.hx b/source/Main.hx index add5bbc67..0e5ed0c31 100644 --- a/source/Main.hx +++ b/source/Main.hx @@ -66,6 +66,18 @@ class Main extends Sprite function init(?event:Event):Void { + #if web + untyped js.Syntax.code(" + window.requestAnimationFrame = function(callback, element) { + var currTime = new Date().getTime(); + var timeToCall = 0; + var id = window.setTimeout(function() { callback(currTime + timeToCall); }, + timeToCall); + lastTime = currTime + timeToCall; + return id; + }"); + #end + if (hasEventListener(Event.ADDED_TO_STAGE)) { removeEventListener(Event.ADDED_TO_STAGE, init); From f8232911cb114e867448f10c134dc63b202b1e48 Mon Sep 17 00:00:00 2001 From: 7oltan <87986834+7oltan@users.noreply.github.com> Date: Tue, 16 Jul 2024 12:52:51 +0300 Subject: [PATCH 512/870] FIX CHARACTER PATHS ISSUE --- source/funkin/play/character/AnimateAtlasCharacter.hx | 2 +- source/funkin/play/character/MultiSparrowCharacter.hx | 4 ++-- source/funkin/play/character/PackerCharacter.hx | 2 +- source/funkin/play/character/SparrowCharacter.hx | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/source/funkin/play/character/AnimateAtlasCharacter.hx b/source/funkin/play/character/AnimateAtlasCharacter.hx index ed58b92b5..5b126db6c 100644 --- a/source/funkin/play/character/AnimateAtlasCharacter.hx +++ b/source/funkin/play/character/AnimateAtlasCharacter.hx @@ -131,7 +131,7 @@ class AnimateAtlasCharacter extends BaseCharacter { trace('[ATLASCHAR] Loading sprite atlas for ${characterId}.'); - var sprite:FlxAtlasSprite = new FlxAtlasSprite(0, 0, Paths.animateAtlas(_data.assetPath, 'shared')); + var sprite:FlxAtlasSprite = new FlxAtlasSprite(0, 0, Paths.animateAtlas(_data.assetPath)); sprite.onAnimationFinish.removeAll(); sprite.onAnimationFinish.add(this.onAnimationFinished); diff --git a/source/funkin/play/character/MultiSparrowCharacter.hx b/source/funkin/play/character/MultiSparrowCharacter.hx index 48c5afb58..48a0ec632 100644 --- a/source/funkin/play/character/MultiSparrowCharacter.hx +++ b/source/funkin/play/character/MultiSparrowCharacter.hx @@ -60,7 +60,7 @@ class MultiSparrowCharacter extends BaseCharacter } } - var texture:FlxAtlasFrames = Paths.getSparrowAtlas(_data.assetPath, 'shared'); + var texture:FlxAtlasFrames = Paths.getSparrowAtlas(_data.assetPath); if (texture == null) { @@ -74,7 +74,7 @@ class MultiSparrowCharacter extends BaseCharacter for (asset in assetList) { - var subTexture:FlxAtlasFrames = Paths.getSparrowAtlas(asset, 'shared'); + var subTexture:FlxAtlasFrames = Paths.getSparrowAtlas(asset); // If we don't do this, the unused textures will be removed as soon as they're loaded. if (subTexture == null) diff --git a/source/funkin/play/character/PackerCharacter.hx b/source/funkin/play/character/PackerCharacter.hx index 2bfac800a..b7dda424f 100644 --- a/source/funkin/play/character/PackerCharacter.hx +++ b/source/funkin/play/character/PackerCharacter.hx @@ -30,7 +30,7 @@ class PackerCharacter extends BaseCharacter { trace('[PACKERCHAR] Loading spritesheet ${_data.assetPath} for ${characterId}'); - var tex:FlxFramesCollection = Paths.getPackerAtlas(_data.assetPath, 'shared'); + var tex:FlxFramesCollection = Paths.getPackerAtlas(_data.assetPath); if (tex == null) { trace('Could not load Packer sprite: ${_data.assetPath}'); diff --git a/source/funkin/play/character/SparrowCharacter.hx b/source/funkin/play/character/SparrowCharacter.hx index a36aed84d..90a695ec3 100644 --- a/source/funkin/play/character/SparrowCharacter.hx +++ b/source/funkin/play/character/SparrowCharacter.hx @@ -33,7 +33,7 @@ class SparrowCharacter extends BaseCharacter { trace('[SPARROWCHAR] Loading spritesheet ${_data.assetPath} for ${characterId}'); - var tex:FlxFramesCollection = Paths.getSparrowAtlas(_data.assetPath, 'shared'); + var tex:FlxFramesCollection = Paths.getSparrowAtlas(_data.assetPath); if (tex == null) { trace('Could not load Sparrow sprite: ${_data.assetPath}'); From f8a0627fd270745ba102e8c6a4b0a223e8cf9d3e Mon Sep 17 00:00:00 2001 From: anysad Date: Tue, 16 Jul 2024 20:53:12 +0300 Subject: [PATCH 513/870] goodbye scripts, hello notestyles! --- assets | 2 +- source/funkin/play/Countdown.hx | 101 +++++++++++--------- source/funkin/play/components/PopUpStuff.hx | 75 +++++++-------- source/funkin/ui/transition/LoadingState.hx | 73 +++++++------- source/funkin/util/Constants.hx | 5 + 5 files changed, 132 insertions(+), 124 deletions(-) diff --git a/assets b/assets index e414ee618..ca4d97554 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit e414ee618b4fa577dc3c3df4e156488e91c6348d +Subproject commit ca4d97554f9e3853fda25733f21a5fa108c0b902 diff --git a/source/funkin/play/Countdown.hx b/source/funkin/play/Countdown.hx index 7686e5b75..b97451fa1 100644 --- a/source/funkin/play/Countdown.hx +++ b/source/funkin/play/Countdown.hx @@ -11,6 +11,8 @@ import funkin.modding.events.ScriptEvent.CountdownScriptEvent; import flixel.util.FlxTimer; import funkin.audio.FunkinSound; import openfl.utils.Assets; +import funkin.data.notestyle.NoteStyleRegistry; +import funkin.play.notes.notestyle.NoteStyle; class Countdown { @@ -20,20 +22,13 @@ class Countdown public static var countdownStep(default, null):CountdownStep = BEFORE; /** - * Which alternate countdown sound effect to use. - * You can set this via script. - * For example, in Week 6 it is `-pixel`. + * Which alternate graphic/sound on countdown to use. + * This is set via the current notestyle. + * For example, in Week 6 it is `pixel`. */ - public static var soundSuffix:String = ''; - - /** - * Which alternate graphic on countdown to use. - * You can set this via script. - * For example, in Week 6 it is `-pixel`. - */ - public static var graphicSuffix:String = ''; - + static var noteStyle:NoteStyle; + static var isPixel:Bool = false; /** * The currently running countdown. This will be null if there is no countdown running. @@ -64,6 +59,11 @@ class Countdown // @:privateAccess // PlayState.instance.dispatchEvent(new SongTimeScriptEvent(SONG_BEAT_HIT, 0, 0)); + var fetchedNoteStyle:NoteStyle = NoteStyleRegistry.instance.fetchEntry(PlayState.instance.currentChart.noteStyle); + if (fetchedNoteStyle == null) noteStyle = NoteStyleRegistry.instance.fetchDefault(); + else noteStyle = fetchedNoteStyle; + if (noteStyle._data.assets.note.isPixel) isPixel = true; + // The timer function gets called based on the beat of the song. countdownTimer = new FlxTimer(); @@ -81,10 +81,10 @@ class Countdown // PlayState.instance.dispatchEvent(new SongTimeScriptEvent(SONG_BEAT_HIT, 0, 0)); // Countdown graphic. - showCountdownGraphic(countdownStep, graphicSuffix.toLowerCase().contains('pixel')); + showCountdownGraphic(countdownStep, noteStyle, isPixel); // Countdown sound. - playCountdownSound(countdownStep); + playCountdownSound(countdownStep, noteStyle); // Event handling bullshit. var cancelled:Bool = propagateCountdownEvent(countdownStep); @@ -197,17 +197,31 @@ class Countdown */ public static function reset() { - soundSuffix = ''; - graphicSuffix = ''; + noteStyle = NoteStyleRegistry.instance.fetchDefault(); + isPixel = false; } /** * Retrieves the graphic to use for this step of the countdown. */ - public static function showCountdownGraphic(index:CountdownStep, isGraphicPixel:Bool):Void + public static function showCountdownGraphic(index:CountdownStep, noteStyle:NoteStyle, isGraphicPixel:Bool):Void { + var indexString:String = null; + switch (index) + { + case TWO: + indexString = 'ready'; + case ONE: + indexString = 'set'; + case GO: + indexString = 'go'; + default: + // null + } + if (indexString == null) return; + var spritePath:String = null; - spritePath = resolveGraphicPath(graphicSuffix, index); + spritePath = resolveGraphicPath(noteStyle, indexString); if (spritePath == null) return; @@ -215,12 +229,15 @@ class Countdown countdownSprite.scrollFactor.set(0, 0); if (isGraphicPixel) countdownSprite.setGraphicSize(Std.int(countdownSprite.width * Constants.PIXEL_ART_SCALE)); + else countdownSprite.setGraphicSize(Std.int(countdownSprite.width * 0.7)); countdownSprite.antialiasing = !isGraphicPixel; countdownSprite.updateHitbox(); countdownSprite.screenCenter(); + countdownSprite.cameras = [PlayState.instance.camHUD]; + // Fade sprite in, then out, then destroy it. FlxTween.tween(countdownSprite, {y: countdownSprite.y += 100, alpha: 0}, Conductor.instance.beatLengthMs / 1000, { @@ -233,29 +250,18 @@ class Countdown PlayState.instance.add(countdownSprite); } - static function resolveGraphicPath(suffix:String, index:CountdownStep):Null + static function resolveGraphicPath(noteStyle:NoteStyle, index:String):Null { var basePath:String = 'ui/countdown/'; - var indexString:String = null; - switch (index) + + var spritePath:String = basePath + noteStyle.id + '/$index'; + // If nothing is found, revert it to default notestyle skin + if (!Assets.exists(Paths.image(spritePath))) { - case TWO: - indexString = 'ready'; - case ONE: - indexString = 'set'; - case GO: - indexString = 'go'; - default: - // null + if (!isPixel) spritePath = basePath + Constants.DEFAULT_NOTE_STYLE + '/$index'; + else spritePath = basePath + Constants.DEFAULT_PIXEL_NOTE_STYLE + '/$index'; } - basePath += indexString; - var spritePath:String = basePath + suffix; - while (!Assets.exists(Paths.image(spritePath)) && suffix.length > 0) - { - suffix = suffix.split('-').slice(0, -1).join('-'); - spritePath = basePath + suffix; - } - if (!Assets.exists(Paths.image(spritePath))) return null; + trace('Resolved sprite path: ' + Paths.image(spritePath)); return spritePath; } @@ -263,23 +269,24 @@ class Countdown /** * Retrieves the sound file to use for this step of the countdown. */ - public static function playCountdownSound(index:CountdownStep):Void + public static function playCountdownSound(step:CountdownStep, noteStyle:NoteStyle):Void { - FunkinSound.playOnce(resolveSoundPath(soundSuffix, index), Constants.COUNTDOWN_VOLUME); + return FunkinSound.playOnce(Paths.sound(resolveSoundPath(noteStyle, step)), Constants.COUNTDOWN_VOLUME); } - static function resolveSoundPath(suffix:String, step:CountdownStep):Null + static function resolveSoundPath(noteStyle:NoteStyle, step:CountdownStep):Null { - var basePath:String = 'gameplay/countdown/intro'; - if (step != CountdownStep.BEFORE || step != CountdownStep.AFTER) basePath += step; + if (step == CountdownStep.BEFORE || step == CountdownStep.AFTER) return null; + var basePath:String = 'gameplay/countdown/'; - var soundPath:String = Paths.sound(basePath + suffix); - while (!Assets.exists(soundPath) && suffix.length > 0) + var soundPath:String = basePath + noteStyle.id + '/intro$step'; + // If nothing is found, revert it to default notestyle sound + if (!Assets.exists(Paths.sound(soundPath))) { - suffix = suffix.split('-').slice(0, -1).join('-'); - soundPath = Paths.sound(basePath + suffix); + if (!isPixel) soundPath = basePath + Constants.DEFAULT_NOTE_STYLE + '/intro$step'; + else soundPath = basePath + Constants.DEFAULT_PIXEL_NOTE_STYLE + '/intro$step'; } - if (!Assets.exists(soundPath)) return null; + trace('Resolved sound path: ' + soundPath); return soundPath; } diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx index 0a4d6b019..eb59a9922 100644 --- a/source/funkin/play/components/PopUpStuff.hx +++ b/source/funkin/play/components/PopUpStuff.hx @@ -8,6 +8,8 @@ import funkin.graphics.FunkinSprite; import funkin.play.PlayState; import funkin.util.TimerUtil; import openfl.utils.Assets; +import funkin.data.notestyle.NoteStyleRegistry; +import funkin.play.notes.notestyle.NoteStyle; class PopUpStuff extends FlxTypedGroup { @@ -15,31 +17,35 @@ class PopUpStuff extends FlxTypedGroup /** * Which alternate graphic on popup to use. - * You can set this via script. - * For example, in Week 6 it is `-pixel`. + * This is set via the current notestyle. + * For example, in Week 6 it is `pixel`. */ - public static var graphicSuffix:String = ''; + static var noteStyle:NoteStyle; + + static var isPixel:Bool = false; override public function new() { super(); + + var fetchedNoteStyle:NoteStyle = NoteStyleRegistry.instance.fetchEntry(PlayState.instance.currentChart.noteStyle); + if (fetchedNoteStyle == null) noteStyle = NoteStyleRegistry.instance.fetchDefault(); + else noteStyle = fetchedNoteStyle; + if (noteStyle._data.assets.note.isPixel) isPixel = true; } - static function resolveGraphicPath(suffix:String, index:String):Null + static function resolveGraphicPath(noteStyle:NoteStyle, index:String):Null { - var folder:String; - if (suffix != '') - folder = suffix.substring(0, suffix.indexOf("-")) + suffix.substring(suffix.indexOf("-") + 1); - else - folder = 'normal'; - var basePath:String = 'gameplay/popup/$folder/$index'; - var spritePath:String = basePath + suffix; - while (!Assets.exists(Paths.image(spritePath)) && suffix.length > 0) + var basePath:String = 'ui/popup/'; + + var spritePath:String = basePath + noteStyle.id + '/$index'; + // If nothing is found, revert it to default notestyle skin + if (!Assets.exists(Paths.image(spritePath))) { - suffix = suffix.split('-').slice(0, -1).join('-'); - spritePath = basePath + suffix; + if (!isPixel) spritePath = basePath + Constants.DEFAULT_NOTE_STYLE + '/$index'; + else spritePath = basePath + Constants.DEFAULT_PIXEL_NOTE_STYLE + '/$index'; } - if (!Assets.exists(Paths.image(spritePath))) return null; + return spritePath; } @@ -49,7 +55,7 @@ class PopUpStuff extends FlxTypedGroup if (daRating == null) daRating = "good"; - var ratingPath:String = resolveGraphicPath(graphicSuffix, daRating); + var ratingPath:String = resolveGraphicPath(noteStyle, daRating); //if (PlayState.instance.currentStageId.startsWith('school')) ratingPath = "weeb/pixelUI/" + ratingPath + "-pixel"; @@ -66,7 +72,7 @@ class PopUpStuff extends FlxTypedGroup add(rating); - if (graphicSuffix.toLowerCase().contains('pixel')) + if (isPixel) { rating.setGraphicSize(Std.int(rating.width * Constants.PIXEL_ART_SCALE * 0.7)); rating.antialiasing = false; @@ -99,7 +105,7 @@ class PopUpStuff extends FlxTypedGroup if (combo == null) combo = 0; - var comboPath:String = resolveGraphicPath(graphicSuffix, Std.string(combo)); + var comboPath:String = resolveGraphicPath(noteStyle, 'combo'); var comboSpr:FunkinSprite = FunkinSprite.create(comboPath); comboSpr.y = (FlxG.camera.height * 0.44) + offsets[1]; comboSpr.x = (FlxG.width * 0.507) + offsets[0]; @@ -111,16 +117,10 @@ class PopUpStuff extends FlxTypedGroup // add(comboSpr); - if (graphicSuffix.toLowerCase().contains('pixel')) - { - comboSpr.setGraphicSize(Std.int(comboSpr.width * Constants.PIXEL_ART_SCALE * 0.7)); - comboSpr.antialiasing = false; - } - else - { - comboSpr.setGraphicSize(Std.int(comboSpr.width * 0.7)); - comboSpr.antialiasing = true; - } + if (isPixel) comboSpr.setGraphicSize(Std.int(comboSpr.width * Constants.PIXEL_ART_SCALE * 0.7)); + else comboSpr.setGraphicSize(Std.int(comboSpr.width * 0.7)); + + comboSpr.antialiasing = !isPixel; comboSpr.updateHitbox(); FlxTween.tween(comboSpr, {alpha: 0}, 0.2, @@ -148,18 +148,12 @@ class PopUpStuff extends FlxTypedGroup var daLoop:Int = 1; for (i in seperatedScore) { - var numScore:FunkinSprite = FunkinSprite.create(0, comboSpr.y, resolveGraphicPath(graphicSuffix, 'num' + Std.int(i))); + var numScore:FunkinSprite = FunkinSprite.create(0, comboSpr.y, resolveGraphicPath(noteStyle, 'num' + Std.int(i))); - if (graphicSuffix.toLowerCase().contains('pixel')) - { - numScore.setGraphicSize(Std.int(numScore.width * Constants.PIXEL_ART_SCALE * 0.7)); - numScore.antialiasing = false; - } - else - { - numScore.setGraphicSize(Std.int(numScore.width * 0.45)); - numScore.antialiasing = true; - } + if (isPixel) numScore.setGraphicSize(Std.int(numScore.width * Constants.PIXEL_ART_SCALE * 0.7)); + else numScore.setGraphicSize(Std.int(numScore.width * 0.45)); + + numScore.antialiasing = !isPixel; numScore.updateHitbox(); numScore.x = comboSpr.x - (36 * daLoop) - 65; //- 90; @@ -191,6 +185,7 @@ class PopUpStuff extends FlxTypedGroup */ public static function reset() { - graphicSuffix = ''; + noteStyle = NoteStyleRegistry.instance.fetchDefault(); + isPixel = false; } } diff --git a/source/funkin/ui/transition/LoadingState.hx b/source/funkin/ui/transition/LoadingState.hx index a571126fe..e50032d65 100644 --- a/source/funkin/ui/transition/LoadingState.hx +++ b/source/funkin/ui/transition/LoadingState.hx @@ -291,46 +291,47 @@ class LoadingState extends MusicBeatSubState FunkinSprite.preparePurgeCache(); FunkinSprite.cacheTexture(Paths.image('healthBar')); FunkinSprite.cacheTexture(Paths.image('menuDesat')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/combo')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num0')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num1')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num2')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num3')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num4')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num5')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num6')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num7')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num8')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num9')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/combo-pixel')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num0-pixel')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num1-pixel')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num2-pixel')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num3-pixel')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num4-pixel')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num5-pixel')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num6-pixel')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num7-pixel')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num8-pixel')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num9-pixel')); + // Lord have mercy on me and this caching -anysad + FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/combo')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num0')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num1')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num2')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num3')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num4')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num5')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num6')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num7')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num8')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num9')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/combo')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num0')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num1')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num2')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num3')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num4')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num5')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num6')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num7')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num8')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num9')); FunkinSprite.cacheTexture(Paths.image('notes', 'shared')); FunkinSprite.cacheTexture(Paths.image('noteSplashes', 'shared')); FunkinSprite.cacheTexture(Paths.image('noteStrumline', 'shared')); FunkinSprite.cacheTexture(Paths.image('NOTE_hold_assets')); - FunkinSprite.cacheTexture(Paths.image('ui/countdown/ready', 'shared')); - FunkinSprite.cacheTexture(Paths.image('ui/countdown/set', 'shared')); - FunkinSprite.cacheTexture(Paths.image('ui/countdown/go', 'shared')); - FunkinSprite.cacheTexture(Paths.image('ui/countdown/ready-pixel', 'shared')); - FunkinSprite.cacheTexture(Paths.image('ui/countdown/set-pixel', 'shared')); - FunkinSprite.cacheTexture(Paths.image('ui/countdown/go-pixel', 'shared')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/sick')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/good')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/bad')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/shit')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/sick-pixel')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/good-pixel')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/bad-pixel')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/shit-pixel')); + FunkinSprite.cacheTexture(Paths.image('ui/countdown/funkin/ready', 'shared')); + FunkinSprite.cacheTexture(Paths.image('ui/countdown/funkin/set', 'shared')); + FunkinSprite.cacheTexture(Paths.image('ui/countdown/funkin/go', 'shared')); + FunkinSprite.cacheTexture(Paths.image('ui/countdown/pixel/ready', 'shared')); + FunkinSprite.cacheTexture(Paths.image('ui/countdown/pixel/set', 'shared')); + FunkinSprite.cacheTexture(Paths.image('ui/countdown/pixel/go', 'shared')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/normal/sick')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/normal/good')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/normal/bad')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/normal/shit')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/sick')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/good')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/bad')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/shit')); FunkinSprite.cacheTexture(Paths.image('miss', 'shared')); // TODO: remove this // List all image assets in the level's library. diff --git a/source/funkin/util/Constants.hx b/source/funkin/util/Constants.hx index 1e0978839..79b0e05c5 100644 --- a/source/funkin/util/Constants.hx +++ b/source/funkin/util/Constants.hx @@ -258,6 +258,11 @@ class Constants */ public static final DEFAULT_NOTE_STYLE:String = 'funkin'; + /** + * The default pixel note style for songs. + */ + public static final DEFAULT_PIXEL_NOTE_STYLE:String = 'pixel'; + /** * The default album for songs in Freeplay. */ From 5e1d25e791a14f6b301730043607e14b53f36e8d Mon Sep 17 00:00:00 2001 From: AppleHair <95587502+AppleHair@users.noreply.github.com> Date: Tue, 16 Jul 2024 21:17:53 +0300 Subject: [PATCH 514/870] [BUGFIX] Prevented infinite recursion on freeplay when a song doesn't have the `normal` difficulty Any attempt to create a song without the `normal` difficulty will result in a silent crash when opening freeplay. After some debugging, I discovered that the issue is caused by infinite recursion, which gets triggered at the start of `FreeplaySongData`'s `updateValues`. --- source/funkin/ui/freeplay/FreeplayState.hx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 0caaf4591..9873f3be6 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -2077,7 +2077,11 @@ class FreeplaySongData function updateValues(variations:Array):Void { this.songDifficulties = song.listDifficulties(null, variations, false, false); - if (!this.songDifficulties.contains(currentDifficulty)) currentDifficulty = Constants.DEFAULT_DIFFICULTY; + if (!this.songDifficulties.contains(currentDifficulty) && currentDifficulty != Constants.DEFAULT_DIFFICULTY) + { + currentDifficulty = Constants.DEFAULT_DIFFICULTY; + return; + } var songDifficulty:SongDifficulty = song.getDifficulty(currentDifficulty, null, variations); if (songDifficulty == null) return; From ee449819959ed51b5719f7ebd39493118c307eee Mon Sep 17 00:00:00 2001 From: anysad Date: Tue, 16 Jul 2024 22:02:05 +0300 Subject: [PATCH 515/870] you know what, make countdown sprites a little bigger --- source/funkin/play/Countdown.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/play/Countdown.hx b/source/funkin/play/Countdown.hx index b97451fa1..ccd478347 100644 --- a/source/funkin/play/Countdown.hx +++ b/source/funkin/play/Countdown.hx @@ -228,8 +228,8 @@ class Countdown var countdownSprite:FunkinSprite = FunkinSprite.create(spritePath); countdownSprite.scrollFactor.set(0, 0); - if (isGraphicPixel) countdownSprite.setGraphicSize(Std.int(countdownSprite.width * Constants.PIXEL_ART_SCALE)); - else countdownSprite.setGraphicSize(Std.int(countdownSprite.width * 0.7)); + if (isGraphicPixel) countdownSprite.setGraphicSize(Std.int(countdownSprite.width * Constants.PIXEL_ART_SCALE * 1.1)); + else countdownSprite.setGraphicSize(Std.int(countdownSprite.width * 0.8)); countdownSprite.antialiasing = !isGraphicPixel; From a93cd05aeb6c30c241c6c8f8211abb953bb65532 Mon Sep 17 00:00:00 2001 From: AppleHair <95587502+AppleHair@users.noreply.github.com> Date: Tue, 16 Jul 2024 22:36:11 +0300 Subject: [PATCH 516/870] Added a comment --- source/funkin/ui/freeplay/FreeplayState.hx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 9873f3be6..51fda0677 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -2080,6 +2080,8 @@ class FreeplaySongData if (!this.songDifficulties.contains(currentDifficulty) && currentDifficulty != Constants.DEFAULT_DIFFICULTY) { currentDifficulty = Constants.DEFAULT_DIFFICULTY; + // This method gets called again by the setter-method, + // so there's no need to continue. return; } From 691da783fc41fc648b760833d4439c4368ef29a3 Mon Sep 17 00:00:00 2001 From: AppleHair <95587502+AppleHair@users.noreply.github.com> Date: Wed, 17 Jul 2024 10:20:48 +0300 Subject: [PATCH 517/870] Updated to extend #2712 --- 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 51fda0677..a22652586 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -2077,11 +2077,11 @@ class FreeplaySongData function updateValues(variations:Array):Void { this.songDifficulties = song.listDifficulties(null, variations, false, false); - if (!this.songDifficulties.contains(currentDifficulty) && currentDifficulty != Constants.DEFAULT_DIFFICULTY) + if (!this.songDifficulties.contains(currentDifficulty)) { currentDifficulty = Constants.DEFAULT_DIFFICULTY; - // This method gets called again by the setter-method, - // so there's no need to continue. + // This method gets called again by the setter-method + // or the difficulty didn't change, so there's no need to continue. return; } From 4d81aa0fe696a1878d3678209e20c985e1631425 Mon Sep 17 00:00:00 2001 From: AppleHair <95587502+AppleHair@users.noreply.github.com> Date: Wed, 17 Jul 2024 18:00:07 +0300 Subject: [PATCH 518/870] [BUGFIX] Ensure the variation used for the next song is valid. When playing in story mode, `PlayState` assumes all the songs use the same variation, which is usually true, but not guaranteed. This PR makes `PlayState` use the `getFirstValidVariation` method to find the valid variation instead of using the `currentVariation` variable, which might not be valid. --- source/funkin/play/PlayState.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index f55cef388..9b1cc2ed9 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -2963,7 +2963,7 @@ class PlayState extends MusicBeatSubState { targetSong: targetSong, targetDifficulty: PlayStatePlaylist.campaignDifficulty, - targetVariation: currentVariation, + targetVariation: targetSong.getFirstValidVariation(PlayStatePlaylist.campaignDifficulty), cameraFollowPoint: cameraFollowPoint.getPosition(), }); }); @@ -2975,7 +2975,7 @@ class PlayState extends MusicBeatSubState { targetSong: targetSong, targetDifficulty: PlayStatePlaylist.campaignDifficulty, - targetVariation: currentVariation, + targetVariation: targetSong.getFirstValidVariation(PlayStatePlaylist.campaignDifficulty), cameraFollowPoint: cameraFollowPoint.getPosition(), }); } From ff1ab1eb4245092829701e322c1b4dbe27f80590 Mon Sep 17 00:00:00 2001 From: anysad Date: Wed, 17 Jul 2024 23:19:18 +0300 Subject: [PATCH 519/870] welcome fallback note styles! --- source/funkin/play/Countdown.hx | 53 ++++++++++++++----- source/funkin/play/components/PopUpStuff.hx | 21 +++++++- .../funkin/play/notes/notestyle/NoteStyle.hx | 2 +- 3 files changed, 59 insertions(+), 17 deletions(-) diff --git a/source/funkin/play/Countdown.hx b/source/funkin/play/Countdown.hx index ccd478347..25a896317 100644 --- a/source/funkin/play/Countdown.hx +++ b/source/funkin/play/Countdown.hx @@ -28,6 +28,8 @@ class Countdown */ static var noteStyle:NoteStyle; + static var fallbackNoteStyle:Null; + static var isPixel:Bool = false; /** @@ -59,10 +61,7 @@ class Countdown // @:privateAccess // PlayState.instance.dispatchEvent(new SongTimeScriptEvent(SONG_BEAT_HIT, 0, 0)); - var fetchedNoteStyle:NoteStyle = NoteStyleRegistry.instance.fetchEntry(PlayState.instance.currentChart.noteStyle); - if (fetchedNoteStyle == null) noteStyle = NoteStyleRegistry.instance.fetchDefault(); - else noteStyle = fetchedNoteStyle; - if (noteStyle._data.assets.note.isPixel) isPixel = true; + fetchNoteStyle(); // The timer function gets called based on the beat of the song. countdownTimer = new FlxTimer(); @@ -81,7 +80,7 @@ class Countdown // PlayState.instance.dispatchEvent(new SongTimeScriptEvent(SONG_BEAT_HIT, 0, 0)); // Countdown graphic. - showCountdownGraphic(countdownStep, noteStyle, isPixel); + showCountdownGraphic(countdownStep, noteStyle); // Countdown sound. playCountdownSound(countdownStep, noteStyle); @@ -201,10 +200,19 @@ class Countdown isPixel = false; } + static function fetchNoteStyle():Void + { + var fetchedNoteStyle:NoteStyle = NoteStyleRegistry.instance.fetchEntry(PlayState.instance.currentChart.noteStyle); + if (fetchedNoteStyle == null) noteStyle = NoteStyleRegistry.instance.fetchDefault(); + else noteStyle = fetchedNoteStyle; + fallbackNoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyle.getFallbackID()); + isPixel = false; + } + /** * Retrieves the graphic to use for this step of the countdown. */ - public static function showCountdownGraphic(index:CountdownStep, noteStyle:NoteStyle, isGraphicPixel:Bool):Void + public static function showCountdownGraphic(index:CountdownStep, noteStyle:NoteStyle):Void { var indexString:String = null; switch (index) @@ -228,16 +236,16 @@ class Countdown var countdownSprite:FunkinSprite = FunkinSprite.create(spritePath); countdownSprite.scrollFactor.set(0, 0); - if (isGraphicPixel) countdownSprite.setGraphicSize(Std.int(countdownSprite.width * Constants.PIXEL_ART_SCALE * 1.1)); + if (isPixel) countdownSprite.setGraphicSize(Std.int(countdownSprite.width * Constants.PIXEL_ART_SCALE * 1.1)); else countdownSprite.setGraphicSize(Std.int(countdownSprite.width * 0.8)); - countdownSprite.antialiasing = !isGraphicPixel; + countdownSprite.antialiasing = !isPixel; + + countdownSprite.cameras = [PlayState.instance.camHUD]; countdownSprite.updateHitbox(); countdownSprite.screenCenter(); - countdownSprite.cameras = [PlayState.instance.camHUD]; - // Fade sprite in, then out, then destroy it. FlxTween.tween(countdownSprite, {y: countdownSprite.y += 100, alpha: 0}, Conductor.instance.beatLengthMs / 1000, { @@ -252,10 +260,18 @@ class Countdown static function resolveGraphicPath(noteStyle:NoteStyle, index:String):Null { + fetchNoteStyle(); var basePath:String = 'ui/countdown/'; - var spritePath:String = basePath + noteStyle.id + '/$index'; - // If nothing is found, revert it to default notestyle skin + + while (!Assets.exists(Paths.image(spritePath)) && fallbackNoteStyle != null) { + noteStyle = fallbackNoteStyle; + fallbackNoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyle.getFallbackID()); + spritePath = basePath + noteStyle.id + '/$index'; + } + if (noteStyle.isHoldNotePixel()) isPixel = true; + + // If ABSOLUTELY nothing is found, revert it to default notestyle skin if (!Assets.exists(Paths.image(spritePath))) { if (!isPixel) spritePath = basePath + Constants.DEFAULT_NOTE_STYLE + '/$index'; @@ -277,10 +293,19 @@ class Countdown static function resolveSoundPath(noteStyle:NoteStyle, step:CountdownStep):Null { if (step == CountdownStep.BEFORE || step == CountdownStep.AFTER) return null; + fetchNoteStyle(); var basePath:String = 'gameplay/countdown/'; - var soundPath:String = basePath + noteStyle.id + '/intro$step'; - // If nothing is found, revert it to default notestyle sound + + while (!Assets.exists(Paths.sound(soundPath)) && fallbackNoteStyle != null) + { + noteStyle = fallbackNoteStyle; + fallbackNoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyle.getFallbackID()); + soundPath = basePath + noteStyle.id + '/intro$step'; + } + if (noteStyle.isHoldNotePixel()) isPixel = true; + + // If ABSOLUTELY nothing is found, revert it to default notestyle sound if (!Assets.exists(Paths.sound(soundPath))) { if (!isPixel) soundPath = basePath + Constants.DEFAULT_NOTE_STYLE + '/intro$step'; diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx index eb59a9922..6c111c0db 100644 --- a/source/funkin/play/components/PopUpStuff.hx +++ b/source/funkin/play/components/PopUpStuff.hx @@ -22,23 +22,40 @@ class PopUpStuff extends FlxTypedGroup */ static var noteStyle:NoteStyle; + static var fallbackNoteStyle:Null; + static var isPixel:Bool = false; override public function new() { super(); + fetchNoteStyle(); + } + + static function fetchNoteStyle():Void + { var fetchedNoteStyle:NoteStyle = NoteStyleRegistry.instance.fetchEntry(PlayState.instance.currentChart.noteStyle); if (fetchedNoteStyle == null) noteStyle = NoteStyleRegistry.instance.fetchDefault(); else noteStyle = fetchedNoteStyle; - if (noteStyle._data.assets.note.isPixel) isPixel = true; + fallbackNoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyle.getFallbackID()); + isPixel = false; } static function resolveGraphicPath(noteStyle:NoteStyle, index:String):Null { + fetchNoteStyle(); var basePath:String = 'ui/popup/'; - var spritePath:String = basePath + noteStyle.id + '/$index'; + + while (!Assets.exists(Paths.image(spritePath)) && fallbackNoteStyle != null) + { + noteStyle = fallbackNoteStyle; + fallbackNoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyle.getFallbackID()); + spritePath = basePath + noteStyle.id + '/$index'; + } + if (noteStyle.isHoldNotePixel()) isPixel = true; + // If nothing is found, revert it to default notestyle skin if (!Assets.exists(Paths.image(spritePath))) { diff --git a/source/funkin/play/notes/notestyle/NoteStyle.hx b/source/funkin/play/notes/notestyle/NoteStyle.hx index d0cc09f6a..edfcff2ee 100644 --- a/source/funkin/play/notes/notestyle/NoteStyle.hx +++ b/source/funkin/play/notes/notestyle/NoteStyle.hx @@ -72,7 +72,7 @@ class NoteStyle implements IRegistryEntry * Get the note style ID of the parent note style. * @return The string ID, or `null` if there is no parent. */ - function getFallbackID():Null + public function getFallbackID():Null { return _data.fallback; } From 73fc855f8e6eb8efb14e7ab7d35ff269e76287f2 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Thu, 18 Jul 2024 05:23:31 +0100 Subject: [PATCH 520/870] new stage names --- source/funkin/data/stage/StageRegistry.hx | 4 ++-- source/funkin/ui/debug/charting/ChartEditorState.hx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/funkin/data/stage/StageRegistry.hx b/source/funkin/data/stage/StageRegistry.hx index a03371296..fbb6f188e 100644 --- a/source/funkin/data/stage/StageRegistry.hx +++ b/source/funkin/data/stage/StageRegistry.hx @@ -93,8 +93,8 @@ class StageRegistry extends BaseRegistry public function listBaseGameStageIds():Array { return [ - "mainStage", "spookyMansion", "phillyTrain", "limoRide", "mallXmas", "mallEvil", "school", "schoolEvil", "tankmanBattlefield", "phillyStreets", - "phillyBlazin", + "mainStage", "spookyMansion", "phillyTrain", "phillyTrainErect", "limoRide", "mallXmas", "mallEvil", "school", "schoolEvil", "tankmanBattlefield", + "phillyStreets", "phillyBlazin", ]; } diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index f72cca77f..a4e0de61e 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -5703,9 +5703,9 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState { case 'mainStage': PlayStatePlaylist.campaignId = 'week1'; - case 'spookyMansion': + case 'spookyMansion' | 'spookyMansionErect': PlayStatePlaylist.campaignId = 'week2'; - case 'phillyTrain': + case 'phillyTrain' | 'phillyTrainErect': PlayStatePlaylist.campaignId = 'week3'; case 'limoRide': PlayStatePlaylist.campaignId = 'week4'; From ad93706b1df16f8191e839b6920da4e5e316c071 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Thu, 18 Jul 2024 05:23:37 +0100 Subject: [PATCH 521/870] adjust color shader --- .../graphics/shaders/AdjustColorShader.hx | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 source/funkin/graphics/shaders/AdjustColorShader.hx diff --git a/source/funkin/graphics/shaders/AdjustColorShader.hx b/source/funkin/graphics/shaders/AdjustColorShader.hx new file mode 100644 index 000000000..2b0970eeb --- /dev/null +++ b/source/funkin/graphics/shaders/AdjustColorShader.hx @@ -0,0 +1,55 @@ +package funkin.graphics.shaders; + +import flixel.addons.display.FlxRuntimeShader; +import funkin.Paths; +import openfl.utils.Assets; + +class AdjustColorShader extends FlxRuntimeShader +{ + public var hue(default, set):Float; + public var saturation(default, set):Float; + public var brightness(default, set):Float; + public var contrast(default, set):Float; + + public function new() + { + super(Assets.getText(Paths.frag('adjustColor'))); + // FlxG.debugger.addTrackerProfile(new TrackerProfile(HSVShader, ['hue', 'saturation', 'brightness', 'contrast'])); + hue = 0; + saturation = 0; + brightness = 0; + contrast = 0; + } + + function set_hue(value:Float):Float + { + this.setFloat('hue', value); + this.hue = value; + + return this.hue; + } + + function set_saturation(value:Float):Float + { + this.setFloat('saturation', value); + this.saturation = value; + + return this.saturation; + } + + function set_brightness(value:Float):Float + { + this.setFloat('brightness', value); + this.brightness = value; + + return this.brightness; + } + + function set_contrast(value:Float):Float + { + this.setFloat('contrast', value); + this.contrast = value; + + return this.contrast; + } +} From 4bcfbc957f82726973b4aa1428b285d1132a19e7 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Thu, 18 Jul 2024 05:24:15 +0100 Subject: [PATCH 522/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 005c96f85..68bf145d5 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 005c96f85f4304865acb196e7cc4d6d83f9d76d8 +Subproject commit 68bf145d5786b2c3e4539a46727da67bef1fd039 From a0ab216617b16d87ed363a590979b4cdc8879012 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Thu, 18 Jul 2024 06:04:19 +0100 Subject: [PATCH 523/870] merged rain shader stuff from 'feature/week2-erect-bg-rain' --- .../shaders/RuntimePostEffectShader.hx | 31 +++++++++++++++++++ .../graphics/shaders/RuntimeRainShader.hx | 8 +++++ 2 files changed, 39 insertions(+) diff --git a/source/funkin/graphics/shaders/RuntimePostEffectShader.hx b/source/funkin/graphics/shaders/RuntimePostEffectShader.hx index 9f49da075..d39f57efe 100644 --- a/source/funkin/graphics/shaders/RuntimePostEffectShader.hx +++ b/source/funkin/graphics/shaders/RuntimePostEffectShader.hx @@ -2,6 +2,7 @@ package funkin.graphics.shaders; import flixel.FlxCamera; import flixel.FlxG; +import flixel.graphics.frames.FlxFrame; import flixel.addons.display.FlxRuntimeShader; import lime.graphics.opengl.GLProgram; import lime.utils.Log; @@ -32,6 +33,9 @@ class RuntimePostEffectShader extends FlxRuntimeShader // equals (camera.viewLeft, camera.viewTop, camera.viewRight, camera.viewBottom) uniform vec4 uCameraBounds; + // equals (frame.left, frame.top, frame.right, frame.bottom) + uniform vec4 uFrameBounds; + // screen coord -> world coord conversion // returns world coord in px vec2 screenToWorld(vec2 screenCoord) { @@ -56,6 +60,25 @@ class RuntimePostEffectShader extends FlxRuntimeShader return (worldCoord - offset) / scale; } + // screen coord -> frame coord conversion + // returns normalized frame coord + vec2 screenToFrame(vec2 screenCoord) { + float left = uFrameBounds.x; + float top = uFrameBounds.y; + float right = uFrameBounds.z; + float bottom = uFrameBounds.w; + float width = right - left; + float height = bottom - top; + + float clampedX = clamp(screenCoord.x, left, right); + float clampedY = clamp(screenCoord.y, top, bottom); + + return vec2( + (clampedX - left) / (width), + (clampedY - top) / (height) + ); + } + // internally used to get the maximum `openfl_TextureCoordv` vec2 bitmapCoordScale() { return openfl_TextureCoordv / screenCoord; @@ -80,6 +103,8 @@ class RuntimePostEffectShader extends FlxRuntimeShader { super(fragmentSource, null, glVersion); uScreenResolution.value = [FlxG.width, FlxG.height]; + uCameraBounds.value = [0, 0, FlxG.width, FlxG.height]; + uFrameBounds.value = [0, 0, FlxG.width, FlxG.height]; } // basically `updateViewInfo(FlxG.width, FlxG.height, FlxG.camera)` is good @@ -89,6 +114,12 @@ class RuntimePostEffectShader extends FlxRuntimeShader uCameraBounds.value = [camera.viewLeft, camera.viewTop, camera.viewRight, camera.viewBottom]; } + public function updateFrameInfo(frame:FlxFrame) + { + // NOTE: uv.width is actually the right pos and uv.height is the bottom pos + uFrameBounds.value = [frame.uv.x, frame.uv.y, frame.uv.width, frame.uv.height]; + } + override function __createGLProgram(vertexSource:String, fragmentSource:String):GLProgram { try diff --git a/source/funkin/graphics/shaders/RuntimeRainShader.hx b/source/funkin/graphics/shaders/RuntimeRainShader.hx index 239276bbe..68a203179 100644 --- a/source/funkin/graphics/shaders/RuntimeRainShader.hx +++ b/source/funkin/graphics/shaders/RuntimeRainShader.hx @@ -32,6 +32,14 @@ class RuntimeRainShader extends RuntimePostEffectShader return time = value; } + public var spriteMode(default, set):Bool = false; + + function set_spriteMode(value:Bool):Bool + { + this.setBool('uSpriteMode', value); + return spriteMode = value; + } + // The scale of the rain depends on the world coordinate system, so higher resolution makes // the raindrops smaller. This parameter can be used to adjust the total scale of the scene. // The size of the raindrops is proportional to the value of this parameter. From 563905ebd42810550904a3c4c894bc24afbc4f30 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Thu, 18 Jul 2024 06:04:32 +0100 Subject: [PATCH 524/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 68bf145d5..cfd67caa6 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 68bf145d5786b2c3e4539a46727da67bef1fd039 +Subproject commit cfd67caa688465b4a282837434832c107b661b04 From ba96b111960e2945c14eef0112368a30152d1e7c Mon Sep 17 00:00:00 2001 From: anysad Date: Thu, 18 Jul 2024 17:56:54 +0300 Subject: [PATCH 525/870] hopefully final polish? --- source/funkin/play/Countdown.hx | 26 ++++++++++----------- source/funkin/play/components/PopUpStuff.hx | 10 ++++---- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/source/funkin/play/Countdown.hx b/source/funkin/play/Countdown.hx index 25a896317..1a9605597 100644 --- a/source/funkin/play/Countdown.hx +++ b/source/funkin/play/Countdown.hx @@ -61,8 +61,6 @@ class Countdown // @:privateAccess // PlayState.instance.dispatchEvent(new SongTimeScriptEvent(SONG_BEAT_HIT, 0, 0)); - fetchNoteStyle(); - // The timer function gets called based on the beat of the song. countdownTimer = new FlxTimer(); @@ -80,10 +78,10 @@ class Countdown // PlayState.instance.dispatchEvent(new SongTimeScriptEvent(SONG_BEAT_HIT, 0, 0)); // Countdown graphic. - showCountdownGraphic(countdownStep, noteStyle); + showCountdownGraphic(countdownStep); // Countdown sound. - playCountdownSound(countdownStep, noteStyle); + playCountdownSound(countdownStep); // Event handling bullshit. var cancelled:Bool = propagateCountdownEvent(countdownStep); @@ -212,7 +210,7 @@ class Countdown /** * Retrieves the graphic to use for this step of the countdown. */ - public static function showCountdownGraphic(index:CountdownStep, noteStyle:NoteStyle):Void + public static function showCountdownGraphic(index:CountdownStep):Void { var indexString:String = null; switch (index) @@ -229,25 +227,24 @@ class Countdown if (indexString == null) return; var spritePath:String = null; - spritePath = resolveGraphicPath(noteStyle, indexString); + spritePath = resolveGraphicPath(indexString); if (spritePath == null) return; var countdownSprite:FunkinSprite = FunkinSprite.create(spritePath); countdownSprite.scrollFactor.set(0, 0); - if (isPixel) countdownSprite.setGraphicSize(Std.int(countdownSprite.width * Constants.PIXEL_ART_SCALE * 1.1)); - else countdownSprite.setGraphicSize(Std.int(countdownSprite.width * 0.8)); + if (isPixel) countdownSprite.setGraphicSize(Std.int(countdownSprite.width * Constants.PIXEL_ART_SCALE)); + else countdownSprite.setGraphicSize(Std.int(countdownSprite.width * 0.7)); countdownSprite.antialiasing = !isPixel; countdownSprite.cameras = [PlayState.instance.camHUD]; countdownSprite.updateHitbox(); - countdownSprite.screenCenter(); // Fade sprite in, then out, then destroy it. - FlxTween.tween(countdownSprite, {y: countdownSprite.y += 100, alpha: 0}, Conductor.instance.beatLengthMs / 1000, + FlxTween.tween(countdownSprite, {alpha: 0}, Conductor.instance.beatLengthMs / 1000, { ease: FlxEase.cubeInOut, onComplete: function(twn:FlxTween) { @@ -256,9 +253,10 @@ class Countdown }); PlayState.instance.add(countdownSprite); + countdownSprite.screenCenter(); } - static function resolveGraphicPath(noteStyle:NoteStyle, index:String):Null + static function resolveGraphicPath(index:String):Null { fetchNoteStyle(); var basePath:String = 'ui/countdown/'; @@ -285,12 +283,12 @@ class Countdown /** * Retrieves the sound file to use for this step of the countdown. */ - public static function playCountdownSound(step:CountdownStep, noteStyle:NoteStyle):Void + public static function playCountdownSound(step:CountdownStep):Void { - return FunkinSound.playOnce(Paths.sound(resolveSoundPath(noteStyle, step)), Constants.COUNTDOWN_VOLUME); + return FunkinSound.playOnce(Paths.sound(resolveSoundPath(step)), Constants.COUNTDOWN_VOLUME); } - static function resolveSoundPath(noteStyle:NoteStyle, step:CountdownStep):Null + static function resolveSoundPath(step:CountdownStep):Null { if (step == CountdownStep.BEFORE || step == CountdownStep.AFTER) return null; fetchNoteStyle(); diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx index 6c111c0db..402535878 100644 --- a/source/funkin/play/components/PopUpStuff.hx +++ b/source/funkin/play/components/PopUpStuff.hx @@ -29,8 +29,6 @@ class PopUpStuff extends FlxTypedGroup override public function new() { super(); - - fetchNoteStyle(); } static function fetchNoteStyle():Void @@ -42,7 +40,7 @@ class PopUpStuff extends FlxTypedGroup isPixel = false; } - static function resolveGraphicPath(noteStyle:NoteStyle, index:String):Null + static function resolveGraphicPath(index:String):Null { fetchNoteStyle(); var basePath:String = 'ui/popup/'; @@ -72,7 +70,7 @@ class PopUpStuff extends FlxTypedGroup if (daRating == null) daRating = "good"; - var ratingPath:String = resolveGraphicPath(noteStyle, daRating); + var ratingPath:String = resolveGraphicPath(daRating); //if (PlayState.instance.currentStageId.startsWith('school')) ratingPath = "weeb/pixelUI/" + ratingPath + "-pixel"; @@ -122,7 +120,7 @@ class PopUpStuff extends FlxTypedGroup if (combo == null) combo = 0; - var comboPath:String = resolveGraphicPath(noteStyle, 'combo'); + var comboPath:String = resolveGraphicPath('combo'); var comboSpr:FunkinSprite = FunkinSprite.create(comboPath); comboSpr.y = (FlxG.camera.height * 0.44) + offsets[1]; comboSpr.x = (FlxG.width * 0.507) + offsets[0]; @@ -165,7 +163,7 @@ class PopUpStuff extends FlxTypedGroup var daLoop:Int = 1; for (i in seperatedScore) { - var numScore:FunkinSprite = FunkinSprite.create(0, comboSpr.y, resolveGraphicPath(noteStyle, 'num' + Std.int(i))); + var numScore:FunkinSprite = FunkinSprite.create(0, comboSpr.y, resolveGraphicPath('num' + Std.int(i))); if (isPixel) numScore.setGraphicSize(Std.int(numScore.width * Constants.PIXEL_ART_SCALE * 0.7)); else numScore.setGraphicSize(Std.int(numScore.width * 0.45)); From 558ec535320cf87c1ad4e31f3f611758c93a74a8 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 18 Jul 2024 23:27:12 -0400 Subject: [PATCH 526/870] Switch songs with no difficulties from an error to a warning. --- 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 91d35d8fa..147923add 100644 --- a/source/funkin/play/song/Song.hx +++ b/source/funkin/play/song/Song.hx @@ -277,7 +277,7 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry Date: Thu, 18 Jul 2024 23:27:24 -0400 Subject: [PATCH 527/870] Blacklist haxe.Unserializer in scripts. --- source/funkin/modding/PolymodHandler.hx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/funkin/modding/PolymodHandler.hx b/source/funkin/modding/PolymodHandler.hx index c352aa606..c5dfcdca3 100644 --- a/source/funkin/modding/PolymodHandler.hx +++ b/source/funkin/modding/PolymodHandler.hx @@ -251,6 +251,10 @@ class PolymodHandler // Lib.load() can load malicious DLLs Polymod.blacklistImport('cpp.Lib'); + // `Unserializer` + // Unserializerr.DEFAULT_RESOLVER.resolveClass() can access blacklisted packages + Polymod.blacklistImport('Unserializer'); + // `polymod.*` // You can probably unblacklist a module for (cls in ClassMacro.listClassesInPackage('polymod')) From 754787553593fe42a2479db09db728192673603d Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 18 Jul 2024 23:27:41 -0400 Subject: [PATCH 528/870] Allow hiding HUD on launcher builds. --- source/funkin/play/PlayState.hx | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 8d7d82aab..a39f10d97 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -578,7 +578,6 @@ class PlayState extends MusicBeatSubState // TODO: Refactor or document var generatedMusic:Bool = false; - var perfectMode:Bool = false; static final BACKGROUND_COLOR:FlxColor = FlxColor.BLACK; @@ -2610,12 +2609,6 @@ class PlayState extends MusicBeatSubState */ function debugKeyShit():Void { - #if !debug - perfectMode = false; - #else - if (FlxG.keys.justPressed.H) camHUD.visible = !camHUD.visible; - #end - #if CHART_EDITOR_SUPPORTED // Open the stage editor overlaying the current state. if (controls.DEBUG_STAGE) @@ -2647,6 +2640,9 @@ class PlayState extends MusicBeatSubState #end #if (debug || FORCE_DEBUG_VERSION) + // H: Hide the HUD. + if (FlxG.keys.justPressed.H) camHUD.visible = !camHUD.visible; + // 1: End the song immediately. if (FlxG.keys.justPressed.ONE) endSong(true); From 0110936a3e2cd00e192c4200d2cf6a5589c3e41d Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 20 Jul 2024 02:19:34 -0400 Subject: [PATCH 529/870] Update assets submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index d5b2d05df..c7589a95a 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit d5b2d05df6d197f90a1b93f5b50835209c21adf7 +Subproject commit c7589a95af2709d240e1b1a2994e68a04565b00a From 1515719a0f1c6f38de0bbea8aeff24f612ad6270 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 22 Jul 2024 18:38:22 -0400 Subject: [PATCH 530/870] Implemented instrumental select (you need to beat the song as Pico first)! --- assets | 2 +- .../funkin/play/event/ZoomCameraSongEvent.hx | 2 +- source/funkin/play/song/Song.hx | 22 +++ .../toolboxes/ChartEditorEventDataToolbox.hx | 4 +- .../funkin/ui/freeplay/CapsuleOptionsMenu.hx | 176 ++++++++++++++++++ source/funkin/ui/freeplay/FreeplayState.hx | 136 ++++++++++---- source/funkin/ui/mainmenu/MainMenuState.hx | 8 +- 7 files changed, 305 insertions(+), 45 deletions(-) create mode 100644 source/funkin/ui/freeplay/CapsuleOptionsMenu.hx diff --git a/assets b/assets index c7589a95a..8af9bd2cf 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit c7589a95af2709d240e1b1a2994e68a04565b00a +Subproject commit 8af9bd2cf7122a5ad4dd2ca3939db75b11a5b239 diff --git a/source/funkin/play/event/ZoomCameraSongEvent.hx b/source/funkin/play/event/ZoomCameraSongEvent.hx index 748abda19..ee2eea8ad 100644 --- a/source/funkin/play/event/ZoomCameraSongEvent.hx +++ b/source/funkin/play/event/ZoomCameraSongEvent.hx @@ -114,7 +114,7 @@ class ZoomCameraSongEvent extends SongEvent name: 'zoom', title: 'Zoom Level', defaultValue: 1.0, - step: 0.1, + step: 0.05, type: SongEventFieldType.FLOAT, units: 'x' }, diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx index 91d35d8fa..333ab1ad4 100644 --- a/source/funkin/play/song/Song.hx +++ b/source/funkin/play/song/Song.hx @@ -514,6 +514,28 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry + { + var targetDifficulty:Null = getDifficulty(difficultyId, variationId); + if (targetDifficulty == null) return []; + + return targetDifficulty?.characters?.altInstrumentals ?? []; + } + + public function getBaseInstrumentalId(difficultyId:String, variationId:String):String + { + var targetDifficulty:Null = getDifficulty(difficultyId, variationId); + if (targetDifficulty == null) return ''; + + return targetDifficulty?.characters?.instrumental ?? ''; + } + /** * Purge the cached chart data for each difficulty of this song. */ diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorEventDataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorEventDataToolbox.hx index 8f021840a..653415363 100644 --- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorEventDataToolbox.hx +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorEventDataToolbox.hx @@ -190,8 +190,8 @@ class ChartEditorEventDataToolbox extends ChartEditorBaseToolbox var numberStepper:NumberStepper = new NumberStepper(); numberStepper.id = field.name; numberStepper.step = field.step ?? 1.0; - numberStepper.min = field.min ?? 0.0; - numberStepper.max = field.max ?? 10.0; + if (field.min != null) numberStepper.min = field.min; + if (field.max != null) numberStepper.max = field.max; if (field.defaultValue != null) numberStepper.value = field.defaultValue; input = numberStepper; case FLOAT: diff --git a/source/funkin/ui/freeplay/CapsuleOptionsMenu.hx b/source/funkin/ui/freeplay/CapsuleOptionsMenu.hx new file mode 100644 index 000000000..cb0fa7b28 --- /dev/null +++ b/source/funkin/ui/freeplay/CapsuleOptionsMenu.hx @@ -0,0 +1,176 @@ +package funkin.ui.freeplay; + +import funkin.graphics.shaders.PureColor; +import funkin.input.Controls; +import flixel.group.FlxSpriteGroup; +import funkin.graphics.FunkinSprite; +import flixel.util.FlxColor; +import flixel.util.FlxTimer; +import flixel.text.FlxText; +import flixel.text.FlxText.FlxTextAlign; + +@:nullSafety +class CapsuleOptionsMenu extends FlxSpriteGroup +{ + var capsuleMenuBG:FunkinSprite; + var parent:FreeplayState; + + var queueDestroy:Bool = false; + + var instrumentalIds:Array = ['']; + var currentInstrumentalIndex:Int = 0; + + var currentInstrumental:FlxText; + + public function new(parent:FreeplayState, x:Float = 0, y:Float = 0, instIds:Array):Void + { + super(x, y); + + this.parent = parent; + this.instrumentalIds = instIds; + + capsuleMenuBG = FunkinSprite.createSparrow(0, 0, 'freeplay/instBox/instBox'); + + capsuleMenuBG.animation.addByPrefix('open', 'open0', 24, false); + capsuleMenuBG.animation.addByPrefix('idle', 'idle0', 24, true); + capsuleMenuBG.animation.addByPrefix('open', 'open0', 24, false); + + currentInstrumental = new FlxText(0, 36, capsuleMenuBG.width, ''); + currentInstrumental.setFormat('VCR OSD Mono', 40, FlxTextAlign.CENTER, true); + + final PAD = 4; + var leftArrow = new InstrumentalSelector(parent, PAD, 30, false, parent.getControls()); + var rightArrow = new InstrumentalSelector(parent, capsuleMenuBG.width - leftArrow.width - PAD, 30, true, parent.getControls()); + + var label:FlxText = new FlxText(0, 5, capsuleMenuBG.width, 'INSTRUMENTAL'); + label.setFormat('VCR OSD Mono', 24, FlxTextAlign.CENTER, true); + + add(capsuleMenuBG); + add(leftArrow); + add(rightArrow); + add(label); + add(currentInstrumental); + + capsuleMenuBG.animation.finishCallback = function(_) { + capsuleMenuBG.animation.play('idle', true); + }; + capsuleMenuBG.animation.play('open', true); + } + + public override function update(elapsed:Float):Void + { + super.update(elapsed); + + if (queueDestroy) + { + destroy(); + return; + } + @:privateAccess + if (parent.controls.BACK) + { + close(); + return; + } + + var changedInst = false; + if (parent.getControls().UI_LEFT_P) + { + currentInstrumentalIndex = (currentInstrumentalIndex + 1) % instrumentalIds.length; + changedInst = true; + } + if (parent.getControls().UI_RIGHT_P) + { + currentInstrumentalIndex = (currentInstrumentalIndex - 1 + instrumentalIds.length) % instrumentalIds.length; + changedInst = true; + } + if (!changedInst && currentInstrumental.text == '') changedInst = true; + + if (changedInst) + { + currentInstrumental.text = instrumentalIds[currentInstrumentalIndex].toTitleCase() ?? ''; + if (currentInstrumental.text == '') currentInstrumental.text = 'Default'; + } + + if (parent.getControls().ACCEPT) + { + onConfirm(instrumentalIds[currentInstrumentalIndex] ?? ''); + } + } + + public function close():Void + { + // Play in reverse. + capsuleMenuBG.animation.play('open', true, true); + capsuleMenuBG.animation.finishCallback = function(_) { + parent.cleanupCapsuleOptionsMenu(); + queueDestroy = true; + }; + } + + /** + * Override this with `capsuleOptionsMenu.onConfirm = myFunction;` + */ + public dynamic function onConfirm(targetInstId:String):Void + { + throw 'onConfirm not implemented!'; + } +} + +/** + * The difficulty selector arrows to the left and right of the difficulty. + */ +class InstrumentalSelector extends FunkinSprite +{ + var controls:Controls; + var whiteShader:PureColor; + + var parent:FreeplayState; + + var baseScale:Float = 0.6; + + public function new(parent:FreeplayState, x:Float, y:Float, flipped:Bool, controls:Controls) + { + super(x, y); + + this.parent = parent; + + this.controls = controls; + + frames = Paths.getSparrowAtlas('freeplay/freeplaySelector'); + animation.addByPrefix('shine', 'arrow pointer loop', 24); + animation.play('shine'); + + whiteShader = new PureColor(FlxColor.WHITE); + + shader = whiteShader; + + flipX = flipped; + + scale.x = scale.y = 1 * baseScale; + updateHitbox(); + } + + override function update(elapsed:Float):Void + { + if (flipX && controls.UI_RIGHT_P) moveShitDown(); + if (!flipX && controls.UI_LEFT_P) moveShitDown(); + + super.update(elapsed); + } + + function moveShitDown():Void + { + offset.y -= 5; + + whiteShader.colorSet = true; + + scale.x = scale.y = 0.5 * baseScale; + + new FlxTimer().start(2 / 24, function(tmr) { + scale.x = scale.y = 1 * baseScale; + whiteShader.colorSet = false; + updateHitbox(); + }); + } +} diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 416e79df6..1399d48b2 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -645,8 +645,8 @@ class FreeplayState extends MusicBeatSubState speed: 0.3 }); - var diffSelLeft:DifficultySelector = new DifficultySelector(20, grpDifficulties.y - 10, false, controls); - var diffSelRight:DifficultySelector = new DifficultySelector(325, grpDifficulties.y - 10, true, controls); + var diffSelLeft:DifficultySelector = new DifficultySelector(this, 20, grpDifficulties.y - 10, false, controls); + var diffSelRight:DifficultySelector = new DifficultySelector(this, 325, grpDifficulties.y - 10, true, controls); diffSelLeft.visible = false; diffSelRight.visible = false; add(diffSelLeft); @@ -822,7 +822,7 @@ class FreeplayState extends MusicBeatSubState funnyMenu.init(FlxG.width, 0, tempSong); funnyMenu.onConfirm = function() { - capsuleOnConfirmDefault(funnyMenu); + capsuleOnOpenDefault(funnyMenu); }; funnyMenu.y = funnyMenu.intendedY(i + 1) + 10; funnyMenu.targetPos.x = funnyMenu.x; @@ -1203,7 +1203,7 @@ class FreeplayState extends MusicBeatSubState /** * If true, disable interaction with the interface. */ - var busy:Bool = false; + public var busy:Bool = false; var originalPos:FlxPoint = new FlxPoint(); @@ -1223,16 +1223,6 @@ class FreeplayState extends MusicBeatSubState }); } - if (FlxG.keys.justPressed.P) - { - FlxG.switchState(FreeplayState.build( - { - { - character: currentCharacterId == "pico" ? Constants.DEFAULT_CHARACTER : "pico", - } - })); - } - // if (FlxG.keys.justPressed.H) // { // rankDisplayNew(fromResultsParams); @@ -1496,7 +1486,7 @@ class FreeplayState extends MusicBeatSubState generateSongList(currentFilter, true); } - if (controls.BACK) + if (controls.BACK && !busy) { busy = true; FlxTween.globalManager.clear(); @@ -1749,7 +1739,86 @@ class FreeplayState extends MusicBeatSubState capsuleOnConfirmDefault(targetSong); } - function capsuleOnConfirmDefault(cap:SongMenuItem):Void + /** + * Called when hitting ENTER to open the instrumental list. + */ + function capsuleOnOpenDefault(cap:SongMenuItem):Void + { + var targetSongId:String = cap?.songData?.songId ?? 'unknown'; + var targetSongNullable:Null = SongRegistry.instance.fetchEntry(targetSongId); + if (targetSongNullable == null) + { + FlxG.log.warn('WARN: could not find song with id (${targetSongId})'); + return; + } + var targetSong:Song = targetSongNullable; + var targetDifficultyId:String = currentDifficulty; + var targetVariation:Null = targetSong.getFirstValidVariation(targetDifficultyId, currentCharacter); + var targetLevelId:Null = cap?.songData?.levelId; + PlayStatePlaylist.campaignId = targetLevelId ?? null; + + var targetDifficulty:Null = targetSong.getDifficulty(targetDifficultyId, targetVariation); + if (targetDifficulty == null) + { + FlxG.log.warn('WARN: could not find difficulty with id (${targetDifficultyId})'); + return; + } + + trace('target difficulty: ${targetDifficultyId}'); + trace('target variation: ${targetDifficulty?.variation ?? Constants.DEFAULT_VARIATION}'); + + var baseInstrumentalId:String = targetSong.getBaseInstrumentalId(targetDifficultyId, targetDifficulty?.variation ?? Constants.DEFAULT_VARIATION) ?? ''; + var altInstrumentalIds:Array = targetSong.listAltInstrumentalIds(targetDifficultyId, + targetDifficulty?.variation ?? Constants.DEFAULT_VARIATION) ?? []; + + if (altInstrumentalIds.length > 0) + { + var instrumentalIds = [baseInstrumentalId].concat(altInstrumentalIds); + openInstrumentalList(cap, instrumentalIds); + } + else + { + trace('NO ALTS'); + capsuleOnConfirmDefault(cap); + } + } + + public function getControls():Controls + { + return controls; + } + + function openInstrumentalList(cap:SongMenuItem, instrumentalIds:Array):Void + { + busy = true; + + capsuleOptionsMenu = new CapsuleOptionsMenu(this, cap.x + 175, cap.y + 115, instrumentalIds); + capsuleOptionsMenu.cameras = [funnyCam]; + capsuleOptionsMenu.zIndex = 10000; + add(capsuleOptionsMenu); + + capsuleOptionsMenu.onConfirm = function(targetInstId:String) { + capsuleOnConfirmDefault(cap, targetInstId); + }; + } + + var capsuleOptionsMenu:Null = null; + + public function cleanupCapsuleOptionsMenu():Void + { + this.busy = false; + + if (capsuleOptionsMenu != null) + { + remove(capsuleOptionsMenu); + capsuleOptionsMenu = null; + } + } + + /** + * Called when hitting ENTER to play the song. + */ + function capsuleOnConfirmDefault(cap:SongMenuItem, ?targetInstId:String):Void { busy = true; letterSort.inputEnabled = false; @@ -1776,18 +1845,11 @@ class FreeplayState extends MusicBeatSubState return; } - var baseInstrumentalId:String = targetDifficulty?.characters?.instrumental ?? ''; - var altInstrumentalIds:Array = targetDifficulty?.characters?.altInstrumentals ?? []; + var baseInstrumentalId:String = targetSong?.getBaseInstrumentalId(targetDifficultyId, targetDifficulty.variation ?? Constants.DEFAULT_VARIATION) ?? ''; + var altInstrumentalIds:Array = targetSong?.listAltInstrumentalIds(targetDifficultyId, + targetDifficulty.variation ?? Constants.DEFAULT_VARIATION) ?? []; - var targetInstId:String = baseInstrumentalId; - - // TODO: Make this a UI element. - #if (debug || FORCE_DEBUG_VERSION) - if (altInstrumentalIds.length > 0 && FlxG.keys.pressed.CONTROL) - { - targetInstId = altInstrumentalIds[0]; - } - #end + if (targetInstId == null) targetInstId = baseInstrumentalId; // Visual and audio effects. FunkinSound.playOnce(Paths.sound('confirmMenu')); @@ -1942,10 +2004,12 @@ class FreeplayState extends MusicBeatSubState if (previewSongId == null) return; var previewSong:Null = SongRegistry.instance.fetchEntry(previewSongId); - var songDifficulty = previewSong?.getDifficulty(currentDifficulty, - previewSong?.getVariationsByCharacter(currentCharacter) ?? Constants.DEFAULT_VARIATION_LIST); - var baseInstrumentalId:String = songDifficulty?.characters?.instrumental ?? ''; - var altInstrumentalIds:Array = songDifficulty?.characters?.altInstrumentals ?? []; + var currentVariation = previewSong?.getVariationsByCharacter(currentCharacter) ?? Constants.DEFAULT_VARIATION_LIST; + var songDifficulty = previewSong?.getDifficulty(currentDifficulty, currentVariation); + + var baseInstrumentalId:String = previewSong?.getBaseInstrumentalId(currentDifficulty, songDifficulty?.variation ?? Constants.DEFAULT_VARIATION) ?? ''; + var altInstrumentalIds:Array = previewSong?.listAltInstrumentalIds(currentDifficulty, + songDifficulty?.variation ?? Constants.DEFAULT_VARIATION) ?? []; var instSuffix:String = baseInstrumentalId; @@ -2008,10 +2072,14 @@ class DifficultySelector extends FlxSprite var controls:Controls; var whiteShader:PureColor; - public function new(x:Float, y:Float, flipped:Bool, controls:Controls) + var parent:FreeplayState; + + public function new(parent:FreeplayState, x:Float, y:Float, flipped:Bool, controls:Controls) { super(x, y); + this.parent = parent; + this.controls = controls; frames = Paths.getSparrowAtlas('freeplay/freeplaySelector'); @@ -2027,8 +2095,8 @@ class DifficultySelector extends FlxSprite override function update(elapsed:Float):Void { - if (flipX && controls.UI_RIGHT_P) moveShitDown(); - if (!flipX && controls.UI_LEFT_P) moveShitDown(); + if (flipX && controls.UI_RIGHT_P && !parent.busy) moveShitDown(); + if (!flipX && controls.UI_LEFT_P && !parent.busy) moveShitDown(); super.update(elapsed); } diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index 3f532d33c..1438b75c7 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -117,13 +117,7 @@ class MainMenuState extends MusicBeatState FlxTransitionableState.skipNextTransIn = true; FlxTransitionableState.skipNextTransOut = true; - openSubState(new FreeplayState( - { - #if debug - // If SHIFT is held, toggle the selected character, else use the remembered character - character: (FlxG.keys.pressed.SHIFT) ? (FreeplayState.rememberedCharacterId == Constants.DEFAULT_CHARACTER ? 'pico' : 'bf') : null, - #end - })); + openSubState(new FreeplayState()); }); #if CAN_OPEN_LINKS From a071e90746d823694c87cd573b962c12f5a91bef Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 22 Jul 2024 20:52:03 -0400 Subject: [PATCH 531/870] Added alt vocal offsets feature, disabled alt instrumentals on Pico mix (for now?) --- assets | 2 +- source/funkin/data/song/CHANGELOG.md | 4 ++++ source/funkin/data/song/SongData.hx | 28 +++++++++++++++++++------ source/funkin/data/song/SongRegistry.hx | 2 +- source/funkin/play/PlayState.hx | 8 +++---- source/funkin/play/song/Song.hx | 6 +++--- 6 files changed, 35 insertions(+), 15 deletions(-) diff --git a/assets b/assets index 8af9bd2cf..d6e024e37 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 8af9bd2cf7122a5ad4dd2ca3939db75b11a5b239 +Subproject commit d6e024e373ee78c53852a8e37de1956041856ad5 diff --git a/source/funkin/data/song/CHANGELOG.md b/source/funkin/data/song/CHANGELOG.md index 4f1c66ade..2e42fe7bd 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.4] +### Added +- Added `offsets.altVocals` field to apply vocal offsets when alternate instrumentals are used. + ## [2.2.3] ### Added - Added `charter` field to denote authorship of a chart. diff --git a/source/funkin/data/song/SongData.hx b/source/funkin/data/song/SongData.hx index 769af8f08..c7206c293 100644 --- a/source/funkin/data/song/SongData.hx +++ b/source/funkin/data/song/SongData.hx @@ -257,13 +257,21 @@ class SongOffsets implements ICloneable public var altInstrumentals:Map; /** - * The offset, in milliseconds, to apply to the song's vocals, relative to the chart. + * The offset, in milliseconds, to apply to the song's vocals, relative to the song's base instrumental. * These are applied ON TOP OF the instrumental offset. */ @:optional @:default([]) public var vocals:Map; + /** + * The offset, in milliseconds, to apply to the songs vocals, relative to each alternate instrumental. + * This is useful for the circumstance where, for example, an alt instrumental has a few seconds of lead in before the song starts. + */ + @:optional + @:default([]) + public var altVocals:Map>; + public function new(instrumental:Float = 0.0, ?altInstrumentals:Map, ?vocals:Map) { this.instrumental = instrumental; @@ -293,11 +301,19 @@ class SongOffsets implements ICloneable return value; } - public function getVocalOffset(charId:String):Float + public function getVocalOffset(charId:String, ?instrumental:String):Float { - if (!this.vocals.exists(charId)) return 0.0; - - return this.vocals.get(charId); + if (instrumental == null) + { + if (!this.vocals.exists(charId)) return 0.0; + return this.vocals.get(charId); + } + else + { + if (!this.altVocals.exists(instrumental)) return 0.0; + if (!this.altVocals.get(instrumental).exists(charId)) return 0.0; + return this.altVocals.get(instrumental).get(charId); + } } public function setVocalOffset(charId:String, value:Float):Float @@ -320,7 +336,7 @@ class SongOffsets implements ICloneable */ public function toString():String { - return 'SongOffsets(${this.instrumental}ms, ${this.altInstrumentals}, ${this.vocals})'; + return 'SongOffsets(${this.instrumental}ms, ${this.altInstrumentals}, ${this.vocals}, ${this.altVocals})'; } } diff --git a/source/funkin/data/song/SongRegistry.hx b/source/funkin/data/song/SongRegistry.hx index a3305c4ec..e7cab246c 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.3"; + public static final SONG_METADATA_VERSION:thx.semver.Version = "2.2.4"; public static final SONG_METADATA_VERSION_RULE:thx.semver.VersionRule = "2.2.x"; diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 8d7d82aab..80c0e16cc 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -666,7 +666,7 @@ class PlayState extends MusicBeatSubState // Prepare the current song's instrumental and vocals to be played. if (!overrideMusic && currentChart != null) { - currentChart.cacheInst(); + currentChart.cacheInst(currentInstrumental); currentChart.cacheVocals(); } @@ -675,7 +675,7 @@ class PlayState extends MusicBeatSubState if (currentChart.offsets != null) { - Conductor.instance.instrumentalOffset = currentChart.offsets.getInstrumentalOffset(); + Conductor.instance.instrumentalOffset = currentChart.offsets.getInstrumentalOffset(currentInstrumental); } Conductor.instance.mapTimeChanges(currentChart.timeChanges); @@ -863,7 +863,7 @@ class PlayState extends MusicBeatSubState { // Stop the vocals if they already exist. if (vocals != null) vocals.stop(); - vocals = currentChart.buildVocals(); + vocals = currentChart.buildVocals(currentInstrumental); if (vocals.members.length == 0) { @@ -1852,7 +1852,7 @@ class PlayState extends MusicBeatSubState { // Stop the vocals if they already exist. if (vocals != null) vocals.stop(); - vocals = currentChart.buildVocals(); + vocals = currentChart.buildVocals(currentInstrumental); if (vocals.members.length == 0) { diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx index 333ab1ad4..156cfda05 100644 --- a/source/funkin/play/song/Song.hx +++ b/source/funkin/play/song/Song.hx @@ -813,7 +813,7 @@ class SongDifficulty * @param charId The player ID. * @return The generated vocal group. */ - public function buildVocals():VoicesGroup + public function buildVocals(?instId:String = ''):VoicesGroup { var result:VoicesGroup = new VoicesGroup(); @@ -839,8 +839,8 @@ class SongDifficulty } } - result.playerVoicesOffset = offsets.getVocalOffset(characters.player); - result.opponentVoicesOffset = offsets.getVocalOffset(characters.opponent); + result.playerVoicesOffset = offsets.getVocalOffset(characters.player, instId); + result.opponentVoicesOffset = offsets.getVocalOffset(characters.opponent, instId); return result; } From 04c88baff0ffa05ca23b6344ab090eff0c1ff388 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 22 Jul 2024 20:53:34 -0400 Subject: [PATCH 532/870] CI fix? --- .github/labeler.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index e8e490865..e8250b4e7 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,7 +1,6 @@ # 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' From 9b8961d4b5c8e150a2c77d39d53566bed5fe6ea7 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 22 Jul 2024 22:20:51 -0400 Subject: [PATCH 533/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 4af95a506..aa1231e8c 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 4af95a506fc62cd683422dfb9c599877b26c27db +Subproject commit aa1231e8cf2990bb902eac3b37815c010fa9919a From c8caeb42ded0be5292680db20c5cb99b2a37bf46 Mon Sep 17 00:00:00 2001 From: AppleHair <95587502+AppleHair@users.noreply.github.com> Date: Tue, 23 Jul 2024 11:34:26 +0300 Subject: [PATCH 534/870] A fix requested by Eric --- source/funkin/play/PlayState.hx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 9b1cc2ed9..20b8d784b 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -2959,11 +2959,16 @@ class PlayState extends MusicBeatSubState FunkinSound.playOnce(Paths.sound('Lights_Shut_off'), function() { // no camFollow so it centers on horror tree var targetSong:Song = SongRegistry.instance.fetchEntry(targetSongId); + var targetVariation:String = currentVariation; + if (!targetSong.hasDifficulty(PlayStatePlaylist.campaignDifficulty, currentVariation)) + { + targetVariation = targetSong.getFirstValidVariation(PlayStatePlaylist.campaignDifficulty) ?? Constants.DEFAULT_VARIATION; + } LoadingState.loadPlayState( { targetSong: targetSong, targetDifficulty: PlayStatePlaylist.campaignDifficulty, - targetVariation: targetSong.getFirstValidVariation(PlayStatePlaylist.campaignDifficulty), + targetVariation: targetVariation, cameraFollowPoint: cameraFollowPoint.getPosition(), }); }); @@ -2971,11 +2976,16 @@ class PlayState extends MusicBeatSubState else { var targetSong:Song = SongRegistry.instance.fetchEntry(targetSongId); + var targetVariation:String = currentVariation; + if (!targetSong.hasDifficulty(PlayStatePlaylist.campaignDifficulty, currentVariation)) + { + targetVariation = targetSong.getFirstValidVariation(PlayStatePlaylist.campaignDifficulty) ?? Constants.DEFAULT_VARIATION; + } LoadingState.loadPlayState( { targetSong: targetSong, targetDifficulty: PlayStatePlaylist.campaignDifficulty, - targetVariation: targetSong.getFirstValidVariation(PlayStatePlaylist.campaignDifficulty), + targetVariation: targetVariation, cameraFollowPoint: cameraFollowPoint.getPosition(), }); } From 8778ab1d0ec46556338e60fe0eb84c6d26064d7f Mon Sep 17 00:00:00 2001 From: Burgerballs <107233412+Burgerballs@users.noreply.github.com> Date: Tue, 23 Jul 2024 18:09:39 +0100 Subject: [PATCH 535/870] Update PlayState.hx --- 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 f55cef388..f82fd791e 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -2033,7 +2033,7 @@ class PlayState extends MusicBeatSubState vocals.pause(); - FlxG.sound.music.play(FlxG.sound.music.time); + FlxG.sound.music.play(Conductor.instance.songPosition + Conductor.instance.instrumentalOffset); vocals.time = FlxG.sound.music.time; vocals.play(false, FlxG.sound.music.time); From 964f6878c3fb8d13f4faf6723d299997edceaccf Mon Sep 17 00:00:00 2001 From: Burgerballs <107233412+Burgerballs@users.noreply.github.com> Date: Tue, 23 Jul 2024 19:02:09 +0100 Subject: [PATCH 536/870] Update PlayState.hx --- source/funkin/play/PlayState.hx | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index f82fd791e..07e4f0b1d 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1404,17 +1404,6 @@ class PlayState extends MusicBeatSubState if (isGamePaused) return false; - if (!startingSong - && FlxG.sound.music != null - && (Math.abs(FlxG.sound.music.time - (Conductor.instance.songPosition + Conductor.instance.instrumentalOffset)) > 200 - || Math.abs(vocals.checkSyncError(Conductor.instance.songPosition + Conductor.instance.instrumentalOffset)) > 200)) - { - trace("VOCALS NEED RESYNC"); - if (vocals != null) trace(vocals.checkSyncError(Conductor.instance.songPosition + Conductor.instance.instrumentalOffset)); - trace(FlxG.sound.music.time - (Conductor.instance.songPosition + Conductor.instance.instrumentalOffset)); - resyncVocals(); - } - if (iconP1 != null) iconP1.onStepHit(Std.int(Conductor.instance.currentStep)); if (iconP2 != null) iconP2.onStepHit(Std.int(Conductor.instance.currentStep)); @@ -1436,6 +1425,17 @@ class PlayState extends MusicBeatSubState // activeNotes.sort(SortUtil.byStrumtime, FlxSort.DESCENDING); } + if (!startingSong + && FlxG.sound.music != null + && (Math.abs(FlxG.sound.music.time - (Conductor.instance.songPosition + Conductor.instance.instrumentalOffset)) > 100 + || Math.abs(vocals.checkSyncError(Conductor.instance.songPosition + Conductor.instance.instrumentalOffset)) > 100)) + { + trace("VOCALS NEED RESYNC"); + if (vocals != null) trace(vocals.checkSyncError(Conductor.instance.songPosition + Conductor.instance.instrumentalOffset)); + trace(FlxG.sound.music.time - (Conductor.instance.songPosition + Conductor.instance.instrumentalOffset)); + resyncVocals(); + } + // Only bop camera if zoom level is below 135% if (Preferences.zoomCamera && FlxG.camera.zoom < (1.35 * FlxCamera.defaultZoom) @@ -2030,13 +2030,15 @@ class PlayState extends MusicBeatSubState // Skip this if the music is paused (GameOver, Pause menu, start-of-song offset, etc.) if (!FlxG.sound.music.playing) return; - + var timeToPlayAt:Float = Conductor.instance.songPosition - Conductor.instance.instrumentalOffset; + FlxG.sound.music.pause(); vocals.pause(); - FlxG.sound.music.play(Conductor.instance.songPosition + Conductor.instance.instrumentalOffset); + FlxG.sound.music.time = timeToPlayAt; + FlxG.sound.music.play(false, timeToPlayAt); - vocals.time = FlxG.sound.music.time; - vocals.play(false, FlxG.sound.music.time); + vocals.time = timeToPlayAt; + vocals.play(false, timeToPlayAt); } /** From 6e301bf648e6df451289a4b1a6ef8453766e7a41 Mon Sep 17 00:00:00 2001 From: Burgerballs <107233412+Burgerballs@users.noreply.github.com> Date: Tue, 23 Jul 2024 18:09:39 +0100 Subject: [PATCH 537/870] Update PlayState.hx --- 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 8d7d82aab..873082091 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -2043,7 +2043,7 @@ class PlayState extends MusicBeatSubState vocals.pause(); - FlxG.sound.music.play(FlxG.sound.music.time); + FlxG.sound.music.play(Conductor.instance.songPosition + Conductor.instance.instrumentalOffset); vocals.time = FlxG.sound.music.time; vocals.play(false, FlxG.sound.music.time); From 1831daac382894aa121180dc8e704d35ce55755c Mon Sep 17 00:00:00 2001 From: Burgerballs <107233412+Burgerballs@users.noreply.github.com> Date: Tue, 23 Jul 2024 19:02:09 +0100 Subject: [PATCH 538/870] Update PlayState.hx --- source/funkin/play/PlayState.hx | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 873082091..18ec0f002 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1417,17 +1417,6 @@ class PlayState extends MusicBeatSubState if (isGamePaused) return false; - if (!startingSong - && FlxG.sound.music != null - && (Math.abs(FlxG.sound.music.time - (Conductor.instance.songPosition + Conductor.instance.instrumentalOffset)) > 200 - || Math.abs(vocals.checkSyncError(Conductor.instance.songPosition + Conductor.instance.instrumentalOffset)) > 200)) - { - trace("VOCALS NEED RESYNC"); - if (vocals != null) trace(vocals.checkSyncError(Conductor.instance.songPosition + Conductor.instance.instrumentalOffset)); - trace(FlxG.sound.music.time - (Conductor.instance.songPosition + Conductor.instance.instrumentalOffset)); - resyncVocals(); - } - if (iconP1 != null) iconP1.onStepHit(Std.int(Conductor.instance.currentStep)); if (iconP2 != null) iconP2.onStepHit(Std.int(Conductor.instance.currentStep)); @@ -1449,6 +1438,17 @@ class PlayState extends MusicBeatSubState // activeNotes.sort(SortUtil.byStrumtime, FlxSort.DESCENDING); } + if (!startingSong + && FlxG.sound.music != null + && (Math.abs(FlxG.sound.music.time - (Conductor.instance.songPosition + Conductor.instance.instrumentalOffset)) > 100 + || Math.abs(vocals.checkSyncError(Conductor.instance.songPosition + Conductor.instance.instrumentalOffset)) > 100)) + { + trace("VOCALS NEED RESYNC"); + if (vocals != null) trace(vocals.checkSyncError(Conductor.instance.songPosition + Conductor.instance.instrumentalOffset)); + trace(FlxG.sound.music.time - (Conductor.instance.songPosition + Conductor.instance.instrumentalOffset)); + resyncVocals(); + } + // Only bop camera if zoom level is below 135% if (Preferences.zoomCamera && FlxG.camera.zoom < (1.35 * FlxCamera.defaultZoom) @@ -2040,13 +2040,15 @@ class PlayState extends MusicBeatSubState // Skip this if the music is paused (GameOver, Pause menu, start-of-song offset, etc.) if (!FlxG.sound.music.playing) return; - + var timeToPlayAt:Float = Conductor.instance.songPosition - Conductor.instance.instrumentalOffset; + FlxG.sound.music.pause(); vocals.pause(); - FlxG.sound.music.play(Conductor.instance.songPosition + Conductor.instance.instrumentalOffset); + FlxG.sound.music.time = timeToPlayAt; + FlxG.sound.music.play(false, timeToPlayAt); - vocals.time = FlxG.sound.music.time; - vocals.play(false, FlxG.sound.music.time); + vocals.time = timeToPlayAt; + vocals.play(false, timeToPlayAt); } /** From aaab24850df5b3882b2282d5b3c8f6d8174853be Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 24 Jun 2024 22:21:53 -0400 Subject: [PATCH 539/870] flixel haxelib updates --- hmm.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hmm.json b/hmm.json index 8eaf24212..07216a351 100644 --- a/hmm.json +++ b/hmm.json @@ -11,14 +11,14 @@ "name": "flixel", "type": "git", "dir": null, - "ref": "a7d8e3bad89a0a3506a4714121f73d8e34522c49", + "ref": "10c2a203c43a78ff1ff26b8368fd736576829d8d", "url": "https://github.com/FunkinCrew/flixel" }, { "name": "flixel-addons", "type": "git", "dir": null, - "ref": "a523c3b56622f0640933944171efed46929e360e", + "ref": "9c6fb47968e894eb36bf10e94725cd7640c49281", "url": "https://github.com/FunkinCrew/flixel-addons" }, { @@ -30,7 +30,7 @@ "name": "flixel-ui", "type": "git", "dir": null, - "ref": "719b4f10d94186ed55f6fef1b6618d32abec8c15", + "ref": "d0afed7293c71ffdb1184751317fc709b44c9056", "url": "https://github.com/HaxeFlixel/flixel-ui" }, { From a15695c3dc8b3c38d8049cb39db4bbf27f2f1d9a Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 19 Jul 2024 19:13:58 -0400 Subject: [PATCH 540/870] compile dev version of hxcpp --- .github/workflows/build-game.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-game.yml b/.github/workflows/build-game.yml index 07802557c..ba8167607 100644 --- a/.github/workflows/build-game.yml +++ b/.github/workflows/build-game.yml @@ -45,7 +45,11 @@ jobs: uses: ./.github/actions/setup-haxe with: gh-token: ${{ steps.app_token.outputs.token }} - + - name: Setup HXCPP dev commit + run: | + cd .haxelib/hxcpp/git/tools/hxcpp + haxe compile.hxml + cd ../../../../.. - name: Build game if: ${{ matrix.target == 'windows' }} run: | From 4dfb46955239664439fbb3c64d8bd40a41b1169c Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 22 Jul 2024 10:12:41 -0400 Subject: [PATCH 541/870] update hxcpp haxelib --- hmm.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hmm.json b/hmm.json index 8eaf24212..387d63f5e 100644 --- a/hmm.json +++ b/hmm.json @@ -99,8 +99,10 @@ }, { "name": "hxcpp", - "type": "haxelib", - "version": "4.3.2" + "type": "git", + "dir": null, + "url": "https://github.com/HaxeFoundation/hxcpp", + "ref": "01cfee282a9a783e10c5a7774a3baaf547e6b0a7" }, { "name": "hxcpp-debug-server", From 3db0cf3e0ab4817f211cd3d8a74c616b15be1239 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 26 Jul 2024 00:22:36 -0400 Subject: [PATCH 542/870] Update Polymod to support applying JSON patches in the _merge folder of mods. --- hmm.json | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index 375fdd0ac..fabd8b51d 100644 --- a/hmm.json +++ b/hmm.json @@ -123,6 +123,20 @@ "ref": "a8c26f18463c98da32f744c214fe02273e1823fa", "url": "https://github.com/FunkinCrew/json2object" }, + { + "name": "jsonpatch", + "type": "git", + "dir": null, + "ref": "f9b83215acd586dc28754b4ae7f69d4c06c3b4d3", + "url": "https://github.com/EliteMasterEric/jsonpatch" + }, + { + "name": "jsonpath", + "type": "git", + "dir": null, + "ref": "7a24193717b36393458c15c0435bb7c4470ecdda", + "url": "https://github.com/EliteMasterEric/jsonpath" + }, { "name": "lime", "type": "git", @@ -169,7 +183,7 @@ "name": "polymod", "type": "git", "dir": null, - "ref": "bfbe30d81601b3543d80dce580108ad6b7e182c7", + "ref": "98945c6c7f5ecde01a32c4623d3515bf012a023a", "url": "https://github.com/larsiusprime/polymod" }, { From f3624f7e76cdd8dcba0762a39ebe1be28389ecef Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sun, 28 Jul 2024 01:42:09 -0400 Subject: [PATCH 543/870] Fixes for scripted song events, define vocal tracks per variation, display suffixed difficulties properly. --- source/funkin/data/event/SongEventRegistry.hx | 4 +- source/funkin/data/song/CHANGELOG.md | 7 + source/funkin/data/song/SongData.hx | 59 ++++--- source/funkin/modding/PolymodHandler.hx | 2 + source/funkin/play/PlayState.hx | 8 +- source/funkin/play/song/Song.hx | 166 ++++++++++++------ source/funkin/ui/freeplay/FreeplayState.hx | 30 +++- source/funkin/ui/freeplay/SongMenuItem.hx | 3 +- 8 files changed, 187 insertions(+), 92 deletions(-) diff --git a/source/funkin/data/event/SongEventRegistry.hx b/source/funkin/data/event/SongEventRegistry.hx index 9b0163557..5ee2d39fa 100644 --- a/source/funkin/data/event/SongEventRegistry.hx +++ b/source/funkin/data/event/SongEventRegistry.hx @@ -46,7 +46,7 @@ class SongEventRegistry if (event != null) { - trace(' Loaded built-in song event: (${event.id})'); + trace(' Loaded built-in song event: ${event.id}'); eventCache.set(event.id, event); } else @@ -59,9 +59,9 @@ class SongEventRegistry static function registerScriptedEvents() { var scriptedEventClassNames:Array = ScriptedSongEvent.listScriptClasses(); + trace('Instantiating ${scriptedEventClassNames.length} scripted song events...'); if (scriptedEventClassNames == null || scriptedEventClassNames.length == 0) return; - trace('Instantiating ${scriptedEventClassNames.length} scripted song events...'); for (eventCls in scriptedEventClassNames) { var event:SongEvent = ScriptedSongEvent.init(eventCls, "UKNOWN"); diff --git a/source/funkin/data/song/CHANGELOG.md b/source/funkin/data/song/CHANGELOG.md index 4f1c66ade..ca36a1d6d 100644 --- a/source/funkin/data/song/CHANGELOG.md +++ b/source/funkin/data/song/CHANGELOG.md @@ -5,6 +5,13 @@ 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.4] +### Added +- Added `playData.characters.opponentVocals` to specify which vocal track(s) to play for the opponent. + - If the value isn't present, it will use the `playData.characters.opponent`, but if it is present, it will be used (even if it's empty, in which case no vocals will be used for the opponent) +- Added `playData.characters.playerVocals` to specify which vocal track(s) to play for the player. + - If the value isn't present, it will use the `playData.characters.player`, but if it is present, it will be used (even if it's empty, in which case no vocals will be used for the player) + ## [2.2.3] ### Added - Added `charter` field to denote authorship of a chart. diff --git a/source/funkin/data/song/SongData.hx b/source/funkin/data/song/SongData.hx index 7bf3f8f19..f487eb54d 100644 --- a/source/funkin/data/song/SongData.hx +++ b/source/funkin/data/song/SongData.hx @@ -529,12 +529,26 @@ class SongCharacterData implements ICloneable @:default([]) public var altInstrumentals:Array = []; - public function new(player:String = '', girlfriend:String = '', opponent:String = '', instrumental:String = '') + @:optional + public var opponentVocals:Null> = null; + + @:optional + public var playerVocals:Null> = null; + + public function new(player:String = '', girlfriend:String = '', opponent:String = '', instrumental:String = '', ?altInstrumentals:Array, + ?opponentVocals:Array, ?playerVocals:Array) { this.player = player; this.girlfriend = girlfriend; this.opponent = opponent; this.instrumental = instrumental; + + this.altInstrumentals = altInstrumentals; + this.opponentVocals = opponentVocals; + this.playerVocals = playerVocals; + + if (opponentVocals == null) this.opponentVocals = [opponent]; + if (playerVocals == null) this.playerVocals = [player]; } public function clone():SongCharacterData @@ -722,18 +736,6 @@ class SongEventDataRaw implements ICloneable { return new SongEventDataRaw(this.time, this.eventKind, this.value); } -} - -/** - * Wrap SongEventData in an abstract so we can overload operators. - */ -@:forward(time, eventKind, value, activated, getStepTime, clone) -abstract SongEventData(SongEventDataRaw) from SongEventDataRaw to SongEventDataRaw -{ - public function new(time:Float, eventKind:String, value:Dynamic = null) - { - this = new SongEventDataRaw(time, eventKind, value); - } public function valueAsStruct(?defaultKey:String = "key"):Dynamic { @@ -757,27 +759,27 @@ abstract SongEventData(SongEventDataRaw) from SongEventDataRaw to SongEventDataR } } - public inline function getHandler():Null + public function getHandler():Null { return SongEventRegistry.getEvent(this.eventKind); } - public inline function getSchema():Null + public function getSchema():Null { return SongEventRegistry.getEventSchema(this.eventKind); } - public inline function getDynamic(key:String):Null + public function getDynamic(key:String):Null { return this.value == null ? null : Reflect.field(this.value, key); } - public inline function getBool(key:String):Null + public function getBool(key:String):Null { return this.value == null ? null : cast Reflect.field(this.value, key); } - public inline function getInt(key:String):Null + public function getInt(key:String):Null { if (this.value == null) return null; var result = Reflect.field(this.value, key); @@ -787,7 +789,7 @@ abstract SongEventData(SongEventDataRaw) from SongEventDataRaw to SongEventDataR return cast result; } - public inline function getFloat(key:String):Null + public function getFloat(key:String):Null { if (this.value == null) return null; var result = Reflect.field(this.value, key); @@ -797,17 +799,17 @@ abstract SongEventData(SongEventDataRaw) from SongEventDataRaw to SongEventDataR return cast result; } - public inline function getString(key:String):String + public function getString(key:String):String { return this.value == null ? null : cast Reflect.field(this.value, key); } - public inline function getArray(key:String):Array + public function getArray(key:String):Array { return this.value == null ? null : cast Reflect.field(this.value, key); } - public inline function getBoolArray(key:String):Array + public function getBoolArray(key:String):Array { return this.value == null ? null : cast Reflect.field(this.value, key); } @@ -839,6 +841,19 @@ abstract SongEventData(SongEventDataRaw) from SongEventDataRaw to SongEventDataR return result; } +} + +/** + * Wrap SongEventData in an abstract so we can overload operators. + */ +@:forward(time, eventKind, value, activated, getStepTime, clone, getHandler, getSchema, getDynamic, getBool, getInt, getFloat, getString, getArray, + getBoolArray, buildTooltip, valueAsStruct) +abstract SongEventData(SongEventDataRaw) from SongEventDataRaw to SongEventDataRaw +{ + public function new(time:Float, eventKind:String, value:Dynamic = null) + { + this = new SongEventDataRaw(time, eventKind, value); + } public function clone():SongEventData { diff --git a/source/funkin/modding/PolymodHandler.hx b/source/funkin/modding/PolymodHandler.hx index 9a9ef9e66..5767199ba 100644 --- a/source/funkin/modding/PolymodHandler.hx +++ b/source/funkin/modding/PolymodHandler.hx @@ -234,6 +234,8 @@ class PolymodHandler // NOTE: Scripted classes are automatically aliased to their parent class. Polymod.addImportAlias('flixel.math.FlxPoint', flixel.math.FlxPoint.FlxBasePoint); + Polymod.addImportAlias('funkin.data.event.SongEventSchema', funkin.data.event.SongEventSchema.SongEventSchemaRaw); + // Add blacklisting for prohibited classes and packages. // `Sys` diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 32b6e7b62..871c784df 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -580,6 +580,8 @@ class PlayState extends MusicBeatSubState // TODO: Refactor or document var generatedMusic:Bool = false; + var skipEndingTransition:Bool = false; + static final BACKGROUND_COLOR:FlxColor = FlxColor.BLACK; /** @@ -1926,7 +1928,9 @@ class PlayState extends MusicBeatSubState return; } - FlxG.sound.music.onComplete = endSong.bind(false); + FlxG.sound.music.onComplete = function() { + endSong(skipEndingTransition); + }; // A negative instrumental offset means the song skips the first few milliseconds of the track. // This just gets added into the startTimestamp behavior so we don't need to do anything extra. FlxG.sound.music.play(true, startTimestamp - Conductor.instance.instrumentalOffset); @@ -1965,7 +1969,7 @@ class PlayState extends MusicBeatSubState if (vocals == null) return; // Skip this if the music is paused (GameOver, Pause menu, start-of-song offset, etc.) - if (!FlxG.sound.music.playing) return; + if (!(FlxG?.sound?.music?.playing ?? false)) return; vocals.pause(); diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx index 147923add..2e7e13f51 100644 --- a/source/funkin/play/song/Song.hx +++ b/source/funkin/play/song/Song.hx @@ -494,6 +494,24 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry, ?showLocked:Bool, ?showHidden:Bool):Array + { + var result = []; + + for (variation in variationIds) + { + var difficulties = listDifficulties(variation, null, showLocked, showHidden); + for (difficulty in difficulties) + { + var suffixedDifficulty = (variation != Constants.DEFAULT_VARIATION + && variation != 'erect') ? '$difficulty-${variation}' : difficulty; + result.push(suffixedDifficulty); + } + } + + return result; + } + public function hasDifficulty(diffId:String, ?variationId:String, ?variationIds:Array):Bool { if (variationIds == null) variationIds = []; @@ -706,10 +724,11 @@ class SongDifficulty * Cache the vocals for a given character. * @param id The character we are about to play. */ - public inline function cacheVocals():Void + public function cacheVocals():Void { for (voice in buildVoiceList()) { + trace('Caching vocal track: $voice'); FlxG.sound.cache(voice); } } @@ -721,6 +740,20 @@ class SongDifficulty * @param id The character we are about to play. */ public function buildVoiceList():Array + { + var result:Array = []; + result = result.concat(buildPlayerVoiceList()); + result = result.concat(buildOpponentVoiceList()); + if (result.length == 0) + { + var suffix:String = (variation != null && variation != '' && variation != 'default') ? '-$variation' : ''; + // Try to use `Voices.ogg` if no other voices are found. + if (Assets.exists(Paths.voices(this.song.id, ''))) result.push(Paths.voices(this.song.id, '$suffix')); + } + return result; + } + + public function buildPlayerVoiceList():Array { var suffix:String = (variation != null && variation != '' && variation != 'default') ? '-$variation' : ''; @@ -728,62 +761,88 @@ class SongDifficulty // For example, if `Voices-bf-car-erect.ogg` does not exist, check for `Voices-bf-erect.ogg`. // Then, check for `Voices-bf-car.ogg`, then `Voices-bf.ogg`. - var playerId:String = characters.player; - var voicePlayer:String = Paths.voices(this.song.id, '-$playerId$suffix'); - while (voicePlayer != null && !Assets.exists(voicePlayer)) + if (characters.playerVocals == null) { - // Remove the last suffix. - // For example, bf-car becomes bf. - playerId = playerId.split('-').slice(0, -1).join('-'); - // Try again. - voicePlayer = playerId == '' ? null : Paths.voices(this.song.id, '-${playerId}$suffix'); - } - if (voicePlayer == null) - { - // Try again without $suffix. - playerId = characters.player; - voicePlayer = Paths.voices(this.song.id, '-${playerId}'); - while (voicePlayer != null && !Assets.exists(voicePlayer)) + var playerId:String = characters.player; + var playerVoice:String = Paths.voices(this.song.id, '-${playerId}$suffix'); + + while (playerVoice != null && !Assets.exists(playerVoice)) { // Remove the last suffix. + // For example, bf-car becomes bf. playerId = playerId.split('-').slice(0, -1).join('-'); // Try again. - voicePlayer = playerId == '' ? null : Paths.voices(this.song.id, '-${playerId}$suffix'); + playerVoice = playerId == '' ? null : Paths.voices(this.song.id, '-${playerId}$suffix'); + } + if (playerVoice == null) + { + // Try again without $suffix. + playerId = characters.player; + playerVoice = Paths.voices(this.song.id, '-${playerId}'); + while (playerVoice != null && !Assets.exists(playerVoice)) + { + // Remove the last suffix. + playerId = playerId.split('-').slice(0, -1).join('-'); + // Try again. + playerVoice = playerId == '' ? null : Paths.voices(this.song.id, '-${playerId}$suffix'); + } } - } - var opponentId:String = characters.opponent; - var voiceOpponent:String = Paths.voices(this.song.id, '-${opponentId}$suffix'); - while (voiceOpponent != null && !Assets.exists(voiceOpponent)) - { - // Remove the last suffix. - opponentId = opponentId.split('-').slice(0, -1).join('-'); - // Try again. - voiceOpponent = opponentId == '' ? null : Paths.voices(this.song.id, '-${opponentId}$suffix'); + return playerVoice != null ? [playerVoice] : []; } - if (voiceOpponent == null) + else { - // Try again without $suffix. - opponentId = characters.opponent; - voiceOpponent = Paths.voices(this.song.id, '-${opponentId}'); - while (voiceOpponent != null && !Assets.exists(voiceOpponent)) + // The metadata explicitly defines the list of voices. + var playerIds:Array = characters?.playerVocals ?? [characters.player]; + var playerVoices:Array = playerIds.map((id) -> Paths.voices(this.song.id, '-$id$suffix')); + + return playerVoices; + } + } + + public function buildOpponentVoiceList():Array + { + var suffix:String = (variation != null && variation != '' && variation != 'default') ? '-$variation' : ''; + + // Automatically resolve voices by removing suffixes. + // For example, if `Voices-bf-car-erect.ogg` does not exist, check for `Voices-bf-erect.ogg`. + // Then, check for `Voices-bf-car.ogg`, then `Voices-bf.ogg`. + + if (characters.opponentVocals == null) + { + var opponentId:String = characters.opponent; + var opponentVoice:String = Paths.voices(this.song.id, '-${opponentId}$suffix'); + while (opponentVoice != null && !Assets.exists(opponentVoice)) { // Remove the last suffix. opponentId = opponentId.split('-').slice(0, -1).join('-'); // Try again. - voiceOpponent = opponentId == '' ? null : Paths.voices(this.song.id, '-${opponentId}$suffix'); + opponentVoice = opponentId == '' ? null : Paths.voices(this.song.id, '-${opponentId}$suffix'); + } + if (opponentVoice == null) + { + // Try again without $suffix. + opponentId = characters.opponent; + opponentVoice = Paths.voices(this.song.id, '-${opponentId}'); + while (opponentVoice != null && !Assets.exists(opponentVoice)) + { + // Remove the last suffix. + opponentId = opponentId.split('-').slice(0, -1).join('-'); + // Try again. + opponentVoice = opponentId == '' ? null : Paths.voices(this.song.id, '-${opponentId}$suffix'); + } } - } - var result:Array = []; - if (voicePlayer != null) result.push(voicePlayer); - if (voiceOpponent != null) result.push(voiceOpponent); - if (voicePlayer == null && voiceOpponent == null) + return opponentVoice != null ? [opponentVoice] : []; + } + else { - // Try to use `Voices.ogg` if no other voices are found. - if (Assets.exists(Paths.voices(this.song.id, ''))) result.push(Paths.voices(this.song.id, '$suffix')); + // The metadata explicitly defines the list of voices. + var opponentIds:Array = characters?.opponentVocals ?? [characters.opponent]; + var opponentVoices:Array = opponentIds.map((id) -> Paths.voices(this.song.id, '-$id$suffix')); + + return opponentVoices; } - return result; } /** @@ -795,26 +854,19 @@ class SongDifficulty { var result:VoicesGroup = new VoicesGroup(); - var voiceList:Array = buildVoiceList(); - - if (voiceList.length == 0) - { - trace('Could not find any voices for song ${this.song.id}'); - return result; - } + var playerVoiceList:Array = this.buildPlayerVoiceList(); + var opponentVoiceList:Array = this.buildOpponentVoiceList(); // Add player vocals. - if (voiceList[0] != null) result.addPlayerVoice(FunkinSound.load(voiceList[0])); - // Add opponent vocals. - if (voiceList[1] != null) result.addOpponentVoice(FunkinSound.load(voiceList[1])); - - // Add additional vocals. - if (voiceList.length > 2) + for (playerVoice in playerVoiceList) { - for (i in 2...voiceList.length) - { - result.add(FunkinSound.load(Assets.getSound(voiceList[i]))); - } + result.addPlayerVoice(FunkinSound.load(playerVoice)); + } + + // Add opponent vocals. + for (opponentVoice in opponentVoiceList) + { + result.addOpponentVoice(FunkinSound.load(opponentVoice)); } result.playerVoicesOffset = offsets.getVocalOffset(characters.player); diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index dc42bd651..2341f04a6 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -339,7 +339,7 @@ class FreeplayState extends MusicBeatSubState // Only display songs which actually have available difficulties for the current character. var displayedVariations = song.getVariationsByCharacter(currentCharacter); trace('Displayed Variations (${songId}): $displayedVariations'); - var availableDifficultiesForSong:Array = song.listDifficulties(displayedVariations, false); + var availableDifficultiesForSong:Array = song.listSuffixedDifficulties(displayedVariations, false, false); trace('Available Difficulties: $availableDifficultiesForSong'); if (availableDifficultiesForSong.length == 0) continue; @@ -1120,7 +1120,7 @@ class FreeplayState extends MusicBeatSubState // NOW we can interact with the menu busy = false; - grpCapsules.members[curSelected].sparkle.alpha = 0.7; + capsule.sparkle.alpha = 0.7; playCurSongPreview(capsule); }, null); @@ -1674,6 +1674,9 @@ class FreeplayState extends MusicBeatSubState songCapsule.init(null, null, null); } } + + // Reset the song preview in case we changed variations (normal->erect etc) + playCurSongPreview(); } // Set the album graphic and play the animation if relevant. @@ -1912,8 +1915,10 @@ class FreeplayState extends MusicBeatSubState } } - public function playCurSongPreview(daSongCapsule:SongMenuItem):Void + public function playCurSongPreview(?daSongCapsule:SongMenuItem):Void { + if (daSongCapsule == null) daSongCapsule = grpCapsules.members[curSelected]; + if (curSelected == 0) { FunkinSound.playMusic('freeplayRandom', @@ -2145,7 +2150,7 @@ class FreeplaySongData function updateValues(variations:Array):Void { - this.songDifficulties = song.listDifficulties(null, variations, false, false); + this.songDifficulties = song.listSuffixedDifficulties(variations, false, false); if (!this.songDifficulties.contains(currentDifficulty)) currentDifficulty = Constants.DEFAULT_DIFFICULTY; var songDifficulty:SongDifficulty = song.getDifficulty(currentDifficulty, null, variations); @@ -2207,15 +2212,26 @@ class DifficultySprite extends FlxSprite difficultyId = diffId; - if (Assets.exists(Paths.file('images/freeplay/freeplay${diffId}.xml'))) + var assetDiffId:String = diffId; + while (!Assets.exists(Paths.image('freeplay/freeplay${assetDiffId}'))) { - this.frames = Paths.getSparrowAtlas('freeplay/freeplay${diffId}'); + // Remove the last suffix of the difficulty id until we find an asset or there are no more suffixes. + var assetDiffIdParts:Array = assetDiffId.split('-'); + assetDiffIdParts.pop(); + if (assetDiffIdParts.length == 0) break; + assetDiffId = assetDiffIdParts.join('-'); + } + + // Check for an XML to use an animation instead of an image. + if (Assets.exists(Paths.file('images/freeplay/freeplay${assetDiffId}.xml'))) + { + this.frames = Paths.getSparrowAtlas('freeplay/freeplay${assetDiffId}'); this.animation.addByPrefix('idle', 'idle0', 24, true); if (Preferences.flashingLights) this.animation.play('idle'); } else { - this.loadGraphic(Paths.image('freeplay/freeplay' + diffId)); + this.loadGraphic(Paths.image('freeplay/freeplay' + assetDiffId)); } } } diff --git a/source/funkin/ui/freeplay/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx index 2eec83223..b4409d377 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -162,7 +162,7 @@ class SongMenuItem extends FlxSpriteGroup sparkle = new FlxSprite(ranking.x, ranking.y); sparkle.frames = Paths.getSparrowAtlas('freeplay/sparkle'); - sparkle.animation.addByPrefix('sparkle', 'sparkle', 24, false); + sparkle.animation.addByPrefix('sparkle', 'sparkle Export0', 24, false); sparkle.animation.play('sparkle', true); sparkle.scale.set(0.8, 0.8); sparkle.blend = BlendMode.ADD; @@ -523,7 +523,6 @@ class SongMenuItem extends FlxSpriteGroup checkWeek(songData?.songId); } - var frameInTicker:Float = 0; var frameInTypeBeat:Int = 0; From 0e7fad090baae898cb7d95aca6a43d0604fc74db Mon Sep 17 00:00:00 2001 From: anysad Date: Sat, 13 Jul 2024 22:45:58 +0300 Subject: [PATCH 544/870] custom popups and countdowns yay!!! --- assets | 2 +- source/funkin/play/Countdown.hx | 158 ++++++++++---------- source/funkin/play/PlayState.hx | 6 +- source/funkin/play/components/PopUpStuff.hx | 59 ++++++-- 4 files changed, 125 insertions(+), 100 deletions(-) diff --git a/assets b/assets index aa1231e8c..3a9e05108 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit aa1231e8cf2990bb902eac3b37815c010fa9919a +Subproject commit 3a9e0510841533f96228609dcd50f2515443bb90 diff --git a/source/funkin/play/Countdown.hx b/source/funkin/play/Countdown.hx index 55c2a8992..542cb067c 100644 --- a/source/funkin/play/Countdown.hx +++ b/source/funkin/play/Countdown.hx @@ -11,6 +11,7 @@ import funkin.modding.events.ScriptEvent.CountdownScriptEvent; import flixel.util.FlxTimer; import funkin.util.EaseUtil; import funkin.audio.FunkinSound; +import openfl.utils.Assets; class Countdown { @@ -19,6 +20,20 @@ class Countdown */ public static var countdownStep(default, null):CountdownStep = BEFORE; + /** + * Which alternate countdown sound effect to use. + * You can set this via script. + * For example, in Week 6 it is `-pixel`. + */ + public static var soundSuffix:String = ''; + + /** + * Which alternate graphic on countdown to use. + * You can set this via script. + * For example, in Week 6 it is `-pixel`. + */ + public static var graphicSuffix:String = ''; + /** * The currently running countdown. This will be null if there is no countdown running. */ @@ -30,7 +45,7 @@ class Countdown * This will automatically stop and restart the countdown if it is already running. * @returns `false` if the countdown was cancelled by a script. */ - public static function performCountdown(isPixelStyle:Bool):Bool + public static function performCountdown():Bool { countdownStep = BEFORE; var cancelled:Bool = propagateCountdownEvent(countdownStep); @@ -65,10 +80,10 @@ class Countdown // PlayState.instance.dispatchEvent(new SongTimeScriptEvent(SONG_BEAT_HIT, 0, 0)); // Countdown graphic. - showCountdownGraphic(countdownStep, isPixelStyle); + showCountdownGraphic(countdownStep, graphicSuffix.toLowerCase().contains('pixel')); // Countdown sound. - playCountdownSound(countdownStep, isPixelStyle); + playCountdownSound(countdownStep); // Event handling bullshit. var cancelled:Bool = propagateCountdownEvent(countdownStep); @@ -177,55 +192,33 @@ class Countdown } /** - * Retrieves the graphic to use for this step of the countdown. - * TODO: Make this less dumb. Unhardcode it? Use modules? Use notestyles? - * - * This is public so modules can do lol funny shit. + * Reset the countdown configuration to the default. */ - public static function showCountdownGraphic(index:CountdownStep, isPixelStyle:Bool):Void + public static function reset() + { + soundSuffix = ''; + graphicSuffix = ''; + } + + /** + * Retrieves the graphic to use for this step of the countdown. + */ + public static function showCountdownGraphic(index:CountdownStep, isGraphicPixel:Bool):Void { var spritePath:String = null; - - var fadeEase = FlxEase.cubeInOut; - - if (isPixelStyle) - { - fadeEase = EaseUtil.stepped(8); - switch (index) - { - case TWO: - spritePath = 'weeb/pixelUI/ready-pixel'; - case ONE: - spritePath = 'weeb/pixelUI/set-pixel'; - case GO: - spritePath = 'weeb/pixelUI/date-pixel'; - default: - // null - } - } - else - { - switch (index) - { - case TWO: - spritePath = 'ready'; - case ONE: - spritePath = 'set'; - case GO: - spritePath = 'go'; - default: - // null - } - } + spritePath = resolveGraphicPath(graphicSuffix, index); if (spritePath == null) return; var countdownSprite:FunkinSprite = FunkinSprite.create(spritePath); countdownSprite.scrollFactor.set(0, 0); - if (isPixelStyle) countdownSprite.setGraphicSize(Std.int(countdownSprite.width * Constants.PIXEL_ART_SCALE)); + if (isGraphicPixel) countdownSprite.setGraphicSize(Std.int(countdownSprite.width * Constants.PIXEL_ART_SCALE)); - countdownSprite.antialiasing = !isPixelStyle; + var fadeEase = FlxEase.cubeInOut; + if (isGraphicPixel) fadeEase = EaseUtil.stepped(8); + + countdownSprite.antialiasing = !isGraphicPixel; countdownSprite.updateHitbox(); countdownSprite.screenCenter(); @@ -247,52 +240,55 @@ class Countdown PlayState.instance.add(countdownSprite); } + static function resolveGraphicPath(suffix:String, index:CountdownStep):Null + { + var basePath:String = 'ui/countdown/'; + var indexString:String = null; + switch (index) + { + case TWO: + indexString = 'ready'; + case ONE: + indexString = 'set'; + case GO: + indexString = 'go'; + default: + // null + } + basePath += indexString; + var spritePath:String = basePath + suffix; + while (!Assets.exists(Paths.image(spritePath)) && suffix.length > 0) + { + suffix = suffix.split('-').slice(0, -1).join('-'); + spritePath = basePath + suffix; + } + if (!Assets.exists(Paths.image(spritePath))) return null; + trace('Resolved sprite path: ' + Paths.image(spritePath)); + return spritePath; + } + /** * Retrieves the sound file to use for this step of the countdown. - * TODO: Make this less dumb. Unhardcode it? Use modules? Use notestyles? - * - * This is public so modules can do lol funny shit. */ - public static function playCountdownSound(index:CountdownStep, isPixelStyle:Bool):Void + public static function playCountdownSound(index:CountdownStep):Void { - var soundPath:String = null; + FunkinSound.playOnce(resolveSoundPath(soundSuffix, index), Constants.COUNTDOWN_VOLUME); + } - if (isPixelStyle) + static function resolveSoundPath(suffix:String, step:CountdownStep):Null + { + var basePath:String = 'gameplay/countdown/intro'; + if (step != CountdownStep.BEFORE || step != CountdownStep.AFTER) basePath += step; + + var soundPath:String = Paths.sound(basePath + suffix); + while (!Assets.exists(soundPath) && suffix.length > 0) { - switch (index) - { - case THREE: - soundPath = 'intro3-pixel'; - case TWO: - soundPath = 'intro2-pixel'; - case ONE: - soundPath = 'intro1-pixel'; - case GO: - soundPath = 'introGo-pixel'; - default: - // null - } + suffix = suffix.split('-').slice(0, -1).join('-'); + soundPath = Paths.sound(basePath + suffix); } - else - { - switch (index) - { - case THREE: - soundPath = 'intro3'; - case TWO: - soundPath = 'intro2'; - case ONE: - soundPath = 'intro1'; - case GO: - soundPath = 'introGo'; - default: - // null - } - } - - if (soundPath == null) return; - - FunkinSound.playOnce(Paths.sound(soundPath), Constants.COUNTDOWN_VOLUME); + if (!Assets.exists(soundPath)) return null; + trace('Resolved sound path: ' + soundPath); + return soundPath; } public static function decrement(step:CountdownStep):CountdownStep diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 32b6e7b62..384c28056 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -900,7 +900,7 @@ class PlayState extends MusicBeatSubState health = Constants.HEALTH_STARTING; songScore = 0; Highscore.tallies.combo = 0; - Countdown.performCountdown(currentStageId.startsWith('school')); + Countdown.performCountdown(); needsReset = false; } @@ -1857,7 +1857,7 @@ class PlayState extends MusicBeatSubState public function startCountdown():Void { // If Countdown.performCountdown returns false, then the countdown was canceled by a script. - var result:Bool = Countdown.performCountdown(currentStageId.startsWith('school')); + var result:Bool = Countdown.performCountdown(); if (!result) return; isInCutscene = false; @@ -3004,6 +3004,8 @@ class PlayState extends MusicBeatSubState GameOverSubState.reset(); PauseSubState.reset(); + Countdown.reset(); + PopUpStuff.reset(); // Clear the static reference to this state. instance = null; diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx index 1bdfd98a8..4ae425cb6 100644 --- a/source/funkin/play/components/PopUpStuff.hx +++ b/source/funkin/play/components/PopUpStuff.hx @@ -8,25 +8,51 @@ import funkin.graphics.FunkinSprite; import funkin.play.PlayState; import funkin.util.TimerUtil; import funkin.util.EaseUtil; +import openfl.utils.Assets; class PopUpStuff extends FlxTypedGroup { public var offsets:Array = [0, 0]; + /** + * Which alternate graphic on popup to use. + * You can set this via script. + * For example, in Week 6 it is `-pixel`. + */ + public static var graphicSuffix:String = ''; + override public function new() { super(); } - public function displayRating(daRating:String):Void + static function resolveGraphicPath(suffix:String, index:String):Null + { + var folder:String; + if (suffix != '') folder = suffix.substring(0, suffix.indexOf("-")) + suffix.substring(suffix.indexOf("-") + 1); + else + folder = 'normal'; + var basePath:String = 'gameplay/popup/$folder/$index'; + var spritePath:String = basePath + suffix; + trace(spritePath); + while (!Assets.exists(Paths.image(spritePath)) && suffix.length > 0) + { + suffix = suffix.split('-').slice(0, -1).join('-'); + spritePath = basePath + suffix; + } + if (!Assets.exists(Paths.image(spritePath))) return null; + return spritePath; + } + + public function displayRating(daRating:String) { var perfStart:Float = TimerUtil.start(); if (daRating == null) daRating = "good"; - var ratingPath:String = daRating; + var ratingPath:String = resolveGraphicPath(graphicSuffix, daRating); - if (PlayState.instance.currentStageId.startsWith('school')) ratingPath = "weeb/pixelUI/" + ratingPath + "-pixel"; + // if (PlayState.instance.currentStageId.startsWith('school')) ratingPath = "weeb/pixelUI/" + ratingPath + "-pixel"; var rating:FunkinSprite = FunkinSprite.create(0, 0, ratingPath); rating.scrollFactor.set(0.2, 0.2); @@ -43,7 +69,7 @@ class PopUpStuff extends FlxTypedGroup var fadeEase = null; - if (PlayState.instance.currentStageId.startsWith('school')) + if (graphicSuffix.toLowerCase().contains('pixel')) { rating.setGraphicSize(Std.int(rating.width * Constants.PIXEL_ART_SCALE * 0.7)); rating.antialiasing = false; @@ -80,15 +106,8 @@ class PopUpStuff extends FlxTypedGroup if (combo == null) combo = 0; - var pixelShitPart1:String = ""; - var pixelShitPart2:String = ''; - - if (PlayState.instance.currentStageId.startsWith('school')) - { - pixelShitPart1 = 'weeb/pixelUI/'; - pixelShitPart2 = '-pixel'; - } - var comboSpr:FunkinSprite = FunkinSprite.create(pixelShitPart1 + 'combo' + pixelShitPart2); + var comboPath:String = resolveGraphicPath(graphicSuffix, Std.string(combo)); + var comboSpr:FunkinSprite = FunkinSprite.create(comboPath); comboSpr.y = (FlxG.camera.height * 0.44) + offsets[1]; comboSpr.x = (FlxG.width * 0.507) + offsets[0]; // comboSpr.x -= FlxG.camera.scroll.x * 0.2; @@ -101,7 +120,7 @@ class PopUpStuff extends FlxTypedGroup var fadeEase = null; - if (PlayState.instance.currentStageId.startsWith('school')) + if (graphicSuffix.toLowerCase().contains('pixel')) { comboSpr.setGraphicSize(Std.int(comboSpr.width * Constants.PIXEL_ART_SCALE * 1)); comboSpr.antialiasing = false; @@ -142,9 +161,9 @@ class PopUpStuff extends FlxTypedGroup var daLoop:Int = 1; for (i in seperatedScore) { - var numScore:FunkinSprite = FunkinSprite.create(0, comboSpr.y, pixelShitPart1 + 'num' + Std.int(i) + pixelShitPart2); + var numScore:FunkinSprite = FunkinSprite.create(0, comboSpr.y, resolveGraphicPath(graphicSuffix, 'num' + Std.int(i))); - if (PlayState.instance.currentStageId.startsWith('school')) + if (graphicSuffix.toLowerCase().contains('pixel')) { numScore.setGraphicSize(Std.int(numScore.width * Constants.PIXEL_ART_SCALE * 1)); numScore.antialiasing = false; @@ -182,4 +201,12 @@ class PopUpStuff extends FlxTypedGroup return combo; } + + /** + * Reset the popup configuration to the default. + */ + public static function reset() + { + graphicSuffix = ''; + } } From bf1d4031af0c60287cbfd700a4597a2dc8fb9829 Mon Sep 17 00:00:00 2001 From: anysad Date: Sat, 13 Jul 2024 23:08:16 +0300 Subject: [PATCH 545/870] remove trace --- source/funkin/play/components/PopUpStuff.hx | 1 - 1 file changed, 1 deletion(-) diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx index 4ae425cb6..971ed1064 100644 --- a/source/funkin/play/components/PopUpStuff.hx +++ b/source/funkin/play/components/PopUpStuff.hx @@ -34,7 +34,6 @@ class PopUpStuff extends FlxTypedGroup folder = 'normal'; var basePath:String = 'gameplay/popup/$folder/$index'; var spritePath:String = basePath + suffix; - trace(spritePath); while (!Assets.exists(Paths.image(spritePath)) && suffix.length > 0) { suffix = suffix.split('-').slice(0, -1).join('-'); From dc9dbe84fa68fd988eeca6666f3d199c92a3f945 Mon Sep 17 00:00:00 2001 From: anysad Date: Sat, 13 Jul 2024 23:29:26 +0300 Subject: [PATCH 546/870] cache textures at their new locations! --- source/funkin/ui/transition/LoadingState.hx | 33 ++++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/source/funkin/ui/transition/LoadingState.hx b/source/funkin/ui/transition/LoadingState.hx index 0f2ce1076..b4987ff27 100644 --- a/source/funkin/ui/transition/LoadingState.hx +++ b/source/funkin/ui/transition/LoadingState.hx @@ -291,17 +291,28 @@ class LoadingState extends MusicBeatSubState FunkinSprite.preparePurgeCache(); FunkinSprite.cacheTexture(Paths.image('healthBar')); FunkinSprite.cacheTexture(Paths.image('menuDesat')); - FunkinSprite.cacheTexture(Paths.image('combo')); - FunkinSprite.cacheTexture(Paths.image('num0')); - FunkinSprite.cacheTexture(Paths.image('num1')); - FunkinSprite.cacheTexture(Paths.image('num2')); - FunkinSprite.cacheTexture(Paths.image('num3')); - FunkinSprite.cacheTexture(Paths.image('num4')); - FunkinSprite.cacheTexture(Paths.image('num5')); - FunkinSprite.cacheTexture(Paths.image('num6')); - FunkinSprite.cacheTexture(Paths.image('num7')); - FunkinSprite.cacheTexture(Paths.image('num8')); - FunkinSprite.cacheTexture(Paths.image('num9')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/combo')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num0')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num1')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num2')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num3')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num4')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num5')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num6')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num7')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num8')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num9')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/combo-pixel')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num0-pixel')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num1-pixel')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num2-pixel')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num3-pixel')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num4-pixel')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num5-pixel')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num6-pixel')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num7-pixel')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num8-pixel')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num9-pixel')); FunkinSprite.cacheTexture(Paths.image('notes', 'shared')); FunkinSprite.cacheTexture(Paths.image('noteSplashes', 'shared')); FunkinSprite.cacheTexture(Paths.image('noteStrumline', 'shared')); From d5a53855d35458fbf4ceb1ab7ad09436d650f9c6 Mon Sep 17 00:00:00 2001 From: anysad Date: Sat, 13 Jul 2024 23:39:56 +0300 Subject: [PATCH 547/870] how the hell did I miss these? --- source/funkin/ui/transition/LoadingState.hx | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/source/funkin/ui/transition/LoadingState.hx b/source/funkin/ui/transition/LoadingState.hx index b4987ff27..3e9dec96b 100644 --- a/source/funkin/ui/transition/LoadingState.hx +++ b/source/funkin/ui/transition/LoadingState.hx @@ -317,13 +317,20 @@ class LoadingState extends MusicBeatSubState FunkinSprite.cacheTexture(Paths.image('noteSplashes', 'shared')); FunkinSprite.cacheTexture(Paths.image('noteStrumline', 'shared')); FunkinSprite.cacheTexture(Paths.image('NOTE_hold_assets')); - FunkinSprite.cacheTexture(Paths.image('ready', 'shared')); - FunkinSprite.cacheTexture(Paths.image('set', 'shared')); - FunkinSprite.cacheTexture(Paths.image('go', 'shared')); - FunkinSprite.cacheTexture(Paths.image('sick', 'shared')); - FunkinSprite.cacheTexture(Paths.image('good', 'shared')); - FunkinSprite.cacheTexture(Paths.image('bad', 'shared')); - FunkinSprite.cacheTexture(Paths.image('shit', 'shared')); + FunkinSprite.cacheTexture(Paths.image('ui/countdown/ready', 'shared')); + FunkinSprite.cacheTexture(Paths.image('ui/countdown/set', 'shared')); + FunkinSprite.cacheTexture(Paths.image('ui/countdown/go', 'shared')); + FunkinSprite.cacheTexture(Paths.image('ui/countdown/ready-pixel', 'shared')); + FunkinSprite.cacheTexture(Paths.image('ui/countdown/set-pixel', 'shared')); + FunkinSprite.cacheTexture(Paths.image('ui/countdown/go-pixel', 'shared')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/sick')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/good')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/bad')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/shit')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/sick-pixel')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/good-pixel')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/bad-pixel')); + FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/shit-pixel')); FunkinSprite.cacheTexture(Paths.image('miss', 'shared')); // TODO: remove this // List all image assets in the level's library. From d3209e57b7f177df969a5610b16f4bd57163ffda Mon Sep 17 00:00:00 2001 From: anysad Date: Tue, 16 Jul 2024 20:53:12 +0300 Subject: [PATCH 548/870] goodbye scripts, hello notestyles! --- source/funkin/play/Countdown.hx | 98 +++++++++++++-------- source/funkin/play/components/PopUpStuff.hx | 48 ++++++---- source/funkin/ui/transition/LoadingState.hx | 73 +++++++-------- source/funkin/util/Constants.hx | 5 ++ 4 files changed, 131 insertions(+), 93 deletions(-) diff --git a/source/funkin/play/Countdown.hx b/source/funkin/play/Countdown.hx index 542cb067c..139b6cacd 100644 --- a/source/funkin/play/Countdown.hx +++ b/source/funkin/play/Countdown.hx @@ -12,6 +12,8 @@ import flixel.util.FlxTimer; import funkin.util.EaseUtil; import funkin.audio.FunkinSound; import openfl.utils.Assets; +import funkin.data.notestyle.NoteStyleRegistry; +import funkin.play.notes.notestyle.NoteStyle; class Countdown { @@ -21,9 +23,9 @@ class Countdown public static var countdownStep(default, null):CountdownStep = BEFORE; /** - * Which alternate countdown sound effect to use. - * You can set this via script. - * For example, in Week 6 it is `-pixel`. + * Which alternate graphic/sound on countdown to use. + * This is set via the current notestyle. + * For example, in Week 6 it is `pixel`. */ public static var soundSuffix:String = ''; @@ -34,6 +36,10 @@ class Countdown */ public static var graphicSuffix:String = ''; + static var noteStyle:NoteStyle; + + static var isPixel:Bool = false; + /** * The currently running countdown. This will be null if there is no countdown running. */ @@ -63,6 +69,12 @@ class Countdown // @:privateAccess // PlayState.instance.dispatchEvent(new SongTimeScriptEvent(SONG_BEAT_HIT, 0, 0)); + var fetchedNoteStyle:NoteStyle = NoteStyleRegistry.instance.fetchEntry(PlayState.instance.currentChart.noteStyle); + if (fetchedNoteStyle == null) noteStyle = NoteStyleRegistry.instance.fetchDefault(); + else + noteStyle = fetchedNoteStyle; + if (noteStyle._data.assets.note.isPixel) isPixel = true; + // The timer function gets called based on the beat of the song. countdownTimer = new FlxTimer(); @@ -80,10 +92,10 @@ class Countdown // PlayState.instance.dispatchEvent(new SongTimeScriptEvent(SONG_BEAT_HIT, 0, 0)); // Countdown graphic. - showCountdownGraphic(countdownStep, graphicSuffix.toLowerCase().contains('pixel')); + showCountdownGraphic(countdownStep, noteStyle, isPixel); // Countdown sound. - playCountdownSound(countdownStep); + playCountdownSound(countdownStep, noteStyle); // Event handling bullshit. var cancelled:Bool = propagateCountdownEvent(countdownStep); @@ -196,17 +208,31 @@ class Countdown */ public static function reset() { - soundSuffix = ''; - graphicSuffix = ''; + noteStyle = NoteStyleRegistry.instance.fetchDefault(); + isPixel = false; } /** * Retrieves the graphic to use for this step of the countdown. */ - public static function showCountdownGraphic(index:CountdownStep, isGraphicPixel:Bool):Void + public static function showCountdownGraphic(index:CountdownStep, noteStyle:NoteStyle, isGraphicPixel:Bool):Void { + var indexString:String = null; + switch (index) + { + case TWO: + indexString = 'ready'; + case ONE: + indexString = 'set'; + case GO: + indexString = 'go'; + default: + // null + } + if (indexString == null) return; + var spritePath:String = null; - spritePath = resolveGraphicPath(graphicSuffix, index); + spritePath = resolveGraphicPath(noteStyle, indexString); if (spritePath == null) return; @@ -214,6 +240,8 @@ class Countdown countdownSprite.scrollFactor.set(0, 0); if (isGraphicPixel) countdownSprite.setGraphicSize(Std.int(countdownSprite.width * Constants.PIXEL_ART_SCALE)); + else + countdownSprite.setGraphicSize(Std.int(countdownSprite.width * 0.7)); var fadeEase = FlxEase.cubeInOut; if (isGraphicPixel) fadeEase = EaseUtil.stepped(8); @@ -223,6 +251,8 @@ class Countdown countdownSprite.updateHitbox(); countdownSprite.screenCenter(); + countdownSprite.cameras = [PlayState.instance.camHUD]; + // Fade sprite in, then out, then destroy it. FlxTween.tween(countdownSprite, {y: countdownSprite.y += 100}, Conductor.instance.beatLengthMs / 1000, { @@ -240,29 +270,19 @@ class Countdown PlayState.instance.add(countdownSprite); } - static function resolveGraphicPath(suffix:String, index:CountdownStep):Null + static function resolveGraphicPath(noteStyle:NoteStyle, index:String):Null { var basePath:String = 'ui/countdown/'; - var indexString:String = null; - switch (index) + + var spritePath:String = basePath + noteStyle.id + '/$index'; + // If nothing is found, revert it to default notestyle skin + if (!Assets.exists(Paths.image(spritePath))) { - case TWO: - indexString = 'ready'; - case ONE: - indexString = 'set'; - case GO: - indexString = 'go'; - default: - // null + if (!isPixel) spritePath = basePath + Constants.DEFAULT_NOTE_STYLE + '/$index'; + else + spritePath = basePath + Constants.DEFAULT_PIXEL_NOTE_STYLE + '/$index'; } - basePath += indexString; - var spritePath:String = basePath + suffix; - while (!Assets.exists(Paths.image(spritePath)) && suffix.length > 0) - { - suffix = suffix.split('-').slice(0, -1).join('-'); - spritePath = basePath + suffix; - } - if (!Assets.exists(Paths.image(spritePath))) return null; + trace('Resolved sprite path: ' + Paths.image(spritePath)); return spritePath; } @@ -270,23 +290,25 @@ class Countdown /** * Retrieves the sound file to use for this step of the countdown. */ - public static function playCountdownSound(index:CountdownStep):Void + public static function playCountdownSound(step:CountdownStep, noteStyle:NoteStyle):Void { - FunkinSound.playOnce(resolveSoundPath(soundSuffix, index), Constants.COUNTDOWN_VOLUME); + return FunkinSound.playOnce(Paths.sound(resolveSoundPath(noteStyle, step)), Constants.COUNTDOWN_VOLUME); } - static function resolveSoundPath(suffix:String, step:CountdownStep):Null + static function resolveSoundPath(noteStyle:NoteStyle, step:CountdownStep):Null { - var basePath:String = 'gameplay/countdown/intro'; - if (step != CountdownStep.BEFORE || step != CountdownStep.AFTER) basePath += step; + if (step == CountdownStep.BEFORE || step == CountdownStep.AFTER) return null; + var basePath:String = 'gameplay/countdown/'; - var soundPath:String = Paths.sound(basePath + suffix); - while (!Assets.exists(soundPath) && suffix.length > 0) + var soundPath:String = basePath + noteStyle.id + '/intro$step'; + // If nothing is found, revert it to default notestyle sound + if (!Assets.exists(Paths.sound(soundPath))) { - suffix = suffix.split('-').slice(0, -1).join('-'); - soundPath = Paths.sound(basePath + suffix); + if (!isPixel) soundPath = basePath + Constants.DEFAULT_NOTE_STYLE + '/intro$step'; + else + soundPath = basePath + Constants.DEFAULT_PIXEL_NOTE_STYLE + '/intro$step'; } - if (!Assets.exists(soundPath)) return null; + trace('Resolved sound path: ' + soundPath); return soundPath; } diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx index 971ed1064..2bd2bf4db 100644 --- a/source/funkin/play/components/PopUpStuff.hx +++ b/source/funkin/play/components/PopUpStuff.hx @@ -9,6 +9,8 @@ import funkin.play.PlayState; import funkin.util.TimerUtil; import funkin.util.EaseUtil; import openfl.utils.Assets; +import funkin.data.notestyle.NoteStyleRegistry; +import funkin.play.notes.notestyle.NoteStyle; class PopUpStuff extends FlxTypedGroup { @@ -16,30 +18,37 @@ class PopUpStuff extends FlxTypedGroup /** * Which alternate graphic on popup to use. - * You can set this via script. - * For example, in Week 6 it is `-pixel`. + * This is set via the current notestyle. + * For example, in Week 6 it is `pixel`. */ - public static var graphicSuffix:String = ''; + static var noteStyle:NoteStyle; + + static var isPixel:Bool = false; override public function new() { super(); + + var fetchedNoteStyle:NoteStyle = NoteStyleRegistry.instance.fetchEntry(PlayState.instance.currentChart.noteStyle); + if (fetchedNoteStyle == null) noteStyle = NoteStyleRegistry.instance.fetchDefault(); + else + noteStyle = fetchedNoteStyle; + if (noteStyle._data.assets.note.isPixel) isPixel = true; } - static function resolveGraphicPath(suffix:String, index:String):Null + static function resolveGraphicPath(noteStyle:NoteStyle, index:String):Null { - var folder:String; - if (suffix != '') folder = suffix.substring(0, suffix.indexOf("-")) + suffix.substring(suffix.indexOf("-") + 1); - else - folder = 'normal'; - var basePath:String = 'gameplay/popup/$folder/$index'; - var spritePath:String = basePath + suffix; - while (!Assets.exists(Paths.image(spritePath)) && suffix.length > 0) + var basePath:String = 'ui/popup/'; + + var spritePath:String = basePath + noteStyle.id + '/$index'; + // If nothing is found, revert it to default notestyle skin + if (!Assets.exists(Paths.image(spritePath))) { - suffix = suffix.split('-').slice(0, -1).join('-'); - spritePath = basePath + suffix; + if (!isPixel) spritePath = basePath + Constants.DEFAULT_NOTE_STYLE + '/$index'; + else + spritePath = basePath + Constants.DEFAULT_PIXEL_NOTE_STYLE + '/$index'; } - if (!Assets.exists(Paths.image(spritePath))) return null; + return spritePath; } @@ -49,7 +58,7 @@ class PopUpStuff extends FlxTypedGroup if (daRating == null) daRating = "good"; - var ratingPath:String = resolveGraphicPath(graphicSuffix, daRating); + var ratingPath:String = resolveGraphicPath(noteStyle, daRating); // if (PlayState.instance.currentStageId.startsWith('school')) ratingPath = "weeb/pixelUI/" + ratingPath + "-pixel"; @@ -68,7 +77,7 @@ class PopUpStuff extends FlxTypedGroup var fadeEase = null; - if (graphicSuffix.toLowerCase().contains('pixel')) + if (isPixel) { rating.setGraphicSize(Std.int(rating.width * Constants.PIXEL_ART_SCALE * 0.7)); rating.antialiasing = false; @@ -105,7 +114,7 @@ class PopUpStuff extends FlxTypedGroup if (combo == null) combo = 0; - var comboPath:String = resolveGraphicPath(graphicSuffix, Std.string(combo)); + var comboPath:String = resolveGraphicPath(noteStyle, 'combo'); var comboSpr:FunkinSprite = FunkinSprite.create(comboPath); comboSpr.y = (FlxG.camera.height * 0.44) + offsets[1]; comboSpr.x = (FlxG.width * 0.507) + offsets[0]; @@ -160,7 +169,7 @@ class PopUpStuff extends FlxTypedGroup var daLoop:Int = 1; for (i in seperatedScore) { - var numScore:FunkinSprite = FunkinSprite.create(0, comboSpr.y, resolveGraphicPath(graphicSuffix, 'num' + Std.int(i))); + var numScore:FunkinSprite = FunkinSprite.create(0, comboSpr.y, resolveGraphicPath(noteStyle, 'num' + Std.int(i))); if (graphicSuffix.toLowerCase().contains('pixel')) { @@ -206,6 +215,7 @@ class PopUpStuff extends FlxTypedGroup */ public static function reset() { - graphicSuffix = ''; + noteStyle = NoteStyleRegistry.instance.fetchDefault(); + isPixel = false; } } diff --git a/source/funkin/ui/transition/LoadingState.hx b/source/funkin/ui/transition/LoadingState.hx index 3e9dec96b..d48ca1c0b 100644 --- a/source/funkin/ui/transition/LoadingState.hx +++ b/source/funkin/ui/transition/LoadingState.hx @@ -291,46 +291,47 @@ class LoadingState extends MusicBeatSubState FunkinSprite.preparePurgeCache(); FunkinSprite.cacheTexture(Paths.image('healthBar')); FunkinSprite.cacheTexture(Paths.image('menuDesat')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/combo')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num0')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num1')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num2')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num3')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num4')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num5')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num6')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num7')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num8')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/num9')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/combo-pixel')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num0-pixel')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num1-pixel')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num2-pixel')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num3-pixel')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num4-pixel')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num5-pixel')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num6-pixel')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num7-pixel')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num8-pixel')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/num9-pixel')); + // Lord have mercy on me and this caching -anysad + FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/combo')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num0')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num1')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num2')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num3')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num4')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num5')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num6')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num7')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num8')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/num9')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/combo')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num0')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num1')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num2')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num3')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num4')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num5')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num6')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num7')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num8')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num9')); FunkinSprite.cacheTexture(Paths.image('notes', 'shared')); FunkinSprite.cacheTexture(Paths.image('noteSplashes', 'shared')); FunkinSprite.cacheTexture(Paths.image('noteStrumline', 'shared')); FunkinSprite.cacheTexture(Paths.image('NOTE_hold_assets')); - FunkinSprite.cacheTexture(Paths.image('ui/countdown/ready', 'shared')); - FunkinSprite.cacheTexture(Paths.image('ui/countdown/set', 'shared')); - FunkinSprite.cacheTexture(Paths.image('ui/countdown/go', 'shared')); - FunkinSprite.cacheTexture(Paths.image('ui/countdown/ready-pixel', 'shared')); - FunkinSprite.cacheTexture(Paths.image('ui/countdown/set-pixel', 'shared')); - FunkinSprite.cacheTexture(Paths.image('ui/countdown/go-pixel', 'shared')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/sick')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/good')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/bad')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/normal/shit')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/sick-pixel')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/good-pixel')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/bad-pixel')); - FunkinSprite.cacheTexture(Paths.image('gameplay/popup/pixel/shit-pixel')); + FunkinSprite.cacheTexture(Paths.image('ui/countdown/funkin/ready', 'shared')); + FunkinSprite.cacheTexture(Paths.image('ui/countdown/funkin/set', 'shared')); + FunkinSprite.cacheTexture(Paths.image('ui/countdown/funkin/go', 'shared')); + FunkinSprite.cacheTexture(Paths.image('ui/countdown/pixel/ready', 'shared')); + FunkinSprite.cacheTexture(Paths.image('ui/countdown/pixel/set', 'shared')); + FunkinSprite.cacheTexture(Paths.image('ui/countdown/pixel/go', 'shared')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/normal/sick')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/normal/good')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/normal/bad')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/normal/shit')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/sick')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/good')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/bad')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/shit')); FunkinSprite.cacheTexture(Paths.image('miss', 'shared')); // TODO: remove this // List all image assets in the level's library. diff --git a/source/funkin/util/Constants.hx b/source/funkin/util/Constants.hx index 2d4fef1f4..85cd1a27b 100644 --- a/source/funkin/util/Constants.hx +++ b/source/funkin/util/Constants.hx @@ -258,6 +258,11 @@ class Constants */ public static final DEFAULT_NOTE_STYLE:String = 'funkin'; + /** + * The default pixel note style for songs. + */ + public static final DEFAULT_PIXEL_NOTE_STYLE:String = 'pixel'; + /** * The default album for songs in Freeplay. */ From 82a6ca591687c01ff82a6605c74195da3237ac6d Mon Sep 17 00:00:00 2001 From: anysad Date: Wed, 17 Jul 2024 23:19:18 +0300 Subject: [PATCH 549/870] welcome fallback note styles! --- source/funkin/play/Countdown.hx | 54 ++++++++++++++----- source/funkin/play/components/PopUpStuff.hx | 21 +++++++- .../funkin/play/notes/notestyle/NoteStyle.hx | 2 +- 3 files changed, 60 insertions(+), 17 deletions(-) diff --git a/source/funkin/play/Countdown.hx b/source/funkin/play/Countdown.hx index 139b6cacd..a8bf1b500 100644 --- a/source/funkin/play/Countdown.hx +++ b/source/funkin/play/Countdown.hx @@ -38,6 +38,8 @@ class Countdown static var noteStyle:NoteStyle; + static var fallbackNoteStyle:Null; + static var isPixel:Bool = false; /** @@ -69,11 +71,7 @@ class Countdown // @:privateAccess // PlayState.instance.dispatchEvent(new SongTimeScriptEvent(SONG_BEAT_HIT, 0, 0)); - var fetchedNoteStyle:NoteStyle = NoteStyleRegistry.instance.fetchEntry(PlayState.instance.currentChart.noteStyle); - if (fetchedNoteStyle == null) noteStyle = NoteStyleRegistry.instance.fetchDefault(); - else - noteStyle = fetchedNoteStyle; - if (noteStyle._data.assets.note.isPixel) isPixel = true; + fetchNoteStyle(); // The timer function gets called based on the beat of the song. countdownTimer = new FlxTimer(); @@ -92,7 +90,7 @@ class Countdown // PlayState.instance.dispatchEvent(new SongTimeScriptEvent(SONG_BEAT_HIT, 0, 0)); // Countdown graphic. - showCountdownGraphic(countdownStep, noteStyle, isPixel); + showCountdownGraphic(countdownStep, noteStyle); // Countdown sound. playCountdownSound(countdownStep, noteStyle); @@ -212,10 +210,20 @@ class Countdown isPixel = false; } + static function fetchNoteStyle():Void + { + var fetchedNoteStyle:NoteStyle = NoteStyleRegistry.instance.fetchEntry(PlayState.instance.currentChart.noteStyle); + if (fetchedNoteStyle == null) noteStyle = NoteStyleRegistry.instance.fetchDefault(); + else + noteStyle = fetchedNoteStyle; + fallbackNoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyle.getFallbackID()); + isPixel = false; + } + /** * Retrieves the graphic to use for this step of the countdown. */ - public static function showCountdownGraphic(index:CountdownStep, noteStyle:NoteStyle, isGraphicPixel:Bool):Void + public static function showCountdownGraphic(index:CountdownStep, noteStyle:NoteStyle):Void { var indexString:String = null; switch (index) @@ -246,13 +254,13 @@ class Countdown var fadeEase = FlxEase.cubeInOut; if (isGraphicPixel) fadeEase = EaseUtil.stepped(8); - countdownSprite.antialiasing = !isGraphicPixel; + countdownSprite.antialiasing = !isPixel; + + countdownSprite.cameras = [PlayState.instance.camHUD]; countdownSprite.updateHitbox(); countdownSprite.screenCenter(); - countdownSprite.cameras = [PlayState.instance.camHUD]; - // Fade sprite in, then out, then destroy it. FlxTween.tween(countdownSprite, {y: countdownSprite.y += 100}, Conductor.instance.beatLengthMs / 1000, { @@ -272,10 +280,19 @@ class Countdown static function resolveGraphicPath(noteStyle:NoteStyle, index:String):Null { + fetchNoteStyle(); var basePath:String = 'ui/countdown/'; - var spritePath:String = basePath + noteStyle.id + '/$index'; - // If nothing is found, revert it to default notestyle skin + + while (!Assets.exists(Paths.image(spritePath)) && fallbackNoteStyle != null) + { + noteStyle = fallbackNoteStyle; + fallbackNoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyle.getFallbackID()); + spritePath = basePath + noteStyle.id + '/$index'; + } + if (noteStyle.isHoldNotePixel()) isPixel = true; + + // If ABSOLUTELY nothing is found, revert it to default notestyle skin if (!Assets.exists(Paths.image(spritePath))) { if (!isPixel) spritePath = basePath + Constants.DEFAULT_NOTE_STYLE + '/$index'; @@ -298,10 +315,19 @@ class Countdown static function resolveSoundPath(noteStyle:NoteStyle, step:CountdownStep):Null { if (step == CountdownStep.BEFORE || step == CountdownStep.AFTER) return null; + fetchNoteStyle(); var basePath:String = 'gameplay/countdown/'; - var soundPath:String = basePath + noteStyle.id + '/intro$step'; - // If nothing is found, revert it to default notestyle sound + + while (!Assets.exists(Paths.sound(soundPath)) && fallbackNoteStyle != null) + { + noteStyle = fallbackNoteStyle; + fallbackNoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyle.getFallbackID()); + soundPath = basePath + noteStyle.id + '/intro$step'; + } + if (noteStyle.isHoldNotePixel()) isPixel = true; + + // If ABSOLUTELY nothing is found, revert it to default notestyle sound if (!Assets.exists(Paths.sound(soundPath))) { if (!isPixel) soundPath = basePath + Constants.DEFAULT_NOTE_STYLE + '/intro$step'; diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx index 2bd2bf4db..97e1d291d 100644 --- a/source/funkin/play/components/PopUpStuff.hx +++ b/source/funkin/play/components/PopUpStuff.hx @@ -23,24 +23,41 @@ class PopUpStuff extends FlxTypedGroup */ static var noteStyle:NoteStyle; + static var fallbackNoteStyle:Null; + static var isPixel:Bool = false; override public function new() { super(); + fetchNoteStyle(); + } + + static function fetchNoteStyle():Void + { var fetchedNoteStyle:NoteStyle = NoteStyleRegistry.instance.fetchEntry(PlayState.instance.currentChart.noteStyle); if (fetchedNoteStyle == null) noteStyle = NoteStyleRegistry.instance.fetchDefault(); else noteStyle = fetchedNoteStyle; - if (noteStyle._data.assets.note.isPixel) isPixel = true; + fallbackNoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyle.getFallbackID()); + isPixel = false; } static function resolveGraphicPath(noteStyle:NoteStyle, index:String):Null { + fetchNoteStyle(); var basePath:String = 'ui/popup/'; - var spritePath:String = basePath + noteStyle.id + '/$index'; + + while (!Assets.exists(Paths.image(spritePath)) && fallbackNoteStyle != null) + { + noteStyle = fallbackNoteStyle; + fallbackNoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyle.getFallbackID()); + spritePath = basePath + noteStyle.id + '/$index'; + } + if (noteStyle.isHoldNotePixel()) isPixel = true; + // If nothing is found, revert it to default notestyle skin if (!Assets.exists(Paths.image(spritePath))) { diff --git a/source/funkin/play/notes/notestyle/NoteStyle.hx b/source/funkin/play/notes/notestyle/NoteStyle.hx index 3993cce52..5a877aa5b 100644 --- a/source/funkin/play/notes/notestyle/NoteStyle.hx +++ b/source/funkin/play/notes/notestyle/NoteStyle.hx @@ -72,7 +72,7 @@ class NoteStyle implements IRegistryEntry * Get the note style ID of the parent note style. * @return The string ID, or `null` if there is no parent. */ - function getFallbackID():Null + public function getFallbackID():Null { return _data.fallback; } From d07564cdc234a39daaa4aebc8ec9b69d4bf2eaf0 Mon Sep 17 00:00:00 2001 From: anysad Date: Thu, 18 Jul 2024 17:56:54 +0300 Subject: [PATCH 550/870] hopefully final polish? --- source/funkin/play/Countdown.hx | 29 ++++++++------------- source/funkin/play/components/PopUpStuff.hx | 10 +++---- 2 files changed, 15 insertions(+), 24 deletions(-) diff --git a/source/funkin/play/Countdown.hx b/source/funkin/play/Countdown.hx index a8bf1b500..47d6faa9c 100644 --- a/source/funkin/play/Countdown.hx +++ b/source/funkin/play/Countdown.hx @@ -71,8 +71,6 @@ class Countdown // @:privateAccess // PlayState.instance.dispatchEvent(new SongTimeScriptEvent(SONG_BEAT_HIT, 0, 0)); - fetchNoteStyle(); - // The timer function gets called based on the beat of the song. countdownTimer = new FlxTimer(); @@ -90,10 +88,10 @@ class Countdown // PlayState.instance.dispatchEvent(new SongTimeScriptEvent(SONG_BEAT_HIT, 0, 0)); // Countdown graphic. - showCountdownGraphic(countdownStep, noteStyle); + showCountdownGraphic(countdownStep); // Countdown sound. - playCountdownSound(countdownStep, noteStyle); + playCountdownSound(countdownStep); // Event handling bullshit. var cancelled:Bool = propagateCountdownEvent(countdownStep); @@ -223,7 +221,7 @@ class Countdown /** * Retrieves the graphic to use for this step of the countdown. */ - public static function showCountdownGraphic(index:CountdownStep, noteStyle:NoteStyle):Void + public static function showCountdownGraphic(index:CountdownStep):Void { var indexString:String = null; switch (index) @@ -240,7 +238,7 @@ class Countdown if (indexString == null) return; var spritePath:String = null; - spritePath = resolveGraphicPath(noteStyle, indexString); + spritePath = resolveGraphicPath(indexString); if (spritePath == null) return; @@ -259,26 +257,21 @@ class Countdown countdownSprite.cameras = [PlayState.instance.camHUD]; countdownSprite.updateHitbox(); - countdownSprite.screenCenter(); // Fade sprite in, then out, then destroy it. - FlxTween.tween(countdownSprite, {y: countdownSprite.y += 100}, Conductor.instance.beatLengthMs / 1000, + FlxTween.tween(countdownSprite, {alpha: 0}, Conductor.instance.beatLengthMs / 1000, { - ease: FlxEase.cubeInOut, + ease: fadeEase, onComplete: function(twn:FlxTween) { countdownSprite.destroy(); } }); - FlxTween.tween(countdownSprite, {alpha: 0}, Conductor.instance.beatLengthMs / 1000, - { - ease: fadeEase - }); - PlayState.instance.add(countdownSprite); + countdownSprite.screenCenter(); } - static function resolveGraphicPath(noteStyle:NoteStyle, index:String):Null + static function resolveGraphicPath(index:String):Null { fetchNoteStyle(); var basePath:String = 'ui/countdown/'; @@ -307,12 +300,12 @@ class Countdown /** * Retrieves the sound file to use for this step of the countdown. */ - public static function playCountdownSound(step:CountdownStep, noteStyle:NoteStyle):Void + public static function playCountdownSound(step:CountdownStep):Void { - return FunkinSound.playOnce(Paths.sound(resolveSoundPath(noteStyle, step)), Constants.COUNTDOWN_VOLUME); + return FunkinSound.playOnce(Paths.sound(resolveSoundPath(step)), Constants.COUNTDOWN_VOLUME); } - static function resolveSoundPath(noteStyle:NoteStyle, step:CountdownStep):Null + static function resolveSoundPath(step:CountdownStep):Null { if (step == CountdownStep.BEFORE || step == CountdownStep.AFTER) return null; fetchNoteStyle(); diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx index 97e1d291d..b9479ec8b 100644 --- a/source/funkin/play/components/PopUpStuff.hx +++ b/source/funkin/play/components/PopUpStuff.hx @@ -30,8 +30,6 @@ class PopUpStuff extends FlxTypedGroup override public function new() { super(); - - fetchNoteStyle(); } static function fetchNoteStyle():Void @@ -44,7 +42,7 @@ class PopUpStuff extends FlxTypedGroup isPixel = false; } - static function resolveGraphicPath(noteStyle:NoteStyle, index:String):Null + static function resolveGraphicPath(index:String):Null { fetchNoteStyle(); var basePath:String = 'ui/popup/'; @@ -75,7 +73,7 @@ class PopUpStuff extends FlxTypedGroup if (daRating == null) daRating = "good"; - var ratingPath:String = resolveGraphicPath(noteStyle, daRating); + var ratingPath:String = resolveGraphicPath(daRating); // if (PlayState.instance.currentStageId.startsWith('school')) ratingPath = "weeb/pixelUI/" + ratingPath + "-pixel"; @@ -131,7 +129,7 @@ class PopUpStuff extends FlxTypedGroup if (combo == null) combo = 0; - var comboPath:String = resolveGraphicPath(noteStyle, 'combo'); + var comboPath:String = resolveGraphicPath('combo'); var comboSpr:FunkinSprite = FunkinSprite.create(comboPath); comboSpr.y = (FlxG.camera.height * 0.44) + offsets[1]; comboSpr.x = (FlxG.width * 0.507) + offsets[0]; @@ -186,7 +184,7 @@ class PopUpStuff extends FlxTypedGroup var daLoop:Int = 1; for (i in seperatedScore) { - var numScore:FunkinSprite = FunkinSprite.create(0, comboSpr.y, resolveGraphicPath(noteStyle, 'num' + Std.int(i))); + var numScore:FunkinSprite = FunkinSprite.create(0, comboSpr.y, resolveGraphicPath('num' + Std.int(i))); if (graphicSuffix.toLowerCase().contains('pixel')) { From 41bd0246ac31bf9b1195b4c317e1f3ea36ae94bb Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sun, 28 Jul 2024 17:10:32 -0400 Subject: [PATCH 551/870] Custom coutndown, judgements, and combo count now use the note style file instead of hardcoded paths. --- assets | 2 +- source/funkin/data/BaseRegistry.hx | 2 +- source/funkin/data/notestyle/CHANGELOG.md | 31 + source/funkin/data/notestyle/NoteStyleData.hx | 88 ++- .../data/notestyle/NoteStyleRegistry.hx | 4 +- source/funkin/play/Countdown.hx | 119 +-- source/funkin/play/PlayState.hx | 23 +- source/funkin/play/components/PopUpStuff.hx | 186 +---- source/funkin/play/notes/StrumlineNote.hx | 7 + .../funkin/play/notes/notestyle/NoteStyle.hx | 712 ++++++++++++++++-- .../components/ChartEditorHoldNoteSprite.hx | 4 +- 11 files changed, 840 insertions(+), 338 deletions(-) create mode 100644 source/funkin/data/notestyle/CHANGELOG.md diff --git a/assets b/assets index 3a9e05108..c4bd52818 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 3a9e0510841533f96228609dcd50f2515443bb90 +Subproject commit c4bd5281880ac2a1e26016c1219824d2f4247536 diff --git a/source/funkin/data/BaseRegistry.hx b/source/funkin/data/BaseRegistry.hx index 118516bec..83413ad00 100644 --- a/source/funkin/data/BaseRegistry.hx +++ b/source/funkin/data/BaseRegistry.hx @@ -263,7 +263,7 @@ abstract class BaseRegistry & Constructible + public function parseEntryDataWithMigration(id:String, version:Null):Null { if (version == null) { diff --git a/source/funkin/data/notestyle/CHANGELOG.md b/source/funkin/data/notestyle/CHANGELOG.md new file mode 100644 index 000000000..d85c11cad --- /dev/null +++ b/source/funkin/data/notestyle/CHANGELOG.md @@ -0,0 +1,31 @@ +# Note Style Data Schema Changelog + +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). + +## [1.1.0] +### Added +- Added several new `assets`: + - `countdownThree` + - `countdownTwo` + - `countdownOne` + - `countdownGo` + - `judgementSick` + - `judgementGood` + - `judgementBad` + - `judgementShit` + - `comboNumber0` + - `comboNumber1` + - `comboNumber2` + - `comboNumber3` + - `comboNumber4` + - `comboNumber5` + - `comboNumber6` + - `comboNumber7` + - `comboNumber8` + - `comboNumber9` + +## [1.0.0] +Initial version. diff --git a/source/funkin/data/notestyle/NoteStyleData.hx b/source/funkin/data/notestyle/NoteStyleData.hx index fcdb3b4f9..39162b896 100644 --- a/source/funkin/data/notestyle/NoteStyleData.hx +++ b/source/funkin/data/notestyle/NoteStyleData.hx @@ -74,6 +74,84 @@ typedef NoteStyleAssetsData = */ @:optional var holdNoteCover:NoteStyleAssetData; + + /** + * The THREE sound (and an optional pre-READY graphic). + */ + @:optional + var countdownThree:NoteStyleAssetData; + + /** + * The TWO sound and READY graphic. + */ + @:optional + var countdownTwo:NoteStyleAssetData; + + /** + * The ONE sound and SET graphic. + */ + @:optional + var countdownOne:NoteStyleAssetData; + + /** + * The GO sound and GO! graphic. + */ + @:optional + var countdownGo:NoteStyleAssetData; + + /** + * The SICK! judgement. + */ + @:optional + var judgementSick:NoteStyleAssetData; + + /** + * The GOOD! judgement. + */ + @:optional + var judgementGood:NoteStyleAssetData; + + /** + * The BAD! judgement. + */ + @:optional + var judgementBad:NoteStyleAssetData; + + /** + * The SHIT! judgement. + */ + @:optional + var judgementShit:NoteStyleAssetData; + + @:optional + var comboNumber0:NoteStyleAssetData; + + @:optional + var comboNumber1:NoteStyleAssetData; + + @:optional + var comboNumber2:NoteStyleAssetData; + + @:optional + var comboNumber3:NoteStyleAssetData; + + @:optional + var comboNumber4:NoteStyleAssetData; + + @:optional + var comboNumber5:NoteStyleAssetData; + + @:optional + var comboNumber6:NoteStyleAssetData; + + @:optional + var comboNumber7:NoteStyleAssetData; + + @:optional + var comboNumber8:NoteStyleAssetData; + + @:optional + var comboNumber9:NoteStyleAssetData; } /** @@ -120,7 +198,8 @@ typedef NoteStyleAssetData = /** * The structure of this data depends on the asset. */ - var data:T; + @:optional + var data:Null; } typedef NoteStyleData_Note = @@ -131,7 +210,14 @@ typedef NoteStyleData_Note = var right:UnnamedAnimationData; } +typedef NoteStyleData_Countdown = +{ + var audioPath:String; +} + typedef NoteStyleData_HoldNote = {} +typedef NoteStyleData_Judgement = {} +typedef NoteStyleData_ComboNum = {} /** * Data on animations for each direction of the strumline. diff --git a/source/funkin/data/notestyle/NoteStyleRegistry.hx b/source/funkin/data/notestyle/NoteStyleRegistry.hx index 5e9fa9a3d..36d1b9200 100644 --- a/source/funkin/data/notestyle/NoteStyleRegistry.hx +++ b/source/funkin/data/notestyle/NoteStyleRegistry.hx @@ -11,9 +11,9 @@ class NoteStyleRegistry extends BaseRegistry * Handle breaking changes by incrementing this value * and adding migration to the `migrateNoteStyleData()` function. */ - public static final NOTE_STYLE_DATA_VERSION:thx.semver.Version = "1.0.0"; + public static final NOTE_STYLE_DATA_VERSION:thx.semver.Version = "1.1.0"; - public static final NOTE_STYLE_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x"; + public static final NOTE_STYLE_DATA_VERSION_RULE:thx.semver.VersionRule = "1.1.x"; public static var instance(get, never):NoteStyleRegistry; static var _instance:Null = null; diff --git a/source/funkin/play/Countdown.hx b/source/funkin/play/Countdown.hx index 47d6faa9c..643883a43 100644 --- a/source/funkin/play/Countdown.hx +++ b/source/funkin/play/Countdown.hx @@ -40,8 +40,6 @@ class Countdown static var fallbackNoteStyle:Null; - static var isPixel:Bool = false; - /** * The currently running countdown. This will be null if there is no countdown running. */ @@ -204,18 +202,22 @@ class Countdown */ public static function reset() { - noteStyle = NoteStyleRegistry.instance.fetchDefault(); - isPixel = false; + noteStyle = null; } - static function fetchNoteStyle():Void + /** + * Retrieve the note style data (if we haven't already) + * @param noteStyleId The id of the note style to fetch. Defaults to the one used by the current PlayState. + * @param force Fetch the note style from the registry even if we've already fetched it. + */ + static function fetchNoteStyle(?noteStyleId:String, force:Bool = false):Void { - var fetchedNoteStyle:NoteStyle = NoteStyleRegistry.instance.fetchEntry(PlayState.instance.currentChart.noteStyle); - if (fetchedNoteStyle == null) noteStyle = NoteStyleRegistry.instance.fetchDefault(); - else - noteStyle = fetchedNoteStyle; - fallbackNoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyle.getFallbackID()); - isPixel = false; + if (noteStyle != null && !force) return; + + if (noteStyleId == null) noteStyleId = PlayState.instance?.currentChart?.noteStyle; + + noteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyleId); + if (noteStyle == null) noteStyle = NoteStyleRegistry.instance.fetchDefault(); } /** @@ -223,40 +225,13 @@ class Countdown */ public static function showCountdownGraphic(index:CountdownStep):Void { - var indexString:String = null; - switch (index) - { - case TWO: - indexString = 'ready'; - case ONE: - indexString = 'set'; - case GO: - indexString = 'go'; - default: - // null - } - if (indexString == null) return; + fetchNoteStyle(); - var spritePath:String = null; - spritePath = resolveGraphicPath(indexString); - - if (spritePath == null) return; - - var countdownSprite:FunkinSprite = FunkinSprite.create(spritePath); - countdownSprite.scrollFactor.set(0, 0); - - if (isGraphicPixel) countdownSprite.setGraphicSize(Std.int(countdownSprite.width * Constants.PIXEL_ART_SCALE)); - else - countdownSprite.setGraphicSize(Std.int(countdownSprite.width * 0.7)); + var countdownSprite = noteStyle.buildCountdownSprite(index); + if (countdownSprite == null) return; var fadeEase = FlxEase.cubeInOut; - if (isGraphicPixel) fadeEase = EaseUtil.stepped(8); - - countdownSprite.antialiasing = !isPixel; - - countdownSprite.cameras = [PlayState.instance.camHUD]; - - countdownSprite.updateHitbox(); + if (noteStyle.isCountdownSpritePixel(index)) fadeEase = EaseUtil.stepped(8); // Fade sprite in, then out, then destroy it. FlxTween.tween(countdownSprite, {alpha: 0}, Conductor.instance.beatLengthMs / 1000, @@ -267,69 +242,25 @@ class Countdown } }); + countdownSprite.cameras = [PlayState.instance.camHUD]; PlayState.instance.add(countdownSprite); countdownSprite.screenCenter(); - } - static function resolveGraphicPath(index:String):Null - { - fetchNoteStyle(); - var basePath:String = 'ui/countdown/'; - var spritePath:String = basePath + noteStyle.id + '/$index'; - - while (!Assets.exists(Paths.image(spritePath)) && fallbackNoteStyle != null) - { - noteStyle = fallbackNoteStyle; - fallbackNoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyle.getFallbackID()); - spritePath = basePath + noteStyle.id + '/$index'; - } - if (noteStyle.isHoldNotePixel()) isPixel = true; - - // If ABSOLUTELY nothing is found, revert it to default notestyle skin - if (!Assets.exists(Paths.image(spritePath))) - { - if (!isPixel) spritePath = basePath + Constants.DEFAULT_NOTE_STYLE + '/$index'; - else - spritePath = basePath + Constants.DEFAULT_PIXEL_NOTE_STYLE + '/$index'; - } - - trace('Resolved sprite path: ' + Paths.image(spritePath)); - return spritePath; + var offsets = noteStyle.getCountdownSpriteOffsets(index); + countdownSprite.x += offsets[0]; + countdownSprite.y += offsets[1]; } /** * Retrieves the sound file to use for this step of the countdown. */ - public static function playCountdownSound(step:CountdownStep):Void + public static function playCountdownSound(step:CountdownStep):FunkinSound { - return FunkinSound.playOnce(Paths.sound(resolveSoundPath(step)), Constants.COUNTDOWN_VOLUME); - } - - static function resolveSoundPath(step:CountdownStep):Null - { - if (step == CountdownStep.BEFORE || step == CountdownStep.AFTER) return null; fetchNoteStyle(); - var basePath:String = 'gameplay/countdown/'; - var soundPath:String = basePath + noteStyle.id + '/intro$step'; + var path = noteStyle.getCountdownSoundPath(step); + if (path == null) return null; - while (!Assets.exists(Paths.sound(soundPath)) && fallbackNoteStyle != null) - { - noteStyle = fallbackNoteStyle; - fallbackNoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyle.getFallbackID()); - soundPath = basePath + noteStyle.id + '/intro$step'; - } - if (noteStyle.isHoldNotePixel()) isPixel = true; - - // If ABSOLUTELY nothing is found, revert it to default notestyle sound - if (!Assets.exists(Paths.sound(soundPath))) - { - if (!isPixel) soundPath = basePath + Constants.DEFAULT_NOTE_STYLE + '/intro$step'; - else - soundPath = basePath + Constants.DEFAULT_PIXEL_NOTE_STYLE + '/intro$step'; - } - - trace('Resolved sound path: ' + soundPath); - return soundPath; + return FunkinSound.playOnce(path, Constants.COUNTDOWN_VOLUME); } public static function decrement(step:CountdownStep):CountdownStep diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 384c28056..3fd68efe9 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -694,12 +694,7 @@ class PlayState extends MusicBeatSubState initMinimalMode(); } initStrumlines(); - - // Initialize the judgements and combo meter. - comboPopUps = new PopUpStuff(); - comboPopUps.zIndex = 900; - add(comboPopUps); - comboPopUps.cameras = [camHUD]; + initPopups(); #if discord_rpc // Initialize Discord Rich Presence. @@ -1727,6 +1722,21 @@ class PlayState extends MusicBeatSubState opponentStrumline.fadeInArrows(); } + /** + * Configures the judgement and combo popups. + */ + function initPopups():Void + { + var noteStyleId:String = currentChart.noteStyle; + var noteStyle:NoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyleId); + if (noteStyle == null) noteStyle = NoteStyleRegistry.instance.fetchDefault(); + // Initialize the judgements and combo meter. + comboPopUps = new PopUpStuff(noteStyle); + comboPopUps.zIndex = 900; + add(comboPopUps); + comboPopUps.cameras = [camHUD]; + } + /** * Initializes the Discord Rich Presence. */ @@ -3005,7 +3015,6 @@ class PlayState extends MusicBeatSubState GameOverSubState.reset(); PauseSubState.reset(); Countdown.reset(); - PopUpStuff.reset(); // Clear the static reference to this state. instance = null; diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx index b9479ec8b..911c3578c 100644 --- a/source/funkin/play/components/PopUpStuff.hx +++ b/source/funkin/play/components/PopUpStuff.hx @@ -12,103 +12,47 @@ import openfl.utils.Assets; import funkin.data.notestyle.NoteStyleRegistry; import funkin.play.notes.notestyle.NoteStyle; +@:nullSafety class PopUpStuff extends FlxTypedGroup { - public var offsets:Array = [0, 0]; - /** - * Which alternate graphic on popup to use. - * This is set via the current notestyle. - * For example, in Week 6 it is `pixel`. + * The current note style to use. This determines which graphics to display. + * For example, Week 6 uses the `pixel` note style, and mods can create their own. */ - static var noteStyle:NoteStyle; + var noteStyle:NoteStyle; - static var fallbackNoteStyle:Null; - - static var isPixel:Bool = false; - - override public function new() + override public function new(noteStyle:NoteStyle) { super(); + + this.noteStyle = noteStyle; } - static function fetchNoteStyle():Void + public function displayRating(daRating:Null) { - var fetchedNoteStyle:NoteStyle = NoteStyleRegistry.instance.fetchEntry(PlayState.instance.currentChart.noteStyle); - if (fetchedNoteStyle == null) noteStyle = NoteStyleRegistry.instance.fetchDefault(); - else - noteStyle = fetchedNoteStyle; - fallbackNoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyle.getFallbackID()); - isPixel = false; - } - - static function resolveGraphicPath(index:String):Null - { - fetchNoteStyle(); - var basePath:String = 'ui/popup/'; - var spritePath:String = basePath + noteStyle.id + '/$index'; - - while (!Assets.exists(Paths.image(spritePath)) && fallbackNoteStyle != null) - { - noteStyle = fallbackNoteStyle; - fallbackNoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyle.getFallbackID()); - spritePath = basePath + noteStyle.id + '/$index'; - } - if (noteStyle.isHoldNotePixel()) isPixel = true; - - // If nothing is found, revert it to default notestyle skin - if (!Assets.exists(Paths.image(spritePath))) - { - if (!isPixel) spritePath = basePath + Constants.DEFAULT_NOTE_STYLE + '/$index'; - else - spritePath = basePath + Constants.DEFAULT_PIXEL_NOTE_STYLE + '/$index'; - } - - return spritePath; - } - - public function displayRating(daRating:String) - { - var perfStart:Float = TimerUtil.start(); - if (daRating == null) daRating = "good"; - var ratingPath:String = resolveGraphicPath(daRating); - - // if (PlayState.instance.currentStageId.startsWith('school')) ratingPath = "weeb/pixelUI/" + ratingPath + "-pixel"; - - var rating:FunkinSprite = FunkinSprite.create(0, 0, ratingPath); - rating.scrollFactor.set(0.2, 0.2); + var rating:Null = noteStyle.buildJudgementSprite(daRating); + if (rating == null) return; rating.zIndex = 1000; - rating.x = (FlxG.width * 0.474) + offsets[0]; - // rating.x -= FlxG.camera.scroll.x * 0.2; - rating.y = (FlxG.camera.height * 0.45 - 60) + offsets[1]; + + rating.x = (FlxG.width * 0.474); + rating.x -= rating.width / 2; + rating.y = (FlxG.camera.height * 0.45 - 60); + rating.y -= rating.height / 2; + + var offsets = noteStyle.getJudgementSpriteOffsets(daRating); + rating.x += offsets[0]; + rating.y += offsets[1]; + rating.acceleration.y = 550; rating.velocity.y -= FlxG.random.int(140, 175); rating.velocity.x -= FlxG.random.int(0, 10); add(rating); - var fadeEase = null; - - if (isPixel) - { - rating.setGraphicSize(Std.int(rating.width * Constants.PIXEL_ART_SCALE * 0.7)); - rating.antialiasing = false; - rating.pixelPerfectRender = true; - rating.pixelPerfectPosition = true; - fadeEase = EaseUtil.stepped(2); - } - else - { - rating.setGraphicSize(Std.int(rating.width * 0.65)); - rating.antialiasing = true; - } - rating.updateHitbox(); - - rating.x -= rating.width / 2; - rating.y -= rating.height / 2; + var fadeEase = noteStyle.isJudgementSpritePixel(daRating) ? EaseUtil.stepped(2) : null; FlxTween.tween(rating, {alpha: 0}, 0.2, { @@ -119,55 +63,10 @@ class PopUpStuff extends FlxTypedGroup startDelay: Conductor.instance.beatLengthMs * 0.001, ease: fadeEase }); - - trace('displayRating took: ${TimerUtil.seconds(perfStart)}'); } - public function displayCombo(?combo:Int = 0):Int + public function displayCombo(combo:Int = 0):Void { - var perfStart:Float = TimerUtil.start(); - - if (combo == null) combo = 0; - - var comboPath:String = resolveGraphicPath('combo'); - var comboSpr:FunkinSprite = FunkinSprite.create(comboPath); - comboSpr.y = (FlxG.camera.height * 0.44) + offsets[1]; - comboSpr.x = (FlxG.width * 0.507) + offsets[0]; - // comboSpr.x -= FlxG.camera.scroll.x * 0.2; - - comboSpr.acceleration.y = 600; - comboSpr.velocity.y -= 150; - comboSpr.velocity.x += FlxG.random.int(1, 10); - - // add(comboSpr); - - var fadeEase = null; - - if (graphicSuffix.toLowerCase().contains('pixel')) - { - comboSpr.setGraphicSize(Std.int(comboSpr.width * Constants.PIXEL_ART_SCALE * 1)); - comboSpr.antialiasing = false; - comboSpr.pixelPerfectRender = true; - comboSpr.pixelPerfectPosition = true; - fadeEase = EaseUtil.stepped(2); - } - else - { - comboSpr.setGraphicSize(Std.int(comboSpr.width * 0.7)); - comboSpr.antialiasing = true; - } - comboSpr.updateHitbox(); - - FlxTween.tween(comboSpr, {alpha: 0}, 0.2, - { - onComplete: function(tween:FlxTween) { - remove(comboSpr, true); - comboSpr.destroy(); - }, - startDelay: Conductor.instance.beatLengthMs * 0.001, - ease: fadeEase - }); - var seperatedScore:Array = []; var tempCombo:Int = combo; @@ -182,31 +81,27 @@ class PopUpStuff extends FlxTypedGroup // seperatedScore.reverse(); var daLoop:Int = 1; - for (i in seperatedScore) + for (digit in seperatedScore) { - var numScore:FunkinSprite = FunkinSprite.create(0, comboSpr.y, resolveGraphicPath('num' + Std.int(i))); + var numScore:Null = noteStyle.buildComboNumSprite(digit); + if (numScore == null) continue; - if (graphicSuffix.toLowerCase().contains('pixel')) - { - numScore.setGraphicSize(Std.int(numScore.width * Constants.PIXEL_ART_SCALE * 1)); - numScore.antialiasing = false; - numScore.pixelPerfectRender = true; - numScore.pixelPerfectPosition = true; - } - else - { - numScore.setGraphicSize(Std.int(numScore.width * 0.45)); - numScore.antialiasing = true; - } - numScore.updateHitbox(); + numScore.x = (FlxG.width * 0.507) - (36 * daLoop) - 65; + trace('numScore($daLoop) = ${numScore.x}'); + numScore.y = (FlxG.camera.height * 0.44); + + var offsets = noteStyle.getComboNumSpriteOffsets(digit); + numScore.x += offsets[0]; + numScore.y += offsets[1]; - numScore.x = comboSpr.x - (36 * daLoop) - 65; //- 90; numScore.acceleration.y = FlxG.random.int(250, 300); numScore.velocity.y -= FlxG.random.int(130, 150); numScore.velocity.x = FlxG.random.float(-5, 5); add(numScore); + var fadeEase = noteStyle.isComboNumSpritePixel(digit) ? EaseUtil.stepped(2) : null; + FlxTween.tween(numScore, {alpha: 0}, 0.2, { onComplete: function(tween:FlxTween) { @@ -219,18 +114,5 @@ class PopUpStuff extends FlxTypedGroup daLoop++; } - - trace('displayCombo took: ${TimerUtil.seconds(perfStart)}'); - - return combo; - } - - /** - * Reset the popup configuration to the default. - */ - public static function reset() - { - noteStyle = NoteStyleRegistry.instance.fetchDefault(); - isPixel = false; } } diff --git a/source/funkin/play/notes/StrumlineNote.hx b/source/funkin/play/notes/StrumlineNote.hx index 40d893255..d8230aa28 100644 --- a/source/funkin/play/notes/StrumlineNote.hx +++ b/source/funkin/play/notes/StrumlineNote.hx @@ -75,6 +75,13 @@ class StrumlineNote extends FlxSprite function setup(noteStyle:NoteStyle):Void { + if (noteStyle == null) + { + // If you get an exception on this line, check the debug console. + // You probably have a parsing error in your note style's JSON file. + throw "FATAL ERROR: Attempted to initialize PlayState with an invalid NoteStyle."; + } + noteStyle.applyStrumlineFrames(this); noteStyle.applyStrumlineAnimations(this, this.direction); diff --git a/source/funkin/play/notes/notestyle/NoteStyle.hx b/source/funkin/play/notes/notestyle/NoteStyle.hx index 5a877aa5b..ee07703f1 100644 --- a/source/funkin/play/notes/notestyle/NoteStyle.hx +++ b/source/funkin/play/notes/notestyle/NoteStyle.hx @@ -1,5 +1,6 @@ package funkin.play.notes.notestyle; +import funkin.play.Countdown; import flixel.graphics.frames.FlxAtlasFrames; import flixel.graphics.frames.FlxFramesCollection; import funkin.data.animation.AnimationData; @@ -16,6 +17,7 @@ using funkin.data.animation.AnimationData.AnimationDataUtil; * Holds the data for what assets to use for a note style, * and provides convenience methods for building sprites based on them. */ +@:nullSafety class NoteStyle implements IRegistryEntry { /** @@ -42,12 +44,8 @@ class NoteStyle implements IRegistryEntry this.id = id; _data = _fetchData(id); - if (_data == null) - { - throw 'Could not parse note style data for id: $id'; - } - - this.fallback = NoteStyleRegistry.instance.fetchEntry(getFallbackID()); + var fallbackID = _data.fallback; + if (fallbackID != null) this.fallback = NoteStyleRegistry.instance.fetchEntry(fallbackID); } /** @@ -80,7 +78,7 @@ class NoteStyle implements IRegistryEntry public function buildNoteSprite(target:NoteSprite):Void { // Apply the note sprite frames. - var atlas:FlxAtlasFrames = buildNoteFrames(false); + var atlas:Null = buildNoteFrames(false); if (atlas == null) { @@ -89,7 +87,7 @@ class NoteStyle implements IRegistryEntry target.frames = atlas; - target.antialiasing = !_data.assets.note.isPixel; + target.antialiasing = !(_data.assets?.note?.isPixel ?? false); // Apply the animations. buildNoteAnimations(target); @@ -99,21 +97,30 @@ class NoteStyle implements IRegistryEntry target.updateHitbox(); } - var noteFrames:FlxAtlasFrames = null; + var noteFrames:Null = null; - function buildNoteFrames(force:Bool = false):FlxAtlasFrames + function buildNoteFrames(force:Bool = false):Null { - if (!FunkinSprite.isTextureCached(Paths.image(getNoteAssetPath()))) + var noteAssetPath = getNoteAssetPath(); + if (noteAssetPath == null) return null; + + if (!FunkinSprite.isTextureCached(Paths.image(noteAssetPath))) { - FlxG.log.warn('Note texture is not cached: ${getNoteAssetPath()}'); + FlxG.log.warn('Note texture is not cached: ${noteAssetPath}'); } // Purge the note frames if the cached atlas is invalid. - if (noteFrames?.parent?.isDestroyed ?? false) noteFrames = null; + @:nullSafety(Off) + { + if (noteFrames?.parent?.isDestroyed ?? false) noteFrames = null; + } if (noteFrames != null && !force) return noteFrames; - noteFrames = Paths.getSparrowAtlas(getNoteAssetPath(), getNoteAssetLibrary()); + var noteAssetPath = getNoteAssetPath(); + if (noteAssetPath == null) return null; + + noteFrames = Paths.getSparrowAtlas(noteAssetPath, getNoteAssetLibrary()); if (noteFrames == null) { @@ -123,17 +130,18 @@ class NoteStyle implements IRegistryEntry return noteFrames; } - function getNoteAssetPath(raw:Bool = false):String + function getNoteAssetPath(raw:Bool = false):Null { if (raw) { var rawPath:Null = _data?.assets?.note?.assetPath; - if (rawPath == null) return fallback.getNoteAssetPath(true); + if (rawPath == null && fallback != null) return fallback.getNoteAssetPath(true); return rawPath; } // library:path - var parts = getNoteAssetPath(true).split(Constants.LIBRARY_SEPARATOR); + var parts = getNoteAssetPath(true)?.split(Constants.LIBRARY_SEPARATOR) ?? []; + if (parts.length == 0) return null; if (parts.length == 1) return getNoteAssetPath(true); return parts[1]; } @@ -141,57 +149,63 @@ class NoteStyle implements IRegistryEntry function getNoteAssetLibrary():Null { // library:path - var parts = getNoteAssetPath(true).split(Constants.LIBRARY_SEPARATOR); + var parts = getNoteAssetPath(true)?.split(Constants.LIBRARY_SEPARATOR) ?? []; + if (parts.length == 0) return null; if (parts.length == 1) return null; return parts[0]; } function buildNoteAnimations(target:NoteSprite):Void { - var leftData:AnimationData = fetchNoteAnimationData(LEFT); - target.animation.addByPrefix('purpleScroll', leftData.prefix, leftData.frameRate, leftData.looped, leftData.flipX, leftData.flipY); - var downData:AnimationData = fetchNoteAnimationData(DOWN); - target.animation.addByPrefix('blueScroll', downData.prefix, downData.frameRate, downData.looped, downData.flipX, downData.flipY); - var upData:AnimationData = fetchNoteAnimationData(UP); - target.animation.addByPrefix('greenScroll', upData.prefix, upData.frameRate, upData.looped, upData.flipX, upData.flipY); - var rightData:AnimationData = fetchNoteAnimationData(RIGHT); - target.animation.addByPrefix('redScroll', rightData.prefix, rightData.frameRate, rightData.looped, rightData.flipX, rightData.flipY); + var leftData:Null = fetchNoteAnimationData(LEFT); + if (leftData != null) target.animation.addByPrefix('purpleScroll', leftData.prefix ?? '', leftData.frameRate ?? 24, leftData.looped ?? false, + leftData.flipX, leftData.flipY); + var downData:Null = fetchNoteAnimationData(DOWN); + if (downData != null) target.animation.addByPrefix('blueScroll', downData.prefix ?? '', downData.frameRate ?? 24, downData.looped ?? false, + downData.flipX, downData.flipY); + var upData:Null = fetchNoteAnimationData(UP); + if (upData != null) target.animation.addByPrefix('greenScroll', upData.prefix ?? '', upData.frameRate ?? 24, upData.looped ?? false, upData.flipX, + upData.flipY); + var rightData:Null = fetchNoteAnimationData(RIGHT); + if (rightData != null) target.animation.addByPrefix('redScroll', rightData.prefix ?? '', rightData.frameRate ?? 24, rightData.looped ?? false, + rightData.flipX, rightData.flipY); } public function isNoteAnimated():Bool { - return _data.assets.note.animated; + return _data.assets?.note?.animated ?? false; } public function getNoteScale():Float { - return _data.assets.note.scale; + return _data.assets?.note?.scale ?? 1.0; } - function fetchNoteAnimationData(dir:NoteDirection):AnimationData + function fetchNoteAnimationData(dir:NoteDirection):Null { var result:Null = switch (dir) { - case LEFT: _data.assets.note.data.left.toNamed(); - case DOWN: _data.assets.note.data.down.toNamed(); - case UP: _data.assets.note.data.up.toNamed(); - case RIGHT: _data.assets.note.data.right.toNamed(); + case LEFT: _data.assets?.note?.data?.left?.toNamed(); + case DOWN: _data.assets?.note?.data?.down?.toNamed(); + case UP: _data.assets?.note?.data?.up?.toNamed(); + case RIGHT: _data.assets?.note?.data?.right?.toNamed(); }; - return (result == null) ? fallback.fetchNoteAnimationData(dir) : result; + return (result == null && fallback != null) ? fallback.fetchNoteAnimationData(dir) : result; } - public function getHoldNoteAssetPath(raw:Bool = false):String + public function getHoldNoteAssetPath(raw:Bool = false):Null { if (raw) { // TODO: figure out why ?. didn't work here var rawPath:Null = (_data?.assets?.holdNote == null) ? null : _data?.assets?.holdNote?.assetPath; - return (rawPath == null) ? fallback.getHoldNoteAssetPath(true) : rawPath; + return (rawPath == null && fallback != null) ? fallback.getHoldNoteAssetPath(true) : rawPath; } // library:path - var parts = getHoldNoteAssetPath(true).split(Constants.LIBRARY_SEPARATOR); + var parts = getHoldNoteAssetPath(true)?.split(Constants.LIBRARY_SEPARATOR) ?? []; + if (parts.length == 0) return null; if (parts.length == 1) return Paths.image(parts[0]); return Paths.image(parts[1], parts[0]); } @@ -199,15 +213,15 @@ class NoteStyle implements IRegistryEntry public function isHoldNotePixel():Bool { var data = _data?.assets?.holdNote; - if (data == null) return fallback.isHoldNotePixel(); - return data.isPixel; + if (data == null && fallback != null) return fallback.isHoldNotePixel(); + return data?.isPixel ?? false; } public function fetchHoldNoteScale():Float { var data = _data?.assets?.holdNote; - if (data == null) return fallback.fetchHoldNoteScale(); - return data.scale; + if (data == null && fallback != null) return fallback.fetchHoldNoteScale(); + return data?.scale ?? 1.0; } public function applyStrumlineFrames(target:StrumlineNote):Void @@ -215,7 +229,7 @@ class NoteStyle implements IRegistryEntry // TODO: Add support for multi-Sparrow. // Will be less annoying after this is merged: https://github.com/HaxeFlixel/flixel/pull/2772 - var atlas:FlxAtlasFrames = Paths.getSparrowAtlas(getStrumlineAssetPath(), getStrumlineAssetLibrary()); + var atlas:FlxAtlasFrames = Paths.getSparrowAtlas(getStrumlineAssetPath() ?? '', getStrumlineAssetLibrary()); if (atlas == null) { @@ -224,31 +238,30 @@ class NoteStyle implements IRegistryEntry target.frames = atlas; - target.scale.x = _data.assets.noteStrumline.scale; - target.scale.y = _data.assets.noteStrumline.scale; - target.antialiasing = !_data.assets.noteStrumline.isPixel; + target.scale.set(_data.assets.noteStrumline?.scale ?? 1.0); + target.antialiasing = !(_data.assets.noteStrumline?.isPixel ?? false); } - function getStrumlineAssetPath(raw:Bool = false):String + function getStrumlineAssetPath(raw:Bool = false):Null { if (raw) { var rawPath:Null = _data?.assets?.noteStrumline?.assetPath; - if (rawPath == null) return fallback.getStrumlineAssetPath(true); + if (rawPath == null && fallback != null) return fallback.getStrumlineAssetPath(true); return rawPath; } // library:path - var parts = getStrumlineAssetPath(true).split(Constants.LIBRARY_SEPARATOR); - if (parts.length == 1) return getStrumlineAssetPath(true); + var parts = getStrumlineAssetPath(true)?.split(Constants.LIBRARY_SEPARATOR) ?? []; + if (parts.length <= 1) return getStrumlineAssetPath(true); return parts[1]; } function getStrumlineAssetLibrary():Null { // library:path - var parts = getStrumlineAssetPath(true).split(Constants.LIBRARY_SEPARATOR); - if (parts.length == 1) return null; + var parts = getStrumlineAssetPath(true)?.split(Constants.LIBRARY_SEPARATOR) ?? []; + if (parts.length <= 1) return null; return parts[0]; } @@ -259,60 +272,592 @@ class NoteStyle implements IRegistryEntry function getStrumlineAnimationData(dir:NoteDirection):Array { - var result:Array = switch (dir) + var result:Array> = switch (dir) { case NoteDirection.LEFT: [ - _data.assets.noteStrumline.data.leftStatic.toNamed('static'), - _data.assets.noteStrumline.data.leftPress.toNamed('press'), - _data.assets.noteStrumline.data.leftConfirm.toNamed('confirm'), - _data.assets.noteStrumline.data.leftConfirmHold.toNamed('confirm-hold'), + _data.assets.noteStrumline?.data?.leftStatic?.toNamed('static'), + _data.assets.noteStrumline?.data?.leftPress?.toNamed('press'), + _data.assets.noteStrumline?.data?.leftConfirm?.toNamed('confirm'), + _data.assets.noteStrumline?.data?.leftConfirmHold?.toNamed('confirm-hold'), ]; case NoteDirection.DOWN: [ - _data.assets.noteStrumline.data.downStatic.toNamed('static'), - _data.assets.noteStrumline.data.downPress.toNamed('press'), - _data.assets.noteStrumline.data.downConfirm.toNamed('confirm'), - _data.assets.noteStrumline.data.downConfirmHold.toNamed('confirm-hold'), + _data.assets.noteStrumline?.data?.downStatic?.toNamed('static'), + _data.assets.noteStrumline?.data?.downPress?.toNamed('press'), + _data.assets.noteStrumline?.data?.downConfirm?.toNamed('confirm'), + _data.assets.noteStrumline?.data?.downConfirmHold?.toNamed('confirm-hold'), ]; case NoteDirection.UP: [ - _data.assets.noteStrumline.data.upStatic.toNamed('static'), - _data.assets.noteStrumline.data.upPress.toNamed('press'), - _data.assets.noteStrumline.data.upConfirm.toNamed('confirm'), - _data.assets.noteStrumline.data.upConfirmHold.toNamed('confirm-hold'), + _data.assets.noteStrumline?.data?.upStatic?.toNamed('static'), + _data.assets.noteStrumline?.data?.upPress?.toNamed('press'), + _data.assets.noteStrumline?.data?.upConfirm?.toNamed('confirm'), + _data.assets.noteStrumline?.data?.upConfirmHold?.toNamed('confirm-hold'), ]; case NoteDirection.RIGHT: [ - _data.assets.noteStrumline.data.rightStatic.toNamed('static'), - _data.assets.noteStrumline.data.rightPress.toNamed('press'), - _data.assets.noteStrumline.data.rightConfirm.toNamed('confirm'), - _data.assets.noteStrumline.data.rightConfirmHold.toNamed('confirm-hold'), + _data.assets.noteStrumline?.data?.rightStatic?.toNamed('static'), + _data.assets.noteStrumline?.data?.rightPress?.toNamed('press'), + _data.assets.noteStrumline?.data?.rightConfirm?.toNamed('confirm'), + _data.assets.noteStrumline?.data?.rightConfirmHold?.toNamed('confirm-hold'), ]; + default: []; }; - return result; + return thx.Arrays.filterNull(result); } - public function applyStrumlineOffsets(target:StrumlineNote) + public function applyStrumlineOffsets(target:StrumlineNote):Void { - target.x += _data.assets.noteStrumline.offsets[0]; - target.y += _data.assets.noteStrumline.offsets[1]; + var offsets = _data?.assets?.noteStrumline?.offsets ?? [0.0, 0.0]; + target.x += offsets[0]; + target.y += offsets[1]; } public function getStrumlineScale():Float { - return _data.assets.noteStrumline.scale; + return _data?.assets?.noteStrumline?.scale ?? 1.0; } public function isNoteSplashEnabled():Bool { var data = _data?.assets?.noteSplash?.data; - if (data == null) return fallback.isNoteSplashEnabled(); - return data.enabled; + if (data == null) return fallback?.isNoteSplashEnabled() ?? false; + return data.enabled ?? false; } public function isHoldNoteCoverEnabled():Bool { var data = _data?.assets?.holdNoteCover?.data; - if (data == null) return fallback.isHoldNoteCoverEnabled(); - return data.enabled; + if (data == null) return fallback?.isHoldNoteCoverEnabled() ?? false; + return data.enabled ?? false; + } + + /** + * Build a sprite for the given step of the countdown. + * @param step + * @return A `FunkinSprite`, or `null` if no graphic is available for this step. + */ + public function buildCountdownSprite(step:Countdown.CountdownStep):Null + { + var result = new FunkinSprite(); + + switch (step) + { + case THREE: + if (_data.assets.countdownThree == null) return fallback?.buildCountdownSprite(step); + var assetPath = buildCountdownSpritePath(step); + if (assetPath == null) return null; + result.loadTexture(assetPath); + result.scale.x = _data.assets.countdownThree?.scale ?? 1.0; + result.scale.y = _data.assets.countdownThree?.scale ?? 1.0; + case TWO: + if (_data.assets.countdownTwo == null) return fallback?.buildCountdownSprite(step); + var assetPath = buildCountdownSpritePath(step); + if (assetPath == null) return null; + result.loadTexture(assetPath); + result.scale.x = _data.assets.countdownTwo?.scale ?? 1.0; + result.scale.y = _data.assets.countdownTwo?.scale ?? 1.0; + case ONE: + if (_data.assets.countdownOne == null) return fallback?.buildCountdownSprite(step); + var assetPath = buildCountdownSpritePath(step); + if (assetPath == null) return null; + result.loadTexture(assetPath); + result.scale.x = _data.assets.countdownOne?.scale ?? 1.0; + result.scale.y = _data.assets.countdownOne?.scale ?? 1.0; + case GO: + if (_data.assets.countdownGo == null) return fallback?.buildCountdownSprite(step); + var assetPath = buildCountdownSpritePath(step); + if (assetPath == null) return null; + result.loadTexture(assetPath); + result.scale.x = _data.assets.countdownGo?.scale ?? 1.0; + result.scale.y = _data.assets.countdownGo?.scale ?? 1.0; + default: + // TODO: Do something here? + return null; + } + + result.scrollFactor.set(0, 0); + result.antialiasing = !isCountdownSpritePixel(step); + result.updateHitbox(); + + return result; + } + + function buildCountdownSpritePath(step:Countdown.CountdownStep):Null + { + var basePath:Null = null; + switch (step) + { + case THREE: + basePath = _data.assets.countdownThree?.assetPath; + case TWO: + basePath = _data.assets.countdownTwo?.assetPath; + case ONE: + basePath = _data.assets.countdownOne?.assetPath; + case GO: + basePath = _data.assets.countdownGo?.assetPath; + default: + basePath = null; + } + + if (basePath == null) return fallback?.buildCountdownSpritePath(step); + + var parts = basePath?.split(Constants.LIBRARY_SEPARATOR) ?? []; + if (parts.length < 1) return null; + if (parts.length == 1) return parts[0]; + + return parts[1]; + } + + function buildCountdownSpriteLibrary(step:Countdown.CountdownStep):Null + { + var basePath:Null = null; + switch (step) + { + case THREE: + basePath = _data.assets.countdownThree?.assetPath; + case TWO: + basePath = _data.assets.countdownTwo?.assetPath; + case ONE: + basePath = _data.assets.countdownOne?.assetPath; + case GO: + basePath = _data.assets.countdownGo?.assetPath; + default: + basePath = null; + } + + if (basePath == null) return fallback?.buildCountdownSpriteLibrary(step); + + var parts = basePath?.split(Constants.LIBRARY_SEPARATOR) ?? []; + if (parts.length <= 1) return null; + + return parts[0]; + } + + public function isCountdownSpritePixel(step:Countdown.CountdownStep):Bool + { + switch (step) + { + case THREE: + var result = _data.assets.countdownThree?.isPixel; + if (result == null && fallback != null) result = fallback.isCountdownSpritePixel(step); + return result ?? false; + case TWO: + var result = _data.assets.countdownTwo?.isPixel; + if (result == null && fallback != null) result = fallback.isCountdownSpritePixel(step); + return result ?? false; + case ONE: + var result = _data.assets.countdownOne?.isPixel; + if (result == null && fallback != null) result = fallback.isCountdownSpritePixel(step); + return result ?? false; + case GO: + var result = _data.assets.countdownGo?.isPixel; + if (result == null && fallback != null) result = fallback.isCountdownSpritePixel(step); + return result ?? false; + default: + return false; + } + } + + public function getCountdownSpriteOffsets(step:Countdown.CountdownStep):Array + { + switch (step) + { + case THREE: + var result = _data.assets.countdownThree?.offsets; + if (result == null && fallback != null) result = fallback.getCountdownSpriteOffsets(step); + return result ?? [0, 0]; + case TWO: + var result = _data.assets.countdownTwo?.offsets; + if (result == null && fallback != null) result = fallback.getCountdownSpriteOffsets(step); + return result ?? [0, 0]; + case ONE: + var result = _data.assets.countdownOne?.offsets; + if (result == null && fallback != null) result = fallback.getCountdownSpriteOffsets(step); + return result ?? [0, 0]; + case GO: + var result = _data.assets.countdownGo?.offsets; + if (result == null && fallback != null) result = fallback.getCountdownSpriteOffsets(step); + return result ?? [0, 0]; + default: + return [0, 0]; + } + } + + public function getCountdownSoundPath(step:Countdown.CountdownStep, raw:Bool = false):Null + { + if (raw) + { + // TODO: figure out why ?. didn't work here + var rawPath:Null = switch (step) + { + case Countdown.CountdownStep.THREE: + _data.assets.countdownThree?.data?.audioPath; + case Countdown.CountdownStep.TWO: + _data.assets.countdownTwo?.data?.audioPath; + case Countdown.CountdownStep.ONE: + _data.assets.countdownOne?.data?.audioPath; + case Countdown.CountdownStep.GO: + _data.assets.countdownGo?.data?.audioPath; + default: + null; + } + + return (rawPath == null && fallback != null) ? fallback.getCountdownSoundPath(step, true) : rawPath; + } + + // library:path + var parts = getCountdownSoundPath(step, true)?.split(Constants.LIBRARY_SEPARATOR) ?? []; + if (parts.length == 0) return null; + if (parts.length == 1) return Paths.image(parts[0]); + return Paths.sound(parts[1], parts[0]); + } + + public function buildJudgementSprite(rating:String):Null + { + var result = new FunkinSprite(); + + switch (rating) + { + case "sick": + if (_data.assets.judgementSick == null) return fallback?.buildJudgementSprite(rating); + var assetPath = buildJudgementSpritePath(rating); + if (assetPath == null) return null; + result.loadTexture(assetPath); + result.scale.x = _data.assets.judgementSick?.scale ?? 1.0; + result.scale.y = _data.assets.judgementSick?.scale ?? 1.0; + case "good": + if (_data.assets.judgementGood == null) return fallback?.buildJudgementSprite(rating); + var assetPath = buildJudgementSpritePath(rating); + if (assetPath == null) return null; + result.loadTexture(assetPath); + result.scale.x = _data.assets.judgementGood?.scale ?? 1.0; + result.scale.y = _data.assets.judgementGood?.scale ?? 1.0; + case "bad": + if (_data.assets.judgementBad == null) return fallback?.buildJudgementSprite(rating); + var assetPath = buildJudgementSpritePath(rating); + if (assetPath == null) return null; + result.loadTexture(assetPath); + result.scale.x = _data.assets.judgementBad?.scale ?? 1.0; + result.scale.y = _data.assets.judgementBad?.scale ?? 1.0; + case "shit": + if (_data.assets.judgementShit == null) return fallback?.buildJudgementSprite(rating); + var assetPath = buildJudgementSpritePath(rating); + if (assetPath == null) return null; + result.loadTexture(assetPath); + result.scale.x = _data.assets.judgementShit?.scale ?? 1.0; + result.scale.y = _data.assets.judgementShit?.scale ?? 1.0; + default: + return null; + } + + result.scrollFactor.set(0.2, 0.2); + var isPixel = isJudgementSpritePixel(rating); + result.antialiasing = !isPixel; + result.pixelPerfectRender = isPixel; + result.pixelPerfectPosition = isPixel; + result.updateHitbox(); + + return result; + } + + public function isJudgementSpritePixel(rating:String):Bool + { + switch (rating) + { + case "sick": + var result = _data.assets.judgementSick?.isPixel; + if (result == null && fallback != null) result = fallback.isJudgementSpritePixel(rating); + return result ?? false; + case "good": + var result = _data.assets.judgementGood?.isPixel; + if (result == null && fallback != null) result = fallback.isJudgementSpritePixel(rating); + return result ?? false; + case "bad": + var result = _data.assets.judgementBad?.isPixel; + if (result == null && fallback != null) result = fallback.isJudgementSpritePixel(rating); + return result ?? false; + case "GO": + var result = _data.assets.judgementShit?.isPixel; + if (result == null && fallback != null) result = fallback.isJudgementSpritePixel(rating); + return result ?? false; + default: + return false; + } + } + + function buildJudgementSpritePath(rating:String):Null + { + var basePath:Null = null; + switch (rating) + { + case "sick": + basePath = _data.assets.judgementSick?.assetPath; + case "good": + basePath = _data.assets.judgementGood?.assetPath; + case "bad": + basePath = _data.assets.judgementBad?.assetPath; + case "shit": + basePath = _data.assets.judgementShit?.assetPath; + default: + basePath = null; + } + + if (basePath == null) return fallback?.buildJudgementSpritePath(rating); + + var parts = basePath?.split(Constants.LIBRARY_SEPARATOR) ?? []; + if (parts.length < 1) return null; + if (parts.length == 1) return parts[0]; + + return parts[1]; + } + + public function getJudgementSpriteOffsets(rating:String):Array + { + switch (rating) + { + case "sick": + var result = _data.assets.judgementSick?.offsets; + if (result == null && fallback != null) result = fallback.getJudgementSpriteOffsets(rating); + return result ?? [0, 0]; + case "good": + var result = _data.assets.judgementGood?.offsets; + if (result == null && fallback != null) result = fallback.getJudgementSpriteOffsets(rating); + return result ?? [0, 0]; + case "bad": + var result = _data.assets.judgementBad?.offsets; + if (result == null && fallback != null) result = fallback.getJudgementSpriteOffsets(rating); + return result ?? [0, 0]; + case "shit": + var result = _data.assets.judgementShit?.offsets; + if (result == null && fallback != null) result = fallback.getJudgementSpriteOffsets(rating); + return result ?? [0, 0]; + default: + return [0, 0]; + } + } + + public function buildComboNumSprite(digit:Int):Null + { + var result = new FunkinSprite(); + + switch (digit) + { + case 0: + if (_data.assets.comboNumber0 == null) return fallback?.buildComboNumSprite(digit); + var assetPath = buildComboNumSpritePath(digit); + if (assetPath == null) return null; + result.loadTexture(assetPath); + result.scale.x = _data.assets.comboNumber0?.scale ?? 1.0; + result.scale.y = _data.assets.comboNumber0?.scale ?? 1.0; + case 1: + if (_data.assets.comboNumber1 == null) return fallback?.buildComboNumSprite(digit); + var assetPath = buildComboNumSpritePath(digit); + if (assetPath == null) return null; + result.loadTexture(assetPath); + result.scale.x = _data.assets.comboNumber1?.scale ?? 1.0; + result.scale.y = _data.assets.comboNumber1?.scale ?? 1.0; + case 2: + if (_data.assets.comboNumber2 == null) return fallback?.buildComboNumSprite(digit); + var assetPath = buildComboNumSpritePath(digit); + if (assetPath == null) return null; + result.loadTexture(assetPath); + result.scale.x = _data.assets.comboNumber2?.scale ?? 1.0; + result.scale.y = _data.assets.comboNumber2?.scale ?? 1.0; + case 3: + if (_data.assets.comboNumber3 == null) return fallback?.buildComboNumSprite(digit); + var assetPath = buildComboNumSpritePath(digit); + if (assetPath == null) return null; + result.loadTexture(assetPath); + result.scale.x = _data.assets.comboNumber3?.scale ?? 1.0; + result.scale.y = _data.assets.comboNumber3?.scale ?? 1.0; + case 4: + if (_data.assets.comboNumber4 == null) return fallback?.buildComboNumSprite(digit); + var assetPath = buildComboNumSpritePath(digit); + if (assetPath == null) return null; + result.loadTexture(assetPath); + result.scale.x = _data.assets.comboNumber4?.scale ?? 1.0; + result.scale.y = _data.assets.comboNumber4?.scale ?? 1.0; + case 5: + if (_data.assets.comboNumber5 == null) return fallback?.buildComboNumSprite(digit); + var assetPath = buildComboNumSpritePath(digit); + if (assetPath == null) return null; + result.loadTexture(assetPath); + result.scale.x = _data.assets.comboNumber5?.scale ?? 1.0; + result.scale.y = _data.assets.comboNumber5?.scale ?? 1.0; + case 6: + if (_data.assets.comboNumber6 == null) return fallback?.buildComboNumSprite(digit); + var assetPath = buildComboNumSpritePath(digit); + if (assetPath == null) return null; + result.loadTexture(assetPath); + result.scale.x = _data.assets.comboNumber6?.scale ?? 1.0; + result.scale.y = _data.assets.comboNumber6?.scale ?? 1.0; + case 7: + if (_data.assets.comboNumber7 == null) return fallback?.buildComboNumSprite(digit); + var assetPath = buildComboNumSpritePath(digit); + if (assetPath == null) return null; + result.loadTexture(assetPath); + result.scale.x = _data.assets.comboNumber7?.scale ?? 1.0; + result.scale.y = _data.assets.comboNumber7?.scale ?? 1.0; + case 8: + if (_data.assets.comboNumber8 == null) return fallback?.buildComboNumSprite(digit); + var assetPath = buildComboNumSpritePath(digit); + if (assetPath == null) return null; + result.loadTexture(assetPath); + result.scale.x = _data.assets.comboNumber8?.scale ?? 1.0; + result.scale.y = _data.assets.comboNumber8?.scale ?? 1.0; + case 9: + if (_data.assets.comboNumber9 == null) return fallback?.buildComboNumSprite(digit); + var assetPath = buildComboNumSpritePath(digit); + if (assetPath == null) return null; + result.loadTexture(assetPath); + result.scale.x = _data.assets.comboNumber9?.scale ?? 1.0; + result.scale.y = _data.assets.comboNumber9?.scale ?? 1.0; + default: + return null; + } + + var isPixel = isComboNumSpritePixel(digit); + result.antialiasing = !isPixel; + result.pixelPerfectRender = isPixel; + result.pixelPerfectPosition = isPixel; + result.updateHitbox(); + + return result; + } + + public function isComboNumSpritePixel(digit:Int):Bool + { + switch (digit) + { + case 0: + var result = _data.assets.comboNumber0?.isPixel; + if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit); + return result ?? false; + case 1: + var result = _data.assets.comboNumber1?.isPixel; + if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit); + return result ?? false; + case 2: + var result = _data.assets.comboNumber2?.isPixel; + if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit); + return result ?? false; + case 3: + var result = _data.assets.comboNumber3?.isPixel; + if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit); + return result ?? false; + case 4: + var result = _data.assets.comboNumber4?.isPixel; + if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit); + return result ?? false; + case 5: + var result = _data.assets.comboNumber5?.isPixel; + if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit); + return result ?? false; + case 6: + var result = _data.assets.comboNumber6?.isPixel; + if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit); + return result ?? false; + case 7: + var result = _data.assets.comboNumber7?.isPixel; + if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit); + return result ?? false; + case 8: + var result = _data.assets.comboNumber8?.isPixel; + if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit); + return result ?? false; + case 9: + var result = _data.assets.comboNumber9?.isPixel; + if (result == null && fallback != null) result = fallback.isComboNumSpritePixel(digit); + return result ?? false; + default: + return false; + } + } + + function buildComboNumSpritePath(digit:Int):Null + { + var basePath:Null = null; + switch (digit) + { + case 0: + basePath = _data.assets.comboNumber0?.assetPath; + case 1: + basePath = _data.assets.comboNumber1?.assetPath; + case 2: + basePath = _data.assets.comboNumber2?.assetPath; + case 3: + basePath = _data.assets.comboNumber3?.assetPath; + case 4: + basePath = _data.assets.comboNumber4?.assetPath; + case 5: + basePath = _data.assets.comboNumber5?.assetPath; + case 6: + basePath = _data.assets.comboNumber6?.assetPath; + case 7: + basePath = _data.assets.comboNumber7?.assetPath; + case 8: + basePath = _data.assets.comboNumber8?.assetPath; + case 9: + basePath = _data.assets.comboNumber9?.assetPath; + default: + basePath = null; + } + + if (basePath == null) return fallback?.buildComboNumSpritePath(digit); + + var parts = basePath?.split(Constants.LIBRARY_SEPARATOR) ?? []; + if (parts.length < 1) return null; + if (parts.length == 1) return parts[0]; + + return parts[1]; + } + + public function getComboNumSpriteOffsets(digit:Int):Array + { + switch (digit) + { + case 0: + var result = _data.assets.comboNumber0?.offsets; + if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit); + return result ?? [0, 0]; + case 1: + var result = _data.assets.comboNumber1?.offsets; + if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit); + return result ?? [0, 0]; + case 2: + var result = _data.assets.comboNumber2?.offsets; + if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit); + return result ?? [0, 0]; + case 3: + var result = _data.assets.comboNumber3?.offsets; + if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit); + return result ?? [0, 0]; + case 4: + var result = _data.assets.comboNumber4?.offsets; + if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit); + return result ?? [0, 0]; + case 5: + var result = _data.assets.comboNumber5?.offsets; + if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit); + return result ?? [0, 0]; + case 6: + var result = _data.assets.comboNumber6?.offsets; + if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit); + return result ?? [0, 0]; + case 7: + var result = _data.assets.comboNumber7?.offsets; + if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit); + return result ?? [0, 0]; + case 8: + var result = _data.assets.comboNumber8?.offsets; + if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit); + return result ?? [0, 0]; + case 9: + var result = _data.assets.comboNumber9?.offsets; + if (result == null && fallback != null) result = fallback.getComboNumSpriteOffsets(digit); + return result ?? [0, 0]; + default: + return [0, 0]; + } } public function destroy():Void {} @@ -322,8 +867,17 @@ class NoteStyle implements IRegistryEntry return 'NoteStyle($id)'; } - static function _fetchData(id:String):Null + static function _fetchData(id:String):NoteStyleData { - return NoteStyleRegistry.instance.parseEntryDataWithMigration(id, NoteStyleRegistry.instance.fetchEntryVersion(id)); + var result = NoteStyleRegistry.instance.parseEntryDataWithMigration(id, NoteStyleRegistry.instance.fetchEntryVersion(id)); + + if (result == null) + { + throw 'Could not parse note style data for id: $id'; + } + else + { + return result; + } } } diff --git a/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx b/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx index 1e631f2cf..ff8446c49 100644 --- a/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx +++ b/source/funkin/ui/debug/charting/components/ChartEditorHoldNoteSprite.hx @@ -60,7 +60,9 @@ class ChartEditorHoldNoteSprite extends SustainTrail override function setupHoldNoteGraphic(noteStyle:NoteStyle):Void { - loadGraphic(noteStyle.getHoldNoteAssetPath()); + var graphicPath = noteStyle.getHoldNoteAssetPath(); + if (graphicPath == null) return; + loadGraphic(graphicPath); antialiasing = true; From 195010c7edf31944e40ad790d44b2c987dd931cd Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 18 Jul 2024 17:45:48 -0400 Subject: [PATCH 552/870] hxcpp and lime hmm updates for arm64 mac --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index fabd8b51d..60a35d4fe 100644 --- a/hmm.json +++ b/hmm.json @@ -141,7 +141,7 @@ "name": "lime", "type": "git", "dir": null, - "ref": "872ff6db2f2d27c0243d4ff76802121ded550dd7", + "ref": "ede0005c3aedcbfea7b6247bfc4972ecf7f78a14", "url": "https://github.com/FunkinCrew/lime" }, { From 5e04628480b53b3d1c5b7386826ddb7a36e2ad93 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sun, 21 Jul 2024 19:02:58 -0400 Subject: [PATCH 553/870] lime shallow cairo --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index 60a35d4fe..ba5274f0d 100644 --- a/hmm.json +++ b/hmm.json @@ -141,7 +141,7 @@ "name": "lime", "type": "git", "dir": null, - "ref": "ede0005c3aedcbfea7b6247bfc4972ecf7f78a14", + "ref": "916da928134edc57db44f604036ae9bec828f340", "url": "https://github.com/FunkinCrew/lime" }, { From e4e4c66c6c06173b187109053769fd4ad4f08758 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 25 Jul 2024 08:33:01 -0400 Subject: [PATCH 554/870] Update Lime version --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index ba5274f0d..5254fe5dd 100644 --- a/hmm.json +++ b/hmm.json @@ -141,7 +141,7 @@ "name": "lime", "type": "git", "dir": null, - "ref": "916da928134edc57db44f604036ae9bec828f340", + "ref": "a393a54b6120bfa9a2f1db5a16fbf1137d41f257", "url": "https://github.com/FunkinCrew/lime" }, { From 68b7610225aa4fd382d53950d0ae889333d9e752 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 29 Jul 2024 17:26:49 -0400 Subject: [PATCH 555/870] Update OpenFL to latest (requires a few fixes) --- hmm.json | 14 ++++++++------ source/funkin/audio/visualize/ABotVis.hx | 2 +- source/funkin/audio/visualize/VisShit.hx | 2 +- source/funkin/audio/waveform/WaveformDataParser.hx | 2 +- .../toolboxes/ChartEditorNoteDataToolbox.hx | 4 ++-- source/funkin/ui/freeplay/FreeplayState.hx | 2 +- source/funkin/ui/story/LevelProp.hx | 2 +- 7 files changed, 15 insertions(+), 13 deletions(-) diff --git a/hmm.json b/hmm.json index 5254fe5dd..e9aa678ef 100644 --- a/hmm.json +++ b/hmm.json @@ -23,8 +23,10 @@ }, { "name": "flixel-text-input", - "type": "haxelib", - "version": "1.1.0" + "type": "git", + "dir": null, + "ref": "951a0103a17bfa55eed86703ce50b4fb0d7590bc", + "url": "https://github.com/FunkinCrew/flixel-text-input" }, { "name": "flixel-ui", @@ -75,14 +77,14 @@ "name": "haxeui-core", "type": "git", "dir": null, - "ref": "5dc4c933bdc029f6139a47962e3b8c754060f210", + "ref": "22f7c5a8ffca90d4677cffd6e570f53761709fbc", "url": "https://github.com/haxeui/haxeui-core" }, { "name": "haxeui-flixel", "type": "git", "dir": null, - "ref": "57c1604d6b5174839d7e0e012a4dd5dcbfc129da", + "ref": "28bb710d0ae5d94b5108787593052165be43b980", "url": "https://github.com/haxeui/haxeui-flixel" }, { @@ -141,7 +143,7 @@ "name": "lime", "type": "git", "dir": null, - "ref": "a393a54b6120bfa9a2f1db5a16fbf1137d41f257", + "ref": "f6153ffcb1ffcf733f91d531eac5fda4189e07f7", "url": "https://github.com/FunkinCrew/lime" }, { @@ -190,7 +192,7 @@ "name": "thx.core", "type": "git", "dir": null, - "ref": "6240b6e136f7490d9298edbe8c1891374bd7cdf2", + "ref": "76d87418fadd92eb8e1b61f004cff27d656e53dd", "url": "https://github.com/fponticelli/thx.core" }, { diff --git a/source/funkin/audio/visualize/ABotVis.hx b/source/funkin/audio/visualize/ABotVis.hx index cf43a8add..a6ad0570e 100644 --- a/source/funkin/audio/visualize/ABotVis.hx +++ b/source/funkin/audio/visualize/ABotVis.hx @@ -54,7 +54,7 @@ class ABotVis extends FlxTypedSpriteGroup public function initAnalyzer() { @:privateAccess - analyzer = new SpectralAnalyzer(snd._channel.__source, 7, 0.1, 40); + analyzer = new SpectralAnalyzer(snd._channel.__audioSource, 7, 0.1, 40); #if desktop // On desktop it uses FFT stuff that isn't as optimized as the direct browser stuff we use on HTML5 diff --git a/source/funkin/audio/visualize/VisShit.hx b/source/funkin/audio/visualize/VisShit.hx index ba235fe89..83b9496ac 100644 --- a/source/funkin/audio/visualize/VisShit.hx +++ b/source/funkin/audio/visualize/VisShit.hx @@ -117,7 +117,7 @@ class VisShit { // Math.pow3 @:privateAccess - var buf = snd._channel.__source.buffer; + var buf = snd._channel.__audioSource.buffer; // @:privateAccess audioData = cast buf.data; // jank and hacky lol! kinda busted on HTML5 also!! diff --git a/source/funkin/audio/waveform/WaveformDataParser.hx b/source/funkin/audio/waveform/WaveformDataParser.hx index 5aa54d744..ca421581b 100644 --- a/source/funkin/audio/waveform/WaveformDataParser.hx +++ b/source/funkin/audio/waveform/WaveformDataParser.hx @@ -16,7 +16,7 @@ class WaveformDataParser // Method 1. This only works if the sound has been played before. @:privateAccess - var soundBuffer:Null = sound?._channel?.__source?.buffer; + var soundBuffer:Null = sound?._channel?.__audioSource?.buffer; if (soundBuffer == null) { diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx index 12f7f7d63..100654a02 100644 --- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorNoteDataToolbox.hx @@ -192,7 +192,7 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox var paramStepper:NumberStepper = new NumberStepper(); paramStepper.value = (setParamsToPlace ? chartEditorState.noteParamsToPlace[i].value : param.data?.defaultValue) ?? 0.0; paramStepper.percentWidth = 100; - paramStepper.step = param.data?.step ?? 1; + paramStepper.step = param.data?.step ?? 1.0; // this check should be unnecessary but for some reason // even when these are null it will set it to 0 @@ -283,7 +283,7 @@ class ChartEditorNoteDataToolbox extends ChartEditorBaseToolbox return; } - var heightToSet:Int = Std.int(Math.max(DIALOG_HEIGHT, (toolboxNotesGrid?.height ?? 50) + HEIGHT_OFFSET)) + MINIMIZE_FIX; + var heightToSet:Int = Std.int(Math.max(DIALOG_HEIGHT, (toolboxNotesGrid?.height ?? 50.0) + HEIGHT_OFFSET)) + MINIMIZE_FIX; if (this.height != heightToSet) { this.height = heightToSet; diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 2341f04a6..690e3b910 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1527,7 +1527,7 @@ class FreeplayState extends MusicBeatSubState var moveDataX = funnyMoveShit.x ?? spr.x; var moveDataY = funnyMoveShit.y ?? spr.y; var moveDataSpeed = funnyMoveShit.speed ?? 0.2; - var moveDataWait = funnyMoveShit.wait ?? 0; + var moveDataWait = funnyMoveShit.wait ?? 0.0; FlxTween.tween(spr, {x: moveDataX, y: moveDataY}, moveDataSpeed, {ease: FlxEase.expoIn}); diff --git a/source/funkin/ui/story/LevelProp.hx b/source/funkin/ui/story/LevelProp.hx index 0547404a1..4e78415e3 100644 --- a/source/funkin/ui/story/LevelProp.hx +++ b/source/funkin/ui/story/LevelProp.hx @@ -16,7 +16,7 @@ class LevelProp extends Bopper this.propData = value; this.visible = this.propData != null; - danceEvery = this.propData?.danceEvery ?? 0; + danceEvery = this.propData?.danceEvery ?? 0.0; applyData(); } From bef2e9822244687b9bb85a57645ff699a8ed5df3 Mon Sep 17 00:00:00 2001 From: AppleHair <95587502+AppleHair@users.noreply.github.com> Date: Wed, 17 Jul 2024 18:00:07 +0300 Subject: [PATCH 556/870] [BUGFIX] Ensure the variation used for the next song is valid. When playing in story mode, `PlayState` assumes all the songs use the same variation, which is usually true, but not guaranteed. This PR makes `PlayState` use the `getFirstValidVariation` method to find the valid variation instead of using the `currentVariation` variable, which might not be valid. --- source/funkin/play/PlayState.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 450f13300..5bb0decf5 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -2912,7 +2912,7 @@ class PlayState extends MusicBeatSubState { targetSong: targetSong, targetDifficulty: PlayStatePlaylist.campaignDifficulty, - targetVariation: currentVariation, + targetVariation: targetSong.getFirstValidVariation(PlayStatePlaylist.campaignDifficulty), cameraFollowPoint: cameraFollowPoint.getPosition(), }); }); @@ -2924,7 +2924,7 @@ class PlayState extends MusicBeatSubState { targetSong: targetSong, targetDifficulty: PlayStatePlaylist.campaignDifficulty, - targetVariation: currentVariation, + targetVariation: targetSong.getFirstValidVariation(PlayStatePlaylist.campaignDifficulty), cameraFollowPoint: cameraFollowPoint.getPosition(), }); } From eb78b754f8464b9ac423191f36236c3a2d89841b Mon Sep 17 00:00:00 2001 From: AppleHair <95587502+AppleHair@users.noreply.github.com> Date: Tue, 23 Jul 2024 11:34:26 +0300 Subject: [PATCH 557/870] A fix requested by Eric --- source/funkin/play/PlayState.hx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 5bb0decf5..da066dd6a 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -2908,11 +2908,16 @@ class PlayState extends MusicBeatSubState FunkinSound.playOnce(Paths.sound('Lights_Shut_off'), function() { // no camFollow so it centers on horror tree var targetSong:Song = SongRegistry.instance.fetchEntry(targetSongId); + var targetVariation:String = currentVariation; + if (!targetSong.hasDifficulty(PlayStatePlaylist.campaignDifficulty, currentVariation)) + { + targetVariation = targetSong.getFirstValidVariation(PlayStatePlaylist.campaignDifficulty) ?? Constants.DEFAULT_VARIATION; + } LoadingState.loadPlayState( { targetSong: targetSong, targetDifficulty: PlayStatePlaylist.campaignDifficulty, - targetVariation: targetSong.getFirstValidVariation(PlayStatePlaylist.campaignDifficulty), + targetVariation: targetVariation, cameraFollowPoint: cameraFollowPoint.getPosition(), }); }); @@ -2920,11 +2925,16 @@ class PlayState extends MusicBeatSubState else { var targetSong:Song = SongRegistry.instance.fetchEntry(targetSongId); + var targetVariation:String = currentVariation; + if (!targetSong.hasDifficulty(PlayStatePlaylist.campaignDifficulty, currentVariation)) + { + targetVariation = targetSong.getFirstValidVariation(PlayStatePlaylist.campaignDifficulty) ?? Constants.DEFAULT_VARIATION; + } LoadingState.loadPlayState( { targetSong: targetSong, targetDifficulty: PlayStatePlaylist.campaignDifficulty, - targetVariation: targetSong.getFirstValidVariation(PlayStatePlaylist.campaignDifficulty), + targetVariation: targetVariation, cameraFollowPoint: cameraFollowPoint.getPosition(), }); } From e2297af1cd019b704f7759a84f6542dce67a6289 Mon Sep 17 00:00:00 2001 From: 7oltan <87986834+7oltan@users.noreply.github.com> Date: Tue, 16 Jul 2024 12:52:51 +0300 Subject: [PATCH 558/870] FIX CHARACTER PATHS ISSUE --- source/funkin/play/character/AnimateAtlasCharacter.hx | 2 +- source/funkin/play/character/MultiSparrowCharacter.hx | 4 ++-- source/funkin/play/character/PackerCharacter.hx | 2 +- source/funkin/play/character/SparrowCharacter.hx | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/source/funkin/play/character/AnimateAtlasCharacter.hx b/source/funkin/play/character/AnimateAtlasCharacter.hx index ed58b92b5..5b126db6c 100644 --- a/source/funkin/play/character/AnimateAtlasCharacter.hx +++ b/source/funkin/play/character/AnimateAtlasCharacter.hx @@ -131,7 +131,7 @@ class AnimateAtlasCharacter extends BaseCharacter { trace('[ATLASCHAR] Loading sprite atlas for ${characterId}.'); - var sprite:FlxAtlasSprite = new FlxAtlasSprite(0, 0, Paths.animateAtlas(_data.assetPath, 'shared')); + var sprite:FlxAtlasSprite = new FlxAtlasSprite(0, 0, Paths.animateAtlas(_data.assetPath)); sprite.onAnimationFinish.removeAll(); sprite.onAnimationFinish.add(this.onAnimationFinished); diff --git a/source/funkin/play/character/MultiSparrowCharacter.hx b/source/funkin/play/character/MultiSparrowCharacter.hx index 41c96fbfa..e23afe18c 100644 --- a/source/funkin/play/character/MultiSparrowCharacter.hx +++ b/source/funkin/play/character/MultiSparrowCharacter.hx @@ -62,7 +62,7 @@ class MultiSparrowCharacter extends BaseCharacter } } - var texture:FlxAtlasFrames = Paths.getSparrowAtlas(_data.assetPath, 'shared'); + var texture:FlxAtlasFrames = Paths.getSparrowAtlas(_data.assetPath); if (texture == null) { @@ -76,7 +76,7 @@ class MultiSparrowCharacter extends BaseCharacter for (asset in assetList) { - var subTexture:FlxAtlasFrames = Paths.getSparrowAtlas(asset, 'shared'); + var subTexture:FlxAtlasFrames = Paths.getSparrowAtlas(asset); // If we don't do this, the unused textures will be removed as soon as they're loaded. if (subTexture == null) diff --git a/source/funkin/play/character/PackerCharacter.hx b/source/funkin/play/character/PackerCharacter.hx index 22edbe339..5d004606c 100644 --- a/source/funkin/play/character/PackerCharacter.hx +++ b/source/funkin/play/character/PackerCharacter.hx @@ -30,7 +30,7 @@ class PackerCharacter extends BaseCharacter { trace('[PACKERCHAR] Loading spritesheet ${_data.assetPath} for ${characterId}'); - var tex:FlxFramesCollection = Paths.getPackerAtlas(_data.assetPath, 'shared'); + var tex:FlxFramesCollection = Paths.getPackerAtlas(_data.assetPath); if (tex == null) { trace('Could not load Packer sprite: ${_data.assetPath}'); diff --git a/source/funkin/play/character/SparrowCharacter.hx b/source/funkin/play/character/SparrowCharacter.hx index 81d98b138..eacf799d8 100644 --- a/source/funkin/play/character/SparrowCharacter.hx +++ b/source/funkin/play/character/SparrowCharacter.hx @@ -33,7 +33,7 @@ class SparrowCharacter extends BaseCharacter { trace('[SPARROWCHAR] Loading spritesheet ${_data.assetPath} for ${characterId}'); - var tex:FlxFramesCollection = Paths.getSparrowAtlas(_data.assetPath, 'shared'); + var tex:FlxFramesCollection = Paths.getSparrowAtlas(_data.assetPath); if (tex == null) { trace('Could not load Sparrow sprite: ${_data.assetPath}'); From 4f46a8e4d06207f2c12ade56cc54aeaa7136e84e Mon Sep 17 00:00:00 2001 From: AppleHair <95587502+AppleHair@users.noreply.github.com> Date: Tue, 16 Jul 2024 21:17:53 +0300 Subject: [PATCH 559/870] [BUGFIX] Prevented infinite recursion on freeplay when a song doesn't have the `normal` difficulty Any attempt to create a song without the `normal` difficulty will result in a silent crash when opening freeplay. After some debugging, I discovered that the issue is caused by infinite recursion, which gets triggered at the start of `FreeplaySongData`'s `updateValues`. --- source/funkin/ui/freeplay/FreeplayState.hx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 690e3b910..a416dbf19 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -2150,8 +2150,11 @@ class FreeplaySongData function updateValues(variations:Array):Void { - this.songDifficulties = song.listSuffixedDifficulties(variations, false, false); - if (!this.songDifficulties.contains(currentDifficulty)) currentDifficulty = Constants.DEFAULT_DIFFICULTY; + this.songDifficulties = song.listDifficulties(null, variations, false, false); + if (!this.songDifficulties.contains(currentDifficulty) && currentDifficulty != Constants.DEFAULT_DIFFICULTY) + { + currentDifficulty = Constants.DEFAULT_DIFFICULTY; + } var songDifficulty:SongDifficulty = song.getDifficulty(currentDifficulty, null, variations); if (songDifficulty == null) return; From c8322c479ced92c8bd737ecf5d64b666958925f3 Mon Sep 17 00:00:00 2001 From: AppleHair <95587502+AppleHair@users.noreply.github.com> Date: Tue, 16 Jul 2024 22:36:11 +0300 Subject: [PATCH 560/870] Added a comment --- source/funkin/ui/freeplay/FreeplayState.hx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index a416dbf19..47f55f686 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -2154,6 +2154,9 @@ class FreeplaySongData if (!this.songDifficulties.contains(currentDifficulty) && currentDifficulty != Constants.DEFAULT_DIFFICULTY) { currentDifficulty = Constants.DEFAULT_DIFFICULTY; + // This method gets called again by the setter-method, + // so there's no need to continue. + return; } var songDifficulty:SongDifficulty = song.getDifficulty(currentDifficulty, null, variations); From cb02ea7da5c662c6befac025510c412a329d939f Mon Sep 17 00:00:00 2001 From: AppleHair <95587502+AppleHair@users.noreply.github.com> Date: Wed, 17 Jul 2024 10:20:48 +0300 Subject: [PATCH 561/870] Updated to extend #2712 --- 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 47f55f686..dedf284ee 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -2151,11 +2151,11 @@ class FreeplaySongData function updateValues(variations:Array):Void { this.songDifficulties = song.listDifficulties(null, variations, false, false); - if (!this.songDifficulties.contains(currentDifficulty) && currentDifficulty != Constants.DEFAULT_DIFFICULTY) + if (!this.songDifficulties.contains(currentDifficulty)) { currentDifficulty = Constants.DEFAULT_DIFFICULTY; - // This method gets called again by the setter-method, - // so there's no need to continue. + // This method gets called again by the setter-method + // or the difficulty didn't change, so there's no need to continue. return; } From c9c81fae51e5f2a23ee7fc1ac0cfd499e95b1b9a Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 29 Jul 2024 21:26:02 -0400 Subject: [PATCH 562/870] assets submod? --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 005c96f85..aa1231e8c 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 005c96f85f4304865acb196e7cc4d6d83f9d76d8 +Subproject commit aa1231e8cf2990bb902eac3b37815c010fa9919a From 3b7e65679357687bd6901f45c120de06970d46f8 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Wed, 31 Jul 2024 14:36:06 +0100 Subject: [PATCH 563/870] add stage names to registry + chart editor --- source/funkin/data/stage/StageRegistry.hx | 4 ++-- source/funkin/ui/debug/charting/ChartEditorState.hx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/funkin/data/stage/StageRegistry.hx b/source/funkin/data/stage/StageRegistry.hx index fbb6f188e..1f0504247 100644 --- a/source/funkin/data/stage/StageRegistry.hx +++ b/source/funkin/data/stage/StageRegistry.hx @@ -93,8 +93,8 @@ class StageRegistry extends BaseRegistry public function listBaseGameStageIds():Array { return [ - "mainStage", "spookyMansion", "phillyTrain", "phillyTrainErect", "limoRide", "mallXmas", "mallEvil", "school", "schoolEvil", "tankmanBattlefield", - "phillyStreets", "phillyBlazin", + "mainStage", "spookyMansion", "phillyTrain", "phillyTrainErect", "limoRide", "limoRideErect", "mallXmas", "mallEvil", "school", "schoolEvil", + "tankmanBattlefield", "phillyStreets", "phillyBlazin", ]; } diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index a4e0de61e..24d290abd 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -5707,7 +5707,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState PlayStatePlaylist.campaignId = 'week2'; case 'phillyTrain' | 'phillyTrainErect': PlayStatePlaylist.campaignId = 'week3'; - case 'limoRide': + case 'limoRide' | 'limoRideErect': PlayStatePlaylist.campaignId = 'week4'; case 'mallXmas' | 'mallEvil': PlayStatePlaylist.campaignId = 'week5'; From 270748d1081a947c0c84ecd718e65ccb34ba6911 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Wed, 31 Jul 2024 14:36:24 +0100 Subject: [PATCH 564/870] fuck these decimals messing up my compiling --- source/funkin/ui/freeplay/FreeplayState.hx | 2 +- source/funkin/ui/story/LevelProp.hx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index dc42bd651..fa895042f 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1527,7 +1527,7 @@ class FreeplayState extends MusicBeatSubState var moveDataX = funnyMoveShit.x ?? spr.x; var moveDataY = funnyMoveShit.y ?? spr.y; var moveDataSpeed = funnyMoveShit.speed ?? 0.2; - var moveDataWait = funnyMoveShit.wait ?? 0; + var moveDataWait = funnyMoveShit.wait ?? 0.0; FlxTween.tween(spr, {x: moveDataX, y: moveDataY}, moveDataSpeed, {ease: FlxEase.expoIn}); diff --git a/source/funkin/ui/story/LevelProp.hx b/source/funkin/ui/story/LevelProp.hx index 0547404a1..4e78415e3 100644 --- a/source/funkin/ui/story/LevelProp.hx +++ b/source/funkin/ui/story/LevelProp.hx @@ -16,7 +16,7 @@ class LevelProp extends Bopper this.propData = value; this.visible = this.propData != null; - danceEvery = this.propData?.danceEvery ?? 0; + danceEvery = this.propData?.danceEvery ?? 0.0; applyData(); } From 8200a08152ceea85cd242b990518007af5d4806f Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Wed, 31 Jul 2024 14:36:34 +0100 Subject: [PATCH 565/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index cfd67caa6..06067d187 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit cfd67caa688465b4a282837434832c107b661b04 +Subproject commit 06067d187e7699a8eec42ab07c53d195c589a690 From f4968b0ae5211e70f99d68f8de618553c8eb9a35 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 5 Aug 2024 10:47:59 -0400 Subject: [PATCH 566/870] openfl hmm commit to dev-funkin --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index e9aa678ef..c72b4240a 100644 --- a/hmm.json +++ b/hmm.json @@ -178,7 +178,7 @@ "name": "openfl", "type": "git", "dir": null, - "ref": "228c1b5063911e2ad75cef6e3168ef0a4b9f9134", + "ref": "8306425c497766739510ab29e876059c96f77bd2", "url": "https://github.com/FunkinCrew/openfl" }, { From d43042fd36a74d789a3e439e0ecec5d8f1a07722 Mon Sep 17 00:00:00 2001 From: Hyper_ Date: Mon, 5 Aug 2024 20:02:23 -0300 Subject: [PATCH 567/870] Fix out of bounds note selection --- 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 f72cca77f..98d8036e9 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -4223,8 +4223,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState } else { - // Minimum of 0. - return 0; + // Minimum of -1. + return -1; } }); From 62d0b33689f3cae21c32778e3428b93a7a50c60c Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 6 Aug 2024 13:44:02 -0400 Subject: [PATCH 568/870] Fix for switching to old icon on isPixel levels --- source/funkin/play/components/HealthIcon.hx | 54 ++++++++++++++------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/source/funkin/play/components/HealthIcon.hx b/source/funkin/play/components/HealthIcon.hx index 2442b0dc5..0e24d73fb 100644 --- a/source/funkin/play/components/HealthIcon.hx +++ b/source/funkin/play/components/HealthIcon.hx @@ -150,13 +150,17 @@ class HealthIcon extends FunkinSprite { if (characterId == 'bf-old') { + isPixel = PlayState.instance.currentStage.getBoyfriend().isPixel; PlayState.instance.currentStage.getBoyfriend().initHealthIcon(false); } else { characterId = 'bf-old'; + isPixel = false; loadCharacter(characterId); } + + lerpIconSize(true); } /** @@ -200,31 +204,45 @@ class HealthIcon extends FunkinSprite if (bopEvery != 0) { - // Lerp the health icon back to its normal size, - // while maintaining aspect ratio. - if (this.width > this.height) - { - // Apply linear interpolation while accounting for frame rate. - var targetSize:Int = Std.int(MathUtil.coolLerp(this.width, HEALTH_ICON_SIZE * this.size.x, 0.15)); - - setGraphicSize(targetSize, 0); - } - else - { - var targetSize:Int = Std.int(MathUtil.coolLerp(this.height, HEALTH_ICON_SIZE * this.size.y, 0.15)); - - setGraphicSize(0, targetSize); - } + lerpIconSize(); // Lerp the health icon back to its normal angle. this.angle = MathUtil.coolLerp(this.angle, 0, 0.15); - - this.updateHitbox(); } this.updatePosition(); } + /** + * Does the calculation to lerp the icon size. Usually called every frame, but can be forced to the target size. + * Mainly forced when changing to old icon to not have a weird lerp related to changing from pixel icon to non-pixel old icon + * @param force Force the icon immedialtely to be the target size. Defaults to false. + */ + function lerpIconSize(force:Bool = false):Void + { + // Lerp the health icon back to its normal size, + // while maintaining aspect ratio. + if (this.width > this.height) + { + // Apply linear interpolation while accounting for frame rate. + var targetSize:Int = Std.int(MathUtil.coolLerp(this.width, HEALTH_ICON_SIZE * this.size.x, 0.15)); + + if (force) targetSize = Std.int(HEALTH_ICON_SIZE * this.size.x); + + setGraphicSize(targetSize, 0); + } + else + { + var targetSize:Int = Std.int(MathUtil.coolLerp(this.height, HEALTH_ICON_SIZE * this.size.y, 0.15)); + + if (force) targetSize = Std.int(HEALTH_ICON_SIZE * this.size.y); + + setGraphicSize(0, targetSize); + } + + this.updateHitbox(); + } + /** * Update the position (and status) of the health icon. */ @@ -412,6 +430,8 @@ class HealthIcon extends FunkinSprite isLegacyStyle = !isNewSpritesheet(charId); + trace(' Loading health icon for character: $charId (legacy: $isLegacyStyle)'); + if (!isLegacyStyle) { loadSparrow('icons/icon-$charId'); From ae648418c2e860dc33a9b61d4be611719209fb53 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 6 Aug 2024 14:03:25 -0400 Subject: [PATCH 569/870] assets submod senpai fix --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index aa1231e8c..a659c2a58 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit aa1231e8cf2990bb902eac3b37815c010fa9919a +Subproject commit a659c2a58d2d8b8036102e563a9c620a590da50a From c3d497a9d907b38cd11d1fa15f2d9a85bf82db96 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 7 Aug 2024 19:01:46 -0400 Subject: [PATCH 570/870] hxcpp bump --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index c72b4240a..aad0be8cf 100644 --- a/hmm.json +++ b/hmm.json @@ -104,7 +104,7 @@ "type": "git", "dir": null, "url": "https://github.com/HaxeFoundation/hxcpp", - "ref": "01cfee282a9a783e10c5a7774a3baaf547e6b0a7" + "ref": "8dc8020f8465027de6c2aaaed90718bc693651ed" }, { "name": "hxcpp-debug-server", From 9ff3e0435ad7b51ef88ceabff8909b4f2845f18e Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 9 Aug 2024 23:02:46 -0400 Subject: [PATCH 571/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index a659c2a58..62c4a8203 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit a659c2a58d2d8b8036102e563a9c620a590da50a +Subproject commit 62c4a8203362c1b434de0d376046ebccb96da254 From b47c695cb7acbe032dc717017332f0395dd92656 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 9 Aug 2024 23:09:23 -0400 Subject: [PATCH 572/870] perhaps use funkin versions of haxelib and hmm? --- .github/actions/setup-haxe/action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/setup-haxe/action.yml b/.github/actions/setup-haxe/action.yml index 5a9f7b293..701a023f9 100644 --- a/.github/actions/setup-haxe/action.yml +++ b/.github/actions/setup-haxe/action.yml @@ -60,8 +60,8 @@ runs: haxelib --debug --never deleterepo || true haxelib --debug --never newrepo echo "HAXEPATH=$(haxelib config)" >> "$GITHUB_ENV" - haxelib --debug --never git haxelib https://github.com/HaxeFoundation/haxelib.git master - haxelib --debug --global install hmm + haxelib --debug --never git haxelib https://github.com/FunkinCrew/haxelib.git funkin-patches --skip-dependencies + haxelib --debug --global git hmm https://github.com/FunkinCrew/hmm funkin-patches echo "TIMER_DEPS=$(date +%s)" >> "$GITHUB_ENV" - name: Restore cached dependencies From a0047a482fd7263ba1b015c4a015054f97b52d7b Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 9 Aug 2024 23:31:40 -0400 Subject: [PATCH 573/870] use --always when installing funkin-patches versions of haxelib and hmm --- .github/actions/setup-haxe/action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/setup-haxe/action.yml b/.github/actions/setup-haxe/action.yml index 701a023f9..b22fc6f69 100644 --- a/.github/actions/setup-haxe/action.yml +++ b/.github/actions/setup-haxe/action.yml @@ -60,8 +60,8 @@ runs: haxelib --debug --never deleterepo || true haxelib --debug --never newrepo echo "HAXEPATH=$(haxelib config)" >> "$GITHUB_ENV" - haxelib --debug --never git haxelib https://github.com/FunkinCrew/haxelib.git funkin-patches --skip-dependencies - haxelib --debug --global git hmm https://github.com/FunkinCrew/hmm funkin-patches + haxelib --debug --always --global git haxelib https://github.com/FunkinCrew/haxelib.git funkin-patches --skip-dependencies + haxelib --debug --global --always git hmm https://github.com/FunkinCrew/hmm funkin-patches echo "TIMER_DEPS=$(date +%s)" >> "$GITHUB_ENV" - name: Restore cached dependencies From c209e0e192bd368685782bc0ddaac366db000767 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 14 Aug 2024 10:57:44 -0400 Subject: [PATCH 574/870] Ugh Erect and Cocoa Erect --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 62c4a8203..f4b0954f1 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 62c4a8203362c1b434de0d376046ebccb96da254 +Subproject commit f4b0954f1951563a09d5c74fc3a1a90959f1ee00 From 988e819e9bd2af12bbdd3df60983382afba78b6c Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 14 Aug 2024 15:10:47 -0400 Subject: [PATCH 575/870] Add a bunch of remixes --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 62c4a8203..05f8c9876 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 62c4a8203362c1b434de0d376046ebccb96da254 +Subproject commit 05f8c987612ab7185ce6b266d9b34c0b391ba695 From 6679ec5519f35e2b3764ef308b745d8326216bb4 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 15 Aug 2024 15:14:41 -0400 Subject: [PATCH 576/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index f4b0954f1..e34113b54 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit f4b0954f1951563a09d5c74fc3a1a90959f1ee00 +Subproject commit e34113b545a15b9a62759db50acdf6e00547f3cf From 0270df6b236637c62374bbb0ada6932e10085e59 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sat, 17 Aug 2024 14:58:42 -0400 Subject: [PATCH 577/870] assets submod --- art | 2 +- assets | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/art b/art index faeba700c..55c1b5682 160000 --- a/art +++ b/art @@ -1 +1 @@ -Subproject commit faeba700c5526bd4fd57ccc927d875c82b9d3553 +Subproject commit 55c1b56823d4d7a74397bab9aeab30f15126499c diff --git a/assets b/assets index d09b1e0f1..b1bc5a647 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit d09b1e0f175dc19986a1ef6ef1185c060acd1b71 +Subproject commit b1bc5a647714ed806ba4e979e0f7b9259880445c From eb5bf449a4ba7a3efb82b093fdc90a6248a78224 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sat, 17 Aug 2024 15:06:10 -0400 Subject: [PATCH 578/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index b1bc5a647..ac95dcfb5 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit b1bc5a647714ed806ba4e979e0f7b9259880445c +Subproject commit ac95dcfb5e702d76852badc21f19706518ceb6e2 From 9d85d423c6d9db326378e210cacbee336e189ae4 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Mon, 19 Aug 2024 04:29:22 +0100 Subject: [PATCH 579/870] add stage to registry and chart editor --- source/funkin/data/stage/StageRegistry.hx | 4 ++-- source/funkin/ui/debug/charting/ChartEditorState.hx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/funkin/data/stage/StageRegistry.hx b/source/funkin/data/stage/StageRegistry.hx index 1f0504247..7754c380e 100644 --- a/source/funkin/data/stage/StageRegistry.hx +++ b/source/funkin/data/stage/StageRegistry.hx @@ -93,8 +93,8 @@ class StageRegistry extends BaseRegistry public function listBaseGameStageIds():Array { return [ - "mainStage", "spookyMansion", "phillyTrain", "phillyTrainErect", "limoRide", "limoRideErect", "mallXmas", "mallEvil", "school", "schoolEvil", - "tankmanBattlefield", "phillyStreets", "phillyBlazin", + "mainStage", "mainStageErect", "spookyMansion", "phillyTrain", "phillyTrainErect", "limoRide", "limoRideErect", "mallXmas", "mallEvil", "school", + "schoolEvil", "tankmanBattlefield", "phillyStreets", "phillyBlazin", ]; } diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 09a06661d..ebfbe5eac 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -5699,7 +5699,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState // TODO: Rework asset system so we can remove this jank. switch (currentSongStage) { - case 'mainStage': + case 'mainStage' | 'mainStageErect': PlayStatePlaylist.campaignId = 'week1'; case 'spookyMansion' | 'spookyMansionErect': PlayStatePlaylist.campaignId = 'week2'; From 8a03cc7b2ac39ad9271e55536a5f6ec0734e4ddf Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Mon, 19 Aug 2024 04:29:28 +0100 Subject: [PATCH 580/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index ac95dcfb5..45de6c66a 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit ac95dcfb5e702d76852badc21f19706518ceb6e2 +Subproject commit 45de6c66a04f806d475eb95fa1a364d63466fdec From 4dad17d241df1e9405a68893736882cc2eb44eb9 Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Mon, 19 Aug 2024 13:40:58 +0200 Subject: [PATCH 581/870] Prepare the FlxAnimate bizz --- source/funkin/ui/debug/anim/FlxAnimateTest.hx | 20 +++---------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/source/funkin/ui/debug/anim/FlxAnimateTest.hx b/source/funkin/ui/debug/anim/FlxAnimateTest.hx index c83d2c370..6a34850ee 100644 --- a/source/funkin/ui/debug/anim/FlxAnimateTest.hx +++ b/source/funkin/ui/debug/anim/FlxAnimateTest.hx @@ -22,28 +22,14 @@ class FlxAnimateTest extends MusicBeatState { super.create(); - sprite = new FlxAtlasSprite(0, 0, 'shared:assets/shared/images/characters/tankman'); - add(sprite); + sprite = new FlxAtlasSprite(0, 0, 'assets/images/freeplay/freeplay-boyfriend'); // I suppose a specific atlas to test should go in here - sprite.playAnimation('idle'); + add(sprite); + sprite.anim.play("Boyfriend DJ"); } public override function update(elapsed:Float):Void { super.update(elapsed); - - if (FlxG.keys.justPressed.SPACE) sprite.playAnimation('idle'); - - if (FlxG.keys.justPressed.W) sprite.playAnimation('singUP'); - - if (FlxG.keys.justPressed.A) sprite.playAnimation('singLEFT'); - - if (FlxG.keys.justPressed.S) sprite.playAnimation('singDOWN'); - - if (FlxG.keys.justPressed.D) sprite.playAnimation('singRIGHT'); - - if (FlxG.keys.justPressed.J) sprite.playAnimation('hehPrettyGood'); - - if (FlxG.keys.justPressed.K) sprite.playAnimation('ugh'); } } From 8a2d8a9941090672b52b36d2e92f250e27b36e43 Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Mon, 19 Aug 2024 13:41:29 +0200 Subject: [PATCH 582/870] Committing all the additional stuff (Lowering FPS For my PC lol) --- art | 2 +- assets | 2 +- source/Main.hx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/art b/art index 55c1b5682..faeba700c 160000 --- a/art +++ b/art @@ -1 +1 @@ -Subproject commit 55c1b56823d4d7a74397bab9aeab30f15126499c +Subproject commit faeba700c5526bd4fd57ccc927d875c82b9d3553 diff --git a/assets b/assets index ac95dcfb5..d09b1e0f1 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit ac95dcfb5e702d76852badc21f19706518ceb6e2 +Subproject commit d09b1e0f175dc19986a1ef6ef1185c060acd1b71 diff --git a/source/Main.hx b/source/Main.hx index add5bbc67..2f31a6d48 100644 --- a/source/Main.hx +++ b/source/Main.hx @@ -26,7 +26,7 @@ class Main extends Sprite var framerate:Int = 60; // How many frames per second the game should run at. #else // TODO: This should probably be in the options menu? - var framerate:Int = 144; // How many frames per second the game should run at. + var framerate:Int = 60; // How many frames per second the game should run at. #end var skipSplash:Bool = true; // Whether to skip the flixel splash screen that appears in release mode. var startFullscreen:Bool = false; // Whether to start the game in fullscreen on desktop targets From 82eea221d8ebc2234b6d60048543217ad32c85ea Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Mon, 19 Aug 2024 14:41:20 +0200 Subject: [PATCH 583/870] Can't seem to understand AtlasSprite --- source/funkin/ui/debug/anim/FlxAnimateTest.hx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/funkin/ui/debug/anim/FlxAnimateTest.hx b/source/funkin/ui/debug/anim/FlxAnimateTest.hx index 6a34850ee..2b76d39e0 100644 --- a/source/funkin/ui/debug/anim/FlxAnimateTest.hx +++ b/source/funkin/ui/debug/anim/FlxAnimateTest.hx @@ -23,9 +23,10 @@ class FlxAnimateTest extends MusicBeatState super.create(); sprite = new FlxAtlasSprite(0, 0, 'assets/images/freeplay/freeplay-boyfriend'); // I suppose a specific atlas to test should go in here - + // Doesn't input anything, How does AtlasSprite work??? -Cheems add(sprite); - sprite.anim.play("Boyfriend DJ"); + camera.follow(sprite); + sprite.playAnimation(null); } public override function update(elapsed:Float):Void From 0aa9c41c5b6177a10d8d7779fb475ef37a4a29d3 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 19 Aug 2024 18:59:08 -0400 Subject: [PATCH 584/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index ac95dcfb5..7bc9a73d8 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit ac95dcfb5e702d76852badc21f19706518ceb6e2 +Subproject commit 7bc9a73d87cf288844a522ca825ae22cfa73d5fb From ec07a476c16dba410313b5316deba4fb23c139ca Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 19 Aug 2024 19:06:07 -0400 Subject: [PATCH 585/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 45de6c66a..2eac23629 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 45de6c66a04f806d475eb95fa1a364d63466fdec +Subproject commit 2eac236291775208ce71287a5c27f8f15ae591c9 From a6f8cf0141ce0775914a25f6fe789412ea08a0bb Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Tue, 20 Aug 2024 01:20:13 +0200 Subject: [PATCH 586/870] Setting a simple mask test --- source/funkin/ui/debug/anim/FlxAnimateTest.hx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/source/funkin/ui/debug/anim/FlxAnimateTest.hx b/source/funkin/ui/debug/anim/FlxAnimateTest.hx index 2b76d39e0..44917e2a5 100644 --- a/source/funkin/ui/debug/anim/FlxAnimateTest.hx +++ b/source/funkin/ui/debug/anim/FlxAnimateTest.hx @@ -22,15 +22,18 @@ class FlxAnimateTest extends MusicBeatState { super.create(); - sprite = new FlxAtlasSprite(0, 0, 'assets/images/freeplay/freeplay-boyfriend'); // I suppose a specific atlas to test should go in here - // Doesn't input anything, How does AtlasSprite work??? -Cheems + sprite = new FlxAtlasSprite(0, 0, 'assets/images/charSelect/maskTest'); add(sprite); - camera.follow(sprite); - sprite.playAnimation(null); + sprite.playAnimation(null, false, false, true); } public override function update(elapsed:Float):Void { super.update(elapsed); + + if (FlxG.keys.justPressed.SPACE) ((sprite.anim.isPlaying) ? sprite.anim.pause() : sprite.playAnimation(null, false, false, true)); + + if (FlxG.keys.anyJustPressed([A, LEFT])) sprite.anim.curFrame--; + if (FlxG.keys.anyJustPressed([D, RIGHT])) sprite.anim.curFrame++; } } From 94a08ff528f5b13d7cac0cc98c1dbe14feb4f58c Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Tue, 20 Aug 2024 01:28:03 +0200 Subject: [PATCH 587/870] asset stuff --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index d09b1e0f1..0e4392bcb 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit d09b1e0f175dc19986a1ef6ef1185c060acd1b71 +Subproject commit 0e4392bcb0ed1dbb496764cff074635c20c91389 From f8b63c99684c4098881f6cda2fce3b0a3f4c4ee2 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 20 Aug 2024 14:19:04 -0400 Subject: [PATCH 588/870] update funkin.vis PR --- hmm.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hmm.json b/hmm.json index d67760882..4cd3e27c7 100644 --- a/hmm.json +++ b/hmm.json @@ -58,8 +58,8 @@ "name": "funkin.vis", "type": "git", "dir": null, - "ref": "38261833590773cb1de34ac5d11e0825696fc340", - "url": "https://github.com/FunkinCrew/funkVis" + "ref": "22b1ce089dd924f15cdc4632397ef3504d464e90", + "url": "https://github.com/MidyGamy/funkVis/" }, { "name": "grig.audio", From 76edf2e4e9e6416ba097e724158fcfe78926d25a Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 20 Aug 2024 14:44:53 -0400 Subject: [PATCH 589/870] remove unused imports --- .../ui/debug/anim/DebugBoundingState.hx | 68 ------------------- 1 file changed, 68 deletions(-) diff --git a/source/funkin/ui/debug/anim/DebugBoundingState.hx b/source/funkin/ui/debug/anim/DebugBoundingState.hx index ed2f5870f..7bb42c89e 100644 --- a/source/funkin/ui/debug/anim/DebugBoundingState.hx +++ b/source/funkin/ui/debug/anim/DebugBoundingState.hx @@ -5,29 +5,22 @@ import flixel.addons.display.FlxGridOverlay; import flixel.FlxCamera; import flixel.FlxSprite; import flixel.FlxState; -import flixel.graphics.frames.FlxAtlasFrames; import flixel.graphics.frames.FlxFrame; import flixel.group.FlxGroup; import flixel.math.FlxPoint; import flixel.text.FlxText; import flixel.util.FlxColor; -import flixel.util.FlxSpriteUtil; -import flixel.util.FlxTimer; -import funkin.audio.FunkinSound; import funkin.input.Cursor; import funkin.play.character.BaseCharacter; import funkin.play.character.CharacterData; import funkin.play.character.CharacterData.CharacterDataParser; -import funkin.play.character.SparrowCharacter; import funkin.ui.mainmenu.MainMenuState; import funkin.util.MouseUtil; import funkin.util.SerializerUtil; import funkin.util.SortUtil; import haxe.ui.components.DropDown; import haxe.ui.containers.dialogs.CollapsibleDialog; -import haxe.ui.core.Component; import haxe.ui.core.Screen; -import haxe.ui.events.ItemEvent; import haxe.ui.events.UIEvent; import haxe.ui.RuntimeComponentBuilder; import lime.utils.Assets as LimeAssets; @@ -36,9 +29,6 @@ import openfl.events.Event; import openfl.events.IOErrorEvent; import openfl.geom.Rectangle; import openfl.net.FileReference; -import openfl.net.URLLoader; -import openfl.net.URLRequest; -import openfl.utils.ByteArray; using flixel.util.FlxSpriteUtil; @@ -164,64 +154,6 @@ class DebugBoundingState extends FlxState addInfo('Height', bf.height); spriteSheetView.add(swagOutlines); - - FlxG.stage.window.onDropFile.add(function(path:String) { - // WACKY ASS TESTING SHIT FOR WEB FILE LOADING?? - #if web - var swagList:FileList = cast path; - - var objShit = js.html.URL.createObjectURL(swagList.item(0)); - trace(objShit); - - var funnysound = new FunkinSound().loadStream('https://cdn.discordapp.com/attachments/767500676166451231/817821618251759666/Flutter.mp3', false, false, - null, function() { - trace('LOADED SHIT??'); - }); - - funnysound.volume = 1; - funnysound.play(); - - var urlShit = new URLLoader(new URLRequest(objShit)); - - new FlxTimer().start(3, function(tmr:FlxTimer) { - // music lol! - if (urlShit.dataFormat == BINARY) - { - // var daSwagBytes:ByteArray = urlShit.data; - - // FlxG.sound.playMusic(); - - // trace('is binary!!'); - } - trace(urlShit.dataFormat); - }); - - // remove(bf); - // FlxG.bitmap.removeByKey(Paths.image('characters/temp')); - // Assets.cache.clear(); - - // bf.loadGraphic(objShit); - // add(bf); - - // trace(swagList.item(0).name); - // var urlShit = js.html.URL.createObjectURL(path); - #end - - #if sys - trace("DROPPED FILE FROM: " + Std.string(path)); - var newPath = "./" + Paths.image('characters/temp'); - File.copy(path, newPath); - - var swag = Paths.image('characters/temp'); - - if (bf != null) remove(bf); - FlxG.bitmap.removeByKey(Paths.image('characters/temp')); - Assets.cache.clear(); - - bf.loadGraphic(Paths.image('characters/temp')); - add(bf); - #end - }); } function generateOutlines(frameShit:Array):Void From e1d8e758bb6ebe25a79f6f01417b9c5113457989 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 21 Aug 2024 16:31:10 -0400 Subject: [PATCH 590/870] completion server fixin? --- source/funkin/util/logging/CrashHandler.hx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/source/funkin/util/logging/CrashHandler.hx b/source/funkin/util/logging/CrashHandler.hx index 71d1ad394..aa2622062 100644 --- a/source/funkin/util/logging/CrashHandler.hx +++ b/source/funkin/util/logging/CrashHandler.hx @@ -265,9 +265,10 @@ class CrashHandler static function renderMethod():String { - try + var outputStr:String = 'UNKNOWN'; + outputStr = try { - return switch (FlxG.renderMethod) + switch (FlxG.renderMethod) { case FlxRenderMethod.DRAW_TILES: 'DRAW_TILES'; case FlxRenderMethod.BLITTING: 'BLITTING'; @@ -276,7 +277,11 @@ class CrashHandler } catch (e) { - return 'ERROR ON QUERY RENDER METHOD: ${e}'; + 'ERROR ON QUERY RENDER METHOD: ${e}'; } + + if (outputStr == null) outputStr = 'UNKNOWN'; + + return outputStr; } } From 5756eff7cfd35b3eb0cbb234b31fc50705e0b779 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 21 Aug 2024 16:39:34 -0400 Subject: [PATCH 591/870] dont need null check, we just need to declare string type --- source/funkin/util/logging/CrashHandler.hx | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/funkin/util/logging/CrashHandler.hx b/source/funkin/util/logging/CrashHandler.hx index aa2622062..1b607ddfd 100644 --- a/source/funkin/util/logging/CrashHandler.hx +++ b/source/funkin/util/logging/CrashHandler.hx @@ -280,8 +280,6 @@ class CrashHandler 'ERROR ON QUERY RENDER METHOD: ${e}'; } - if (outputStr == null) outputStr = 'UNKNOWN'; - return outputStr; } } From 7f0f0efe46b6d1b37d464227921e0f7477c1c344 Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Thu, 22 Aug 2024 23:36:43 +0200 Subject: [PATCH 592/870] initial Commit --- assets | 2 +- .../graphics/adobeanimate/FlxAtlasSprite.hx | 3 +- source/funkin/ui/charSelect/CharSelectGF.hx | 71 +++++++++++++++- .../funkin/ui/charSelect/CharSelectPlayer.hx | 81 +++++++++++++++---- .../ui/charSelect/CharSelectSubState.hx | 52 +++++++++++- 5 files changed, 189 insertions(+), 20 deletions(-) diff --git a/assets b/assets index 0e4392bcb..299f5ac20 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 0e4392bcb0ed1dbb496764cff074635c20c91389 +Subproject commit 299f5ac20fd9ee50fda5cadd6abb22b68d86fb87 diff --git a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx index 049c6e206..fdb53e30e 100644 --- a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx +++ b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx @@ -182,6 +182,7 @@ class FlxAtlasSprite extends FlxAnimate trace('Playing animation $id'); this.anim.play(id, restart, false, startFrame); goToFrameLabel(id); + anim.curFrame += startFrame; this.currentAnimation = id; } @@ -301,7 +302,7 @@ class FlxAtlasSprite extends FlxAnimate public function getBasePosition():Null { - var stagePos = new FlxPoint(anim.stageInstance.matrix.tx, anim.stageInstance.matrix.ty); + // var stagePos = new FlxPoint(anim.stageInstance.matrix.tx, anim.stageInstance.matrix.ty); var instancePos = new FlxPoint(anim.curInstance.matrix.tx, anim.curInstance.matrix.ty); var firstElement = anim.curSymbol.timeline?.get(0)?.get(0)?.get(0); if (firstElement == null) return instancePos; diff --git a/source/funkin/ui/charSelect/CharSelectGF.hx b/source/funkin/ui/charSelect/CharSelectGF.hx index 6d8e3e657..44a9a6088 100644 --- a/source/funkin/ui/charSelect/CharSelectGF.hx +++ b/source/funkin/ui/charSelect/CharSelectGF.hx @@ -8,6 +8,7 @@ import funkin.util.FramesJSFLParser; import funkin.util.FramesJSFLParser.FramesJSFLInfo; import funkin.util.FramesJSFLParser.FramesJSFLFrame; import flixel.math.FlxMath; +import funkin.vis.dsp.SpectralAnalyzer; class CharSelectGF extends FlxAtlasSprite { @@ -20,14 +21,47 @@ class CharSelectGF extends FlxAtlasSprite var intendedYPos:Float = 0; var intendedAlpha:Float = 0; + var list:Array = []; + var char:String = "gf"; + + var analyzer:SpectralAnalyzer; public function new() { super(0, 0, Paths.animateAtlas("charSelect/gfChill")); anim.play(""); + list = anim.curSymbol.getFrameLabelNames(); + switchGF("bf"); } + var _addedCallback:String = ""; + + override public function playAnimation(id:String, restart:Bool = false, ignoreOther:Bool = false, loop:Bool = false, startFrame:Int = 0):Void + { + if (id == null) id = "idle"; + // var fr = anim.getFrameLabel("confirm"); + // fr.removeCallbacks(); + // fr.add(() -> trace("HEY")); + + if (id != _addedCallback) + { + var next = list[list.indexOf(_addedCallback) + 1]; + if (next != null) anim.getFrameLabel(next).removeCallbacks(); + + var index:Int = list.indexOf(id); + + _addedCallback = list[index]; + if (index != -1 && index + 1 < list.length) + { + var lb = anim.getFrameLabel(list[index + 1]); + @:privateAccess + lb.add(() -> playAnimation(list[index], true, false, false)); + } + } + super.playAnimation(id, restart, ignoreOther, loop, startFrame); + } + override public function update(elapsed:Float) { super.update(elapsed); @@ -59,6 +93,39 @@ class CharSelectGF extends FlxAtlasSprite } } + override public function draw() + { + if (analyzer != null) drawFFT(); + super.draw(); + } + + function drawFFT() + { + if (char == "nene") + { + var levels = analyzer.getLevels(); + var frame = anim.curSymbol.timeline.get("VIZ_bars").get(anim.curFrame); + var elements = frame.getList(); + var len:Int = cast Math.min(elements.length, 7); + + for (i in 0...len) + { + var animFrame:Int = Math.round(levels[i].value * 12); + + #if desktop + animFrame = Math.round(animFrame * FlxG.sound.volume); + #end + + animFrame = Math.floor(Math.min(12, animFrame)); + animFrame = Math.floor(Math.max(0, animFrame)); + + animFrame = Std.int(Math.abs(animFrame - 12)); // shitty dumbass flip, cuz dave got da shit backwards lol! + + elements[i].symbol.firstFrame = animFrame; + } + } + } + /** * @param animInfo Should not be confused with animInInfo! * This is merely a local var for the function! @@ -113,6 +180,7 @@ class CharSelectGF extends FlxAtlasSprite "gf"; } + char = str; switch str { default: @@ -123,7 +191,8 @@ class CharSelectGF extends FlxAtlasSprite animOutInfo = FramesJSFLParser.parse(Paths.file("images/charSelect/" + str + "AnimInfo/" + str + "Out.txt")); anim.play(""); - playAnimation("idle", true, false, true); + playAnimation("idle", true, false, false); + addFrameCallback(getNextFrameLabel("idle"), () -> playAnimation("idle", true, false, false)); updateHitbox(); } diff --git a/source/funkin/ui/charSelect/CharSelectPlayer.hx b/source/funkin/ui/charSelect/CharSelectPlayer.hx index 9052c60e9..8a5d57530 100644 --- a/source/funkin/ui/charSelect/CharSelectPlayer.hx +++ b/source/funkin/ui/charSelect/CharSelectPlayer.hx @@ -10,22 +10,76 @@ class CharSelectPlayer extends FlxAtlasSprite super(x, y, Paths.animateAtlas("charSelect/bfChill")); onAnimationComplete.add(function(animLabel:String) { - switch (animLabel) - { - case "slidein": - if (hasAnimation("slidein idle point")) playAnimation("slidein idle point", true, false, false); - else - playAnimation("idle", true, false, true); - case "slidein idle point": - playAnimation("idle", true, false, true); - case "select": - anim.pause(); - case "deselect": - playAnimation("deselect loop start", true, false, true); - } + if (hasAnimation("slidein idle point")) playAnimation("slidein idle point", true, false, false); + else + playAnimation("idle"); }); } + var _addedCall = false; + + override public function playAnimation(id:String, restart:Bool = false, ignoreOther:Bool = false, loop:Bool = false, startFrame:Int = 0):Void + { + if (id == null || id == "") id = "idle"; + switch (id) + { + case "idle", "slidein idle point": + if (!_addedCall) + { + var fr = anim.getFrameLabel("idle end"); + if (fr != null) fr.add(() -> { + playAnimation("idle", true, false, false); + }); + } + _addedCall = true; + + case "select": + if (_addedCall) + { + anim.getFrameLabel("idle end").removeCallbacks(); + _addedCall = false; + } + + var fr = anim.getFrameLabel("deselect"); + + fr.add(() -> { + anim.pause(); + anim.curFrame--; + }); + + _addedCall = true; + + case "deselect": + var og = anim.getFrameLabel("deselect"); + if (_addedCall) + { + og.removeCallbacks(); + _addedCall = false; + } + + var fr = anim.getFrameLabel("deselect loop end"); + + fr.removeCallbacks(); + fr.add(() -> playAnimation("deselect loop start", true, false, false)); + + _addedCall = true; + + case "slidein", "slideout": + if (_addedCall) + { + anim.getFrameLabel("deselect loop end").removeCallbacks(); + _addedCall = false; + } + default: + if (_addedCall) + { + anim.getFrameLabel("idle end").removeCallbacks(); + _addedCall = false; + } + } + super.playAnimation(id, restart, ignoreOther, loop, startFrame); + } + public function updatePosition(str:String) { switch (str) @@ -48,7 +102,6 @@ class CharSelectPlayer extends FlxAtlasSprite loadAtlas(Paths.animateAtlas("charSelect/" + str + "Chill")); } - anim.play(""); playAnimation("slidein", true, false, false); updateHitbox(); diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index 8b1f050f5..2b577dd95 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -22,6 +22,8 @@ import flixel.util.FlxTimer; import flixel.tweens.FlxEase; import flixel.sound.FlxSound; import funkin.audio.FunkinSound; +import funkin.graphics.FunkinCamera; +import funkin.vis.dsp.SpectralAnalyzer; class CharSelectSubState extends MusicBeatSubState { @@ -63,6 +65,10 @@ class CharSelectSubState extends MusicBeatSubState var selectTimer:FlxTimer = new FlxTimer(); var selectSound:FunkinSound; + var charSelectCam:FunkinCamera; + + var introM:FunkinSound = null; + public function new() { super(); @@ -90,13 +96,21 @@ class CharSelectSubState extends MusicBeatSubState restartTrack: true }); var introMusic:String = Paths.music('stayFunky/stayFunky-intro'); - FunkinSound.load(introMusic, 1.0, false, true, true, () -> { + introM = FunkinSound.load(introMusic, 1.0, false, true, true, () -> { FunkinSound.playMusic('stayFunky', { startingVolume: 1, overrideExisting: true, restartTrack: true }); + @:privateAccess + gfChill.analyzer = new SpectralAnalyzer(FlxG.sound.music._channel.__audioSource, 7, 0.1); + #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! + @:privateAccess + gfChill.analyzer.fftN = 512; + #end }); var bg:FlxSprite = new FlxSprite(-153, -140); @@ -137,7 +151,7 @@ class CharSelectSubState extends MusicBeatSubState gfChill = new CharSelectGF(); gfChill.switchGF("bf"); add(gfChill); - + @:privateAccess playerChill = new CharSelectPlayer(0, 0); playerChill.switchChar("bf"); add(playerChill); @@ -349,6 +363,17 @@ class CharSelectSubState extends MusicBeatSubState override public function update(elapsed:Float):Void { super.update(elapsed); + @:privateAccess + if (introM != null && !introM.paused && gfChill.analyzer == null) + { + gfChill.analyzer = new SpectralAnalyzer(introM._channel.__audioSource, 7, 0.1); + #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! + @:privateAccess + gfChill.analyzer.fftN = 512; + #end + } Conductor.instance.update(); @@ -449,6 +474,7 @@ class CharSelectSubState extends MusicBeatSubState FlxTween.tween(FlxG.sound.music, {pitch: 0.1}, 1.5, {ease: FlxEase.quadInOut}); playerChill.playAnimation("select"); + gfChill.playAnimation("confirm"); pressedSelect = true; selectTimer.start(1.5, (_) -> { pressedSelect = false; @@ -467,8 +493,20 @@ class CharSelectSubState extends MusicBeatSubState grpCursors.visible = true; FlxTween.globalManager.cancelTweensOf(FlxG.sound.music); - FlxTween.tween(FlxG.sound.music, {pitch: 1.0}, 1, {ease: FlxEase.quartInOut}); playerChill.playAnimation("deselect"); + gfChill.playAnimation("deselect"); + FlxTween.tween(FlxG.sound.music, {pitch: 1.0}, 1, + { + ease: FlxEase.quartInOut, + onComplete: (_) -> { + var fr = playerChill.anim.getFrameLabel("deselect loop end"); + if (fr != null) fr.removeCallbacks(); + @:privateAccess + playerChill._addedCall = false; + playerChill.playAnimation("idle"); + gfChill.playAnimation("idle"); + } + }); pressedSelect = false; selectTimer.cancel(); } @@ -572,6 +610,14 @@ class CharSelectSubState extends MusicBeatSubState memb.scale.set(2.6, 2.6); if (controls.ACCEPT) memb.animation.play("confirm"); + if (controls.BACK) + { + memb.animation.play("confirm", false, true); + member.animation.finishCallback = (_) -> { + member.animation.play("idle"); + member.animation.finishCallback = null; + }; + } } else { From 0d3fa41b29b4613ca9241c2081d16426ca1c850e Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Fri, 23 Aug 2024 13:35:50 +0100 Subject: [PATCH 593/870] blue fade shader --- source/funkin/graphics/shaders/BlueFade.hx | 51 ++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 source/funkin/graphics/shaders/BlueFade.hx diff --git a/source/funkin/graphics/shaders/BlueFade.hx b/source/funkin/graphics/shaders/BlueFade.hx new file mode 100644 index 000000000..f57bcfbf1 --- /dev/null +++ b/source/funkin/graphics/shaders/BlueFade.hx @@ -0,0 +1,51 @@ +package funkin.graphics.shaders; + +import flixel.system.FlxAssets.FlxShader; +import flixel.tweens.FlxEase; +import flixel.tweens.FlxTween; + +class BlueFade extends FlxShader +{ + public var fadeVal(default, set):Float; + + function set_fadeVal(val:Float):Float + { + fadeAmt.value = [val]; + fadeVal = val; + // trace(fadeVal); + + return val; + } + + public function fade(startAmt:Float = 0, targetAmt:Float = 1, duration:Float, _options:TweenOptions):Void + { + fadeVal = startAmt; + FlxTween.tween(this, {fadeVal: targetAmt}, duration, _options); + } + + @:glFragmentSource(' + #pragma header + + // Value from (0, 1) + uniform float fadeAmt; + + // fade the image to blue as it fades to black + + void main() + { + vec4 tex = flixel_texture2D(bitmap, openfl_TextureCoordv); + + vec4 finalColor = mix(vec4(vec4(0.0, 0.0, tex.b, tex.a) * fadeAmt), vec4(tex * fadeAmt), fadeAmt); + + // Output to screen + gl_FragColor = finalColor; + } + + ') + public function new() + { + super(); + + this.fadeVal = 1; + } +} From e37330f2888ee77982031bea0e19b3bd1e655943 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Fri, 23 Aug 2024 13:36:00 +0100 Subject: [PATCH 594/870] character select transition --- .../ui/charSelect/CharSelectSubState.hx | 120 +++++++++++++++--- 1 file changed, 104 insertions(+), 16 deletions(-) diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index 8b1f050f5..34ffbaf58 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -22,6 +22,8 @@ import flixel.util.FlxTimer; import flixel.tweens.FlxEase; import flixel.sound.FlxSound; import funkin.audio.FunkinSound; +import funkin.graphics.shaders.BlueFade; +import openfl.filters.ShaderFilter; class CharSelectSubState extends MusicBeatSubState { @@ -53,9 +55,16 @@ class CharSelectSubState extends MusicBeatSubState var gfChill:CharSelectGF; var gfChillOut:CharSelectGF; + var barthing:FlxAtlasSprite; + var dipshitBacking:FlxSprite; + var chooseDipshit:FlxSprite; + var dipshitBlur:FlxSprite; + var transitionGradient:FlxSprite; + var curChar(default, set):String = "pico"; var nametag:Nametag; var camFollow:FlxObject; + var autoFollow:Bool = false; var availableChars:Map = new Map(); var pressedSelect:Bool = false; @@ -71,10 +80,17 @@ class CharSelectSubState extends MusicBeatSubState availableChars.set(3, "pico"); } + var fadeShader:BlueFade = new BlueFade(); + override public function create():Void { super.create(); + autoFollow = false; + + var fadeShaderFilter:ShaderFilter = new ShaderFilter(fadeShader); + FlxG.camera.setFilters([fadeShaderFilter]); + selectSound = new FunkinSound(); selectSound.loadEmbedded(Paths.sound('CS_select')); selectSound.pitch = 1; @@ -120,12 +136,15 @@ class CharSelectSubState extends MusicBeatSubState curtains.scrollFactor.set(1.4, 1.4); add(curtains); - var barthing:FlxAtlasSprite = new FlxAtlasSprite(0, 0, Paths.animateAtlas("charSelect/barThing")); + barthing = new FlxAtlasSprite(0, 0, Paths.animateAtlas("charSelect/barThing")); barthing.anim.play(""); barthing.blend = BlendMode.MULTIPLY; barthing.scrollFactor.set(0, 0); add(barthing); + barthing.y += 80; + FlxTween.tween(barthing, {y: barthing.y - 80}, 1.3, {ease: FlxEase.expoOut}); + var charLight:FlxSprite = new FlxSprite(800, 250); charLight.loadGraphic(Paths.image('charSelect/charLight')); add(charLight); @@ -156,24 +175,33 @@ class CharSelectSubState extends MusicBeatSubState fgBlur.blend = openfl.display.BlendMode.MULTIPLY; add(fgBlur); - var dipshitBlur:FlxSprite = new FlxSprite(419, -65); + dipshitBlur = new FlxSprite(419, -65); dipshitBlur.frames = Paths.getSparrowAtlas("charSelect/dipshitBlur"); dipshitBlur.animation.addByPrefix('idle', "CHOOSE vertical", 24, true); dipshitBlur.blend = BlendMode.ADD; dipshitBlur.animation.play("idle"); add(dipshitBlur); - var dipshitBacking:FlxSprite = new FlxSprite(423, -17); + dipshitBacking = new FlxSprite(423, -17); dipshitBacking.frames = Paths.getSparrowAtlas("charSelect/dipshitBacking"); dipshitBacking.animation.addByPrefix('idle', "CHOOSE horizontal", 24, true); dipshitBacking.blend = BlendMode.ADD; dipshitBacking.animation.play("idle"); add(dipshitBacking); - var chooseDipshit:FlxSprite = new FlxSprite(426, -13); + dipshitBacking.y += 210; + FlxTween.tween(dipshitBacking, {y: dipshitBacking.y - 210}, 1.1, {ease: FlxEase.expoOut}); + + chooseDipshit = new FlxSprite(426, -13); chooseDipshit.loadGraphic(Paths.image('charSelect/chooseDipshit')); add(chooseDipshit); + chooseDipshit.y += 200; + FlxTween.tween(chooseDipshit, {y: chooseDipshit.y - 200}, 1, {ease: FlxEase.expoOut}); + + dipshitBlur.y += 220; + FlxTween.tween(dipshitBlur, {y: dipshitBlur.y - 220}, 1.2, {ease: FlxEase.expoOut}); + chooseDipshit.scrollFactor.set(); dipshitBacking.scrollFactor.set(); dipshitBlur.scrollFactor.set(); @@ -241,6 +269,12 @@ class CharSelectSubState extends MusicBeatSubState initLocks(); + for (index => member in grpIcons.members) + { + member.y += 300; + FlxTween.tween(member, {y: member.y - 300}, 1, {ease: FlxEase.expoOut}); + } + cursor.scrollFactor.set(); cursorBlue.scrollFactor.set(); cursorDarkBlue.scrollFactor.set(); @@ -258,7 +292,8 @@ class CharSelectSubState extends MusicBeatSubState add(camFollow); camFollow.screenCenter(); - FlxG.camera.follow(camFollow, LOCKON, 0.01); + // FlxG.camera.follow(camFollow, LOCKON, 0.01); + FlxG.camera.follow(camFollow, LOCKON); var temp:FlxSprite = new FlxSprite(); temp.loadGraphic(Paths.image('charSelect/placement')); @@ -266,6 +301,25 @@ class CharSelectSubState extends MusicBeatSubState temp.alpha = 0.0; Conductor.stepHit.add(spamOnStep); // FlxG.debugger.track(temp, "tempBG"); + + transitionGradient = new FlxSprite(0, 0).loadGraphic(Paths.image('freeplay/transitionGradient')); + transitionGradient.scale.set(1280, 1); + transitionGradient.flipY = true; + transitionGradient.updateHitbox(); + FlxTween.tween(transitionGradient, {y: -720}, 1, {ease: FlxEase.expoOut}); + add(transitionGradient); + + camFollow.screenCenter(); + camFollow.y -= 150; + fadeShader.fade(0.0, 1.0, 0.8, {ease: FlxEase.quadOut}); + FlxTween.tween(camFollow, {y: camFollow.y + 150}, 1.5, + { + ease: FlxEase.expoOut, + onComplete: function(_) { + autoFollow = true; + FlxG.camera.follow(camFollow, LOCKON, 0.01); + } + }); } var grpIcons:FlxSpriteGroup; @@ -337,6 +391,35 @@ class CharSelectSubState extends MusicBeatSubState } } + function testLol():Void + { + autoFollow = false; + FlxTween.tween(barthing, {y: barthing.y + 80}, 0.8, {ease: FlxEase.backIn}); + FlxTween.tween(dipshitBacking, {y: dipshitBacking.y + 210}, 0.8, {ease: FlxEase.backIn}); + FlxTween.tween(chooseDipshit, {y: chooseDipshit.y + 200}, 0.8, {ease: FlxEase.backIn}); + FlxTween.tween(dipshitBlur, {y: dipshitBlur.y + 220}, 0.8, {ease: FlxEase.backIn}); + for (index => member in grpIcons.members) + { + // member.y += 300; + FlxTween.tween(member, {y: member.y + 300}, 0.8, {ease: FlxEase.backIn}); + } + FlxG.camera.follow(camFollow, LOCKON); + FlxTween.tween(transitionGradient, {y: -150}, 0.8, {ease: FlxEase.backIn}); + fadeShader.fade(1.0, 0, 0.8, {ease: FlxEase.quadIn}); + FlxTween.tween(camFollow, {y: camFollow.y - 150}, 0.8, + { + ease: FlxEase.backIn, + onComplete: function(_) { + FlxG.switchState(FreeplayState.build( + { + { + character: curChar + } + })); + } + }); + } + var holdTmrUp:Float = 0; var holdTmrDown:Float = 0; var holdTmrLeft:Float = 0; @@ -447,17 +530,19 @@ class CharSelectSubState extends MusicBeatSubState FlxG.sound.play(Paths.sound('CS_confirm')); - FlxTween.tween(FlxG.sound.music, {pitch: 0.1}, 1.5, {ease: FlxEase.quadInOut}); + FlxTween.tween(FlxG.sound.music, {pitch: 0.1}, 1, {ease: FlxEase.quadInOut}); + FlxTween.tween(FlxG.sound.music, {volume: 0.0}, 1.5, {ease: FlxEase.quadInOut}); playerChill.playAnimation("select"); pressedSelect = true; selectTimer.start(1.5, (_) -> { pressedSelect = false; - FlxG.switchState(FreeplayState.build( - { - { - character: curChar - } - })); + // FlxG.switchState(FreeplayState.build( + // { + // { + // character: curChar + // } + // })); + testLol(); }); } @@ -467,7 +552,7 @@ class CharSelectSubState extends MusicBeatSubState grpCursors.visible = true; FlxTween.globalManager.cancelTweensOf(FlxG.sound.music); - FlxTween.tween(FlxG.sound.music, {pitch: 1.0}, 1, {ease: FlxEase.quartInOut}); + FlxTween.tween(FlxG.sound.music, {pitch: 1.0, volume: 1.0}, 1, {ease: FlxEase.quartInOut}); playerChill.playAnimation("deselect"); pressedSelect = false; selectTimer.cancel(); @@ -491,9 +576,12 @@ class CharSelectSubState extends MusicBeatSubState updateLockAnims(); - camFollow.screenCenter(); - camFollow.x += cursorX * 10; - camFollow.y += cursorY * 10; + if (autoFollow == true) + { + camFollow.screenCenter(); + camFollow.x += cursorX * 10; + camFollow.y += cursorY * 10; + } cursorLocIntended.x = (cursorFactor * cursorX) + (FlxG.width / 2) - cursor.width / 2; cursorLocIntended.y = (cursorFactor * cursorY) + (FlxG.height / 2) - cursor.height / 2; From 55dd1857c96f7bbcb64b0738757c0a3dfdbebb62 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Fri, 23 Aug 2024 13:36:35 +0100 Subject: [PATCH 595/870] freeplay transition + wip card classes --- source/funkin/ui/freeplay/AlbumRoll.hx | 28 +- source/funkin/ui/freeplay/FreeplayState.hx | 385 ++++++++---------- .../ui/freeplay/backcards/BackingCard.hx | 217 ++++++++++ .../ui/freeplay/backcards/BoyfriendCard.hx | 168 ++++++++ .../funkin/ui/freeplay/backcards/PicoCard.hx | 74 ++++ 5 files changed, 650 insertions(+), 222 deletions(-) create mode 100644 source/funkin/ui/freeplay/backcards/BackingCard.hx create mode 100644 source/funkin/ui/freeplay/backcards/BoyfriendCard.hx create mode 100644 source/funkin/ui/freeplay/backcards/PicoCard.hx diff --git a/source/funkin/ui/freeplay/AlbumRoll.hx b/source/funkin/ui/freeplay/AlbumRoll.hx index 36dba0054..beed7baca 100644 --- a/source/funkin/ui/freeplay/AlbumRoll.hx +++ b/source/funkin/ui/freeplay/AlbumRoll.hx @@ -41,6 +41,7 @@ class AlbumRoll extends FlxSpriteGroup var difficultyStars:DifficultyStars; var _exitMovers:Null; + var _exitMoversCharSel:Null; var albumData:Album; @@ -128,7 +129,7 @@ class AlbumRoll extends FlxSpriteGroup * Apply exit movers for the album roll. * @param exitMovers The exit movers to apply. */ - public function applyExitMovers(?exitMovers:FreeplayState.ExitMoverData):Void + public function applyExitMovers(?exitMovers:FreeplayState.ExitMoverData, ?exitMoversCharSel:FreeplayState.ExitMoverData):Void { if (exitMovers == null) { @@ -141,12 +142,30 @@ class AlbumRoll extends FlxSpriteGroup if (exitMovers == null) return; + if (exitMoversCharSel == null) + { + exitMoversCharSel = _exitMoversCharSel; + } + else + { + _exitMoversCharSel = exitMoversCharSel; + } + + if (exitMoversCharSel == null) return; + exitMovers.set([newAlbumArt, difficultyStars], { x: FlxG.width, speed: 0.4, wait: 0 }); + + exitMoversCharSel.set([newAlbumArt, difficultyStars], + { + y: -175, + speed: 0.8, + wait: 0.1 + }); } var titleTimer:Null = null; @@ -207,6 +226,13 @@ class AlbumRoll extends FlxSpriteGroup speed: 0.4, wait: 0 }); + + if (_exitMoversCharSel != null) _exitMoversCharSel.set([albumTitle], + { + y: -190, + speed: 0.8, + wait: 0.1 + }); } public function setDifficultyStars(?difficulty:Int):Void diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 63767d28e..614e8cc86 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1,5 +1,8 @@ package funkin.ui.freeplay; +import funkin.ui.freeplay.backcards.BackingCard; +import funkin.ui.freeplay.backcards.BoyfriendCard; +import funkin.ui.freeplay.backcards.PicoCard; import flixel.addons.transition.FlxTransitionableState; import flixel.addons.ui.FlxInputText; import flixel.FlxCamera; @@ -30,7 +33,9 @@ import funkin.graphics.shaders.AngleMask; import funkin.graphics.shaders.GaussianBlurShader; import funkin.graphics.shaders.HSVShader; import funkin.graphics.shaders.PureColor; +import funkin.graphics.shaders.BlueFade; import funkin.graphics.shaders.StrokeShader; +import openfl.filters.ShaderFilter; import funkin.input.Controls; import funkin.play.PlayStatePlaylist; import funkin.play.scoring.Scoring; @@ -176,6 +181,8 @@ class FreeplayState extends MusicBeatSubState var letterSort:LetterSort; var exitMovers:ExitMoverData = new Map(); + var exitMoversCharSel:ExitMoverData = new Map(); + var stickerSubState:Null = null; public static var rememberedDifficulty:Null = Constants.DEFAULT_DIFFICULTY; @@ -186,23 +193,9 @@ class FreeplayState extends MusicBeatSubState 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 backingCard:Null = null; - 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 var bgDad:FlxSprite; var fromResultsParams:Null = null; @@ -232,49 +225,38 @@ class FreeplayState extends MusicBeatSubState stickerSubState = stickers; } + switch (currentCharacterId) + { + case 'bf': + backingCard = new BoyfriendCard(currentCharacter); + case 'pico': + backingCard = new PicoCard(currentCharacter); + default: + backingCard = new BackingCard(currentCharacter); + } + // We build a bunch of sprites BEFORE create() so we can guarantee they aren't null later on. albumRoll = new AlbumRoll(); fp = new FreeplayScore(460, 60, 7, 100); - cardGlow = new FlxSprite(-30, -30).loadGraphic(Paths.image('freeplay/cardGlow')); - confirmGlow = new FlxSprite(-30, 240).loadGraphic(Paths.image('freeplay/confirmGlow')); - confirmTextGlow = new FlxSprite(-8, 115).loadGraphic(Paths.image('freeplay/glowingText')); rankCamera = new FunkinCamera('rankCamera', 0, 0, FlxG.width, FlxG.height); funnyCam = new FunkinCamera('freeplayFunny', 0, 0, FlxG.width, FlxG.height); - funnyScroll = new BGScrollingText(0, 220, currentCharacter.getFreeplayDJText(1), FlxG.width / 2, false, 60); - funnyScroll2 = new BGScrollingText(0, 335, currentCharacter.getFreeplayDJText(1), FlxG.width / 2, false, 60); grpCapsules = new FlxTypedGroup(); grpDifficulties = new FlxTypedSpriteGroup(-300, 80); letterSort = new LetterSort(400, 75); grpSongs = new FlxTypedGroup(); - moreWays = new BGScrollingText(0, 160, currentCharacter.getFreeplayDJText(2), FlxG.width, true, 43); - moreWays2 = new BGScrollingText(0, 397, currentCharacter.getFreeplayDJText(2), FlxG.width, true, 43); - pinkBack = FunkinSprite.create('freeplay/pinkBack'); rankBg = new FunkinSprite(0, 0); rankVignette = new FlxSprite(0, 0).loadGraphic(Paths.image('freeplay/rankVignette')); sparks = new FlxSprite(0, 0); sparksADD = new FlxSprite(0, 0); txtCompletion = new AtlasText(1185, 87, '69', AtlasFont.FREEPLAY_CLEAR); - txtNuts = new BGScrollingText(0, 285, currentCharacter.getFreeplayDJText(3), FlxG.width / 2, true, 43); ostName = new FlxText(8, 8, FlxG.width - 8 - 8, 'OFFICIAL OST', 48); - orangeBackShit = new FunkinSprite(84, 440).makeSolidColor(Std.int(pinkBack.width), 75, 0xFFFEDA00); - - bgDad = new FlxSprite(pinkBack.width * 0.74, 0).loadGraphic(Paths.image('freeplay/freeplayBGdad')); - alsoOrangeLOL = new FunkinSprite(0, orangeBackShit.y).makeSolidColor(100, Std.int(orangeBackShit.height), 0xFFFFD400); - confirmGlow2 = new FlxSprite(confirmGlow.x, confirmGlow.y).loadGraphic(Paths.image('freeplay/confirmGlow2')); - funnyScroll3 = new BGScrollingText(0, orangeBackShit.y + 10, currentCharacter.getFreeplayDJText(1), FlxG.width / 2, 60); - 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), - }); + bgDad = new FlxSprite(backingCard.pinkBack.width * 0.74, 0).loadGraphic(Paths.image('freeplay/freeplayBGdad')); } + var fadeShader:BlueFade = new BlueFade(); + override function create():Void { super.create(); @@ -283,6 +265,9 @@ class FreeplayState extends MusicBeatSubState FlxTransitionableState.skipNextTransIn = true; + var fadeShaderFilter:ShaderFilter = new ShaderFilter(fadeShader); + funnyCam.setFilters([fadeShaderFilter]); + if (stickerSubState != null) { this.persistentUpdate = true; @@ -360,113 +345,12 @@ class FreeplayState extends MusicBeatSubState trace(FlxG.camera.initialZoom); trace(FlxCamera.defaultZoom); - pinkBack.color = 0xFFFFD4E9; // sets it to pink! - pinkBack.x -= pinkBack.width; - - FlxTween.tween(pinkBack, {x: 0}, 0.6, {ease: FlxEase.quartOut}); - add(pinkBack); - - add(orangeBackShit); - - add(alsoOrangeLOL); - - exitMovers.set([pinkBack, orangeBackShit, alsoOrangeLOL], - { - x: -pinkBack.width, - y: pinkBack.y, - speed: 0.4, - wait: 0 - }); - - FlxSpriteUtil.alphaMaskFlxSprite(orangeBackShit, pinkBack, orangeBackShit); - orangeBackShit.visible = false; - alsoOrangeLOL.visible = false; - - confirmTextGlow.blend = BlendMode.ADD; - confirmTextGlow.visible = false; - - confirmGlow.blend = BlendMode.ADD; - - 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'])); - - moreWays.funnyColor = 0xFFFFF383; - moreWays.speed = 6.8; - grpTxtScrolls.add(moreWays); - - exitMovers.set([moreWays], - { - x: FlxG.width * 2, - speed: 0.4, - }); - - funnyScroll.funnyColor = 0xFFFF9963; - funnyScroll.speed = -3.8; - grpTxtScrolls.add(funnyScroll); - - exitMovers.set([funnyScroll], - { - x: -funnyScroll.width * 2, - y: funnyScroll.y, - speed: 0.4, - wait: 0 - }); - - txtNuts.speed = 3.5; - grpTxtScrolls.add(txtNuts); - exitMovers.set([txtNuts], - { - x: FlxG.width * 2, - speed: 0.4, - }); - - funnyScroll2.funnyColor = 0xFFFF9963; - funnyScroll2.speed = -3.8; - grpTxtScrolls.add(funnyScroll2); - - exitMovers.set([funnyScroll2], - { - x: -funnyScroll2.width * 2, - speed: 0.5, - }); - - moreWays2.funnyColor = 0xFFFFF383; - moreWays2.speed = 6.8; - grpTxtScrolls.add(moreWays2); - - exitMovers.set([moreWays2], - { - x: FlxG.width * 2, - speed: 0.4 - }); - - funnyScroll3.funnyColor = 0xFFFEA400; - funnyScroll3.speed = -3.8; - grpTxtScrolls.add(funnyScroll3); - - exitMovers.set([funnyScroll3], - { - x: -funnyScroll3.width * 2, - speed: 0.3 - }); - - add(backingTextYeah); - - cardGlow.blend = BlendMode.ADD; - cardGlow.visible = false; - - add(cardGlow); + if (backingCard != null) + { + add(backingCard); + backingCard.init(); + backingCard.applyExitMovers(exitMovers, exitMoversCharSel); + } if (currentCharacter?.getFreeplayDJData() != null) { @@ -477,6 +361,12 @@ class FreeplayState extends MusicBeatSubState speed: 0.5 }); add(dj); + exitMoversCharSel.set([dj], + { + y: -175, + speed: 0.8, + wait: 0.1 + }); } bgDad.shader = new AngleMask(); @@ -499,8 +389,16 @@ class FreeplayState extends MusicBeatSubState wait: 0 }); + exitMoversCharSel.set([blackOverlayBullshitLOLXD, bgDad], + { + y: -100, + speed: 0.8, + wait: 0.1 + }); + add(bgDad); - FlxTween.tween(blackOverlayBullshitLOLXD, {x: pinkBack.width * 0.74}, 0.7, {ease: FlxEase.quintOut}); + // backingCard.pinkBack.width * 0.74 + FlxTween.tween(blackOverlayBullshitLOLXD, {x: 387.76}, 0.7, {ease: FlxEase.quintOut}); blackOverlayBullshitLOLXD.shader = bgDad.shader; @@ -520,6 +418,13 @@ class FreeplayState extends MusicBeatSubState wait: 0 }); + exitMoversCharSel.set([grpDifficulties], + { + y: -270, + speed: 0.8, + wait: 0.1 + }); + for (diffId in diffIdsTotal) { var diffSprite:DifficultySprite = new DifficultySprite(diffId); @@ -540,12 +445,12 @@ class FreeplayState extends MusicBeatSubState albumRoll.albumId = null; add(albumRoll); - albumRoll.applyExitMovers(exitMovers); + albumRoll.applyExitMovers(exitMovers, exitMoversCharSel); - var overhangStuff:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, 64, FlxColor.BLACK); + var overhangStuff:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, 164, FlxColor.BLACK); overhangStuff.y -= overhangStuff.height; - add(overhangStuff); - FlxTween.tween(overhangStuff, {y: 0}, 0.3, {ease: FlxEase.quartOut}); + + FlxTween.tween(overhangStuff, {y: -100}, 0.3, {ease: FlxEase.quartOut}); var fnfFreeplay:FlxText = new FlxText(8, 8, 0, 'FREEPLAY', 48); fnfFreeplay.font = 'VCR OSD Mono'; @@ -563,11 +468,16 @@ class FreeplayState extends MusicBeatSubState wait: 0 }); + exitMoversCharSel.set([overhangStuff, fnfFreeplay, ostName], + { + y: -300, + speed: 0.8, + wait: 0.1 + }); + var sillyStroke:StrokeShader = new StrokeShader(0xFFFFFFFF, 2, 2); fnfFreeplay.shader = sillyStroke; ostName.shader = sillyStroke; - add(fnfFreeplay); - add(ostName); var fnfHighscoreSpr:FlxSprite = new FlxSprite(860, 70); fnfHighscoreSpr.frames = Paths.getSparrowAtlas('freeplay/highscore'); @@ -601,6 +511,13 @@ class FreeplayState extends MusicBeatSubState speed: 0.3 }); + exitMoversCharSel.set([letterSort], + { + y: -270, + speed: 0.8, + wait: 0.1 + }); + letterSort.changeSelectionCallback = (str) -> { switch (str) { @@ -630,6 +547,13 @@ class FreeplayState extends MusicBeatSubState speed: 0.3 }); + exitMoversCharSel.set([fp, txtCompletion, fnfHighscoreSpr, txtCompletion, clearBoxSprite], + { + y: -270, + speed: 0.8, + wait: 0.1 + }); + var diffSelLeft:DifficultySelector = new DifficultySelector(20, grpDifficulties.y - 10, false, controls); var diffSelRight:DifficultySelector = new DifficultySelector(325, grpDifficulties.y - 10, true, controls); diffSelLeft.visible = false; @@ -637,6 +561,11 @@ class FreeplayState extends MusicBeatSubState add(diffSelLeft); add(diffSelRight); + // putting these here to fix the layering + add(overhangStuff); + add(fnfFreeplay); + add(ostName); + // be careful not to "add()" things in here unless it's to a group that's already added to the state // otherwise it won't be properly attatched to funnyCamera (relavent code should be at the bottom of create()) var onDJIntroDone = function() { @@ -656,6 +585,13 @@ class FreeplayState extends MusicBeatSubState speed: 0.26 }); + exitMoversCharSel.set([diffSelLeft, diffSelRight], + { + y: -270, + speed: 0.8, + wait: 0.1 + }); + new FlxTimer().start(1 / 24, function(handShit) { fnfHighscoreSpr.visible = true; fnfFreeplay.visible = true; @@ -674,18 +610,12 @@ class FreeplayState extends MusicBeatSubState }); }); - pinkBack.color = 0xFFFFD863; bgDad.visible = true; - orangeBackShit.visible = true; - alsoOrangeLOL.visible = true; - grpTxtScrolls.visible = true; + backingCard?.introDone(); // render optimisation if (_parentState != null) _parentState.persistentDraw = false; - cardGlow.visible = true; - FlxTween.tween(cardGlow, {alpha: 0, "scale.x": 1.2, "scale.y": 1.2}, 0.45, {ease: FlxEase.sineOut}); - if (prepForNewRank && fromResultsParams != null) { rankAnimStart(fromResultsParams); @@ -872,7 +802,7 @@ class FreeplayState extends MusicBeatSubState return str.songName.toLowerCase().startsWith(songFilter.filterData ?? ''); }); case ALL: - // no filter! + // no filter! case FAVORITE: songsToFilter = songsToFilter.filter(str -> { if (str == null) return true; // Random @@ -1174,6 +1104,62 @@ class FreeplayState extends MusicBeatSubState }); } + function goToCharSelect():Void + { + var transitionGradient = new FlxSprite(0, 720).loadGraphic(Paths.image('freeplay/transitionGradient')); + transitionGradient.scale.set(1280, 1); + transitionGradient.updateHitbox(); + transitionGradient.cameras = [rankCamera]; + exitMoversCharSel.set([transitionGradient], + { + y: -720, + speed: 0.8, + wait: 0.1 + }); + add(transitionGradient); + // busy = true; + for (index => capsule in grpCapsules.members) + { + var distFromSelected:Float = Math.abs(index - curSelected) - 1; + if (distFromSelected < 5) + { + capsule.doLerp = false; + exitMoversCharSel.set([capsule], + { + y: -250, + speed: 0.8, + wait: 0.1 + }); + } + } + fadeShader.fade(1.0, 0.0, 0.8, {ease: FlxEase.quadIn}); + FlxG.sound.music.fadeOut(0.9, 0); + // FlxTween.tween(transitionGradient, {y: 0}, 1, {ease: FlxEase.expoOut, startDelay: 0.3}); + new FlxTimer().start(0.9, _ -> { + FlxG.switchState(new funkin.ui.charSelect.CharSelectSubState()); + }); + for (grpSpr in exitMoversCharSel.keys()) + { + var moveData:Null = exitMoversCharSel.get(grpSpr); + if (moveData == null) continue; + + for (spr in grpSpr) + { + if (spr == null) continue; + + var funnyMoveShit:MoveData = moveData; + + var moveDataX = funnyMoveShit.x ?? spr.x; + var moveDataY = funnyMoveShit.y ?? spr.y; + var moveDataSpeed = funnyMoveShit.speed ?? 0.2; + var moveDataWait = funnyMoveShit.wait ?? 0.0; + + FlxTween.tween(spr, {x: moveDataX, y: moveDataY + spr.y}, moveDataSpeed, {ease: FlxEase.backIn}); + // longestTimer = Math.max(longestTimer, moveDataSpeed + moveDataWait); + } + } + } + var touchY:Float = 0; var touchX:Float = 0; var dxTouch:Float = 0; @@ -1199,16 +1185,9 @@ class FreeplayState extends MusicBeatSubState { super.update(elapsed); - #if debug - if (FlxG.keys.justPressed.T) + if (FlxG.keys.justPressed.G) { - rankAnimStart(fromResultsParams ?? - { - playRankAnim: true, - newRank: PERFECT_GOLD, - songId: "tutorial", - difficultyId: "hard" - }); + goToCharSelect(); } if (FlxG.keys.justPressed.P) @@ -1221,6 +1200,18 @@ class FreeplayState extends MusicBeatSubState })); } + #if debug + if (FlxG.keys.justPressed.T) + { + rankAnimStart(fromResultsParams ?? + { + playRankAnim: true, + newRank: PERFECT_GOLD, + songId: "tutorial", + difficultyId: "hard" + }); + } + // if (FlxG.keys.justPressed.H) // { // rankDisplayNew(fromResultsParams); @@ -1495,23 +1486,7 @@ 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; + backingCard?.disappear(); for (grpSpr in exitMovers.keys()) { @@ -1787,39 +1762,7 @@ class FreeplayState extends MusicBeatSubState grpCapsules.members[curSelected].forcePosition(); grpCapsules.members[curSelected].confirm(); - // 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.playAnimation("BF back card confirm raw", false, 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; + backingCard?.confirm(); new FlxTimer().start(1, function(tmr:FlxTimer) { FunkinSound.emptyPartialQueue(); diff --git a/source/funkin/ui/freeplay/backcards/BackingCard.hx b/source/funkin/ui/freeplay/backcards/BackingCard.hx new file mode 100644 index 000000000..8a2a2c910 --- /dev/null +++ b/source/funkin/ui/freeplay/backcards/BackingCard.hx @@ -0,0 +1,217 @@ +package funkin.ui.freeplay.backcards; + +import funkin.ui.freeplay.FreeplayState; +import flixel.FlxCamera; +import flixel.FlxSprite; +import flixel.group.FlxGroup; +import flixel.group.FlxGroup.FlxTypedGroup; +import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup; +import flixel.math.FlxAngle; +import flixel.math.FlxPoint; +import flixel.text.FlxText; +import flixel.tweens.FlxEase; +import flixel.tweens.FlxTween; +import flixel.util.FlxColor; +import flixel.util.FlxSpriteUtil; +import flixel.util.FlxTimer; +import funkin.graphics.adobeanimate.FlxAtlasSprite; +import funkin.graphics.FunkinSprite; +import funkin.ui.freeplay.charselect.PlayableCharacter; +import funkin.ui.MusicBeatSubState; +import lime.utils.Assets; +import openfl.display.BlendMode; +import flixel.group.FlxSpriteGroup; + +/** + * A class for the backing cards so they dont have to be part of freeplayState...... + */ +class BackingCard extends FlxSpriteGroup +{ + public var backingTextYeah:FlxAtlasSprite; + public var orangeBackShit:FunkinSprite; + public var alsoOrangeLOL:FunkinSprite; + public var pinkBack:FunkinSprite; + public var confirmGlow:FlxSprite; + public var confirmGlow2:FlxSprite; + public var confirmTextGlow:FlxSprite; + public var cardGlow:FlxSprite; + + var _exitMovers:Null; + var _exitMoversCharSel:Null; + + public function new(currentCharacter:PlayableCharacter) + { + super(); + + cardGlow = new FlxSprite(-30, -30).loadGraphic(Paths.image('freeplay/cardGlow')); + confirmGlow = new FlxSprite(-30, 240).loadGraphic(Paths.image('freeplay/confirmGlow')); + confirmTextGlow = new FlxSprite(-8, 115).loadGraphic(Paths.image('freeplay/glowingText')); + pinkBack = FunkinSprite.create('freeplay/pinkBack'); + orangeBackShit = new FunkinSprite(84, 440).makeSolidColor(Std.int(pinkBack.width), 75, 0xFFFEDA00); + alsoOrangeLOL = new FunkinSprite(0, orangeBackShit.y).makeSolidColor(100, Std.int(orangeBackShit.height), 0xFFFFD400); + confirmGlow2 = new FlxSprite(confirmGlow.x, confirmGlow.y).loadGraphic(Paths.image('freeplay/confirmGlow2')); + 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), + }); + + pinkBack.color = 0xFFFFD4E9; // sets it to pink! + pinkBack.x -= pinkBack.width; + } + + /** + * Apply exit movers for the pieces of the backing card. + * @param exitMovers The exit movers to apply. + */ + public function applyExitMovers(?exitMovers:FreeplayState.ExitMoverData, ?exitMoversCharSel:FreeplayState.ExitMoverData):Void + { + if (exitMovers == null) + { + exitMovers = _exitMovers; + } + else + { + _exitMovers = exitMovers; + } + + if (exitMovers == null) return; + + if (exitMoversCharSel == null) + { + exitMoversCharSel = _exitMoversCharSel; + } + else + { + _exitMoversCharSel = exitMoversCharSel; + } + + if (exitMoversCharSel == null) return; + + exitMovers.set([pinkBack, orangeBackShit, alsoOrangeLOL], + { + x: -pinkBack.width, + y: pinkBack.y, + speed: 0.4, + wait: 0 + }); + + exitMoversCharSel.set([pinkBack], + { + y: -100, + speed: 0.8, + wait: 0.1 + }); + + exitMoversCharSel.set([orangeBackShit, alsoOrangeLOL], + { + y: -40, + speed: 0.8, + wait: 0.1 + }); + } + + /** + * Called in create. Adds sprites and tweens. + */ + public function init():Void + { + FlxTween.tween(pinkBack, {x: 0}, 0.6, {ease: FlxEase.quartOut}); + add(pinkBack); + + add(orangeBackShit); + + add(alsoOrangeLOL); + + FlxSpriteUtil.alphaMaskFlxSprite(orangeBackShit, pinkBack, orangeBackShit); + orangeBackShit.visible = false; + alsoOrangeLOL.visible = false; + + confirmTextGlow.blend = BlendMode.ADD; + confirmTextGlow.visible = false; + + confirmGlow.blend = BlendMode.ADD; + + confirmGlow.visible = false; + confirmGlow2.visible = false; + + add(confirmGlow2); + add(confirmGlow); + + add(confirmTextGlow); + + add(backingTextYeah); + + cardGlow.blend = BlendMode.ADD; + cardGlow.visible = false; + + add(cardGlow); + } + + /** + * Override parts of Freeplay depending on the card class. + */ + public function applyStyle(_freeplayState:FreeplayState):Void {} + + /** + * Called after the dj finishes their start animation. + */ + public function introDone():Void + { + pinkBack.color = 0xFFFFD863; + orangeBackShit.visible = true; + alsoOrangeLOL.visible = true; + cardGlow.visible = true; + FlxTween.tween(cardGlow, {alpha: 0, "scale.x": 1.2, "scale.y": 1.2}, 0.45, {ease: FlxEase.sineOut}); + } + + /** + * Called when selecting a song. + */ + public function confirm():Void + { + FlxTween.color(pinkBack, 0.33, 0xFFFFD0D5, 0xFF171831, {ease: FlxEase.quadOut}); + orangeBackShit.visible = false; + alsoOrangeLOL.visible = false; + + confirmGlow.visible = true; + confirmGlow2.visible = true; + + backingTextYeah.playAnimation("BF back card confirm raw", false, 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); + } + }); + } + + /** + * Called when exiting the freeplay menu + */ + public function disappear():Void + { + 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; + } +} diff --git a/source/funkin/ui/freeplay/backcards/BoyfriendCard.hx b/source/funkin/ui/freeplay/backcards/BoyfriendCard.hx new file mode 100644 index 000000000..737a0a2dc --- /dev/null +++ b/source/funkin/ui/freeplay/backcards/BoyfriendCard.hx @@ -0,0 +1,168 @@ +package funkin.ui.freeplay.backcards; + +import funkin.ui.freeplay.FreeplayState; +import flixel.FlxCamera; +import flixel.FlxSprite; +import flixel.group.FlxGroup; +import flixel.group.FlxGroup.FlxTypedGroup; +import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup; +import flixel.math.FlxAngle; +import flixel.math.FlxPoint; +import flixel.text.FlxText; +import flixel.tweens.FlxEase; +import flixel.tweens.FlxTween; +import flixel.util.FlxColor; +import flixel.util.FlxSpriteUtil; +import flixel.util.FlxTimer; +import funkin.graphics.adobeanimate.FlxAtlasSprite; +import funkin.graphics.FunkinSprite; +import funkin.ui.freeplay.charselect.PlayableCharacter; +import funkin.ui.MusicBeatSubState; +import lime.utils.Assets; +import openfl.display.BlendMode; +import flixel.group.FlxSpriteGroup; + +/** + * A class for the backing cards so they dont have to be part of freeplayState...... + */ +class BoyfriendCard extends BackingCard +{ + public var moreWays:BGScrollingText; + public var funnyScroll:BGScrollingText; + public var txtNuts:BGScrollingText; + public var funnyScroll2:BGScrollingText; + public var moreWays2:BGScrollingText; + public var funnyScroll3:BGScrollingText; + + public override function applyExitMovers(?exitMovers:FreeplayState.ExitMoverData, ?exitMoversCharSel:FreeplayState.ExitMoverData):Void + { + super.applyExitMovers(exitMovers, exitMoversCharSel); + if (exitMovers == null || exitMoversCharSel == null) return; + exitMovers.set([moreWays], + { + x: FlxG.width * 2, + speed: 0.4, + }); + exitMovers.set([funnyScroll], + { + x: -funnyScroll.width * 2, + y: funnyScroll.y, + speed: 0.4, + wait: 0 + }); + exitMovers.set([txtNuts], + { + x: FlxG.width * 2, + speed: 0.4, + }); + exitMovers.set([funnyScroll2], + { + x: -funnyScroll2.width * 2, + speed: 0.5, + }); + exitMovers.set([moreWays2], + { + x: FlxG.width * 2, + speed: 0.4 + }); + exitMovers.set([funnyScroll3], + { + x: -funnyScroll3.width * 2, + speed: 0.3 + }); + + exitMoversCharSel.set([moreWays, funnyScroll, txtNuts, funnyScroll2, moreWays2, funnyScroll3], + { + y: -60, + speed: 0.8, + wait: 0.1 + }); + } + + public override function new(currentCharacter:PlayableCharacter) + { + super(currentCharacter); + + funnyScroll = new BGScrollingText(0, 220, currentCharacter.getFreeplayDJText(1), FlxG.width / 2, false, 60); + funnyScroll2 = new BGScrollingText(0, 335, currentCharacter.getFreeplayDJText(1), FlxG.width / 2, false, 60); + moreWays = new BGScrollingText(0, 160, currentCharacter.getFreeplayDJText(2), FlxG.width, true, 43); + moreWays2 = new BGScrollingText(0, 397, currentCharacter.getFreeplayDJText(2), FlxG.width, true, 43); + txtNuts = new BGScrollingText(0, 285, currentCharacter.getFreeplayDJText(3), FlxG.width / 2, true, 43); + funnyScroll3 = new BGScrollingText(0, orangeBackShit.y + 10, currentCharacter.getFreeplayDJText(1), FlxG.width / 2, 60); + } + + public override function init():Void + { + super.init(); + + // var grpTxtScrolls:FlxGroup = new FlxGroup(); + // add(grpTxtScrolls); + + moreWays.visible = false; + funnyScroll.visible = false; + txtNuts.visible = false; + funnyScroll2.visible = false; + moreWays2.visible = false; + funnyScroll3.visible = false; + + moreWays.funnyColor = 0xFFFFF383; + moreWays.speed = 6.8; + add(moreWays); + + funnyScroll.funnyColor = 0xFFFF9963; + funnyScroll.speed = -3.8; + add(funnyScroll); + + txtNuts.speed = 3.5; + add(txtNuts); + + funnyScroll2.funnyColor = 0xFFFF9963; + funnyScroll2.speed = -3.8; + add(funnyScroll2); + + moreWays2.funnyColor = 0xFFFFF383; + moreWays2.speed = 6.8; + add(moreWays2); + + funnyScroll3.funnyColor = 0xFFFEA400; + funnyScroll3.speed = -3.8; + add(funnyScroll3); + } + + public override function introDone():Void + { + super.introDone(); + moreWays.visible = true; + funnyScroll.visible = true; + txtNuts.visible = true; + funnyScroll2.visible = true; + moreWays2.visible = true; + funnyScroll3.visible = true; + // grpTxtScrolls.visible = true; + } + + public override function confirm():Void + { + super.confirm(); + // FlxTween.color(bgDad, 0.33, 0xFFFFFFFF, 0xFF555555, {ease: FlxEase.quadOut}); + + moreWays.visible = false; + funnyScroll.visible = false; + txtNuts.visible = false; + funnyScroll2.visible = false; + moreWays2.visible = false; + funnyScroll3.visible = false; + } + + public override function disappear():Void + { + super.disappear(); + + moreWays.visible = false; + funnyScroll.visible = false; + txtNuts.visible = false; + funnyScroll2.visible = false; + moreWays2.visible = false; + funnyScroll3.visible = false; + } +} diff --git a/source/funkin/ui/freeplay/backcards/PicoCard.hx b/source/funkin/ui/freeplay/backcards/PicoCard.hx new file mode 100644 index 000000000..a424a76ef --- /dev/null +++ b/source/funkin/ui/freeplay/backcards/PicoCard.hx @@ -0,0 +1,74 @@ +package funkin.ui.freeplay.backcards; + +import funkin.ui.freeplay.FreeplayState; +import flixel.FlxCamera; +import flixel.FlxSprite; +import flixel.group.FlxGroup; +import flixel.group.FlxGroup.FlxTypedGroup; +import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup; +import flixel.math.FlxAngle; +import flixel.math.FlxPoint; +import flixel.text.FlxText; +import flixel.tweens.FlxEase; +import flixel.tweens.FlxTween; +import flixel.util.FlxColor; +import flixel.util.FlxSpriteUtil; +import flixel.util.FlxTimer; +import funkin.graphics.adobeanimate.FlxAtlasSprite; +import funkin.graphics.FunkinSprite; +import funkin.ui.freeplay.charselect.PlayableCharacter; +import funkin.ui.MusicBeatSubState; +import lime.utils.Assets; +import openfl.display.BlendMode; +import flixel.group.FlxSpriteGroup; + +/** + * A class for the backing cards so they dont have to be part of freeplayState...... + */ +class PicoCard extends BackingCard +{ + public override function init():Void + { + FlxTween.tween(pinkBack, {x: 0}, 0.6, {ease: FlxEase.quartOut}); + add(pinkBack); + + // add(orangeBackShit); + + // add(alsoOrangeLOL); + + // FlxSpriteUtil.alphaMaskFlxSprite(orangeBackShit, pinkBack, orangeBackShit); + // orangeBackShit.visible = false; + // alsoOrangeLOL.visible = false; + + confirmTextGlow.blend = BlendMode.ADD; + confirmTextGlow.visible = false; + + confirmGlow.blend = BlendMode.ADD; + + confirmGlow.visible = false; + confirmGlow2.visible = false; + + add(confirmGlow2); + add(confirmGlow); + + add(confirmTextGlow); + + add(backingTextYeah); + + cardGlow.blend = BlendMode.ADD; + cardGlow.visible = false; + + add(cardGlow); + } + + public override function applyStyle(_freeplayState:FreeplayState):Void {} + + public override function introDone():Void + { + pinkBack.color = 0xFF98A2F3; + // orangeBackShit.visible = true; + // alsoOrangeLOL.visible = true; + cardGlow.visible = true; + FlxTween.tween(cardGlow, {alpha: 0, "scale.x": 1.2, "scale.y": 1.2}, 0.45, {ease: FlxEase.sineOut}); + } +} From 9e1d328a0f3ae6236cf036abf78d54bd24c0a7ab Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Fri, 23 Aug 2024 13:37:50 +0100 Subject: [PATCH 596/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 2eac23629..0d97c9b20 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 2eac236291775208ce71287a5c27f8f15ae591c9 +Subproject commit 0d97c9b20a989b4517fd6174fe56583ac600522c From 00c7767f8a82304a7b7595e041ad60dbbc8cb3ca Mon Sep 17 00:00:00 2001 From: cyn Date: Fri, 23 Aug 2024 20:17:10 -0700 Subject: [PATCH 597/870] Update FunkinSound.hx --- source/funkin/audio/FunkinSound.hx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index c70f195d2..7105a8735 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -543,11 +543,12 @@ class FunkinSound extends FlxSound implements ICloneable /** * Stop all sounds in the pool and allow them to be recycled. */ - public static function stopAllAudio(musicToo:Bool = false):Void + public static function stopAllAudio(musicToo:Bool = false, persistToo:Bool = false):Void { for (sound in pool) { if (sound == null) continue; + if (!persistToo && sound.persist) continue; if (!musicToo && sound == FlxG.sound.music) continue; sound.destroy(); } From 025c186ddc5e9b68109835ac800b0d8cbb23dc39 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 26 Aug 2024 13:18:05 -0400 Subject: [PATCH 598/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index b57d7f8d3..2ad892c76 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit b57d7f8d308e468f7b0947d4784d0efeca44d9aa +Subproject commit 2ad892c76665abad5764137288c606f2f4fcd331 From 0b19b4bc25806ab9ae82376946937c3e95b7feb8 Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Mon, 26 Aug 2024 20:34:14 +0200 Subject: [PATCH 599/870] add the maskTest Bizz --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 299f5ac20..0e4392bcb 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 299f5ac20fd9ee50fda5cadd6abb22b68d86fb87 +Subproject commit 0e4392bcb0ed1dbb496764cff074635c20c91389 From a1714711e3f85f207b47dab03899543428bce3f1 Mon Sep 17 00:00:00 2001 From: mint Date: Mon, 26 Aug 2024 17:52:37 +0200 Subject: [PATCH 600/870] swap docker image deps --- .github/actions/setup-haxe/action.yml | 5 ++--- .github/workflows/build-game.yml | 1 + build/Dockerfile | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/actions/setup-haxe/action.yml b/.github/actions/setup-haxe/action.yml index b22fc6f69..cf74cfb63 100644 --- a/.github/actions/setup-haxe/action.yml +++ b/.github/actions/setup-haxe/action.yml @@ -56,11 +56,10 @@ runs: shell: bash run: | echo "TIMER_HAXELIB=$(date +%s)" >> "$GITHUB_ENV" - haxelib --debug --never install haxelib 4.1.0 --global - haxelib --debug --never deleterepo || true + haxelib --debug --always git haxelib https://github.com/FunkinCrew/haxelib.git funkin-patches --skip-dependencies --global + rm -rf .haxelib haxelib --debug --never newrepo echo "HAXEPATH=$(haxelib config)" >> "$GITHUB_ENV" - haxelib --debug --always --global git haxelib https://github.com/FunkinCrew/haxelib.git funkin-patches --skip-dependencies haxelib --debug --global --always git hmm https://github.com/FunkinCrew/hmm funkin-patches echo "TIMER_DEPS=$(date +%s)" >> "$GITHUB_ENV" diff --git a/.github/workflows/build-game.yml b/.github/workflows/build-game.yml index ba8167607..46f478a14 100644 --- a/.github/workflows/build-game.yml +++ b/.github/workflows/build-game.yml @@ -112,6 +112,7 @@ jobs: run: | git config --global 'url.https://x-access-token:${{ steps.app_token.outputs.token }}@github.com/.insteadOf' https://github.com/ haxelib --global run hmm install -q + cd .haxelib/hxcpp/git/tools/hxcpp && haxe compile.hxml - if: ${{ matrix.target != 'html5' }} name: Restore hxcpp cache diff --git a/build/Dockerfile b/build/Dockerfile index c545d1364..0e61bd92c 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -137,8 +137,8 @@ ENV PATH="$HAXEPATH:$PATH" RUN < Date: Mon, 26 Aug 2024 18:12:16 +0200 Subject: [PATCH 601/870] pulseaudio --- .github/actions/setup-haxe/action.yml | 2 +- build/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/setup-haxe/action.yml b/.github/actions/setup-haxe/action.yml index cf74cfb63..298dda631 100644 --- a/.github/actions/setup-haxe/action.yml +++ b/.github/actions/setup-haxe/action.yml @@ -44,7 +44,7 @@ runs: g++ \ libx11-dev libxi-dev libxext-dev libxinerama-dev libxrandr-dev \ libgl-dev libgl1-mesa-dev \ - libasound2-dev + libasound2-dev libpulse-dev ln -s /usr/lib/x86_64-linux-gnu/libffi.so.8 /usr/lib/x86_64-linux-gnu/libffi.so.6 || true - name: Install linux-specific dependencies if: ${{ runner.os == 'Linux' && contains(inputs.targets, 'linux') }} diff --git a/build/Dockerfile b/build/Dockerfile index 0e61bd92c..318870166 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -83,7 +83,7 @@ apt-fast install -y --no-install-recommends \ libc6-dev libffi-dev \ libx11-dev libxi-dev libxext-dev libxinerama-dev libxrandr-dev \ libgl-dev libgl1-mesa-dev \ - libasound2-dev \ + libasound2-dev libpulse-dev \ libvlc-dev libvlccore-dev EOF From 1089764ab62a174525aaa6159e15db04b91df20a Mon Sep 17 00:00:00 2001 From: mint Date: Mon, 26 Aug 2024 18:56:32 +0200 Subject: [PATCH 602/870] suppress useless git warnings --- .github/workflows/build-game.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-game.yml b/.github/workflows/build-game.yml index 46f478a14..dff9a369d 100644 --- a/.github/workflows/build-game.yml +++ b/.github/workflows/build-game.yml @@ -111,6 +111,7 @@ jobs: name: Install dependencies run: | git config --global 'url.https://x-access-token:${{ steps.app_token.outputs.token }}@github.com/.insteadOf' https://github.com/ + git config --global advice.detachedHead false haxelib --global run hmm install -q cd .haxelib/hxcpp/git/tools/hxcpp && haxe compile.hxml From 7cac3c95eea321367803ebb77c8e8c4a9de098a8 Mon Sep 17 00:00:00 2001 From: mint Date: Mon, 26 Aug 2024 19:27:11 +0200 Subject: [PATCH 603/870] config the haxelib :eye: --- .github/actions/setup-haxe/action.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/actions/setup-haxe/action.yml b/.github/actions/setup-haxe/action.yml index 298dda631..918718c55 100644 --- a/.github/actions/setup-haxe/action.yml +++ b/.github/actions/setup-haxe/action.yml @@ -56,11 +56,14 @@ runs: shell: bash run: | echo "TIMER_HAXELIB=$(date +%s)" >> "$GITHUB_ENV" - haxelib --debug --always git haxelib https://github.com/FunkinCrew/haxelib.git funkin-patches --skip-dependencies --global + haxelib remove --global haxelib git + haxelib remove --global hmm git rm -rf .haxelib + git config -l --show-scope + haxelib --debug --never --global git haxelib https://github.com/FunkinCrew/haxelib.git funkin-patches --skip-dependencies + haxelib --debug --never --global git hmm https://github.com/FunkinCrew/hmm funkin-patches haxelib --debug --never newrepo echo "HAXEPATH=$(haxelib config)" >> "$GITHUB_ENV" - haxelib --debug --global --always git hmm https://github.com/FunkinCrew/hmm funkin-patches echo "TIMER_DEPS=$(date +%s)" >> "$GITHUB_ENV" - name: Restore cached dependencies From 0193bde70058e0017ac253ed053917b0752820bb Mon Sep 17 00:00:00 2001 From: mint Date: Mon, 26 Aug 2024 19:32:38 +0200 Subject: [PATCH 604/870] hm, pain --- .github/actions/setup-haxe/action.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/actions/setup-haxe/action.yml b/.github/actions/setup-haxe/action.yml index 918718c55..4a81d0079 100644 --- a/.github/actions/setup-haxe/action.yml +++ b/.github/actions/setup-haxe/action.yml @@ -56,13 +56,16 @@ runs: shell: bash run: | echo "TIMER_HAXELIB=$(date +%s)" >> "$GITHUB_ENV" - haxelib remove --global haxelib git - haxelib remove --global hmm git + haxelib --debug --never --global install haxelib 4.1.0 + haxelib --global set haxelib 4.1.0 + haxelib --global remove haxelib git + haxelib --global remove hmm git rm -rf .haxelib git config -l --show-scope haxelib --debug --never --global git haxelib https://github.com/FunkinCrew/haxelib.git funkin-patches --skip-dependencies haxelib --debug --never --global git hmm https://github.com/FunkinCrew/hmm funkin-patches haxelib --debug --never newrepo + haxelib version echo "HAXEPATH=$(haxelib config)" >> "$GITHUB_ENV" echo "TIMER_DEPS=$(date +%s)" >> "$GITHUB_ENV" From 8010441befab58f56e5ef12859555a4c41762d96 Mon Sep 17 00:00:00 2001 From: mint Date: Mon, 26 Aug 2024 19:34:30 +0200 Subject: [PATCH 605/870] haxelib --- .github/actions/setup-haxe/action.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/actions/setup-haxe/action.yml b/.github/actions/setup-haxe/action.yml index 4a81d0079..193c81d1f 100644 --- a/.github/actions/setup-haxe/action.yml +++ b/.github/actions/setup-haxe/action.yml @@ -56,10 +56,11 @@ runs: shell: bash run: | echo "TIMER_HAXELIB=$(date +%s)" >> "$GITHUB_ENV" + haxelib fixrepo --global haxelib --debug --never --global install haxelib 4.1.0 haxelib --global set haxelib 4.1.0 haxelib --global remove haxelib git - haxelib --global remove hmm git + haxelib --global remove hmm rm -rf .haxelib git config -l --show-scope haxelib --debug --never --global git haxelib https://github.com/FunkinCrew/haxelib.git funkin-patches --skip-dependencies From 514aa576eafdb5fc5444d1689be5765053e940cd Mon Sep 17 00:00:00 2001 From: mint Date: Mon, 26 Aug 2024 19:35:54 +0200 Subject: [PATCH 606/870] haxelib --- .github/actions/setup-haxe/action.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/actions/setup-haxe/action.yml b/.github/actions/setup-haxe/action.yml index 193c81d1f..aba5371b5 100644 --- a/.github/actions/setup-haxe/action.yml +++ b/.github/actions/setup-haxe/action.yml @@ -56,11 +56,10 @@ runs: shell: bash run: | echo "TIMER_HAXELIB=$(date +%s)" >> "$GITHUB_ENV" - haxelib fixrepo --global + haxelib fixrepo --global || true haxelib --debug --never --global install haxelib 4.1.0 - haxelib --global set haxelib 4.1.0 - haxelib --global remove haxelib git - haxelib --global remove hmm + haxelib --global remove haxelib git || true + haxelib --global remove hmm || true rm -rf .haxelib git config -l --show-scope haxelib --debug --never --global git haxelib https://github.com/FunkinCrew/haxelib.git funkin-patches --skip-dependencies From 266bf939a977c8136bce647a4475cdc6ebe1f69e Mon Sep 17 00:00:00 2001 From: mint Date: Mon, 26 Aug 2024 19:38:21 +0200 Subject: [PATCH 607/870] haxelib --- .github/actions/setup-haxe/action.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/setup-haxe/action.yml b/.github/actions/setup-haxe/action.yml index aba5371b5..97bc02e66 100644 --- a/.github/actions/setup-haxe/action.yml +++ b/.github/actions/setup-haxe/action.yml @@ -58,6 +58,7 @@ runs: echo "TIMER_HAXELIB=$(date +%s)" >> "$GITHUB_ENV" haxelib fixrepo --global || true haxelib --debug --never --global install haxelib 4.1.0 + haxelib --debug --global set haxelib 4.1.0 haxelib --global remove haxelib git || true haxelib --global remove hmm || true rm -rf .haxelib From a778555a973bc3227689b592aec084f349579640 Mon Sep 17 00:00:00 2001 From: mint Date: Mon, 26 Aug 2024 19:52:53 +0200 Subject: [PATCH 608/870] more debug info --- .github/actions/setup-haxe/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/setup-haxe/action.yml b/.github/actions/setup-haxe/action.yml index 97bc02e66..9da7d3272 100644 --- a/.github/actions/setup-haxe/action.yml +++ b/.github/actions/setup-haxe/action.yml @@ -62,7 +62,7 @@ runs: haxelib --global remove haxelib git || true haxelib --global remove hmm || true rm -rf .haxelib - git config -l --show-scope + git config -l --show-scope --show-origin haxelib --debug --never --global git haxelib https://github.com/FunkinCrew/haxelib.git funkin-patches --skip-dependencies haxelib --debug --never --global git hmm https://github.com/FunkinCrew/hmm funkin-patches haxelib --debug --never newrepo From 3c208ee143c271f4fd1cf8293aa96680e04e135c Mon Sep 17 00:00:00 2001 From: mint Date: Mon, 26 Aug 2024 20:00:53 +0200 Subject: [PATCH 609/870] git cleanup crew --- .github/actions/setup-haxe/action.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/actions/setup-haxe/action.yml b/.github/actions/setup-haxe/action.yml index 9da7d3272..438f330a2 100644 --- a/.github/actions/setup-haxe/action.yml +++ b/.github/actions/setup-haxe/action.yml @@ -62,7 +62,6 @@ runs: haxelib --global remove haxelib git || true haxelib --global remove hmm || true rm -rf .haxelib - git config -l --show-scope --show-origin haxelib --debug --never --global git haxelib https://github.com/FunkinCrew/haxelib.git funkin-patches --skip-dependencies haxelib --debug --never --global git hmm https://github.com/FunkinCrew/hmm funkin-patches haxelib --debug --never newrepo @@ -81,7 +80,11 @@ runs: name: Prep git for dependency install uses: gacts/run-and-post-run@v1 with: - run: git config --global 'url.https://x-access-token:${{ inputs.gh-token }}@github.com/.insteadOf' https://github.com/ + run: | + git config --global --name-only --get-regexp 'url\.https\:\/\/x-access-token:.+@github\.com\/\.insteadOf' \ + | xargs git config --global --unset + git config -l --show-scope --show-origin + git config --global 'url.https://x-access-token:${{ inputs.gh-token }}@github.com/.insteadOf' https://github.com/ post: git config --global --unset 'url.https://x-access-token:${{ inputs.gh-token }}@github.com/.insteadOf' - if: ${{ steps.cache-hmm.outputs.cache-hit != 'true' }} From b51ba61d078b8a4247a0b09a01db53edc536b096 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 26 Aug 2024 17:14:15 -0400 Subject: [PATCH 610/870] Update art submodule --- art | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/art b/art index faeba700c..0bb988c49 160000 --- a/art +++ b/art @@ -1 +1 @@ -Subproject commit faeba700c5526bd4fd57ccc927d875c82b9d3553 +Subproject commit 0bb988c49788fd25a230b56dd9e4448838bc79c9 From f2433bfdcc4fa240687260e7ab7e450e035fd16c Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 26 Aug 2024 18:00:59 -0400 Subject: [PATCH 611/870] Updated CHANGELOG --- CHANGELOG.md | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 653ee203f..53e981284 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,62 @@ 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.5.0] - 2024-08-?? +### Added +- Added a new Character Select screen to switch between playable characters in Freeplay + - Modding isn't 100% there but we're working on it! +- Added Pico as a playable character! Unlock him by completing Weekend 1 (if you haven't already done that) + - The songs from Weekend 1 have moved; you must now switch to Pico in Freeplay to access them +- Added ## new Pico remixes! Access them by selecting Pico from in the Character Select screen +- Added 2 new Erect remixes! Access them by switching difficulty on the song +- Implemented support for a new Instrumental Selector in Freeplay + - Beating a Pico remix lets you use that instrumental when playing as Boyfriend +- Added the first batch of Erect Stages! These graphical overhauls of the original stages will be used when playing Erect remixes and Pico remixes +- Implemented support for scripted Note Kinds. You can use HScript define a different note style to display for these notes as well as custom behavior. (community feature by lemz1) +- Implemented a new Strumline Background option, to display a darkened background behind the strumline with your choice of opacity. +- Implemented support for Numeric and Selector options in the Options menu. (community feature by FlooferLand) +## Changed +- Girlfriend and Nene now perform previously unused animations when you achieve a large combo, or drop a large combo. +- The pixel character icons in the Freeplay menu now display an animation! +- Altered how Week 6 displays sprites to make things look more retro. +- Character offsets are now independent of the character's scale. + - This should resolve issues with offsets when porting characters from older mods. + - Pixel character offsets have been modified to compensate. +- Note style data can now specify custom combo count graphics, judgement graphics, countdown graphics, and countdown audio. (community feature by anysad) + - These were previously using hardcoded values based on whether the stage was `school` or `schoolEvil`. +- The `danceEvery` property of characters and stage props can now use values with a precision of `0.25`, to play their idle animation up to four times per beat. +- Reworked the JSON merging system in Polymod; you can now include JSONPatch files under `_merge` in your mod folder to add, modify, or remove values in a JSON without replacing it entirely! +- Cutscenes now automatically pause when tabbing out (community fix by AbnormalPoof) +- Characters will now respect the `danceEvery` property (community fix by gamerbross) +- The F5 function now reloads the current song's chart data from disc (community feature by gamerbross) +- Refactored the compilation guide and added common troubleshooting steps (community fix by Hundrec) +- Made several layout improvements and fixes to the Animation Offsets editor in the Debug menu (community fix by gamerbross) +- Fixed a bug where the Back sound would be not played when leaving the Story menu and Options menu (community fix by AppleHair) +- Animation offsets no longer directly modify the `x` and `y` position of props, which makes props work better with tweens (community fix by Sword352) +- The YEAH! events in Tutorial now use chart events rather than being hard-coded (community fix by anysad) +- The player's Score now displays commas in it (community fix by loggo) +## Fixed +- Fixed an issue where songs with no notes would crash on the Results screen. +- Fixed an issue where the old icon easter egg would not work properly on pixel levels. +- Fixed an issue where you could play notes during the Thorns cutscene. +- Fixed an issue where the Heart icon when favoriting a song in Freeplay would be malformed. +- Fixed an issue where Pico's death animation displays a faint blue background (community fix by doggogit) +- Fixed an issue where mod songs would not play a preview in the Freeplay menu (community fix by KarimAkra) +- Fixed an issue where the Memory Usage counter could overflow and display a negative number (community fix by KarimAkra) +- Fixed an issue where pressing the Chart Editor keybind while playtesting a chart would reset the chart editor (community fix by gamerbross) +- Fixed a crash bug when pressing F5 after seeing the sticker transition (community fix by gamerbross) +- Fixed an issue where the Story Mode menu couldn't be scrolled with a mouse (community fix by JVNpixels) +- Fixed an issue causing the song to majorly desync sometimes (community fix by Burgerballs) +- Fixed an issue where the Freeplay song preview would not respect the instrumental ID specified in the song metadata (community fix by AppleHair) +- Fixed an issue where Tankman's icon wouldn't display in the Chart Editor (community fix by hundrec) +- Fixed an issue where pausing the game during a camera zoom would zoom the pause menu. (community fix by gamerbros) +- Fixed an issue where certain UI elements would not flash at a consistent rate (community fix by cyn0x8) +- Fixed an issue where the game would not use the placeholder health icon as a fallback (community fix by gamerbross) +- Fixed an issue where the chart editor could get stuck creating a hold note when using Live Inputs (community fix by gamerbross) +- Fixed an issue where character graphics could not be placed in week folders (community fix by 7oltan) +- Fixed a crash issue when a Freeplay song has no `Normal` difficulty (community fix by Applehair and gamerbross) +- Fixed an issue in Story Mode where a song that isn't valid for the current variation could be selected (community fix by Applehair) + ## [0.4.1] - 2024-06-12 ### Added - Pressing ESCAPE on the title screen on desktop now exits the game, allowing you to exit the game while in fullscreen on desktop From 269f3ecfbe16b32698c0a6adcea4c8648faf509b Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 26 Aug 2024 18:01:06 -0400 Subject: [PATCH 612/870] Updated haxelibs --- hmm.json | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/hmm.json b/hmm.json index 4cd3e27c7..38e82acf2 100644 --- a/hmm.json +++ b/hmm.json @@ -1,5 +1,12 @@ { "dependencies": [ + { + "name": "FlxPartialSound", + "type": "git", + "dir": null, + "ref": "a1eab7b9bf507b87200a3341719054fe427f3b15", + "url": "https://github.com/FunkinCrew/FlxPartialSound.git" + }, { "name": "discord_rpc", "type": "git", @@ -32,7 +39,7 @@ "name": "flixel-ui", "type": "git", "dir": null, - "ref": "d0afed7293c71ffdb1184751317fc709b44c9056", + "ref": "27f1ba626f80a6282fa8a187115e79a4a2133dc2", "url": "https://github.com/HaxeFlixel/flixel-ui" }, { @@ -42,13 +49,6 @@ "ref": "768740a56b26aa0c072720e0d1236b94afe68e3e", "url": "https://github.com/Dot-Stuff/flxanimate" }, - { - "name": "FlxPartialSound", - "type": "git", - "dir": null, - "ref": "a1eab7b9bf507b87200a3341719054fe427f3b15", - "url": "https://github.com/FunkinCrew/FlxPartialSound.git" - }, { "name": "format", "type": "haxelib", @@ -59,7 +59,7 @@ "type": "git", "dir": null, "ref": "22b1ce089dd924f15cdc4632397ef3504d464e90", - "url": "https://github.com/MidyGamy/funkVis/" + "url": "https://github.com/FunkinCrew/funkVis" }, { "name": "grig.audio", @@ -89,8 +89,10 @@ }, { "name": "hscript", - "type": "haxelib", - "version": "2.5.0" + "type": "git", + "dir": null, + "ref": "59b33162e9dcd7e48b186a9f25ee81b6e47a4dd7", + "url": "https://github.com/haxefoundation/hscript" }, { "name": "hxCodec", @@ -104,7 +106,7 @@ "type": "git", "dir": null, "url": "https://github.com/HaxeFoundation/hxcpp", - "ref": "8dc8020f8465027de6c2aaaed90718bc693651ed" + "ref": "904ea40643b050a5a154c5e4c33a83fd2aec18b1" }, { "name": "hxcpp-debug-server", @@ -185,7 +187,7 @@ "name": "polymod", "type": "git", "dir": null, - "ref": "98945c6c7f5ecde01a32c4623d3515bf012a023a", + "ref": "96cfc5fa693b017e47f7cb13b765cc68698fa6b6", "url": "https://github.com/larsiusprime/polymod" }, { From 6b9bdb5f2adb76ced506e424b8e2a961af02944a Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 26 Aug 2024 18:01:23 -0400 Subject: [PATCH 613/870] Upgraded project file to HXP --- .github/labeler.yml | 1 - .vscode/settings.json | 30 +- Project.xml | 266 ---------- project.hxp | 1109 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1124 insertions(+), 282 deletions(-) delete mode 100644 Project.xml create mode 100644 project.hxp diff --git a/.github/labeler.yml b/.github/labeler.yml index e8e490865..e8250b4e7 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,7 +1,6 @@ # 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' diff --git a/.vscode/settings.json b/.vscode/settings.json index 26fe0b042..227cb94ec 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -94,12 +94,12 @@ { "label": "Windows / Debug", "target": "windows", - "args": ["-debug", "-DFORCE_DEBUG_VERSION"] + "args": ["-debug", "-DFEATURE_DEBUG_FUNCTIONS"] }, { "label": "Linux / Debug", "target": "linux", - "args": ["-debug", "-DFORCE_DEBUG_VERSION"] + "args": ["-debug", "-DFEATURE_DEBUG_FUNCTIONS"] }, { "label": "HashLink / Debug", @@ -109,7 +109,7 @@ { "label": "Windows / Debug (FlxAnimate Test)", "target": "windows", - "args": ["-debug", "-DANIMATE", "-DFORCE_DEBUG_VERSION"] + "args": ["-debug", "-DANIMATE", "-DFEATURE_DEBUG_FUNCTIONS"] }, { "label": "HashLink / Debug (FlxAnimate Test)", @@ -119,7 +119,7 @@ { "label": "Windows / Debug (Straight to Freeplay)", "target": "windows", - "args": ["-debug", "-DFREEPLAY", "-DFORCE_DEBUG_VERSION"] + "args": ["-debug", "-DFREEPLAY", "-DFEATURE_DEBUG_FUNCTIONS"] }, { "label": "HashLink / Debug (Straight to Freeplay)", @@ -132,13 +132,13 @@ "args": [ "-debug", "-DSONG=bopeebo -DDIFFICULTY=normal", - "-DFORCE_DEBUG_VERSION" + "-DFEATURE_DEBUG_FUNCTIONS" ] }, { "label": "Windows / Debug (Straight to Play - 2hot)", "target": "windows", - "args": ["-debug", "-DSONG=2hot", "-DFORCE_DEBUG_VERSION"] + "args": ["-debug", "-DSONG=2hot", "-DFEATURE_DEBUG_FUNCTIONS"] }, { "label": "HashLink / Debug (Straight to Play - Bopeebo Normal)", @@ -148,7 +148,7 @@ { "label": "Windows / Debug (Conversation Test)", "target": "windows", - "args": ["-debug", "-DDIALOGUE", "-DFORCE_DEBUG_VERSION"] + "args": ["-debug", "-DDIALOGUE", "-DFEATURE_DEBUG_FUNCTIONS"] }, { "label": "HashLink / Debug (Conversation Test)", @@ -163,7 +163,7 @@ { "label": "Windows / Debug (Straight to Chart Editor)", "target": "windows", - "args": ["-debug", "-DCHARTING", "-DFORCE_DEBUG_VERSION"] + "args": ["-debug", "-DCHARTING", "-DFEATURE_DEBUG_FUNCTIONS"] }, { "label": "HashLink / Debug (Straight to Chart Editor)", @@ -173,12 +173,12 @@ { "label": "Windows / Debug (Straight to Animation Editor)", "target": "windows", - "args": ["-debug", "-DANIMDEBUG", "-DFORCE_DEBUG_VERSION"] + "args": ["-debug", "-DANIMDEBUG", "-DFEATURE_DEBUG_FUNCTIONS"] }, { "label": "Windows / Debug (Debug hxCodec)", "target": "windows", - "args": ["-debug", "-DHXC_LIBVLC_LOGGING", "-DFORCE_DEBUG_VERSION"] + "args": ["-debug", "-DHXC_LIBVLC_LOGGING", "-DFEATURE_DEBUG_FUNCTIONS"] }, { "label": "HashLink / Debug (Straight to Animation Editor)", @@ -188,7 +188,7 @@ { "label": "Windows / Debug (Latency Test)", "target": "windows", - "args": ["-debug", "-DLATENCY", "-DFORCE_DEBUG_VERSION"] + "args": ["-debug", "-DLATENCY", "-DFEATURE_DEBUG_FUNCTIONS"] }, { "label": "HashLink / Debug (Latency Test)", @@ -198,7 +198,7 @@ { "label": "Windows / Debug (Waveform Test)", "target": "windows", - "args": ["-debug", "-DWAVEFORM", "-DFORCE_DEBUG_VERSION"] + "args": ["-debug", "-DWAVEFORM", "-DFEATURE_DEBUG_FUNCTIONS"] }, { "label": "Windows / Release", @@ -218,17 +218,17 @@ { "label": "HTML5 / Debug", "target": "html5", - "args": ["-debug", "-DFORCE_DEBUG_VERSION"] + "args": ["-debug", "-DFEATURE_DEBUG_FUNCTIONS"] }, { "label": "HTML5 / Debug (Watch)", "target": "html5", - "args": ["-debug", "-watch", "-DFORCE_DEBUG_VERSION"] + "args": ["-debug", "-watch", "-DFEATURE_DEBUG_FUNCTIONS"] }, { "label": "macOS / Debug", "target": "mac", - "args": ["-debug", "-DFORCE_DEBUG_VERSION"] + "args": ["-debug", "-DFEATURE_DEBUG_FUNCTIONS"] }, { "label": "macOS / Release", diff --git a/Project.xml b/Project.xml deleted file mode 100644 index 656590aec..000000000 --- a/Project.xml +++ /dev/null @@ -1,266 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - -
-
- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - -
-
- - - - - - -
- - - - -
- - -
- - -
- - -
- - - --> - --> - - - -
- -
- - - - - - -
- - - - - - - - - - - - - - - - -
-
diff --git a/project.hxp b/project.hxp new file mode 100644 index 000000000..0e090a4c9 --- /dev/null +++ b/project.hxp @@ -0,0 +1,1109 @@ +package; + +// I don't think we can import `funkin` classes here. Macros? Recursion? IDK. +import hxp.*; +import lime.tools.*; +import sys.FileSystem; + +using StringTools; + +/** + * This HXP performs the functions of a Lime `project.xml` file, + * but it's written in Haxe rather than XML! + * + * This makes it far easier to organize, reuse, and refactor, + * and improves management of feature flag logic. + */ +@:nullSafety +class Project extends HXProject { + // + // METADATA + // + + /** + * The game's version number, as a Semantic Versioning string with no prefix. + * REMEMBER TO CHANGE THIS WHEN THE GAME UPDATES! + * You only have to change it here, the rest of the game will query this value. + */ + static final VERSION:String = "0.5.0"; + + /** + * The game's name. Used as the default window title. + */ + static final TITLE:String = "Friday Night Funkin'"; + + /** + * The name of the generated executable file. + * For example, `"Funkin"` will create a file called `Funkin.exe`. + */ + static final EXECUTABLE_NAME:String = "Funkin"; + + /** + * The relative location of the source code. + */ + static final SOURCE_DIR:String = "source"; + + /** + * The fully qualified class path for the game's preloader. + * Particularly important on HTML5 but we use it on all platforms. + */ + static final PRELOADER:String = "funkin.ui.transition.preload.FunkinPreloader"; + + /** + * A package name used for identifying the app on various app stores. + */ + static final PACKAGE_NAME:String = "me.funkin.fnf"; + + /** + * The fully qualified class path for the entry point class to execute when launching the game. + * It's where `public static function main():Void` goes. + */ + static final MAIN_CLASS:String = "Main"; + + /** + * The company name for the game. + * This appears in metadata in places I think. + */ + static final COMPANY:String = "The Funkin' Crew"; + + /** + * Path to the Haxe script run before building the game. + */ + static final PREBUILD_HX:String = "source/Prebuild.hx"; + + /** + * Path to the Haxe script run after building the game. + */ + static final POSTBUILD_HX:String = "source/Postbuild.hx"; + + /** + * Asset path globs to always exclude from asset libraries. + */ + static final EXCLUDE_ASSETS:Array = [".*", "cvs", "thumbs.db", "desktop.ini", "*.hash", "*.md"]; + + /** + * Asset path globs to exclude on web platforms. + */ + static final EXCLUDE_ASSETS_WEB:Array = ["*.ogg"]; + /** + * Asset path globs to exclude on native platforms. + */ + static final EXCLUDE_ASSETS_NATIVE:Array = ["*.mp3"]; + + // + // FEATURE FLAGS + // Inverse feature flags are automatically populated. + // + + /** + * `-DGITHUB_BUILD` + * If this flag is enabled, the game will use the configuration used by GitHub Actions + * to generate playtest builds to be pushed to the launcher. + * + * This is generally used to forcibly enable debugging features, + * even when the game is built in release mode for performance reasons. + */ + static final GITHUB_BUILD:FeatureFlag = "GITHUB_BUILD"; + + /** + * `-DREDIRECT_ASSETS_FOLDER` + * If this flag is enabled, the game will redirect the `assets` folder from the `export` folder + * to the `assets` folder at the root of the workspace. + * This is useful for ensuring hot reloaded changes don't get lost when rebuilding the game. + */ + static final REDIRECT_ASSETS_FOLDER:FeatureFlag = "REDIRECT_ASSETS_FOLDER"; + + /** + * `-DTOUCH_HERE_TO_PLAY` + * If this flag is enabled, the game will display a prompt to the user after the preloader completes, + * requiring them to click anywhere on the screen to start the game. + * This is done to ensure that the audio context can initialize properly on HTML5. Not necessary on desktop. + */ + static final TOUCH_HERE_TO_PLAY:FeatureFlag = "TOUCH_HERE_TO_PLAY"; + + /** + * `-DPRELOAD_ALL` + * Whether to preload all asset libraries. + * Disabled on web, enabled on desktop. + */ + static final PRELOAD_ALL:FeatureFlag = "PRELOAD_ALL"; + + /** + * `-DEMBED_ASSETS` + * Whether to embed all asset libraries into the executable. + */ + static final EMBED_ASSETS:FeatureFlag = "EMBED_ASSETS"; + + /** + * `-DHARDCODED_CREDITS` + * If this flag is enabled, the credits will be parsed and encoded in the game at compile time, + * rather than read from JSON data at runtime. + */ + static final HARDCODED_CREDITS:FeatureFlag = "HARDCODED_CREDITS"; + + /** + * `-DFEATURE_DEBUG_FUNCTIONS` + * If this flag is enabled, the game will have all playtester-only debugging functionality enabled. + * This includes debug hotkeys like time travel in the Play State. + * By default, enabled on debug builds or playtester builds and disabled on release builds. + */ + static final FEATURE_DEBUG_FUNCTIONS:FeatureFlag = "FEATURE_DEBUG_FUNCTIONS"; + + /** + * `-DFEATURE_DISCORD_RPC` + * If this flag is enabled, the game will enable the Discord Remote Procedure Call library. + * This is used to provide Discord Rich Presence support. + */ + static final FEATURE_DISCORD_RPC:FeatureFlag = "FEATURE_DISCORD_RPC"; + + /** + * `-DFEATURE_NEWGROUNDS` + * If this flag is enabled, the game will enable the Newgrounds library. + * This is used to provide Medal and Leaderboard support. + */ + static final FEATURE_NEWGROUNDS:FeatureFlag = "FEATURE_NEWGROUNDS"; + + /** + * `-DFEATURE_FUNKVIS` + * If this flag is enabled, the game will enable the Funkin Visualizer library. + * This is used to provide audio visualization like Nene's speaker. + * Disabling this will make some waveforms inactive. + */ + static final FEATURE_FUNKVIS:FeatureFlag = "FEATURE_FUNKVIS"; + + /** + * `-DFEATURE_PARTIAL_SOUNDS` + * If this flag is enabled, the game will enable the FlxPartialSound library. + * This is used to provide audio previews in Freeplay. + * Disabling this will make those previews not play. + */ + static final FEATURE_PARTIAL_SOUNDS:FeatureFlag = "FEATURE_PARTIAL_SOUNDS"; + + /** + * `-DFEATURE_VIDEO_PLAYBACK` + * If this flag is enabled, the game will enable support for video playback. + * This requires the hxCodec library on desktop platforms. + */ + static final FEATURE_VIDEO_PLAYBACK:FeatureFlag = "FEATURE_VIDEO_PLAYBACK"; + + /** + * `-DFEATURE_FILE_DROP` + * If this flag is enabled, the game will support dragging and dropping files onto it for various features. + * Disabled on MacOS. + */ + static final FEATURE_FILE_DROP:FeatureFlag = "FEATURE_FILE_DROP"; + + /** + * `-DFEATURE_OPEN_URL` + * If this flag is enabled, the game will support opening URLs (such as the merch page). + */ + static final FEATURE_OPEN_URL:FeatureFlag = "FEATURE_OPEN_URL"; + + /** + * `-DFEATURE_CHART_EDITOR` + * If this flag is enabled, the Chart Editor will be accessible from the debug menu. + */ + static final FEATURE_CHART_EDITOR:FeatureFlag = "FEATURE_CHART_EDITOR"; + + /** + * `-DFEATURE_STAGE_EDITOR` + * If this flag is enabled, the Stage Editor will be accessible from the debug menu. + */ + static final FEATURE_STAGE_EDITOR:FeatureFlag = "FEATURE_STAGE_EDITOR"; + + /** + * `-DFEATURE_POLYMOD_MODS` + * If this flag is enabled, the game will enable the Polymod library's support for atomic mod loading from the `./mods` folder. + * If this flag is disabled, no mods will be loaded. + */ + static final FEATURE_POLYMOD_MODS:FeatureFlag = "FEATURE_POLYMOD_MODS"; + + /** + * `-DFEATURE_GHOST_TAPPING` + * If this flag is enabled, misses will not be counted when it is not the player's turn. + * Misses are still counted when the player has notes to hit. + */ + static final FEATURE_GHOST_TAPPING:FeatureFlag = "FEATURE_GHOST_TAPPING"; + + // + // CONFIGURATION FUNCTIONS + // + + public function new() { + super(); + + flair(); + configureApp(); + + displayTarget(); + configureFeatureFlags(); + configureCompileDefines(); + configureIncludeMacros(); + configureCustomMacros(); + configureOutputDir(); + configurePolymod(); + configureHaxelibs(); + configureAssets(); + configureIcons(); + } + + /** + * Do something before building, display some ASCII or something IDK + */ + function flair() { + // TODO: Implement this. + info("Friday Night Funkin'"); + info("Initializing build..."); + + info("Target Version: " + VERSION); + info("Git Branch: " + getGitBranch()); + info("Git Commit: " + getGitCommit()); + info("Git Modified? " + getGitModified()); + info("Display? " + isDisplay()); + } + + /** + * Apply basic project metadata, such as the game title and version number, + * as well as info like the package name and company (used by various app stores). + */ + function configureApp() { + this.meta.title = TITLE; + this.meta.version = VERSION; + this.meta.packageName = PACKAGE_NAME; + this.meta.company = COMPANY; + + this.app.main = MAIN_CLASS; + this.app.file = EXECUTABLE_NAME; + this.app.preloader = PRELOADER; + + // Tell Lime where to look for the game's source code. + // If for some reason we have multiple source directories, we can add more entries here. + this.sources.push(SOURCE_DIR); + + // Tell Lime to run some prebuild and postbuild scripts. + this.preBuildCallbacks.push(buildHaxeCLICommand(PREBUILD_HX)); + this.postBuildCallbacks.push(buildHaxeCLICommand(POSTBUILD_HX)); + + // TODO: Should we provide this? + // this.meta.buildNumber = 0; + + // These values are only used by the SWF target I think. + // this.app.path + // this.app.init + // this.app.swfVersion + // this.app.url + + // These values are only used by... FIREFOX MARKETPLACE WHAT? + // this.meta.description = ""; + // this.meta.companyId = COMPANY; + // this.meta.companyUrl = COMPANY; + + // Configure the window. + // Automatically configure FPS. + this.window.fps = 60; + // Set the window size. + this.window.width = 1280; + this.window.height = 720; + // Black background on release builds, magenta on debug builds. + this.window.background = FEATURE_DEBUG_FUNCTIONS.isEnabled(this) ? 0xFFFF00FF : 0xFF000000; + + this.window.hardware = true; + this.window.vsync = false; + + if (isWeb()) { + this.window.resizable = true; + } + + if (isDesktop()) { + this.window.orientation = Orientation.LANDSCAPE; + this.window.fullscreen = false; + this.window.resizable = true; + this.window.vsync = false; + } + + if (isMobile()) { + this.window.orientation = Orientation.LANDSCAPE; + this.window.fullscreen = false; + this.window.resizable = false; + this.window.width = 0; + this.window.height = 0; + } + } + + /** + * Log information about the configured target platform. + */ + function displayTarget() { + // Display the target operating system. + switch (this.target) { + case Platform.WINDOWS: + info('Target Platform: Windows'); + case Platform.MAC: + info('Target Platform: MacOS'); + case Platform.LINUX: + info('Target Platform: Linux'); + case Platform.ANDROID: + info('Target Platform: Android'); + case Platform.IOS: + info('Target Platform: IOS'); + case Platform.HTML5: + info('Target Platform: HTML5'); + // See lime.tools.Platform for a full list. + // case Platform.EMSCRITEN: // A WebAssembly build might be interesting... + // case Platform.AIR: + // case Platform.BLACKBERRY: + // case Platform.CONSOLE_PC: + // case Platform.FIREFOX: + // case Platform.FLASH: + // case Platform.PS3: + // case Platform.PS4: + // case Platform.TIZEN: + // case Platform.TVOS: + // case Platform.VITA: + // case Platform.WEBOS: + // case Platform.WIIU: + // case Platform.XBOX1: + default: + error('Unsupported platform (got ${target})'); + } + + switch (this.platformType) { + case PlatformType.DESKTOP: + info('Platform Type: Desktop'); + case PlatformType.MOBILE: + info('Platform Type: Mobile'); + case PlatformType.WEB: + info('Platform Type: Web'); + case PlatformType.CONSOLE: + info('Platform Type: Console'); + default: + error('Unknown platform type (got ${platformType})'); + } + + // Print whether we are using HXCPP, HashLink, or something else. + if (isWeb()) { + info('Target Language: JavaScript (HTML5)'); + } else if (isHashLink()) { + info('Target Language: HashLink'); + } else if (isNeko()) { + info('Target Language: Neko'); + } else if (isJava()) { + info('Target Language: Java'); + } else if (isNodeJS()) { + info('Target Language: JavaScript (NodeJS)'); + } else if (isCSharp()) { + info('Target Language: C#'); + } else { + info('Target Language: C++'); + } + + for (arch in this.architectures) { + // Display the list of target architectures. + switch (arch) { + case Architecture.X86: + info('Architecture: x86'); + case Architecture.X64: + info('Architecture: x64'); + case Architecture.ARMV5: + info('Architecture: ARMv5'); + case Architecture.ARMV6: + info('Architecture: ARMv6'); + case Architecture.ARMV7: + info('Architecture: ARMv7'); + case Architecture.ARMV7S: + info('Architecture: ARMv7S'); + case Architecture.ARM64: + info('Architecture: ARMx64'); + case Architecture.MIPS: + info('Architecture: MIPS'); + case Architecture.MIPSEL: + info('Architecture: MIPSEL'); + case null: + if (!isWeb()) { + error('Unsupported architecture (got null on non-web platform)'); + } else { + info('Architecture: Web'); + } + default: + error('Unsupported architecture (got ${arch})'); + } + } + } + + /** + * Apply various feature flags based on the target platform and the user-provided build flags. + */ + function configureFeatureFlags() { + // You can explicitly override any of these. + // For example, `-DGITHUB_BUILD` or `-DNO_HARDCODED_CREDITS` + + // Should be false unless explicitly requested. + GITHUB_BUILD.apply(this, false); + FEATURE_STAGE_EDITOR.apply(this, false); + FEATURE_NEWGROUNDS.apply(this, false); + FEATURE_GHOST_TAPPING.apply(this, false); + + // Should be true unless explicitly requested. + HARDCODED_CREDITS.apply(this, true); + FEATURE_OPEN_URL.apply(this, true); + FEATURE_POLYMOD_MODS.apply(this, true); + FEATURE_FUNKVIS.apply(this, true); + FEATURE_PARTIAL_SOUNDS.apply(this, true); + FEATURE_VIDEO_PLAYBACK.apply(this, true); + + // Should be true on debug builds or if GITHUB_BUILD is enabled. + FEATURE_DEBUG_FUNCTIONS.apply(this, isDebug() || GITHUB_BUILD.isEnabled(this)); + + // Should default to true on workspace builds and false on release builds. + REDIRECT_ASSETS_FOLDER.apply(this, isDebug() && isDesktop()); + + // Should be true on release, non-tester builds. + // We don't want testers to accidentally leak songs to their Discord friends! + // TODO: Re-enable this. + FEATURE_DISCORD_RPC.apply(this, false && !FEATURE_DEBUG_FUNCTIONS.isEnabled(this)); + + // Should be true only on web builds. + // Audio context issues only exist there. + TOUCH_HERE_TO_PLAY.apply(this, isWeb()); + + // Should be true only on web builds. + // Enabling embedding and preloading is required to preload assets properly. + EMBED_ASSETS.apply(this, isWeb()); + PRELOAD_ALL.apply(this, true); + + // Should be true except on MacOS. + // File drop doesn't work there. + FEATURE_FILE_DROP.apply(this, !isMac()); + + // Should be true except on web builds. + // Chart editor doesn't work there. + FEATURE_CHART_EDITOR.apply(this, !isWeb()); + } + + /** + * Set compilation flags which are not feature flags. + */ + function configureCompileDefines() { + // Enable OpenFL's error handler. Required for the crash logger. + setHaxedef("openfl-enable-handle-error"); + + // Enable stack trace tracking. Good for debugging but has a (minor) performance impact. + setHaxedef("HXCPP_CHECK_POINTER"); + setHaxedef("HXCPP_STACK_LINE"); + setHaxedef("HXCPP_STACK_TRACE"); + setHaxedef("hscriptPos"); + + setHaxedef("safeMode"); + + // If we aren't using the Flixel debugger, strip it out. + if (FEATURE_DEBUG_FUNCTIONS.isDisabled(this)) { + setHaxedef("FLX_NO_DEBUG"); + } + + // Disable the built in pause screen when unfocusing the game. + setHaxedef("FLX_NO_FOCUS_LOST_SCREEN"); + + // HaxeUI configuration. + setHaxedef("haxeui_no_mouse_reset"); + setHaxedef("haxeui_focus_out_on_click"); // Unfocus a dialog when clicking out of it + setHaxedef("haxeui_dont_impose_base_class"); // Suppress a macro error + + if (isRelease()) { + // Improve performance on Nape + // TODO: Do we even use Nape? + setHaxedef("NAPE_RELEASE_BUILD"); + } + + // Cleaner looking compiler errors. + setHaxedef("message.reporting", "pretty"); + } + + /** + * Set compilation flags which manage dead code elimination. + */ + function configureIncludeMacros() { + // Disable dead code elimination. + // This prevents functions that are unused by the base game from being unavailable to HScript. + addHaxeFlag("-dce no"); + + // Forcibly include all Funkin' classes in builds. + // This prevents classes that are unused by the base game from being unavailable to HScript. + addHaxeMacro("include('funkin')"); + + // Ensure all HaxeUI components are available at runtime. + addHaxeMacro("include('haxe.ui.backend.flixel.components')"); + addHaxeMacro("include('haxe.ui.core')"); + addHaxeMacro("include('haxe.ui.components')"); + addHaxeMacro("include('haxe.ui.containers')"); + addHaxeMacro("include('haxe.ui.containers.dialogs')"); + addHaxeMacro("include('haxe.ui.containers.menus')"); + addHaxeMacro("include('haxe.ui.containers.properties')"); + + // Ensure all Flixel classes are available at runtime. + // Explicitly ignore packages which require additional dependencies. + addHaxeMacro("include('flixel', true, [ 'flixel.addons.editors.spine.*', 'flixel.addons.nape.*', 'flixel.system.macros.*' ])"); + } + + /** + * Set compilation flags which manage bespoke build-time macros. + */ + function configureCustomMacros() { + // This macro allows addition of new functionality to existing Flixel. --> + addHaxeMacro("addMetadata('@:build(funkin.util.macro.FlxMacro.buildFlxBasic())', 'flixel.FlxBasic')"); + } + + function configureOutputDir() { + // Set the output directory. Depends on the target platform and build type. + + var buildDir = 'export/${isDebug() ? 'debug' : 'release'}/'; + + info('Output directory: $buildDir'); + // setenv('BUILD_DIR', buildDir); + app.path = buildDir; + } + + function configurePolymod() { + // The file extension to use for script files. + setHaxedef("POLYMOD_SCRIPT_EXT", ".hscript"); + // Which asset library to use for scripts. + setHaxedef("POLYMOD_SCRIPT_LIBRARY", "scripts"); + // The base path from which scripts should be accessed. + setHaxedef("POLYMOD_ROOT_PATH", "scripts/"); + // Determines the subdirectory of the mod folder used for file appending. + setHaxedef("POLYMOD_APPEND_FOLDER", "_append"); + // Determines the subdirectory of the mod folder used for file merges. + setHaxedef("POLYMOD_MERGE_FOLDER", "_merge"); + // Determines the file in the mod folder used for metadata. + setHaxedef("POLYMOD_MOD_METADATA_FILE", "_polymod_meta.json"); + // Determines the file in the mod folder used for the icon. + setHaxedef("POLYMOD_MOD_ICON_FILE", "_polymod_icon.png"); + + if (isDebug()) { + // Turns on additional debug logging. + setHaxedef("POLYMOD_DEBUG"); + } + } + + function configureHaxelibs() { + // Don't enforce + addHaxelib('lime'); // Game engine backend + addHaxelib('openfl'); // Game engine backend + + addHaxelib('flixel'); // Game engine + + addHaxelib('flixel-addons'); // Additional utilities for Flixel + addHaxelib('hscript'); // Scripting + // addHaxelib('flixel-ui'); // UI framework (DEPRECATED) + addHaxelib('haxeui-core'); // UI framework + addHaxelib('haxeui-flixel'); // Integrate HaxeUI with Flixel + addHaxelib('flixel-text-input'); // Improved text field rendering for HaxeUI + + addHaxelib('polymod'); // Modding framework + addHaxelib('flxanimate'); // Texture atlas rendering + + addHaxelib('json2object'); // JSON parsing + addHaxelib('jsonpath'); // JSON parsing + addHaxelib('jsonpatch'); // JSON parsing + addHaxelib('thx.core'); // General utility library, "the lodash of Haxe" + addHaxelib('thx.semver'); // Version string handling + + if (isDebug()) { + addHaxelib('hxcpp-debug-server'); // VSCode debug support + } + + if (isDesktop() && !isHashLink() && FEATURE_VIDEO_PLAYBACK.isEnabled(this)) { + // hxCodec doesn't function on HashLink or non-desktop platforms + // It's also unnecessary if video playback is disabled + addHaxelib('hxCodec'); // Video playback + } + + if (FEATURE_DISCORD_RPC.isEnabled(this)) { + addHaxelib('discord_rpc'); // Discord API + } + + if (FEATURE_NEWGROUNDS.isEnabled(this)) { + addHaxelib('newgrounds'); // Newgrounds API + } + + if (FEATURE_FUNKVIS.isEnabled(this)) { + addHaxelib('funkin.vis'); // Audio visualization + addHaxelib('grig.audio'); // Audio data utilities + } + + if (FEATURE_PARTIAL_SOUNDS.isEnabled(this)) { + addHaxelib('FlxPartialSound'); // Partial sound + } + } + + function configureAssets() { + var exclude = EXCLUDE_ASSETS.concat(isWeb() ? EXCLUDE_ASSETS_WEB : EXCLUDE_ASSETS_NATIVE); + var shouldPreload = PRELOAD_ALL.isEnabled(this); + var shouldEmbed = EMBED_ASSETS.isEnabled(this); + + if (shouldEmbed) { + info('Embedding assets into executable...'); + } else { + info('Including assets alongside executable...'); + } + + // Default asset library + var shouldPreloadDefault = true; + addAssetLibrary("default", shouldEmbed, shouldPreloadDefault); + addAssetPath("assets/preload", "assets", "default", ["*"], exclude, shouldEmbed); + + // Font assets + var shouldEmbedFonts = true; + addAssetPath("assets/fonts", null, "default", ["*"], exclude, shouldEmbedFonts); + + // Shared asset libraries + addAssetLibrary("songs", shouldEmbed, shouldPreload); + addAssetPath("assets/songs", "assets/songs", "songs", ["*"], exclude, shouldEmbed); + addAssetLibrary("shared", shouldEmbed, shouldPreload); + addAssetPath("assets/shared", "assets/shared", "shared", ["*"], exclude, shouldEmbed); + if (FEATURE_VIDEO_PLAYBACK.isEnabled(this)) { + var shouldEmbedVideos = false; + addAssetLibrary("videos", shouldEmbedVideos, shouldPreload); + addAssetPath("assets/videos", "assets/videos", "videos", ["*"], exclude, shouldEmbedVideos); + } + + // Level asset libraries + addAssetLibrary("tutorial", shouldEmbed, shouldPreload); + addAssetPath("assets/tutorial", "assets/tutorial", "tutorial", ["*"], exclude, shouldEmbed); + addAssetLibrary("week1", shouldEmbed, shouldPreload); + addAssetPath("assets/week1", "assets/week1", "week1", ["*"], exclude, shouldEmbed); + addAssetLibrary("week2", shouldEmbed, shouldPreload); + addAssetPath("assets/week2", "assets/week2", "week2", ["*"], exclude, shouldEmbed); + addAssetLibrary("week3", shouldEmbed, shouldPreload); + addAssetPath("assets/week3", "assets/week3", "week3", ["*"], exclude, shouldEmbed); + addAssetLibrary("week4", shouldEmbed, shouldPreload); + addAssetPath("assets/week4", "assets/week4", "week4", ["*"], exclude, shouldEmbed); + addAssetLibrary("week5", shouldEmbed, shouldPreload); + addAssetPath("assets/week5", "assets/week5", "week5", ["*"], exclude, shouldEmbed); + addAssetLibrary("week6", shouldEmbed, shouldPreload); + addAssetPath("assets/week6", "assets/week6", "week6", ["*"], exclude, shouldEmbed); + addAssetLibrary("week7", shouldEmbed, shouldPreload); + addAssetPath("assets/week7", "assets/week7", "week7", ["*"], exclude, shouldEmbed); + addAssetLibrary("weekend1", shouldEmbed, shouldPreload); + addAssetPath("assets/weekend1", "assets/weekend1", "weekend1", ["*"], exclude, shouldEmbed); + + // Art asset library (where README and CHANGELOG pull from) + var shouldEmbedArt = false; + var shouldPreloadArt = false; + addAssetLibrary("art", shouldEmbedArt, shouldPreloadArt); + addAsset("art/readme.txt", "do NOT readme.txt", "art", shouldEmbedArt); + addAsset("LICENSE.md", "LICENSE.md", "art", shouldEmbedArt); + addAsset("CHANGELOG.md", "CHANGELOG.md", "art", shouldEmbedArt); + } + + /** + * Configure the application's favicon and executable icon. + */ + function configureIcons() { + addIcon("art/icon16.png", 16); + addIcon("art/icon32.png", 32); + addIcon("art/icon64.png", 64); + addIcon("art/iconOG.png"); + } + + // + // HELPER FUNCTIONS + // Easy functions to make the code more readable. + // + + public function isWeb():Bool { + return this.platformType == PlatformType.WEB; + } + + public function isMobile():Bool { + return this.platformType == PlatformType.MOBILE; + } + + public function isDesktop():Bool { + return this.platformType == PlatformType.DESKTOP; + } + + public function isConsole():Bool { + return this.platformType == PlatformType.CONSOLE; + } + + public function is32Bit():Bool { + return this.architectures.contains(Architecture.X86); + } + + public function is64Bit():Bool { + return this.architectures.contains(Architecture.X64); + } + + public function isWindows():Bool { + return this.target == Platform.WINDOWS; + } + + public function isMac():Bool { + return this.target == Platform.MAC; + } + + public function isLinux():Bool { + return this.target == Platform.LINUX; + } + + public function isAndroid():Bool { + return this.target == Platform.ANDROID; + } + + public function isIOS():Bool { + return this.target == Platform.IOS; + } + + public function isHashLink():Bool { + return this.targetFlags.exists("hl"); + } + + public function isNeko():Bool { + return this.targetFlags.exists("neko"); + } + + public function isJava():Bool { + return this.targetFlags.exists("java"); + } + + public function isNodeJS():Bool { + return this.targetFlags.exists("nodejs"); + } + + public function isCSharp():Bool { + return this.targetFlags.exists("cs"); + } + + public function isDisplay():Bool { + return this.command == "display"; + } + + public function isDebug():Bool { + return this.debug; + } + + public function isRelease():Bool { + return !isDebug(); + } + + public function getHaxedef(name:String):Null { + return this.haxedefs.get(name); + } + + public function setHaxedef(name:String, ?value:String):Void { + if (value == null) value = ""; + + this.haxedefs.set(name, value); + } + + public function unsetHaxedef(name:String):Void { + this.haxedefs.remove(name); + } + + public function getDefine(name:String):Null { + return this.defines.get(name); + } + + public function hasDefine(name:String):Bool { + return this.defines.exists(name); + } + + /** + * Add a library to the list of dependencies for the project. + * @param name The name of the library to add. + * @param version The version of the library to add. Optional. + */ + public function addHaxelib(name:String, version:String = ""):Void { + this.haxelibs.push(new Haxelib(name, version)); + } + + /** + * Add a `haxeflag` to the project. + */ + public function addHaxeFlag(value:String):Void { + this.haxeflags.push(value); + } + + /** + * Call a Haxe build macro. + */ + public function addHaxeMacro(value:String):Void { + addHaxeFlag('--macro ${value}'); + } + + /** + * Add an icon to the project. + * @param icon The path to the icon. + * @param size The size of the icon. Optional. + */ + public function addIcon(icon:String, ?size:Int):Void { + this.icons.push(new Icon(icon, size)); + } + + /** + * Add an asset to the game build. + * @param path The path the asset is located at. + * @param rename The path the asset should be placed. + * @param library The asset library to add the asset to. `null` = "default" + * @param embed Whether to embed the asset in the executable. + */ + public function addAsset(path:String, ?rename:String, ?library:String, embed:Bool = false):Void { + // path, rename, type, embed, setDefaults + var asset = new Asset(path, rename, null, embed, true); + @:nullSafety(Off) + { + asset.library = library ?? "default"; + } + this.assets.push(asset); + } + + /** + * Add an entire path of assets to the game build. + * @param path The path the assets are located at. + * @param rename The path the assets should be placed. + * @param library The asset library to add the assets to. `null` = "default" + * @param include An optional array to include specific asset names. + * @param exclude An optional array to exclude specific asset names. + * @param embed Whether to embed the assets in the executable. + */ + public function addAssetPath(path:String, ?rename:String, library:String, ?include:Array, ?exclude:Array, embed:Bool = false):Void { + // Argument parsing. + if (path == "") return; + + if (include == null) include = []; + + if (exclude == null) exclude = []; + + var targetPath = rename ?? path; + if (targetPath != "") targetPath += "/"; + + // Validate path. + if (!sys.FileSystem.exists(path)) { + error('Could not find asset path "${path}".'); + } else if (!sys.FileSystem.isDirectory(path)) { + error('Could not parse asset path "${path}", expected a directory.'); + } else { + // info(' Found asset path "${path}".'); + } + + for (file in sys.FileSystem.readDirectory(path)) { + if (sys.FileSystem.isDirectory('${path}/${file}')) { + // Attempt to recursively add all assets in the directory. + if (this.filter(file, ["*"], exclude)) { + addAssetPath('${path}/${file}', '${targetPath}${file}', library, include, exclude, embed); + } + } else { + if (this.filter(file, include, exclude)) { + addAsset('${path}/${file}', '${targetPath}${file}', library, embed); + } + } + } + } + + /** + * Add an asset library to the game build. + * @param name The name of the library. + * @param embed + * @param preload + */ + public function addAssetLibrary(name:String, embed:Bool = false, preload:Bool = false):Void { + // sourcePath, name, type, embed, preload, generate, prefix + var sourcePath = ''; + this.libraries.push(new Library(sourcePath, name, null, embed, preload, false, "")); + } + + // + // PROCESS FUNCTIONS + // + + /** + * A CLI command to run a command in the shell. + */ + public function buildCLICommand(cmd:String):CLICommand { + return CommandHelper.fromSingleString(cmd); + } + + /** + * A CLI command to run a Haxe script via `--interp`. + */ + public function buildHaxeCLICommand(path:String):CLICommand { + return CommandHelper.interpretHaxe(path); + } + + public function getGitCommit():String { + // Cannibalized from GitCommit.hx + var process = new sys.io.Process('git', ['rev-parse', 'HEAD']); + if (process.exitCode() != 0) { + var message = process.stderr.readAll().toString(); + error('[ERROR] Could not determine current git commit; is this a proper Git repository?'); + } + + var commitHash:String = process.stdout.readLine(); + var commitHashSplice:String = commitHash.substr(0, 7); + + return commitHashSplice; + } + + public function getGitBranch():String { + // Cannibalized from GitCommit.hx + var branchProcess = new sys.io.Process('git', ['rev-parse', '--abbrev-ref', 'HEAD']); + + if (branchProcess.exitCode() != 0) { + var message = branchProcess.stderr.readAll().toString(); + error('Could not determine current git branch; is this a proper Git repository?'); + } + + var branchName:String = branchProcess.stdout.readLine(); + + return branchName; + } + + public function getGitModified():Bool { + var branchProcess = new sys.io.Process('git', ['status', '--porcelain']); + + if (branchProcess.exitCode() != 0) { + var message = branchProcess.stderr.readAll().toString(); + error('Could not determine current git status; is this a proper Git repository?'); + } + + var output:String = ''; + try { + output = branchProcess.stdout.readLine(); + } catch (e) { + if (e.message == 'Eof') { + // Do nothing. + // Eof = No output. + } else { + // Rethrow other exceptions. + throw e; + } + } + + return output.length > 0; + } + + // + // LOGGING FUNCTIONS + // + + /** + * Display an error message. This should stop the build process. + */ + public function error(message:String):Void { + Log.error('${message}'); + } + + /** + * Display an info message. This should not interfere with the build process. + */ + public function info(message:String):Void { + // CURSED: We have to disable info() log calls because of a bug. + // https://github.com/haxelime/lime-vscode-extension/issues/88 + + // Log.info('[INFO] ${message}'); + + // trace(message); + // Sys.println(message); + // Sys.stdout().writeString(message); + // Sys.stderr().writeString(message); + } +} + +/** + * An object representing a feature flag, which can be enabled or disabled. + * Includes features such as automatic generation of compile defines and inversion. + */ +abstract FeatureFlag(String) { + static final INVERSE_PREFIX:String = "NO_"; + + public function new(input:String) { + this = input; + } + + @:from + public static function fromString(input:String):FeatureFlag { + return new FeatureFlag(input); + } + + /** + * Enable/disable a feature flag if it is unset, and handle the inverse flag. + * Doesn't override a feature flag that was set explicitly. + * @param enableByDefault Whether to enable this feature flag if it is unset. + */ + public function apply(project:Project, enableByDefault:Bool = false):Void { + // TODO: Name this function better? + + if (isEnabled(project)) { + // If this flag was already enabled, disable the inverse. + project.info('Enabling feature flag ${this}'); + getInverse().disable(project, false); + } else if (getInverse().isEnabled(project)) { + // If the inverse flag was already enabled, disable this flag. + project.info('Disabling feature flag ${this}'); + disable(project, false); + } else { + if (enableByDefault) { + // Enable this flag if it was unset, and disable the inverse. + project.info('Enabling feature flag ${this}'); + enable(project, true); + } else { + // Disable this flag if it was unset, and enable the inverse. + project.info('Disabling feature flag ${this}'); + disable(project, true); + } + } + } + + /** + * Enable this feature flag by setting the appropriate compile define. + * + * @param project The project to modify. + * @param andInverse Also disable the feature flag's inverse. + */ + public function enable(project:Project, andInverse:Bool = true) { + project.setHaxedef(this, ""); + if (andInverse) { + getInverse().disable(project, false); + } + } + + /** + * Disable this feature flag by removing the appropriate compile define. + * + * @param project The project to modify. + * @param andInverse Also enable the feature flag's inverse. + */ + public function disable(project:Project, andInverse:Bool = true) { + project.unsetHaxedef(this); + if (andInverse) { + getInverse().enable(project, false); + } + } + + /** + * Query if this feature flag is enabled. + * @param project The project to query. + */ + public function isEnabled(project:Project):Bool { + // Check both Haxedefs and Defines for this flag. + return project.haxedefs.exists(this) || project.defines.exists(this); + } + + /** + * Query if this feature flag's inverse is enabled. + */ + public function isDisabled(project:Project):Bool { + return getInverse().isEnabled(project); + } + + /** + * Return the inverse of this feature flag. + * @return A new feature flag that is the inverse of this one. + */ + public function getInverse():FeatureFlag { + if (this.startsWith(INVERSE_PREFIX)) { + return this.substring(INVERSE_PREFIX.length); + } + return INVERSE_PREFIX + this; + } +} From 200b3c963b6f3793c231eb8b4792af7b7d24e98e Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 26 Aug 2024 18:01:36 -0400 Subject: [PATCH 614/870] Updated compile defines to use feature flag system --- source/Main.hx | 2 +- source/funkin/InitState.hx | 17 +- source/funkin/api/discord/Discord.hx | 4 +- source/funkin/api/newgrounds/NGUnsafe.hx | 6 +- source/funkin/api/newgrounds/NGio.hx | 6 +- source/funkin/data/story/level/LevelData.hx | 4 +- .../graphics/adobeanimate/FlxAtlasSprite.hx | 2 +- source/funkin/input/Controls.hx | 7 +- source/funkin/modding/PolymodHandler.hx | 33 +- source/funkin/play/PauseSubState.hx | 2 +- source/funkin/play/PlayState.hx | 282 +++++++++--------- source/funkin/play/stage/Stage.hx | 6 +- source/funkin/ui/debug/DebugMenuSubState.hx | 2 +- .../ui/debug/charting/ChartEditorState.hx | 2 +- source/funkin/ui/freeplay/FreeplayDJ.hx | 2 +- source/funkin/ui/freeplay/FreeplayState.hx | 14 +- source/funkin/ui/mainmenu/MainMenuState.hx | 6 +- source/funkin/ui/story/StoryMenuState.hx | 2 +- source/funkin/ui/transition/LoadingState.hx | 2 +- source/funkin/util/Constants.hx | 8 +- 20 files changed, 216 insertions(+), 193 deletions(-) diff --git a/source/Main.hx b/source/Main.hx index add5bbc67..2426fa0d9 100644 --- a/source/Main.hx +++ b/source/Main.hx @@ -113,7 +113,7 @@ class Main extends Sprite addChild(game); - #if debug + #if FEATURE_DEBUG_FUNCTIONS game.debugger.interaction.addTool(new funkin.util.TrackerToolButtonUtil()); #end diff --git a/source/funkin/InitState.hx b/source/funkin/InitState.hx index e53499e3c..21f83022e 100644 --- a/source/funkin/InitState.hx +++ b/source/funkin/InitState.hx @@ -34,7 +34,7 @@ import funkin.util.CLIUtil; import funkin.util.CLIUtil.CLIParams; import funkin.util.TimerUtil; import funkin.util.TrackerUtil; -#if discord_rpc +#if FEATURE_DISCORD_RPC import Discord.DiscordClient; #end @@ -123,7 +123,7 @@ class InitState extends FlxState // // DISCORD API SETUP // - #if discord_rpc + #if FEATURE_DISCORD_RPC DiscordClient.initialize(); Application.current.onExit.add(function(exitCode) { @@ -144,7 +144,7 @@ class InitState extends FlxState // Plugins provide a useful interface for globally active Flixel objects, // that receive update events regardless of the current state. // TODO: Move scripted Module behavior to a Flixel plugin. - #if debug + #if FEATURE_DEBUG_FUNCTIONS funkin.util.plugins.MemoryGCPlugin.initialize(); #end funkin.util.plugins.EvacuateDebugPlugin.initialize(); @@ -374,11 +374,16 @@ class InitState extends FlxState // // FLIXEL DEBUG SETUP // - #if (debug || FORCE_DEBUG_VERSION) - // Make errors and warnings less annoying. - // Forcing this always since I have never been happy to have the debugger to pop up + #if FEATURE_DEBUG_FUNCTIONS + trace('Initializing Flixel debugger...'); + + #if !debug + // Make errors less annoying on release builds. LogStyle.ERROR.openConsole = false; LogStyle.ERROR.errorSound = null; + #end + + // Make errors and warnings less annoying. LogStyle.WARNING.openConsole = false; LogStyle.WARNING.errorSound = null; diff --git a/source/funkin/api/discord/Discord.hx b/source/funkin/api/discord/Discord.hx index a4d65684e..9dd513bf7 100644 --- a/source/funkin/api/discord/Discord.hx +++ b/source/funkin/api/discord/Discord.hx @@ -1,13 +1,13 @@ package funkin.api.discord; import Sys.sleep; -#if discord_rpc +#if FEATURE_DISCORD_RPC import discord_rpc.DiscordRpc; #end class DiscordClient { - #if discord_rpc + #if FEATURE_DISCORD_RPC public function new() { trace("Discord Client starting..."); diff --git a/source/funkin/api/newgrounds/NGUnsafe.hx b/source/funkin/api/newgrounds/NGUnsafe.hx index 77e44bd1d..81da7359e 100644 --- a/source/funkin/api/newgrounds/NGUnsafe.hx +++ b/source/funkin/api/newgrounds/NGUnsafe.hx @@ -24,7 +24,7 @@ class NGUnsafe NG.core.calls.event.logEvent(event).send(); trace('should have logged: ' + event); #else - #if debug + #if FEATURE_DEBUG_FUNCTIONS trace('event:$event - not logged, missing NG.io lib'); #end #end @@ -39,7 +39,7 @@ class NGUnsafe if (!medal.unlocked) medal.sendUnlock(); } #else - #if debug + #if FEATURE_DEBUG_FUNCTIONS trace('medal:$id - not unlocked, missing NG.io lib'); #end #end @@ -63,7 +63,7 @@ class NGUnsafe } } #else - #if debug + #if FEATURE_DEBUG_FUNCTIONS trace('Song:$song, Score:$score - not posted, missing NG.io lib'); #end #end diff --git a/source/funkin/api/newgrounds/NGio.hx b/source/funkin/api/newgrounds/NGio.hx index 3f5fc078a..a866783c1 100644 --- a/source/funkin/api/newgrounds/NGio.hx +++ b/source/funkin/api/newgrounds/NGio.hx @@ -239,7 +239,7 @@ class NGio NG.core.calls.event.logEvent(event).send(); trace('should have logged: ' + event); #else - #if debug + #if FEATURE_DEBUG_FUNCTIONS trace('event:$event - not logged, missing NG.io lib'); #end #end @@ -254,7 +254,7 @@ class NGio if (!medal.unlocked) medal.sendUnlock(); } #else - #if debug + #if FEATURE_DEBUG_FUNCTIONS trace('medal:$id - not unlocked, missing NG.io lib'); #end #end @@ -278,7 +278,7 @@ class NGio } } #else - #if debug + #if FEATURE_DEBUG_FUNCTIONS trace('Song:$song, Score:$score - not posted, missing NG.io lib'); #end #end diff --git a/source/funkin/data/story/level/LevelData.hx b/source/funkin/data/story/level/LevelData.hx index d01689a82..d1b00bbe6 100644 --- a/source/funkin/data/story/level/LevelData.hx +++ b/source/funkin/data/story/level/LevelData.hx @@ -93,9 +93,9 @@ typedef LevelPropData = * The frequency to bop at, in beats. * 1 = every beat, 2 = every other beat, etc. * Supports up to 0.25 precision. - * @default 0.0 + * @default 1.0 */ - @:default(0.0) + @:default(1.0) @:optional var danceEvery:Float; diff --git a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx index 049c6e206..194584992 100644 --- a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx +++ b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx @@ -21,7 +21,7 @@ class FlxAtlasSprite extends FlxAnimate FrameRate: 24.0, Reversed: false, // ?OnComplete:Void -> Void, - ShowPivot: #if debug false #else false #end, + ShowPivot: false, Antialiasing: true, ScrollFactor: null, // Offset: new FlxPoint(0, 0), // This is just FlxSprite.offset diff --git a/source/funkin/input/Controls.hx b/source/funkin/input/Controls.hx index 6b8e9aa3e..b5aefd08d 100644 --- a/source/funkin/input/Controls.hx +++ b/source/funkin/input/Controls.hx @@ -356,9 +356,10 @@ class Controls extends FlxActionSet public function check(name:Action, trigger:FlxInputState = JUST_PRESSED, gamepadOnly:Bool = false):Bool { - #if debug + #if FEATURE_DEBUG_FUNCTIONS if (!byName.exists(name)) throw 'Invalid name: $name'; #end + var action = byName[name]; if (gamepadOnly) return action.checkFiltered(trigger, GAMEPAD); else @@ -367,7 +368,7 @@ class Controls extends FlxActionSet public function getKeysForAction(name:Action):Array { - #if debug + #if FEATURE_DEBUG_FUNCTIONS if (!byName.exists(name)) throw 'Invalid name: $name'; #end @@ -382,7 +383,7 @@ class Controls extends FlxActionSet public function getButtonsForAction(name:Action):Array { - #if debug + #if FEATURE_DEBUG_FUNCTIONS if (!byName.exists(name)) throw 'Invalid name: $name'; #end diff --git a/source/funkin/modding/PolymodHandler.hx b/source/funkin/modding/PolymodHandler.hx index 5767199ba..52d4624cb 100644 --- a/source/funkin/modding/PolymodHandler.hx +++ b/source/funkin/modding/PolymodHandler.hx @@ -28,11 +28,10 @@ class PolymodHandler { /** * The API version that mods should comply with. - * Format this with Semantic Versioning; ... - * Bug fixes increment the patch version, new features increment the minor version. - * Changes that break old mods increment the major version. + * Indicates which mods are compatible with this version of the game. + * Minor updates rarely impact mods but major versions often do. */ - static final API_VERSION:String = '0.1.0'; + static final API_VERSION:String = "0.5.0"; // Constants.VERSION; /** * Where relative to the executable that mods are located. @@ -178,7 +177,7 @@ class PolymodHandler loadedModIds.push(mod.id); } - #if debug + #if FEATURE_DEBUG_FUNCTIONS var fileList:Array = Polymod.listModFiles(PolymodAssetType.IMAGE); trace('Installed mods have replaced ${fileList.length} images.'); for (item in fileList) @@ -258,8 +257,29 @@ class PolymodHandler // Unserializerr.DEFAULT_RESOLVER.resolveClass() can access blacklisted packages Polymod.blacklistImport('Unserializer'); + // `lime.system.CFFI` + // Can load and execute compiled binaries. + Polymod.blacklistImport('lime.system.CFFI'); + + // `lime.system.JNI` + // Can load and execute compiled binaries. + Polymod.blacklistImport('lime.system.JNI'); + + // `lime.system.System` + // System.load() can load malicious DLLs + Polymod.blacklistImport('lime.system.System'); + + // `lime.utils.Assets` + // Literally just has a private `resolveClass` function for some reason? + Polymod.blacklistImport('lime.utils.Assets'); + Polymod.blacklistImport('openfl.utils.Assets'); + + // `openfl.desktop.NativeProcess` + // Can load native processes on the host operating system. + Polymod.blacklistImport('openfl.desktop.NativeProcess'); + // `polymod.*` - // You can probably unblacklist a module + // Contains functions which may allow for un-blacklisting other modules. for (cls in ClassMacro.listClassesInPackage('polymod')) { if (cls == null) continue; @@ -268,6 +288,7 @@ class PolymodHandler } // `sys.*` + // Access to system utilities such as the file system. for (cls in ClassMacro.listClassesInPackage('sys')) { if (cls == null) continue; diff --git a/source/funkin/play/PauseSubState.hx b/source/funkin/play/PauseSubState.hx index 6f8908eea..9ff70bee5 100644 --- a/source/funkin/play/PauseSubState.hx +++ b/source/funkin/play/PauseSubState.hx @@ -430,7 +430,7 @@ class PauseSubState extends MusicBeatSubState resume(this); } - #if (debug || FORCE_DEBUG_VERSION) + #if FEATURE_DEBUG_FUNCTIONS // to pause the game and get screenshots easy, press H on pause menu! if (FlxG.keys.justPressed.H) { diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index b6a17947f..928f392e5 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -67,7 +67,7 @@ import lime.ui.Haptic; import openfl.display.BitmapData; import openfl.geom.Rectangle; import openfl.Lib; -#if discord_rpc +#if FEATURE_DISCORD_RPC import Discord.DiscordClient; #end @@ -445,7 +445,7 @@ class PlayState extends MusicBeatSubState */ public var vocals:VoicesGroup; - #if discord_rpc + #if FEATURE_DISCORD_RPC // Discord RPC variables var storyDifficultyText:String = ''; var iconRPC:String = ''; @@ -698,7 +698,7 @@ class PlayState extends MusicBeatSubState initStrumlines(); initPopups(); - #if discord_rpc + #if FEATURE_DISCORD_RPC // Initialize Discord Rich Presence. initDiscord(); #end @@ -738,7 +738,7 @@ class PlayState extends MusicBeatSubState rightWatermarkText.cameras = [camHUD]; // Initialize some debug stuff. - #if (debug || FORCE_DEBUG_VERSION) + #if FEATURE_DEBUG_FUNCTIONS // Display the version number (and git commit hash) in the bottom right corner. this.rightWatermarkText.text = Constants.VERSION; @@ -977,7 +977,7 @@ class PlayState extends MusicBeatSubState // boyfriendPos.put(); // TODO: Why is this here? } - #if discord_rpc + #if FEATURE_DISCORD_RPC DiscordClient.changePresence(detailsPausedText, currentSong.song + ' (' + storyDifficultyText + ')', iconRPC); #end } @@ -1036,7 +1036,7 @@ class PlayState extends MusicBeatSubState // Disable updates, preventing animations in the background from playing. persistentUpdate = false; - #if (debug || FORCE_DEBUG_VERSION) + #if FEATURE_DEBUG_FUNCTIONS if (FlxG.keys.pressed.THREE) { // TODO: Change the key or delete this? @@ -1047,7 +1047,7 @@ class PlayState extends MusicBeatSubState { #end persistentDraw = false; - #if (debug || FORCE_DEBUG_VERSION) + #if FEATURE_DEBUG_FUNCTIONS } #end @@ -1066,7 +1066,7 @@ class PlayState extends MusicBeatSubState moveToGameOver(); } - #if discord_rpc + #if FEATURE_DISCORD_RPC // Game Over doesn't get his own variable because it's only used here DiscordClient.changePresence('Game Over - ' + detailsText, currentSong.song + ' (' + storyDifficultyText + ')', iconRPC); #end @@ -1179,9 +1179,9 @@ class PlayState extends MusicBeatSubState } /** - * Function called before opening a new substate. - * @param subState The substate to open. - */ + * Function called before opening a new substate. + * @param subState The substate to open. + */ public override function openSubState(subState:FlxSubState):Void { // If there is a substate which requires the game to continue, @@ -1237,9 +1237,9 @@ class PlayState extends MusicBeatSubState } /** - * Function called before closing the current substate. - * @param subState - */ + * Function called before closing the current substate. + * @param subState + */ public override function closeSubState():Void { if (Std.isOfType(subState, PauseSubState)) @@ -1278,7 +1278,7 @@ class PlayState extends MusicBeatSubState // Resume the countdown. Countdown.resumeCountdown(); - #if discord_rpc + #if FEATURE_DISCORD_RPC if (startTimer.finished) { DiscordClient.changePresence(detailsText, '${currentChart.songName} ($storyDifficultyText)', iconRPC, true, @@ -1301,8 +1301,8 @@ class PlayState extends MusicBeatSubState } /** - * Function called when the game window gains focus. - */ + * Function called when the game window gains focus. + */ public override function onFocus():Void { if (VideoCutscene.isPlaying() && FlxG.autoPause && isGamePaused) VideoCutscene.pauseVideo(); @@ -1311,7 +1311,7 @@ class PlayState extends MusicBeatSubState VideoCutscene.resumeVideo(); #end - #if discord_rpc + #if FEATURE_DISCORD_RPC if (health > Constants.HEALTH_MIN && !paused && FlxG.autoPause) { if (Conductor.instance.songPosition > 0.0) DiscordClient.changePresence(detailsText, currentSong.song @@ -1329,15 +1329,15 @@ class PlayState extends MusicBeatSubState } /** - * Function called when the game window loses focus. - */ + * Function called when the game window loses focus. + */ public override function onFocusLost():Void { #if html5 if (FlxG.autoPause) VideoCutscene.pauseVideo(); #end - #if discord_rpc + #if FEATURE_DISCORD_RPC if (health > Constants.HEALTH_MIN && !paused && FlxG.autoPause) DiscordClient.changePresence(detailsPausedText, currentSong.song + ' (' + storyDifficultyText + ')', iconRPC); #end @@ -1346,8 +1346,8 @@ class PlayState extends MusicBeatSubState } /** - * Call this by pressing F5 on a debug build. - */ + * Call this by pressing F5 on a debug build. + */ override function reloadAssets():Void { funkin.modding.PolymodHandler.forceReloadAssets(); @@ -1459,8 +1459,8 @@ class PlayState extends MusicBeatSubState } /** - * Initializes the game and HUD cameras. - */ + * Initializes the game and HUD cameras. + */ function initCameras():Void { camGame = new FunkinCamera('playStateCamGame'); @@ -1484,8 +1484,8 @@ class PlayState extends MusicBeatSubState } /** - * Initializes the health bar on the HUD. - */ + * Initializes the health bar on the HUD. + */ function initHealthBar():Void { var healthBarYPos:Float = Preferences.downscroll ? FlxG.height * 0.1 : FlxG.height * 0.9; @@ -1516,8 +1516,8 @@ class PlayState extends MusicBeatSubState } /** - * Generates the stage and all its props. - */ + * Generates the stage and all its props. + */ function initStage():Void { loadStage(currentStageId); @@ -1537,10 +1537,10 @@ class PlayState extends MusicBeatSubState } /** - * Loads stage data from cache, assembles the props, - * and adds it to the state. - * @param id - */ + * Loads stage data from cache, assembles the props, + * and adds it to the state. + * @param id + */ function loadStage(id:String):Void { currentStage = StageRegistry.instance.fetchEntry(id); @@ -1558,7 +1558,7 @@ class PlayState extends MusicBeatSubState // Add the stage to the scene. this.add(currentStage); - #if (debug || FORCE_DEBUG_VERSION) + #if FEATURE_DEBUG_FUNCTIONS FlxG.console.registerObject('stage', currentStage); #end } @@ -1581,8 +1581,8 @@ class PlayState extends MusicBeatSubState } /** - * Generates the character sprites and adds them to the stage. - */ + * Generates the character sprites and adds them to the stage. + */ function initCharacters():Void { if (currentSong == null || currentChart == null) @@ -1661,7 +1661,7 @@ class PlayState extends MusicBeatSubState { currentStage.addCharacter(girlfriend, GF); - #if (debug || FORCE_DEBUG_VERSION) + #if FEATURE_DEBUG_FUNCTIONS FlxG.console.registerObject('gf', girlfriend); #end } @@ -1670,7 +1670,7 @@ class PlayState extends MusicBeatSubState { currentStage.addCharacter(boyfriend, BF); - #if (debug || FORCE_DEBUG_VERSION) + #if FEATURE_DEBUG_FUNCTIONS FlxG.console.registerObject('bf', boyfriend); #end } @@ -1681,7 +1681,7 @@ class PlayState extends MusicBeatSubState // Camera starts at dad. cameraFollowPoint.setPosition(dad.cameraFocusPoint.x, dad.cameraFocusPoint.y); - #if (debug || FORCE_DEBUG_VERSION) + #if FEATURE_DEBUG_FUNCTIONS FlxG.console.registerObject('dad', dad); #end } @@ -1692,8 +1692,8 @@ class PlayState extends MusicBeatSubState } /** - * Constructs the strumlines for each player. - */ + * Constructs the strumlines for each player. + */ function initStrumlines():Void { var noteStyleId:String = currentChart.noteStyle; @@ -1725,8 +1725,8 @@ class PlayState extends MusicBeatSubState } /** - * Configures the judgement and combo popups. - */ + * Configures the judgement and combo popups. + */ function initPopups():Void { var noteStyleId:String = currentChart.noteStyle; @@ -1740,11 +1740,11 @@ class PlayState extends MusicBeatSubState } /** - * Initializes the Discord Rich Presence. - */ + * Initializes the Discord Rich Presence. + */ function initDiscord():Void { - #if discord_rpc + #if FEATURE_DISCORD_RPC storyDifficultyText = difficultyString(); iconRPC = currentSong.player2; @@ -1775,9 +1775,9 @@ class PlayState extends MusicBeatSubState } /** - * Initializes the song (applying the chart, generating the notes, etc.) - * Should be done before the countdown starts. - */ + * Initializes the song (applying the chart, generating the notes, etc.) + * Should be done before the countdown starts. + */ function generateSong():Void { if (currentChart == null) @@ -1808,8 +1808,8 @@ class PlayState extends MusicBeatSubState } /** - * Read note data from the chart and generate the notes. - */ + * Read note data from the chart and generate the notes. + */ function regenNoteData(startTime:Float = 0):Void { Highscore.tallies.combo = 0; @@ -1862,10 +1862,10 @@ class PlayState extends MusicBeatSubState } /** - * Prepares to start the countdown. - * Ends any running cutscenes, creates the strumlines, and starts the countdown. - * This is public so that scripts can call it. - */ + * Prepares to start the countdown. + * Ends any running cutscenes, creates the strumlines, and starts the countdown. + * This is public so that scripts can call it. + */ public function startCountdown():Void { // If Countdown.performCountdown returns false, then the countdown was canceled by a script. @@ -1879,9 +1879,9 @@ class PlayState extends MusicBeatSubState } /** - * Displays a dialogue cutscene with the given ID. - * This is used by song scripts to display dialogue. - */ + * Displays a dialogue cutscene with the given ID. + * This is used by song scripts to display dialogue. + */ public function startConversation(conversationId:String):Void { isInCutscene = true; @@ -1901,8 +1901,8 @@ class PlayState extends MusicBeatSubState } /** - * Handler function called when a conversation ends. - */ + * Handler function called when a conversation ends. + */ function onConversationComplete():Void { isInCutscene = false; @@ -1921,8 +1921,8 @@ class PlayState extends MusicBeatSubState } /** - * Starts playing the song after the countdown has completed. - */ + * Starts playing the song after the countdown has completed. + */ function startSong():Void { startingSong = false; @@ -1957,7 +1957,7 @@ class PlayState extends MusicBeatSubState vocals.pitch = playbackRate; resyncVocals(); - #if discord_rpc + #if FEATURE_DISCORD_RPC // Updating Discord Rich Presence (with Time Left) DiscordClient.changePresence(detailsText, '${currentChart.songName} ($storyDifficultyText)', iconRPC, true, currentSongLengthMs); #end @@ -1972,8 +1972,8 @@ class PlayState extends MusicBeatSubState } /** - * Resyncronize the vocal tracks if they have become offset from the instrumental. - */ + * Resyncronize the vocal tracks if they have become offset from the instrumental. + */ function resyncVocals():Void { if (vocals == null) return; @@ -1992,8 +1992,8 @@ class PlayState extends MusicBeatSubState } /** - * Updates the position and contents of the score display. - */ + * Updates the position and contents of the score display. + */ function updateScoreText():Void { // TODO: Add functionality for modules to update the score text. @@ -2010,8 +2010,8 @@ class PlayState extends MusicBeatSubState } /** - * Updates the values of the health bar. - */ + * Updates the values of the health bar. + */ function updateHealthBar():Void { if (isBotPlayMode) @@ -2025,8 +2025,8 @@ class PlayState extends MusicBeatSubState } /** - * Callback executed when one of the note keys is pressed. - */ + * Callback executed when one of the note keys is pressed. + */ function onKeyPress(event:PreciseInputEvent):Void { if (isGamePaused) return; @@ -2036,8 +2036,8 @@ class PlayState extends MusicBeatSubState } /** - * Callback executed when one of the note keys is released. - */ + * Callback executed when one of the note keys is released. + */ function onKeyRelease(event:PreciseInputEvent):Void { if (isGamePaused) return; @@ -2047,8 +2047,8 @@ class PlayState extends MusicBeatSubState } /** - * Handles opponent note hits and player note misses. - */ + * Handles opponent note hits and player note misses. + */ function processNotes(elapsed:Float):Void { if (playerStrumline?.notes?.members == null || opponentStrumline?.notes?.members == null) return; @@ -2266,8 +2266,8 @@ class PlayState extends MusicBeatSubState } /** - * Spitting out the input for ravy 🙇‍♂️!! - */ + * Spitting out the input for ravy 🙇‍♂️!! + */ var inputSpitter:Array = []; function handleSkippedNotes():Void @@ -2291,9 +2291,9 @@ class PlayState extends MusicBeatSubState } /** - * PreciseInputEvents are put into a queue between update() calls, - * and then processed here. - */ + * PreciseInputEvents are put into a queue between update() calls, + * and then processed here. + */ function processInputQueue():Void { if (inputPressQueue.length + inputReleaseQueue.length == 0) return; @@ -2435,9 +2435,9 @@ class PlayState extends MusicBeatSubState } /** - * Called when a note leaves the screen and is considered missed by the player. - * @param note - */ + * Called when a note leaves the screen and is considered missed by the player. + * @param note + */ function onNoteMiss(note:NoteSprite, playSound:Bool = false, healthChange:Float):Void { // If we are here, we already CALLED the onNoteMiss script hook! @@ -2493,13 +2493,13 @@ class PlayState extends MusicBeatSubState } /** - * Called when a player presses a key with no note present. - * Scripts can modify the amount of health/score lost, whether player animations or sounds are used, - * or even cancel the event entirely. - * - * @param direction - * @param hasPossibleNotes - */ + * Called when a player presses a key with no note present. + * Scripts can modify the amount of health/score lost, whether player animations or sounds are used, + * or even cancel the event entirely. + * + * @param direction + * @param hasPossibleNotes + */ function ghostNoteMiss(direction:NoteDirection, hasPossibleNotes:Bool = true):Void { var event:GhostMissNoteScriptEvent = new GhostMissNoteScriptEvent(direction, // Direction missed in. @@ -2548,11 +2548,11 @@ class PlayState extends MusicBeatSubState } /** - * Debug keys. Disabled while in cutscenes. - */ + * Debug keys. Disabled while in cutscenes. + */ function debugKeyShit():Void { - #if CHART_EDITOR_SUPPORTED + #if FEATURE_CHART_EDITOR // Open the stage editor overlaying the current state. if (controls.DEBUG_STAGE) { @@ -2582,7 +2582,7 @@ class PlayState extends MusicBeatSubState } #end - #if (debug || FORCE_DEBUG_VERSION) + #if FEATURE_DEBUG_FUNCTIONS // H: Hide the HUD. if (FlxG.keys.justPressed.H) camHUD.visible = !camHUD.visible; @@ -2599,7 +2599,7 @@ class PlayState extends MusicBeatSubState // 9: Toggle the old icon. if (FlxG.keys.justPressed.NINE) iconP1.toggleOldIcon(); - #if (debug || FORCE_DEBUG_VERSION) + #if FEATURE_DEBUG_FUNCTIONS // PAGEUP: Skip forward two sections. // SHIFT+PAGEUP: Skip forward twenty sections. if (FlxG.keys.justPressed.PAGEUP) changeSection(FlxG.keys.pressed.SHIFT ? 20 : 2); @@ -2612,8 +2612,8 @@ class PlayState extends MusicBeatSubState } /** - * Handles applying health, score, and ratings. - */ + * Handles applying health, score, and ratings. + */ function applyScore(score:Int, daRating:String, healthChange:Float, isComboBreak:Bool) { switch (daRating) @@ -2645,8 +2645,8 @@ class PlayState extends MusicBeatSubState } /** - * Handles rating popups when a note is hit. - */ + * Handles rating popups when a note is hit. + */ function popUpScore(daRating:String, ?combo:Int):Void { if (daRating == 'miss') @@ -2703,10 +2703,10 @@ class PlayState extends MusicBeatSubState } /** - * Handle keyboard inputs during cutscenes. - * This includes advancing conversations and skipping videos. - * @param elapsed Time elapsed since last game update. - */ + * Handle keyboard inputs during cutscenes. + * This includes advancing conversations and skipping videos. + * @param elapsed Time elapsed since last game update. + */ function handleCutsceneKeys(elapsed:Float):Void { if (isGamePaused) return; @@ -2750,20 +2750,20 @@ class PlayState extends MusicBeatSubState } /** - * Handle logic for actually skipping a video cutscene after it has been held. - */ + * Handle logic for actually skipping a video cutscene after it has been held. + */ function skipVideoCutscene():Void { VideoCutscene.finishVideo(); } /** - * End the song. Handle saving high scores and transitioning to the results screen. - * - * Broadcasts an `onSongEnd` event, which can be cancelled to prevent the song from ending (for a cutscene or something). - * Remember to call `endSong` again when the song should actually end! - * @param rightGoddamnNow If true, don't play the fancy animation where you zoom onto Girlfriend. Used after a cutscene. - */ + * End the song. Handle saving high scores and transitioning to the results screen. + * + * Broadcasts an `onSongEnd` event, which can be cancelled to prevent the song from ending (for a cutscene or something). + * Remember to call `endSong` again when the song should actually end! + * @param rightGoddamnNow If true, don't play the fancy animation where you zoom onto Girlfriend. Used after a cutscene. + */ public function endSong(rightGoddamnNow:Bool = false):Void { if (FlxG.sound.music != null) FlxG.sound.music.volume = 0; @@ -2978,8 +2978,8 @@ class PlayState extends MusicBeatSubState } /** - * Perform necessary cleanup before leaving the PlayState. - */ + * Perform necessary cleanup before leaving the PlayState. + */ function performCleanup():Void { // If the camera is being tweened, stop it. @@ -3037,8 +3037,8 @@ class PlayState extends MusicBeatSubState } /** - * Play the camera zoom animation and then move to the results screen once it's done. - */ + * Play the camera zoom animation and then move to the results screen once it's done. + */ function zoomIntoResultsScreen(isNewHighscore:Bool, ?prevScoreData:SaveScoreData):Void { trace('WENT TO RESULTS SCREEN!'); @@ -3102,17 +3102,17 @@ class PlayState extends MusicBeatSubState // Zoom over to the Results screen. // TODO: Re-enable this. /* - FlxTween.tween(FlxG.camera, {zoom: 1200}, 1.1, - { - ease: FlxEase.expoIn, - }); - */ + FlxTween.tween(FlxG.camera, {zoom: 1200}, 1.1, + { + ease: FlxEase.expoIn, + }); + */ }); } /** - * Move to the results screen right goddamn now. - */ + * Move to the results screen right goddamn now. + */ function moveToResultsScreen(isNewHighscore:Bool, ?prevScoreData:SaveScoreData):Void { persistentUpdate = false; @@ -3152,8 +3152,8 @@ class PlayState extends MusicBeatSubState } /** - * Pauses music and vocals easily. - */ + * Pauses music and vocals easily. + */ public function pauseMusic():Void { if (FlxG.sound.music != null) FlxG.sound.music.pause(); @@ -3161,8 +3161,8 @@ class PlayState extends MusicBeatSubState } /** - * Resets the camera's zoom level and focus point. - */ + * Resets the camera's zoom level and focus point. + */ public function resetCamera(?resetZoom:Bool = true, ?cancelTweens:Bool = true):Void { // Cancel camera tweens if any are active. @@ -3184,8 +3184,8 @@ class PlayState extends MusicBeatSubState } /** - * Sets the camera follow point's position and tweens the camera there. - */ + * Sets the camera follow point's position and tweens the camera there. + */ public function tweenCameraToPosition(?x:Float, ?y:Float, ?duration:Float, ?ease:NullFloat>):Void { cameraFollowPoint.setPosition(x, y); @@ -3193,8 +3193,8 @@ class PlayState extends MusicBeatSubState } /** - * Disables camera following and tweens the camera to the follow point manually. - */ + * Disables camera following and tweens the camera to the follow point manually. + */ public function tweenCameraToFollowPoint(?duration:Float, ?ease:NullFloat>):Void { // Cancel the current tween if it's active. @@ -3231,8 +3231,8 @@ class PlayState extends MusicBeatSubState } /** - * Tweens the camera zoom to the desired amount. - */ + * Tweens the camera zoom to the desired amount. + */ public function tweenCameraZoom(?zoom:Float, ?duration:Float, ?direct:Bool, ?ease:NullFloat>):Void { // Cancel the current tween if it's active. @@ -3263,8 +3263,8 @@ class PlayState extends MusicBeatSubState } /** - * Cancel all active camera tweens simultaneously. - */ + * Cancel all active camera tweens simultaneously. + */ public function cancelAllCameraTweens() { cancelCameraFollowTween(); @@ -3274,8 +3274,8 @@ class PlayState extends MusicBeatSubState var prevScrollTargets:Array = []; // used to snap scroll speed when things go unruely /** - * The magical function that shall tween the scroll speed. - */ + * The magical function that shall tween the scroll speed. + */ public function tweenScrollSpeed(?speed:Float, ?duration:Float, ?ease:NullFloat>, strumlines:Array):Void { // Cancel the current tween if it's active. @@ -3325,12 +3325,12 @@ class PlayState extends MusicBeatSubState scrollSpeedTweens = []; } - #if (debug || FORCE_DEBUG_VERSION) + #if FEATURE_DEBUG_FUNCTIONS /** - * Jumps forward or backward a number of sections in the song. - * Accounts for BPM changes, does not prevent death from skipped notes. - * @param sections The number of sections to jump, negative to go backwards. - */ + * Jumps forward or backward a number of sections in the song. + * Accounts for BPM changes, does not prevent death from skipped notes. + * @param sections The number of sections to jump, negative to go backwards. + */ function changeSection(sections:Int):Void { // FlxG.sound.music.pause(); diff --git a/source/funkin/play/stage/Stage.hx b/source/funkin/play/stage/Stage.hx index 85b0056ca..dc24b7a5b 100644 --- a/source/funkin/play/stage/Stage.hx +++ b/source/funkin/play/stage/Stage.hx @@ -386,7 +386,7 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements { if (character == null) return; - #if debug + #if FEATURE_DEBUG_FUNCTIONS // Temporary marker that shows where the character's location is relative to. // Should display at the stage position of the character (before any offsets). // TODO: Make this a toggle? It's useful to turn on from time to time. @@ -451,7 +451,7 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements character.cameraFocusPoint.x += stageCharData.cameraOffsets[0]; character.cameraFocusPoint.y += stageCharData.cameraOffsets[1]; - #if debug + #if FEATURE_DEBUG_FUNCTIONS // Draw the debug icon at the character's feet. if (charType == BF || charType == DAD) { @@ -468,7 +468,7 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements ScriptEventDispatcher.callEvent(character, new ScriptEvent(ADDED, false)); - #if debug + #if FEATURE_DEBUG_FUNCTIONS debugIconGroup.add(debugIcon); debugIconGroup.add(debugIcon2); #end diff --git a/source/funkin/ui/debug/DebugMenuSubState.hx b/source/funkin/ui/debug/DebugMenuSubState.hx index 590cce88b..fc5f3aa37 100644 --- a/source/funkin/ui/debug/DebugMenuSubState.hx +++ b/source/funkin/ui/debug/DebugMenuSubState.hx @@ -54,7 +54,7 @@ class DebugMenuSubState extends MusicBeatSubState // Create each menu item. // Call onMenuChange when the first item is created to move the camera . - #if CHART_EDITOR_SUPPORTED + #if FEATURE_CHART_EDITOR onMenuChange(createItem("CHART EDITOR", openChartEditor)); #end // createItem("Input Offset Testing", openInputOffsetTesting); diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index ebfbe5eac..a1d7aca6b 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -3327,7 +3327,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState handleTestKeybinds(); handleHelpKeybinds(); - #if (debug || FORCE_DEBUG_VERSION) + #if FEATURE_DEBUG_FUNCTIONS handleQuickWatch(); #end diff --git a/source/funkin/ui/freeplay/FreeplayDJ.hx b/source/funkin/ui/freeplay/FreeplayDJ.hx index 317a52308..fd00a9549 100644 --- a/source/funkin/ui/freeplay/FreeplayDJ.hx +++ b/source/funkin/ui/freeplay/FreeplayDJ.hx @@ -148,7 +148,7 @@ class FreeplayDJ extends FlxAtlasSprite // I shit myself. } - #if debug + #if FEATURE_DEBUG_FUNCTIONS if (FlxG.keys.pressed.CONTROL) { if (FlxG.keys.justPressed.LEFT) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 9e0e15019..cffb0b5a4 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -291,14 +291,14 @@ class FreeplayState extends MusicBeatSubState stickerSubState.degenStickers(); } - #if discord_rpc + #if FEATURE_DISCORD_RPC // Updating Discord Rich Presence DiscordClient.changePresence('In the Menus', null); #end var isDebug:Bool = false; - #if debug + #if FEATURE_DEBUG_FUNCTIONS isDebug = true; #end @@ -871,7 +871,7 @@ class FreeplayState extends MusicBeatSubState return str.songName.toLowerCase().startsWith(songFilter.filterData ?? ''); }); case ALL: - // no filter! + // no filter! case FAVORITE: songsToFilter = songsToFilter.filter(str -> { if (str == null) return true; // Random @@ -1198,7 +1198,7 @@ class FreeplayState extends MusicBeatSubState { super.update(elapsed); - #if debug + #if FEATURE_DEBUG_FUNCTIONS if (FlxG.keys.justPressed.T) { rankAnimStart(fromResultsParams ?? @@ -1772,7 +1772,7 @@ class FreeplayState extends MusicBeatSubState var targetInstId:String = baseInstrumentalId; // TODO: Make this a UI element. - #if (debug || FORCE_DEBUG_VERSION) + #if FEATURE_DEBUG_FUNCTIONS if (altInstrumentalIds.length > 0 && FlxG.keys.pressed.CONTROL) { targetInstId = altInstrumentalIds[0]; @@ -1833,7 +1833,7 @@ class FreeplayState extends MusicBeatSubState practiceMode: false, minimalMode: false, - #if (debug || FORCE_DEBUG_VERSION) + #if FEATURE_DEBUG_FUNCTIONS botPlayMode: FlxG.keys.pressed.SHIFT, #else botPlayMode: false, @@ -1942,7 +1942,7 @@ class FreeplayState extends MusicBeatSubState var instSuffix:String = baseInstrumentalId; // TODO: Make this a UI element. - #if (debug || FORCE_DEBUG_VERSION) + #if FEATURE_DEBUG_FUNCTIONS if (altInstrumentalIds.length > 0 && FlxG.keys.pressed.CONTROL) { instSuffix = altInstrumentalIds[0]; diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index d219bfbcf..2d809354a 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -27,7 +27,7 @@ import funkin.ui.title.TitleState; import funkin.ui.story.StoryMenuState; import funkin.ui.Prompt; import funkin.util.WindowUtil; -#if discord_rpc +#if FEATURE_DISCORD_RPC import Discord.DiscordClient; #end #if newgrounds @@ -54,7 +54,7 @@ class MainMenuState extends MusicBeatState override function create():Void { - #if discord_rpc + #if FEATURE_DISCORD_RPC // Updating Discord Rich Presence DiscordClient.changePresence("In the Menus", null); #end @@ -344,7 +344,7 @@ class MainMenuState extends MusicBeatState } } - #if (debug || FORCE_DEBUG_VERSION) + #if FEATURE_DEBUG_FUNCTIONS // Open the debug menu, defaults to ` / ~ if (controls.DEBUG_MENU) { diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx index 4e51fb229..18614d414 100644 --- a/source/funkin/ui/story/StoryMenuState.hx +++ b/source/funkin/ui/story/StoryMenuState.hx @@ -216,7 +216,7 @@ class StoryMenuState extends MusicBeatState changeLevel(); refresh(); - #if discord_rpc + #if FEATURE_DISCORD_RPC // Updating Discord Rich Presence DiscordClient.changePresence('In the Menus', null); #end diff --git a/source/funkin/ui/transition/LoadingState.hx b/source/funkin/ui/transition/LoadingState.hx index d48ca1c0b..067de0e7f 100644 --- a/source/funkin/ui/transition/LoadingState.hx +++ b/source/funkin/ui/transition/LoadingState.hx @@ -174,7 +174,7 @@ class LoadingState extends MusicBeatSubState FlxG.watch.addQuick('percentage?', callbacks.numRemaining / callbacks.length); } - #if debug + #if FEATURE_DEBUG_FUNCTIONS if (FlxG.keys.justPressed.SPACE) trace('fired: ' + callbacks.getFired() + ' unfired:' + callbacks.getUnfired()); #end } diff --git a/source/funkin/util/Constants.hx b/source/funkin/util/Constants.hx index 85cd1a27b..80318f1a4 100644 --- a/source/funkin/util/Constants.hx +++ b/source/funkin/util/Constants.hx @@ -41,9 +41,9 @@ class Constants * A suffix to add to the game version. * Add a suffix to prototype builds and remove it for releases. */ - public static final VERSION_SUFFIX:String = #if (DEBUG || FORCE_DEBUG_VERSION) ' PROTOTYPE' #else '' #end; + public static final VERSION_SUFFIX:String = #if FEATURE_DEBUG_FUNCTIONS ' PROTOTYPE' #else '' #end; - #if (debug || FORCE_DEBUG_VERSION) + #if FEATURE_DEBUG_FUNCTIONS static function get_VERSION():String { return 'v${Application.current.meta.get('version')} (${GIT_BRANCH} : ${GIT_HASH}${GIT_HAS_LOCAL_CHANGES ? ' : MODIFIED' : ''})' + VERSION_SUFFIX; @@ -384,11 +384,7 @@ class Constants * 1 = The preloader waits for 1 second before moving to the next step. * The progress bare is automatically rescaled to match. */ - #if debug - public static final PRELOADER_MIN_STAGE_TIME:Float = 0.0; - #else public static final PRELOADER_MIN_STAGE_TIME:Float = 0.1; - #end /** * HEALTH VALUES From 91e4043ce99b4370ffbc01feaf0e2862ecabb508 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 26 Aug 2024 21:58:35 -0400 Subject: [PATCH 615/870] small hmm updates --- hmm.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hmm.json b/hmm.json index 4cd3e27c7..1a1fd2203 100644 --- a/hmm.json +++ b/hmm.json @@ -59,7 +59,7 @@ "type": "git", "dir": null, "ref": "22b1ce089dd924f15cdc4632397ef3504d464e90", - "url": "https://github.com/MidyGamy/funkVis/" + "url": "https://github.com/FunkinCrew/funkVis/" }, { "name": "grig.audio", @@ -104,7 +104,7 @@ "type": "git", "dir": null, "url": "https://github.com/HaxeFoundation/hxcpp", - "ref": "8dc8020f8465027de6c2aaaed90718bc693651ed" + "ref": "904ea40643b050a5a154c5e4c33a83fd2aec18b1" }, { "name": "hxcpp-debug-server", @@ -143,7 +143,7 @@ "name": "lime", "type": "git", "dir": null, - "ref": "f6153ffcb1ffcf733f91d531eac5fda4189e07f7", + "ref": "e0b2339e02fff91168789dbd1a0dd019ea3dda39", "url": "https://github.com/FunkinCrew/lime" }, { From 5caba54e19b68b2e7eb220d127386fd3d5dc0770 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 27 Aug 2024 02:33:17 -0400 Subject: [PATCH 616/870] Update HScript to use the organization's fork --- hmm.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hmm.json b/hmm.json index 38e82acf2..017b8714c 100644 --- a/hmm.json +++ b/hmm.json @@ -91,8 +91,8 @@ "name": "hscript", "type": "git", "dir": null, - "ref": "59b33162e9dcd7e48b186a9f25ee81b6e47a4dd7", - "url": "https://github.com/haxefoundation/hscript" + "ref": "12785398e2f07082f05034cb580682e5671442a2", + "url": "https://github.com/FunkinCrew/hscript" }, { "name": "hxCodec", From df42ac75311165fd1348b807365b73846e11b0fe Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 27 Aug 2024 04:20:49 -0400 Subject: [PATCH 617/870] Fixed issues with Nene offsets in Pico mode --- assets | 2 +- source/funkin/play/character/BaseCharacter.hx | 2 -- source/funkin/play/character/MultiSparrowCharacter.hx | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/assets b/assets index 2ad892c76..8573b2039 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 2ad892c76665abad5764137288c606f2f4fcd331 +Subproject commit 8573b2039b9fb37551a41f5195aaa2abdc63770e diff --git a/source/funkin/play/character/BaseCharacter.hx b/source/funkin/play/character/BaseCharacter.hx index 15e196dc1..55b849bcb 100644 --- a/source/funkin/play/character/BaseCharacter.hx +++ b/source/funkin/play/character/BaseCharacter.hx @@ -411,7 +411,6 @@ class BaseCharacter extends Bopper else { // Play the idle animation. - trace('${characterId}: attempting dance'); dance(true); } } @@ -633,7 +632,6 @@ class BaseCharacter extends Bopper public override function playAnimation(name:String, restart:Bool = false, ignoreOther:Bool = false, reversed:Bool = false):Void { - // FlxG.watch.addQuick('playAnim(${characterName})', name); super.playAnimation(name, restart, ignoreOther, reversed); } } diff --git a/source/funkin/play/character/MultiSparrowCharacter.hx b/source/funkin/play/character/MultiSparrowCharacter.hx index e23afe18c..759d17a6b 100644 --- a/source/funkin/play/character/MultiSparrowCharacter.hx +++ b/source/funkin/play/character/MultiSparrowCharacter.hx @@ -67,6 +67,8 @@ class MultiSparrowCharacter extends BaseCharacter if (texture == null) { trace('Multi-Sparrow atlas could not load PRIMARY texture: ${_data.assetPath}'); + FlxG.log.error('Multi-Sparrow atlas could not load PRIMARY texture: ${_data.assetPath}'); + return; } else { From d02f632c0e706a3454182438b138d42b41e227b9 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 27 Aug 2024 04:54:02 -0400 Subject: [PATCH 618/870] Fix a bug where stage props would receive events twice --- source/funkin/play/stage/Stage.hx | 152 ++++-------------------------- 1 file changed, 20 insertions(+), 132 deletions(-) diff --git a/source/funkin/play/stage/Stage.hx b/source/funkin/play/stage/Stage.hx index 85b0056ca..bece8b530 100644 --- a/source/funkin/play/stage/Stage.hx +++ b/source/funkin/play/stage/Stage.hx @@ -769,39 +769,15 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements * A function that gets called once per step in the song. * @param curStep The current step number. */ - public function onStepHit(event:SongTimeScriptEvent):Void - { - // Override me in your scripted stage to perform custom behavior! - // Make sure to call super.onStepHit(event) if you want to keep the boppers dancing. - - for (bopper in boppers) - { - ScriptEventDispatcher.callEvent(bopper, event); - } - } + public function onStepHit(event:SongTimeScriptEvent):Void {} /** * A function that gets called once per beat in the song (once every four steps). * @param curStep The current beat number. */ - public function onBeatHit(event:SongTimeScriptEvent):Void - { - // Override me in your scripted stage to perform custom behavior! - // Make sure to call super.onBeatHit(event) if you want to keep the boppers dancing. + public function onBeatHit(event:SongTimeScriptEvent):Void {} - for (bopper in boppers) - { - ScriptEventDispatcher.callEvent(bopper, event); - } - } - - public function onUpdate(event:UpdateScriptEvent) - { - for (bopper in boppers) - { - ScriptEventDispatcher.callEvent(bopper, event); - } - } + public function onUpdate(event:UpdateScriptEvent) {} public override function kill() { @@ -883,129 +859,41 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements public function onScriptEvent(event:ScriptEvent) { + // Ensure all custom events get broadcast to the elements of the stage. + // If we do it here, we don't have to add a handler to EACH script event function. for (bopper in boppers) { ScriptEventDispatcher.callEvent(bopper, event); } } - public function onPause(event:PauseScriptEvent) - { - for (bopper in boppers) - { - ScriptEventDispatcher.callEvent(bopper, event); - } - } + public function onPause(event:PauseScriptEvent) {} - public function onResume(event:ScriptEvent) - { - for (bopper in boppers) - { - ScriptEventDispatcher.callEvent(bopper, event); - } - } + public function onResume(event:ScriptEvent) {} - public function onSongStart(event:ScriptEvent) - { - for (bopper in boppers) - { - ScriptEventDispatcher.callEvent(bopper, event); - } - } + public function onSongStart(event:ScriptEvent) {} - public function onSongEnd(event:ScriptEvent) - { - for (bopper in boppers) - { - ScriptEventDispatcher.callEvent(bopper, event); - } - } + public function onSongEnd(event:ScriptEvent) {} - public function onGameOver(event:ScriptEvent) - { - for (bopper in boppers) - { - ScriptEventDispatcher.callEvent(bopper, event); - } - } + public function onGameOver(event:ScriptEvent) {} - public function onCountdownStart(event:CountdownScriptEvent) - { - for (bopper in boppers) - { - ScriptEventDispatcher.callEvent(bopper, event); - } - } + public function onCountdownStart(event:CountdownScriptEvent) {} - public function onCountdownStep(event:CountdownScriptEvent) - { - for (bopper in boppers) - { - ScriptEventDispatcher.callEvent(bopper, event); - } - } + public function onCountdownStep(event:CountdownScriptEvent) {} - public function onCountdownEnd(event:CountdownScriptEvent) - { - for (bopper in boppers) - { - ScriptEventDispatcher.callEvent(bopper, event); - } - } + public function onCountdownEnd(event:CountdownScriptEvent) {} - public function onNoteIncoming(event:NoteScriptEvent) - { - for (bopper in boppers) - { - ScriptEventDispatcher.callEvent(bopper, event); - } - } + public function onNoteIncoming(event:NoteScriptEvent) {} - public function onNoteHit(event:HitNoteScriptEvent) - { - for (bopper in boppers) - { - ScriptEventDispatcher.callEvent(bopper, event); - } - } + public function onNoteHit(event:HitNoteScriptEvent) {} - public function onNoteMiss(event:NoteScriptEvent) - { - for (bopper in boppers) - { - ScriptEventDispatcher.callEvent(bopper, event); - } - } + public function onNoteMiss(event:NoteScriptEvent) {} - public function onSongEvent(event:SongEventScriptEvent) - { - for (bopper in boppers) - { - ScriptEventDispatcher.callEvent(bopper, event); - } - } + public function onSongEvent(event:SongEventScriptEvent) {} - public function onNoteGhostMiss(event:GhostMissNoteScriptEvent) - { - for (bopper in boppers) - { - ScriptEventDispatcher.callEvent(bopper, event); - } - } + public function onNoteGhostMiss(event:GhostMissNoteScriptEvent) {} - public function onSongLoaded(event:SongLoadScriptEvent) - { - for (bopper in boppers) - { - ScriptEventDispatcher.callEvent(bopper, event); - } - } + public function onSongLoaded(event:SongLoadScriptEvent) {} - public function onSongRetry(event:ScriptEvent) - { - for (bopper in boppers) - { - ScriptEventDispatcher.callEvent(bopper, event); - } - } + public function onSongRetry(event:ScriptEvent) {} } From 82496299e79e39729df70b1cdff28ffa12c1c13a Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 27 Aug 2024 14:21:40 -0400 Subject: [PATCH 619/870] Display syntax formatting in project.hxp on Github.com --- .gitattributes | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index 94f480de9..e7a218c89 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,3 @@ -* text=auto eol=lf \ No newline at end of file +* text=auto eol=lf +*.hxc linguist-language=Haxe +*.hxp linguist-language=Haxe From 861b869b2d88784b3fcbde951dbb776ef5ce182f Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 27 Aug 2024 15:23:27 -0400 Subject: [PATCH 620/870] fonts fix for mac --- source/funkin/ui/credits/CreditsState.hx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/funkin/ui/credits/CreditsState.hx b/source/funkin/ui/credits/CreditsState.hx index 44769e9b3..b37985650 100644 --- a/source/funkin/ui/credits/CreditsState.hx +++ b/source/funkin/ui/credits/CreditsState.hx @@ -34,7 +34,13 @@ class CreditsState extends MusicBeatState * To use a font from the `assets` folder, use `Paths.font(...)`. * Choose something that will render Unicode properly. */ + #if windows static final CREDITS_FONT = 'Consolas'; + #elseif mac + static final CREDITS_FONT = 'Menlo'; + #else + static final CREDITS_FONT = "Courier New"; + #end /** * The size of the font. From 9b712ce2aa407ba2ac01715e76eaceadb02207b9 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 27 Aug 2024 16:13:52 -0400 Subject: [PATCH 621/870] bump flixel --- hmm.json | 8 +++----- source/funkin/ui/charSelect/CharSelectSubState.hx | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/hmm.json b/hmm.json index c6fb67eba..0520b85c9 100644 --- a/hmm.json +++ b/hmm.json @@ -18,7 +18,7 @@ "name": "flixel", "type": "git", "dir": null, - "ref": "10c2a203c43a78ff1ff26b8368fd736576829d8d", + "ref": "599f38eeb502a8ba6439784036c2cfdc7b485260", "url": "https://github.com/FunkinCrew/flixel" }, { @@ -59,9 +59,7 @@ "type": "git", "dir": null, "ref": "22b1ce089dd924f15cdc4632397ef3504d464e90", - "url": "https://github.com/FunkinCrew/funkVis" - }, { "name": "grig.audio", @@ -107,8 +105,8 @@ "name": "hxcpp", "type": "git", "dir": null, - "url": "https://github.com/HaxeFoundation/hxcpp", - "ref": "904ea40643b050a5a154c5e4c33a83fd2aec18b1" + "ref": "904ea40643b050a5a154c5e4c33a83fd2aec18b1", + "url": "https://github.com/HaxeFoundation/hxcpp" }, { "name": "hxcpp-debug-server", diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index 8b1f050f5..41ed7ef1e 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -245,7 +245,7 @@ class CharSelectSubState extends MusicBeatSubState cursorBlue.scrollFactor.set(); cursorDarkBlue.scrollFactor.set(); - FlxTween.color(cursor, 0.2, 0xFFFFFF00, 0xFFFFCC00, {type: FlxTween.PINGPONG}); + FlxTween.color(cursor, 0.2, 0xFFFFFF00, 0xFFFFCC00, {type: PINGPONG}); // FlxG.debugger.track(cursor); From 353aa42f5b46122b2115b7be0ca54ed416adb47f Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Wed, 28 Aug 2024 02:48:56 +0200 Subject: [PATCH 622/870] Fixes for the atlasSprite bizz --- assets | 2 +- .../graphics/adobeanimate/FlxAtlasSprite.hx | 32 ++++++- source/funkin/ui/charSelect/CharSelectGF.hx | 34 +------- .../funkin/ui/charSelect/CharSelectPlayer.hx | 85 +++++-------------- .../ui/charSelect/CharSelectSubState.hx | 17 ++-- source/funkin/ui/freeplay/AlbumRoll.hx | 4 +- source/funkin/ui/freeplay/FreeplayState.hx | 3 + 7 files changed, 66 insertions(+), 111 deletions(-) diff --git a/assets b/assets index 0e4392bcb..f986e5281 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 0e4392bcb0ed1dbb496764cff074635c20c91389 +Subproject commit f986e52819c5fd2e47f4d8d3297f326351682675 diff --git a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx index fdb53e30e..9a9ba7036 100644 --- a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx +++ b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx @@ -9,6 +9,7 @@ import flixel.system.FlxAssets.FlxGraphicAsset; import openfl.display.BitmapData; import openfl.utils.Assets; import flixel.math.FlxPoint; +import flxanimate.animate.FlxKeyFrame; /** * A sprite which provides convenience functions for rendering a texture atlas with animations. @@ -121,6 +122,12 @@ class FlxAtlasSprite extends FlxAnimate return false; } + var _completeAnim:Bool = false; + + var fr:FlxKeyFrame = null; + + var looping:Bool = false; + /** * Plays an animation. * @param id A string ID of the animation to play. @@ -174,6 +181,8 @@ class FlxAtlasSprite extends FlxAnimate } }); + looping = loop; + // Prevent other animations from playing if `ignoreOther` is true. if (ignoreOther) canPlayOtherAnims = false; @@ -182,6 +191,9 @@ class FlxAtlasSprite extends FlxAnimate trace('Playing animation $id'); this.anim.play(id, restart, false, startFrame); goToFrameLabel(id); + + fr = anim.getFrameLabel(id); + anim.curFrame += startFrame; this.currentAnimation = id; } @@ -259,7 +271,21 @@ class FlxAtlasSprite extends FlxAnimate if (currentAnimation != null) { onAnimationFrame.dispatch(currentAnimation, frame); - if (isLoopComplete()) onAnimationLoopComplete.dispatch(currentAnimation); + + if (fr != null && frame > (fr.index + fr.duration - 1) || isLoopFinished()) + { + anim.pause(); + _onAnimationComplete(); + if (looping) + { + anim.curFrame = (fr != null) ? fr.index : 0; + anim.resume(); + } + else + { + anim.curFrame--; + } + } } } @@ -267,7 +293,9 @@ class FlxAtlasSprite extends FlxAnimate { if (currentAnimation != null) { - onAnimationComplete.dispatch(currentAnimation); + if (looping) onAnimationLoopComplete.dispatch(currentAnimation); + else + onAnimationComplete.dispatch(currentAnimation); } } diff --git a/source/funkin/ui/charSelect/CharSelectGF.hx b/source/funkin/ui/charSelect/CharSelectGF.hx index 44a9a6088..cb4eda8be 100644 --- a/source/funkin/ui/charSelect/CharSelectGF.hx +++ b/source/funkin/ui/charSelect/CharSelectGF.hx @@ -29,39 +29,12 @@ class CharSelectGF extends FlxAtlasSprite public function new() { super(0, 0, Paths.animateAtlas("charSelect/gfChill")); - anim.play(""); + list = anim.curSymbol.getFrameLabelNames(); switchGF("bf"); } - var _addedCallback:String = ""; - - override public function playAnimation(id:String, restart:Bool = false, ignoreOther:Bool = false, loop:Bool = false, startFrame:Int = 0):Void - { - if (id == null) id = "idle"; - // var fr = anim.getFrameLabel("confirm"); - // fr.removeCallbacks(); - // fr.add(() -> trace("HEY")); - - if (id != _addedCallback) - { - var next = list[list.indexOf(_addedCallback) + 1]; - if (next != null) anim.getFrameLabel(next).removeCallbacks(); - - var index:Int = list.indexOf(id); - - _addedCallback = list[index]; - if (index != -1 && index + 1 < list.length) - { - var lb = anim.getFrameLabel(list[index + 1]); - @:privateAccess - lb.add(() -> playAnimation(list[index], true, false, false)); - } - } - super.playAnimation(id, restart, ignoreOther, loop, startFrame); - } - override public function update(elapsed:Float) { super.update(elapsed); @@ -190,9 +163,8 @@ class CharSelectGF extends FlxAtlasSprite animInInfo = FramesJSFLParser.parse(Paths.file("images/charSelect/" + str + "AnimInfo/" + str + "In.txt")); animOutInfo = FramesJSFLParser.parse(Paths.file("images/charSelect/" + str + "AnimInfo/" + str + "Out.txt")); - anim.play(""); - playAnimation("idle", true, false, false); - addFrameCallback(getNextFrameLabel("idle"), () -> playAnimation("idle", true, false, false)); + playAnimation("idle", true, false, true); + // addFrameCallback(getNextFrameLabel("idle"), () -> playAnimation("idle", true, false, false)); updateHitbox(); } diff --git a/source/funkin/ui/charSelect/CharSelectPlayer.hx b/source/funkin/ui/charSelect/CharSelectPlayer.hx index 8a5d57530..07c82d038 100644 --- a/source/funkin/ui/charSelect/CharSelectPlayer.hx +++ b/source/funkin/ui/charSelect/CharSelectPlayer.hx @@ -2,82 +2,33 @@ package funkin.ui.charSelect; import flixel.FlxSprite; import funkin.graphics.adobeanimate.FlxAtlasSprite; +import flxanimate.animate.FlxKeyFrame; class CharSelectPlayer extends FlxAtlasSprite { + var desLp:FlxKeyFrame = null; + public function new(x:Float, y:Float) { super(x, y, Paths.animateAtlas("charSelect/bfChill")); + desLp = anim.getFrameLabel("deselect loop start"); + onAnimationComplete.add(function(animLabel:String) { - if (hasAnimation("slidein idle point")) playAnimation("slidein idle point", true, false, false); - else - playAnimation("idle"); + switch (animLabel) + { + case "slidein": + if (hasAnimation("slidein idle point")) playAnimation("slidein idle point", true, false, false); + else + playAnimation("idle", true, false, true); + case "slidein idle point": + playAnimation("idle", true, false, true); + } }); - } - var _addedCall = false; - - override public function playAnimation(id:String, restart:Bool = false, ignoreOther:Bool = false, loop:Bool = false, startFrame:Int = 0):Void - { - if (id == null || id == "") id = "idle"; - switch (id) - { - case "idle", "slidein idle point": - if (!_addedCall) - { - var fr = anim.getFrameLabel("idle end"); - if (fr != null) fr.add(() -> { - playAnimation("idle", true, false, false); - }); - } - _addedCall = true; - - case "select": - if (_addedCall) - { - anim.getFrameLabel("idle end").removeCallbacks(); - _addedCall = false; - } - - var fr = anim.getFrameLabel("deselect"); - - fr.add(() -> { - anim.pause(); - anim.curFrame--; - }); - - _addedCall = true; - - case "deselect": - var og = anim.getFrameLabel("deselect"); - if (_addedCall) - { - og.removeCallbacks(); - _addedCall = false; - } - - var fr = anim.getFrameLabel("deselect loop end"); - - fr.removeCallbacks(); - fr.add(() -> playAnimation("deselect loop start", true, false, false)); - - _addedCall = true; - - case "slidein", "slideout": - if (_addedCall) - { - anim.getFrameLabel("deselect loop end").removeCallbacks(); - _addedCall = false; - } - default: - if (_addedCall) - { - anim.getFrameLabel("idle end").removeCallbacks(); - _addedCall = false; - } - } - super.playAnimation(id, restart, ignoreOther, loop, startFrame); + onAnimationFrame.add(function(animLabel:String, frame:Int) { + if (animLabel == "deselect" && desLp != null && frame >= desLp.index) playAnimation("deselect loop start", true, false, true); + }); } public function updatePosition(str:String) @@ -104,6 +55,8 @@ class CharSelectPlayer extends FlxAtlasSprite playAnimation("slidein", true, false, false); + desLp = anim.getFrameLabel("deselect loop start"); + updateHitbox(); updatePosition(str); diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index 2b577dd95..9aed0ef02 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -499,12 +499,8 @@ class CharSelectSubState extends MusicBeatSubState { ease: FlxEase.quartInOut, onComplete: (_) -> { - var fr = playerChill.anim.getFrameLabel("deselect loop end"); - if (fr != null) fr.removeCallbacks(); - @:privateAccess - playerChill._addedCall = false; - playerChill.playAnimation("idle"); - gfChill.playAnimation("idle"); + playerChill.playAnimation("idle", true, false, true); + gfChill.playAnimation("idle", true, false, true); } }); pressedSelect = false; @@ -645,20 +641,23 @@ class CharSelectSubState extends MusicBeatSubState nametag.switchChar(value); playerChill.visible = false; playerChillOut.visible = true; - playerChillOut.anim.goToFrameLabel("slideout"); + playerChillOut.playAnimation("slideout"); + var index = playerChillOut.anim.getFrameLabel("slideout").index; playerChillOut.onAnimationFrame.add((_, frame:Int) -> { - if (frame == playerChillOut.anim.getFrameLabel("slideout").index + 1) + if (frame == index + 1) { playerChill.visible = true; playerChill.switchChar(value); gfChill.switchGF(value); } - if (frame == playerChillOut.anim.getFrameLabel("slideout").index + 2) + if (frame == index + 2) { playerChillOut.switchChar(value); playerChillOut.visible = false; + playerChillOut.onAnimationFrame.removeAll(); } }); + return value; } diff --git a/source/funkin/ui/freeplay/AlbumRoll.hx b/source/funkin/ui/freeplay/AlbumRoll.hx index 36dba0054..64b86120c 100644 --- a/source/funkin/ui/freeplay/AlbumRoll.hx +++ b/source/funkin/ui/freeplay/AlbumRoll.hx @@ -60,7 +60,7 @@ class AlbumRoll extends FlxSpriteGroup { super(); - newAlbumArt = new FlxAtlasSprite(640, 350, Paths.animateAtlas("freeplay/albumRoll/freeplayAlbum")); + newAlbumArt = new FlxAtlasSprite(640, 360, Paths.animateAtlas("freeplay/albumRoll/freeplayAlbum")); newAlbumArt.visible = false; newAlbumArt.onAnimationComplete.add(onAlbumFinish); @@ -79,7 +79,7 @@ class AlbumRoll extends FlxSpriteGroup // Play the idle animation for the current album. if (animName != "idle") { - // newAlbumArt.playAnimation('idle', true); + newAlbumArt.playAnimation('idle', true); } } diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 63767d28e..d30bb3e8c 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -643,6 +643,9 @@ class FreeplayState extends MusicBeatSubState // when boyfriend hits dat shiii albumRoll.playIntro(); + var daSong = grpCapsules.members[curSelected].songData; + albumRoll.albumId = daSong?.albumId; + FlxTween.tween(grpDifficulties, {x: 90}, 0.6, {ease: FlxEase.quartOut}); From 469ff6690f93ebb93fa1c4f11b9eef0520fba62b Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 28 Aug 2024 05:40:50 -0400 Subject: [PATCH 623/870] Fix a crash when skipping in the song before it started. --- 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 928f392e5..fa059f73a 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1979,7 +1979,7 @@ class PlayState extends MusicBeatSubState if (vocals == null) return; // Skip this if the music is paused (GameOver, Pause menu, start-of-song offset, etc.) - if (!FlxG.sound.music.playing) return; + if (!(FlxG.sound.music?.playing ?? false)) return; var timeToPlayAt:Float = Conductor.instance.songPosition - Conductor.instance.instrumentalOffset; FlxG.sound.music.pause(); vocals.pause(); From 382af3b4851c63839bca5eed672bf0c2d5a2ed1a Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 28 Aug 2024 05:42:14 -0400 Subject: [PATCH 624/870] Reimplement ghost tapping (disabled via compile define) --- source/funkin/play/PlayState.hx | 16 +++---- source/funkin/play/notes/Strumline.hx | 65 ++++++++++++++++++++++++--- source/funkin/util/Constants.hx | 10 +++-- 3 files changed, 71 insertions(+), 20 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index fa059f73a..b3beba4e2 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -2323,7 +2323,11 @@ class PlayState extends MusicBeatSubState var notesInDirection:Array = notesByDirection[input.noteDirection]; - if (!Constants.GHOST_TAPPING && notesInDirection.length == 0) + #if FEATURE_GHOST_TAPPING + if ((!playerStrumline.mayGhostTap()) && notesInDirection.length == 0) + #else + if (notesInDirection.length == 0) + #end { // Pressed a wrong key with no notes nearby. // Perform a ghost miss (anti-spam). @@ -2333,16 +2337,6 @@ class PlayState extends MusicBeatSubState playerStrumline.playPress(input.noteDirection); trace('PENALTY Score: ${songScore}'); } - else if (Constants.GHOST_TAPPING && (!playerStrumline.mayGhostTap()) && notesInDirection.length == 0) - { - // 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. diff --git a/source/funkin/play/notes/Strumline.hx b/source/funkin/play/notes/Strumline.hx index 1e5782ad2..e894f9c62 100644 --- a/source/funkin/play/notes/Strumline.hx +++ b/source/funkin/play/notes/Strumline.hx @@ -94,6 +94,10 @@ class Strumline extends FlxSpriteGroup final noteStyle:NoteStyle; + #if FEATURE_GHOST_TAPPING + var ghostTapTimer:Float = 0.0; + #end + /** * The note data for the song. Should NOT be altered after the song starts, * so we can easily rewind. @@ -179,21 +183,36 @@ class Strumline extends FlxSpriteGroup super.update(elapsed); updateNotes(); + + #if FEATURE_GHOST_TAPPING + updateGhostTapTimer(elapsed); + #end } + #if FEATURE_GHOST_TAPPING /** * 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. + // Any notes in range of the strumline. + if (getNotesMayHit().length > 0) + { + return false; + } + // Any hold notes in range of the strumline. + if (getHoldNotesHitOrMissed().length > 0) + { + return false; + } - // 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; + // Note has been hit recently. + if (ghostTapTimer > 0.0) return false; + + // **yippee** + return true; } + #end /** * Return notes that are within `Constants.HIT_WINDOW` ms of the strumline. @@ -492,6 +511,32 @@ class Strumline extends FlxSpriteGroup } } + /** + * Return notes that are within, or way after, `Constants.HIT_WINDOW` ms of the strumline. + * @return An array of `NoteSprite` objects. + */ + public function getNotesOnScreen():Array + { + return notes.members.filter(function(note:NoteSprite) { + return note != null && note.alive && !note.hasBeenHit; + }); + } + + #if FEATURE_GHOST_TAPPING + function updateGhostTapTimer(elapsed:Float):Void + { + // If it's still our turn, don't update the ghost tap timer. + if (getNotesOnScreen().length > 0) return; + + ghostTapTimer -= elapsed; + + if (ghostTapTimer <= 0) + { + ghostTapTimer = 0; + } + } + #end + /** * Called when the PlayState skips a large amount of time forward or backward. */ @@ -563,6 +608,10 @@ class Strumline extends FlxSpriteGroup playStatic(dir); } resetScrollSpeed(); + + #if FEATURE_GHOST_TAPPING + ghostTapTimer = 0; + #end } public function applyNoteData(data:Array):Void @@ -602,6 +651,10 @@ class Strumline extends FlxSpriteGroup note.holdNoteSprite.sustainLength = (note.holdNoteSprite.strumTime + note.holdNoteSprite.fullSustainLength) - conductorInUse.songPosition; } + + #if FEATURE_GHOST_TAPPING + ghostTapTimer = Constants.GHOST_TAP_DELAY; + #end } public function killNote(note:NoteSprite):Void diff --git a/source/funkin/util/Constants.hx b/source/funkin/util/Constants.hx index 80318f1a4..fa03b229d 100644 --- a/source/funkin/util/Constants.hx +++ b/source/funkin/util/Constants.hx @@ -524,12 +524,16 @@ class Constants * OTHER */ // ============================== + #if FEATURE_GHOST_TAPPING + // Hey there, Eric here. + // This feature is currently still in development. You can test it out by creating a special debug build! + // lime build windows -DFEATURE_GHOST_TAPPING /** - * If true, the player will not receive the ghost miss penalty if there are no notes within the hit window. - * This is the thing people have been begging for forever lolol. + * Duration, in seconds, after the player's section ends before the player can spam without penalty. */ - public static final GHOST_TAPPING:Bool = false; + public static final GHOST_TAP_DELAY:Float = 3 / 8; + #end /** * The maximum number of previous file paths for the Chart Editor to remember. From b0f04779dc49a5a9e9dd40d194e57e82efa5f8d9 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 28 Aug 2024 05:43:01 -0400 Subject: [PATCH 625/870] Fix to Spooky icon in Freeplay menu --- source/funkin/play/character/CharacterData.hx | 2 ++ source/funkin/ui/PixelatedIcon.hx | 28 +++++++++++++------ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/source/funkin/play/character/CharacterData.hx b/source/funkin/play/character/CharacterData.hx index d447eb97f..bac2c7141 100644 --- a/source/funkin/play/character/CharacterData.hx +++ b/source/funkin/play/character/CharacterData.hx @@ -305,6 +305,8 @@ class CharacterDataParser icon = "darnell"; case "senpai-angry": icon = "senpai"; + case "spooky-dark": + icon = "spooky"; case "tankman-atlas": icon = "tankman"; } diff --git a/source/funkin/ui/PixelatedIcon.hx b/source/funkin/ui/PixelatedIcon.hx index 8d9b97d9c..d1ea652c3 100644 --- a/source/funkin/ui/PixelatedIcon.hx +++ b/source/funkin/ui/PixelatedIcon.hx @@ -22,14 +22,26 @@ class PixelatedIcon extends FlxSprite switch (char) { - case 'monster-christmas': - charPath += 'monsterpixel'; - case 'mom-car': - charPath += 'mommypixel'; - case 'darnell-blazin': - charPath += 'darnellpixel'; - case 'senpai-angry': - charPath += 'senpaipixel'; + case "bf-christmas" | "bf-car" | "bf-pixel" | "bf-holding-gf": + charPath += "bfpixel"; + case "monster-christmas": + charPath += "monsterpixel"; + case "mom" | "mom-car": + charPath += "mommypixel"; + case "pico-blazin" | "pico-playable" | "pico-speaker": + charPath += "picopixel"; + case "gf-christmas" | "gf-car" | "gf-pixel" | "gf-tankmen": + charPath += "gfpixel"; + case "dad": + charPath += "dadpixel"; + case "darnell-blazin": + charPath += "darnellpixel"; + case "senpai-angry": + charPath += "senpaipixel"; + case "spooky-dark": + charPath += "spookypixel"; + case "tankman-atlas": + charPath += "tankmanpixel"; default: charPath += '${char}pixel'; } From af93da6cd4d6ebd414ed196448c5549264e7d932 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 28 Aug 2024 05:43:23 -0400 Subject: [PATCH 626/870] Fixes to Chart Editor toolboxes --- source/funkin/play/event/ZoomCameraSongEvent.hx | 2 +- .../debug/charting/toolboxes/ChartEditorEventDataToolbox.hx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/funkin/play/event/ZoomCameraSongEvent.hx b/source/funkin/play/event/ZoomCameraSongEvent.hx index 748abda19..ee2eea8ad 100644 --- a/source/funkin/play/event/ZoomCameraSongEvent.hx +++ b/source/funkin/play/event/ZoomCameraSongEvent.hx @@ -114,7 +114,7 @@ class ZoomCameraSongEvent extends SongEvent name: 'zoom', title: 'Zoom Level', defaultValue: 1.0, - step: 0.1, + step: 0.05, type: SongEventFieldType.FLOAT, units: 'x' }, diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorEventDataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorEventDataToolbox.hx index 8f021840a..70580300e 100644 --- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorEventDataToolbox.hx +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorEventDataToolbox.hx @@ -190,8 +190,8 @@ class ChartEditorEventDataToolbox extends ChartEditorBaseToolbox var numberStepper:NumberStepper = new NumberStepper(); numberStepper.id = field.name; numberStepper.step = field.step ?? 1.0; - numberStepper.min = field.min ?? 0.0; - numberStepper.max = field.max ?? 10.0; + if (field.min != null) numberStepper.min = field.min; + if (field.min != null) numberStepper.max = field.max; if (field.defaultValue != null) numberStepper.value = field.defaultValue; input = numberStepper; case FLOAT: From ccabded2cc5a2c81666b827148388c5bafc46f82 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 28 Aug 2024 05:43:41 -0400 Subject: [PATCH 627/870] Fix warning related to bad asset caching for judgements. --- source/funkin/ui/transition/LoadingState.hx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/source/funkin/ui/transition/LoadingState.hx b/source/funkin/ui/transition/LoadingState.hx index 067de0e7f..5b82cc741 100644 --- a/source/funkin/ui/transition/LoadingState.hx +++ b/source/funkin/ui/transition/LoadingState.hx @@ -314,25 +314,28 @@ class LoadingState extends MusicBeatSubState FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num7')); FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num8')); FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/num9')); + FunkinSprite.cacheTexture(Paths.image('notes', 'shared')); FunkinSprite.cacheTexture(Paths.image('noteSplashes', 'shared')); FunkinSprite.cacheTexture(Paths.image('noteStrumline', 'shared')); FunkinSprite.cacheTexture(Paths.image('NOTE_hold_assets')); + FunkinSprite.cacheTexture(Paths.image('ui/countdown/funkin/ready', 'shared')); FunkinSprite.cacheTexture(Paths.image('ui/countdown/funkin/set', 'shared')); FunkinSprite.cacheTexture(Paths.image('ui/countdown/funkin/go', 'shared')); FunkinSprite.cacheTexture(Paths.image('ui/countdown/pixel/ready', 'shared')); FunkinSprite.cacheTexture(Paths.image('ui/countdown/pixel/set', 'shared')); FunkinSprite.cacheTexture(Paths.image('ui/countdown/pixel/go', 'shared')); - FunkinSprite.cacheTexture(Paths.image('ui/popup/normal/sick')); - FunkinSprite.cacheTexture(Paths.image('ui/popup/normal/good')); - FunkinSprite.cacheTexture(Paths.image('ui/popup/normal/bad')); - FunkinSprite.cacheTexture(Paths.image('ui/popup/normal/shit')); + + FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/sick')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/good')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/bad')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/funkin/shit')); + FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/sick')); FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/good')); FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/bad')); FunkinSprite.cacheTexture(Paths.image('ui/popup/pixel/shit')); - FunkinSprite.cacheTexture(Paths.image('miss', 'shared')); // TODO: remove this // List all image assets in the level's library. // This is crude and I want to remove it when we have a proper asset caching system. From 89402f8bb839827f7cf6322c320d92aea9f57f99 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 28 Aug 2024 05:47:34 -0400 Subject: [PATCH 628/870] Fix a bug where Bot Play could miss (via lag or the player mashing) and lose the song. --- source/funkin/play/PlayState.hx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index b3beba4e2..f4b177763 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -2221,10 +2221,14 @@ class PlayState extends MusicBeatSubState // Calling event.cancelEvent() skips all the other logic! Neat! if (event.eventCanceled) continue; + // Skip handling the miss in botplay! + if (!isBotPlayMode) + { // Judge the miss. // NOTE: This is what handles the scoring. trace('Missed note! ${note.noteData}'); onNoteMiss(note, event.playSound, event.healthChange); + } note.handledMiss = true; } @@ -2321,6 +2325,9 @@ class PlayState extends MusicBeatSubState playerStrumline.pressKey(input.noteDirection); + // Don't credit or penalize inputs in Bot Play. + if (isBotPlayMode) continue; + var notesInDirection:Array = notesByDirection[input.noteDirection]; #if FEATURE_GHOST_TAPPING From 152820f2e1961684ed8607cbcb5c4ab8773c2ce3 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 28 Aug 2024 06:03:12 -0400 Subject: [PATCH 629/870] Fix some warnings with props in StoryMenu --- source/funkin/ui/story/LevelProp.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/ui/story/LevelProp.hx b/source/funkin/ui/story/LevelProp.hx index 4e78415e3..dfb11dd20 100644 --- a/source/funkin/ui/story/LevelProp.hx +++ b/source/funkin/ui/story/LevelProp.hx @@ -16,7 +16,7 @@ class LevelProp extends Bopper this.propData = value; this.visible = this.propData != null; - danceEvery = this.propData?.danceEvery ?? 0.0; + danceEvery = this.propData?.danceEvery ?? 1.0; applyData(); } @@ -32,7 +32,7 @@ class LevelProp extends Bopper public function playConfirm():Void { - playAnimation('confirm', true, true); + if (hasAnimation('confirm')) playAnimation('confirm', true, true); } function applyData():Void From 570e672296d02522399e249c5c8509f966db4cca Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 28 Aug 2024 06:03:26 -0400 Subject: [PATCH 630/870] Fix magenta flicker on the main menu. --- source/funkin/ui/mainmenu/MainMenuState.hx | 36 ++++++++++++++-------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index 2d809354a..c426fd048 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -98,14 +98,7 @@ class MainMenuState extends MusicBeatState add(menuItems); menuItems.onChange.add(onMenuItemChange); menuItems.onAcceptPress.add(function(_) { - if (_.name == 'freeplay') - { - magenta.visible = true; - } - else - { - FlxFlicker.flicker(magenta, 1.1, 0.15, false, true); - } + FlxFlicker.flicker(magenta, 1.1, 0.15, false, true); }); menuItems.enabled = true; // can move on intro @@ -117,10 +110,7 @@ class MainMenuState extends MusicBeatState FlxTransitionableState.skipNextTransIn = true; FlxTransitionableState.skipNextTransOut = true; - openSubState(new FreeplayState( - { - character: FlxG.keys.pressed.SHIFT ? 'pico' : 'bf', - })); + openSubState(new FreeplayState()); }); #if CAN_OPEN_LINKS @@ -375,6 +365,28 @@ class MainMenuState extends MusicBeatState }); } + if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.L) + { + // Give the user a score of 0 points on Weekend 1 story mode. + // This makes the level count as uncleared and no longer displays the songs in Freeplay. + funkin.save.Save.instance.setLevelScore('weekend1', 'easy', + { + score: 1, + tallies: + { + sick: 0, + good: 0, + bad: 0, + shit: 0, + missed: 0, + combo: 0, + maxCombo: 0, + totalNotesHit: 0, + totalNotes: 0, + } + }); + } + if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.R) { // Give the user a hypothetical overridden score, From 2e7eabc4947ae53752b06b4341723fa4e3fdb404 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 28 Aug 2024 06:05:28 -0400 Subject: [PATCH 631/870] Remember character ID between visits to Freeplay, plus some fixes to prevent spamming keys --- source/funkin/ui/freeplay/FreeplayState.hx | 43 +++++++++++++++------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index cffb0b5a4..f04fd8ff6 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -177,9 +177,22 @@ class FreeplayState extends MusicBeatSubState var stickerSubState:Null = null; - public static var rememberedDifficulty:Null = Constants.DEFAULT_DIFFICULTY; + /** + * The difficulty we were on when this menu was last accessed. + */ + public static var rememberedDifficulty:String = Constants.DEFAULT_DIFFICULTY; + + /** + * The song we were on when this menu was last accessed. + * NOTE: `null` if the last song was `Random`. + */ public static var rememberedSongId:Null = 'tutorial'; + /** + * The character we were on when this menu was last accessed. + */ + public static var rememberedCharacterId:String = Constants.DEFAULT_CHARACTER; + var funnyCam:FunkinCamera; var rankCamera:FunkinCamera; var rankBg:FunkinSprite; @@ -209,14 +222,16 @@ class FreeplayState extends MusicBeatSubState public function new(?params:FreeplayStateParams, ?stickers:StickerSubState) { - currentCharacterId = params?.character ?? Constants.DEFAULT_CHARACTER; + currentCharacterId = params?.character ?? rememberedCharacterId; var fetchPlayableCharacter = function():PlayableCharacter { - var result = PlayerRegistry.instance.fetchEntry(params?.character ?? Constants.DEFAULT_CHARACTER); + var result = PlayerRegistry.instance.fetchEntry(params?.character ?? rememberedCharacterId); if (result == null) throw 'No valid playable character with id ${params?.character}'; return result; }; currentCharacter = fetchPlayableCharacter(); + rememberedCharacterId = currentCharacter?.id ?? Constants.DEFAULT_CHARACTER; + fromResultsParams = params?.fromResults; if (fromResultsParams?.playRankAnim == true) @@ -743,10 +758,7 @@ class FreeplayState extends MusicBeatSubState var tempSongs:Array> = songs; // Remember just the difficulty because it's important for song sorting. - if (rememberedDifficulty != null) - { - currentDifficulty = rememberedDifficulty; - } + currentDifficulty = rememberedDifficulty; if (filterStuff != null) tempSongs = sortSongs(tempSongs, filterStuff); @@ -1190,7 +1202,7 @@ class FreeplayState extends MusicBeatSubState /** * If true, disable interaction with the interface. */ - var busy:Bool = false; + public var busy:Bool = false; var originalPos:FlxPoint = new FlxPoint(); @@ -1326,6 +1338,8 @@ class FreeplayState extends MusicBeatSubState } handleInputs(elapsed); + + if (dj != null) FlxG.watch.addQuick('dj-anim', dj.getCurrentAnimation()); } function handleInputs(elapsed:Float):Void @@ -1483,7 +1497,7 @@ class FreeplayState extends MusicBeatSubState generateSongList(currentFilter, true); } - if (controls.BACK) + if (controls.BACK && !busy) { busy = true; FlxTween.globalManager.clear(); @@ -1891,7 +1905,7 @@ class FreeplayState extends MusicBeatSubState intendedCompletion = 0.0; diffIdsCurrent = diffIdsTotal; rememberedSongId = null; - rememberedDifficulty = null; + rememberedDifficulty = Constants.DEFAULT_DIFFICULTY; albumRoll.albumId = null; } @@ -2000,10 +2014,13 @@ class DifficultySelector extends FlxSprite var controls:Controls; var whiteShader:PureColor; - public function new(x:Float, y:Float, flipped:Bool, controls:Controls) + var parent:FreeplayState; + + public function new(parent:FreeplayState, x:Float, y:Float, flipped:Bool, controls:Controls) { super(x, y); + this.parent = parent; this.controls = controls; frames = Paths.getSparrowAtlas('freeplay/freeplaySelector'); @@ -2019,8 +2036,8 @@ class DifficultySelector extends FlxSprite override function update(elapsed:Float):Void { - if (flipX && controls.UI_RIGHT_P) moveShitDown(); - if (!flipX && controls.UI_LEFT_P) moveShitDown(); + if (flipX && controls.UI_RIGHT_P && !parent.busy) moveShitDown(); + if (!flipX && controls.UI_LEFT_P && !parent.busy) moveShitDown(); super.update(elapsed); } From 16a6dba9df36fecd81b879df2924db472042ba4c Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 28 Aug 2024 06:08:30 -0400 Subject: [PATCH 632/870] Pico Fist Pump animation (with loss animation) --- .../funkin/data/freeplay/player/PlayerData.hx | 75 +++++++++++++ source/funkin/play/stage/Bopper.hx | 2 +- source/funkin/ui/freeplay/FreeplayDJ.hx | 105 ++++++++++++++++-- source/funkin/ui/freeplay/FreeplayState.hx | 18 ++- 4 files changed, 183 insertions(+), 17 deletions(-) diff --git a/source/funkin/data/freeplay/player/PlayerData.hx b/source/funkin/data/freeplay/player/PlayerData.hx index f6c085018..de55fdf5f 100644 --- a/source/funkin/data/freeplay/player/PlayerData.hx +++ b/source/funkin/data/freeplay/player/PlayerData.hx @@ -38,6 +38,11 @@ class PlayerData @:optional public var freeplayDJ:Null = null; + + /** + * Data for displaying this character in the results screen. + */ + @:optional public var results:Null = null; /** @@ -97,6 +102,9 @@ class PlayerFreeplayDJData @:optional var cartoon:Null; + @:optional + var fistPump:Null; + public function new() { animationMap = new Map(); @@ -183,6 +191,46 @@ class PlayerFreeplayDJData { return cartoon?.channelChangeFrame ?? 60; } + + public function getFistPumpIntroStartFrame():Int + { + return fistPump?.introStartFrame ?? 0; + } + + public function getFistPumpIntroEndFrame():Int + { + return fistPump?.introEndFrame ?? 0; + } + + public function getFistPumpLoopStartFrame():Int + { + return fistPump?.loopStartFrame ?? 0; + } + + public function getFistPumpLoopEndFrame():Int + { + return fistPump?.loopEndFrame ?? 0; + } + + public function getFistPumpIntroBadStartFrame():Int + { + return fistPump?.introBadStartFrame ?? 0; + } + + public function getFistPumpIntroBadEndFrame():Int + { + return fistPump?.introBadEndFrame ?? 0; + } + + public function getFistPumpLoopBadStartFrame():Int + { + return fistPump?.loopBadStartFrame ?? 0; + } + + public function getFistPumpLoopBadEndFrame():Int + { + return fistPump?.loopBadEndFrame ?? 0; + } } typedef PlayerResultsData = @@ -242,3 +290,30 @@ typedef PlayerFreeplayDJCartoonData = var loopFrame:Int; var channelChangeFrame:Int; } + +typedef PlayerFreeplayDJFistPumpData = +{ + @:default(0) + var introStartFrame:Int; + + @:default(4) + var introEndFrame:Int; + + @:default(4) + var loopStartFrame:Int; + + @:default(-1) + var loopEndFrame:Int; + + @:default(0) + var introBadStartFrame:Int; + + @:default(4) + var introBadEndFrame:Int; + + @:default(4) + var loopBadStartFrame:Int; + + @:default(-1) + var loopBadEndFrame:Int; +}; diff --git a/source/funkin/play/stage/Bopper.hx b/source/funkin/play/stage/Bopper.hx index de19c51b4..96a217d31 100644 --- a/source/funkin/play/stage/Bopper.hx +++ b/source/funkin/play/stage/Bopper.hx @@ -315,7 +315,7 @@ class Bopper extends StageProp implements IPlayStateScriptedClass public function isAnimationFinished():Bool { - return this.animation.finished; + return this.animation?.finished ?? false; } public function setAnimationOffsets(name:String, xOffset:Float, yOffset:Float):Void diff --git a/source/funkin/ui/freeplay/FreeplayDJ.hx b/source/funkin/ui/freeplay/FreeplayDJ.hx index fd00a9549..6e2f83a63 100644 --- a/source/funkin/ui/freeplay/FreeplayDJ.hx +++ b/source/funkin/ui/freeplay/FreeplayDJ.hx @@ -116,13 +116,54 @@ class FreeplayDJ extends FlxAtlasSprite if (getCurrentAnimation() != animPrefix) playFlashAnimation(animPrefix, false); timeIdling = 0; case FistPumpIntro: - var animPrefix = playableCharData.getAnimationPrefix('fistPump'); - if (getCurrentAnimation() != animPrefix) playFlashAnimation('Boyfriend DJ fist pump', false); - if (getCurrentAnimation() == animPrefix && anim.curFrame >= 4) + var animPrefixA = playableCharData.getAnimationPrefix('fistPump'); + var animPrefixB = playableCharData.getAnimationPrefix('loss'); + + if (getCurrentAnimation() == animPrefixA) { - playAnimation("Boyfriend DJ fist pump", true, false, false, 0); + var endFrame = playableCharData.getFistPumpIntroEndFrame(); + if (endFrame > -1 && anim.curFrame >= endFrame) + { + playFlashAnimation(animPrefixA, true, false, false, playableCharData.getFistPumpIntroStartFrame()); + } } + else if (getCurrentAnimation() == animPrefixB) + { + var endFrame = playableCharData.getFistPumpIntroBadEndFrame(); + if (endFrame > -1 && anim.curFrame >= endFrame) + { + playFlashAnimation(animPrefixB, true, false, false, playableCharData.getFistPumpIntroBadStartFrame()); + } + } + else + { + FlxG.log.warn("Unrecognized animation in FistPumpIntro: " + getCurrentAnimation()); + } + case FistPump: + var animPrefixA = playableCharData.getAnimationPrefix('fistPump'); + var animPrefixB = playableCharData.getAnimationPrefix('loss'); + + if (getCurrentAnimation() == animPrefixA) + { + var endFrame = playableCharData.getFistPumpLoopEndFrame(); + if (endFrame > -1 && anim.curFrame >= endFrame) + { + playFlashAnimation(animPrefixA, true, false, false, playableCharData.getFistPumpLoopStartFrame()); + } + } + else if (getCurrentAnimation() == animPrefixB) + { + var endFrame = playableCharData.getFistPumpLoopBadEndFrame(); + if (endFrame > -1 && anim.curFrame >= endFrame) + { + playFlashAnimation(animPrefixB, true, false, false, playableCharData.getFistPumpLoopBadStartFrame()); + } + } + else + { + FlxG.log.warn("Unrecognized animation in FistPump: " + getCurrentAnimation()); + } case IdleEasterEgg: var animPrefix = playableCharData.getAnimationPrefix('idleEasterEgg'); @@ -271,7 +312,7 @@ class FreeplayDJ extends FlxAtlasSprite function loadCartoon() { cartoonSnd = FunkinSound.load(Paths.sound(getRandomFlashToon()), 1.0, false, true, true, function() { - playAnimation("Boyfriend DJ watchin tv OG", true, false, false, 60); + playFlashAnimation(playableCharData.getAnimationPrefix('cartoon'), true, false, false, 60); }); // Fade out music to 40% volume over 1 second. @@ -301,21 +342,32 @@ class FreeplayDJ extends FlxAtlasSprite currentState = Confirm; } - public function fistPump():Void + public function fistPumpIntro():Void { currentState = FistPumpIntro; + var animPrefix = playableCharData.getAnimationPrefix('fistPump'); + playFlashAnimation(animPrefix, true, false, false, playableCharData.getFistPumpIntroStartFrame()); } - public function pumpFist():Void + public function fistPump():Void { currentState = FistPump; - playAnimation("Boyfriend DJ fist pump", true, false, false, 4); + var animPrefix = playableCharData.getAnimationPrefix('fistPump'); + playFlashAnimation(animPrefix, true, false, false, playableCharData.getFistPumpLoopStartFrame()); } - public function pumpFistBad():Void + public function fistPumpLossIntro():Void + { + currentState = FistPumpIntro; + var animPrefix = playableCharData.getAnimationPrefix('loss'); + playFlashAnimation(animPrefix, true, false, false, playableCharData.getFistPumpIntroBadStartFrame()); + } + + public function fistPumpLoss():Void { currentState = FistPump; - playAnimation("Boyfriend DJ loss reaction 1", true, false, false, 4); + var animPrefix = playableCharData.getAnimationPrefix('loss'); + playFlashAnimation(animPrefix, true, false, false, playableCharData.getFistPumpLoopBadStartFrame()); } override public function getCurrentAnimation():String @@ -366,12 +418,43 @@ class FreeplayDJ extends FlxAtlasSprite } } -enum DJBoyfriendState +enum FreeplayDJState { + /** + * Character enters the frame and transitions to Idle. + */ Intro; + + /** + * Character loops in idle. + */ Idle; + + /** + * Plays an easter egg animation after a period in Idle, then reverts to Idle. + */ + IdleEasterEgg; + + /** + * Plays an elaborate easter egg animation. Does not revert until another animation is triggered. + */ + Cartoon; + + /** + * Player has selected a song. + */ Confirm; + + /** + * Character preps to play the fist pump animation; plays after the Results screen. + * The actual frame label that gets played may vary based on the player's success. + */ FistPumpIntro; + + /** + * Character plays the fist pump animation. + * The actual frame label that gets played may vary based on the player's success. + */ FistPump; IdleEasterEgg; Cartoon; diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index f04fd8ff6..6d612b7fc 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -644,8 +644,8 @@ class FreeplayState extends MusicBeatSubState speed: 0.3 }); - var diffSelLeft:DifficultySelector = new DifficultySelector(20, grpDifficulties.y - 10, false, controls); - var diffSelRight:DifficultySelector = new DifficultySelector(325, grpDifficulties.y - 10, true, controls); + var diffSelLeft:DifficultySelector = new DifficultySelector(this, 20, grpDifficulties.y - 10, false, controls); + var diffSelRight:DifficultySelector = new DifficultySelector(this, 325, grpDifficulties.y - 10, true, controls); diffSelLeft.visible = false; diffSelRight.visible = false; add(diffSelLeft); @@ -913,7 +913,15 @@ class FreeplayState extends MusicBeatSubState changeSelection(); changeDiff(); - if (dj != null) dj.fistPump(); + if (fromResultsParams?.newRank == SHIT) + { + if (dj != null) dj.fistPumpLossIntro(); + } + else + { + if (dj != null) dj.fistPumpIntro(); + } + // rankCamera.fade(FlxColor.BLACK, 0.5, true); rankCamera.fade(0xFF000000, 0.5, true, null, true); if (FlxG.sound.music != null) FlxG.sound.music.volume = 0; @@ -1095,11 +1103,11 @@ class FreeplayState extends MusicBeatSubState if (fromResultsParams?.newRank == SHIT) { - if (dj != null) dj.pumpFistBad(); + if (dj != null) dj.fistPumpLoss(); } else { - if (dj != null) dj.pumpFist(); + if (dj != null) dj.fistPump(); } rankCamera.zoom = 0.8; From 7e39687994a85bb9c458e4eac7f5cac915527dc8 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 28 Aug 2024 06:09:14 -0400 Subject: [PATCH 633/870] Data driven char select grid positions --- .../funkin/data/freeplay/player/PlayerData.hx | 18 +++++++++++++ .../ui/charSelect/CharSelectSubState.hx | 25 +++++++++++++++++-- .../freeplay/charselect/PlayableCharacter.hx | 5 ++++ 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/source/funkin/data/freeplay/player/PlayerData.hx b/source/funkin/data/freeplay/player/PlayerData.hx index de55fdf5f..55657ba46 100644 --- a/source/funkin/data/freeplay/player/PlayerData.hx +++ b/source/funkin/data/freeplay/player/PlayerData.hx @@ -38,6 +38,12 @@ class PlayerData @:optional public var freeplayDJ:Null = null; + /** + * Data for displaying this character in the Character Select menu. + * If null, exclude from Character Select. + */ + @:optional + public var charSelect:Null = null; /** * Data for displaying this character in the results screen. @@ -233,6 +239,18 @@ class PlayerFreeplayDJData } } +class PlayerCharSelectData +{ + /** + * A zero-indexed number for the character's preferred position in the grid. + * 0 = top left, 4 = center, 8 = bottom right + * In the event of a conflict, the first character alphabetically gets it, + * and others get shifted over. + */ + @:optional + public var position:Null; +} + typedef PlayerResultsData = { var perfect:Array; diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index 8b1f050f5..4717c91ca 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -67,8 +67,29 @@ class CharSelectSubState extends MusicBeatSubState { super(); - availableChars.set(4, "bf"); - availableChars.set(3, "pico"); + loadAvailableCharacters(); + } + + function loadAvailableCharacters():Void + { + var playerIds:Array = PlayerRegistry.instance.listEntryIds(); + + for (playerId in playerIds) + { + var player:Null = PlayerRegistry.instance.fetchEntry(playerId); + if (player == null) continue; + var playerData = player.getCharSelectData(); + if (playerData == null) continue; + + var targetPosition:Int = playerData.position ?? 0; + while (availableChars.exists(targetPosition)) + { + targetPosition += 1; + } + + trace('Placing player ${playerId} at position ${targetPosition}'); + availableChars.set(targetPosition, playerId); + } } override public function create():Void diff --git a/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx b/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx index c46b4b930..d4dd7aaa4 100644 --- a/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx +++ b/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx @@ -88,6 +88,11 @@ class PlayableCharacter implements IRegistryEntry return _data.freeplayDJ.getFreeplayDJText(index); } + public function getCharSelectData():PlayerCharSelectData + { + return _data.charSelect; + } + /** * @param rank Which rank to get info for * @return An array of animations. For example, BF Great has two animations, one for BF and one for GF From 1fb5c31c2279a699654e33f7992db75b2a12ad64 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 28 Aug 2024 06:09:34 -0400 Subject: [PATCH 634/870] Don't apply global offset twice (NOTE: this may break Nene again!) --- source/funkin/play/stage/Stage.hx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/funkin/play/stage/Stage.hx b/source/funkin/play/stage/Stage.hx index c547b9f5f..c42e41cad 100644 --- a/source/funkin/play/stage/Stage.hx +++ b/source/funkin/play/stage/Stage.hx @@ -436,8 +436,9 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements // Start with the per-stage character position. // Subtracting the origin ensures characters are positioned relative to their feet. // Subtracting the global offset allows positioning on a per-character basis. - character.x = stageCharData.position[0] - character.characterOrigin.x + character.globalOffsets[0]; - character.y = stageCharData.position[1] - character.characterOrigin.y + character.globalOffsets[1]; + // We previously applied the global offset here but that is now done elsewhere. + character.x = stageCharData.position[0] - character.characterOrigin.x; + character.y = stageCharData.position[1] - character.characterOrigin.y; @:privateAccess(funkin.play.stage.Bopper) { From e7fca119f8e4ce7c795aa4729a5f0a5b89961aec Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 28 Aug 2024 06:11:01 -0400 Subject: [PATCH 635/870] Logic + animations for new unlocks --- .../data/freeplay/player/PlayerRegistry.hx | 35 ++++++++++ source/funkin/save/Save.hx | 57 +++++++++++++-- .../ui/charSelect/CharSelectSubState.hx | 1 - source/funkin/ui/freeplay/FreeplayDJ.hx | 69 +++++++++++++++++-- source/funkin/ui/freeplay/FreeplayState.hx | 27 +++++++- 5 files changed, 178 insertions(+), 11 deletions(-) diff --git a/source/funkin/data/freeplay/player/PlayerRegistry.hx b/source/funkin/data/freeplay/player/PlayerRegistry.hx index be8730ccd..62c05fc91 100644 --- a/source/funkin/data/freeplay/player/PlayerRegistry.hx +++ b/source/funkin/data/freeplay/player/PlayerRegistry.hx @@ -53,6 +53,41 @@ class PlayerRegistry extends BaseRegistry log('Loaded ${countEntries()} playable characters with ${ownedCharacterIds.size()} associations.'); } + public function countUnlockedCharacters():Int + { + var count = 0; + + for (charId in listEntryIds()) + { + var player = fetchEntry(charId); + if (player == null) continue; + + if (player.isUnlocked()) count++; + } + + return count; + } + + public function hasNewCharacter():Bool + { + var characters = Save.instance.charactersSeen.clone(); + + for (charId in listEntryIds()) + { + var player = fetchEntry(charId); + if (player == null) continue; + + if (!player.isUnlocked()) continue; + if (characters.contains(charId)) continue; + + // This character is unlocked but we haven't seen them in Freeplay yet. + return true; + } + + // Fallthrough case. + return false; + } + /** * Get the playable character associated with a given stage character. * @param characterId The stage character ID. diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx index 2900ce2be..a3d945594 100644 --- a/source/funkin/save/Save.hx +++ b/source/funkin/save/Save.hx @@ -121,6 +121,12 @@ class Save modOptions: [], }, + unlocks: + { + // Default to having seen the default character. + charactersSeen: ["bf"], + }, + optionsChartEditor: { // Reasonable defaults. @@ -393,6 +399,22 @@ class Save return data.optionsChartEditor.playbackSpeed; } + public var charactersSeen(get, never):Array; + + function get_charactersSeen():Array + { + return data.unlocks.charactersSeen; + } + + /** + * When we've seen a character unlock, add it to the list of characters seen. + * @param character + */ + public function addCharacterSeen(character:String):Void + { + data.unlocks.charactersSeen.push(character); + } + /** * Return the score the user achieved for a given level on a given difficulty. * @@ -471,10 +493,18 @@ class Save for (difficulty in difficultyList) { var score:Null = getLevelScore(levelId, difficulty); - // TODO: Do we need to check accuracy/score here? if (score != null) { - return true; + if (score.score > 0) + { + // Level has score data, which means we cleared it! + return true; + } + else + { + // Level has score data, but the score is 0. + return false; + } } } return false; @@ -630,10 +660,18 @@ class Save for (difficulty in difficultyList) { var score:Null = getSongScore(songId, difficulty); - // TODO: Do we need to check accuracy/score here? if (score != null) { - return true; + if (score.score > 0) + { + // Level has score data, which means we cleared it! + return true; + } + else + { + // Level has score data, but the score is 0. + return false; + } } } return false; @@ -956,6 +994,8 @@ typedef RawSaveData = */ var options:SaveDataOptions; + var unlocks:SaveDataUnlocks; + /** * The user's favorited songs in the Freeplay menu, * as a list of song IDs. @@ -980,6 +1020,15 @@ typedef SaveApiNewgroundsData = var sessionId:Null; } +typedef SaveDataUnlocks = +{ + /** + * Every time we see the unlock animation for a character, + * add it to this list so that we don't show it again. + */ + var charactersSeen:Array; +} + /** * An anoymous structure containing options about the user's high scores. */ diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index 4717c91ca..e6cb3fb77 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -290,7 +290,6 @@ class CharSelectSubState extends MusicBeatSubState } var grpIcons:FlxSpriteGroup; - var grpXSpread(default, set):Float = 107; var grpYSpread(default, set):Float = 127; diff --git a/source/funkin/ui/freeplay/FreeplayDJ.hx b/source/funkin/ui/freeplay/FreeplayDJ.hx index 6e2f83a63..21bd89f93 100644 --- a/source/funkin/ui/freeplay/FreeplayDJ.hx +++ b/source/funkin/ui/freeplay/FreeplayDJ.hx @@ -99,7 +99,7 @@ class FreeplayDJ extends FlxAtlasSprite playFlashAnimation(animPrefix, true, false, true); } - if (getCurrentAnimation() == animPrefix && this.isLoopFinished()) + if (getCurrentAnimation() == animPrefix && this.isLoopComplete()) { if (timeIdling >= IDLE_EGG_PERIOD && !seenIdleEasterEgg) { @@ -111,6 +111,16 @@ class FreeplayDJ extends FlxAtlasSprite } } timeIdling += elapsed; + case NewUnlock: + var animPrefix = playableCharData.getAnimationPrefix('newUnlock'); + if (!hasAnimation(animPrefix)) + { + currentState = Idle; + } + if (getCurrentAnimation() != animPrefix) + { + playFlashAnimation(animPrefix, true, false, true); + } case Confirm: var animPrefix = playableCharData.getAnimationPrefix('confirm'); if (getCurrentAnimation() != animPrefix) playFlashAnimation(animPrefix, false); @@ -226,7 +236,14 @@ class FreeplayDJ extends FlxAtlasSprite if (name == playableCharData.getAnimationPrefix('intro')) { - currentState = Idle; + if (PlayerRegistry.instance.hasNewCharacter()) + { + currentState = NewUnlock; + } + else + { + currentState = Idle; + } onIntroDone.dispatch(); } else if (name == playableCharData.getAnimationPrefix('idle')) @@ -266,9 +283,17 @@ class FreeplayDJ extends FlxAtlasSprite // runTvLogic(); } trace('Replay idle: ${frame}'); - playAnimation(playableCharData.getAnimationPrefix('cartoon'), true, false, false, frame); + playFlashAnimation(playableCharData.getAnimationPrefix('cartoon'), true, false, false, frame); // trace('Finished confirm'); } + else if (name == playableCharData.getAnimationPrefix('newUnlock')) + { + // Animation should loop. + } + else if (name == playableCharData.getAnimationPrefix('charSelect')) + { + onCharSelectComplete(); + } else { trace('Finished ${name}'); @@ -281,6 +306,15 @@ class FreeplayDJ extends FlxAtlasSprite seenIdleEasterEgg = false; } + /** + * Dynamic function, it's actually a variable you can reassign! + * `dj.onCharSelectComplete = function() {};` + */ + public dynamic function onCharSelectComplete():Void + { + trace('onCharSelectComplete()'); + } + var offsetX:Float = 0.0; var offsetY:Float = 0.0; @@ -342,6 +376,22 @@ class FreeplayDJ extends FlxAtlasSprite currentState = Confirm; } + public function toCharSelect():Void + { + if (hasAnimation('charSelect')) + { + currentState = CharSelect; + var animPrefix = playableCharData.getAnimationPrefix('charSelect'); + playFlashAnimation(animPrefix, true, false, false, 0); + } + else + { + currentState = Confirm; + // Call this immediately; otherwise, we get locked out of Character Select. + onCharSelectComplete(); + } + } + public function fistPumpIntro():Void { currentState = FistPumpIntro; @@ -456,6 +506,15 @@ enum FreeplayDJState * The actual frame label that gets played may vary based on the player's success. */ FistPump; - IdleEasterEgg; - Cartoon; + + /** + * Plays an animation to indicate that the player has a new unlock in Character Select. + * Overrides all idle animations as well as the fist pump. Only Confirm and CharSelect will override this. + */ + NewUnlock; + + /** + * Plays an animation to transition to the Character Select screen. + */ + CharSelect; } diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 6d612b7fc..79ca758c5 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1253,7 +1253,32 @@ class FreeplayState extends MusicBeatSubState if (controls.FREEPLAY_CHAR_SELECT && !busy) { - FlxG.switchState(new funkin.ui.charSelect.CharSelectSubState()); + // Check if we have ACCESS to character select! + trace('Is Pico unlocked? ${PlayerRegistry.instance.fetchEntry('pico')?.isUnlocked()}'); + trace('Number of characters: ${PlayerRegistry.instance.countUnlockedCharacters()}'); + + if (PlayerRegistry.instance.countUnlockedCharacters() > 1) + { + if (dj != null) + { + busy = true; + // Transition to character select after animation + dj.onCharSelectComplete = function() { + FlxG.switchState(new funkin.ui.charSelect.CharSelectSubState()); + } + dj.toCharSelect(); + } + else + { + // Transition to character select immediately + FlxG.switchState(new funkin.ui.charSelect.CharSelectSubState()); + } + } + else + { + trace('Not enough characters unlocked to open character select!'); + FunkinSound.playOnce(Paths.sound('cancelMenu')); + } } if (controls.FREEPLAY_FAVORITE && !busy) From 6cff1efc722be13a063ca69d6f36f7a95e5ef2b0 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 28 Aug 2024 06:45:18 -0400 Subject: [PATCH 636/870] Fix several compile errors, and update assets submodule. --- assets | 2 +- .../data/freeplay/player/PlayerRegistry.hx | 1 + .../ui/charSelect/CharSelectSubState.hx | 38 ++++++++++--------- source/funkin/ui/freeplay/FreeplayDJ.hx | 2 +- source/funkin/ui/mainmenu/MainMenuState.hx | 2 + 5 files changed, 26 insertions(+), 19 deletions(-) diff --git a/assets b/assets index 8573b2039..33c913793 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 8573b2039b9fb37551a41f5195aaa2abdc63770e +Subproject commit 33c91379353de42f2c11f1c7a9aebf66069ec13d diff --git a/source/funkin/data/freeplay/player/PlayerRegistry.hx b/source/funkin/data/freeplay/player/PlayerRegistry.hx index 62c05fc91..c0a15ed1c 100644 --- a/source/funkin/data/freeplay/player/PlayerRegistry.hx +++ b/source/funkin/data/freeplay/player/PlayerRegistry.hx @@ -3,6 +3,7 @@ package funkin.data.freeplay.player; import funkin.data.freeplay.player.PlayerData; import funkin.ui.freeplay.charselect.PlayableCharacter; import funkin.ui.freeplay.charselect.ScriptedPlayableCharacter; +import funkin.save.Save; class PlayerRegistry extends BaseRegistry { diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index e6cb3fb77..1374c64ef 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -1,27 +1,31 @@ package funkin.ui.charSelect; -import funkin.ui.freeplay.FreeplayState; -import flixel.text.FlxText; -import funkin.ui.PixelatedIcon; -import flixel.system.debug.watch.Tracker.TrackerProfile; -import flixel.math.FlxPoint; -import flixel.tweens.FlxTween; -import openfl.display.BlendMode; -import flixel.group.FlxGroup.FlxTypedGroup; +import flixel.FlxObject; import flixel.FlxSprite; +import flixel.group.FlxGroup; +import flixel.group.FlxGroup.FlxTypedGroup; import flixel.group.FlxSpriteGroup; -import funkin.play.stage.Stage; +import flixel.math.FlxPoint; +import flixel.sound.FlxSound; +import flixel.system.debug.watch.Tracker.TrackerProfile; +import flixel.text.FlxText; +import flixel.tweens.FlxEase; +import flixel.tweens.FlxTween; +import flixel.util.FlxTimer; +import funkin.audio.FunkinSound; +import funkin.data.freeplay.player.PlayerData; +import funkin.data.freeplay.player.PlayerRegistry; +import funkin.graphics.adobeanimate.FlxAtlasSprite; +import funkin.graphics.FunkinCamera; import funkin.modding.events.ScriptEvent; import funkin.modding.events.ScriptEventDispatcher; -import funkin.graphics.adobeanimate.FlxAtlasSprite; -import flixel.FlxObject; -import openfl.display.BlendMode; -import flixel.group.FlxGroup; +import funkin.play.stage.Stage; +import funkin.ui.freeplay.charselect.PlayableCharacter; +import funkin.ui.freeplay.FreeplayState; +import funkin.ui.PixelatedIcon; import funkin.util.MathUtil; -import flixel.util.FlxTimer; -import flixel.tweens.FlxEase; -import flixel.sound.FlxSound; -import funkin.audio.FunkinSound; +import funkin.vis.dsp.SpectralAnalyzer; +import openfl.display.BlendMode; class CharSelectSubState extends MusicBeatSubState { diff --git a/source/funkin/ui/freeplay/FreeplayDJ.hx b/source/funkin/ui/freeplay/FreeplayDJ.hx index 21bd89f93..b1528d906 100644 --- a/source/funkin/ui/freeplay/FreeplayDJ.hx +++ b/source/funkin/ui/freeplay/FreeplayDJ.hx @@ -15,7 +15,7 @@ class FreeplayDJ extends FlxAtlasSprite { // Represents the sprite's current status. // Without state machines I would have driven myself crazy years ago. - public var currentState:DJBoyfriendState = Intro; + public var currentState:FreeplayDJState = Intro; // A callback activated when the intro animation finishes. public var onIntroDone:FlxSignal = new FlxSignal(); diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index c426fd048..83da967b0 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -345,6 +345,7 @@ class MainMenuState extends MusicBeatState if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.W) { + FunkinSound.playOnce(Paths.sound('confirmMenu')); // Give the user a score of 1 point on Weekend 1 story mode. // This makes the level count as cleared and displays the songs in Freeplay. funkin.save.Save.instance.setLevelScore('weekend1', 'easy', @@ -367,6 +368,7 @@ class MainMenuState extends MusicBeatState if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.L) { + FunkinSound.playOnce(Paths.sound('confirmMenu')); // Give the user a score of 0 points on Weekend 1 story mode. // This makes the level count as uncleared and no longer displays the songs in Freeplay. funkin.save.Save.instance.setLevelScore('weekend1', 'easy', From 452747139eabd92115ea3823851926081011db3c Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 28 Aug 2024 09:41:58 -0400 Subject: [PATCH 637/870] Updated Pico and Erect charts, sent on August 27th --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 8573b2039..e19aaca19 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 8573b2039b9fb37551a41f5195aaa2abdc63770e +Subproject commit e19aaca19254ec2717a4f942005f32b42b6ecb18 From 5d590654f4b1931a7186371f18435adac6f9cf78 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 28 Aug 2024 16:32:41 -0400 Subject: [PATCH 638/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 33c913793..721056203 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 33c91379353de42f2c11f1c7a9aebf66069ec13d +Subproject commit 7210562035c7ab6d2122606ec607b3e897a5ef20 From 560badd6b502d1dea6c899c19bc428ad10540888 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 29 Aug 2024 06:59:10 -0400 Subject: [PATCH 639/870] File optimization and Expansion 2 album art --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 721056203..fda4eaaf3 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 7210562035c7ab6d2122606ec607b3e897a5ef20 +Subproject commit fda4eaaf3bab4e6ebcf66548517ee89de0438e3d From 0a316c815fac3897309eae10f13516599c52580e Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 29 Aug 2024 13:22:56 -0400 Subject: [PATCH 640/870] stop main menu music from playing when entering freeplay from pausemenu --- source/funkin/ui/freeplay/FreeplayState.hx | 14 +------------- source/funkin/ui/mainmenu/MainMenuState.hx | 2 +- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 79ca758c5..09d7fb7b8 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -317,15 +317,6 @@ class FreeplayState extends MusicBeatSubState isDebug = true; #end - if (prepForNewRank == false) - { - FunkinSound.playMusic('freakyMenu', - { - overrideExisting: true, - restartTrack: false - }); - } - // Add a null entry that represents the RANDOM option songs.push(null); @@ -2028,10 +2019,7 @@ class FreeplayState extends MusicBeatSubState public static function build(?params:FreeplayStateParams, ?stickers:StickerSubState):MusicBeatState { var result:MainMenuState; - if (params?.fromResults?.playRankAnim ?? false) result = new MainMenuState(true); - else - result = new MainMenuState(false); - + result = new MainMenuState(true); result.openSubState(new FreeplayState(params, stickers)); result.persistentUpdate = false; result.persistentDraw = true; diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index 83da967b0..c777e685b 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -64,7 +64,7 @@ class MainMenuState extends MusicBeatState transIn = FlxTransitionableState.defaultTransIn; transOut = FlxTransitionableState.defaultTransOut; - if (overrideMusic == false) playMenuMusic(); + if (!overrideMusic) 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; From 0392eddba649ec4842a91f508813355a70ddbf6b Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 29 Aug 2024 14:32:10 -0400 Subject: [PATCH 641/870] gf/nene char select mini optimization --- source/funkin/ui/charSelect/CharSelectGF.hx | 40 +++++++++++++-------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/source/funkin/ui/charSelect/CharSelectGF.hx b/source/funkin/ui/charSelect/CharSelectGF.hx index 6d8e3e657..ac8dafabc 100644 --- a/source/funkin/ui/charSelect/CharSelectGF.hx +++ b/source/funkin/ui/charSelect/CharSelectGF.hx @@ -21,6 +21,8 @@ class CharSelectGF extends FlxAtlasSprite var intendedYPos:Float = 0; var intendedAlpha:Float = 0; + var curGF:GFChar = GF; + public function new() { super(0, 0, Paths.animateAtlas("charSelect/gfChill")); @@ -28,7 +30,7 @@ class CharSelectGF extends FlxAtlasSprite switchGF("bf"); } - override public function update(elapsed:Float) + override public function update(elapsed:Float):Void { super.update(elapsed); @@ -63,7 +65,7 @@ class CharSelectGF extends FlxAtlasSprite * @param animInfo Should not be confused with animInInfo! * This is merely a local var for the function! */ - function doFade(animInfo:FramesJSFLInfo) + function doFade(animInfo:FramesJSFLInfo):Void { fadeTimer += FlxG.elapsed; if (fadeTimer >= 1 / 24) @@ -101,26 +103,30 @@ class CharSelectGF extends FlxAtlasSprite fadeAnimIndex = 0; } - public function switchGF(str:String) + /** + * For switching between "GFs" such as gf, nene, etc + * @param bf Which BF we are selecting, so that we know the accompyaning GF + */ + public function switchGF(bf:String):Void { - str = switch (str) + var prevGF:GFChar = curGF; + switch (bf) { case "pico": - "nene"; + curGF = NENE; case "bf": - "gf"; + curGF = GF; default: - "gf"; + curGF = GF; } - switch str - { - default: - loadAtlas(Paths.animateAtlas("charSelect/" + str + "Chill")); - } + // We don't need to update any anims if we didn't change GF + if (prevGF == curGF) return; - animInInfo = FramesJSFLParser.parse(Paths.file("images/charSelect/" + str + "AnimInfo/" + str + "In.txt")); - animOutInfo = FramesJSFLParser.parse(Paths.file("images/charSelect/" + str + "AnimInfo/" + str + "Out.txt")); + loadAtlas(Paths.animateAtlas("charSelect/" + curGF + "Chill")); + + animInInfo = FramesJSFLParser.parse(Paths.file("images/charSelect/" + curGF + "AnimInfo/" + curGF + "In.txt")); + animOutInfo = FramesJSFLParser.parse(Paths.file("images/charSelect/" + curGF + "AnimInfo/" + curGF + "Out.txt")); anim.play(""); playAnimation("idle", true, false, true); @@ -135,3 +141,9 @@ enum FadeStatus FADE_OUT; FADE_IN; } + +enum abstract GFChar(String) from String to String +{ + var GF = "gf"; + var NENE = "nene"; +} From 364a5d5a55229acee3246e54a7dbe7554e5123a3 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 29 Aug 2024 15:06:11 -0400 Subject: [PATCH 642/870] hmm flxanimate version fix --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index d67760882..b59a5d258 100644 --- a/hmm.json +++ b/hmm.json @@ -39,7 +39,7 @@ "name": "flxanimate", "type": "git", "dir": null, - "ref": "768740a56b26aa0c072720e0d1236b94afe68e3e", + "ref": "c3340af27d8e5bc11b42362d0ba33504bd2f3d35", "url": "https://github.com/Dot-Stuff/flxanimate" }, { From 737a679196bdffc7edc3f6d293523fbca091722d Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 29 Aug 2024 15:26:35 -0400 Subject: [PATCH 643/870] merge conflict fixins --- assets | 2 +- source/Main.hx | 2 +- source/funkin/ui/charSelect/CharSelectGF.hx | 3 +-- source/funkin/ui/charSelect/CharSelectSubState.hx | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/assets b/assets index 8558bc906..b7f132a4e 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 8558bc906ecd48ba5d7b1c213982f15b5d033227 +Subproject commit b7f132a4e6c528c2d55831f88a11781df0149fd5 diff --git a/source/Main.hx b/source/Main.hx index 475fa9234..2426fa0d9 100644 --- a/source/Main.hx +++ b/source/Main.hx @@ -26,7 +26,7 @@ class Main extends Sprite var framerate:Int = 60; // How many frames per second the game should run at. #else // TODO: This should probably be in the options menu? - var framerate:Int = 60; // How many frames per second the game should run at. + var framerate:Int = 144; // How many frames per second the game should run at. #end var skipSplash:Bool = true; // Whether to skip the flixel splash screen that appears in release mode. var startFullscreen:Bool = false; // Whether to start the game in fullscreen on desktop targets diff --git a/source/funkin/ui/charSelect/CharSelectGF.hx b/source/funkin/ui/charSelect/CharSelectGF.hx index 7122a8b90..2e0e3980c 100644 --- a/source/funkin/ui/charSelect/CharSelectGF.hx +++ b/source/funkin/ui/charSelect/CharSelectGF.hx @@ -22,7 +22,6 @@ class CharSelectGF extends FlxAtlasSprite var intendedYPos:Float = 0; var intendedAlpha:Float = 0; var list:Array = []; - var char:String = "gf"; var analyzer:SpectralAnalyzer; @@ -76,7 +75,7 @@ class CharSelectGF extends FlxAtlasSprite function drawFFT() { - if (char == "nene") + if (curGF == NENE) { var levels = analyzer.getLevels(); var frame = anim.curSymbol.timeline.get("VIZ_bars").get(anim.curFrame); diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index 832a56f99..c2850916a 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -309,7 +309,7 @@ class CharSelectSubState extends MusicBeatSubState var grpXSpread(default, set):Float = 107; var grpYSpread(default, set):Float = 127; - function initLocks() + function initLocks():Void { grpIcons = new FlxSpriteGroup(); add(grpIcons); From 3e339916d2d73120cce2b83a79c9178b79f42258 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 29 Aug 2024 18:11:51 -0400 Subject: [PATCH 644/870] flxanimate bump --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index f84af9f4f..3cd8d5d3d 100644 --- a/hmm.json +++ b/hmm.json @@ -46,7 +46,7 @@ "name": "flxanimate", "type": "git", "dir": null, - "ref": "c3340af27d8e5bc11b42362d0ba33504bd2f3d35", + "ref": "27a0a1f0afc1074f619991472fb3ee209aad28df", "url": "https://github.com/Dot-Stuff/flxanimate" }, { From ecd6100cf95b13e0b19b481356f8c9fe7ad9700e Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 29 Aug 2024 18:26:04 -0400 Subject: [PATCH 645/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index b7f132a4e..5a0c8da32 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit b7f132a4e6c528c2d55831f88a11781df0149fd5 +Subproject commit 5a0c8da32111571648b8fd07deabe2f78ae99eaa From a4f3c2cb84ed51b0185ae3bbf630f243c3d48600 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Fri, 30 Aug 2024 00:55:24 +0100 Subject: [PATCH 646/870] freeplay style code --- source/funkin/InitState.hx | 2 + .../data/freeplay/style/FreeplayStyleData.hx | 48 +++++++ .../freeplay/style/FreeplayStyleRegistry.hx | 84 ++++++++++++ source/funkin/ui/freeplay/FreeplayStyle.hx | 121 ++++++++++++++++++ .../ui/freeplay/ScriptedFreeplayStyle.hx | 9 ++ 5 files changed, 264 insertions(+) create mode 100644 source/funkin/data/freeplay/style/FreeplayStyleData.hx create mode 100644 source/funkin/data/freeplay/style/FreeplayStyleRegistry.hx create mode 100644 source/funkin/ui/freeplay/FreeplayStyle.hx create mode 100644 source/funkin/ui/freeplay/ScriptedFreeplayStyle.hx diff --git a/source/funkin/InitState.hx b/source/funkin/InitState.hx index e53499e3c..f8dc66b1b 100644 --- a/source/funkin/InitState.hx +++ b/source/funkin/InitState.hx @@ -19,6 +19,7 @@ import funkin.play.PlayStatePlaylist; import openfl.display.BitmapData; import funkin.data.story.level.LevelRegistry; import funkin.data.notestyle.NoteStyleRegistry; +import funkin.data.freeplay.style.FreeplayStyleRegistry; import funkin.data.event.SongEventRegistry; import funkin.data.stage.StageRegistry; import funkin.data.dialogue.conversation.ConversationRegistry; @@ -170,6 +171,7 @@ class InitState extends FlxState ConversationRegistry.instance.loadEntries(); DialogueBoxRegistry.instance.loadEntries(); SpeakerRegistry.instance.loadEntries(); + FreeplayStyleRegistry.instance.loadEntries(); AlbumRegistry.instance.loadEntries(); StageRegistry.instance.loadEntries(); diff --git a/source/funkin/data/freeplay/style/FreeplayStyleData.hx b/source/funkin/data/freeplay/style/FreeplayStyleData.hx new file mode 100644 index 000000000..1af198217 --- /dev/null +++ b/source/funkin/data/freeplay/style/FreeplayStyleData.hx @@ -0,0 +1,48 @@ +package funkin.data.freeplay.style; + +import funkin.data.animation.AnimationData; + +/** + * A type definition for the data for an album of songs. + * It includes things like what graphics to display in Freeplay. + * @see https://lib.haxe.org/p/json2object/ + */ +typedef FreeplayStyleData = +{ + /** + * Semantic version for style data. + */ + public var version:String; + + /** + * Asset key for the background image. + */ + public var bgAsset:String; + + /** + * Asset key for the difficulty selector image. + */ + public var selectorAsset:String; + + /** + * Asset key for the numbers shown at the top right of the screen. + */ + public var numbersAsset:String; + + /** + * Asset key for the freeplay capsules. + */ + public var capsuleAsset:String; + + /** + * Color data for the capsule text outline. + * the order of this array goes as follows: [DESELECTED, SELECTED] + */ + public var capsuleTextColors:Array; + + /** + * Delay time after confirming a song selection, before entering PlayState. + * Useful for letting longer animations play out. + */ + public var startDelay:Float; +} diff --git a/source/funkin/data/freeplay/style/FreeplayStyleRegistry.hx b/source/funkin/data/freeplay/style/FreeplayStyleRegistry.hx new file mode 100644 index 000000000..626e2ac39 --- /dev/null +++ b/source/funkin/data/freeplay/style/FreeplayStyleRegistry.hx @@ -0,0 +1,84 @@ +package funkin.data.freeplay.style; + +import funkin.ui.freeplay.FreeplayStyle; +import funkin.data.freeplay.style.FreeplayStyleData; +import funkin.ui.freeplay.ScriptedFreeplayStyle; + +class FreeplayStyleRegistry extends BaseRegistry +{ + /** + * The current version string for the style data format. + * Handle breaking changes by incrementing this value + * and adding migration to the `migrateStyleData()` function. + */ + public static final FREEPLAYSTYLE_DATA_VERSION:thx.semver.Version = '1.0.0'; + + public static final FREEPLAYSTYLE_DATA_VERSION_RULE:thx.semver.VersionRule = '1.0.x'; + + public static final instance:FreeplayStyleRegistry = new FreeplayStyleRegistry(); + + public function new() + { + super('FREEPLAYSTYLE', 'ui/freeplay/styles', FREEPLAYSTYLE_DATA_VERSION_RULE); + } + + /** + * Read, parse, and validate the JSON data and produce the corresponding data object. + * @param id The ID of the entry to load. + * @return The parsed data object. + */ + public function parseEntryData(id:String):Null + { + // JsonParser does not take type parameters, + // otherwise this function would be in BaseRegistry. + var parser:json2object.JsonParser = new json2object.JsonParser(); + parser.ignoreUnknownVariables = false; + + switch (loadEntryFile(id)) + { + case {fileName: fileName, contents: contents}: + parser.fromJson(contents, fileName); + default: + return null; + } + + if (parser.errors.length > 0) + { + printErrors(parser.errors, id); + return null; + } + return parser.value; + } + + /** + * Parse and validate the JSON data and produce the corresponding data object. + * + * NOTE: Must be implemented on the implementation class. + * @param contents The JSON as a string. + * @param fileName An optional file name for error reporting. + * @return The parsed data object. + */ + public function parseEntryDataRaw(contents:String, ?fileName:String):Null + { + var parser:json2object.JsonParser = new json2object.JsonParser(); + parser.ignoreUnknownVariables = false; + parser.fromJson(contents, fileName); + + if (parser.errors.length > 0) + { + printErrors(parser.errors, fileName); + return null; + } + return parser.value; + } + + function createScriptedEntry(clsName:String):FreeplayStyle + { + return ScriptedFreeplayStyle.init(clsName, 'unknown'); + } + + function getScriptedClassNames():Array + { + return ScriptedFreeplayStyle.listScriptClasses(); + } +} diff --git a/source/funkin/ui/freeplay/FreeplayStyle.hx b/source/funkin/ui/freeplay/FreeplayStyle.hx new file mode 100644 index 000000000..5ced51e1c --- /dev/null +++ b/source/funkin/ui/freeplay/FreeplayStyle.hx @@ -0,0 +1,121 @@ +package funkin.ui.freeplay; + +import funkin.data.freeplay.style.FreeplayStyleData; +import funkin.data.freeplay.style.FreeplayStyleRegistry; +import funkin.data.animation.AnimationData; +import funkin.data.IRegistryEntry; +import flixel.graphics.FlxGraphic; +import flixel.util.FlxColor; + +/** + * A class representing the data for a style of the Freeplay menu. + */ +class FreeplayStyle implements IRegistryEntry +{ + /** + * The internal ID for this freeplay style. + */ + public final id:String; + + /** + * The full data for a freeplay style. + */ + public final _data:FreeplayStyleData; + + public function new(id:String) + { + this.id = id; + this._data = _fetchData(id); + + if (_data == null) + { + throw 'Could not parse album data for id: $id'; + } + } + + /** + * Get the background art as a graphic, ready to apply to a sprite. + * @return The built graphic + */ + public function getBgAssetGraphic():FlxGraphic + { + return FlxG.bitmap.add(Paths.image(getBgAssetKey())); + } + + /** + * Get the asset key for the background. + * @return The asset key + */ + public function getBgAssetKey():String + { + return _data.bgAsset; + } + + /** + * Get the asset key for the background. + * @return The asset key + */ + public function getSelectorAssetKey():String + { + return _data.selectorAsset; + } + + /** + * Get the asset key for the number assets. + * @return The asset key + */ + public function getCapsuleAssetKey():String + { + return _data.capsuleAsset; + } + + /** + * Get the asset key for the capsule art. + * @return The asset key + */ + public function getNumbersAssetKey():String + { + return _data.numbersAsset; + } + + /** + * Return the deselected color of the text outline + * for freeplay capsules. + * @return The deselected color + */ + public function getCapsuleDeselCol():FlxColor + { + return FlxColor.fromString(_data.capsuleTextColors[0]); + } + + /** + * Return the song selection transition delay. + * @return The start delay + */ + public function getStartDelay():Float + { + return _data.startDelay; + } + + public function toString():String + { + return 'Style($id)'; + } + + /** + * Return the selected color of the text outline + * for freeplay capsules. + * @return The selected color + */ + public function getCapsuleSelCol():FlxColor + { + return FlxColor.fromString(_data.capsuleTextColors[1]); + } + + public function destroy():Void {} + + static function _fetchData(id:String):Null + { + return FreeplayStyleRegistry.instance.parseEntryDataWithMigration(id, FreeplayStyleRegistry.instance.fetchEntryVersion(id)); + } +} diff --git a/source/funkin/ui/freeplay/ScriptedFreeplayStyle.hx b/source/funkin/ui/freeplay/ScriptedFreeplayStyle.hx new file mode 100644 index 000000000..b7013a6b2 --- /dev/null +++ b/source/funkin/ui/freeplay/ScriptedFreeplayStyle.hx @@ -0,0 +1,9 @@ +package funkin.ui.freeplay; + +/** + * A script that can be tied to a Freeplay style. + * Create a scripted class that extends FreeplayStyle to use this. + * This allows you to customize how a specific style works. + */ +@:hscriptClass +class ScriptedFreeplayStyle extends funkin.ui.freeplay.FreeplayStyle implements polymod.hscript.HScriptedClass {} From e7448cb8f7a804775f0d2af11f4c7ab5e7bca430 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Fri, 30 Aug 2024 00:58:19 +0100 Subject: [PATCH 647/870] style support --- source/funkin/ui/freeplay/CapsuleText.hx | 19 ++++++++++-- source/funkin/ui/freeplay/FreeplayScore.hx | 34 +++++++++++++++------- source/funkin/ui/freeplay/SongMenuItem.hx | 27 ++++++++++++----- 3 files changed, 59 insertions(+), 21 deletions(-) diff --git a/source/funkin/ui/freeplay/CapsuleText.hx b/source/funkin/ui/freeplay/CapsuleText.hx index c3bcdb09b..aae72544e 100644 --- a/source/funkin/ui/freeplay/CapsuleText.hx +++ b/source/funkin/ui/freeplay/CapsuleText.hx @@ -10,6 +10,7 @@ import flixel.tweens.FlxEase; import flixel.util.FlxTimer; import flixel.tweens.FlxTween; import openfl.display.BlendMode; +import flixel.util.FlxColor; class CapsuleText extends FlxSpriteGroup { @@ -25,6 +26,8 @@ class CapsuleText extends FlxSpriteGroup public var tooLong:Bool = false; + var glowColor:FlxColor = 0xFF00ccff; + // 255, 27 normal // 220, 27 favourited @@ -38,7 +41,7 @@ class CapsuleText extends FlxSpriteGroup // whiteText.shader = new GaussianBlurShader(0.3); text = songTitle; - blurredText.color = 0xFF00ccff; + blurredText.color = glowColor; whiteText.color = 0xFFFFFFFF; add(blurredText); add(whiteText); @@ -51,6 +54,16 @@ class CapsuleText extends FlxSpriteGroup return text; } + public function applyStyle(styleData:FreeplayStyle):Void + { + glowColor = styleData.getCapsuleSelCol(); + blurredText.color = glowColor; + whiteText.textField.filters = [ + new openfl.filters.GlowFilter(glowColor, 1, 5, 5, 210, BitmapFilterQuality.MEDIUM), + // new openfl.filters.BlurFilter(5, 5, BitmapFilterQuality.LOW) + ]; + } + // ???? none // 255, 27 normal // 220, 27 favourited @@ -99,7 +112,7 @@ class CapsuleText extends FlxSpriteGroup whiteText.text = value; checkClipWidth(); whiteText.textField.filters = [ - new openfl.filters.GlowFilter(0x00ccff, 1, 5, 5, 210, BitmapFilterQuality.MEDIUM), + new openfl.filters.GlowFilter(glowColor, 1, 5, 5, 210, BitmapFilterQuality.MEDIUM), // new openfl.filters.BlurFilter(5, 5, BitmapFilterQuality.LOW) ]; @@ -186,7 +199,7 @@ class CapsuleText extends FlxSpriteGroup } else { - blurredText.color = 0xFF00aadd; + blurredText.color = glowColor; whiteText.color = 0xFFDDDDDD; whiteText.textField.filters = [ new openfl.filters.GlowFilter(0xDDDDDD, 1, 5, 5, 210, BitmapFilterQuality.MEDIUM), diff --git a/source/funkin/ui/freeplay/FreeplayScore.hx b/source/funkin/ui/freeplay/FreeplayScore.hx index da4c9f5d4..fee55ce7c 100644 --- a/source/funkin/ui/freeplay/FreeplayScore.hx +++ b/source/funkin/ui/freeplay/FreeplayScore.hx @@ -42,13 +42,20 @@ class FreeplayScore extends FlxTypedSpriteGroup return val; } - public function new(x:Float, y:Float, digitCount:Int, scoreShit:Int = 100) + public function new(x:Float, y:Float, digitCount:Int, scoreShit:Int = 100, ?styleData:FreeplayStyle) { super(x, y); for (i in 0...digitCount) { - add(new ScoreNum(x + (45 * i), y, 0)); + if (styleData == null) + { + add(new ScoreNum(x + (45 * i), y, 0)); + } + else + { + add(new ScoreNum(x + (45 * i), y, 0, styleData)); + } } this.scoreShit = scoreShit; @@ -76,16 +83,16 @@ class ScoreNum extends FlxSprite case 1: offset.x -= 15; case 5: - // set offsets - // offset.x += 0; - // offset.y += 10; + // set offsets + // offset.x += 0; + // offset.y += 10; case 7: - // offset.y += 6; + // offset.y += 6; case 4: - // offset.y += 5; + // offset.y += 5; case 9: - // offset.y += 5; + // offset.y += 5; default: centerOffsets(false); } @@ -99,14 +106,21 @@ class ScoreNum extends FlxSprite var numToString:Array = ["ZERO", "ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE"]; - public function new(x:Float, y:Float, ?initDigit:Int = 0) + public function new(x:Float, y:Float, ?initDigit:Int = 0, ?styleData:FreeplayStyle) { super(x, y); baseY = y; baseX = x; - frames = Paths.getSparrowAtlas('digital_numbers'); + if (styleData == null) + { + frames = Paths.getSparrowAtlas('digital_numbers'); + } + else + { + frames = Paths.getSparrowAtlas(styleData.getNumbersAssetKey()); + } for (i in 0...10) { diff --git a/source/funkin/ui/freeplay/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx index b4409d377..11ca44d54 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -88,7 +88,7 @@ class SongMenuItem extends FlxSpriteGroup super(x, y); capsule = new FlxSprite(); - capsule.frames = Paths.getSparrowAtlas('freeplay/freeplayCapsule'); + capsule.frames = Paths.getSparrowAtlas('freeplay/freeplayCapsule/capsule/freeplayCapsule'); capsule.animation.addByPrefix('selected', 'mp3 capsule w backing0', 24); capsule.animation.addByPrefix('unselected', 'mp3 capsule w backing NOT SELECTED', 24); // capsule.animation @@ -500,12 +500,23 @@ class SongMenuItem extends FlxSpriteGroup updateSelected(); } - public function init(?x:Float, ?y:Float, songData:Null):Void + public function init(?x:Float, ?y:Float, songData:Null, ?styleData:FreeplayStyle = null):Void { if (x != null) this.x = x; if (y != null) this.y = y; this.songData = songData; + // im so mad i have to do this but im pretty sure with the capsules recycling i cant call the new function properly :/ + // if thats possible someone Please change the new function to be something like + // capsule.frames = Paths.getSparrowAtlas(styleData == null ? 'freeplay/freeplayCapsule/capsule/freeplayCapsule' : styleData.getCapsuleAssetKey()); thank u luv u + if (styleData != null) + { + capsule.frames = Paths.getSparrowAtlas(styleData.getCapsuleAssetKey()); + capsule.animation.addByPrefix('selected', 'mp3 capsule w backing0', 24); + capsule.animation.addByPrefix('unselected', 'mp3 capsule w backing NOT SELECTED', 24); + songText.applyStyle(styleData); + } + // Update capsule text. songText.text = songData?.songName ?? 'Random'; // Update capsule character. @@ -727,7 +738,7 @@ class FreeplayRank extends FlxSprite switch (val) { case SHIT: - // offset.x -= 1; + // offset.x -= 1; case GOOD: // offset.x -= 1; offset.y -= 8; @@ -735,11 +746,11 @@ class FreeplayRank extends FlxSprite // offset.x -= 1; offset.y -= 8; case EXCELLENT: - // offset.y += 5; + // offset.y += 5; case PERFECT: - // offset.y += 5; + // offset.y += 5; case PERFECT_GOLD: - // offset.y += 5; + // offset.y += 5; default: centerOffsets(false); this.visible = false; @@ -796,9 +807,9 @@ class CapsuleNumber extends FlxSprite case 6: case 4: - // offset.y += 5; + // offset.y += 5; case 9: - // offset.y += 5; + // offset.y += 5; default: centerOffsets(false); } From de03da7e6fef675c200554ed34903233c5440c8e Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Fri, 30 Aug 2024 01:02:32 +0100 Subject: [PATCH 648/870] backing card classes --- .../ui/freeplay/backcards/BackingCard.hx | 48 ++- .../ui/freeplay/backcards/BoyfriendCard.hx | 82 +++++- .../ui/freeplay/backcards/NewCharacterCard.hx | 278 ++++++++++++++++++ .../funkin/ui/freeplay/backcards/PicoCard.hx | 278 ++++++++++++++++-- 4 files changed, 653 insertions(+), 33 deletions(-) create mode 100644 source/funkin/ui/freeplay/backcards/NewCharacterCard.hx diff --git a/source/funkin/ui/freeplay/backcards/BackingCard.hx b/source/funkin/ui/freeplay/backcards/BackingCard.hx index 8a2a2c910..bb662cc8d 100644 --- a/source/funkin/ui/freeplay/backcards/BackingCard.hx +++ b/source/funkin/ui/freeplay/backcards/BackingCard.hx @@ -39,10 +39,14 @@ class BackingCard extends FlxSpriteGroup var _exitMovers:Null; var _exitMoversCharSel:Null; - public function new(currentCharacter:PlayableCharacter) + public var instance:FreeplayState; + + public function new(currentCharacter:PlayableCharacter, ?_instance:FreeplayState) { super(); + if (_instance != null) instance = _instance; + cardGlow = new FlxSprite(-30, -30).loadGraphic(Paths.image('freeplay/cardGlow')); confirmGlow = new FlxSprite(-30, 240).loadGraphic(Paths.image('freeplay/confirmGlow')); confirmTextGlow = new FlxSprite(-8, 115).loadGraphic(Paths.image('freeplay/glowingText')); @@ -115,6 +119,16 @@ class BackingCard extends FlxSpriteGroup }); } + /** + * Helper function to snap the back of the card to its final position. + * Used when returning from character select, as we dont want to play the full animation of everything sliding in. + */ + public function skipIntroTween():Void + { + FlxTween.cancelTweensOf(pinkBack); + pinkBack.x = 0; + } + /** * Called in create. Adds sprites and tweens. */ @@ -152,11 +166,6 @@ class BackingCard extends FlxSpriteGroup add(cardGlow); } - /** - * Override parts of Freeplay depending on the card class. - */ - public function applyStyle(_freeplayState:FreeplayState):Void {} - /** * Called after the dj finishes their start animation. */ @@ -181,10 +190,16 @@ class BackingCard extends FlxSpriteGroup confirmGlow.visible = true; confirmGlow2.visible = true; - backingTextYeah.playAnimation("BF back card confirm raw", false, false, false, 0); + backingTextYeah.anim.play(""); confirmGlow2.alpha = 0; confirmGlow.alpha = 0; + FlxTween.color(instance.bgDad, 0.5, 0xFFA8A8A8, 0xFF646464, + { + onUpdate: function(_) { + instance.angleMaskShader.extraColor = instance.bgDad.color; + } + }); FlxTween.tween(confirmGlow2, {alpha: 0.5}, 0.33, { ease: FlxEase.quadOut, @@ -195,12 +210,29 @@ class BackingCard extends FlxSpriteGroup confirmTextGlow.alpha = 1; FlxTween.tween(confirmTextGlow, {alpha: 0.4}, 0.5); FlxTween.tween(confirmGlow, {alpha: 0}, 0.5); + FlxTween.color(instance.bgDad, 2, 0xFFCDCDCD, 0xFF555555, + { + ease: FlxEase.expoOut, + onUpdate: function(_) { + instance.angleMaskShader.extraColor = instance.bgDad.color; + } + }); } }); } /** - * Called when exiting the freeplay menu + * Called when entering character select, does nothing by default. + */ + public function enterCharSel():Void {} + + /** + * Called on each beat in freeplay state. + */ + public function beatHit():Void {} + + /** + * Called when exiting the freeplay menu. */ public function disappear():Void { diff --git a/source/funkin/ui/freeplay/backcards/BoyfriendCard.hx b/source/funkin/ui/freeplay/backcards/BoyfriendCard.hx index 737a0a2dc..597fd1a34 100644 --- a/source/funkin/ui/freeplay/backcards/BoyfriendCard.hx +++ b/source/funkin/ui/freeplay/backcards/BoyfriendCard.hx @@ -22,9 +22,6 @@ import lime.utils.Assets; import openfl.display.BlendMode; import flixel.group.FlxSpriteGroup; -/** - * A class for the backing cards so they dont have to be part of freeplayState...... - */ class BoyfriendCard extends BackingCard { public var moreWays:BGScrollingText; @@ -34,6 +31,9 @@ class BoyfriendCard extends BackingCard public var moreWays2:BGScrollingText; public var funnyScroll3:BGScrollingText; + var glow:FlxSprite; + var glowDark:FlxSprite; + public override function applyExitMovers(?exitMovers:FreeplayState.ExitMoverData, ?exitMoversCharSel:FreeplayState.ExitMoverData):Void { super.applyExitMovers(exitMovers, exitMoversCharSel); @@ -79,6 +79,16 @@ class BoyfriendCard extends BackingCard }); } + public override function enterCharSel():Void + { + FlxTween.tween(funnyScroll, {speed: 0}, 0.8, {ease: FlxEase.sineIn}); + FlxTween.tween(funnyScroll2, {speed: 0}, 0.8, {ease: FlxEase.sineIn}); + FlxTween.tween(moreWays, {speed: 0}, 0.8, {ease: FlxEase.sineIn}); + FlxTween.tween(moreWays2, {speed: 0}, 0.8, {ease: FlxEase.sineIn}); + FlxTween.tween(txtNuts, {speed: 0}, 0.8, {ease: FlxEase.sineIn}); + FlxTween.tween(funnyScroll3, {speed: 0}, 0.8, {ease: FlxEase.sineIn}); + } + public override function new(currentCharacter:PlayableCharacter) { super(currentCharacter); @@ -93,10 +103,34 @@ class BoyfriendCard extends BackingCard public override function init():Void { - super.init(); + FlxTween.tween(pinkBack, {x: 0}, 0.6, {ease: FlxEase.quartOut}); + add(pinkBack); - // var grpTxtScrolls:FlxGroup = new FlxGroup(); - // add(grpTxtScrolls); + add(orangeBackShit); + + add(alsoOrangeLOL); + + FlxSpriteUtil.alphaMaskFlxSprite(orangeBackShit, pinkBack, orangeBackShit); + orangeBackShit.visible = false; + alsoOrangeLOL.visible = false; + + confirmTextGlow.blend = BlendMode.ADD; + confirmTextGlow.visible = false; + + confirmGlow.blend = BlendMode.ADD; + + confirmGlow.visible = false; + confirmGlow2.visible = false; + + add(confirmGlow2); + add(confirmGlow); + + add(confirmTextGlow); + + add(backingTextYeah); + + cardGlow.blend = BlendMode.ADD; + cardGlow.visible = false; moreWays.visible = false; funnyScroll.visible = false; @@ -127,6 +161,36 @@ class BoyfriendCard extends BackingCard funnyScroll3.funnyColor = 0xFFFEA400; funnyScroll3.speed = -3.8; add(funnyScroll3); + + glowDark = new FlxSprite(-300, 330).loadGraphic(Paths.image('freeplay/beatglow')); + glowDark.blend = BlendMode.MULTIPLY; + add(glowDark); + + glow = new FlxSprite(-300, 330).loadGraphic(Paths.image('freeplay/beatglow')); + glow.blend = BlendMode.ADD; + add(glow); + + glowDark.visible = false; + glow.visible = false; + + add(cardGlow); + } + + var beatFreq:Int = 1; + var beatFreqList:Array = [1,2,4,8]; + + public override function beatHit():Void { + // increases the amount of beats that need to go by to pulse the glow because itd flash like craazy at high bpms..... + beatFreq = beatFreqList[Math.floor(Conductor.instance.bpm/140)]; + + if(Conductor.instance.currentBeat % beatFreq != 0) return; + FlxTween.cancelTweensOf(glow); + FlxTween.cancelTweensOf(glowDark); + + glow.alpha = 0.8; + FlxTween.tween(glow, {alpha: 0}, 16/24, {ease: FlxEase.quartOut}); + glowDark.alpha = 0; + FlxTween.tween(glowDark, {alpha: 0.6}, 18/24, {ease: FlxEase.quartOut}); } public override function introDone():Void @@ -139,6 +203,8 @@ class BoyfriendCard extends BackingCard moreWays2.visible = true; funnyScroll3.visible = true; // grpTxtScrolls.visible = true; + glowDark.visible = true; + glow.visible = true; } public override function confirm():Void @@ -152,6 +218,8 @@ class BoyfriendCard extends BackingCard funnyScroll2.visible = false; moreWays2.visible = false; funnyScroll3.visible = false; + glowDark.visible = false; + glow.visible = false; } public override function disappear():Void @@ -164,5 +232,7 @@ class BoyfriendCard extends BackingCard funnyScroll2.visible = false; moreWays2.visible = false; funnyScroll3.visible = false; + glowDark.visible = false; + glow.visible = false; } } diff --git a/source/funkin/ui/freeplay/backcards/NewCharacterCard.hx b/source/funkin/ui/freeplay/backcards/NewCharacterCard.hx new file mode 100644 index 000000000..a44ff88a6 --- /dev/null +++ b/source/funkin/ui/freeplay/backcards/NewCharacterCard.hx @@ -0,0 +1,278 @@ +package funkin.ui.freeplay.backcards; + +import funkin.ui.freeplay.FreeplayState; +import flash.display.BitmapData; +import flixel.FlxCamera; +import flixel.math.FlxMath; +import flixel.FlxSprite; +import flixel.group.FlxGroup; +import flixel.group.FlxGroup.FlxTypedGroup; +import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup; +import flixel.math.FlxAngle; +import flixel.math.FlxPoint; +import flixel.text.FlxText; +import flixel.tweens.FlxEase; +import flixel.tweens.FlxTween; +import flixel.util.FlxColor; +import flixel.util.FlxSpriteUtil; +import flixel.util.FlxTimer; +import funkin.graphics.adobeanimate.FlxAtlasSprite; +import funkin.graphics.FunkinSprite; +import funkin.ui.freeplay.charselect.PlayableCharacter; +import funkin.ui.MusicBeatSubState; +import lime.utils.Assets; +import openfl.display.BlendMode; +import flixel.group.FlxSpriteGroup; +import funkin.graphics.shaders.AdjustColorShader; +import flixel.addons.display.FlxTiledSprite; +import flixel.addons.display.FlxBackdrop; + +class NewCharacterCard extends BackingCard +{ + var confirmAtlas:FlxAtlasSprite; + + var darkBg:FlxSprite; + var lightLayer:FlxSprite; + var multiply1:FlxSprite; + var multiply2:FlxSprite; + var lightLayer2:FlxSprite; + var lightLayer3:FlxSprite; + var yellow:FlxSprite; + var multiplyBar:FlxSprite; + + var bruh:FlxSprite; + + public var friendFoe:BGScrollingText; + public var newUnlock1:BGScrollingText; + public var waiting:BGScrollingText; + public var newUnlock2:BGScrollingText; + public var friendFoe2:BGScrollingText; + public var newUnlock3:BGScrollingText; + + public override function applyExitMovers(?exitMovers:FreeplayState.ExitMoverData, ?exitMoversCharSel:FreeplayState.ExitMoverData):Void + { + super.applyExitMovers(exitMovers, exitMoversCharSel); + if (exitMovers == null || exitMoversCharSel == null) return; + exitMovers.set([friendFoe], + { + x: FlxG.width * 2, + speed: 0.4, + }); + exitMovers.set([newUnlock1], + { + x: -newUnlock1.width * 2, + y: newUnlock1.y, + speed: 0.4, + wait: 0 + }); + exitMovers.set([waiting], + { + x: FlxG.width * 2, + speed: 0.4, + }); + exitMovers.set([newUnlock2], + { + x: -newUnlock2.width * 2, + speed: 0.5, + }); + exitMovers.set([friendFoe2], + { + x: FlxG.width * 2, + speed: 0.4 + }); + exitMovers.set([newUnlock3], + { + x: -newUnlock3.width * 2, + speed: 0.3 + }); + + exitMoversCharSel.set([friendFoe, newUnlock1, waiting, newUnlock2, friendFoe2, newUnlock3, multiplyBar], { + y: -60, + speed: 0.8, + wait: 0.1 + }); + } + + public override function introDone():Void + { + // pinkBack.color = 0xFFFFD863; + + darkBg.visible = true; + friendFoe.visible = true; + newUnlock1.visible = true; + waiting.visible = true; + newUnlock2.visible = true; + friendFoe2.visible = true; + newUnlock3.visible = true; + multiplyBar.visible = true; + lightLayer.visible = true; + multiply1.visible = true; + multiply2.visible = true; + lightLayer2.visible = true; + yellow.visible = true; + lightLayer3.visible = true; + + cardGlow.visible = true; + FlxTween.tween(cardGlow, {alpha: 0, "scale.x": 1.2, "scale.y": 1.2}, 0.45, {ease: FlxEase.sineOut}); + } + + public override function enterCharSel():Void + { + FlxTween.tween(friendFoe, {speed: 0}, 0.8, {ease: FlxEase.sineIn}); + FlxTween.tween(newUnlock1, {speed: 0}, 0.8, {ease: FlxEase.sineIn}); + FlxTween.tween(waiting, {speed: 0}, 0.8, {ease: FlxEase.sineIn}); + FlxTween.tween(newUnlock2, {speed: 0}, 0.8, {ease: FlxEase.sineIn}); + FlxTween.tween(friendFoe2, {speed: 0}, 0.8, {ease: FlxEase.sineIn}); + FlxTween.tween(newUnlock3, {speed: 0}, 0.8, {ease: FlxEase.sineIn}); + } + + public override function init():Void + { + FlxTween.tween(pinkBack, {x: 0}, 0.6, {ease: FlxEase.quartOut}); + add(pinkBack); + + confirmTextGlow.blend = BlendMode.ADD; + confirmTextGlow.visible = false; + + confirmGlow.blend = BlendMode.ADD; + + confirmGlow.visible = false; + confirmGlow2.visible = false; + + friendFoe = new BGScrollingText(0, 163, "COULD IT BE A NEW FRIEND? OR FOE??", FlxG.width, true, 43); + newUnlock1 = new BGScrollingText(-440, 215, 'NEW UNLOCK!', FlxG.width / 2, true, 80); + waiting = new BGScrollingText(0, 286, "SOMEONE'S WAITING!", FlxG.width / 2, true, 43); + newUnlock2 = new BGScrollingText(-220, 331, 'NEW UNLOCK!', FlxG.width / 2, true, 80); + friendFoe2 = new BGScrollingText(0, 402, 'COULD IT BE A NEW FRIEND? OR FOE??', FlxG.width, true, 43); + newUnlock3 = new BGScrollingText(0, 458, 'NEW UNLOCK!', FlxG.width / 2, true, 80); + + darkBg = new FlxSprite(0, 0).loadGraphic(Paths.image('freeplay/backingCards/newCharacter/darkback')); + add(darkBg); + + friendFoe.funnyColor = 0xFF139376; + friendFoe.speed = -4; + add(friendFoe); + + newUnlock1.funnyColor = 0xFF99BDF2; + newUnlock1.speed = 2; + add(newUnlock1); + + waiting.funnyColor = 0xFF40EA84; + waiting.speed = -2; + add(waiting); + + newUnlock2.funnyColor = 0xFF99BDF2; + newUnlock2.speed = 2; + add(newUnlock2); + + friendFoe2.funnyColor = 0xFF139376; + friendFoe2.speed = -4; + add(friendFoe2); + + newUnlock3.funnyColor = 0xFF99BDF2; + newUnlock3.speed = 2; + add(newUnlock3); + + multiplyBar = new FlxSprite(-10, 440).loadGraphic(Paths.image('freeplay/backingCards/newCharacter/multiplyBar')); + multiplyBar.blend = BlendMode.MULTIPLY; + add(multiplyBar); + + lightLayer = new FlxSprite(-360, 230).loadGraphic(Paths.image('freeplay/backingCards/newCharacter/orange gradient')); + lightLayer.blend = BlendMode.ADD; + add(lightLayer); + + multiply1 = new FlxSprite(-15, -125).loadGraphic(Paths.image('freeplay/backingCards/newCharacter/red')); + multiply1.blend = BlendMode.MULTIPLY; + add(multiply1); + + multiply2 = new FlxSprite(-15, -125).loadGraphic(Paths.image('freeplay/backingCards/newCharacter/red')); + multiply2.blend = BlendMode.MULTIPLY; + add(multiply2); + + lightLayer2 = new FlxSprite(-360, 230).loadGraphic(Paths.image('freeplay/backingCards/newCharacter/orange gradient')); + lightLayer2.blend = BlendMode.ADD; + add(lightLayer2); + + yellow = new FlxSprite(0, 0).loadGraphic(Paths.image('freeplay/backingCards/newCharacter/yellow bg piece')); + yellow.blend = BlendMode.MULTIPLY; + add(yellow); + + lightLayer3 = new FlxSprite(-360, 290).loadGraphic(Paths.image('freeplay/backingCards/newCharacter/red gradient')); + lightLayer3.blend = BlendMode.ADD; + add(lightLayer3); + + cardGlow.blend = BlendMode.ADD; + cardGlow.visible = false; + + add(cardGlow); + + darkBg.visible = false; + friendFoe.visible = false; + newUnlock1.visible = false; + waiting.visible = false; + newUnlock2.visible = false; + friendFoe2.visible = false; + newUnlock3.visible = false; + multiplyBar.visible = false; + lightLayer.visible = false; + multiply1.visible = false; + multiply2.visible = false; + lightLayer2.visible = false; + yellow.visible = false; + lightLayer3.visible = false; + } + + var _timer:Float = 0; + + override public function update(elapsed:Float):Void + { + super.update(elapsed); + + _timer += elapsed * 2; + var sinTest:Float = (Math.sin(_timer) + 1) / 2; + lightLayer.alpha = FlxMath.lerp(0.4, 1, sinTest); + lightLayer2.alpha = FlxMath.lerp(0.2, 0.5, sinTest); + lightLayer3.alpha = FlxMath.lerp(0.1, 0.7, sinTest); + + multiply1.alpha = FlxMath.lerp(1, 0.21, sinTest); + multiply2.alpha = FlxMath.lerp(1, 0.21, sinTest); + + yellow.alpha = FlxMath.lerp(0.2, 0.72, sinTest); + + if (instance != null) + { + instance.angleMaskShader.extraColor = FlxColor.interpolate(0xFF2E2E46, 0xFF60607B, sinTest); + } + } + + public override function disappear():Void + { + FlxTween.color(pinkBack, 0.25, 0xFF05020E, 0xFFFFD0D5, {ease: FlxEase.quadOut}); + + darkBg.visible = false; + friendFoe.visible = false; + newUnlock1.visible = false; + waiting.visible = false; + newUnlock2.visible = false; + friendFoe2.visible = false; + newUnlock3.visible = false; + multiplyBar.visible = false; + lightLayer.visible = false; + multiply1.visible = false; + multiply2.visible = false; + lightLayer2.visible = false; + yellow.visible = false; + lightLayer3.visible = false; + + 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}); + } + + override public function confirm():Void + { + // confirmAtlas.visible = true; + // confirmAtlas.anim.play(""); + } +} diff --git a/source/funkin/ui/freeplay/backcards/PicoCard.hx b/source/funkin/ui/freeplay/backcards/PicoCard.hx index a424a76ef..f5db1ccc3 100644 --- a/source/funkin/ui/freeplay/backcards/PicoCard.hx +++ b/source/funkin/ui/freeplay/backcards/PicoCard.hx @@ -1,7 +1,9 @@ package funkin.ui.freeplay.backcards; import funkin.ui.freeplay.FreeplayState; +import flash.display.BitmapData; import flixel.FlxCamera; +import flixel.math.FlxMath; import flixel.FlxSprite; import flixel.group.FlxGroup; import flixel.group.FlxGroup.FlxTypedGroup; @@ -21,25 +23,77 @@ import funkin.ui.MusicBeatSubState; import lime.utils.Assets; import openfl.display.BlendMode; import flixel.group.FlxSpriteGroup; +import funkin.graphics.shaders.AdjustColorShader; +import flixel.addons.display.FlxTiledSprite; +import flixel.addons.display.FlxBackdrop; -/** - * A class for the backing cards so they dont have to be part of freeplayState...... - */ class PicoCard extends BackingCard { + var scrollBack:FlxBackdrop; + var scrollLower:FlxBackdrop; + var scrollTop:FlxBackdrop; + var scrollMiddle:FlxBackdrop; + + var glow:FlxSprite; + var glowDark:FlxSprite; + var blueBar:FlxSprite; + + var confirmAtlas:FlxAtlasSprite; + + public override function enterCharSel():Void + { + FlxTween.tween(scrollBack.velocity, {x: 0}, 0.8, {ease: FlxEase.sineIn}); + FlxTween.tween(scrollLower.velocity, {x: 0}, 0.8, {ease: FlxEase.sineIn}); + FlxTween.tween(scrollTop.velocity, {x: 0}, 0.8, {ease: FlxEase.sineIn}); + FlxTween.tween(scrollMiddle.velocity, {x: 0}, 0.8, {ease: FlxEase.sineIn}); + } + + public override function applyExitMovers(?exitMovers:FreeplayState.ExitMoverData, ?exitMoversCharSel:FreeplayState.ExitMoverData):Void + { + super.applyExitMovers(exitMovers, exitMoversCharSel); + if (exitMovers == null || exitMoversCharSel == null) return; + + exitMoversCharSel.set([scrollTop], + { + y: -90, + speed: 0.8, + wait: 0.1 + }); + + exitMoversCharSel.set([scrollMiddle], + { + y: -80, + speed: 0.8, + wait: 0.1 + }); + + exitMoversCharSel.set([blueBar], + { + y: -70, + speed: 0.8, + wait: 0.1 + }); + + exitMoversCharSel.set([scrollLower], + { + y: -60, + speed: 0.8, + wait: 0.1 + }); + + exitMoversCharSel.set([scrollBack], + { + y: -50, + speed: 0.8, + wait: 0.1 + }); + } + public override function init():Void { FlxTween.tween(pinkBack, {x: 0}, 0.6, {ease: FlxEase.quartOut}); add(pinkBack); - // add(orangeBackShit); - - // add(alsoOrangeLOL); - - // FlxSpriteUtil.alphaMaskFlxSprite(orangeBackShit, pinkBack, orangeBackShit); - // orangeBackShit.visible = false; - // alsoOrangeLOL.visible = false; - confirmTextGlow.blend = BlendMode.ADD; confirmTextGlow.visible = false; @@ -48,27 +102,213 @@ class PicoCard extends BackingCard confirmGlow.visible = false; confirmGlow2.visible = false; - add(confirmGlow2); - add(confirmGlow); + scrollBack = new FlxBackdrop(Paths.image('freeplay/backingCards/pico/lowerLoop'), X, 20); + scrollBack.setPosition(0, 200); + scrollBack.flipX = true; + scrollBack.alpha = 0.39; + scrollBack.velocity.x = 110; + add(scrollBack); - add(confirmTextGlow); + scrollLower = new FlxBackdrop(Paths.image('freeplay/backingCards/pico/lowerLoop'), X, 20); + scrollLower.setPosition(0, 406); + scrollLower.velocity.x = -110; + add(scrollLower); - add(backingTextYeah); + blueBar = new FlxSprite(0, 239).loadGraphic(Paths.image('freeplay/backingCards/pico/blueBar')); + blueBar.blend = BlendMode.MULTIPLY; + blueBar.alpha = 0.4; + add(blueBar); + + scrollTop = new FlxBackdrop(null, X, 20); + scrollTop.setPosition(0, 80); + scrollTop.velocity.x = -220; + + scrollTop.frames = Paths.getSparrowAtlas('freeplay/backingCards/pico/topLoop'); + scrollTop.animation.addByPrefix('uzi', 'uzi info', 24, false); + scrollTop.animation.addByPrefix('sniper', 'sniper info', 24, false); + scrollTop.animation.addByPrefix('rocket launcher', 'rocket launcher info', 24, false); + scrollTop.animation.addByPrefix('rifle', 'rifle info', 24, false); + scrollTop.animation.addByPrefix('base', 'base', 24, false); + scrollTop.animation.play('base'); + + add(scrollTop); + + scrollMiddle = new FlxBackdrop(Paths.image('freeplay/backingCards/pico/middleLoop'), X, 15); + scrollMiddle.setPosition(0, 346); + add(scrollMiddle); + scrollMiddle.velocity.x = 220; + + glowDark = new FlxSprite(-300, 330).loadGraphic(Paths.image('freeplay/backingCards/pico/glow')); + glowDark.blend = BlendMode.MULTIPLY; + add(glowDark); + + glow = new FlxSprite(-300, 330).loadGraphic(Paths.image('freeplay/backingCards/pico/glow')); + glow.blend = BlendMode.ADD; + add(glow); + + blueBar.visible = false; + scrollBack.visible = false; + scrollLower.visible = false; + scrollTop.visible = false; + scrollMiddle.visible = false; + glow.visible = false; + glowDark.visible = false; + + confirmAtlas = new FlxAtlasSprite(5, 55, Paths.animateAtlas("freeplay/backingCards/pico/pico-confirm")); + confirmAtlas.visible = false; + add(confirmAtlas); cardGlow.blend = BlendMode.ADD; cardGlow.visible = false; - add(cardGlow); } - public override function applyStyle(_freeplayState:FreeplayState):Void {} + override public function confirm():Void + { + confirmAtlas.visible = true; + confirmAtlas.anim.play(""); + + FlxTween.color(instance.bgDad, 10 / 24, 0xFFFFFFFF, 0xFF8A8A8A, + { + ease: FlxEase.expoOut, + onUpdate: function(_) { + instance.angleMaskShader.extraColor = instance.bgDad.color; + } + }); + + new FlxTimer().start(10 / 24, function(_) { + // shoot + FlxTween.color(instance.bgDad, 3 / 24, 0xFF343036, 0xFF696366, + { + ease: FlxEase.expoOut, + onUpdate: function(_) { + instance.angleMaskShader.extraColor = instance.bgDad.color; + } + }); + }); + + new FlxTimer().start(14 / 24, function(_) { + // shoot + FlxTween.color(instance.bgDad, 3 / 24, 0xFF27292D, 0xFF686A6F, + { + ease: FlxEase.expoOut, + onUpdate: function(_) { + instance.angleMaskShader.extraColor = instance.bgDad.color; + } + }); + }); + + new FlxTimer().start(18 / 24, function(_) { + // shoot + FlxTween.color(instance.bgDad, 3 / 24, 0xFF2D282D, 0xFF676164, + { + ease: FlxEase.expoOut, + onUpdate: function(_) { + instance.angleMaskShader.extraColor = instance.bgDad.color; + } + }); + }); + + new FlxTimer().start(21 / 24, function(_) { + // shoot + FlxTween.color(instance.bgDad, 3 / 24, 0xFF29292F, 0xFF62626B, + { + ease: FlxEase.expoOut, + onUpdate: function(_) { + instance.angleMaskShader.extraColor = instance.bgDad.color; + } + }); + }); + + new FlxTimer().start(24 / 24, function(_) { + // shoot + FlxTween.color(instance.bgDad, 3 / 24, 0xFF29232C, 0xFF808080, + { + ease: FlxEase.expoOut, + onUpdate: function(_) { + instance.angleMaskShader.extraColor = instance.bgDad.color; + } + }); + }); + } + + var beatFreq:Int = 1; + var beatFreqList:Array = [1,2,4,8]; + + public override function beatHit():Void { + // increases the amount of beats that need to go by to pulse the glow because itd flash like craazy at high bpms..... + beatFreq = beatFreqList[Math.floor(Conductor.instance.bpm/140)]; + + if(Conductor.instance.currentBeat % beatFreq != 0) return; + FlxTween.cancelTweensOf(glow); + FlxTween.cancelTweensOf(glowDark); + + glow.alpha = 1; + FlxTween.tween(glow, {alpha: 0}, 16/24, {ease: FlxEase.quartOut}); + glowDark.alpha = 0; + FlxTween.tween(glowDark, {alpha: 1}, 18/24, {ease: FlxEase.quartOut}); + } public override function introDone():Void { pinkBack.color = 0xFF98A2F3; - // orangeBackShit.visible = true; - // alsoOrangeLOL.visible = true; + + blueBar.visible = true; + scrollBack.visible = true; + scrollLower.visible = true; + scrollTop.visible = true; + scrollMiddle.visible = true; + glowDark.visible = true; + glow.visible = true; + cardGlow.visible = true; FlxTween.tween(cardGlow, {alpha: 0, "scale.x": 1.2, "scale.y": 1.2}, 0.45, {ease: FlxEase.sineOut}); } + + public override function disappear():Void + { + FlxTween.color(pinkBack, 0.25, 0xFF98A2F3, 0xFFFFD0D5, {ease: FlxEase.quadOut}); + + blueBar.visible = false; + scrollBack.visible = false; + scrollLower.visible = false; + scrollTop.visible = false; + scrollMiddle.visible = false; + glowDark.visible = false; + glow.visible = false; + + 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}); + } + + override public function update(elapsed:Float):Void + { + super.update(elapsed); + var scrollProgress:Float = Math.abs(scrollTop.x % (scrollTop.frameWidth + 20)); + + if (scrollTop.animation.curAnim.finished == true) + { + if (FlxMath.inBounds(scrollProgress, 500, 700) && scrollTop.animation.curAnim.name != 'sniper') + { + scrollTop.animation.play('sniper', true, false); + } + + if (FlxMath.inBounds(scrollProgress, 700, 1300) && scrollTop.animation.curAnim.name != 'rifle') + { + scrollTop.animation.play('rifle', true, false); + } + + if (FlxMath.inBounds(scrollProgress, 1450, 2000) && scrollTop.animation.curAnim.name != 'rocket launcher') + { + scrollTop.animation.play('rocket launcher', true, false); + } + + if (FlxMath.inBounds(scrollProgress, 0, 300) && scrollTop.animation.curAnim.name != 'uzi') + { + scrollTop.animation.play('uzi', true, false); + } + } + } } From 0c809c828e369130e8429a1d5d68732c3acfb4cf Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Fri, 30 Aug 2024 01:03:11 +0100 Subject: [PATCH 649/870] color tint for angle mask shader --- source/funkin/graphics/shaders/AngleMask.hx | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/source/funkin/graphics/shaders/AngleMask.hx b/source/funkin/graphics/shaders/AngleMask.hx index c5ef87b72..ce27311cd 100644 --- a/source/funkin/graphics/shaders/AngleMask.hx +++ b/source/funkin/graphics/shaders/AngleMask.hx @@ -1,12 +1,25 @@ package funkin.graphics.shaders; import flixel.system.FlxAssets.FlxShader; +import flixel.util.FlxColor; class AngleMask extends FlxShader { + public var extraColor(default, set):FlxColor = 0xFFFFFFFF; + + function set_extraColor(value:FlxColor):FlxColor + { + extraTint.value = [value.redFloat, value.greenFloat, value.blueFloat]; + this.extraColor = value; + + return this.extraColor; + } + @:glFragmentSource(' #pragma header + uniform vec3 extraTint; + uniform vec2 endPosition; vec2 hash22(vec2 p) { vec3 p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973)); @@ -69,6 +82,7 @@ class AngleMask extends FlxShader void main() { vec4 col = antialias(openfl_TextureCoordv); + col.xyz = col.xyz * extraTint.xyz; // col.xyz = gamma(col.xyz); gl_FragColor = col; }') @@ -77,5 +91,6 @@ class AngleMask extends FlxShader super(); endPosition.value = [90, 100]; // 100 AS DEFAULT WORKS NICELY FOR FREEPLAY? + extraTint.value = [1, 1, 1]; } } From 60c10aae997a64c2817e27c49e2be2c6e9419550 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Fri, 30 Aug 2024 01:04:30 +0100 Subject: [PATCH 650/870] char select to freeplay transition, backing card implementation, beatHit for backing cards --- .../ui/charSelect/CharSelectSubState.hx | 13 +- source/funkin/ui/freeplay/FreeplayState.hx | 185 ++++++++++++++---- 2 files changed, 159 insertions(+), 39 deletions(-) diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index 34ffbaf58..d0bafddf9 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -391,9 +391,15 @@ class CharSelectSubState extends MusicBeatSubState } } - function testLol():Void + function goToFreeplay():Void { autoFollow = false; + + FlxTween.tween(cursor, {alpha: 0}, 0.8, {ease: FlxEase.expoOut}); + FlxTween.tween(cursorBlue, {alpha: 0}, 0.8, {ease: FlxEase.expoOut}); + FlxTween.tween(cursorDarkBlue, {alpha: 0}, 0.8, {ease: FlxEase.expoOut}); + FlxTween.tween(cursorConfirmed, {alpha: 0}, 0.8, {ease: FlxEase.expoOut}); + FlxTween.tween(barthing, {y: barthing.y + 80}, 0.8, {ease: FlxEase.backIn}); FlxTween.tween(dipshitBacking, {y: dipshitBacking.y + 210}, 0.8, {ease: FlxEase.backIn}); FlxTween.tween(chooseDipshit, {y: chooseDipshit.y + 200}, 0.8, {ease: FlxEase.backIn}); @@ -413,7 +419,8 @@ class CharSelectSubState extends MusicBeatSubState FlxG.switchState(FreeplayState.build( { { - character: curChar + character: curChar, + fromCharSelect: true } })); } @@ -542,7 +549,7 @@ class CharSelectSubState extends MusicBeatSubState // character: curChar // } // })); - testLol(); + goToFreeplay(); }); } diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 614e8cc86..5d3a2bead 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1,8 +1,6 @@ package funkin.ui.freeplay; -import funkin.ui.freeplay.backcards.BackingCard; -import funkin.ui.freeplay.backcards.BoyfriendCard; -import funkin.ui.freeplay.backcards.PicoCard; +import funkin.ui.freeplay.backcards.*; import flixel.addons.transition.FlxTransitionableState; import flixel.addons.ui.FlxInputText; import flixel.FlxCamera; @@ -55,6 +53,8 @@ import funkin.util.MathUtil; import funkin.util.SortUtil; import lime.utils.Assets; import openfl.display.BlendMode; +import funkin.data.freeplay.style.FreeplayStyleRegistry; +import funkin.data.song.SongData.SongMusicData; /** * Parameters used to initialize the FreeplayState. @@ -63,6 +63,8 @@ typedef FreeplayStateParams = { ?character:String, + ?fromCharSelect:Bool, + ?fromResults:FromResultsParams, }; @@ -149,7 +151,8 @@ class FreeplayState extends MusicBeatSubState var curSelected:Int = 0; var currentDifficulty:String = Constants.DEFAULT_DIFFICULTY; - var fp:FreeplayScore; + public var fp:FreeplayScore; + var txtCompletion:AtlasText; var lerpCompletion:Float = 0; var intendedCompletion:Float = 0; @@ -201,9 +204,14 @@ class FreeplayState extends MusicBeatSubState var prepForNewRank:Bool = false; + var styleData:Null = null; + + var fromCharSelect:Null = null; + public function new(?params:FreeplayStateParams, ?stickers:StickerSubState) { currentCharacterId = params?.character ?? Constants.DEFAULT_CHARACTER; + styleData = FreeplayStyleRegistry.instance.fetchEntry(currentCharacterId); var fetchPlayableCharacter = function():PlayableCharacter { var result = PlayerRegistry.instance.fetchEntry(params?.character ?? Constants.DEFAULT_CHARACTER); if (result == null) throw 'No valid playable character with id ${params?.character}'; @@ -211,6 +219,8 @@ class FreeplayState extends MusicBeatSubState }; currentCharacter = fetchPlayableCharacter(); + fromCharSelect = params?.fromCharSelect; + fromResultsParams = params?.fromResults; if (fromResultsParams?.playRankAnim == true) @@ -228,7 +238,7 @@ class FreeplayState extends MusicBeatSubState switch (currentCharacterId) { case 'bf': - backingCard = new BoyfriendCard(currentCharacter); + backingCard = new NewCharacterCard(currentCharacter); case 'pico': backingCard = new PicoCard(currentCharacter); default: @@ -237,7 +247,7 @@ class FreeplayState extends MusicBeatSubState // We build a bunch of sprites BEFORE create() so we can guarantee they aren't null later on. albumRoll = new AlbumRoll(); - fp = new FreeplayScore(460, 60, 7, 100); + fp = new FreeplayScore(460, 60, 7, 100, styleData); rankCamera = new FunkinCamera('rankCamera', 0, 0, FlxG.width, FlxG.height); funnyCam = new FunkinCamera('freeplayFunny', 0, 0, FlxG.width, FlxG.height); grpCapsules = new FlxTypedGroup(); @@ -252,11 +262,13 @@ class FreeplayState extends MusicBeatSubState ostName = new FlxText(8, 8, FlxG.width - 8 - 8, 'OFFICIAL OST', 48); - bgDad = new FlxSprite(backingCard.pinkBack.width * 0.74, 0).loadGraphic(Paths.image('freeplay/freeplayBGdad')); + bgDad = new FlxSprite(backingCard.pinkBack.width * 0.74, 0).loadGraphic(styleData == null ? 'freeplay/freeplayBGdad' : styleData.getBgAssetGraphic()); } var fadeShader:BlueFade = new BlueFade(); + public var angleMaskShader:AngleMask = new AngleMask(); + override function create():Void { super.create(); @@ -350,6 +362,7 @@ class FreeplayState extends MusicBeatSubState add(backingCard); backingCard.init(); backingCard.applyExitMovers(exitMovers, exitMoversCharSel); + backingCard.instance = this; } if (currentCharacter?.getFreeplayDJData() != null) @@ -369,7 +382,7 @@ class FreeplayState extends MusicBeatSubState }); } - bgDad.shader = new AngleMask(); + bgDad.shader = angleMaskShader; bgDad.visible = false; var blackOverlayBullshitLOLXD:FlxSprite = new FlxSprite(FlxG.width).makeGraphic(Std.int(bgDad.width), Std.int(bgDad.height), FlxColor.BLACK); @@ -398,7 +411,6 @@ class FreeplayState extends MusicBeatSubState add(bgDad); // backingCard.pinkBack.width * 0.74 - FlxTween.tween(blackOverlayBullshitLOLXD, {x: 387.76}, 0.7, {ease: FlxEase.quintOut}); blackOverlayBullshitLOLXD.shader = bgDad.shader; @@ -445,12 +457,18 @@ class FreeplayState extends MusicBeatSubState albumRoll.albumId = null; add(albumRoll); - albumRoll.applyExitMovers(exitMovers, exitMoversCharSel); - var overhangStuff:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, 164, FlxColor.BLACK); overhangStuff.y -= overhangStuff.height; - FlxTween.tween(overhangStuff, {y: -100}, 0.3, {ease: FlxEase.quartOut}); + if(fromCharSelect == true){ + blackOverlayBullshitLOLXD.x = 387.76; + overhangStuff.y = -100; + backingCard?.skipIntroTween(); + }else{ + albumRoll.applyExitMovers(exitMovers, exitMoversCharSel); + FlxTween.tween(overhangStuff, {y: -100}, 0.3, {ease: FlxEase.quartOut}); + FlxTween.tween(blackOverlayBullshitLOLXD, {x: 387.76}, 0.7, {ease: FlxEase.quintOut}); + } var fnfFreeplay:FlxText = new FlxText(8, 8, 0, 'FREEPLAY', 48); fnfFreeplay.font = 'VCR OSD Mono'; @@ -554,8 +572,8 @@ class FreeplayState extends MusicBeatSubState wait: 0.1 }); - var diffSelLeft:DifficultySelector = new DifficultySelector(20, grpDifficulties.y - 10, false, controls); - var diffSelRight:DifficultySelector = new DifficultySelector(325, grpDifficulties.y - 10, true, controls); + var diffSelLeft:DifficultySelector = new DifficultySelector(20, grpDifficulties.y - 10, false, controls, styleData); + var diffSelRight:DifficultySelector = new DifficultySelector(325, grpDifficulties.y - 10, true, controls, styleData); diffSelLeft.visible = false; diffSelRight.visible = false; add(diffSelLeft); @@ -573,6 +591,19 @@ class FreeplayState extends MusicBeatSubState albumRoll.playIntro(); + if (fromCharSelect == null) { + // render optimisation + if (_parentState != null) _parentState.persistentDraw = false; + + FlxTween.color(bgDad, 0.6, 0xFF000000, 0xFFFFFFFF, + { + ease: FlxEase.expoOut, + onUpdate: function(_) { + angleMaskShader.extraColor = bgDad.color; + } + }); + } + FlxTween.tween(grpDifficulties, {x: 90}, 0.6, {ease: FlxEase.quartOut}); diffSelLeft.visible = true; @@ -613,9 +644,6 @@ class FreeplayState extends MusicBeatSubState bgDad.visible = true; backingCard?.introDone(); - // render optimisation - if (_parentState != null) _parentState.persistentDraw = false; - if (prepForNewRank && fromResultsParams != null) { rankAnimStart(fromResultsParams); @@ -657,6 +685,12 @@ class FreeplayState extends MusicBeatSubState { rankCamera.fade(0xFF000000, 0, false, null, true); } + + if (fromCharSelect == true) + { + enterFromCharSel(); + onDJIntroDone(); + } } var currentFilter:Null = null; @@ -715,7 +749,7 @@ class FreeplayState extends MusicBeatSubState var hsvShader:HSVShader = new HSVShader(); var randomCapsule:SongMenuItem = grpCapsules.recycle(SongMenuItem); - randomCapsule.init(FlxG.width, 0, null); + randomCapsule.init(FlxG.width, 0, null, styleData); randomCapsule.onConfirm = function() { capsuleOnConfirmRandom(randomCapsule); }; @@ -727,7 +761,14 @@ class FreeplayState extends MusicBeatSubState randomCapsule.favIconBlurred.visible = false; randomCapsule.ranking.visible = false; randomCapsule.blurredRanking.visible = false; - randomCapsule.initJumpIn(0, force); + if (fromCharSelect == false) + { + randomCapsule.initJumpIn(0, force); + } + else + { + randomCapsule.forcePosition(); + } randomCapsule.hsvShader = hsvShader; grpCapsules.add(randomCapsule); @@ -738,7 +779,7 @@ class FreeplayState extends MusicBeatSubState var funnyMenu:SongMenuItem = grpCapsules.recycle(SongMenuItem); - funnyMenu.init(FlxG.width, 0, tempSong); + funnyMenu.init(FlxG.width, 0, tempSong, styleData); funnyMenu.onConfirm = function() { capsuleOnConfirmDefault(funnyMenu); }; @@ -1106,6 +1147,7 @@ class FreeplayState extends MusicBeatSubState function goToCharSelect():Void { + busy = true; var transitionGradient = new FlxSprite(0, 720).loadGraphic(Paths.image('freeplay/transitionGradient')); transitionGradient.scale.set(1280, 1); transitionGradient.updateHitbox(); @@ -1117,7 +1159,6 @@ class FreeplayState extends MusicBeatSubState wait: 0.1 }); add(transitionGradient); - // busy = true; for (index => capsule in grpCapsules.members) { var distFromSelected:Float = Math.abs(index - curSelected) - 1; @@ -1134,7 +1175,6 @@ class FreeplayState extends MusicBeatSubState } fadeShader.fade(1.0, 0.0, 0.8, {ease: FlxEase.quadIn}); FlxG.sound.music.fadeOut(0.9, 0); - // FlxTween.tween(transitionGradient, {y: 0}, 1, {ease: FlxEase.expoOut, startDelay: 0.3}); new FlxTimer().start(0.9, _ -> { FlxG.switchState(new funkin.ui.charSelect.CharSelectSubState()); }); @@ -1149,13 +1189,77 @@ class FreeplayState extends MusicBeatSubState var funnyMoveShit:MoveData = moveData; - var moveDataX = funnyMoveShit.x ?? spr.x; var moveDataY = funnyMoveShit.y ?? spr.y; var moveDataSpeed = funnyMoveShit.speed ?? 0.2; var moveDataWait = funnyMoveShit.wait ?? 0.0; - FlxTween.tween(spr, {x: moveDataX, y: moveDataY + spr.y}, moveDataSpeed, {ease: FlxEase.backIn}); - // longestTimer = Math.max(longestTimer, moveDataSpeed + moveDataWait); + FlxTween.tween(spr, {y: moveDataY + spr.y}, moveDataSpeed, {ease: FlxEase.backIn}); + } + } + backingCard?.enterCharSel(); + } + + function enterFromCharSel():Void + { + busy = true; + if (_parentState != null) _parentState.persistentDraw = false; + + var transitionGradient = new FlxSprite(0, 720).loadGraphic(Paths.image('freeplay/transitionGradient')); + transitionGradient.scale.set(1280, 1); + transitionGradient.updateHitbox(); + transitionGradient.cameras = [rankCamera]; + exitMoversCharSel.set([transitionGradient], + { + y: -720, + speed: 1.5, + wait: 0.1 + }); + add(transitionGradient); + // FlxTween.tween(transitionGradient, {alpha: 0}, 1, {ease: FlxEase.circIn}); + // for (index => capsule in grpCapsules.members) + // { + // var distFromSelected:Float = Math.abs(index - curSelected) - 1; + // if (distFromSelected < 5) + // { + // capsule.doLerp = false; + // exitMoversCharSel.set([capsule], + // { + // y: -250, + // speed: 0.8, + // wait: 0.1 + // }); + // } + // } + fadeShader.fade(0.0, 1.0, 0.8, {ease: FlxEase.quadIn}); + for (grpSpr in exitMoversCharSel.keys()) + { + var moveData:Null = exitMoversCharSel.get(grpSpr); + if (moveData == null) continue; + + for (spr in grpSpr) + { + if (spr == null) continue; + + var funnyMoveShit:MoveData = moveData; + + var moveDataY = funnyMoveShit.y ?? spr.y; + var moveDataSpeed = funnyMoveShit.speed ?? 0.2; + var moveDataWait = funnyMoveShit.wait ?? 0.0; + + spr.y += moveDataY; + FlxTween.tween(spr, {y: spr.y - moveDataY}, moveDataSpeed * 1.2, + { + ease: FlxEase.expoOut, + onComplete: function(_) { + for (index => capsule in grpCapsules.members) + { + capsule.doLerp = true; + fromCharSelect = false; + busy = false; + albumRoll.applyExitMovers(exitMovers, exitMoversCharSel); + } + } + }); } } } @@ -1185,10 +1289,7 @@ class FreeplayState extends MusicBeatSubState { super.update(elapsed); - if (FlxG.keys.justPressed.G) - { - goToCharSelect(); - } + Conductor.instance.update(); if (FlxG.keys.justPressed.P) { @@ -1225,7 +1326,7 @@ class FreeplayState extends MusicBeatSubState if (controls.FREEPLAY_CHAR_SELECT && !busy) { - FlxG.switchState(new funkin.ui.charSelect.CharSelectSubState()); + goToCharSelect(); } if (controls.FREEPLAY_FAVORITE && !busy) @@ -1549,6 +1650,13 @@ class FreeplayState extends MusicBeatSubState } } + override function beatHit():Bool + { + backingCard?.beatHit(); + + return super.beatHit(); + } + public override function destroy():Void { super.destroy(); @@ -1764,7 +1872,7 @@ class FreeplayState extends MusicBeatSubState backingCard?.confirm(); - new FlxTimer().start(1, function(tmr:FlxTimer) { + new FlxTimer().start(styleData?.getStartDelay(), function(tmr:FlxTimer) { FunkinSound.emptyPartialQueue(); Paths.setCurrentLevel(cap?.songData?.levelId); @@ -1878,7 +1986,7 @@ class FreeplayState extends MusicBeatSubState if (previewSongId == null) return; var previewSong:Null = SongRegistry.instance.fetchEntry(previewSongId); - var songDifficulty = previewSong?.getDifficulty(currentDifficulty, + var songDifficulty:Null = previewSong?.getDifficulty(currentDifficulty, previewSong?.getVariationsByCharacter(currentCharacter) ?? Constants.DEFAULT_VARIATION_LIST); var baseInstrumentalId:String = songDifficulty?.characters?.instrumental ?? ''; var altInstrumentalIds:Array = songDifficulty?.characters?.altInstrumentals ?? []; @@ -1908,13 +2016,18 @@ class FreeplayState extends MusicBeatSubState partialParams: { loadPartial: true, - start: 0.05, - end: 0.25 + start: 0, + end: 0.2 }, onLoad: function() { FlxG.sound.music.fadeIn(2, 0, 0.4); } }); + + if(songDifficulty != null) { + Conductor.instance.mapTimeChanges(songDifficulty.timeChanges); + Conductor.instance.update(FlxG.sound?.music?.time ?? 0.0); + } } } @@ -1944,13 +2057,13 @@ class DifficultySelector extends FlxSprite var controls:Controls; var whiteShader:PureColor; - public function new(x:Float, y:Float, flipped:Bool, controls:Controls) + public function new(x:Float, y:Float, flipped:Bool, controls:Controls, ?styleData:FreeplayStyle = null) { super(x, y); this.controls = controls; - frames = Paths.getSparrowAtlas('freeplay/freeplaySelector'); + frames = Paths.getSparrowAtlas(styleData == null ? 'freeplay/freeplaySelector' : styleData.getSelectorAssetKey()); animation.addByPrefix('shine', 'arrow pointer loop', 24); animation.play('shine'); From 27970e4c2dbf60003d67e27cfff6da165908cce9 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Fri, 30 Aug 2024 01:04:51 +0100 Subject: [PATCH 651/870] freeplay style changelog oops --- source/funkin/data/freeplay/style/CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 source/funkin/data/freeplay/style/CHANGELOG.md diff --git a/source/funkin/data/freeplay/style/CHANGELOG.md b/source/funkin/data/freeplay/style/CHANGELOG.md new file mode 100644 index 000000000..8fe9f7eb8 --- /dev/null +++ b/source/funkin/data/freeplay/style/CHANGELOG.md @@ -0,0 +1,9 @@ +# Freeplay Style Data Schema Changelog + +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). + +## [1.0.0] +Initial release. From 4f562e3d6c825aa82d3c211c9a5339afe74a07f1 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Fri, 30 Aug 2024 01:08:47 +0100 Subject: [PATCH 652/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 0d97c9b20..2ef40f931 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 0d97c9b20a989b4517fd6174fe56583ac600522c +Subproject commit 2ef40f931e1b514c2d0381078e0a4f46db83a3c6 From 71da847158273b12cd692a9503e741391790cebe Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Fri, 30 Aug 2024 01:12:26 +0100 Subject: [PATCH 653/870] forgot to change these back --- 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 5d3a2bead..bf24aa3b3 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -238,7 +238,7 @@ class FreeplayState extends MusicBeatSubState switch (currentCharacterId) { case 'bf': - backingCard = new NewCharacterCard(currentCharacter); + backingCard = new BoyfriendCard(currentCharacter); case 'pico': backingCard = new PicoCard(currentCharacter); default: From 21d5bb6112403c017f7f0eb1f51114b1b3b6f807 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 29 Aug 2024 22:10:27 -0400 Subject: [PATCH 654/870] Update assets submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index fda4eaaf3..91877ca4d 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit fda4eaaf3bab4e6ebcf66548517ee89de0438e3d +Subproject commit 91877ca4d17a319e8aa84234ab62c88269a8df39 From 7511de1e7a1856f325f07940d8800e9bf5e8fe5f Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sun, 1 Sep 2024 03:22:34 -0400 Subject: [PATCH 655/870] A bunch of Freeplay visual fixes --- assets | 2 +- source/funkin/Assets.hx | 33 +++ .../funkin/data/freeplay/player/PlayerData.hx | 20 ++ source/funkin/data/song/SongData.hx | 11 +- .../graphics/adobeanimate/FlxAtlasSprite.hx | 49 +++-- source/funkin/modding/IScriptedClass.hx | 28 ++- source/funkin/modding/PolymodHandler.hx | 9 +- .../modding/events/ScriptEventDispatcher.hx | 21 +- source/funkin/ui/charSelect/CharSelectGF.hx | 45 ++++- .../funkin/ui/charSelect/CharSelectPlayer.hx | 43 +++- .../ui/charSelect/CharSelectSubState.hx | 22 +- source/funkin/ui/freeplay/FreeplayDJ.hx | 6 +- source/funkin/ui/freeplay/FreeplayState.hx | 191 +++++++++++++++--- .../freeplay/charselect/PlayableCharacter.hx | 33 +-- source/funkin/ui/mainmenu/MainMenuState.hx | 12 +- source/funkin/util/Constants.hx | 5 + source/funkin/util/ReflectUtil.hx | 15 ++ 17 files changed, 436 insertions(+), 109 deletions(-) create mode 100644 source/funkin/Assets.hx diff --git a/assets b/assets index 5a0c8da32..dc2263336 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 5a0c8da32111571648b8fd07deabe2f78ae99eaa +Subproject commit dc226333655b7ec841b213968ef5264278fbcd63 diff --git a/source/funkin/Assets.hx b/source/funkin/Assets.hx new file mode 100644 index 000000000..67a668839 --- /dev/null +++ b/source/funkin/Assets.hx @@ -0,0 +1,33 @@ +package funkin; + +/** + * A wrapper around `openfl.utils.Assets` which disallows access to the harmful functions. + * Later we'll add Funkin-specific caching to this. + */ +class Assets +{ + public static function getText(path:String):String + { + return openfl.utils.Assets.getText(path); + } + + public static function getMusic(path:String):openfl.media.Sound + { + return openfl.utils.Assets.getMusic(path); + } + + public static function getBitmapData(path:String):openfl.display.BitmapData + { + return openfl.utils.Assets.getBitmapData(path); + } + + public static function getBytes(path:String):haxe.io.Bytes + { + return openfl.utils.Assets.getBytes(path); + } + + public static function list(type:openfl.utils.AssetType):Array + { + return openfl.utils.Assets.list(type); + } +} diff --git a/source/funkin/data/freeplay/player/PlayerData.hx b/source/funkin/data/freeplay/player/PlayerData.hx index 55657ba46..b2905ae98 100644 --- a/source/funkin/data/freeplay/player/PlayerData.hx +++ b/source/funkin/data/freeplay/player/PlayerData.hx @@ -31,6 +31,13 @@ class PlayerData @:default(false) public var showUnownedChars:Bool = false; + /** + * Which freeplay style to use for this character. + */ + @:optional + @:default("bf") + public var freeplayStyle:String = Constants.DEFAULT_FREEPLAY_STYLE; + /** * Data for displaying this character in the Freeplay menu. * If null, display no DJ. @@ -105,6 +112,9 @@ class PlayerFreeplayDJData @:jignored var prefixToOffsetsMap:Map>; + @:optional + var charSelect:Null; + @:optional var cartoon:Null; @@ -237,6 +247,11 @@ class PlayerFreeplayDJData { return fistPump?.loopBadEndFrame ?? 0; } + + public function getCharSelectTransitionDelay():Float + { + return charSelect?.transitionDelay ?? 0.25; + } } class PlayerCharSelectData @@ -300,6 +315,11 @@ typedef PlayerResultsAnimationData = var loopFrameLabel:Null; }; +typedef PlayerFreeplayDJCharSelectData = +{ + var transitionDelay:Float; +} + typedef PlayerFreeplayDJCartoonData = { var soundClickFrame:Int; diff --git a/source/funkin/data/song/SongData.hx b/source/funkin/data/song/SongData.hx index f487eb54d..551bcc8a3 100644 --- a/source/funkin/data/song/SongData.hx +++ b/source/funkin/data/song/SongData.hx @@ -264,11 +264,20 @@ class SongOffsets implements ICloneable @:default([]) public var vocals:Map; - public function new(instrumental:Float = 0.0, ?altInstrumentals:Map, ?vocals:Map) + /** + * The offset, in milliseconds, to apply to the songs vocals, relative to each alternate instrumental. + * This is useful for the circumstance where, for example, an alt instrumental has a few seconds of lead in before the song starts. + */ + @:optional + @:default([]) + public var altVocals:Map>; + + public function new(instrumental:Float = 0.0, ?altInstrumentals:Map, ?vocals:Map, ?altVocals:Map>) { this.instrumental = instrumental; this.altInstrumentals = altInstrumentals == null ? new Map() : altInstrumentals; this.vocals = vocals == null ? new Map() : vocals; + this.altVocals = altVocals == null ? new Map>() : altVocals; } public function getInstrumentalOffset(?instrumental:String):Float diff --git a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx index b32914ca3..c4eaaff50 100644 --- a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx +++ b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx @@ -105,23 +105,6 @@ class FlxAtlasSprite extends FlxAnimate return this.currentAnimation; } - /** - * `anim.finished` always returns false on looping animations, - * but this function will return true if we are on the last frame of the looping animation. - */ - public function isLoopFinished():Bool - { - if (this.anim == null) return false; - if (!this.anim.isPlaying) return false; - - // Reverse animation finished. - if (this.anim.reversed && this.anim.curFrame == 0) return true; - // Forward animation finished. - if (!this.anim.reversed && this.anim.curFrame >= (this.anim.length - 1)) return true; - - return false; - } - var _completeAnim:Bool = false; var fr:FlxKeyFrame = null; @@ -142,6 +125,8 @@ class FlxAtlasSprite extends FlxAnimate // Skip if not allowed to play animations. if ((!canPlayOtherAnims && !ignoreOther)) return; + if (anim == null) return; + if (id == null || id == '') id = this.currentAnimation; if (this.currentAnimation == id && !restart) @@ -189,10 +174,16 @@ class FlxAtlasSprite extends FlxAnimate // Move to the first frame of the animation. // goToFrameLabel(id); trace('Playing animation $id'); - this.anim.play(id, restart, false, startFrame); - goToFrameLabel(id); - - fr = anim.getFrameLabel(id); + if (this.anim.symbolDictionary.exists(id) || (this.anim.getByName(id) != null)) + { + this.anim.play(id, restart, false, startFrame); + } + // Only call goToFrameLabel if there is a frame label with that name. This prevents annoying warnings! + if (getFrameLabelNames().indexOf(id) != -1) + { + goToFrameLabel(id); + fr = anim.getFrameLabel(id); + } anim.curFrame += startFrame; this.currentAnimation = id; @@ -218,6 +209,8 @@ class FlxAtlasSprite extends FlxAnimate */ public function isLoopComplete():Bool { + if (this.anim == null) return false; + if (!this.anim.isPlaying) return false; return (anim.reversed && anim.curFrame == 0 || !(anim.reversed) && (anim.curFrame) >= (anim.length - 1)); } @@ -244,6 +237,18 @@ class FlxAtlasSprite extends FlxAnimate this.anim.goToFrameLabel(label); } + function getFrameLabelNames(?layer:haxe.extern.EitherType = null) + { + var labels = this.anim.getFrameLabels(layer); + var array = []; + for (label in labels) + { + array.push(label.name); + } + + return array; + } + function getNextFrameLabel(label:String):String { return listAnimations()[(getLabelIndex(label) + 1) % listAnimations().length]; @@ -272,7 +277,7 @@ class FlxAtlasSprite extends FlxAnimate { onAnimationFrame.dispatch(currentAnimation, frame); - if (fr != null && frame > (fr.index + fr.duration - 1) || isLoopFinished()) + if (fr != null && frame > (fr.index + fr.duration - 1) || isLoopComplete()) { anim.pause(); _onAnimationComplete(); diff --git a/source/funkin/modding/IScriptedClass.hx b/source/funkin/modding/IScriptedClass.hx index 5f2ff2b9e..14aa6b494 100644 --- a/source/funkin/modding/IScriptedClass.hx +++ b/source/funkin/modding/IScriptedClass.hx @@ -73,6 +73,22 @@ interface INoteScriptedClass extends IScriptedClass public function onNoteMiss(event:NoteScriptEvent):Void; } +/** + * Defines a set of callbacks available to scripted classes which represent sprites synced with the BPM. + */ +interface IBPMSyncedScriptedClass extends IScriptedClass +{ + /** + * Called once every step of the song. + */ + public function onStepHit(event:SongTimeScriptEvent):Void; + + /** + * Called once every beat of the song. + */ + public function onBeatHit(event:SongTimeScriptEvent):Void; +} + /** * Developer note: * @@ -86,7 +102,7 @@ interface INoteScriptedClass extends IScriptedClass /** * Defines a set of callbacks available to scripted classes that involve the lifecycle of the Play State. */ -interface IPlayStateScriptedClass extends INoteScriptedClass +interface IPlayStateScriptedClass extends INoteScriptedClass extends IBPMSyncedScriptedClass { /** * Called when the game is paused. @@ -136,16 +152,6 @@ interface IPlayStateScriptedClass extends INoteScriptedClass */ public function onSongEvent(event:SongEventScriptEvent):Void; - /** - * Called once every step of the song. - */ - public function onStepHit(event:SongTimeScriptEvent):Void; - - /** - * Called once every beat of the song. - */ - public function onBeatHit(event:SongTimeScriptEvent):Void; - /** * Called when the countdown of the song starts. */ diff --git a/source/funkin/modding/PolymodHandler.hx b/source/funkin/modding/PolymodHandler.hx index 52d4624cb..75c69e506 100644 --- a/source/funkin/modding/PolymodHandler.hx +++ b/source/funkin/modding/PolymodHandler.hx @@ -235,6 +235,10 @@ class PolymodHandler Polymod.addImportAlias('funkin.data.event.SongEventSchema', funkin.data.event.SongEventSchema.SongEventSchemaRaw); + // `lime.utils.Assets` literally just has a private `resolveClass` function for some reason? so we replace it with our own. + Polymod.addImportAlias('lime.utils.Assets', funkin.Assets); + Polymod.addImportAlias('openfl.utils.Assets', funkin.Assets); + // Add blacklisting for prohibited classes and packages. // `Sys` @@ -269,11 +273,6 @@ class PolymodHandler // System.load() can load malicious DLLs Polymod.blacklistImport('lime.system.System'); - // `lime.utils.Assets` - // Literally just has a private `resolveClass` function for some reason? - Polymod.blacklistImport('lime.utils.Assets'); - Polymod.blacklistImport('openfl.utils.Assets'); - // `openfl.desktop.NativeProcess` // Can load native processes on the host operating system. Polymod.blacklistImport('openfl.desktop.NativeProcess'); diff --git a/source/funkin/modding/events/ScriptEventDispatcher.hx b/source/funkin/modding/events/ScriptEventDispatcher.hx index c262c311d..7e19173c4 100644 --- a/source/funkin/modding/events/ScriptEventDispatcher.hx +++ b/source/funkin/modding/events/ScriptEventDispatcher.hx @@ -94,6 +94,21 @@ class ScriptEventDispatcher } } + if (Std.isOfType(target, IBPMSyncedScriptedClass)) + { + var t:IBPMSyncedScriptedClass = cast(target, IBPMSyncedScriptedClass); + switch (event.type) + { + case SONG_BEAT_HIT: + t.onBeatHit(cast event); + return; + case SONG_STEP_HIT: + t.onStepHit(cast event); + return; + default: // Continue; + } + } + if (Std.isOfType(target, IPlayStateScriptedClass)) { var t:IPlayStateScriptedClass = cast(target, IPlayStateScriptedClass); @@ -102,12 +117,6 @@ class ScriptEventDispatcher case NOTE_GHOST_MISS: t.onNoteGhostMiss(cast event); return; - case SONG_BEAT_HIT: - t.onBeatHit(cast event); - return; - case SONG_STEP_HIT: - t.onStepHit(cast event); - return; case SONG_START: t.onSongStart(event); return; diff --git a/source/funkin/ui/charSelect/CharSelectGF.hx b/source/funkin/ui/charSelect/CharSelectGF.hx index 2e0e3980c..ea7d41448 100644 --- a/source/funkin/ui/charSelect/CharSelectGF.hx +++ b/source/funkin/ui/charSelect/CharSelectGF.hx @@ -7,10 +7,12 @@ import flixel.math.FlxMath; import funkin.util.FramesJSFLParser; import funkin.util.FramesJSFLParser.FramesJSFLInfo; import funkin.util.FramesJSFLParser.FramesJSFLFrame; +import funkin.modding.IScriptedClass.IBPMSyncedScriptedClass; import flixel.math.FlxMath; +import funkin.modding.events.ScriptEvent; import funkin.vis.dsp.SpectralAnalyzer; -class CharSelectGF extends FlxAtlasSprite +class CharSelectGF extends FlxAtlasSprite implements IBPMSyncedScriptedClass { var fadeTimer:Float = 0; var fadingStatus:FadeStatus = OFF; @@ -54,6 +56,7 @@ class CharSelectGF extends FlxAtlasSprite default: } + #if FEATURE_DEBUG_FUNCTIONS if (FlxG.keys.justPressed.J) { alpha = 1; @@ -65,8 +68,27 @@ class CharSelectGF extends FlxAtlasSprite alpha = 0; fadingStatus = FADE_IN; } + #end } + public function onStepHit(event:SongTimeScriptEvent):Void {} + + var danceEvery:Int = 2; + + public function onBeatHit(event:SongTimeScriptEvent):Void + { + // TODO: There's a minor visual bug where there's a little stutter. + // This happens because the animation is getting restarted while it's already playing. + // I tried make this not interrupt an existing idle, + // but isAnimationFinished() and isLoopComplete() both don't work! What the hell? + // danceEvery isn't necessary if that gets fixed. + if (getCurrentAnimation() == "idle" && (event.beat % danceEvery == 0)) + { + trace('GF beat hit'); + playAnimation("idle", true, false, false); + } + }; + override public function draw() { if (analyzer != null) drawFFT(); @@ -160,18 +182,27 @@ class CharSelectGF extends FlxAtlasSprite } // We don't need to update any anims if we didn't change GF - if (prevGF == curGF) return; + if (prevGF != curGF) + { + loadAtlas(Paths.animateAtlas("charSelect/" + curGF + "Chill")); - loadAtlas(Paths.animateAtlas("charSelect/" + curGF + "Chill")); + animInInfo = FramesJSFLParser.parse(Paths.file("images/charSelect/" + curGF + "AnimInfo/" + curGF + "In.txt")); + animOutInfo = FramesJSFLParser.parse(Paths.file("images/charSelect/" + curGF + "AnimInfo/" + curGF + "Out.txt")); + } - animInInfo = FramesJSFLParser.parse(Paths.file("images/charSelect/" + curGF + "AnimInfo/" + curGF + "In.txt")); - animOutInfo = FramesJSFLParser.parse(Paths.file("images/charSelect/" + curGF + "AnimInfo/" + curGF + "Out.txt")); - - playAnimation("idle", true, false, true); + playAnimation("idle", true, false, false); // addFrameCallback(getNextFrameLabel("idle"), () -> playAnimation("idle", true, false, false)); updateHitbox(); } + + public function onScriptEvent(event:ScriptEvent):Void {}; + + public function onCreate(event:ScriptEvent):Void {}; + + public function onDestroy(event:ScriptEvent):Void {}; + + public function onUpdate(event:UpdateScriptEvent):Void {}; } enum FadeStatus diff --git a/source/funkin/ui/charSelect/CharSelectPlayer.hx b/source/funkin/ui/charSelect/CharSelectPlayer.hx index 07c82d038..8e94e25fe 100644 --- a/source/funkin/ui/charSelect/CharSelectPlayer.hx +++ b/source/funkin/ui/charSelect/CharSelectPlayer.hx @@ -3,8 +3,10 @@ package funkin.ui.charSelect; import flixel.FlxSprite; import funkin.graphics.adobeanimate.FlxAtlasSprite; import flxanimate.animate.FlxKeyFrame; +import funkin.modding.IScriptedClass.IBPMSyncedScriptedClass; +import funkin.modding.events.ScriptEvent; -class CharSelectPlayer extends FlxAtlasSprite +class CharSelectPlayer extends FlxAtlasSprite implements IBPMSyncedScriptedClass { var desLp:FlxKeyFrame = null; @@ -18,11 +20,20 @@ class CharSelectPlayer extends FlxAtlasSprite switch (animLabel) { case "slidein": - if (hasAnimation("slidein idle point")) playAnimation("slidein idle point", true, false, false); + if (hasAnimation("slidein idle point")) + { + playAnimation("slidein idle point", true, false, false); + } else - playAnimation("idle", true, false, true); + { + // Handled by onBeatHit now + playAnimation("idle", true, false, false); + } case "slidein idle point": - playAnimation("idle", true, false, true); + // Handled by onBeatHit now + playAnimation("idle", true, false, false); + case "idle": + trace('Waiting for onBeatHit'); } }); @@ -31,6 +42,22 @@ class CharSelectPlayer extends FlxAtlasSprite }); } + public function onStepHit(event:SongTimeScriptEvent):Void {} + + public function onBeatHit(event:SongTimeScriptEvent):Void + { + // TODO: There's a minor visual bug where there's a little stutter. + // This happens because the animation is getting restarted while it's already playing. + // I tried make this not interrupt an existing idle, + // but isAnimationFinished() and isLoopComplete() both don't work! What the hell? + // danceEvery isn't necessary if that gets fixed. + if (getCurrentAnimation() == "idle") + { + trace('Player beat hit'); + playAnimation("idle", true, false, false); + } + }; + public function updatePosition(str:String) { switch (str) @@ -61,4 +88,12 @@ class CharSelectPlayer extends FlxAtlasSprite updatePosition(str); } + + public function onScriptEvent(event:ScriptEvent):Void {}; + + public function onCreate(event:ScriptEvent):Void {}; + + public function onDestroy(event:ScriptEvent):Void {}; + + public function onUpdate(event:UpdateScriptEvent):Void {}; } diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index c2850916a..ccfe17a81 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -148,7 +148,7 @@ class CharSelectSubState extends MusicBeatSubState var stageSpr:FlxSprite = new FlxSprite(-40, 391); stageSpr.frames = Paths.getSparrowAtlas("charSelect/charSelectStage"); - stageSpr.animation.addByPrefix("idle", "stage", 24, true); + stageSpr.animation.addByPrefix("idle", "stage full instance 1", 24, true); stageSpr.animation.play("idle"); add(stageSpr); @@ -195,14 +195,14 @@ class CharSelectSubState extends MusicBeatSubState var dipshitBlur:FlxSprite = new FlxSprite(419, -65); dipshitBlur.frames = Paths.getSparrowAtlas("charSelect/dipshitBlur"); - dipshitBlur.animation.addByPrefix('idle', "CHOOSE vertical", 24, true); + dipshitBlur.animation.addByPrefix('idle', "CHOOSE vertical offset instance 1", 24, true); dipshitBlur.blend = BlendMode.ADD; dipshitBlur.animation.play("idle"); add(dipshitBlur); var dipshitBacking:FlxSprite = new FlxSprite(423, -17); dipshitBacking.frames = Paths.getSparrowAtlas("charSelect/dipshitBacking"); - dipshitBacking.animation.addByPrefix('idle', "CHOOSE horizontal", 24, true); + dipshitBacking.animation.addByPrefix('idle', "CHOOSE horizontal offset instance 1", 24, true); dipshitBacking.blend = BlendMode.ADD; dipshitBacking.animation.play("idle"); add(dipshitBacking); @@ -261,14 +261,14 @@ class CharSelectSubState extends MusicBeatSubState cursorConfirmed = new FlxSprite(0, 0); cursorConfirmed.scrollFactor.set(); cursorConfirmed.frames = Paths.getSparrowAtlas("charSelect/charSelectorConfirm"); - cursorConfirmed.animation.addByPrefix("idle", "cursor ACCEPTED", 24, true); + cursorConfirmed.animation.addByPrefix("idle", "cursor ACCEPTED instance 1", 24, true); cursorConfirmed.visible = false; add(cursorConfirmed); cursorDenied = new FlxSprite(0, 0); cursorDenied.scrollFactor.set(); cursorDenied.frames = Paths.getSparrowAtlas("charSelect/charSelectorDenied"); - cursorDenied.animation.addByPrefix("idle", "cursor DENIED", 24, false); + cursorDenied.animation.addByPrefix("idle", "cursor DENIED instance 1", 24, false); cursorDenied.visible = false; add(cursorDenied); @@ -289,8 +289,6 @@ class CharSelectSubState extends MusicBeatSubState FlxG.debugger.addTrackerProfile(new TrackerProfile(CharSelectSubState, ["curChar", "grpXSpread", "grpYSpread"])); FlxG.debugger.track(this); - FlxG.sound.playMusic(Paths.music('charSelect/charSelectMusic')); - camFollow = new FlxObject(0, 0, 1, 1); add(camFollow); camFollow.screenCenter(); @@ -567,6 +565,16 @@ class CharSelectSubState extends MusicBeatSubState cursorDarkBlue.y = MathUtil.coolLerp(cursorDarkBlue.y, cursorLocIntended.y, lerpAmnt * 0.2); } + public override function dispatchEvent(event:ScriptEvent):Void + { + // super.dispatchEvent(event) dispatches event to module scripts. + super.dispatchEvent(event); + + // Dispatch events (like onBeatHit) to props + ScriptEventDispatcher.callEvent(playerChill, event); + ScriptEventDispatcher.callEvent(gfChill, event); + } + function spamOnStep():Void { if (spamUp || spamDown || spamLeft || spamRight) diff --git a/source/funkin/ui/freeplay/FreeplayDJ.hx b/source/funkin/ui/freeplay/FreeplayDJ.hx index b1528d906..3ef00eb09 100644 --- a/source/funkin/ui/freeplay/FreeplayDJ.hx +++ b/source/funkin/ui/freeplay/FreeplayDJ.hx @@ -15,7 +15,9 @@ class FreeplayDJ extends FlxAtlasSprite { // Represents the sprite's current status. // Without state machines I would have driven myself crazy years ago. - public var currentState:FreeplayDJState = Intro; + // Made this PRIVATE so we can keep track of everything that can alter the state! + // Add a function to this class if you want to edit this value from outside. + private var currentState:FreeplayDJState = Intro; // A callback activated when the intro animation finishes. public var onIntroDone:FlxSignal = new FlxSignal(); @@ -378,7 +380,7 @@ class FreeplayDJ extends FlxAtlasSprite public function toCharSelect():Void { - if (hasAnimation('charSelect')) + if (hasAnimation(playableCharData.getAnimationPrefix('charSelect'))) { currentState = CharSelect; var animPrefix = playableCharData.getAnimationPrefix('charSelect'); diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index f0bad1718..4d6d8dc9d 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -224,12 +224,14 @@ class FreeplayState extends MusicBeatSubState { currentCharacterId = params?.character ?? rememberedCharacterId; var fetchPlayableCharacter = function():PlayableCharacter { - var result = PlayerRegistry.instance.fetchEntry(params?.character ?? rememberedCharacterId); - if (result == null) throw 'No valid playable character with id ${params?.character}'; + var targetCharId = params?.character ?? rememberedCharacterId; + var result = PlayerRegistry.instance.fetchEntry(targetCharId); + if (result == null) throw 'No valid playable character with id ${targetCharId}'; return result; }; currentCharacter = fetchPlayableCharacter(); + styleData = FreeplayStyleRegistry.instance.fetchEntry(currentCharacter.getFreeplayStyleID()); rememberedCharacterId = currentCharacter?.id ?? Constants.DEFAULT_CHARACTER; fromResultsParams = params?.fromResults; @@ -317,6 +319,9 @@ class FreeplayState extends MusicBeatSubState isDebug = true; #end + // Block input until the intro finishes. + busy = true; + // Add a null entry that represents the RANDOM option songs.push(null); @@ -645,13 +650,14 @@ class FreeplayState extends MusicBeatSubState // be careful not to "add()" things in here unless it's to a group that's already added to the state // otherwise it won't be properly attatched to funnyCamera (relavent code should be at the bottom of create()) var onDJIntroDone = function() { + busy = false; + // when boyfriend hits dat shiii albumRoll.playIntro(); var daSong = grpCapsules.members[curSelected].songData; albumRoll.albumId = daSong?.albumId; - FlxTween.tween(grpDifficulties, {x: 90}, 0.6, {ease: FlxEase.quartOut}); diffSelLeft.visible = true; @@ -1187,6 +1193,158 @@ class FreeplayState extends MusicBeatSubState }); } + function tryOpenCharSelect():Void + { + // Check if we have ACCESS to character select! + trace('Is Pico unlocked? ${PlayerRegistry.instance.fetchEntry('pico')?.isUnlocked()}'); + trace('Number of characters: ${PlayerRegistry.instance.countUnlockedCharacters()}'); + + if (PlayerRegistry.instance.countUnlockedCharacters() > 1) + { + trace('Opening character select!'); + } + else + { + trace('Not enough characters unlocked to open character select!'); + FunkinSound.playOnce(Paths.sound('cancelMenu')); + return; + } + + busy = true; + + FunkinSound.playOnce(Paths.sound('confirmMenu')); + + if (dj != null) + { + dj.toCharSelect(); + } + + // Get this character's transition delay, with a reasonable default. + var transitionDelay:Float = currentCharacter.getFreeplayDJData()?.getCharSelectTransitionDelay() ?? 0.25; + + new FlxTimer().start(transitionDelay, _ -> { + transitionToCharSelect(); + }); + } + + function transitionToCharSelect():Void + { + var transitionGradient = new FlxSprite(0, 720).loadGraphic(Paths.image('freeplay/transitionGradient')); + transitionGradient.scale.set(1280, 1); + transitionGradient.updateHitbox(); + transitionGradient.cameras = [rankCamera]; + exitMoversCharSel.set([transitionGradient], + { + y: -720, + speed: 0.8, + wait: 0.1 + }); + add(transitionGradient); + for (index => capsule in grpCapsules.members) + { + var distFromSelected:Float = Math.abs(index - curSelected) - 1; + if (distFromSelected < 5) + { + capsule.doLerp = false; + exitMoversCharSel.set([capsule], + { + y: -250, + speed: 0.8, + wait: 0.1 + }); + } + } + fadeShader.fade(1.0, 0.0, 0.8, {ease: FlxEase.quadIn}); + FlxG.sound.music.fadeOut(0.9, 0); + new FlxTimer().start(0.9, _ -> { + FlxG.switchState(new funkin.ui.charSelect.CharSelectSubState()); + }); + for (grpSpr in exitMoversCharSel.keys()) + { + var moveData:Null = exitMoversCharSel.get(grpSpr); + if (moveData == null) continue; + + for (spr in grpSpr) + { + if (spr == null) continue; + + var funnyMoveShit:MoveData = moveData; + + var moveDataY = funnyMoveShit.y ?? spr.y; + var moveDataSpeed = funnyMoveShit.speed ?? 0.2; + var moveDataWait = funnyMoveShit.wait ?? 0.0; + + FlxTween.tween(spr, {y: moveDataY + spr.y}, moveDataSpeed, {ease: FlxEase.backIn}); + } + } + backingCard?.enterCharSel(); + } + + function enterFromCharSel():Void + { + busy = true; + if (_parentState != null) _parentState.persistentDraw = false; + + var transitionGradient = new FlxSprite(0, 720).loadGraphic(Paths.image('freeplay/transitionGradient')); + transitionGradient.scale.set(1280, 1); + transitionGradient.updateHitbox(); + transitionGradient.cameras = [rankCamera]; + exitMoversCharSel.set([transitionGradient], + { + y: -720, + speed: 1.5, + wait: 0.1 + }); + add(transitionGradient); + // FlxTween.tween(transitionGradient, {alpha: 0}, 1, {ease: FlxEase.circIn}); + // for (index => capsule in grpCapsules.members) + // { + // var distFromSelected:Float = Math.abs(index - curSelected) - 1; + // if (distFromSelected < 5) + // { + // capsule.doLerp = false; + // exitMoversCharSel.set([capsule], + // { + // y: -250, + // speed: 0.8, + // wait: 0.1 + // }); + // } + // } + fadeShader.fade(0.0, 1.0, 0.8, {ease: FlxEase.quadIn}); + for (grpSpr in exitMoversCharSel.keys()) + { + var moveData:Null = exitMoversCharSel.get(grpSpr); + if (moveData == null) continue; + + for (spr in grpSpr) + { + if (spr == null) continue; + + var funnyMoveShit:MoveData = moveData; + + var moveDataY = funnyMoveShit.y ?? spr.y; + var moveDataSpeed = funnyMoveShit.speed ?? 0.2; + var moveDataWait = funnyMoveShit.wait ?? 0.0; + + spr.y += moveDataY; + FlxTween.tween(spr, {y: spr.y - moveDataY}, moveDataSpeed * 1.2, + { + ease: FlxEase.expoOut, + onComplete: function(_) { + for (index => capsule in grpCapsules.members) + { + capsule.doLerp = true; + fromCharSelect = false; + busy = false; + albumRoll.applyExitMovers(exitMovers, exitMoversCharSel); + } + } + }); + } + } + } + var touchY:Float = 0; var touchX:Float = 0; var dxTouch:Float = 0; @@ -1247,32 +1405,7 @@ class FreeplayState extends MusicBeatSubState if (controls.FREEPLAY_CHAR_SELECT && !busy) { - // Check if we have ACCESS to character select! - trace('Is Pico unlocked? ${PlayerRegistry.instance.fetchEntry('pico')?.isUnlocked()}'); - trace('Number of characters: ${PlayerRegistry.instance.countUnlockedCharacters()}'); - - if (PlayerRegistry.instance.countUnlockedCharacters() > 1) - { - if (dj != null) - { - busy = true; - // Transition to character select after animation - dj.onCharSelectComplete = function() { - FlxG.switchState(new funkin.ui.charSelect.CharSelectSubState()); - } - dj.toCharSelect(); - } - else - { - // Transition to character select immediately - FlxG.switchState(new funkin.ui.charSelect.CharSelectSubState()); - } - } - else - { - trace('Not enough characters unlocked to open character select!'); - FunkinSound.playOnce(Paths.sound('cancelMenu')); - } + tryOpenCharSelect(); } if (controls.FREEPLAY_FAVORITE && !busy) diff --git a/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx b/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx index d4dd7aaa4..85ecb4247 100644 --- a/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx +++ b/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx @@ -9,6 +9,7 @@ import funkin.play.scoring.Scoring.ScoringRank; * An object used to retrieve data about a playable character (also known as "weeks"). * Can be scripted to override each function, for custom behavior. */ +@:nullSafety class PlayableCharacter implements IRegistryEntry { /** @@ -19,7 +20,7 @@ class PlayableCharacter implements IRegistryEntry /** * Playable character data as parsed from the JSON file. */ - public final _data:PlayerData; + public final _data:Null; /** * @param id The ID of the JSON file to parse. @@ -41,7 +42,7 @@ class PlayableCharacter implements IRegistryEntry public function getName():String { // TODO: Maybe add localization support? - return _data.name; + return _data?.name ?? "Unknown"; } /** @@ -50,7 +51,7 @@ class PlayableCharacter implements IRegistryEntry */ public function getOwnedCharacterIds():Array { - return _data.ownedChars; + return _data?.ownedChars ?? []; } /** @@ -59,17 +60,17 @@ class PlayableCharacter implements IRegistryEntry */ public function shouldShowUnownedChars():Bool { - return _data.showUnownedChars; + return _data?.showUnownedChars ?? false; } public function shouldShowCharacter(id:String):Bool { - if (_data.ownedChars.contains(id)) + if (getOwnedCharacterIds().contains(id)) { return true; } - if (_data.showUnownedChars) + if (shouldShowUnownedChars()) { var result = !PlayerRegistry.instance.isCharacterOwned(id); return result; @@ -78,19 +79,25 @@ class PlayableCharacter implements IRegistryEntry return false; } - public function getFreeplayDJData():PlayerFreeplayDJData + public function getFreeplayStyleID():String { - return _data.freeplayDJ; + return _data?.freeplayStyle ?? Constants.DEFAULT_FREEPLAY_STYLE; + } + + public function getFreeplayDJData():Null + { + return _data?.freeplayDJ; } public function getFreeplayDJText(index:Int):String { - return _data.freeplayDJ.getFreeplayDJText(index); + // Silly little placeholder + return _data?.freeplayDJ?.getFreeplayDJText(index) ?? 'GET FREAKY ON A FRIDAY'; } - public function getCharSelectData():PlayerCharSelectData + public function getCharSelectData():Null { - return _data.charSelect; + return _data?.charSelect; } /** @@ -99,7 +106,7 @@ class PlayableCharacter implements IRegistryEntry */ public function getResultsAnimationDatas(rank:ScoringRank):Array { - if (_data.results == null) + if (_data == null || _data.results == null) { return []; } @@ -124,7 +131,7 @@ class PlayableCharacter implements IRegistryEntry */ public function isUnlocked():Bool { - return _data.unlocked; + return _data?.unlocked ?? true; } /** diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index c777e685b..d2a9f046a 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -110,7 +110,17 @@ class MainMenuState extends MusicBeatState FlxTransitionableState.skipNextTransIn = true; FlxTransitionableState.skipNextTransOut = true; - openSubState(new FreeplayState()); + #if FEATURE_DEBUG_FUNCTIONS + // Debug function: Hold SHIFT when selecting Freeplay to swap character without the char select menu + var targetCharacter:Null = (FlxG.keys.pressed.SHIFT) ? (FreeplayState.rememberedCharacterId == "pico" ? "bf" : "pico") : null; + #else + var targetCharacter:Null = null; + #end + + openSubState(new FreeplayState( + { + character: targetCharacter + })); }); #if CAN_OPEN_LINKS diff --git a/source/funkin/util/Constants.hx b/source/funkin/util/Constants.hx index fa03b229d..1653311df 100644 --- a/source/funkin/util/Constants.hx +++ b/source/funkin/util/Constants.hx @@ -258,6 +258,11 @@ class Constants */ public static final DEFAULT_NOTE_STYLE:String = 'funkin'; + /** + * The default freeplay style for characters. + */ + public static final DEFAULT_FREEPLAY_STYLE:String = 'bf'; + /** * The default pixel note style for songs. */ diff --git a/source/funkin/util/ReflectUtil.hx b/source/funkin/util/ReflectUtil.hx index 830edd31d..da98c820b 100644 --- a/source/funkin/util/ReflectUtil.hx +++ b/source/funkin/util/ReflectUtil.hx @@ -33,4 +33,19 @@ class ReflectUtil { return Type.getClassName(Type.getClass(obj)); } + + public static function getAnonymousFieldsOf(obj:Dynamic):Array + { + return Reflect.fields(obj); + } + + public static function getAnonymousField(obj:Dynamic, name:String):Dynamic + { + return Reflect.field(obj, name); + } + + public static function hasAnonymousField(obj:Dynamic, name:String):Bool + { + return Reflect.hasField(obj, name); + } } From cdc3883173634469be23f90603b50a1fb219d8fe Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sun, 1 Sep 2024 17:19:39 -0400 Subject: [PATCH 656/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 91877ca4d..0586aae55 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 91877ca4d17a319e8aa84234ab62c88269a8df39 +Subproject commit 0586aae5565e3707f232e05439f42c815e32aec8 From 2f59363432946d493cb580f9aa417f384a0e502c Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 3 Sep 2024 00:21:25 -0400 Subject: [PATCH 657/870] Merge branch 'bugfix/assets-cleanup' into develop-2 --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 67c2375ef..114dce37b 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 67c2375ef0d6e8d48dea50bc17e8252219c05a97 +Subproject commit 114dce37bab3938eebf788910cde60140dd7562f From d049478c65eae793b61f2b8cb4ff1b998c6bcc26 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Tue, 3 Sep 2024 19:16:46 +0100 Subject: [PATCH 658/870] registry updates --- source/funkin/data/stage/StageRegistry.hx | 2 +- source/funkin/ui/debug/charting/ChartEditorState.hx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/data/stage/StageRegistry.hx b/source/funkin/data/stage/StageRegistry.hx index 7754c380e..3d3779bce 100644 --- a/source/funkin/data/stage/StageRegistry.hx +++ b/source/funkin/data/stage/StageRegistry.hx @@ -94,7 +94,7 @@ class StageRegistry extends BaseRegistry { return [ "mainStage", "mainStageErect", "spookyMansion", "phillyTrain", "phillyTrainErect", "limoRide", "limoRideErect", "mallXmas", "mallEvil", "school", - "schoolEvil", "tankmanBattlefield", "phillyStreets", "phillyBlazin", + "schoolEvil", "tankmanBattlefield", "phillyStreets", "phillyStreetsErect", "phillyBlazin", ]; } diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index a1d7aca6b..20d39183b 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -5713,7 +5713,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState PlayStatePlaylist.campaignId = 'week6'; case 'tankmanBattlefield': PlayStatePlaylist.campaignId = 'week7'; - case 'phillyStreets' | 'phillyBlazin' | 'phillyBlazin2': + case 'phillyStreets' | 'phillyStreetsErect' | 'phillyBlazin' | 'phillyBlazin2': PlayStatePlaylist.campaignId = 'weekend1'; } Paths.setCurrentLevel(PlayStatePlaylist.campaignId); From b58bd07fd266474d8af2345b6318cf6ac93f1508 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Tue, 3 Sep 2024 19:16:58 +0100 Subject: [PATCH 659/870] rain shader recolor support --- source/funkin/graphics/shaders/RuntimeRainShader.hx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/source/funkin/graphics/shaders/RuntimeRainShader.hx b/source/funkin/graphics/shaders/RuntimeRainShader.hx index 68a203179..d0c036623 100644 --- a/source/funkin/graphics/shaders/RuntimeRainShader.hx +++ b/source/funkin/graphics/shaders/RuntimeRainShader.hx @@ -4,6 +4,7 @@ import flixel.system.FlxAssets.FlxShader; import openfl.display.BitmapData; import openfl.display.ShaderParameter; import openfl.display.ShaderParameterType; +import flixel.util.FlxColor; import openfl.utils.Assets; typedef Light = @@ -94,6 +95,14 @@ class RuntimeRainShader extends RuntimePostEffectShader return mask = value; } + public var rainColor(default, set):FlxColor; + + function set_rainColor(color:FlxColor):FlxColor + { + this.setFloatArray("uRainColor", [color.red / 255, color.green / 255, color.blue / 255]); + return rainColor = color; + } + public var lightMap(default, set):BitmapData; function set_lightMap(value:BitmapData):BitmapData @@ -113,6 +122,7 @@ class RuntimeRainShader extends RuntimePostEffectShader public function new() { super(Assets.getText(Paths.frag('rain'))); + this.rainColor = 0xFF6680cc; } public function update(elapsed:Float):Void From f16bffb3fcf5bf18b3d59de7dd6c7325772f7bf0 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Tue, 3 Sep 2024 19:19:25 +0100 Subject: [PATCH 660/870] assets submod..................... --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 5a0c8da32..e80d92ac4 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 5a0c8da32111571648b8fd07deabe2f78ae99eaa +Subproject commit e80d92ac484fe432ab34d45b22158f5d565afb0f From 36505f75c1cdfb7597b0ce5b0d180aecb6440fa3 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 3 Sep 2024 21:14:57 -0400 Subject: [PATCH 661/870] The actual code for custom freeplay music LOL --- CHANGELOG.md | 18 ++++++++- source/funkin/Assets.hx | 38 +++++++++++++++++++ .../funkin/data/freeplay/player/PlayerData.hx | 23 +++++++++++ source/funkin/play/ResultState.hx | 13 +++++-- source/funkin/play/scoring/Scoring.hx | 34 ----------------- source/funkin/ui/freeplay/FreeplayDJ.hx | 1 + .../freeplay/charselect/PlayableCharacter.hx | 21 ++++++++++ 7 files changed, 108 insertions(+), 40 deletions(-) create mode 100644 source/funkin/Assets.hx diff --git a/CHANGELOG.md b/CHANGELOG.md index 53e981284..22a36fa8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,14 +4,28 @@ 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.5.0] - 2024-08-?? +## [0.5.0] - 2024-09-12 ### Added - Added a new Character Select screen to switch between playable characters in Freeplay - Modding isn't 100% there but we're working on it! - Added Pico as a playable character! Unlock him by completing Weekend 1 (if you haven't already done that) - The songs from Weekend 1 have moved; you must now switch to Pico in Freeplay to access them -- Added ## new Pico remixes! Access them by selecting Pico from in the Character Select screen +- Added 10 new Pico remixes! Access them by selecting Pico from in the Character Select screen + - Bopeebo (Pico Mix) + - Fresh (Pico Mix) + - DadBattle (Pico Mix) + - Spookeez (Pico Mix) + - South (Pico Mix) + - Philly Nice (Pico Mix) + - Blammed (Pico Mix) + - Eggnog (Pico Mix) + - Ugh (Pico Mix) + - Guns (Pico Mix) +- Added 1 new Boyfriend remix! Access it by selecting Pico from in the Character Select screen + - Darnell (BF Mix) - Added 2 new Erect remixes! Access them by switching difficulty on the song + - Cocoa Erect + - Ugh Erect - Implemented support for a new Instrumental Selector in Freeplay - Beating a Pico remix lets you use that instrumental when playing as Boyfriend - Added the first batch of Erect Stages! These graphical overhauls of the original stages will be used when playing Erect remixes and Pico remixes diff --git a/source/funkin/Assets.hx b/source/funkin/Assets.hx new file mode 100644 index 000000000..5351676d4 --- /dev/null +++ b/source/funkin/Assets.hx @@ -0,0 +1,38 @@ +package funkin; + +/** + * A wrapper around `openfl.utils.Assets` which disallows access to the harmful functions. + * Later we'll add Funkin-specific caching to this. + */ +class Assets +{ + public static function getText(path:String):String + { + return openfl.utils.Assets.getText(path); + } + + public static function getMusic(path:String):openfl.media.Sound + { + return openfl.utils.Assets.getMusic(path); + } + + public static function getBitmapData(path:String):openfl.display.BitmapData + { + return openfl.utils.Assets.getBitmapData(path); + } + + public static function getBytes(path:String):haxe.io.Bytes + { + return openfl.utils.Assets.getBytes(path); + } + + public static function exists(path:String, ?type:openfl.utils.AssetType):Bool + { + return openfl.utils.Assets.exists(path, type); + } + + public static function list(type:openfl.utils.AssetType):Array + { + return openfl.utils.Assets.list(type); + } +} diff --git a/source/funkin/data/freeplay/player/PlayerData.hx b/source/funkin/data/freeplay/player/PlayerData.hx index 55657ba46..fa72f497b 100644 --- a/source/funkin/data/freeplay/player/PlayerData.hx +++ b/source/funkin/data/freeplay/player/PlayerData.hx @@ -253,6 +253,8 @@ class PlayerCharSelectData typedef PlayerResultsData = { + var music:PlayerResultsMusicData; + var perfect:Array; var excellent:Array; var great:Array; @@ -260,6 +262,27 @@ typedef PlayerResultsData = var loss:Array; }; +typedef PlayerResultsMusicData = +{ + @:optional + var PERFECT_GOLD:String; + + @:optional + var PERFECT:String; + + @:optional + var EXCELLENT:String; + + @:optional + var GREAT:String; + + @:optional + var GOOD:String; + + @:optional + var SHIT:String; +} + typedef PlayerResultsAnimationData = { /** diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index b1ff69a3a..ec6069ad4 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -404,12 +404,12 @@ class ResultState extends MusicBeatSubState // } new FlxTimer().start(rank.getMusicDelay(), _ -> { - if (rank.hasMusicIntro()) + var introMusic:String = Paths.music(getMusicPath(playerCharacter, rank) + '/' + getMusicPath(playerCharacter, rank) + '-intro'); + if (Assets.exists(introMusic)) { // 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(), + FunkinSound.playMusic(getMusicPath(playerCharacter, rank), { startingVolume: 1.0, overrideExisting: true, @@ -420,7 +420,7 @@ class ResultState extends MusicBeatSubState } else { - FunkinSound.playMusic(rank.getMusicPath(), + FunkinSound.playMusic(getMusicPath(playerCharacter, rank), { startingVolume: 1.0, overrideExisting: true, @@ -441,6 +441,11 @@ class ResultState extends MusicBeatSubState super.create(); } + function getMusicPath(playerCharacter:Null, rank:ScoringRank):String + { + return playerCharacter?.getResultsMusicPath(rank) ?? 'resultsNORMAL'; + } + var rankTallyTimer:Null = null; var clearPercentTarget:Int = 100; var clearPercentLerp:Int = 0; diff --git a/source/funkin/play/scoring/Scoring.hx b/source/funkin/play/scoring/Scoring.hx index 02e5750bc..6c9f9bd97 100644 --- a/source/funkin/play/scoring/Scoring.hx +++ b/source/funkin/play/scoring/Scoring.hx @@ -556,40 +556,6 @@ enum abstract ScoringRank(String) } } - 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():String { switch (abstract) diff --git a/source/funkin/ui/freeplay/FreeplayDJ.hx b/source/funkin/ui/freeplay/FreeplayDJ.hx index b1528d906..3ae0361ce 100644 --- a/source/funkin/ui/freeplay/FreeplayDJ.hx +++ b/source/funkin/ui/freeplay/FreeplayDJ.hx @@ -386,6 +386,7 @@ class FreeplayDJ extends FlxAtlasSprite } else { + FlxG.log.warn("Freeplay character does not have 'charSelect' animation!"); currentState = Confirm; // Call this immediately; otherwise, we get locked out of Character Select. onCharSelectComplete(); diff --git a/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx b/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx index d4dd7aaa4..09d9fd664 100644 --- a/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx +++ b/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx @@ -119,6 +119,27 @@ class PlayableCharacter implements IRegistryEntry } } + public function getResultsMusicPath(rank:ScoringRank):String + { + switch (rank) + { + case PERFECT_GOLD: + return _data?.results?.music?.PERFECT_GOLD ?? "resultsPERFECT"; + case PERFECT: + return _data?.results?.music?.PERFECT ?? "resultsPERFECT"; + case EXCELLENT: + return _data?.results?.music?.EXCELLENT ?? "resultsEXCELLENT"; + case GREAT: + return _data?.results?.music?.GREAT ?? "resultsNORMAL"; + case GOOD: + return _data?.results?.music?.GOOD ?? "resultsNORMAL"; + case SHIT: + return _data?.results?.music?.SHIT ?? "resultsSHIT"; + default: + return _data?.results?.music?.GOOD ?? "resultsNORMAL"; + } + } + /** * Returns whether this character is unlocked. */ From b37ebf1aacfb6a655a40f81b9f5bda068fd52bb1 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 3 Sep 2024 23:57:01 -0400 Subject: [PATCH 662/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 6857c7c89..0250e6718 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 6857c7c8999f02b595098fc36a2e1026cc0a22dd +Subproject commit 0250e67186915094244615fe10db549ba7bc59d7 From 0a6350113e81ff935c991b2bd9b4703e348cc043 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 26 Aug 2024 21:24:46 -0400 Subject: [PATCH 663/870] Fix some issues with Blazin --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 0250e6718..8156c2d4b 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 0250e67186915094244615fe10db549ba7bc59d7 +Subproject commit 8156c2d4b356a9e4b12a0275a82e58c84b65c4c3 From 3a2ca6b52506d64df01a0e42e3cadc8801c4fa46 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 26 Aug 2024 21:25:04 -0400 Subject: [PATCH 664/870] Code changes to fix Blazin' --- .../funkin/graphics/adobeanimate/FlxAtlasSprite.hx | 6 ++++++ .../funkin/play/character/AnimateAtlasCharacter.hx | 6 +++++- source/funkin/play/components/PopUpStuff.hx | 14 ++++++++++++-- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx index c4eaaff50..e187c7808 100644 --- a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx +++ b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx @@ -56,6 +56,12 @@ class FlxAtlasSprite extends FlxAnimate throw 'Null path specified for FlxAtlasSprite!'; } + // Validate asset path. + if (!Assets.exists('${path}/Animation.json')) + { + throw 'FlxAtlasSprite does not have an Animation.json file at the specified path (${path})'; + } + super(x, y, path, settings); if (this.anim.stageInstance == null) diff --git a/source/funkin/play/character/AnimateAtlasCharacter.hx b/source/funkin/play/character/AnimateAtlasCharacter.hx index 32a4e765c..5cc603429 100644 --- a/source/funkin/play/character/AnimateAtlasCharacter.hx +++ b/source/funkin/play/character/AnimateAtlasCharacter.hx @@ -129,7 +129,11 @@ class AnimateAtlasCharacter extends BaseCharacter { trace('[ATLASCHAR] Loading sprite atlas for ${characterId}.'); - var sprite:FlxAtlasSprite = new FlxAtlasSprite(0, 0, Paths.animateAtlas(_data.assetPath)); + var animLibrary:String = Paths.getLibrary(_data.assetPath); + var animPath:String = Paths.stripLibrary(_data.assetPath); + var assetPath:String = Paths.animateAtlas(animPath, animLibrary); + + var sprite:FlxAtlasSprite = new FlxAtlasSprite(0, 0, assetPath); // sprite.onAnimationComplete.removeAll(); sprite.onAnimationComplete.add(this.onAnimationFinished); diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx index 911c3578c..a02291e4e 100644 --- a/source/funkin/play/components/PopUpStuff.hx +++ b/source/funkin/play/components/PopUpStuff.hx @@ -21,6 +21,12 @@ class PopUpStuff extends FlxTypedGroup */ var noteStyle:NoteStyle; + /** + * Offsets that are applied to all elements, independent of the note style. + * Used to allow scripts to reposition the elements. + */ + var offsets:Array = [0, 0]; + override public function new(noteStyle:NoteStyle) { super(); @@ -42,9 +48,11 @@ class PopUpStuff extends FlxTypedGroup rating.y = (FlxG.camera.height * 0.45 - 60); rating.y -= rating.height / 2; - var offsets = noteStyle.getJudgementSpriteOffsets(daRating); rating.x += offsets[0]; rating.y += offsets[1]; + var styleOffsets = noteStyle.getJudgementSpriteOffsets(daRating); + rating.x += styleOffsets[0]; + rating.y += styleOffsets[1]; rating.acceleration.y = 550; rating.velocity.y -= FlxG.random.int(140, 175); @@ -90,9 +98,11 @@ class PopUpStuff extends FlxTypedGroup trace('numScore($daLoop) = ${numScore.x}'); numScore.y = (FlxG.camera.height * 0.44); - var offsets = noteStyle.getComboNumSpriteOffsets(digit); numScore.x += offsets[0]; numScore.y += offsets[1]; + var styleOffsets = noteStyle.getComboNumSpriteOffsets(digit); + numScore.x += styleOffsets[0]; + numScore.y += styleOffsets[1]; numScore.acceleration.y = FlxG.random.int(250, 300); numScore.velocity.y -= FlxG.random.int(130, 150); From 24096bd319c10aa150c9a8fcd578fbb812e14045 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 4 Sep 2024 10:58:18 -0400 Subject: [PATCH 665/870] Fixed positioning in Blazin'. --- assets | 2 +- source/funkin/audio/visualize/ABotVis.hx | 4 +++- source/funkin/play/character/AnimateAtlasCharacter.hx | 2 +- source/funkin/ui/charSelect/CharSelectGF.hx | 4 +++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/assets b/assets index 8156c2d4b..bbf8c7d53 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 8156c2d4b356a9e4b12a0275a82e58c84b65c4c3 +Subproject commit bbf8c7d53b7560c7440efd4fb8b1d5cfa17e56b9 diff --git a/source/funkin/audio/visualize/ABotVis.hx b/source/funkin/audio/visualize/ABotVis.hx index a6ad0570e..4d2243b7c 100644 --- a/source/funkin/audio/visualize/ABotVis.hx +++ b/source/funkin/audio/visualize/ABotVis.hx @@ -102,7 +102,9 @@ class ABotVis extends FlxTypedSpriteGroup var animFrame:Int = Math.round(levels[i].value * 5); #if desktop - animFrame = Math.round(animFrame * FlxG.sound.volume); + // Web version scales with the Flixel volume level. + // This line brings platform parity but looks worse. + // animFrame = Math.round(animFrame * FlxG.sound.volume); #end animFrame = Math.floor(Math.min(5, animFrame)); diff --git a/source/funkin/play/character/AnimateAtlasCharacter.hx b/source/funkin/play/character/AnimateAtlasCharacter.hx index 5cc603429..f432d08a0 100644 --- a/source/funkin/play/character/AnimateAtlasCharacter.hx +++ b/source/funkin/play/character/AnimateAtlasCharacter.hx @@ -122,7 +122,7 @@ class AnimateAtlasCharacter extends BaseCharacter */ public override function isAnimationFinished():Bool { - return mainSprite.isAnimationFinished(); + return mainSprite?.isAnimationFinished() ?? false; } function loadAtlasSprite():FlxAtlasSprite diff --git a/source/funkin/ui/charSelect/CharSelectGF.hx b/source/funkin/ui/charSelect/CharSelectGF.hx index ea7d41448..a990db817 100644 --- a/source/funkin/ui/charSelect/CharSelectGF.hx +++ b/source/funkin/ui/charSelect/CharSelectGF.hx @@ -109,7 +109,9 @@ class CharSelectGF extends FlxAtlasSprite implements IBPMSyncedScriptedClass var animFrame:Int = Math.round(levels[i].value * 12); #if desktop - animFrame = Math.round(animFrame * FlxG.sound.volume); + // Web version scales with the Flixel volume level. + // This line brings platform parity but looks worse. + // animFrame = Math.round(animFrame * FlxG.sound.volume); #end animFrame = Math.floor(Math.min(12, animFrame)); From def2b64a417470322a8b26e22734258795270555 Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Wed, 4 Sep 2024 20:08:38 +0200 Subject: [PATCH 666/870] Add lock bizz --- assets | 2 +- project/lib/harfbuzz | 1 + project/lib/hashlink | 1 + project/lib/jpeg | 1 + project/lib/lzma | 1 + project/lib/mbedtls | 1 + project/lib/mojoal | 1 + project/lib/neko | 1 + project/lib/ogg | 1 + project/lib/openal | 1 + project/lib/pixman | 1 + project/lib/png | 1 + project/lib/sdl | 1 + project/lib/tinyfiledialogs | 1 + project/lib/vorbis | 1 + project/lib/vpx | 1 + project/lib/webm | 1 + project/lib/zlib | 1 + .../ui/charSelect/CharSelectSubState.hx | 29 ++++++--------- source/funkin/ui/charSelect/Lock.hx | 35 +++++++++++++++++++ 20 files changed, 64 insertions(+), 19 deletions(-) create mode 160000 project/lib/harfbuzz create mode 160000 project/lib/hashlink create mode 160000 project/lib/jpeg create mode 160000 project/lib/lzma create mode 160000 project/lib/mbedtls create mode 160000 project/lib/mojoal create mode 160000 project/lib/neko create mode 160000 project/lib/ogg create mode 160000 project/lib/openal create mode 160000 project/lib/pixman create mode 160000 project/lib/png create mode 160000 project/lib/sdl create mode 160000 project/lib/tinyfiledialogs create mode 160000 project/lib/vorbis create mode 160000 project/lib/vpx create mode 160000 project/lib/webm create mode 160000 project/lib/zlib create mode 100644 source/funkin/ui/charSelect/Lock.hx diff --git a/assets b/assets index 5a0c8da32..74bd0131b 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 5a0c8da32111571648b8fd07deabe2f78ae99eaa +Subproject commit 74bd0131b705e87f9704c54a44d64579153ab4af diff --git a/project/lib/harfbuzz b/project/lib/harfbuzz new file mode 160000 index 000000000..2ba0b9ee9 --- /dev/null +++ b/project/lib/harfbuzz @@ -0,0 +1 @@ +Subproject commit 2ba0b9ee94e4fdea5c3e9d20fa73eb893c0bb95e diff --git a/project/lib/hashlink b/project/lib/hashlink new file mode 160000 index 000000000..9888913ed --- /dev/null +++ b/project/lib/hashlink @@ -0,0 +1 @@ +Subproject commit 9888913ed2e1eef9fc03085100c92bd44985c781 diff --git a/project/lib/jpeg b/project/lib/jpeg new file mode 160000 index 000000000..5cf796067 --- /dev/null +++ b/project/lib/jpeg @@ -0,0 +1 @@ +Subproject commit 5cf79606784f0616590e6a3a7fdf17ad32a6df9b diff --git a/project/lib/lzma b/project/lib/lzma new file mode 160000 index 000000000..5748ce6ad --- /dev/null +++ b/project/lib/lzma @@ -0,0 +1 @@ +Subproject commit 5748ce6ad668bb10e1a1fe322b37245d0053e71a diff --git a/project/lib/mbedtls b/project/lib/mbedtls new file mode 160000 index 000000000..ab0af45d1 --- /dev/null +++ b/project/lib/mbedtls @@ -0,0 +1 @@ +Subproject commit ab0af45d11db04bd6e42ccfabe1b8d8deaae3243 diff --git a/project/lib/mojoal b/project/lib/mojoal new file mode 160000 index 000000000..a9e2f30b0 --- /dev/null +++ b/project/lib/mojoal @@ -0,0 +1 @@ +Subproject commit a9e2f30b04f10df1912d06ff5a610edda4677ba5 diff --git a/project/lib/neko b/project/lib/neko new file mode 160000 index 000000000..d8a3b4638 --- /dev/null +++ b/project/lib/neko @@ -0,0 +1 @@ +Subproject commit d8a3b463861779656a78c1a5e31c013580642185 diff --git a/project/lib/ogg b/project/lib/ogg new file mode 160000 index 000000000..db5c7a49c --- /dev/null +++ b/project/lib/ogg @@ -0,0 +1 @@ +Subproject commit db5c7a49ce7ebda47b15b78471e78fb7f2483e22 diff --git a/project/lib/openal b/project/lib/openal new file mode 160000 index 000000000..326133368 --- /dev/null +++ b/project/lib/openal @@ -0,0 +1 @@ +Subproject commit 326133368c3d7149d0ab4a98fc96f654553094a7 diff --git a/project/lib/pixman b/project/lib/pixman new file mode 160000 index 000000000..0cb4fbe32 --- /dev/null +++ b/project/lib/pixman @@ -0,0 +1 @@ +Subproject commit 0cb4fbe3241988a5d6b51d3551998ec6837c75a1 diff --git a/project/lib/png b/project/lib/png new file mode 160000 index 000000000..e4a31f024 --- /dev/null +++ b/project/lib/png @@ -0,0 +1 @@ +Subproject commit e4a31f024b6158aaaf55a43502f574d5f5d1c894 diff --git a/project/lib/sdl b/project/lib/sdl new file mode 160000 index 000000000..8ea38ebed --- /dev/null +++ b/project/lib/sdl @@ -0,0 +1 @@ +Subproject commit 8ea38ebedc846faa547693f60bcd213b21370982 diff --git a/project/lib/tinyfiledialogs b/project/lib/tinyfiledialogs new file mode 160000 index 000000000..4927ea8f4 --- /dev/null +++ b/project/lib/tinyfiledialogs @@ -0,0 +1 @@ +Subproject commit 4927ea8f44fa0151dc8e0a2b79a13dbd7827cc48 diff --git a/project/lib/vorbis b/project/lib/vorbis new file mode 160000 index 000000000..84c023699 --- /dev/null +++ b/project/lib/vorbis @@ -0,0 +1 @@ +Subproject commit 84c023699cdf023a32fa4ded32019f194afcdad0 diff --git a/project/lib/vpx b/project/lib/vpx new file mode 160000 index 000000000..fbf63dff1 --- /dev/null +++ b/project/lib/vpx @@ -0,0 +1 @@ +Subproject commit fbf63dff1f528d44f24bd662abb89fd01a4a1c25 diff --git a/project/lib/webm b/project/lib/webm new file mode 160000 index 000000000..6c1e511f4 --- /dev/null +++ b/project/lib/webm @@ -0,0 +1 @@ +Subproject commit 6c1e511f487eaea026d94d0c6494a617155b5cfb diff --git a/project/lib/zlib b/project/lib/zlib new file mode 160000 index 000000000..545f19496 --- /dev/null +++ b/project/lib/zlib @@ -0,0 +1 @@ +Subproject commit 545f1949635949159fa6282e81712aec32b5d4f1 diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index c2850916a..1a27d0392 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -331,21 +331,8 @@ class CharSelectSubState extends MusicBeatSubState } else { - var temp:FlxSprite = new FlxSprite(); + var temp:Lock = new Lock(0, 0, i); temp.ID = 1; - temp.frames = Paths.getSparrowAtlas("charSelect/locks"); - - var lockIndex:Int = i + 1; - - if (i == 3) lockIndex = 3; - - if (i >= 4) lockIndex = i - 2; - - temp.animation.addByIndices("idle", "LOCK FULL " + lockIndex + " instance 1", [0], "", 24); - temp.animation.addByIndices("selected", "LOCK FULL " + lockIndex + " instance 1", [3, 4, 5], "", 24, false); - temp.animation.addByIndices("clicked", "LOCK FULL " + lockIndex + " instance 1", [9, 10, 11, 12, 13, 14, 15], "", 24, false); - - temp.animation.play("idle"); grpIcons.add(temp); } @@ -569,6 +556,11 @@ class CharSelectSubState extends MusicBeatSubState function spamOnStep():Void { + if (FlxG.keys.justPressed.B) + { + cursorY = 3; + cursorX = 3; + } if (spamUp || spamDown || spamLeft || spamRight) { // selectSound.changePitchBySemitone(1); @@ -605,19 +597,20 @@ class CharSelectSubState extends MusicBeatSubState switch (member.ID) { case 1: + var lock:Lock = cast member; if (index == getCurrentSelected()) { - switch (member.animation.curAnim.name) + switch (lock.getCurrentAnimation()) { case "idle": - member.animation.play("selected"); + lock.playAnimation("selected"); case "selected" | "clicked": - if (controls.ACCEPT) member.animation.play("clicked", true); + if (controls.ACCEPT) lock.playAnimation((FlxG.keys.pressed.CONTROL) ? "unlock" : "clicked", true); } } else { - member.animation.play("idle"); + lock.playAnimation("idle"); } case 0: var memb:PixelatedIcon = cast member; diff --git a/source/funkin/ui/charSelect/Lock.hx b/source/funkin/ui/charSelect/Lock.hx new file mode 100644 index 000000000..42e5d63f4 --- /dev/null +++ b/source/funkin/ui/charSelect/Lock.hx @@ -0,0 +1,35 @@ +package funkin.ui.charSelect; + +import flixel.util.FlxColor; +import flxanimate.effects.FlxTint; +import funkin.graphics.adobeanimate.FlxAtlasSprite; + +class Lock extends FlxAtlasSprite +{ + var colors:Array = [ + 0x31F2A5, 0x20ECCD, 0x24D9E8, + 0x20ECCD, 0x20C8D4, 0x209BDD, + 0x209BDD, 0x2362C9, 0x243FB9 + ]; // lock colors, in a nx3 matrix format + + public function new(x:Float = 0, y:Float = 0, index:Int) + { + super(x, y, Paths.animateAtlas("charSelect/lock")); + + var tint:FlxTint = new FlxTint(colors[index], 1); + + var arr:Array = ["lock", "lock top 1", "lock top 2", "lock top 3", "lock base fuck it"]; + + onAnimationComplete.add((_) -> if (_ == "unlock") playAnimation("idle")); + var func = function(name) { + var symbol = anim.symbolDictionary[name]; + if (symbol != null && symbol.timeline.get("color") != null) symbol.timeline.get("color").get(0).colorEffect = tint; + } + for (symbol in arr) + { + func(symbol); + } + + playAnimation("idle"); + } +} From 33aaabe190ce4469a221f2113d62cc1a77aac648 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 5 Sep 2024 01:22:45 -0400 Subject: [PATCH 667/870] lil console command helper for camera zoom --- source/funkin/play/PlayState.hx | 65 ++++++++++++++++----------- source/funkin/ui/MusicBeatSubState.hx | 4 ++ 2 files changed, 43 insertions(+), 26 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 414c833ff..0b2b8846d 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -503,6 +503,12 @@ class PlayState extends MusicBeatSubState */ public var camGame:FlxCamera; + /** + * Simple helper debug variable, to be able to move the camera around for debug purposes + * without worrying about the camera tweening back to the follow point. + */ + public var debugUnbindCameraZoom:Bool = false; + /** * The camera which contains, and controls visibility of, a video cutscene, dialogue, pause menu and sticker transition. */ @@ -992,7 +998,7 @@ class PlayState extends MusicBeatSubState { cameraBopMultiplier = FlxMath.lerp(1.0, cameraBopMultiplier, 0.95); // Lerp bop multiplier back to 1.0x var zoomPlusBop = currentCameraZoom * cameraBopMultiplier; // Apply camera bop multiplier. - FlxG.camera.zoom = zoomPlusBop; // Actually apply the zoom to the camera. + if (!debugUnbindCameraZoom) FlxG.camera.zoom = zoomPlusBop; // Actually apply the zoom to the camera. camHUD.zoom = FlxMath.lerp(defaultHUDCameraZoom, camHUD.zoom, 0.95); } @@ -1458,6 +1464,13 @@ class PlayState extends MusicBeatSubState super.destroy(); } + public override function initConsoleHelpers():Void + { + FlxG.console.registerFunction("debugUnbindCameraZoom", () -> { + debugUnbindCameraZoom = !debugUnbindCameraZoom; + }); + }; + /** * Initializes the game and HUD cameras. */ @@ -2224,10 +2237,10 @@ class PlayState extends MusicBeatSubState // Skip handling the miss in botplay! if (!isBotPlayMode) { - // Judge the miss. - // NOTE: This is what handles the scoring. - trace('Missed note! ${note.noteData}'); - onNoteMiss(note, event.playSound, event.healthChange); + // Judge the miss. + // NOTE: This is what handles the scoring. + trace('Missed note! ${note.noteData}'); + onNoteMiss(note, event.playSound, event.healthChange); } note.handledMiss = true; @@ -2344,31 +2357,31 @@ class PlayState extends MusicBeatSubState playerStrumline.playPress(input.noteDirection); trace('PENALTY Score: ${songScore}'); } - else if (notesInDirection.length == 0) - { - // Press a key with no penalty. + 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 - { - // Choose the first note, deprioritizing low priority notes. - var targetNote:Null = notesInDirection.find((note) -> !note.lowPriority); - if (targetNote == null) targetNote = notesInDirection[0]; - if (targetNote == null) continue; + // Play the strumline animation. + playerStrumline.playPress(input.noteDirection); + trace('NO PENALTY Score: ${songScore}'); + } + else + { + // Choose the first note, deprioritizing low priority notes. + var targetNote:Null = notesInDirection.find((note) -> !note.lowPriority); + if (targetNote == null) targetNote = notesInDirection[0]; + if (targetNote == null) continue; - // Judge and hit the note. - trace('Hit note! ${targetNote.noteData}'); - goodNoteHit(targetNote, input); - trace('Score: ${songScore}'); + // Judge and hit the note. + trace('Hit note! ${targetNote.noteData}'); + goodNoteHit(targetNote, input); + trace('Score: ${songScore}'); - notesInDirection.remove(targetNote); + notesInDirection.remove(targetNote); - // Play the strumline animation. - playerStrumline.playConfirm(input.noteDirection); - } + // Play the strumline animation. + playerStrumline.playConfirm(input.noteDirection); + } } while (inputReleaseQueue.length > 0) diff --git a/source/funkin/ui/MusicBeatSubState.hx b/source/funkin/ui/MusicBeatSubState.hx index 5c40b37bc..02cebeb45 100644 --- a/source/funkin/ui/MusicBeatSubState.hx +++ b/source/funkin/ui/MusicBeatSubState.hx @@ -56,6 +56,8 @@ class MusicBeatSubState extends FlxSubState implements IEventHandler Conductor.beatHit.add(this.beatHit); Conductor.stepHit.add(this.stepHit); + + initConsoleHelpers(); } public override function destroy():Void @@ -79,6 +81,8 @@ class MusicBeatSubState extends FlxSubState implements IEventHandler dispatchEvent(new UpdateScriptEvent(elapsed)); } + public function initConsoleHelpers():Void {} + function reloadAssets() { PolymodHandler.forceReloadAssets(); From 239b9b0419fdbb273c0571f0426308df6be58e9f Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 5 Sep 2024 02:10:51 -0400 Subject: [PATCH 668/870] Update assets submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index f1c74ef59..a9f81e916 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit f1c74ef595a29d11544492e0dc907ba9a21d7c4f +Subproject commit a9f81e916f673c5084851b56ee37a2952e9f9587 From 34d13c61de236682535bab4b04bfca5c6744bf1d Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sun, 24 Sep 2023 00:53:53 -0400 Subject: [PATCH 669/870] Cleanup character unlock impl and queue it for after Story Mode is completed. --- source/funkin/InitState.hx | 2 +- .../data/freeplay/player/PlayerRegistry.hx | 24 +++- source/funkin/play/ResultState.hx | 74 +++++++--- source/funkin/play/components/HealthIcon.hx | 32 +++-- .../ui/charSelect/CharacterUnlockState.hx | 128 ++++++++++++++++++ source/funkin/ui/mainmenu/MainMenuState.hx | 14 +- 6 files changed, 240 insertions(+), 34 deletions(-) create mode 100644 source/funkin/ui/charSelect/CharacterUnlockState.hx diff --git a/source/funkin/InitState.hx b/source/funkin/InitState.hx index a203a8d77..f71de00f4 100644 --- a/source/funkin/InitState.hx +++ b/source/funkin/InitState.hx @@ -225,7 +225,7 @@ class InitState extends FlxState // -DRESULTS FlxG.switchState(() -> new funkin.play.ResultState( { - storyMode: false, + storyMode: true, title: "Cum Song Erect by Kawai Sprite", songId: "cum", characterId: "pico-playable", diff --git a/source/funkin/data/freeplay/player/PlayerRegistry.hx b/source/funkin/data/freeplay/player/PlayerRegistry.hx index c0a15ed1c..76b1c25c1 100644 --- a/source/funkin/data/freeplay/player/PlayerRegistry.hx +++ b/source/funkin/data/freeplay/player/PlayerRegistry.hx @@ -71,7 +71,7 @@ class PlayerRegistry extends BaseRegistry public function hasNewCharacter():Bool { - var characters = Save.instance.charactersSeen.clone(); + var charactersSeen = Save.instance.charactersSeen.clone(); for (charId in listEntryIds()) { @@ -79,7 +79,7 @@ class PlayerRegistry extends BaseRegistry if (player == null) continue; if (!player.isUnlocked()) continue; - if (characters.contains(charId)) continue; + if (charactersSeen.contains(charId)) continue; // This character is unlocked but we haven't seen them in Freeplay yet. return true; @@ -89,6 +89,26 @@ class PlayerRegistry extends BaseRegistry return false; } + public function listNewCharacters():Array + { + var charactersSeen = Save.instance.charactersSeen.clone(); + var result = []; + + for (charId in listEntryIds()) + { + var player = fetchEntry(charId); + if (player == null) continue; + + if (!player.isUnlocked()) continue; + if (charactersSeen.contains(charId)) continue; + + // This character is unlocked but we haven't seen them in Freeplay yet. + result.push(charId); + } + + return result; + } + /** * Get the playable character associated with a given stage character. * @param characterId The stage character ID. diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index ec6069ad4..2878248e2 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -731,42 +731,59 @@ class ResultState extends MusicBeatSubState } }); } + + // Determining the target state(s) to go to. + // Default to main menu because that's better than `null`. + var targetState:flixel.FlxState = new funkin.ui.mainmenu.MainMenuState(); + var shouldTween = false; + if (params.storyMode) { - openSubState(new funkin.ui.transition.StickerSubState(null, (sticker) -> new StoryMenuState(sticker))); + if (PlayerRegistry.instance.hasNewCharacter()) + { + targetState = new StoryMenuState(null); + + var newCharacters = PlayerRegistry.instance.listNewCharacters(); + + for (charId in newCharacters) + { + shouldTween = true; + // This works recursively, ehe! + targetState = new funkin.ui.charSelect.CharacterUnlockState(charId, targetState); + } + } + else + { + targetState = new funkin.ui.transition.StickerSubState(null, (sticker) -> new StoryMenuState(sticker)); + } } else { - var rigged:Bool = true; - if (rank > Scoring.calculateRank(params?.prevScoreData)) // if (rigged) + if (rank > Scoring.calculateRank(params?.prevScoreData)) { trace('THE RANK IS Higher.....'); - FlxTween.tween(rankBg, {alpha: 1}, 0.5, + shouldTween = true; + targetState = FreeplayState.build( { - ease: FlxEase.expoOut, - onComplete: function(_) { - FlxG.switchState(FreeplayState.build( + { + character: playerCharacterId ?? "bf", + fromResults: { - { - character: playerCharacterId ?? "bf", - fromResults: - { - oldRank: Scoring.calculateRank(params?.prevScoreData), - newRank: rank, - songId: params.songId, - difficultyId: params.difficultyId, - playRankAnim: true - } - } - })); + oldRank: Scoring.calculateRank(params?.prevScoreData), + newRank: rank, + songId: params.songId, + difficultyId: params.difficultyId, + playRankAnim: true + } } }); } else { trace('rank is lower...... and/or equal'); - openSubState(new funkin.ui.transition.StickerSubState(null, (sticker) -> FreeplayState.build( + + targetState = new funkin.ui.transition.StickerSubState(null, (sticker) -> FreeplayState.build( { { fromResults: @@ -778,9 +795,24 @@ class ResultState extends MusicBeatSubState difficultyId: params.difficultyId } } - }, sticker))); + }, sticker)); } } + + if (shouldTween) + { + FlxTween.tween(rankBg, {alpha: 1}, 0.5, + { + ease: FlxEase.expoOut, + onComplete: function(_) { + FlxG.switchState(targetState); + } + }); + } + else + { + FlxG.switchState(targetState); + } } super.update(elapsed); diff --git a/source/funkin/play/components/HealthIcon.hx b/source/funkin/play/components/HealthIcon.hx index 0e24d73fb..c11850b2a 100644 --- a/source/funkin/play/components/HealthIcon.hx +++ b/source/funkin/play/components/HealthIcon.hx @@ -49,7 +49,7 @@ class HealthIcon extends FunkinSprite * this value allows you to set a relative scale for the icon. * @default 1x scale = 150px width and height. */ - public var size:FlxPoint = new FlxPoint(1, 1); + public var size:FlxPoint; /** * Apply the "bop" animation once every X steps. @@ -120,11 +120,15 @@ class HealthIcon extends FunkinSprite { super(0, 0); this.playerId = playerId; + this.size = new FlxCallbackPoint(onSetSize); this.scrollFactor.set(); - + size.set(1.0, 1.0); this.characterId = char; + } - initTargetSize(); + function onSetSize(value:FlxPoint):Void + { + snapToTargetSize(); } function set_characterId(value:Null):Null @@ -243,6 +247,22 @@ class HealthIcon extends FunkinSprite this.updateHitbox(); } + /* + * Immediately snap the health icon to its target size without lerping. + */ + public function snapToTargetSize():Void + { + if (this.width > this.height) + { + setGraphicSize(Std.int(HEALTH_ICON_SIZE * this.size.x), 0); + } + else + { + setGraphicSize(0, Std.int(HEALTH_ICON_SIZE * this.size.y)); + } + updateHitbox(); + } + /** * Update the position (and status) of the health icon. */ @@ -301,12 +321,6 @@ class HealthIcon extends FunkinSprite } } - inline function initTargetSize():Void - { - setGraphicSize(HEALTH_ICON_SIZE); - updateHitbox(); - } - function updateHealthIcon(health:Float):Void { // We want to efficiently handle animation playback diff --git a/source/funkin/ui/charSelect/CharacterUnlockState.hx b/source/funkin/ui/charSelect/CharacterUnlockState.hx new file mode 100644 index 000000000..25cd1baf0 --- /dev/null +++ b/source/funkin/ui/charSelect/CharacterUnlockState.hx @@ -0,0 +1,128 @@ +package funkin.ui.charSelect; + +import flixel.FlxSprite; +import flixel.FlxState; +import flixel.group.FlxSpriteGroup; +import flixel.text.FlxText; +import flixel.tweens.FlxEase; +import flixel.tweens.FlxTween; +import flixel.util.FlxColor; +import funkin.play.character.CharacterData; +import funkin.play.character.CharacterData.CharacterDataParser; +import funkin.play.components.HealthIcon; +import funkin.ui.freeplay.charselect.PlayableCharacter; +import funkin.data.freeplay.player.PlayerData; +import funkin.data.freeplay.player.PlayerRegistry; +import funkin.ui.mainmenu.MainMenuState; + +using flixel.util.FlxSpriteUtil; + +/** + * When you want the player to unlock a character, call `CharacterUnlockState.unlock(characterName)`. + * It handles both the act of unlocking the character and displaying the dialog. + */ +class CharacterUnlockState extends MusicBeatState +{ + public var targetCharacterId:String = ""; + public var targetCharacterData:Null; + + var nextState:FlxState; + + static final DIALOG_BG_COLOR:FlxColor = 0xFF000000; // Iconic + static final DIALOG_COLOR:FlxColor = 0xFF4344F6; // Iconic + static final DIALOG_FONT_COLOR:FlxColor = 0xFFFFFFFF; // Iconic + + var busy:Bool = false; + + public function new(targetPlayableCharacter:String, ?nextState:FlxState) + { + super(); + + this.targetCharacterId = targetPlayableCharacter; + this.targetCharacterData = PlayerRegistry.instance.fetchEntry(targetCharacterId); + this.nextState = nextState == null ? new MainMenuState() : nextState; + } + + override function create():Void + { + super.create(); + + handleMusic(); + + bgColor = DIALOG_BG_COLOR; + + var dialogContainer:FlxSpriteGroup = new FlxSpriteGroup(); + add(dialogContainer); + + // Build the graphic for the text... + var charName:String = targetCharacterData != null ? targetCharacterData.getName() : targetCharacterId.toTitleCase(); + // var dialogText:FlxText = new FlxText(0, 0, 0, 'You can now play as $charName.\n\nCheck it out in Freeplay!'); + var dialogText:FlxText = new FlxText(0, 0, 0, 'You can now play as $charName.'); + dialogText.setFormat("VCR OSD Mono", 32, DIALOG_FONT_COLOR, LEFT); + + // THEN we can size the dialog to match... + var dialogBG:FlxSprite = new FlxSprite(0, 0); + dialogBG.makeGraphic(Std.int(dialogText.width + 32), Std.int(dialogText.height + 32), FlxColor.TRANSPARENT); + dialogBG.drawRoundRect(0, 0, dialogBG.width, dialogBG.height, 16, 16, DIALOG_COLOR); + dialogContainer.add(dialogBG); + + dialogBG.screenCenter(XY); + + // THEN we can position the text inside that. + dialogText.x = dialogBG.x + 16; + dialogText.y = dialogBG.y + 16; + dialogContainer.add(dialogText); + + // HealthIcon handles getting the right frames for us, + // but it has a bunch of overhead in it that makes it gross to work with outside the health bar. + var healthIconCharacterId = targetCharacterData.getOwnedCharacterIds()[0]; + var baseCharacter = CharacterDataParser.fetchCharacter(healthIconCharacterId); + var healthIcon:HealthIcon = new HealthIcon(healthIconCharacterId); + @:privateAccess + healthIcon.configure(baseCharacter._data.healthIcon); + healthIcon.autoUpdate = false; + healthIcon.bopEvery = 0; // You can increase this number later once the animation is done. + healthIcon.size.set(0.5, 0.5); + healthIcon.x = dialogBG.x + 390; + healthIcon.y = dialogBG.y + 6; + healthIcon.flipX = true; + healthIcon.snapToTargetSize(); + dialogContainer.add(healthIcon); + + dialogContainer.scale.set(0, 0); + FlxTween.num(0.0, 1.0, 0.75, + { + ease: FlxEase.elasticOut, + }, function(curScale) { + dialogContainer.scale.set(curScale, curScale); + healthIcon.size.set(0.5 * curScale, 0.5 * curScale); + }); + + // performUnlock(); + } + + function handleMusic():Void + { + FlxG.sound.music.stop(); + FlxG.sound.play(Paths.sound('confirmMenu')); + } + + override function update(elapsed:Float):Void + { + super.update(elapsed); + + if (controls.ACCEPT || controls.BACK && !busy) + { + busy = true; + startClose(); + } + } + + function startClose():Void + { + // Fade to black, then switch state. + FlxG.camera.fade(FlxColor.BLACK, 0.75, false, () -> { + FlxG.switchState(nextState); + }); + } +} diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index d2a9f046a..19dc0d687 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -344,8 +344,8 @@ class MainMenuState extends MusicBeatState } } - #if FEATURE_DEBUG_FUNCTIONS // Open the debug menu, defaults to ` / ~ + // This includes stuff like the Chart Editor, so it should be present on all builds. if (controls.DEBUG_MENU) { persistentUpdate = false; @@ -353,6 +353,18 @@ class MainMenuState extends MusicBeatState FlxG.state.openSubState(new DebugMenuSubState()); } + #if FEATURE_DEBUG_FUNCTIONS + // Ctrl+Alt+Shift+P = Character Unlock screen + // Ctrl+Alt+Shift+W = Meet requirements for Pico Unlock + // Ctrl+Alt+Shift+L = Revoke requirements for Pico Unlock + // Ctrl+Alt+Shift+R = Score/Rank conflict test + // Ctrl+Alt+Shift+E = Dump save data + + if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.P) + { + FlxG.switchState(() -> new funkin.ui.charSelect.CharacterUnlockState('pico')); + } + if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.W) { FunkinSound.playOnce(Paths.sound('confirmMenu')); From 677357ba37d1aaba3e3154ed70dd97e786353194 Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Fri, 6 Sep 2024 02:55:47 +0200 Subject: [PATCH 670/870] wip sequence --- source/funkin/audio/FunkinSound.hx | 4 +- .../funkin/ui/charSelect/CharSelectPlayer.hx | 2 +- .../ui/charSelect/CharSelectSubState.hx | 160 ++++++++++++------ 3 files changed, 111 insertions(+), 55 deletions(-) diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index 9cb131c91..b33126998 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -388,7 +388,7 @@ class FunkinSound extends FlxSound implements ICloneable } else { - var music = FunkinSound.load(pathToUse, params?.startingVolume ?? 1.0, params.loop ?? true, false, true); + var music = FunkinSound.load(pathToUse, params?.startingVolume ?? 1.0, params.loop ?? true, false, true, params.onComplete); if (music != null) { FlxG.sound.music = music; @@ -396,6 +396,8 @@ class FunkinSound extends FlxSound implements ICloneable // Prevent repeat update() and onFocus() calls. FlxG.sound.list.remove(FlxG.sound.music); + if (FlxG.sound.music != null && params.onLoad != null) params.onLoad(); + return true; } else diff --git a/source/funkin/ui/charSelect/CharSelectPlayer.hx b/source/funkin/ui/charSelect/CharSelectPlayer.hx index 07c82d038..0ac74f98e 100644 --- a/source/funkin/ui/charSelect/CharSelectPlayer.hx +++ b/source/funkin/ui/charSelect/CharSelectPlayer.hx @@ -21,7 +21,7 @@ class CharSelectPlayer extends FlxAtlasSprite if (hasAnimation("slidein idle point")) playAnimation("slidein idle point", true, false, false); else playAnimation("idle", true, false, true); - case "slidein idle point": + case "slidein idle point", "cannot select", "unlock": playAnimation("idle", true, false, true); } }); diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index 1a27d0392..a2fe4a7dc 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -26,6 +26,7 @@ import funkin.ui.PixelatedIcon; import funkin.util.MathUtil; import funkin.vis.dsp.SpectralAnalyzer; import openfl.display.BlendMode; +import funkin.save.Save; class CharSelectSubState extends MusicBeatSubState { @@ -69,8 +70,6 @@ class CharSelectSubState extends MusicBeatSubState var charSelectCam:FunkinCamera; - var introM:FunkinSound = null; - public function new() { super(); @@ -89,6 +88,8 @@ class CharSelectSubState extends MusicBeatSubState var playerData = player.getCharSelectData(); if (playerData == null) continue; + trace(player.isUnlocked()); + var targetPosition:Int = playerData.position ?? 0; while (availableChars.exists(targetPosition)) { @@ -104,38 +105,6 @@ class CharSelectSubState extends MusicBeatSubState { super.create(); - selectSound = new FunkinSound(); - selectSound.loadEmbedded(Paths.sound('CS_select')); - selectSound.pitch = 1; - selectSound.volume = 0.7; - FlxG.sound.defaultSoundGroup.add(selectSound); - - // playing it here to preload it. not doing this makes a super awkward pause at the end of the intro - // TODO: probably make an intro thing for funkinSound itself that preloads the next audio? - FunkinSound.playMusic('stayFunky', - { - startingVolume: 0, - overrideExisting: true, - restartTrack: true - }); - var introMusic:String = Paths.music('stayFunky/stayFunky-intro'); - introM = FunkinSound.load(introMusic, 1.0, false, true, true, () -> { - FunkinSound.playMusic('stayFunky', - { - startingVolume: 1, - overrideExisting: true, - restartTrack: true - }); - @:privateAccess - gfChill.analyzer = new SpectralAnalyzer(FlxG.sound.music._channel.__audioSource, 7, 0.1); - #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! - @:privateAccess - gfChill.analyzer.fftN = 512; - #end - }); - var bg:FlxSprite = new FlxSprite(-153, -140); bg.loadGraphic(Paths.image('charSelect/charSelectBG')); bg.scrollFactor.set(0.1, 0.1); @@ -174,15 +143,15 @@ class CharSelectSubState extends MusicBeatSubState gfChill = new CharSelectGF(); gfChill.switchGF("bf"); add(gfChill); - @:privateAccess - playerChill = new CharSelectPlayer(0, 0); - playerChill.switchChar("bf"); - add(playerChill); playerChillOut = new CharSelectPlayer(0, 0); playerChillOut.switchChar("bf"); add(playerChillOut); + playerChill = new CharSelectPlayer(0, 0); + playerChill.switchChar("bf"); + add(playerChill); + var speakers:FlxAtlasSprite = new FlxAtlasSprite(0, 0, Paths.animateAtlas("charSelect/charSelectSpeakers")); speakers.anim.play(""); speakers.scrollFactor.set(1.8, 1.8); @@ -289,7 +258,7 @@ class CharSelectSubState extends MusicBeatSubState FlxG.debugger.addTrackerProfile(new TrackerProfile(CharSelectSubState, ["curChar", "grpXSpread", "grpYSpread"])); FlxG.debugger.track(this); - FlxG.sound.playMusic(Paths.music('charSelect/charSelectMusic')); + // FlxG.sound.playMusic(Paths.music('charSelect/charSelectMusic')); camFollow = new FlxObject(0, 0, 1, 1); add(camFollow); @@ -301,6 +270,14 @@ class CharSelectSubState extends MusicBeatSubState temp.loadGraphic(Paths.image('charSelect/placement')); add(temp); temp.alpha = 0.0; + + selectSound = new FunkinSound(); + selectSound.loadEmbedded(Paths.sound('CS_select')); + selectSound.pitch = 1; + selectSound.volume = 0.7; + + FlxG.sound.defaultSoundGroup.add(selectSound); + Conductor.stepHit.add(spamOnStep); // FlxG.debugger.track(temp, "tempBG"); } @@ -309,6 +286,8 @@ class CharSelectSubState extends MusicBeatSubState var grpXSpread(default, set):Float = 107; var grpYSpread(default, set):Float = 127; + var nonLocks = []; + function initLocks():Void { grpIcons = new FlxSpriteGroup(); @@ -319,7 +298,7 @@ class CharSelectSubState extends MusicBeatSubState for (i in 0...9) { - if (availableChars.exists(i)) + if (availableChars.exists(i) && Save.instance.charactersSeen.contains(availableChars[i])) { var path:String = availableChars.get(i); var temp:PixelatedIcon = new PixelatedIcon(0, 0); @@ -331,9 +310,15 @@ class CharSelectSubState extends MusicBeatSubState } else { + if (availableChars.exists(i)) nonLocks.push(i); + var temp:Lock = new Lock(0, 0, i); temp.ID = 1; + temp.onAnimationComplete.add(function(anim) { + if (anim == "unlock") playerChill.playAnimation("unlock", true); + }); + grpIcons.add(temp); } } @@ -341,6 +326,78 @@ class CharSelectSubState extends MusicBeatSubState updateIconPositions(); grpIcons.scrollFactor.set(); + + // playing it here to preload it. not doing this makes a super awkward pause at the end of the intro + // TODO: probably make an intro thing for funkinSound itself that preloads the next audio? + FunkinSound.playMusic('stayFunky', + { + startingVolume: 0, + overrideExisting: true, + restartTrack: true, + }); + + unLock(); + } + + function unLock() + { + var index = nonLocks[0]; + + var copy = 3; + + var yThing = 0; + + while (index > copy) + { + yThing++; + copy += 3; + } + + var xThing = copy - index - 1; + + cursorY = 3 - yThing; + cursorX = 3 - xThing; + + selectTimer.start(1, function(_) { + var lock:Lock = cast grpIcons.group.members[index]; + + lock.playAnimation("unlock"); + + playerChill.visible = false; + playerChill.switchChar(availableChars[index]); + + playerChillOut.visible = true; + playerChillOut.playAnimation("death"); + playerChillOut.onAnimationComplete.addOnce((_) -> if (_ == "death") + { + playerChill.playAnimation("unlock"); + playerChill.onAnimationComplete.addOnce(function(_) { + nonLocks.shift(); + + if (nonLocks.length > 0) unLock(); + else + { + FunkinSound.playMusic('stayFunky', + { + startingVolume: 1, + overrideExisting: true, + restartTrack: true, + onLoad: function() { + @:privateAccess + gfChill.analyzer = new SpectralAnalyzer(FlxG.sound.music._channel.__audioSource, 7, 0.1); + #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! + @:privateAccess + gfChill.analyzer.fftN = 512; + #end + } + }); + } + }); + playerChill.visible = true; + }); + }); } function updateIconPositions() @@ -372,17 +429,6 @@ class CharSelectSubState extends MusicBeatSubState override public function update(elapsed:Float):Void { super.update(elapsed); - @:privateAccess - if (introM != null && !introM.paused && gfChill.analyzer == null) - { - gfChill.analyzer = new SpectralAnalyzer(introM._channel.__audioSource, 7, 0.1); - #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! - @:privateAccess - gfChill.analyzer.fftN = 512; - #end - } Conductor.instance.update(); @@ -426,6 +472,8 @@ class CharSelectSubState extends MusicBeatSubState if (controls.UI_UP_P) { cursorY -= 1; + cursorDenied.visible = false; + holdTmrUp = 0; selectSound.play(true); @@ -433,18 +481,22 @@ class CharSelectSubState extends MusicBeatSubState if (controls.UI_DOWN_P) { cursorY += 1; + cursorDenied.visible = false; holdTmrDown = 0; selectSound.play(true); } if (controls.UI_LEFT_P) { cursorX -= 1; + cursorDenied.visible = false; + holdTmrLeft = 0; selectSound.play(true); } if (controls.UI_RIGHT_P) { cursorX += 1; + cursorDenied.visible = false; holdTmrRight = 0; selectSound.play(true); } @@ -466,7 +518,7 @@ class CharSelectSubState extends MusicBeatSubState cursorY = -1; } - if (availableChars.exists(getCurrentSelected())) + if (availableChars.exists(getCurrentSelected()) && Save.instance.charactersSeen.contains(availableChars[getCurrentSelected()])) { curChar = availableChars.get(getCurrentSelected()); @@ -567,6 +619,8 @@ class CharSelectSubState extends MusicBeatSubState if (selectSound.pitch > 5) selectSound.pitch = 5; selectSound.play(true); + cursorDenied.visible = false; + if (spamUp) { cursorY -= 1; @@ -621,7 +675,7 @@ class CharSelectSubState extends MusicBeatSubState memb.scale.set(2.6, 2.6); if (controls.ACCEPT) memb.animation.play("confirm"); - if (controls.BACK) + if (memb.animation.curAnim.name == "confirm" && controls.BACK) { memb.animation.play("confirm", false, true); member.animation.finishCallback = (_) -> { From 4cad56705ab5866d2b2a94224b08ebc7e63bc132 Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Wed, 4 Sep 2024 20:08:38 +0200 Subject: [PATCH 671/870] Add lock bizz --- assets | 2 +- project/lib/harfbuzz | 1 + project/lib/hashlink | 1 + project/lib/jpeg | 1 + project/lib/lzma | 1 + project/lib/mbedtls | 1 + project/lib/mojoal | 1 + project/lib/neko | 1 + project/lib/ogg | 1 + project/lib/openal | 1 + project/lib/pixman | 1 + project/lib/png | 1 + project/lib/sdl | 1 + project/lib/tinyfiledialogs | 1 + project/lib/vorbis | 1 + project/lib/vpx | 1 + project/lib/webm | 1 + project/lib/zlib | 1 + .../ui/charSelect/CharSelectSubState.hx | 29 ++++++--------- source/funkin/ui/charSelect/Lock.hx | 35 +++++++++++++++++++ 20 files changed, 64 insertions(+), 19 deletions(-) create mode 160000 project/lib/harfbuzz create mode 160000 project/lib/hashlink create mode 160000 project/lib/jpeg create mode 160000 project/lib/lzma create mode 160000 project/lib/mbedtls create mode 160000 project/lib/mojoal create mode 160000 project/lib/neko create mode 160000 project/lib/ogg create mode 160000 project/lib/openal create mode 160000 project/lib/pixman create mode 160000 project/lib/png create mode 160000 project/lib/sdl create mode 160000 project/lib/tinyfiledialogs create mode 160000 project/lib/vorbis create mode 160000 project/lib/vpx create mode 160000 project/lib/webm create mode 160000 project/lib/zlib create mode 100644 source/funkin/ui/charSelect/Lock.hx diff --git a/assets b/assets index f1c74ef59..b0549bb2b 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit f1c74ef595a29d11544492e0dc907ba9a21d7c4f +Subproject commit b0549bb2b4341e10502cc964df06d6148575c1e1 diff --git a/project/lib/harfbuzz b/project/lib/harfbuzz new file mode 160000 index 000000000..2ba0b9ee9 --- /dev/null +++ b/project/lib/harfbuzz @@ -0,0 +1 @@ +Subproject commit 2ba0b9ee94e4fdea5c3e9d20fa73eb893c0bb95e diff --git a/project/lib/hashlink b/project/lib/hashlink new file mode 160000 index 000000000..9888913ed --- /dev/null +++ b/project/lib/hashlink @@ -0,0 +1 @@ +Subproject commit 9888913ed2e1eef9fc03085100c92bd44985c781 diff --git a/project/lib/jpeg b/project/lib/jpeg new file mode 160000 index 000000000..5cf796067 --- /dev/null +++ b/project/lib/jpeg @@ -0,0 +1 @@ +Subproject commit 5cf79606784f0616590e6a3a7fdf17ad32a6df9b diff --git a/project/lib/lzma b/project/lib/lzma new file mode 160000 index 000000000..5748ce6ad --- /dev/null +++ b/project/lib/lzma @@ -0,0 +1 @@ +Subproject commit 5748ce6ad668bb10e1a1fe322b37245d0053e71a diff --git a/project/lib/mbedtls b/project/lib/mbedtls new file mode 160000 index 000000000..ab0af45d1 --- /dev/null +++ b/project/lib/mbedtls @@ -0,0 +1 @@ +Subproject commit ab0af45d11db04bd6e42ccfabe1b8d8deaae3243 diff --git a/project/lib/mojoal b/project/lib/mojoal new file mode 160000 index 000000000..a9e2f30b0 --- /dev/null +++ b/project/lib/mojoal @@ -0,0 +1 @@ +Subproject commit a9e2f30b04f10df1912d06ff5a610edda4677ba5 diff --git a/project/lib/neko b/project/lib/neko new file mode 160000 index 000000000..d8a3b4638 --- /dev/null +++ b/project/lib/neko @@ -0,0 +1 @@ +Subproject commit d8a3b463861779656a78c1a5e31c013580642185 diff --git a/project/lib/ogg b/project/lib/ogg new file mode 160000 index 000000000..db5c7a49c --- /dev/null +++ b/project/lib/ogg @@ -0,0 +1 @@ +Subproject commit db5c7a49ce7ebda47b15b78471e78fb7f2483e22 diff --git a/project/lib/openal b/project/lib/openal new file mode 160000 index 000000000..326133368 --- /dev/null +++ b/project/lib/openal @@ -0,0 +1 @@ +Subproject commit 326133368c3d7149d0ab4a98fc96f654553094a7 diff --git a/project/lib/pixman b/project/lib/pixman new file mode 160000 index 000000000..0cb4fbe32 --- /dev/null +++ b/project/lib/pixman @@ -0,0 +1 @@ +Subproject commit 0cb4fbe3241988a5d6b51d3551998ec6837c75a1 diff --git a/project/lib/png b/project/lib/png new file mode 160000 index 000000000..e4a31f024 --- /dev/null +++ b/project/lib/png @@ -0,0 +1 @@ +Subproject commit e4a31f024b6158aaaf55a43502f574d5f5d1c894 diff --git a/project/lib/sdl b/project/lib/sdl new file mode 160000 index 000000000..8ea38ebed --- /dev/null +++ b/project/lib/sdl @@ -0,0 +1 @@ +Subproject commit 8ea38ebedc846faa547693f60bcd213b21370982 diff --git a/project/lib/tinyfiledialogs b/project/lib/tinyfiledialogs new file mode 160000 index 000000000..4927ea8f4 --- /dev/null +++ b/project/lib/tinyfiledialogs @@ -0,0 +1 @@ +Subproject commit 4927ea8f44fa0151dc8e0a2b79a13dbd7827cc48 diff --git a/project/lib/vorbis b/project/lib/vorbis new file mode 160000 index 000000000..84c023699 --- /dev/null +++ b/project/lib/vorbis @@ -0,0 +1 @@ +Subproject commit 84c023699cdf023a32fa4ded32019f194afcdad0 diff --git a/project/lib/vpx b/project/lib/vpx new file mode 160000 index 000000000..fbf63dff1 --- /dev/null +++ b/project/lib/vpx @@ -0,0 +1 @@ +Subproject commit fbf63dff1f528d44f24bd662abb89fd01a4a1c25 diff --git a/project/lib/webm b/project/lib/webm new file mode 160000 index 000000000..6c1e511f4 --- /dev/null +++ b/project/lib/webm @@ -0,0 +1 @@ +Subproject commit 6c1e511f487eaea026d94d0c6494a617155b5cfb diff --git a/project/lib/zlib b/project/lib/zlib new file mode 160000 index 000000000..545f19496 --- /dev/null +++ b/project/lib/zlib @@ -0,0 +1 @@ +Subproject commit 545f1949635949159fa6282e81712aec32b5d4f1 diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index 60b931410..6c18c905f 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -387,21 +387,8 @@ class CharSelectSubState extends MusicBeatSubState } else { - var temp:FlxSprite = new FlxSprite(); + var temp:Lock = new Lock(0, 0, i); temp.ID = 1; - temp.frames = Paths.getSparrowAtlas("charSelect/locks"); - - var lockIndex:Int = i + 1; - - if (i == 3) lockIndex = 3; - - if (i >= 4) lockIndex = i - 2; - - temp.animation.addByIndices("idle", "LOCK FULL " + lockIndex + " instance 1", [0], "", 24); - temp.animation.addByIndices("selected", "LOCK FULL " + lockIndex + " instance 1", [3, 4, 5], "", 24, false); - temp.animation.addByIndices("clicked", "LOCK FULL " + lockIndex + " instance 1", [9, 10, 11, 12, 13, 14, 15], "", 24, false); - - temp.animation.play("idle"); grpIcons.add(temp); } @@ -677,6 +664,11 @@ class CharSelectSubState extends MusicBeatSubState function spamOnStep():Void { + if (FlxG.keys.justPressed.B) + { + cursorY = 3; + cursorX = 3; + } if (spamUp || spamDown || spamLeft || spamRight) { // selectSound.changePitchBySemitone(1); @@ -713,19 +705,20 @@ class CharSelectSubState extends MusicBeatSubState switch (member.ID) { case 1: + var lock:Lock = cast member; if (index == getCurrentSelected()) { - switch (member.animation.curAnim.name) + switch (lock.getCurrentAnimation()) { case "idle": - member.animation.play("selected"); + lock.playAnimation("selected"); case "selected" | "clicked": - if (controls.ACCEPT) member.animation.play("clicked", true); + if (controls.ACCEPT) lock.playAnimation((FlxG.keys.pressed.CONTROL) ? "unlock" : "clicked", true); } } else { - member.animation.play("idle"); + lock.playAnimation("idle"); } case 0: var memb:PixelatedIcon = cast member; diff --git a/source/funkin/ui/charSelect/Lock.hx b/source/funkin/ui/charSelect/Lock.hx new file mode 100644 index 000000000..42e5d63f4 --- /dev/null +++ b/source/funkin/ui/charSelect/Lock.hx @@ -0,0 +1,35 @@ +package funkin.ui.charSelect; + +import flixel.util.FlxColor; +import flxanimate.effects.FlxTint; +import funkin.graphics.adobeanimate.FlxAtlasSprite; + +class Lock extends FlxAtlasSprite +{ + var colors:Array = [ + 0x31F2A5, 0x20ECCD, 0x24D9E8, + 0x20ECCD, 0x20C8D4, 0x209BDD, + 0x209BDD, 0x2362C9, 0x243FB9 + ]; // lock colors, in a nx3 matrix format + + public function new(x:Float = 0, y:Float = 0, index:Int) + { + super(x, y, Paths.animateAtlas("charSelect/lock")); + + var tint:FlxTint = new FlxTint(colors[index], 1); + + var arr:Array = ["lock", "lock top 1", "lock top 2", "lock top 3", "lock base fuck it"]; + + onAnimationComplete.add((_) -> if (_ == "unlock") playAnimation("idle")); + var func = function(name) { + var symbol = anim.symbolDictionary[name]; + if (symbol != null && symbol.timeline.get("color") != null) symbol.timeline.get("color").get(0).colorEffect = tint; + } + for (symbol in arr) + { + func(symbol); + } + + playAnimation("idle"); + } +} From 1021f5c2eee9e01289021132d2cfb98f3d1539f4 Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Fri, 6 Sep 2024 02:55:47 +0200 Subject: [PATCH 672/870] wip sequence --- source/funkin/audio/FunkinSound.hx | 4 +- .../funkin/ui/charSelect/CharSelectPlayer.hx | 8 +- .../ui/charSelect/CharSelectSubState.hx | 169 +++++++++++------- 3 files changed, 113 insertions(+), 68 deletions(-) diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index 9cb131c91..b33126998 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -388,7 +388,7 @@ class FunkinSound extends FlxSound implements ICloneable } else { - var music = FunkinSound.load(pathToUse, params?.startingVolume ?? 1.0, params.loop ?? true, false, true); + var music = FunkinSound.load(pathToUse, params?.startingVolume ?? 1.0, params.loop ?? true, false, true, params.onComplete); if (music != null) { FlxG.sound.music = music; @@ -396,6 +396,8 @@ class FunkinSound extends FlxSound implements ICloneable // Prevent repeat update() and onFocus() calls. FlxG.sound.list.remove(FlxG.sound.music); + if (FlxG.sound.music != null && params.onLoad != null) params.onLoad(); + return true; } else diff --git a/source/funkin/ui/charSelect/CharSelectPlayer.hx b/source/funkin/ui/charSelect/CharSelectPlayer.hx index 8e94e25fe..eac2f459a 100644 --- a/source/funkin/ui/charSelect/CharSelectPlayer.hx +++ b/source/funkin/ui/charSelect/CharSelectPlayer.hx @@ -26,12 +26,10 @@ class CharSelectPlayer extends FlxAtlasSprite implements IBPMSyncedScriptedClass } else { - // Handled by onBeatHit now - playAnimation("idle", true, false, false); + playAnimation("idle", true, false, true); } - case "slidein idle point": - // Handled by onBeatHit now - playAnimation("idle", true, false, false); + case "slidein idle point", "cannot select", "unlock": + playAnimation("idle", true, false, true); case "idle": trace('Waiting for onBeatHit'); } diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index 6c18c905f..65fb48bb3 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -17,20 +17,17 @@ import funkin.data.freeplay.player.PlayerData; import funkin.data.freeplay.player.PlayerRegistry; import funkin.graphics.adobeanimate.FlxAtlasSprite; import funkin.graphics.FunkinCamera; +import funkin.graphics.shaders.BlueFade; import funkin.modding.events.ScriptEvent; import funkin.modding.events.ScriptEventDispatcher; import funkin.play.stage.Stage; +import funkin.save.Save; import funkin.ui.freeplay.charselect.PlayableCharacter; import funkin.ui.freeplay.FreeplayState; import funkin.ui.PixelatedIcon; import funkin.util.MathUtil; import funkin.vis.dsp.SpectralAnalyzer; import openfl.display.BlendMode; -import flixel.util.FlxTimer; -import flixel.tweens.FlxEase; -import flixel.sound.FlxSound; -import funkin.audio.FunkinSound; -import funkin.graphics.shaders.BlueFade; import openfl.filters.ShaderFilter; class CharSelectSubState extends MusicBeatSubState @@ -82,8 +79,6 @@ class CharSelectSubState extends MusicBeatSubState var charSelectCam:FunkinCamera; - var introM:FunkinSound = null; - public function new() { super(); @@ -102,6 +97,8 @@ class CharSelectSubState extends MusicBeatSubState var playerData = player.getCharSelectData(); if (playerData == null) continue; + trace(player.isUnlocked()); + var targetPosition:Int = playerData.position ?? 0; while (availableChars.exists(targetPosition)) { @@ -119,43 +116,6 @@ class CharSelectSubState extends MusicBeatSubState { super.create(); - autoFollow = false; - - var fadeShaderFilter:ShaderFilter = new ShaderFilter(fadeShader); - FlxG.camera.filters = [fadeShaderFilter]; - - selectSound = new FunkinSound(); - selectSound.loadEmbedded(Paths.sound('CS_select')); - selectSound.pitch = 1; - selectSound.volume = 0.7; - FlxG.sound.defaultSoundGroup.add(selectSound); - - // playing it here to preload it. not doing this makes a super awkward pause at the end of the intro - // TODO: probably make an intro thing for funkinSound itself that preloads the next audio? - FunkinSound.playMusic('stayFunky', - { - startingVolume: 0, - overrideExisting: true, - restartTrack: true - }); - var introMusic:String = Paths.music('stayFunky/stayFunky-intro'); - introM = FunkinSound.load(introMusic, 1.0, false, true, true, () -> { - FunkinSound.playMusic('stayFunky', - { - startingVolume: 1, - overrideExisting: true, - restartTrack: true - }); - @:privateAccess - gfChill.analyzer = new SpectralAnalyzer(FlxG.sound.music._channel.__audioSource, 7, 0.1); - #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! - @:privateAccess - gfChill.analyzer.fftN = 512; - #end - }); - var bg:FlxSprite = new FlxSprite(-153, -140); bg.loadGraphic(Paths.image('charSelect/charSelectBG')); bg.scrollFactor.set(0.1, 0.1); @@ -197,15 +157,15 @@ class CharSelectSubState extends MusicBeatSubState gfChill = new CharSelectGF(); gfChill.switchGF("bf"); add(gfChill); - @:privateAccess - playerChill = new CharSelectPlayer(0, 0); - playerChill.switchChar("bf"); - add(playerChill); playerChillOut = new CharSelectPlayer(0, 0); playerChillOut.switchChar("bf"); add(playerChillOut); + playerChill = new CharSelectPlayer(0, 0); + playerChill.switchChar("bf"); + add(playerChill); + var speakers:FlxAtlasSprite = new FlxAtlasSprite(0, 0, Paths.animateAtlas("charSelect/charSelectSpeakers")); speakers.anim.play(""); speakers.scrollFactor.set(1.8, 1.8); @@ -338,6 +298,14 @@ class CharSelectSubState extends MusicBeatSubState temp.loadGraphic(Paths.image('charSelect/placement')); add(temp); temp.alpha = 0.0; + + selectSound = new FunkinSound(); + selectSound.loadEmbedded(Paths.sound('CS_select')); + selectSound.pitch = 1; + selectSound.volume = 0.7; + + FlxG.sound.defaultSoundGroup.add(selectSound); + Conductor.stepHit.add(spamOnStep); // FlxG.debugger.track(temp, "tempBG"); @@ -365,6 +333,8 @@ class CharSelectSubState extends MusicBeatSubState var grpXSpread(default, set):Float = 107; var grpYSpread(default, set):Float = 127; + var nonLocks = []; + function initLocks():Void { grpIcons = new FlxSpriteGroup(); @@ -375,7 +345,7 @@ class CharSelectSubState extends MusicBeatSubState for (i in 0...9) { - if (availableChars.exists(i)) + if (availableChars.exists(i) && Save.instance.charactersSeen.contains(availableChars[i])) { var path:String = availableChars.get(i); var temp:PixelatedIcon = new PixelatedIcon(0, 0); @@ -387,9 +357,15 @@ class CharSelectSubState extends MusicBeatSubState } else { + if (availableChars.exists(i)) nonLocks.push(i); + var temp:Lock = new Lock(0, 0, i); temp.ID = 1; + temp.onAnimationComplete.add(function(anim) { + if (anim == "unlock") playerChill.playAnimation("unlock", true); + }); + grpIcons.add(temp); } } @@ -397,6 +373,78 @@ class CharSelectSubState extends MusicBeatSubState updateIconPositions(); grpIcons.scrollFactor.set(); + + // playing it here to preload it. not doing this makes a super awkward pause at the end of the intro + // TODO: probably make an intro thing for funkinSound itself that preloads the next audio? + FunkinSound.playMusic('stayFunky', + { + startingVolume: 0, + overrideExisting: true, + restartTrack: true, + }); + + unLock(); + } + + function unLock() + { + var index = nonLocks[0]; + + var copy = 3; + + var yThing = 0; + + while (index > copy) + { + yThing++; + copy += 3; + } + + var xThing = copy - index - 1; + + cursorY = 3 - yThing; + cursorX = 3 - xThing; + + selectTimer.start(1, function(_) { + var lock:Lock = cast grpIcons.group.members[index]; + + lock.playAnimation("unlock"); + + playerChill.visible = false; + playerChill.switchChar(availableChars[index]); + + playerChillOut.visible = true; + playerChillOut.playAnimation("death"); + playerChillOut.onAnimationComplete.addOnce((_) -> if (_ == "death") + { + playerChill.playAnimation("unlock"); + playerChill.onAnimationComplete.addOnce(function(_) { + nonLocks.shift(); + + if (nonLocks.length > 0) unLock(); + else + { + FunkinSound.playMusic('stayFunky', + { + startingVolume: 1, + overrideExisting: true, + restartTrack: true, + onLoad: function() { + @:privateAccess + gfChill.analyzer = new SpectralAnalyzer(FlxG.sound.music._channel.__audioSource, 7, 0.1); + #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! + @:privateAccess + gfChill.analyzer.fftN = 512; + #end + } + }); + } + }); + playerChill.visible = true; + }); + }); } function updateIconPositions() @@ -464,17 +512,6 @@ class CharSelectSubState extends MusicBeatSubState override public function update(elapsed:Float):Void { super.update(elapsed); - @:privateAccess - if (introM != null && !introM.paused && gfChill.analyzer == null) - { - gfChill.analyzer = new SpectralAnalyzer(introM._channel.__audioSource, 7, 0.1); - #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! - @:privateAccess - gfChill.analyzer.fftN = 512; - #end - } Conductor.instance.update(); @@ -518,6 +555,8 @@ class CharSelectSubState extends MusicBeatSubState if (controls.UI_UP_P) { cursorY -= 1; + cursorDenied.visible = false; + holdTmrUp = 0; selectSound.play(true); @@ -525,18 +564,22 @@ class CharSelectSubState extends MusicBeatSubState if (controls.UI_DOWN_P) { cursorY += 1; + cursorDenied.visible = false; holdTmrDown = 0; selectSound.play(true); } if (controls.UI_LEFT_P) { cursorX -= 1; + cursorDenied.visible = false; + holdTmrLeft = 0; selectSound.play(true); } if (controls.UI_RIGHT_P) { cursorX += 1; + cursorDenied.visible = false; holdTmrRight = 0; selectSound.play(true); } @@ -558,7 +601,7 @@ class CharSelectSubState extends MusicBeatSubState cursorY = -1; } - if (availableChars.exists(getCurrentSelected())) + if (availableChars.exists(getCurrentSelected()) && Save.instance.charactersSeen.contains(availableChars[getCurrentSelected()])) { curChar = availableChars.get(getCurrentSelected()); @@ -675,6 +718,8 @@ class CharSelectSubState extends MusicBeatSubState if (selectSound.pitch > 5) selectSound.pitch = 5; selectSound.play(true); + cursorDenied.visible = false; + if (spamUp) { cursorY -= 1; @@ -729,7 +774,7 @@ class CharSelectSubState extends MusicBeatSubState memb.scale.set(2.6, 2.6); if (controls.ACCEPT) memb.animation.play("confirm"); - if (controls.BACK) + if (memb.animation.curAnim.name == "confirm" && controls.BACK) { memb.animation.play("confirm", false, true); member.animation.finishCallback = (_) -> { From 313dba6985b473c3d8ec8f7283fa41178c4793fd Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 6 Sep 2024 00:24:07 -0400 Subject: [PATCH 673/870] Update assets submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index f1c74ef59..8e0d71c8f 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit f1c74ef595a29d11544492e0dc907ba9a21d7c4f +Subproject commit 8e0d71c8f32ebd872f7f7411b3f7108083554de9 From a61f40571d31d792e0d4ea7322af4261ca574cf5 Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Fri, 6 Sep 2024 06:28:08 +0200 Subject: [PATCH 674/870] add wip bizz --- assets | 2 +- source/funkin/graphics/FlxFilteredSprite.hx | 407 ++++++++++++++++++ source/funkin/ui/PixelatedIcon.hx | 3 +- .../ui/charSelect/CharSelectSubState.hx | 3 + 4 files changed, 413 insertions(+), 2 deletions(-) create mode 100644 source/funkin/graphics/FlxFilteredSprite.hx diff --git a/assets b/assets index 74bd0131b..f73c8f479 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 74bd0131b705e87f9704c54a44d64579153ab4af +Subproject commit f73c8f4798bfcd23c98db03bcde2e0afcbce4cfd diff --git a/source/funkin/graphics/FlxFilteredSprite.hx b/source/funkin/graphics/FlxFilteredSprite.hx new file mode 100644 index 000000000..3563ea976 --- /dev/null +++ b/source/funkin/graphics/FlxFilteredSprite.hx @@ -0,0 +1,407 @@ +package funkin.graphics; + +import flixel.FlxBasic; +import flixel.FlxCamera; +import flixel.FlxG; +import flixel.FlxSprite; +import flixel.graphics.FlxGraphic; +import flixel.graphics.frames.FlxFrame; +import flixel.math.FlxMatrix; +import flixel.math.FlxPoint; +import flixel.math.FlxRect; +import flixel.util.FlxColor; +import lime.graphics.cairo.Cairo; +import openfl.display.BitmapData; +import openfl.display.BlendMode; +import openfl.display.DisplayObjectRenderer; +import openfl.display.Graphics; +import openfl.display.OpenGLRenderer; +import openfl.display._internal.Context3DGraphics; +import openfl.display3D.Context3D; +import openfl.display3D.Context3DClearMask; +import openfl.filters.BitmapFilter; +import openfl.filters.BlurFilter; +import openfl.geom.ColorTransform; +import openfl.geom.Matrix; +import openfl.geom.Point; +import openfl.geom.Rectangle; +#if (js && html5) +import lime._internal.graphics.ImageCanvasUtil; +import openfl.display.CanvasRenderer; +import openfl.display._internal.CanvasGraphics as GfxRenderer; +#else +import openfl.display.CairoRenderer; +import openfl.display._internal.CairoGraphics as GfxRenderer; +#end + +/** + * A modified `FlxSprite` that supports filters. + * The name's pretty much self-explanatory. + * @author CheemsAndFriends + */ +@:access(openfl.geom.Rectangle) +@:access(openfl.filters.BitmapFilter) +@:access(flixel.graphics.frames.FlxFrame) +class FlxFilteredSprite extends FlxSprite +{ + @:noCompletion var _renderer:FlxAnimateFilterRenderer = new FlxAnimateFilterRenderer(); + + @:noCompletion var _filterMatrix:FlxMatrix; + + /** + * An `Array` of shader filters (aka `BitmapFilter`). + */ + public var filters(default, set):Array; + + /** + * a flag to update the image with the filters. + * Useful when trying to render a shader at all times. + */ + public var filterDirty:Bool = false; + + @:noCompletion var filtered:Bool; + + @:noCompletion var _blankFrame:FlxFrame; + + var _filterBmp1:BitmapData; + var _filterBmp2:BitmapData; + + override public function update(elapsed:Float) + { + super.update(elapsed); + if (!filterDirty && filters != null) + { + for (filter in filters) + { + if (filter.__renderDirty) + { + filterDirty = true; + break; + } + } + } + } + + @:noCompletion + override function initVars():Void + { + super.initVars(); + _filterMatrix = new FlxMatrix(); + filters = null; + filtered = false; + } + + override public function draw():Void + { + checkEmptyFrame(); + + if (alpha == 0 || _frame.type == FlxFrameType.EMPTY) return; + + if (dirty) // rarely + calcFrame(useFramePixels); + + if (filterDirty) filterFrame(); + + for (camera in cameras) + { + if (!camera.visible || !camera.exists || !isOnScreen(camera)) continue; + + getScreenPosition(_point, camera).subtractPoint(offset); + + if (isSimpleRender(camera)) drawSimple(camera); + else + drawComplex(camera); + + #if FLX_DEBUG + FlxBasic.visibleCount++; + #end + } + + #if FLX_DEBUG + if (FlxG.debugger.drawDebug) drawDebug(); + #end + } + + @:noCompletion + override function drawComplex(camera:FlxCamera):Void + { + _frame.prepareMatrix(_matrix, FlxFrameAngle.ANGLE_0, checkFlipX(), checkFlipY()); + _matrix.concat(_filterMatrix); + _matrix.translate(-origin.x, -origin.y); + _matrix.scale(scale.x, scale.y); + + if (bakedRotationAngle <= 0) + { + updateTrig(); + + if (angle != 0) _matrix.rotateWithTrig(_cosAngle, _sinAngle); + } + + _point.add(origin.x, origin.y); + _matrix.translate(_point.x, _point.y); + + if (isPixelPerfectRender(camera)) + { + _matrix.tx = Math.floor(_matrix.tx); + _matrix.ty = Math.floor(_matrix.ty); + } + + camera.drawPixels(_frame, framePixels, _matrix, colorTransform, blend, antialiasing, shader); + } + + @:noCompletion + function filterFrame() + { + filterDirty = false; + _filterMatrix.identity(); + var filteredFrame = (filtered) ? _frame : null; + + if (filters != null && filters.length > 0) + { + _flashRect.setEmpty(); + + for (filter in filters) + { + _flashRect.__expand(-filter.__leftExtension, + -filter.__topExtension, filter.__leftExtension + + filter.__rightExtension, + filter.__topExtension + + filter.__bottomExtension); + } + _flashRect.width += frameWidth; + _flashRect.height += frameHeight; + if (_blankFrame == null) _blankFrame = new FlxFrame(null); + + if (_blankFrame.parent == null || _flashRect.width > _blankFrame.parent.width || _flashRect.height > _blankFrame.parent.height) + { + if (_blankFrame.parent != null) + { + _blankFrame.parent.destroy(); + _filterBmp1.dispose(); + _filterBmp2.dispose(); + } + + _blankFrame.parent = FlxGraphic.fromRectangle(Math.ceil(_flashRect.width * 1.25), Math.ceil(_flashRect.height * 1.25), 0, true); + _filterBmp1 = new BitmapData(_blankFrame.parent.width, _blankFrame.parent.height, 0); + _filterBmp2 = new BitmapData(_blankFrame.parent.width, _blankFrame.parent.height, 0); + } + _blankFrame.offset.copyFrom(_frame.offset); + _blankFrame.parent.bitmap = _renderer.applyFilter(_blankFrame.parent.bitmap, _filterBmp1, _filterBmp2, frame.parent.bitmap, filters, _flashRect, + frame.frame.copyToFlash()); + _blankFrame.frame = FlxRect.get(0, 0, _blankFrame.parent.bitmap.width, _blankFrame.parent.bitmap.height); + _filterMatrix.translate(_flashRect.x, _flashRect.y); + _frame = _blankFrame.copyTo(); + filtered = true; + } + else + { + resetFrame(); + filtered = false; + } + } + + @:noCompletion + function set_filters(value:Array) + { + if (filters != value) filterDirty = true; + + return filters = value; + } + + @:noCompletion + override function set_frame(value:FlxFrame) + { + if (value != frame) filterDirty = true; + + return super.set_frame(value); + } +} + +@:noCompletion +@:access(openfl.display.OpenGLRenderer) +@:access(openfl.filters.BitmapFilter) +@:access(openfl.geom.Rectangle) +@:access(openfl.display.Stage) +@:access(openfl.display.Graphics) +@:access(openfl.display.Shader) +@:access(openfl.display.BitmapData) +@:access(openfl.geom.ColorTransform) +@:access(openfl.display.DisplayObject) +@:access(openfl.display3D.Context3D) +@:access(openfl.display.CanvasRenderer) +@:access(openfl.display.CairoRenderer) +@:access(openfl.display3D.Context3D) +class FlxAnimateFilterRenderer +{ + var renderer:OpenGLRenderer; + var context:Context3D; + + public function new() + { + // context = new openfl.display3D.Context3D(null); + renderer = new OpenGLRenderer(FlxG.game.stage.context3D); + renderer.__worldTransform = new Matrix(); + renderer.__worldColorTransform = new ColorTransform(); + } + + @:noCompletion function setRenderer(renderer:DisplayObjectRenderer, rect:Rectangle) + { + @:privateAccess + if (true) + { + var displayObject = FlxG.game; + var pixelRatio = FlxG.game.stage.__renderer.__pixelRatio; + + var offsetX = rect.x > 0 ? Math.ceil(rect.x) : Math.floor(rect.x); + var offsetY = rect.y > 0 ? Math.ceil(rect.y) : Math.floor(rect.y); + if (renderer.__worldTransform == null) + { + renderer.__worldTransform = new Matrix(); + renderer.__worldColorTransform = new ColorTransform(); + } + if (displayObject.__cacheBitmapColorTransform == null) displayObject.__cacheBitmapColorTransform = new ColorTransform(); + + renderer.__stage = displayObject.stage; + + renderer.__allowSmoothing = true; + renderer.__setBlendMode(NORMAL); + renderer.__worldAlpha = 1 / displayObject.__worldAlpha; + + renderer.__worldTransform.identity(); + renderer.__worldTransform.invert(); + renderer.__worldTransform.concat(new Matrix()); + renderer.__worldTransform.tx -= offsetX; + renderer.__worldTransform.ty -= offsetY; + renderer.__worldTransform.scale(pixelRatio, pixelRatio); + + renderer.__pixelRatio = pixelRatio; + } + } + + public function applyFilter(target:BitmapData = null, target1:BitmapData = null, target2:BitmapData = null, bmp:BitmapData, filters:Array, + rect:Rectangle, bmpRect:Rectangle) + { + if (filters == null || filters.length == 0) return bmp; + + renderer.__setBlendMode(NORMAL); + renderer.__worldAlpha = 1; + + if (renderer.__worldTransform == null) + { + renderer.__worldTransform = new Matrix(); + renderer.__worldColorTransform = new ColorTransform(); + } + renderer.__worldTransform.identity(); + renderer.__worldColorTransform.__identity(); + + var bitmap:BitmapData = (target == null) ? new BitmapData(Math.ceil(rect.width * 1.25), Math.ceil(rect.height * 1.25), true, 0) : target; + + var bitmap2 = (target1 == null) ? new BitmapData(Math.ceil(rect.width * 1.25), Math.ceil(rect.height * 1.25), true, 0) : target1, + bitmap3 = (target2 == null) ? bitmap2.clone() : target2; + renderer.__setRenderTarget(bitmap); + + bmp.__renderTransform.translate(Math.abs(rect.x) - bmpRect.x, Math.abs(rect.y) - bmpRect.y); + bmpRect.x = Math.abs(rect.x); + bmpRect.y = Math.abs(rect.y); + + var bestResolution = renderer.__context3D.__backBufferWantsBestResolution; + renderer.__context3D.__backBufferWantsBestResolution = false; + renderer.__scissorRect(bmpRect); + renderer.__renderFilterPass(bmp, renderer.__defaultDisplayShader, true); + renderer.__scissorRect(); + + renderer.__context3D.__backBufferWantsBestResolution = bestResolution; + + bmp.__renderTransform.identity(); + + var shader, cacheBitmap = null; + for (filter in filters) + { + if (filter.__preserveObject) + { + renderer.__setRenderTarget(bitmap3); + renderer.__renderFilterPass(bitmap, renderer.__defaultDisplayShader, filter.__smooth); + } + + for (i in 0...filter.__numShaderPasses) + { + shader = filter.__initShader(renderer, i, (filter.__preserveObject) ? bitmap3 : null); + renderer.__setBlendMode(filter.__shaderBlendMode); + renderer.__setRenderTarget(bitmap2); + renderer.__renderFilterPass(bitmap, shader, filter.__smooth); + + cacheBitmap = bitmap; + bitmap = bitmap2; + bitmap2 = cacheBitmap; + } + filter.__renderDirty = false; + } + if (target1 == null) bitmap2.dispose(); + if (target2 == null) bitmap3.dispose(); + + return bitmap; + } + + public function applyBlend(blend:BlendMode, bitmap:BitmapData) + { + bitmap.__update(false, true); + var bmp = new BitmapData(bitmap.width, bitmap.height, 0); + + #if (js && html5) + ImageCanvasUtil.convertToCanvas(bmp.image); + @:privateAccess + var renderer = new CanvasRenderer(bmp.image.buffer.__srcContext); + #else + var renderer = new CairoRenderer(new Cairo(bmp.getSurface())); + #end + + // setRenderer(renderer, bmp.rect); + + var m = new Matrix(); + var c = new ColorTransform(); + renderer.__allowSmoothing = true; + renderer.__overrideBlendMode = blend; + renderer.__worldTransform = m; + renderer.__worldAlpha = 1; + renderer.__worldColorTransform = c; + + renderer.__setBlendMode(blend); + #if (js && html5) + bmp.__drawCanvas(bitmap, renderer); + #else + bmp.__drawCairo(bitmap, renderer); + #end + + return bitmap; + } + + public function graphicstoBitmapData(gfx:Graphics) + { + if (gfx.__bounds == null) return null; + // var cacheRTT = renderer.__context3D.__state.renderToTexture; + // var cacheRTTDepthStencil = renderer.__context3D.__state.renderToTextureDepthStencil; + // var cacheRTTAntiAlias = renderer.__context3D.__state.renderToTextureAntiAlias; + // var cacheRTTSurfaceSelector = renderer.__context3D.__state.renderToTextureSurfaceSelector; + + // var bmp = new BitmapData(Math.ceil(gfx.__width), Math.ceil(gfx.__height), 0); + // renderer.__context3D.setRenderToTexture(bmp.getTexture(renderer.__context3D)); + // gfx.__owner.__renderTransform.identity(); + // gfx.__renderTransform.identity(); + // Context3DGraphics.render(gfx, renderer); + GfxRenderer.render(gfx, cast renderer.__softwareRenderer); + var bmp = gfx.__bitmap; + + gfx.__bitmap = null; + + // if (cacheRTT != null) + // { + // renderer.__context3D.setRenderToTexture(cacheRTT, cacheRTTDepthStencil, cacheRTTAntiAlias, cacheRTTSurfaceSelector); + // } + // else + // { + // renderer.__context3D.setRenderToBackBuffer(); + // } + + return bmp; + } +} diff --git a/source/funkin/ui/PixelatedIcon.hx b/source/funkin/ui/PixelatedIcon.hx index d1ea652c3..4252c9695 100644 --- a/source/funkin/ui/PixelatedIcon.hx +++ b/source/funkin/ui/PixelatedIcon.hx @@ -1,12 +1,13 @@ package funkin.ui; import flixel.FlxSprite; +import funkin.graphics.FlxFilteredSprite; /** * The icon that gets used for Freeplay capsules and char select * NOT to be confused with the CharIcon class, which is for the in-game icons */ -class PixelatedIcon extends FlxSprite +class PixelatedIcon extends FlxFilteredSprite { public function new(x:Float, y:Float) { diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index a2fe4a7dc..e2b662c14 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -16,6 +16,7 @@ import funkin.audio.FunkinSound; import funkin.data.freeplay.player.PlayerData; import funkin.data.freeplay.player.PlayerRegistry; import funkin.graphics.adobeanimate.FlxAtlasSprite; +import openfl.filters.DropShadowFilter; import funkin.graphics.FunkinCamera; import funkin.modding.events.ScriptEvent; import funkin.modding.events.ScriptEventDispatcher; @@ -672,6 +673,7 @@ class CharSelectSubState extends MusicBeatSubState if (index == getCurrentSelected()) { // memb.pixels = memb.withDropShadow.clone(); + if (memb.scale.x != 2.6) memb.filters = [new DropShadowFilter()]; memb.scale.set(2.6, 2.6); if (controls.ACCEPT) memb.animation.play("confirm"); @@ -687,6 +689,7 @@ class CharSelectSubState extends MusicBeatSubState else { // memb.pixels = memb.noDropShadow.clone(); + if (memb.scale.x == 2) memb.filters = []; memb.scale.set(2, 2); } } From c45fa93786453077da19b9940e8f94622351bf68 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 6 Sep 2024 16:46:11 -0400 Subject: [PATCH 675/870] update lime (ndlls) --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index 3cd8d5d3d..35c40798b 100644 --- a/hmm.json +++ b/hmm.json @@ -145,7 +145,7 @@ "name": "lime", "type": "git", "dir": null, - "ref": "e0b2339e02fff91168789dbd1a0dd019ea3dda39", + "ref": "fe3368f611a84a19afc03011353945ae4da8fffd", "url": "https://github.com/FunkinCrew/lime" }, { From 4f666e48559f823e670b2f69538c6301d3410144 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 6 Sep 2024 19:12:36 -0400 Subject: [PATCH 676/870] creds merge --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index a9f81e916..0ffaac38e 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit a9f81e916f673c5084851b56ee37a2952e9f9587 +Subproject commit 0ffaac38e32afe8cb95e896f7fa4db43bb3d884d From 89e1cb82588f80a0f6f9af6ab820365d68a35938 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 6 Sep 2024 19:44:33 -0400 Subject: [PATCH 677/870] small null fix for if we're not playing music --- source/funkin/ui/charSelect/CharacterUnlockState.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/charSelect/CharacterUnlockState.hx b/source/funkin/ui/charSelect/CharacterUnlockState.hx index 25cd1baf0..b32a35145 100644 --- a/source/funkin/ui/charSelect/CharacterUnlockState.hx +++ b/source/funkin/ui/charSelect/CharacterUnlockState.hx @@ -103,7 +103,7 @@ class CharacterUnlockState extends MusicBeatState function handleMusic():Void { - FlxG.sound.music.stop(); + FlxG.sound.music?.stop(); FlxG.sound.play(Paths.sound('confirmMenu')); } From e0a4818e5a781b4bcf1d58484cc7ee9a93e5ea8c Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Sat, 7 Sep 2024 00:52:38 +0100 Subject: [PATCH 678/870] registry updates --- source/funkin/data/stage/StageRegistry.hx | 4 ++-- source/funkin/ui/debug/charting/ChartEditorState.hx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/funkin/data/stage/StageRegistry.hx b/source/funkin/data/stage/StageRegistry.hx index 3d3779bce..87113ef05 100644 --- a/source/funkin/data/stage/StageRegistry.hx +++ b/source/funkin/data/stage/StageRegistry.hx @@ -93,8 +93,8 @@ class StageRegistry extends BaseRegistry public function listBaseGameStageIds():Array { return [ - "mainStage", "mainStageErect", "spookyMansion", "phillyTrain", "phillyTrainErect", "limoRide", "limoRideErect", "mallXmas", "mallEvil", "school", - "schoolEvil", "tankmanBattlefield", "phillyStreets", "phillyStreetsErect", "phillyBlazin", + "mainStage", "mainStageErect", "spookyMansion", "phillyTrain", "phillyTrainErect", "limoRide", "limoRideErect", "mallXmas", "mallXmasErect", "mallEvil", + "school", "schoolEvil", "tankmanBattlefield", "phillyStreets", "phillyStreetsErect", "phillyBlazin", ]; } diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 20d39183b..811e08e5d 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -5707,7 +5707,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState PlayStatePlaylist.campaignId = 'week3'; case 'limoRide' | 'limoRideErect': PlayStatePlaylist.campaignId = 'week4'; - case 'mallXmas' | 'mallEvil': + case 'mallXmas' | 'mallXmasErect' | 'mallEvil': PlayStatePlaylist.campaignId = 'week5'; case 'school' | 'schoolEvil': PlayStatePlaylist.campaignId = 'week6'; From 40b5ad7c2a7d32c13af8a5c7a83b7c58ce2e1dfe Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Sat, 7 Sep 2024 00:54:21 +0100 Subject: [PATCH 679/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index f1c74ef59..c430b1c7b 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit f1c74ef595a29d11544492e0dc907ba9a21d7c4f +Subproject commit c430b1c7b20efbd5062df17e31b5de0add6a62ff From f3722e5da2643660805ce6c3b466013c50c0d5f0 Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Sat, 7 Sep 2024 02:07:00 +0200 Subject: [PATCH 680/870] Add hmm flxanimate, new conditional for Cheems' PC sake and more wip char select animation --- assets | 2 +- hmm.json | 4 +- source/Main.hx | 2 +- .../ui/charSelect/CharSelectSubState.hx | 100 ++++++++++-------- source/funkin/ui/charSelect/Lock.hx | 1 - 5 files changed, 62 insertions(+), 47 deletions(-) diff --git a/assets b/assets index f73c8f479..d2ea072f3 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit f73c8f4798bfcd23c98db03bcde2e0afcbce4cfd +Subproject commit d2ea072f32d0ba74cf8c62576f28e7b03d591ddb diff --git a/hmm.json b/hmm.json index 3cd8d5d3d..eefaf86d5 100644 --- a/hmm.json +++ b/hmm.json @@ -46,7 +46,7 @@ "name": "flxanimate", "type": "git", "dir": null, - "ref": "27a0a1f0afc1074f619991472fb3ee209aad28df", + "ref": "280d1a46ac60021d08bb18181631cbd6d061782c", "url": "https://github.com/Dot-Stuff/flxanimate" }, { @@ -205,4 +205,4 @@ "url": "https://github.com/fponticelli/thx.semver" } ] -} +} \ No newline at end of file diff --git a/source/Main.hx b/source/Main.hx index 2426fa0d9..dc462ee5c 100644 --- a/source/Main.hx +++ b/source/Main.hx @@ -22,7 +22,7 @@ class Main extends Sprite var gameHeight:Int = 720; // Height of the game in pixels (might be less / more in actual pixels depending on your zoom). var initialState:Class = funkin.InitState; // The FlxState the game starts with. var zoom:Float = -1; // If -1, zoom is automatically calculated to fit the window dimensions. - #if web + #if (web || CHEEMS) var framerate:Int = 60; // How many frames per second the game should run at. #else // TODO: This should probably be in the options menu? diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index 3c53fe916..80ad59439 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -78,6 +78,7 @@ class CharSelectSubState extends MusicBeatSubState var selectTimer:FlxTimer = new FlxTimer(); var selectSound:FunkinSound; + var unlockSound:FunkinSound; var charSelectCam:FunkinCamera; @@ -270,6 +271,20 @@ class CharSelectSubState extends MusicBeatSubState grpCursors.add(cursorBlue); grpCursors.add(cursor); + selectSound = new FunkinSound(); + selectSound.loadEmbedded(Paths.sound('CS_select')); + selectSound.pitch = 1; + selectSound.volume = 0.7; + + FlxG.sound.defaultSoundGroup.add(selectSound); + + unlockSound = new FunkinSound(); + unlockSound.loadEmbedded(Paths.sound('CS_unlock')); + unlockSound.pitch = 1; + unlockSound.volume = 0.7; + + FlxG.sound.defaultSoundGroup.add(unlockSound); + initLocks(); for (index => member in grpIcons.members) @@ -301,13 +316,6 @@ class CharSelectSubState extends MusicBeatSubState add(temp); temp.alpha = 0.0; - selectSound = new FunkinSound(); - selectSound.loadEmbedded(Paths.sound('CS_select')); - selectSound.pitch = 1; - selectSound.volume = 0.7; - - FlxG.sound.defaultSoundGroup.add(selectSound); - Conductor.stepHit.add(spamOnStep); // FlxG.debugger.track(temp, "tempBG"); @@ -394,58 +402,66 @@ class CharSelectSubState extends MusicBeatSubState var copy = 3; - var yThing = 0; + var yThing = -1; - while (index > copy) + while ((index + 1) > copy) { yThing++; copy += 3; } - var xThing = copy - index - 1; + var xThing = (copy - index - 2) * -1; + // Look, I'd write better code but I had better aneurysms, my bad - Cheems + cursorY = yThing; + cursorX = xThing; - cursorY = 3 - yThing; - cursorX = 3 - xThing; + selectSound.play(true); + + nonLocks.shift(); selectTimer.start(1, function(_) { var lock:Lock = cast grpIcons.group.members[index]; + lock.anim.getFrameLabel("unlockAnim").add(function() { + playerChillOut.playAnimation("death"); + }); + lock.playAnimation("unlock"); + unlockSound.play(true); + + lock.onAnimationComplete.addOnce(function(_) { + camera.flash(0xFFFFFFFF, 0.1); + playerChill.playAnimation("unlock"); + playerChill.visible = true; + + if (nonLocks.length == 0) + { + FunkinSound.playMusic('stayFunky', + { + startingVolume: 1, + overrideExisting: true, + restartTrack: true, + onLoad: function() { + @:privateAccess + gfChill.analyzer = new SpectralAnalyzer(FlxG.sound.music._channel.__audioSource, 7, 0.1); + #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! + @:privateAccess + gfChill.analyzer.fftN = 512; + #end + } + }); + } + else + playerChill.onAnimationComplete.addOnce((_) -> unLock()); + }); + playerChill.visible = false; playerChill.switchChar(availableChars[index]); playerChillOut.visible = true; - playerChillOut.playAnimation("death"); - playerChillOut.onAnimationComplete.addOnce((_) -> if (_ == "death") - { - playerChill.playAnimation("unlock"); - playerChill.onAnimationComplete.addOnce(function(_) { - nonLocks.shift(); - - if (nonLocks.length > 0) unLock(); - else - { - FunkinSound.playMusic('stayFunky', - { - startingVolume: 1, - overrideExisting: true, - restartTrack: true, - onLoad: function() { - @:privateAccess - gfChill.analyzer = new SpectralAnalyzer(FlxG.sound.music._channel.__audioSource, 7, 0.1); - #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! - @:privateAccess - gfChill.analyzer.fftN = 512; - #end - } - }); - } - }); - playerChill.visible = true; - }); }); } diff --git a/source/funkin/ui/charSelect/Lock.hx b/source/funkin/ui/charSelect/Lock.hx index 42e5d63f4..982145d5c 100644 --- a/source/funkin/ui/charSelect/Lock.hx +++ b/source/funkin/ui/charSelect/Lock.hx @@ -20,7 +20,6 @@ class Lock extends FlxAtlasSprite var arr:Array = ["lock", "lock top 1", "lock top 2", "lock top 3", "lock base fuck it"]; - onAnimationComplete.add((_) -> if (_ == "unlock") playAnimation("idle")); var func = function(name) { var symbol = anim.symbolDictionary[name]; if (symbol != null && symbol.timeline.get("color") != null) symbol.timeline.get("color").get(0).colorEffect = tint; From 77346696f834fa7e628c19c50e0f5e9d974cff33 Mon Sep 17 00:00:00 2001 From: lemz Date: Sat, 7 Sep 2024 19:49:08 +0200 Subject: [PATCH 681/870] Update MusicBeatSubState.hx --- source/funkin/ui/MusicBeatSubState.hx | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/source/funkin/ui/MusicBeatSubState.hx b/source/funkin/ui/MusicBeatSubState.hx index 9035d12ff..614961d70 100644 --- a/source/funkin/ui/MusicBeatSubState.hx +++ b/source/funkin/ui/MusicBeatSubState.hx @@ -37,17 +37,25 @@ class MusicBeatSubState extends FlxSubState implements IEventHandler return _conductorInUse = value; } - public function new(bgColor:FlxColor = FlxColor.TRANSPARENT) - { - super(); - this.bgColor = bgColor; - } - var controls(get, never):Controls; inline function get_controls():Controls return PlayerSettings.player1.controls; + public function new(bgColor:FlxColor = FlxColor.TRANSPARENT) + { + super(); + this.bgColor = bgColor; + + initCallbacks(); + } + + function initCallbacks() + { + subStateOpened.add(onOpenSubStateComplete); + subStateClosed.add(onCloseSubStateComplete); + } + override function create():Void { super.create(); From 51e5eb929ce70ad314d827bcf30f39b8d7449854 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sun, 8 Sep 2024 11:22:24 -0400 Subject: [PATCH 682/870] add hxjsonast to hmm.json to fix builds? --- hmm.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index 35c40798b..ea32399f8 100644 --- a/hmm.json +++ b/hmm.json @@ -115,6 +115,13 @@ "ref": "147294123f983e35f50a966741474438069a7a8f", "url": "https://github.com/FunkinCrew/hxcpp-debugger" }, + { + "name": "hxjsonast", + "type": "git", + "dir": null, + "ref": "20e72cc68c823496359775ac1f06500e67f189d5", + "url": "https://github.com/nadako/hxjsonast/" + }, { "name": "hxp", "type": "haxelib", @@ -205,4 +212,4 @@ "url": "https://github.com/fponticelli/thx.semver" } ] -} +} \ No newline at end of file From 4f1423870cb6248cc8bdb0d2e9696b278e24a982 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sun, 8 Sep 2024 14:44:22 -0400 Subject: [PATCH 683/870] Update assets submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 5af650e1a..2b48f3d9e 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 5af650e1ac562f95e03f6484d7fa33d7d83f5c8d +Subproject commit 2b48f3d9e2a83c6eb9d4dd1a9dada5f35b87d49b From 16905c8210b0ada422d2552d3908f70cf9c6a2d3 Mon Sep 17 00:00:00 2001 From: Abnormal <86753001+AbnormalPoof@users.noreply.github.com> Date: Sun, 8 Sep 2024 21:48:48 +0000 Subject: [PATCH 684/870] Update ScriptedFunkinSprite.hx --- source/funkin/modding/base/ScriptedFunkinSprite.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/modding/base/ScriptedFunkinSprite.hx b/source/funkin/modding/base/ScriptedFunkinSprite.hx index dd8d15007..2ce84db3e 100644 --- a/source/funkin/modding/base/ScriptedFunkinSprite.hx +++ b/source/funkin/modding/base/ScriptedFunkinSprite.hx @@ -1,8 +1,8 @@ package funkin.modding.base; /** - * A script that can be tied to an FlxSprite. - * Create a scripted class that extends FlxSprite to use this. + * A script that can be tied to a FunkinSprite. + * Create a scripted class that extends FunkinSprite to use this. */ @:hscriptClass class ScriptedFunkinSprite extends funkin.graphics.FunkinSprite implements HScriptedClass {} From 6961e6cc63f9e9fc63cf8007eba8a82c82c86389 Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Mon, 9 Sep 2024 08:23:46 +0200 Subject: [PATCH 685/870] Add a buncho Gizmos --- art | 2 +- assets | 2 +- source/funkin/graphics/FlxFilteredSprite.hx | 19 ++- .../graphics/adobeanimate/FlxAtlasSprite.hx | 5 +- source/funkin/save/Save.hx | 2 +- source/funkin/ui/charSelect/CharSelectGF.hx | 2 +- .../funkin/ui/charSelect/CharSelectPlayer.hx | 11 +- .../ui/charSelect/CharSelectSubState.hx | 143 +++++++++++++++--- source/funkin/ui/title/TitleState.hx | 3 + source/funkin/util/FramesJSFLParser.hx | 19 ++- source/funkin/util/logging/AnsiTrace.hx | 3 + 11 files changed, 174 insertions(+), 37 deletions(-) diff --git a/art b/art index faeba700c..e2663c1cb 160000 --- a/art +++ b/art @@ -1 +1 @@ -Subproject commit faeba700c5526bd4fd57ccc927d875c82b9d3553 +Subproject commit e2663c1cbe029f04a98500735943f0b9465548bf diff --git a/assets b/assets index d2ea072f3..c6a2a13d7 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit d2ea072f32d0ba74cf8c62576f28e7b03d591ddb +Subproject commit c6a2a13d754e3566d25e762acec3a74e7116f23e diff --git a/source/funkin/graphics/FlxFilteredSprite.hx b/source/funkin/graphics/FlxFilteredSprite.hx index 3563ea976..af4418d60 100644 --- a/source/funkin/graphics/FlxFilteredSprite.hx +++ b/source/funkin/graphics/FlxFilteredSprite.hx @@ -37,7 +37,6 @@ import openfl.display._internal.CairoGraphics as GfxRenderer; /** * A modified `FlxSprite` that supports filters. * The name's pretty much self-explanatory. - * @author CheemsAndFriends */ @:access(openfl.geom.Rectangle) @:access(openfl.filters.BitmapFilter) @@ -146,7 +145,7 @@ class FlxFilteredSprite extends FlxSprite _matrix.ty = Math.floor(_matrix.ty); } - camera.drawPixels(_frame, framePixels, _matrix, colorTransform, blend, antialiasing, shader); + camera.drawPixels((filtered) ? _blankFrame : _frame, framePixels, _matrix, colorTransform, blend, antialiasing, shader); } @:noCompletion @@ -154,7 +153,6 @@ class FlxFilteredSprite extends FlxSprite { filterDirty = false; _filterMatrix.identity(); - var filteredFrame = (filtered) ? _frame : null; if (filters != null && filters.length > 0) { @@ -195,6 +193,7 @@ class FlxFilteredSprite extends FlxSprite } else { + trace("GAGAGA"); resetFrame(); filtered = false; } @@ -215,6 +214,11 @@ class FlxFilteredSprite extends FlxSprite return super.set_frame(value); } + + override public function destroy() + { + super.destroy(); + } } @:noCompletion @@ -339,6 +343,15 @@ class FlxAnimateFilterRenderer if (target1 == null) bitmap2.dispose(); if (target2 == null) bitmap3.dispose(); + // var gl = renderer.__gl; + + // var renderBuffer = bitmap.getTexture(renderer.__context3D); + // @:privateAccess + // gl.readPixels(0, 0, bitmap.width, bitmap.height, renderBuffer.__format, gl.UNSIGNED_BYTE, bitmap.image.data); + // bitmap.image.version = 0; + // @:privateAccess + // bitmap.__textureVersion = -1; + return bitmap; } diff --git a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx index e187c7808..d4df2a4f7 100644 --- a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx +++ b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx @@ -217,6 +217,9 @@ class FlxAtlasSprite extends FlxAnimate { if (this.anim == null) return false; if (!this.anim.isPlaying) return false; + + if (fr != null) return (anim.reversed && anim.curFrame < fr.index || !anim.reversed && anim.curFrame >= (fr.index + fr.duration)); + return (anim.reversed && anim.curFrame == 0 || !(anim.reversed) && (anim.curFrame) >= (anim.length - 1)); } @@ -283,7 +286,7 @@ class FlxAtlasSprite extends FlxAnimate { onAnimationFrame.dispatch(currentAnimation, frame); - if (fr != null && frame > (fr.index + fr.duration - 1) || isLoopComplete()) + if (isLoopComplete()) { anim.pause(); _onAnimationComplete(); diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx index a3d945594..80b05e5ac 100644 --- a/source/funkin/save/Save.hx +++ b/source/funkin/save/Save.hx @@ -412,7 +412,7 @@ class Save */ public function addCharacterSeen(character:String):Void { - data.unlocks.charactersSeen.push(character); + if (!data.unlocks.charactersSeen.contains(character)) data.unlocks.charactersSeen.push(character); } /** diff --git a/source/funkin/ui/charSelect/CharSelectGF.hx b/source/funkin/ui/charSelect/CharSelectGF.hx index a990db817..e8eeded40 100644 --- a/source/funkin/ui/charSelect/CharSelectGF.hx +++ b/source/funkin/ui/charSelect/CharSelectGF.hx @@ -133,7 +133,7 @@ class CharSelectGF extends FlxAtlasSprite implements IBPMSyncedScriptedClass fadeTimer += FlxG.elapsed; if (fadeTimer >= 1 / 24) { - fadeTimer = 0; + fadeTimer -= FlxG.elapsed; // only inc the index for the first frame, used for reference of where to "start" if (fadeAnimIndex == 0) { diff --git a/source/funkin/ui/charSelect/CharSelectPlayer.hx b/source/funkin/ui/charSelect/CharSelectPlayer.hx index 8809ad29b..9767c2d3b 100644 --- a/source/funkin/ui/charSelect/CharSelectPlayer.hx +++ b/source/funkin/ui/charSelect/CharSelectPlayer.hx @@ -26,19 +26,17 @@ class CharSelectPlayer extends FlxAtlasSprite implements IBPMSyncedScriptedClass } else { - playAnimation("idle", true, false, true); + playAnimation("idle", true, false, false); } + case "deselect": + playAnimation("deselect loop start", true, false, true); case "slidein idle point", "cannot select", "unlock": - playAnimation("idle", true, false, true); + playAnimation("idle", true, false, false); case "idle": trace('Waiting for onBeatHit'); } }); - - onAnimationFrame.add(function(animLabel:String, frame:Int) { - if (animLabel == "deselect" && desLp != null && frame >= desLp.index) playAnimation("deselect loop start", true, false, true); - }); } public function onStepHit(event:SongTimeScriptEvent):Void {} @@ -50,6 +48,7 @@ class CharSelectPlayer extends FlxAtlasSprite implements IBPMSyncedScriptedClass // I tried make this not interrupt an existing idle, // but isAnimationFinished() and isLoopComplete() both don't work! What the hell? // danceEvery isn't necessary if that gets fixed. + // if (getCurrentAnimation() == "idle") { trace('Player beat hit'); diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index 80ad59439..818b68c1c 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -1,5 +1,6 @@ package funkin.ui.charSelect; +import openfl.filters.BitmapFilter; import flixel.FlxObject; import flixel.FlxSprite; import flixel.group.FlxGroup; @@ -31,6 +32,9 @@ import funkin.vis.dsp.SpectralAnalyzer; import openfl.display.BlendMode; import funkin.save.Save; import openfl.filters.ShaderFilter; +import funkin.util.FramesJSFLParser; +import funkin.util.FramesJSFLParser.FramesJSFLInfo; +import funkin.util.FramesJSFLParser.FramesJSFLFrame; class CharSelectSubState extends MusicBeatSubState { @@ -82,10 +86,16 @@ class CharSelectSubState extends MusicBeatSubState var charSelectCam:FunkinCamera; + var selectedBizz:Array = [ + new DropShadowFilter(0, 0, 0xFFFFFF, 1, 2, 2, 21, 1, false, false, false), + new DropShadowFilter(5, 45, 0x000000, 1, 2, 2, 1, 1, false, false, false) + ]; + + var bopInfo:FramesJSFLInfo; + public function new() { super(); - loadAvailableCharacters(); } @@ -119,6 +129,8 @@ class CharSelectSubState extends MusicBeatSubState { super.create(); + bopInfo = FramesJSFLParser.parse(Paths.file("images/charSelect/iconBopInfo/iconBopInfo.txt")); + var bg:FlxSprite = new FlxSprite(-153, -140); bg.loadGraphic(Paths.image('charSelect/charSelectBG')); bg.scrollFactor.set(0.1, 0.1); @@ -281,10 +293,21 @@ class CharSelectSubState extends MusicBeatSubState unlockSound = new FunkinSound(); unlockSound.loadEmbedded(Paths.sound('CS_unlock')); unlockSound.pitch = 1; - unlockSound.volume = 0.7; + + unlockSound.volume = 0; + unlockSound.play(true); FlxG.sound.defaultSoundGroup.add(unlockSound); + // playing it here to preload it. not doing this makes a super awkward pause at the end of the intro + // TODO: probably make an intro thing for funkinSound itself that preloads the next audio? + FunkinSound.playMusic('stayFunky', + { + startingVolume: 0, + overrideExisting: true, + restartTrack: true, + }); + initLocks(); for (index => member in grpIcons.members) @@ -384,16 +407,24 @@ class CharSelectSubState extends MusicBeatSubState grpIcons.scrollFactor.set(); - // playing it here to preload it. not doing this makes a super awkward pause at the end of the intro - // TODO: probably make an intro thing for funkinSound itself that preloads the next audio? - FunkinSound.playMusic('stayFunky', - { - startingVolume: 0, - overrideExisting: true, - restartTrack: true, - }); - - unLock(); + if (nonLocks.length > 0) unLock(); + else + FunkinSound.playMusic('stayFunky', + { + startingVolume: 1, + overrideExisting: true, + restartTrack: true, + onLoad: function() { + @:privateAccess + gfChill.analyzer = new SpectralAnalyzer(FlxG.sound.music._channel.__audioSource, 7, 0.1); + #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! + @:privateAccess + gfChill.analyzer.fftN = 512; + #end + } + }); } function unLock() @@ -428,15 +459,37 @@ class CharSelectSubState extends MusicBeatSubState lock.playAnimation("unlock"); + unlockSound.volume = 0.7; unlockSound.play(true); lock.onAnimationComplete.addOnce(function(_) { + var char = availableChars.get(index); camera.flash(0xFFFFFFFF, 0.1); playerChill.playAnimation("unlock"); playerChill.visible = true; + var id = grpIcons.members.indexOf(lock); + + nametag.switchChar(char); + gfChill.switchGF(char); + + var icon = new PixelatedIcon(0, 0); + icon.setCharacter(char); + icon.setGraphicSize(128, 128); + icon.updateHitbox(); + grpIcons.insert(id, icon); + grpIcons.remove(lock, true); + icon.ID = 0; + + bopPlay = true; + + updateIconPositions(); + if (nonLocks.length == 0) { + playerChillOut.onAnimationComplete.addOnce((_) -> playerChillOut.switchChar(char)); + @:bypassAccessor curChar = char; + Save.instance.addCharacterSeen(char); FunkinSound.playMusic('stayFunky', { startingVolume: 1, @@ -713,6 +766,48 @@ class CharSelectSubState extends MusicBeatSubState cursorDarkBlue.y = MathUtil.coolLerp(cursorDarkBlue.y, cursorLocIntended.y, lerpAmnt * 0.2); } + var bopTimer:Float = 0; + + var delay = 1 / 24; + + var bopFr = 0; + + var bopPlay:Bool = false; + + var bopRefX:Float = 0; + var bopRefY:Float = 0; + + function doBop(icon:PixelatedIcon, elapsed:Float):Void + { + if (bopFr >= bopInfo.frames.length) + { + bopRefX = 0; + bopRefY = 0; + bopPlay = false; + bopFr = 0; + return; + } + bopTimer += elapsed; + + if (bopTimer >= delay) + { + bopTimer -= bopTimer; + + var refFrame = bopInfo.frames[bopInfo.frames.length - 1]; + var curFrame = bopInfo.frames[bopFr]; + + var xDiff:Float = curFrame.x - refFrame.x; + var yDiff:Float = curFrame.y - refFrame.y; + var scaleXDiff:Float = curFrame.scaleX - refFrame.scaleX; + var scaleYDiff:Float = curFrame.scaleY - refFrame.scaleY; + + icon.scale.set(2.6, 2.6); + icon.scale.add(scaleXDiff, scaleYDiff); + + bopFr++; + } + } + public override function dispatchEvent(event:ScriptEvent):Void { // super.dispatchEvent(event) dispatches event to module scripts. @@ -725,11 +820,6 @@ class CharSelectSubState extends MusicBeatSubState function spamOnStep():Void { - if (FlxG.keys.justPressed.B) - { - cursorY = 3; - cursorX = 3; - } if (spamUp || spamDown || spamLeft || spamRight) { // selectSound.changePitchBySemitone(1); @@ -776,7 +866,7 @@ class CharSelectSubState extends MusicBeatSubState case "idle": lock.playAnimation("selected"); case "selected" | "clicked": - if (controls.ACCEPT) lock.playAnimation((FlxG.keys.pressed.CONTROL) ? "unlock" : "clicked", true); + if (controls.ACCEPT) lock.playAnimation("clicked", true); } } else @@ -789,8 +879,19 @@ class CharSelectSubState extends MusicBeatSubState if (index == getCurrentSelected()) { // memb.pixels = memb.withDropShadow.clone(); - if (memb.scale.x != 2.6) memb.filters = [new DropShadowFilter()]; - memb.scale.set(2.6, 2.6); + memb.filters = selectedBizz; + + if (bopPlay) + { + if (bopRefX == 0) + { + bopRefX = memb.x; + bopRefY = memb.y; + } + doBop(memb, FlxG.elapsed); + } + else + memb.scale.set(2.6, 2.6); if (controls.ACCEPT) memb.animation.play("confirm"); if (memb.animation.curAnim.name == "confirm" && controls.BACK) @@ -805,7 +906,7 @@ class CharSelectSubState extends MusicBeatSubState else { // memb.pixels = memb.noDropShadow.clone(); - if (memb.scale.x == 2) memb.filters = []; + memb.filters = null; memb.scale.set(2, 2); } } diff --git a/source/funkin/ui/title/TitleState.hx b/source/funkin/ui/title/TitleState.hx index 8087916cb..79b30ff4d 100644 --- a/source/funkin/ui/title/TitleState.hx +++ b/source/funkin/ui/title/TitleState.hx @@ -32,6 +32,7 @@ import openfl.media.Video; import openfl.net.NetStream; import funkin.api.newgrounds.NGio; import openfl.display.BlendMode; +import funkin.save.Save; #if desktop #end @@ -272,6 +273,8 @@ class TitleState extends MusicBeatState } #end + if (Save.instance.charactersSeen.contains("pico")) Save.instance.charactersSeen.remove("pico"); + Conductor.instance.update(); /* if (FlxG.onMobile) diff --git a/source/funkin/util/FramesJSFLParser.hx b/source/funkin/util/FramesJSFLParser.hx index 33bcf9d9d..fa01a2c87 100644 --- a/source/funkin/util/FramesJSFLParser.hx +++ b/source/funkin/util/FramesJSFLParser.hx @@ -25,9 +25,22 @@ class FramesJSFLParser var x:Float = Std.parseFloat(frameInfo[0]); var y:Float = Std.parseFloat(frameInfo[1]); - var alpha:Float = Std.parseFloat(frameInfo[2]); + var alpha:Float = (frameInfo[2] != "undefined") ? Std.parseFloat(frameInfo[2]) : 100; - var shit:FramesJSFLFrame = {x: x, y: y, alpha: alpha}; + var scaleX:Float = 1; + var scaleY:Float = 1; + + if (frameInfo[3] != null) scaleX = Std.parseFloat(frameInfo[4]); + if (frameInfo[4] != null) scaleX = Std.parseFloat(frameInfo[4]); + + var shit:FramesJSFLFrame = + { + x: x, + y: y, + alpha: alpha, + scaleX: scaleX, + scaleY: scaleY + }; output.frames.push(shit); } @@ -45,4 +58,6 @@ typedef FramesJSFLFrame = var x:Float; var y:Float; var alpha:Float; + var scaleX:Float; + var scaleY:Float; } diff --git a/source/funkin/util/logging/AnsiTrace.hx b/source/funkin/util/logging/AnsiTrace.hx index 2c18d494d..322a66820 100644 --- a/source/funkin/util/logging/AnsiTrace.hx +++ b/source/funkin/util/logging/AnsiTrace.hx @@ -6,6 +6,9 @@ class AnsiTrace // but adds nice cute ANSI things public static function trace(v:Dynamic, ?info:haxe.PosInfos) { + #if TREMOVE + return; + #end var str = formatOutput(v, info); #if js if (js.Syntax.typeof(untyped console) != "undefined" && (untyped console).log != null) (untyped console).log(str); From f8a2709482ec00b03c9bc77cd5128d6918ba63aa Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Mon, 9 Sep 2024 08:03:06 +0100 Subject: [PATCH 686/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 5af650e1a..08b78bdb4 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 5af650e1ac562f95e03f6484d7fa33d7d83f5c8d +Subproject commit 08b78bdb4a3e14c487a5cb51dffff29f20c240df From 50d2a8fd9d7e1475be54906d455243ed1108846d Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Mon, 9 Sep 2024 08:06:11 +0100 Subject: [PATCH 687/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 5af650e1a..3879a4905 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 5af650e1ac562f95e03f6484d7fa33d7d83f5c8d +Subproject commit 3879a4905a96c3bbe0756fe49f07902041e893d3 From b9b849024334102b6d7a17d323d9460b96b57444 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Mon, 9 Sep 2024 08:09:40 +0100 Subject: [PATCH 688/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 08b78bdb4..8791959f4 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 08b78bdb4a3e14c487a5cb51dffff29f20c240df +Subproject commit 8791959f4643d838cccb5b582b5a20df964f673a From d61357b80db4eaa1b929009726de0e3555539015 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 9 Sep 2024 11:40:17 -0400 Subject: [PATCH 689/870] hmm flxanimate bump --- hmm.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hmm.json b/hmm.json index ea32399f8..5205603c9 100644 --- a/hmm.json +++ b/hmm.json @@ -46,7 +46,7 @@ "name": "flxanimate", "type": "git", "dir": null, - "ref": "27a0a1f0afc1074f619991472fb3ee209aad28df", + "ref": "280d1a46ac60021d08bb18181631cbd6d061782c", "url": "https://github.com/Dot-Stuff/flxanimate" }, { @@ -212,4 +212,4 @@ "url": "https://github.com/fponticelli/thx.semver" } ] -} \ No newline at end of file +} From 35af057f88ef52da2488d556d092e26f6f950f98 Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Mon, 9 Sep 2024 17:41:25 +0200 Subject: [PATCH 690/870] Fix scaleY not parsing --- source/funkin/ui/charSelect/CharSelectSubState.hx | 9 ++++----- source/funkin/util/FramesJSFLParser.hx | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index 818b68c1c..db8844288 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -110,8 +110,6 @@ class CharSelectSubState extends MusicBeatSubState var playerData = player.getCharSelectData(); if (playerData == null) continue; - trace(player.isUnlocked()); - var targetPosition:Int = playerData.position ?? 0; while (availableChars.exists(targetPosition)) { @@ -487,7 +485,10 @@ class CharSelectSubState extends MusicBeatSubState if (nonLocks.length == 0) { - playerChillOut.onAnimationComplete.addOnce((_) -> playerChillOut.switchChar(char)); + playerChillOut.onAnimationComplete.addOnce((_) -> { + playerChillOut.visible = false; + playerChillOut.switchChar(char); + }); @:bypassAccessor curChar = char; Save.instance.addCharacterSeen(char); FunkinSound.playMusic('stayFunky', @@ -796,8 +797,6 @@ class CharSelectSubState extends MusicBeatSubState var refFrame = bopInfo.frames[bopInfo.frames.length - 1]; var curFrame = bopInfo.frames[bopFr]; - var xDiff:Float = curFrame.x - refFrame.x; - var yDiff:Float = curFrame.y - refFrame.y; var scaleXDiff:Float = curFrame.scaleX - refFrame.scaleX; var scaleYDiff:Float = curFrame.scaleY - refFrame.scaleY; diff --git a/source/funkin/util/FramesJSFLParser.hx b/source/funkin/util/FramesJSFLParser.hx index fa01a2c87..3a9ff8d0a 100644 --- a/source/funkin/util/FramesJSFLParser.hx +++ b/source/funkin/util/FramesJSFLParser.hx @@ -31,7 +31,7 @@ class FramesJSFLParser var scaleY:Float = 1; if (frameInfo[3] != null) scaleX = Std.parseFloat(frameInfo[4]); - if (frameInfo[4] != null) scaleX = Std.parseFloat(frameInfo[4]); + if (frameInfo[4] != null) scaleY = Std.parseFloat(frameInfo[4]); var shit:FramesJSFLFrame = { From 5a4795eea28319cb5f614137b67e2ce3761e7fef Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 9 Sep 2024 11:44:27 -0400 Subject: [PATCH 691/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 3879a4905..f0c46cf53 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 3879a4905a96c3bbe0756fe49f07902041e893d3 +Subproject commit f0c46cf53cebc3aed5773c945b8633f7b31fe25d From 7220fd7e95a0a0f8d26f2550ca6bbf62f625b85a Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 9 Sep 2024 11:45:37 -0400 Subject: [PATCH 692/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 8791959f4..80cfbbdeb 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 8791959f4643d838cccb5b582b5a20df964f673a +Subproject commit 80cfbbdebad184f2f5429677a0ac05f95cef6706 From 591d4a29f42e26f6decf1c064c341cc533b245b1 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 9 Sep 2024 12:34:55 -0400 Subject: [PATCH 693/870] gameover positioning fixes --- source/funkin/play/GameOverSubState.hx | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/source/funkin/play/GameOverSubState.hx b/source/funkin/play/GameOverSubState.hx index 6eb954c0f..f6a7148f8 100644 --- a/source/funkin/play/GameOverSubState.hx +++ b/source/funkin/play/GameOverSubState.hx @@ -17,6 +17,7 @@ import funkin.ui.story.StoryMenuState; import funkin.util.MathUtil; import openfl.utils.Assets; import funkin.effects.RetroCameraFade; +import flixel.math.FlxPoint; /** * A substate which renders over the PlayState when the player dies. @@ -168,8 +169,8 @@ class GameOverSubState extends MusicBeatSubState // 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; - cameraFollowPoint.y = boyfriend.getGraphicMidpoint().y; + cameraFollowPoint.x = getMidPointOld(boyfriend).x; + cameraFollowPoint.y = getMidPointOld(boyfriend).y; var offsets:Array = boyfriend.getDeathCameraOffsets(); cameraFollowPoint.x += offsets[0]; cameraFollowPoint.y += offsets[1]; @@ -180,6 +181,21 @@ class GameOverSubState extends MusicBeatSubState targetCameraZoom = (PlayState?.instance?.currentStage?.camZoom ?? 1.0) * boyfriend.getDeathCameraZoom(); } + /** + * FlxSprite.getMidpoint(); calculations changed in this git commit + * https://github.com/HaxeFlixel/flixel/commit/1553b5af0871462fcefedc091b7885437d6c36d2 + * https://github.com/HaxeFlixel/flixel/pull/3125 + * + * So we use this to do the old math that gets the midpoint of our graphics + * Luckily, we don't use getGraphicMidpoint() much in the code, so it's fine being in GameoverSubState here. + * @return FlxPoint + */ + function getMidPointOld(spr:FlxSprite, ?point:FlxPoint):FlxPoint + { + if (point == null) point = FlxPoint.get(); + return point.set(spr.x + spr.frameWidth * 0.5 * spr.scale.x, spr.y + spr.frameHeight * 0.5 * spr.scale.y); + } + /** * Forcibly reset the camera zoom level to that of the current stage. * This prevents camera zoom events from adversely affecting the game over state. From e2c287e112a3b1b4369be464caa11b20016b7083 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 9 Sep 2024 13:01:19 -0400 Subject: [PATCH 694/870] logarithmic volume control --- hmm.json | 2 +- source/funkin/ui/options/FunkinSoundTray.hx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hmm.json b/hmm.json index 5205603c9..cf41fdcd9 100644 --- a/hmm.json +++ b/hmm.json @@ -18,7 +18,7 @@ "name": "flixel", "type": "git", "dir": null, - "ref": "599f38eeb502a8ba6439784036c2cfdc7b485260", + "ref": "f2b090d6c608471e730b051c8ee22b8b378964b1", "url": "https://github.com/FunkinCrew/flixel" }, { diff --git a/source/funkin/ui/options/FunkinSoundTray.hx b/source/funkin/ui/options/FunkinSoundTray.hx index 792e38fc4..170ad8497 100644 --- a/source/funkin/ui/options/FunkinSoundTray.hx +++ b/source/funkin/ui/options/FunkinSoundTray.hx @@ -120,7 +120,7 @@ class FunkinSoundTray extends FlxSoundTray lerpYPos = 10; visible = true; active = true; - var globalVolume:Int = Math.round(FlxG.sound.volume * 10); + var globalVolume:Int = Math.round(FlxG.sound.logToLinear(FlxG.sound.volume) * 10); if (FlxG.sound.muted) { From 8d27a45d17635e526abb91c7b01186e22f300aca Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Mon, 9 Sep 2024 21:39:38 +0200 Subject: [PATCH 695/870] change lock a bit --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index c6a2a13d7..37b30c8d3 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit c6a2a13d754e3566d25e762acec3a74e7116f23e +Subproject commit 37b30c8d3934617f2a4630e69a51887555a605eb From af8fe0c0d2445bb2ebf01b0bc669f179916e7020 Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Tue, 10 Sep 2024 01:11:41 +0200 Subject: [PATCH 696/870] Remove onAnimationLoopComplete --- source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx index d4df2a4f7..fefb224eb 100644 --- a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx +++ b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx @@ -38,11 +38,6 @@ class FlxAtlasSprite extends FlxAnimate */ public var onAnimationComplete:FlxTypedSignalVoid> = new FlxTypedSignal(); - /** - * Signal dispatched when a looping animation finishes playing - */ - public var onAnimationLoopComplete:FlxTypedSignalVoid> = new FlxTypedSignal(); - var currentAnimation:String; var canPlayOtherAnims:Bool = true; @@ -162,7 +157,6 @@ class FlxAtlasSprite extends FlxAnimate anim.onComplete.add(function() { if (loop) { - onAnimationLoopComplete.dispatch(id); this.anim.play(id, restart, false, startFrame); this.currentAnimation = id; } @@ -307,9 +301,7 @@ class FlxAtlasSprite extends FlxAnimate { if (currentAnimation != null) { - if (looping) onAnimationLoopComplete.dispatch(currentAnimation); - else - onAnimationComplete.dispatch(currentAnimation); + onAnimationComplete.dispatch(currentAnimation); } } From 877d64c32bf877ad501883efc638386bc20cc46f Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 9 Sep 2024 21:21:50 -0400 Subject: [PATCH 697/870] Fixed a bug where the instrumental selector would be ignored sometimes --- source/funkin/ui/freeplay/FreeplayState.hx | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index e421efd8a..6e961c287 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1985,22 +1985,6 @@ class FreeplayState extends MusicBeatSubState return; } - var baseInstrumentalId:String = targetSong?.getBaseInstrumentalId(targetDifficultyId, targetDifficulty.variation ?? Constants.DEFAULT_VARIATION) ?? ''; - var altInstrumentalIds:Array = targetSong?.listAltInstrumentalIds(targetDifficultyId, - targetDifficulty.variation ?? Constants.DEFAULT_VARIATION) ?? []; - - var targetInstId:String = baseInstrumentalId; - - // TODO: Make this a UI element. - #if FEATURE_DEBUG_FUNCTIONS - if (altInstrumentalIds.length > 0 && FlxG.keys.pressed.CONTROL) - { - targetInstId = altInstrumentalIds[0]; - } - - if (targetInstId == null) targetInstId = baseInstrumentalId; - #end - // Visual and audio effects. FunkinSound.playOnce(Paths.sound('confirmMenu')); if (dj != null) dj.confirm(); From 4c1b4859e77ac0634b1500002624fc053e188de8 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 9 Sep 2024 22:35:02 -0400 Subject: [PATCH 698/870] Fix a bug where the random event in Week 3 would always trigger --- assets | 2 +- source/funkin/play/character/BaseCharacter.hx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/assets b/assets index 80cfbbdeb..5a4dea425 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 80cfbbdebad184f2f5429677a0ac05f95cef6706 +Subproject commit 5a4dea425190d192f4f242a189a8daf5779efb8b diff --git a/source/funkin/play/character/BaseCharacter.hx b/source/funkin/play/character/BaseCharacter.hx index 28b2dbee2..bce7f0d98 100644 --- a/source/funkin/play/character/BaseCharacter.hx +++ b/source/funkin/play/character/BaseCharacter.hx @@ -376,7 +376,7 @@ class BaseCharacter extends Bopper { if (isAnimationFinished()) { - trace('Not playing hold (${getCurrentAnimation()}) (${isAnimationFinished()}, ${getCurrentAnimation().endsWith(Constants.ANIMATION_HOLD_SUFFIX)}, ${hasAnimation(getCurrentAnimation() + Constants.ANIMATION_HOLD_SUFFIX)})'); + // trace('Not playing hold (${getCurrentAnimation()}) (${isAnimationFinished()}, ${getCurrentAnimation().endsWith(Constants.ANIMATION_HOLD_SUFFIX)}, ${hasAnimation(getCurrentAnimation() + Constants.ANIMATION_HOLD_SUFFIX)})'); } } From adb4bc96ca58f7ea9c595516f270455841820709 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 9 Sep 2024 23:47:17 -0400 Subject: [PATCH 699/870] flxanimate version bump --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index cf41fdcd9..50b81bb85 100644 --- a/hmm.json +++ b/hmm.json @@ -46,7 +46,7 @@ "name": "flxanimate", "type": "git", "dir": null, - "ref": "280d1a46ac60021d08bb18181631cbd6d061782c", + "ref": "0654797e5eb7cd7de0c1b2dbaa1efe5a1e1d9412", "url": "https://github.com/Dot-Stuff/flxanimate" }, { From f6bd20378669a3fef445ef3f0a3580e90a1e86df Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 10 Sep 2024 01:33:15 -0400 Subject: [PATCH 700/870] Fix an issue where base inst wouldn't be chosen properly on remixes --- source/funkin/ui/freeplay/FreeplayState.hx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 6e961c287..d3c72e924 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1985,6 +1985,12 @@ class FreeplayState extends MusicBeatSubState return; } + if (targetInstId == null) + { + var baseInstrumentalId:String = targetSong?.getBaseInstrumentalId(targetDifficultyId, targetDifficulty.variation ?? Constants.DEFAULT_VARIATION) ?? ''; + targetInstId = baseInstrumentalId; + } + // Visual and audio effects. FunkinSound.playOnce(Paths.sound('confirmMenu')); if (dj != null) dj.confirm(); @@ -2409,6 +2415,7 @@ class DifficultySprite extends FlxSprite if (assetDiffIdParts.length == 0) break; assetDiffId = assetDiffIdParts.join('-'); } + trace('Found difficulty asset: freeplay/freeplay${assetDiffId}'); // Check for an XML to use an animation instead of an image. if (Assets.exists(Paths.file('images/freeplay/freeplay${assetDiffId}.xml'))) From 34e93fa95a464656b5e7742a74d9f76fd5a7e4d1 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Tue, 10 Sep 2024 07:25:11 +0100 Subject: [PATCH 701/870] color util (with just one function lol) --- source/funkin/util/FlxColorUtil.hx | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 source/funkin/util/FlxColorUtil.hx diff --git a/source/funkin/util/FlxColorUtil.hx b/source/funkin/util/FlxColorUtil.hx new file mode 100644 index 000000000..429d536d8 --- /dev/null +++ b/source/funkin/util/FlxColorUtil.hx @@ -0,0 +1,22 @@ +package funkin.util; + +import flixel.util.FlxColor; + +/** + * Non inline FlxColor functions for use in hscript files + */ +class FlxColorUtil +{ + /** + * Get an interpolated color based on two different colors. + * + * @param Color1 The first color + * @param Color2 The second color + * @param Factor Value from 0 to 1 representing how much to shift Color1 toward Color2 + * @return The interpolated color + */ + public static function interpolate(Color1:FlxColor, Color2:FlxColor, Factor:Float = 0.5):FlxColor + { + return FlxColor.interpolate(Color1, Color2, Factor); + } +} From 03d9416ab16ab07f6a3552dd3938555a5f8edd34 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Tue, 10 Sep 2024 07:26:15 +0100 Subject: [PATCH 702/870] texture swap shader --- source/funkin/graphics/shaders/TextureSwap.hx | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 source/funkin/graphics/shaders/TextureSwap.hx diff --git a/source/funkin/graphics/shaders/TextureSwap.hx b/source/funkin/graphics/shaders/TextureSwap.hx new file mode 100644 index 000000000..65de87ea3 --- /dev/null +++ b/source/funkin/graphics/shaders/TextureSwap.hx @@ -0,0 +1,48 @@ +package funkin.graphics.shaders; + +import flixel.system.FlxAssets.FlxShader; +import flixel.util.FlxColor; +import openfl.display.BitmapData; + +class TextureSwap extends FlxShader +{ + public var swappedImage(default, set):BitmapData; + public var amount(default, set):Float; + + function set_swappedImage(_bitmapData:BitmapData):BitmapData + { + image.input = _bitmapData; + + return _bitmapData; + } + + function set_amount(val:Float):Float + { + fadeAmount.value = [val]; + + return val; + } + + @:glFragmentSource(' + #pragma header + + uniform sampler2D image; + uniform float fadeAmount; + + void main() + { + vec4 tex = flixel_texture2D(bitmap, openfl_TextureCoordv); + vec4 tex2 = flixel_texture2D(image, openfl_TextureCoordv); + + vec4 finalColor = mix(tex, vec4(tex2.rgb, tex.a), fadeAmount); + + gl_FragColor = finalColor; + } + ') + public function new() + { + super(); + + this.amount = 1; + } +} From ee78178b20bb90b04f83504b26f533f9be03d6ee Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Tue, 10 Sep 2024 07:30:24 +0100 Subject: [PATCH 703/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 5a4dea425..aaa449a55 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 5a4dea425190d192f4f242a189a8daf5779efb8b +Subproject commit aaa449a55f9ab46463328074b9e3afc322aeb1ed From 7063fafd33de3d2d2b256cda9f08ce4462db2c9a Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 10 Sep 2024 17:26:33 -0400 Subject: [PATCH 704/870] Fix web builds using disgusting amounts of bandwidth --- project.hxp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project.hxp b/project.hxp index 0e090a4c9..1193a9cd4 100644 --- a/project.hxp +++ b/project.hxp @@ -469,7 +469,7 @@ class Project extends HXProject { // Should be true only on web builds. // Enabling embedding and preloading is required to preload assets properly. EMBED_ASSETS.apply(this, isWeb()); - PRELOAD_ALL.apply(this, true); + PRELOAD_ALL.apply(this, !isWeb()); // Should be true except on MacOS. // File drop doesn't work there. From 5021b499159a4b330283d8c931178ec2c56e0cfb Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 10 Sep 2024 17:27:04 -0400 Subject: [PATCH 705/870] Enable the New Character backing card --- source/funkin/ui/freeplay/FreeplayState.hx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index d3c72e924..ec07c9d15 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -253,6 +253,8 @@ class FreeplayState extends MusicBeatSubState switch (currentCharacterId) { + case(PlayerRegistry.instance.hasNewCharacter()) => true: + backingCard = new NewCharacterCard(currentCharacter); case 'bf': backingCard = new BoyfriendCard(currentCharacter); case 'pico': From c678cabbf2fd00b4d8d8a42b7d625061e4637f68 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 10 Sep 2024 17:30:33 -0400 Subject: [PATCH 706/870] Fix issue where difficulty names wouldn't show up properly sometimes. --- source/funkin/ui/freeplay/FreeplayState.hx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index ec07c9d15..14c5829af 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -349,6 +349,7 @@ class FreeplayState extends MusicBeatSubState var displayedVariations = song.getVariationsByCharacter(currentCharacter); trace('Displayed Variations (${songId}): $displayedVariations'); var availableDifficultiesForSong:Array = song.listSuffixedDifficulties(displayedVariations, false, false); + var unsuffixedDifficulties = song.listDifficulties(displayedVariations, false, false); trace('Available Difficulties: $availableDifficultiesForSong'); if (availableDifficultiesForSong.length == 0) continue; @@ -357,6 +358,10 @@ class FreeplayState extends MusicBeatSubState { diffIdsTotal.pushUnique(difficulty); } + for (difficulty in unsuffixedDifficulties) + { + diffIdsTotal.pushUnique(difficulty); + } } } @@ -2414,10 +2419,13 @@ class DifficultySprite extends FlxSprite // Remove the last suffix of the difficulty id until we find an asset or there are no more suffixes. var assetDiffIdParts:Array = assetDiffId.split('-'); assetDiffIdParts.pop(); - if (assetDiffIdParts.length == 0) break; + if (assetDiffIdParts.length == 0) + { + trace('Could not find difficulty asset: freeplay/freeplay${diffId} (from ${diffId})'); + return; + }; assetDiffId = assetDiffIdParts.join('-'); } - trace('Found difficulty asset: freeplay/freeplay${assetDiffId}'); // Check for an XML to use an animation instead of an image. if (Assets.exists(Paths.file('images/freeplay/freeplay${assetDiffId}.xml'))) @@ -2429,6 +2437,7 @@ class DifficultySprite extends FlxSprite else { this.loadGraphic(Paths.image('freeplay/freeplay' + assetDiffId)); + trace('Loaded difficulty asset: freeplay/freeplay${assetDiffId} (from ${diffId})'); } } } From 7aa20223b98a9c99fbd236675e4ba8af7674137f Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 10 Sep 2024 17:35:52 -0400 Subject: [PATCH 707/870] Update art submodule --- art | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/art b/art index faeba700c..0bb988c49 160000 --- a/art +++ b/art @@ -1 +1 @@ -Subproject commit faeba700c5526bd4fd57ccc927d875c82b9d3553 +Subproject commit 0bb988c49788fd25a230b56dd9e4448838bc79c9 From 0ec22bcc85a2abb357da8dc20d96fe0eddd8cfa5 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 10 Sep 2024 17:40:27 -0400 Subject: [PATCH 708/870] Update assets submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 5a4dea425..ba6621b9e 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 5a4dea425190d192f4f242a189a8daf5779efb8b +Subproject commit ba6621b9e8126b3e84ae9b79f22999b2b2402c65 From f74365f2309f64c9cd6173a4b2728ed3a7c1b093 Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Wed, 11 Sep 2024 00:55:14 +0200 Subject: [PATCH 709/870] Add Changes --- assets | 2 +- source/funkin/graphics/FlxFilteredSprite.hx | 1 - .../funkin/ui/charSelect/CharSelectPlayer.hx | 6 - .../ui/charSelect/CharSelectSubState.hx | 239 +++++++++++------- source/funkin/ui/charSelect/IntroSubState.hx | 141 +++++++++++ 5 files changed, 294 insertions(+), 95 deletions(-) create mode 100644 source/funkin/ui/charSelect/IntroSubState.hx diff --git a/assets b/assets index 37b30c8d3..49e375616 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 37b30c8d3934617f2a4630e69a51887555a605eb +Subproject commit 49e375616e0c4f3fc66874ebe4262ac389d8c746 diff --git a/source/funkin/graphics/FlxFilteredSprite.hx b/source/funkin/graphics/FlxFilteredSprite.hx index af4418d60..ea0376c3d 100644 --- a/source/funkin/graphics/FlxFilteredSprite.hx +++ b/source/funkin/graphics/FlxFilteredSprite.hx @@ -193,7 +193,6 @@ class FlxFilteredSprite extends FlxSprite } else { - trace("GAGAGA"); resetFrame(); filtered = false; } diff --git a/source/funkin/ui/charSelect/CharSelectPlayer.hx b/source/funkin/ui/charSelect/CharSelectPlayer.hx index 9767c2d3b..710bdd45a 100644 --- a/source/funkin/ui/charSelect/CharSelectPlayer.hx +++ b/source/funkin/ui/charSelect/CharSelectPlayer.hx @@ -8,14 +8,10 @@ import funkin.modding.events.ScriptEvent; class CharSelectPlayer extends FlxAtlasSprite implements IBPMSyncedScriptedClass { - var desLp:FlxKeyFrame = null; - public function new(x:Float, y:Float) { super(x, y, Paths.animateAtlas("charSelect/bfChill")); - desLp = anim.getFrameLabel("deselect loop start"); - onAnimationComplete.add(function(animLabel:String) { switch (animLabel) { @@ -80,8 +76,6 @@ class CharSelectPlayer extends FlxAtlasSprite implements IBPMSyncedScriptedClass playAnimation("slidein", true, false, false); - desLp = anim.getFrameLabel("deselect loop start"); - updateHitbox(); updatePosition(str); diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index db8844288..aa207c865 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -125,6 +125,11 @@ class CharSelectSubState extends MusicBeatSubState override public function create():Void { + openSubState(new IntroSubState()); + subStateClosed.addOnce((_) -> { + camera.flash(); + checkNewChar(); + }); super.create(); bopInfo = FramesJSFLParser.parse(Paths.file("images/charSelect/iconBopInfo/iconBopInfo.txt")); @@ -287,6 +292,7 @@ class CharSelectSubState extends MusicBeatSubState selectSound.volume = 0.7; FlxG.sound.defaultSoundGroup.add(selectSound); + FlxG.sound.list.add(selectSound); unlockSound = new FunkinSound(); unlockSound.loadEmbedded(Paths.sound('CS_unlock')); @@ -296,6 +302,7 @@ class CharSelectSubState extends MusicBeatSubState unlockSound.play(true); FlxG.sound.defaultSoundGroup.add(unlockSound); + FlxG.sound.list.add(unlockSound); // playing it here to preload it. not doing this makes a super awkward pause at the end of the intro // TODO: probably make an intro thing for funkinSound itself that preloads the next audio? @@ -360,6 +367,32 @@ class CharSelectSubState extends MusicBeatSubState }); } + function checkNewChar():Void + { + if (nonLocks.length > 0) selectTimer.start(0.5, (_) -> { + unLock(); + }); + else + { + FunkinSound.playMusic('stayFunky', + { + startingVolume: 1, + overrideExisting: true, + restartTrack: true, + onLoad: function() { + @:privateAccess + gfChill.analyzer = new SpectralAnalyzer(FlxG.sound.music._channel.__audioSource, 7, 0.1); + #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! + @:privateAccess + gfChill.analyzer.fftN = 512; + #end + } + }); + } + } + var grpIcons:FlxSpriteGroup; var grpXSpread(default, set):Float = 107; var grpYSpread(default, set):Float = 127; @@ -404,31 +437,14 @@ class CharSelectSubState extends MusicBeatSubState updateIconPositions(); grpIcons.scrollFactor.set(); - - if (nonLocks.length > 0) unLock(); - else - FunkinSound.playMusic('stayFunky', - { - startingVolume: 1, - overrideExisting: true, - restartTrack: true, - onLoad: function() { - @:privateAccess - gfChill.analyzer = new SpectralAnalyzer(FlxG.sound.music._channel.__audioSource, 7, 0.1); - #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! - @:privateAccess - gfChill.analyzer.fftN = 512; - #end - } - }); } function unLock() { var index = nonLocks[0]; + // pressedSelect = true; + var copy = 3; var yThing = -1; @@ -448,7 +464,7 @@ class CharSelectSubState extends MusicBeatSubState nonLocks.shift(); - selectTimer.start(1, function(_) { + selectTimer.start(0.5, function(_) { var lock:Lock = cast grpIcons.group.members[index]; lock.anim.getFrameLabel("unlockAnim").add(function() { @@ -460,7 +476,12 @@ class CharSelectSubState extends MusicBeatSubState unlockSound.volume = 0.7; unlockSound.play(true); + syncLock = lock; + + // sync = true; + lock.onAnimationComplete.addOnce(function(_) { + syncLock = null; var char = availableChars.get(index); camera.flash(0xFFFFFFFF, 0.1); playerChill.playAnimation("unlock"); @@ -482,15 +503,18 @@ class CharSelectSubState extends MusicBeatSubState bopPlay = true; updateIconPositions(); + playerChillOut.onAnimationComplete.addOnce((_) -> if (_ == "death") + { + sync = false; + playerChillOut.visible = false; + playerChillOut.switchChar(char); + }); + Save.instance.addCharacterSeen(char); if (nonLocks.length == 0) { - playerChillOut.onAnimationComplete.addOnce((_) -> { - playerChillOut.visible = false; - playerChillOut.switchChar(char); - }); + pressedSelect = false; @:bypassAccessor curChar = char; - Save.instance.addCharacterSeen(char); FunkinSound.playMusic('stayFunky', { startingVolume: 1, @@ -536,6 +560,38 @@ class CharSelectSubState extends MusicBeatSubState } } + var sync:Bool = false; + + var syncLock:Lock = null; + + var audioBizz:Float = 0; + + function syncAudio(elapsed:Float):Void + { + @:privateAccess + if (sync && !unlockSound.paused) + { + // if (playerChillOut.anim.framerate > 0) + // { + // if (syncLock != null) syncLock.anim.framerate = 0; + // playerChillOut.anim.framerate = 0; + // } + + playerChillOut.anim._tick = 0; + if (syncLock != null) syncLock.anim._tick = 0; + + trace(unlockSound.time); + + if ((unlockSound.time - audioBizz) >= (delay * 1000)) + { + if (syncLock != null) syncLock.anim._tick = delay; + + playerChillOut.anim._tick = delay; + audioBizz += delay * 1000; + } + } + } + function goToFreeplay():Void { autoFollow = false; @@ -589,71 +645,76 @@ class CharSelectSubState extends MusicBeatSubState if (controls.UI_UP_R || controls.UI_DOWN_R || controls.UI_LEFT_R || controls.UI_RIGHT_R) selectSound.pitch = 1; - if (controls.UI_UP) holdTmrUp += elapsed; - if (controls.UI_UP_R) + syncAudio(elapsed); + + if (!pressedSelect) { - holdTmrUp = 0; - spamUp = false; - } + if (controls.UI_UP) holdTmrUp += elapsed; + if (controls.UI_UP_R) + { + holdTmrUp = 0; + spamUp = false; + } - if (controls.UI_DOWN) holdTmrDown += elapsed; - if (controls.UI_DOWN_R) - { - holdTmrDown = 0; - spamDown = false; - } + if (controls.UI_DOWN) holdTmrDown += elapsed; + if (controls.UI_DOWN_R) + { + holdTmrDown = 0; + spamDown = false; + } - if (controls.UI_LEFT) holdTmrLeft += elapsed; - if (controls.UI_LEFT_R) - { - holdTmrLeft = 0; - spamLeft = false; - } + if (controls.UI_LEFT) holdTmrLeft += elapsed; + if (controls.UI_LEFT_R) + { + holdTmrLeft = 0; + spamLeft = false; + } - if (controls.UI_RIGHT) holdTmrRight += elapsed; - if (controls.UI_RIGHT_R) - { - holdTmrRight = 0; - spamRight = false; - } + if (controls.UI_RIGHT) holdTmrRight += elapsed; + if (controls.UI_RIGHT_R) + { + holdTmrRight = 0; + spamRight = false; + } - var initSpam = 0.5; + var initSpam = 0.5; - if (holdTmrUp >= initSpam) spamUp = true; - if (holdTmrDown >= initSpam) spamDown = true; - if (holdTmrLeft >= initSpam) spamLeft = true; - if (holdTmrRight >= initSpam) spamRight = true; + if (holdTmrUp >= initSpam) spamUp = true; + if (holdTmrDown >= initSpam) spamDown = true; + if (holdTmrLeft >= initSpam) spamLeft = true; + if (holdTmrRight >= initSpam) spamRight = true; - if (controls.UI_UP_P) - { - cursorY -= 1; - cursorDenied.visible = false; + if (controls.UI_UP_P) + { + cursorY -= 1; + cursorDenied.visible = false; - holdTmrUp = 0; + holdTmrUp = 0; - selectSound.play(true); - } - if (controls.UI_DOWN_P) - { - cursorY += 1; - cursorDenied.visible = false; - holdTmrDown = 0; - selectSound.play(true); - } - if (controls.UI_LEFT_P) - { - cursorX -= 1; - cursorDenied.visible = false; + selectSound.play(true); + } + if (controls.UI_DOWN_P) + { + cursorY += 1; + cursorDenied.visible = false; + holdTmrDown = 0; + selectSound.play(true); + } + if (controls.UI_LEFT_P) + { + cursorX -= 1; + cursorDenied.visible = false; - holdTmrLeft = 0; - selectSound.play(true); - } - if (controls.UI_RIGHT_P) - { - cursorX += 1; - cursorDenied.visible = false; - holdTmrRight = 0; - selectSound.play(true); + holdTmrLeft = 0; + selectSound.play(true); + } + if (controls.UI_RIGHT_P) + { + cursorX += 1; + cursorDenied.visible = false; + holdTmrRight = 0; + selectSound.play(true); + } } if (cursorX < -1) @@ -694,7 +755,7 @@ class CharSelectSubState extends MusicBeatSubState gfChill.playAnimation("confirm"); pressedSelect = true; selectTimer.start(1.5, (_) -> { - pressedSelect = false; + // pressedSelect = false; // FlxG.switchState(FreeplayState.build( // { // { @@ -735,6 +796,8 @@ class CharSelectSubState extends MusicBeatSubState cursorDenied.visible = true; cursorDenied.x = cursor.x - 2; cursorDenied.y = cursor.y - 4; + + playerChill.playAnimation("cannot select", true); cursorDenied.animation.play("idle", true); cursorDenied.animation.finishCallback = (_) -> { cursorDenied.visible = false; @@ -796,6 +859,7 @@ class CharSelectSubState extends MusicBeatSubState var refFrame = bopInfo.frames[bopInfo.frames.length - 1]; var curFrame = bopInfo.frames[bopFr]; + if (bopFr >= 13) icon.filters = selectedBizz; var scaleXDiff:Float = curFrame.scaleX - refFrame.scaleX; var scaleYDiff:Float = curFrame.scaleY - refFrame.scaleY; @@ -878,7 +942,6 @@ class CharSelectSubState extends MusicBeatSubState if (index == getCurrentSelected()) { // memb.pixels = memb.withDropShadow.clone(); - memb.filters = selectedBizz; if (bopPlay) { @@ -890,12 +953,14 @@ class CharSelectSubState extends MusicBeatSubState doBop(memb, FlxG.elapsed); } else - memb.scale.set(2.6, 2.6); - - if (controls.ACCEPT) memb.animation.play("confirm"); - if (memb.animation.curAnim.name == "confirm" && controls.BACK) { - memb.animation.play("confirm", false, true); + memb.filters = selectedBizz; + memb.scale.set(2.6, 2.6); + } + if (controls.ACCEPT && memb.animation.curAnim.name == "confirm") memb.animation.play("confirm"); + if (pressedSelect && controls.BACK) + { + memb.animation.play("confirm", true, true); member.animation.finishCallback = (_) -> { member.animation.play("idle"); member.animation.finishCallback = null; diff --git a/source/funkin/ui/charSelect/IntroSubState.hx b/source/funkin/ui/charSelect/IntroSubState.hx new file mode 100644 index 000000000..04503cbb9 --- /dev/null +++ b/source/funkin/ui/charSelect/IntroSubState.hx @@ -0,0 +1,141 @@ +package funkin.ui.charSelect; + +#if html5 +import funkin.graphics.video.FlxVideo; +#end +#if hxCodec +import hxcodec.flixel.FlxVideoSprite; +#end +import funkin.ui.MusicBeatSubState; +import funkin.audio.FunkinSound; + +/** + * After about 2 minutes of inactivity on the title screen, + * the game will enter the Attract state, as a reference to physical arcade machines. + * + * In the current version, this just plays the ~~Kickstarter trailer~~ Erect teaser, but this can be changed to + * gameplay footage, a generic game trailer, or something more elaborate. + */ +class IntroSubState extends MusicBeatSubState +{ + static final ATTRACT_VIDEO_PATH:String = Paths.stripLibrary(Paths.videos('introSelect')); + + var introSound:FunkinSound = null; + + public override function create():Void + { + // Pause existing music. + if (FlxG.sound.music != null) + { + FlxG.sound.music.destroy(); + FlxG.sound.music = null; + } + + #if html5 + trace('Playing web video ${ATTRACT_VIDEO_PATH}'); + playVideoHTML5(ATTRACT_VIDEO_PATH); + #end + + #if hxCodec + trace('Playing native video ${ATTRACT_VIDEO_PATH}'); + playVideoNative(ATTRACT_VIDEO_PATH); + #end + + introSound = new FunkinSound(); + introSound.loadEmbedded(Paths.sound('CS_Lights')); + introSound.pitch = 1; + + FlxG.sound.defaultSoundGroup.add(introSound); + FlxG.sound.list.add(introSound); + + introSound.play(true); + } + + #if html5 + var vid:FlxVideo; + + function playVideoHTML5(filePath:String):Void + { + // Video displays OVER the FlxState. + vid = new FlxVideo(filePath); + + vid.scrollFactor.set(); + if (vid != null) + { + vid.zIndex = 0; + + vid.finishCallback = onAttractEnd; + + add(vid); + } + else + { + trace('ALERT: Video is null! Could not play cutscene!'); + } + } + #end + + #if hxCodec + var vid:FlxVideoSprite; + + function playVideoNative(filePath:String):Void + { + // Video displays OVER the FlxState. + vid = new FlxVideoSprite(0, 0); + + vid.scrollFactor.set(); + + if (vid != null) + { + vid.zIndex = 0; + vid.bitmap.onEndReached.add(onAttractEnd); + + add(vid); + vid.play(filePath, false); + } + else + { + trace('ALERT: Video is null! Could not play cutscene!'); + } + } + #end + + public override function update(elapsed:Float):Void + { + super.update(elapsed); + + if (controls.ACCEPT) + { + onAttractEnd(); + } + } + + /** + * When the attraction state ends (after the video ends or the user presses any button), + * switch immediately to the title screen. + */ + function onAttractEnd():Void + { + #if html5 + if (vid != null) + { + remove(vid); + } + #end + + #if hxCodec + if (vid != null) + { + vid.stop(); + remove(vid); + } + #end + + #if (html5 || hxCodec) + vid.destroy(); + vid = null; + #end + + close(); + } +} From a530d91a767c3028b16294e903e0993fa68cee02 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 10 Sep 2024 19:16:48 -0400 Subject: [PATCH 710/870] Fix a bug where StickerSubState was being loaded as a state and not a substate, breaking some transitions --- source/funkin/play/ResultState.hx | 43 +++++++++++++++++++------------ 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index 2878248e2..e7087e340 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -4,6 +4,8 @@ import funkin.util.MathUtil; import funkin.ui.story.StoryMenuState; import funkin.graphics.adobeanimate.FlxAtlasSprite; import flixel.FlxSprite; +import flixel.FlxState; +import flixel.FlxSubState; import funkin.graphics.FunkinSprite; import flixel.effects.FlxFlicker; import flixel.graphics.frames.FlxBitmapFont; @@ -736,11 +738,13 @@ class ResultState extends MusicBeatSubState // Default to main menu because that's better than `null`. var targetState:flixel.FlxState = new funkin.ui.mainmenu.MainMenuState(); var shouldTween = false; + var shouldUseSubstate = false; if (params.storyMode) { if (PlayerRegistry.instance.hasNewCharacter()) { + // New character, display the notif. targetState = new StoryMenuState(null); var newCharacters = PlayerRegistry.instance.listNewCharacters(); @@ -754,6 +758,9 @@ class ResultState extends MusicBeatSubState } else { + // No new characters. + shouldTween = false; + shouldUseSubstate = true; targetState = new funkin.ui.transition.StickerSubState(null, (sticker) -> new StoryMenuState(sticker)); } } @@ -781,21 +788,9 @@ class ResultState extends MusicBeatSubState } else { - trace('rank is lower...... and/or equal'); - - targetState = new funkin.ui.transition.StickerSubState(null, (sticker) -> FreeplayState.build( - { - { - fromResults: - { - oldRank: null, - playRankAnim: false, - newRank: rank, - songId: params.songId, - difficultyId: params.difficultyId - } - } - }, sticker)); + shouldTween = false; + shouldUseSubstate = true; + targetState = new funkin.ui.transition.StickerSubState(null, (sticker) -> FreeplayState.build(null, sticker)); } } @@ -805,13 +800,27 @@ class ResultState extends MusicBeatSubState { ease: FlxEase.expoOut, onComplete: function(_) { - FlxG.switchState(targetState); + if (shouldUseSubstate && targetState is FlxSubState) + { + openSubState(cast targetState); + } + else + { + FlxG.switchState(targetState); + } } }); } else { - FlxG.switchState(targetState); + if (shouldUseSubstate && targetState is FlxSubState) + { + openSubState(cast targetState); + } + else + { + FlxG.switchState(targetState); + } } } From 9a242c5d002b77ab9de4fefae4812ea6bd144d4a Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 10 Sep 2024 19:32:10 -0400 Subject: [PATCH 711/870] Fix an issue where New labels wouldn't show on character mixes --- 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 14c5829af..a908e54c6 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -2377,7 +2377,7 @@ class FreeplaySongData this.scoringRank = Save.instance.getSongRank(songId, suffixedDifficulty); - this.isNew = song.isSongNew(currentDifficulty); + this.isNew = song.isSongNew(suffixedDifficulty); } } From 59fac5a809ad5dddf565ea4d6fc7275bbe1abc30 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 10 Sep 2024 19:32:19 -0400 Subject: [PATCH 712/870] Enable New labels for character mixes --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index ba6621b9e..ebbe6a0d9 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit ba6621b9e8126b3e84ae9b79f22999b2b2402c65 +Subproject commit ebbe6a0d9a4f47786f858c2505ca27bf0760dd2e From e5a788de7ddae5e533147c0c17bd54a9bc5d6987 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 10 Sep 2024 20:22:44 -0400 Subject: [PATCH 713/870] change xargs input --- .github/actions/setup-haxe/action.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/actions/setup-haxe/action.yml b/.github/actions/setup-haxe/action.yml index 438f330a2..a6c21f6a9 100644 --- a/.github/actions/setup-haxe/action.yml +++ b/.github/actions/setup-haxe/action.yml @@ -82,7 +82,8 @@ runs: with: run: | git config --global --name-only --get-regexp 'url\.https\:\/\/x-access-token:.+@github\.com\/\.insteadOf' \ - | xargs git config --global --unset + | xargs -I {} git config --global --unset {} + git config -l --show-scope --show-origin git config --global 'url.https://x-access-token:${{ inputs.gh-token }}@github.com/.insteadOf' https://github.com/ post: git config --global --unset 'url.https://x-access-token:${{ inputs.gh-token }}@github.com/.insteadOf' From 4cbea7d4863327b8975a91cdb876253b6f203d3b Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 11 Sep 2024 00:07:52 -0400 Subject: [PATCH 714/870] get rid of submodules that appeared for some reason --- .gitignore | 6 ------ project/lib/harfbuzz | 1 - project/lib/hashlink | 1 - project/lib/jpeg | 1 - project/lib/lzma | 1 - project/lib/mbedtls | 1 - project/lib/mojoal | 1 - project/lib/neko | 1 - project/lib/ogg | 1 - project/lib/openal | 1 - project/lib/pixman | 1 - project/lib/png | 1 - project/lib/sdl | 1 - project/lib/tinyfiledialogs | 1 - project/lib/vorbis | 1 - project/lib/vpx | 1 - project/lib/webm | 1 - project/lib/zlib | 1 - 18 files changed, 23 deletions(-) delete mode 160000 project/lib/harfbuzz delete mode 160000 project/lib/hashlink delete mode 160000 project/lib/jpeg delete mode 160000 project/lib/lzma delete mode 160000 project/lib/mbedtls delete mode 160000 project/lib/mojoal delete mode 160000 project/lib/neko delete mode 160000 project/lib/ogg delete mode 160000 project/lib/openal delete mode 160000 project/lib/pixman delete mode 160000 project/lib/png delete mode 160000 project/lib/sdl delete mode 160000 project/lib/tinyfiledialogs delete mode 160000 project/lib/vorbis delete mode 160000 project/lib/vpx delete mode 160000 project/lib/webm delete mode 160000 project/lib/zlib diff --git a/.gitignore b/.gitignore index 068780a25..ae402bdee 100644 --- a/.gitignore +++ b/.gitignore @@ -13,10 +13,4 @@ shitAudio/ node_modules/ package.json package-lock.json -<<<<<<< HEAD .aider* -||||||| bcaeae27 -======= -.aider.* -.aider* ->>>>>>> rewrite/master diff --git a/project/lib/harfbuzz b/project/lib/harfbuzz deleted file mode 160000 index 2ba0b9ee9..000000000 --- a/project/lib/harfbuzz +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2ba0b9ee94e4fdea5c3e9d20fa73eb893c0bb95e diff --git a/project/lib/hashlink b/project/lib/hashlink deleted file mode 160000 index 9888913ed..000000000 --- a/project/lib/hashlink +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9888913ed2e1eef9fc03085100c92bd44985c781 diff --git a/project/lib/jpeg b/project/lib/jpeg deleted file mode 160000 index 5cf796067..000000000 --- a/project/lib/jpeg +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5cf79606784f0616590e6a3a7fdf17ad32a6df9b diff --git a/project/lib/lzma b/project/lib/lzma deleted file mode 160000 index 5748ce6ad..000000000 --- a/project/lib/lzma +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5748ce6ad668bb10e1a1fe322b37245d0053e71a diff --git a/project/lib/mbedtls b/project/lib/mbedtls deleted file mode 160000 index ab0af45d1..000000000 --- a/project/lib/mbedtls +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ab0af45d11db04bd6e42ccfabe1b8d8deaae3243 diff --git a/project/lib/mojoal b/project/lib/mojoal deleted file mode 160000 index a9e2f30b0..000000000 --- a/project/lib/mojoal +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a9e2f30b04f10df1912d06ff5a610edda4677ba5 diff --git a/project/lib/neko b/project/lib/neko deleted file mode 160000 index d8a3b4638..000000000 --- a/project/lib/neko +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d8a3b463861779656a78c1a5e31c013580642185 diff --git a/project/lib/ogg b/project/lib/ogg deleted file mode 160000 index db5c7a49c..000000000 --- a/project/lib/ogg +++ /dev/null @@ -1 +0,0 @@ -Subproject commit db5c7a49ce7ebda47b15b78471e78fb7f2483e22 diff --git a/project/lib/openal b/project/lib/openal deleted file mode 160000 index 326133368..000000000 --- a/project/lib/openal +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 326133368c3d7149d0ab4a98fc96f654553094a7 diff --git a/project/lib/pixman b/project/lib/pixman deleted file mode 160000 index 0cb4fbe32..000000000 --- a/project/lib/pixman +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0cb4fbe3241988a5d6b51d3551998ec6837c75a1 diff --git a/project/lib/png b/project/lib/png deleted file mode 160000 index e4a31f024..000000000 --- a/project/lib/png +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e4a31f024b6158aaaf55a43502f574d5f5d1c894 diff --git a/project/lib/sdl b/project/lib/sdl deleted file mode 160000 index 8ea38ebed..000000000 --- a/project/lib/sdl +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8ea38ebedc846faa547693f60bcd213b21370982 diff --git a/project/lib/tinyfiledialogs b/project/lib/tinyfiledialogs deleted file mode 160000 index 4927ea8f4..000000000 --- a/project/lib/tinyfiledialogs +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 4927ea8f44fa0151dc8e0a2b79a13dbd7827cc48 diff --git a/project/lib/vorbis b/project/lib/vorbis deleted file mode 160000 index 84c023699..000000000 --- a/project/lib/vorbis +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 84c023699cdf023a32fa4ded32019f194afcdad0 diff --git a/project/lib/vpx b/project/lib/vpx deleted file mode 160000 index fbf63dff1..000000000 --- a/project/lib/vpx +++ /dev/null @@ -1 +0,0 @@ -Subproject commit fbf63dff1f528d44f24bd662abb89fd01a4a1c25 diff --git a/project/lib/webm b/project/lib/webm deleted file mode 160000 index 6c1e511f4..000000000 --- a/project/lib/webm +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6c1e511f487eaea026d94d0c6494a617155b5cfb diff --git a/project/lib/zlib b/project/lib/zlib deleted file mode 160000 index 545f19496..000000000 --- a/project/lib/zlib +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 545f1949635949159fa6282e81712aec32b5d4f1 From d1622040b6fd4b03f54087439839789d31b46980 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 11 Sep 2024 04:22:33 -0400 Subject: [PATCH 715/870] Fix a bug where vocals would restart after a song ends --- source/funkin/audio/FunkinSound.hx | 8 ++++++++ source/funkin/audio/SoundGroup.hx | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index b33126998..2f891a1e7 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -567,6 +567,14 @@ class FunkinSound extends FlxSound implements ICloneable return sound; } + + /** + * Produces a string representation suitable for debugging. + */ + public function toString():String + { + return 'FunkinSound(${this._label})'; + } } /** diff --git a/source/funkin/audio/SoundGroup.hx b/source/funkin/audio/SoundGroup.hx index 5fc2abe0e..5d53fedd6 100644 --- a/source/funkin/audio/SoundGroup.hx +++ b/source/funkin/audio/SoundGroup.hx @@ -113,6 +113,11 @@ class SoundGroup extends FlxTypedGroup public function play(forceRestart:Bool = false, startTime:Float = 0.0, ?endTime:Float) { forEachAlive(function(sound:FunkinSound) { + if (sound.length < startTime) + { + // trace('Queuing sound (${sound.toString()} past its length! Skipping...)'); + return; + } sound.play(forceRestart, startTime, endTime); }); } From c63feaafbd07c376359492d4dabbbc01f0d2c9a6 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 11 Sep 2024 06:00:06 -0400 Subject: [PATCH 716/870] BF force plays the unlock animation even when he would fist pump --- source/funkin/ui/freeplay/FreeplayDJ.hx | 35 +++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/source/funkin/ui/freeplay/FreeplayDJ.hx b/source/funkin/ui/freeplay/FreeplayDJ.hx index 51829d44d..3d9ffd4d6 100644 --- a/source/funkin/ui/freeplay/FreeplayDJ.hx +++ b/source/funkin/ui/freeplay/FreeplayDJ.hx @@ -375,6 +375,13 @@ class FreeplayDJ extends FlxAtlasSprite public function confirm():Void { + // We really don't want to play anything but the new character animation here. + if (PlayerRegistry.instance.hasNewCharacter()) + { + currentState = NewUnlock; + return; + } + currentState = Confirm; } @@ -397,6 +404,13 @@ class FreeplayDJ extends FlxAtlasSprite public function fistPumpIntro():Void { + // We really don't want to play anything but the new character animation here. + if (PlayerRegistry.instance.hasNewCharacter()) + { + currentState = NewUnlock; + return; + } + currentState = FistPumpIntro; var animPrefix = playableCharData.getAnimationPrefix('fistPump'); playFlashAnimation(animPrefix, true, false, false, playableCharData.getFistPumpIntroStartFrame()); @@ -404,6 +418,13 @@ class FreeplayDJ extends FlxAtlasSprite public function fistPump():Void { + // We really don't want to play anything but the new character animation here. + if (PlayerRegistry.instance.hasNewCharacter()) + { + currentState = NewUnlock; + return; + } + currentState = FistPump; var animPrefix = playableCharData.getAnimationPrefix('fistPump'); playFlashAnimation(animPrefix, true, false, false, playableCharData.getFistPumpLoopStartFrame()); @@ -411,6 +432,13 @@ class FreeplayDJ extends FlxAtlasSprite public function fistPumpLossIntro():Void { + // We really don't want to play anything but the new character animation here. + if (PlayerRegistry.instance.hasNewCharacter()) + { + currentState = NewUnlock; + return; + } + currentState = FistPumpIntro; var animPrefix = playableCharData.getAnimationPrefix('loss'); playFlashAnimation(animPrefix, true, false, false, playableCharData.getFistPumpIntroBadStartFrame()); @@ -418,6 +446,13 @@ class FreeplayDJ extends FlxAtlasSprite public function fistPumpLoss():Void { + // We really don't want to play anything but the new character animation here. + if (PlayerRegistry.instance.hasNewCharacter()) + { + currentState = NewUnlock; + return; + } + currentState = FistPump; var animPrefix = playableCharData.getAnimationPrefix('loss'); playFlashAnimation(animPrefix, true, false, false, playableCharData.getFistPumpLoopBadStartFrame()); From 0956b692d7d61eb76e97c2a0c69cc9c4a9cb5164 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 11 Sep 2024 06:18:16 -0400 Subject: [PATCH 717/870] Add a debug hotkey to set characters as not seen. --- source/funkin/audio/FunkinSound.hx | 2 +- source/funkin/ui/mainmenu/MainMenuState.hx | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index 2f891a1e7..18a0b4da2 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -571,7 +571,7 @@ class FunkinSound extends FlxSound implements ICloneable /** * Produces a string representation suitable for debugging. */ - public function toString():String + public override function toString():String { return 'FunkinSound(${this._label})'; } diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index 19dc0d687..4e416abeb 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -358,6 +358,7 @@ class MainMenuState extends MusicBeatState // Ctrl+Alt+Shift+W = Meet requirements for Pico Unlock // Ctrl+Alt+Shift+L = Revoke requirements for Pico Unlock // Ctrl+Alt+Shift+R = Score/Rank conflict test + // Ctrl+Alt+Shift+N = Mark all characters as not seen // Ctrl+Alt+Shift+E = Dump save data if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.P) @@ -433,6 +434,12 @@ class MainMenuState extends MusicBeatState }); } + if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.N) + { + @:privateAccess + funkin.save.Save.instance.data.unlocks.charactersSeen = ["bf"]; + } + if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.E) { funkin.save.Save.instance.debug_dumpSave(); From 94856a6c32667e89eb2c840f204258396ce11949 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 11 Sep 2024 06:18:31 -0400 Subject: [PATCH 718/870] Fix a bug where you could select Pico inst on erect difficulty --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 638a44fdd..5822338a5 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 638a44fdd7635814db89e96bdfdc9a9be54b39c9 +Subproject commit 5822338a50cafbb277a91d949681baea2627fa80 From c3fcc707f1db976d34e1f2bb4a0e0c05b6c4865e Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 11 Sep 2024 06:52:46 -0400 Subject: [PATCH 719/870] Update compilation guide --- docs/COMPILING.md | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index 628eb13cc..01bcaf78a 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -14,7 +14,7 @@ 5. Run `haxelib --global install hmm` and then `haxelib --global run hmm setup` to install hmm.json 6. Run `hmm install` to install all haxelibs of the current branch 7. Run `haxelib run lime setup` to set up lime -8. Platform setup +8. Perform additional 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 @@ -22,8 +22,24 @@ - 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 -9. If you are targeting for native, you may need to run `lime rebuild PLATFORM` and `lime rebuild PLATFORM -debug` -10. `lime test PLATFORM` ! Add `-debug` to enable several debug features such as time travel (`PgUp`/`PgDn` in Play State). +9. If you are targeting for native, you may need to run `lime rebuild ` and `lime rebuild -debug` +10. `lime test ` to build and launch the game for your platform (for example, `lime test windows`) + +## Build Flags + +There are several useful build flags you can add to a build to affect how it works. A full list can be found in `project.hxp`, but here's information on some of them: + +- `-debug` to build the game in debug mode. This automatically enables several useful debug features. + - This includes enabling in-game debug functions, disables compile-time optimizations, enabling asset redirection (see below), and enabling the VSCode debug server (which can slow the game on some machines but allows for powerful debugging through breakpoints). + - `-DGITHUB_BUILD` will enable in-game debug functions (such as the ability to time travel in a song by pressing `PgUp`/`PgDn`), without enabling the other stuff +- `-DFEATURE_POLYMOD_MODS` or `-DNO_FEATURE_POLYMOD_MODS` to forcibly enable or disable modding support. +- `-DREDIRECT_ASSETS_FOLDER` or `-DNO_REDIRECT_ASSETS_FOLDER` to forcibly enable or disable asset redirection. + - This feature causes the game to load exported assets from the project's assets folder rather than the exported one. Great for fast iteration, but the game +- `-DFEATURE_DISCORD_RPC` or `-DNO_FEATURE_DISCORD_RPC` to forcibly enable or disable support for Discord Rich Presence. +- `-DFEATURE_VIDEO_PLAYBACK` or `-DNO_FEATURE_VIDEO_PLAYBACK` to forcibly enable or disable video cutscene support. +- `-DFEATURE_CHART_EDITOR` or `-DNO_FEATURE_CHART_EDITOR` to forcibly enable or disable the chart editor in the Debug menu. +- `-DFEATURE_STAGE_EDITOR` to forcibly enable the experimental stage editor. +- `-DFEATURE_GHOST_TAPPING` to forcibly enable an experimental gameplay change to the anti-mash system. # Troubleshooting - GO THROUGH THESE STEPS BEFORE OPENING ISSUES ON GITHUB! From 07d9ce2d5a524fd1c890a3ceebd3940c1f82f65f Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Wed, 11 Sep 2024 17:15:31 +0200 Subject: [PATCH 720/870] Submodule thing --- art | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/art b/art index e2663c1cb..1206249aa 160000 --- a/art +++ b/art @@ -1 +1 @@ -Subproject commit e2663c1cbe029f04a98500735943f0b9465548bf +Subproject commit 1206249aa65e13df2d6a196c35222f768ad4a3f4 From 2aa9e58f67a3176735d0b5edff01236be6b85c61 Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Wed, 11 Sep 2024 18:29:00 +0200 Subject: [PATCH 721/870] Fix titlestate reentering crash --- source/funkin/ui/title/TitleState.hx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/funkin/ui/title/TitleState.hx b/source/funkin/ui/title/TitleState.hx index 79b30ff4d..df628fa87 100644 --- a/source/funkin/ui/title/TitleState.hx +++ b/source/funkin/ui/title/TitleState.hx @@ -523,7 +523,8 @@ class TitleState extends MusicBeatState remove(ngSpr); FlxG.camera.flash(FlxColor.WHITE, initialized ? 1 : 4); - remove(credGroup); + + if (credGroup != null) remove(credGroup); skippedIntro = true; } } From 0dc286e1d37f222a4935ce5ea9e630ba74d7abc3 Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Wed, 11 Sep 2024 18:29:31 +0200 Subject: [PATCH 722/870] Fix Eggnog santa not playing plus Ugh fix --- .../graphics/adobeanimate/FlxAtlasSprite.hx | 43 +++++++++++++------ .../play/character/AnimateAtlasCharacter.hx | 2 + 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx index fefb224eb..30ee20068 100644 --- a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx +++ b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx @@ -95,7 +95,7 @@ class FlxAtlasSprite extends FlxAnimate */ public function hasAnimation(id:String):Bool { - return getLabelIndex(id) != -1; + return getLabelIndex(id) != -1 || anim.symbolDictionary.exists(id); } /** @@ -112,6 +112,8 @@ class FlxAtlasSprite extends FlxAnimate var looping:Bool = false; + public var ignoreExclusionPref:Array = []; + /** * Plays an animation. * @param id A string ID of the animation to play. @@ -124,7 +126,25 @@ class FlxAtlasSprite extends FlxAnimate public function playAnimation(id:String, restart:Bool = false, ignoreOther:Bool = false, loop:Bool = false, startFrame:Int = 0):Void { // Skip if not allowed to play animations. - if ((!canPlayOtherAnims && !ignoreOther)) return; + if ((!canPlayOtherAnims)) + { + if (this.currentAnimation == id && restart) {} + else if (ignoreExclusionPref != null && ignoreExclusionPref.length > 0) + { + var detected:Bool = false; + for (entry in ignoreExclusionPref) + { + if (StringTools.startsWith(id, entry)) + { + detected = true; + break; + } + } + if (!detected) return; + } + else + return; + } if (anim == null) return; @@ -132,16 +152,12 @@ class FlxAtlasSprite extends FlxAnimate if (this.currentAnimation == id && !restart) { - if (anim.isPlaying) - { - // Skip if animation is already playing. - return; - } - else + if (!anim.isPlaying) { // Resume animation if it's paused. anim.play('', restart, false, startFrame); } + return; } else { @@ -174,18 +190,19 @@ class FlxAtlasSprite extends FlxAnimate // Move to the first frame of the animation. // goToFrameLabel(id); trace('Playing animation $id'); - if (this.anim.symbolDictionary.exists(id) || (this.anim.getByName(id) != null)) - { - this.anim.play(id, restart, false, startFrame); - } // Only call goToFrameLabel if there is a frame label with that name. This prevents annoying warnings! if (getFrameLabelNames().indexOf(id) != -1) { goToFrameLabel(id); fr = anim.getFrameLabel(id); + anim.curFrame += startFrame; + } + else + { + this.anim.play(id, restart, false, startFrame); + fr = null; } - anim.curFrame += startFrame; this.currentAnimation = id; } diff --git a/source/funkin/play/character/AnimateAtlasCharacter.hx b/source/funkin/play/character/AnimateAtlasCharacter.hx index f432d08a0..b78aed983 100644 --- a/source/funkin/play/character/AnimateAtlasCharacter.hx +++ b/source/funkin/play/character/AnimateAtlasCharacter.hx @@ -166,6 +166,8 @@ class AnimateAtlasCharacter extends BaseCharacter this.mainSprite = sprite; + mainSprite.ignoreExclusionPref = ["sing"]; + // This forces the atlas to recalcuate its width and height this.mainSprite.alpha = 0.0001; this.mainSprite.draw(); From 5c1766a00f78fc1af65b03bc1a0c9ac446aafe9d Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Wed, 11 Sep 2024 18:29:47 +0200 Subject: [PATCH 723/870] Fix char select substate crash --- source/funkin/ui/charSelect/CharSelectSubState.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index aa207c865..e075abca3 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -239,7 +239,7 @@ class CharSelectSubState extends MusicBeatSubState // FlxG.debugger.track(bfChill, "bf chill"); // FlxG.debugger.track(playerChill, "player"); // FlxG.debugger.track(nametag, "nametag"); - FlxG.debugger.track(selectSound, "selectSound"); + // FlxG.debugger.track(selectSound, "selectSound"); // FlxG.debugger.track(chooseDipshit, "choose dipshit"); // FlxG.debugger.track(barthing, "barthing"); // FlxG.debugger.track(fgBlur, "fgBlur"); From 6349ba3a5ac5a0ddec7dabf03b7cc900f6fdf4b2 Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Wed, 11 Sep 2024 18:30:11 +0200 Subject: [PATCH 724/870] Fix GF not appearing on screen --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 638a44fdd..26ab9a1dc 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 638a44fdd7635814db89e96bdfdc9a9be54b39c9 +Subproject commit 26ab9a1dc8eec563717711b290c21d0e9e56a005 From 68d87a08372facd15678268fa2b4cc518dc6c9cb Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Wed, 11 Sep 2024 19:24:21 +0200 Subject: [PATCH 725/870] Add one more conditional in atlas + add ignoreExclusions in Bopper/BaseCharacter --- .../graphics/adobeanimate/FlxAtlasSprite.hx | 2 +- source/funkin/play/character/BaseCharacter.hx | 2 ++ source/funkin/play/stage/Bopper.hx | 23 ++++++++++++++++++- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx index 30ee20068..037b87faa 100644 --- a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx +++ b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx @@ -95,7 +95,7 @@ class FlxAtlasSprite extends FlxAnimate */ public function hasAnimation(id:String):Bool { - return getLabelIndex(id) != -1 || anim.symbolDictionary.exists(id); + return getLabelIndex(id) != -1 || anim.symbolDictionary.exists(id) || anim.getByName(id); } /** diff --git a/source/funkin/play/character/BaseCharacter.hx b/source/funkin/play/character/BaseCharacter.hx index bce7f0d98..365c8d112 100644 --- a/source/funkin/play/character/BaseCharacter.hx +++ b/source/funkin/play/character/BaseCharacter.hx @@ -151,6 +151,8 @@ class BaseCharacter extends Bopper super(CharacterDataParser.DEFAULT_DANCEEVERY); this.characterId = id; + ignoreExclusionPref = ["sing"]; + _data = CharacterDataParser.fetchCharacterData(this.characterId); if (_data == null) { diff --git a/source/funkin/play/stage/Bopper.hx b/source/funkin/play/stage/Bopper.hx index 96a217d31..721a60517 100644 --- a/source/funkin/play/stage/Bopper.hx +++ b/source/funkin/play/stage/Bopper.hx @@ -260,6 +260,8 @@ class Bopper extends StageProp implements IPlayStateScriptedClass public var canPlayOtherAnims:Bool = true; + public var ignoreExclusionPref:Array = []; + /** * @param name The name of the animation to play. * @param restart Whether to restart the animation if it is already playing. @@ -268,7 +270,26 @@ class Bopper extends StageProp implements IPlayStateScriptedClass */ public function playAnimation(name:String, restart:Bool = false, ignoreOther:Bool = false, reversed:Bool = false):Void { - if (!canPlayOtherAnims && !ignoreOther) return; + if ((!canPlayOtherAnims)) + { + var id = name; + if (getCurrentAnimation() == id && restart) {} + else if (ignoreExclusionPref != null && ignoreExclusionPref.length > 0) + { + var detected:Bool = false; + for (entry in ignoreExclusionPref) + { + if (StringTools.startsWith(id, entry)) + { + detected = true; + break; + } + } + if (!detected) return; + } + else + return; + } var correctName = correctAnimationName(name); if (correctName == null) return; From 17a48bfc2b6b7bc1e5a16b11f0c3112fca4a0b2a Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Wed, 11 Sep 2024 19:26:38 +0200 Subject: [PATCH 726/870] D'oh! --- source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx index 037b87faa..eeb4eccef 100644 --- a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx +++ b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx @@ -95,7 +95,7 @@ class FlxAtlasSprite extends FlxAnimate */ public function hasAnimation(id:String):Bool { - return getLabelIndex(id) != -1 || anim.symbolDictionary.exists(id) || anim.getByName(id); + return getLabelIndex(id) != -1 || anim.symbolDictionary.exists(id) || anim.getByName(id) != null; } /** From c81f0416959370ad41b25f72be7eb6d936c2dc9a Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Wed, 11 Sep 2024 20:05:39 +0200 Subject: [PATCH 727/870] Tinkering with atlassprite --- .../graphics/adobeanimate/FlxAtlasSprite.hx | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx index eeb4eccef..eef8bee2b 100644 --- a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx +++ b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx @@ -169,19 +169,6 @@ class FlxAtlasSprite extends FlxAnimate } } - anim.onComplete.removeAll(); - anim.onComplete.add(function() { - if (loop) - { - this.anim.play(id, restart, false, startFrame); - this.currentAnimation = id; - } - else - { - onAnimationComplete.dispatch(id); - } - }); - looping = loop; // Prevent other animations from playing if `ignoreOther` is true. @@ -191,7 +178,7 @@ class FlxAtlasSprite extends FlxAnimate // goToFrameLabel(id); trace('Playing animation $id'); // Only call goToFrameLabel if there is a frame label with that name. This prevents annoying warnings! - if (getFrameLabelNames().indexOf(id) != -1) + if (getLabelIndex(id) != -1) { goToFrameLabel(id); fr = anim.getFrameLabel(id); From bea23c37a81bdc1f2a2b537a3c519c95b6b48ca0 Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Wed, 11 Sep 2024 20:47:45 +0200 Subject: [PATCH 728/870] readd FlxAtlasSprite from char unlock branch --- .../graphics/adobeanimate/FlxAtlasSprite.hx | 37 ++++++++++--------- source/funkin/ui/charSelect/IntroSubState.hx | 27 +++++--------- 2 files changed, 30 insertions(+), 34 deletions(-) diff --git a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx index eef8bee2b..6f91dbac5 100644 --- a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx +++ b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx @@ -95,7 +95,7 @@ class FlxAtlasSprite extends FlxAnimate */ public function hasAnimation(id:String):Bool { - return getLabelIndex(id) != -1 || anim.symbolDictionary.exists(id) || anim.getByName(id) != null; + return getLabelIndex(id) != -1 || anim.symbolDictionary.exists(id); } /** @@ -155,20 +155,24 @@ class FlxAtlasSprite extends FlxAnimate if (!anim.isPlaying) { // Resume animation if it's paused. - anim.play('', restart, false, startFrame); + anim.resume(); } + return; } - else + else if (!hasAnimation(id)) { // Skip if the animation doesn't exist - if (!hasAnimation(id)) - { - trace('Animation ' + id + ' not found'); - return; - } + trace('Animation ' + id + ' not found'); + return; } + this.currentAnimation = id; + anim.onComplete.removeAll(); + anim.onComplete.add(function() { + _onAnimationComplete(); + }); + looping = loop; // Prevent other animations from playing if `ignoreOther` is true. @@ -177,20 +181,18 @@ class FlxAtlasSprite extends FlxAnimate // Move to the first frame of the animation. // goToFrameLabel(id); trace('Playing animation $id'); + if (this.anim.symbolDictionary.exists(id) || (this.anim.getByName(id) != null)) + { + this.anim.play(id, true, false, startFrame); + fr = null; + } // Only call goToFrameLabel if there is a frame label with that name. This prevents annoying warnings! - if (getLabelIndex(id) != -1) + if (getFrameLabelNames().indexOf(id) != -1) { goToFrameLabel(id); fr = anim.getFrameLabel(id); anim.curFrame += startFrame; } - else - { - this.anim.play(id, restart, false, startFrame); - fr = null; - } - - this.currentAnimation = id; } override public function update(elapsed:Float) @@ -288,12 +290,13 @@ class FlxAtlasSprite extends FlxAnimate { anim.pause(); _onAnimationComplete(); + if (looping) { anim.curFrame = (fr != null) ? fr.index : 0; anim.resume(); } - else + else if (fr != null) { anim.curFrame--; } diff --git a/source/funkin/ui/charSelect/IntroSubState.hx b/source/funkin/ui/charSelect/IntroSubState.hx index 04503cbb9..16271337b 100644 --- a/source/funkin/ui/charSelect/IntroSubState.hx +++ b/source/funkin/ui/charSelect/IntroSubState.hx @@ -116,24 +116,17 @@ class IntroSubState extends MusicBeatSubState */ function onAttractEnd():Void { - #if html5 - if (vid != null) - { - remove(vid); - } - #end - - #if hxCodec - if (vid != null) - { - vid.stop(); - remove(vid); - } - #end - #if (html5 || hxCodec) - vid.destroy(); - vid = null; + if (vid != null) + { + #if hxCodec + vid.stop(); + #end + remove(vid); + + vid.destroy(); + vid = null; + } #end close(); From 9f5c154b1d29ac195023fd8a12856d27856d8777 Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Wed, 11 Sep 2024 20:49:55 +0200 Subject: [PATCH 729/870] readd IntroSubState from char unlock --- source/funkin/ui/charSelect/IntroSubState.hx | 54 ++++++++++++-------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/source/funkin/ui/charSelect/IntroSubState.hx b/source/funkin/ui/charSelect/IntroSubState.hx index 16271337b..a0c44c225 100644 --- a/source/funkin/ui/charSelect/IntroSubState.hx +++ b/source/funkin/ui/charSelect/IntroSubState.hx @@ -8,22 +8,24 @@ import hxcodec.flixel.FlxVideoSprite; #end import funkin.ui.MusicBeatSubState; import funkin.audio.FunkinSound; +import funkin.save.Save; /** - * After about 2 minutes of inactivity on the title screen, - * the game will enter the Attract state, as a reference to physical arcade machines. - * - * In the current version, this just plays the ~~Kickstarter trailer~~ Erect teaser, but this can be changed to - * gameplay footage, a generic game trailer, or something more elaborate. + * When you first enter the character select state, it will play an introductory video opening up the lights */ class IntroSubState extends MusicBeatSubState { - static final ATTRACT_VIDEO_PATH:String = Paths.stripLibrary(Paths.videos('introSelect')); + static final LIGHTS_VIDEO_PATH:String = Paths.stripLibrary(Paths.videos('introSelect')); var introSound:FunkinSound = null; public override function create():Void { + if (Save.instance.oldChar) + { + onLightsEnd(); + return; + } // Pause existing music. if (FlxG.sound.music != null) { @@ -32,15 +34,20 @@ class IntroSubState extends MusicBeatSubState } #if html5 - trace('Playing web video ${ATTRACT_VIDEO_PATH}'); - playVideoHTML5(ATTRACT_VIDEO_PATH); + trace('Playing web video ${LIGHTS_VIDEO_PATH}'); + playVideoHTML5(LIGHTS_VIDEO_PATH); #end #if hxCodec - trace('Playing native video ${ATTRACT_VIDEO_PATH}'); - playVideoNative(ATTRACT_VIDEO_PATH); + trace('Playing native video ${LIGHTS_VIDEO_PATH}'); + playVideoNative(LIGHTS_VIDEO_PATH); #end + // Im TOO lazy to even care, so uh, yep + FlxG.camera.zoom = 0.66666666666666666666666666666667; + vid.x = -(FlxG.width - (FlxG.width * FlxG.camera.zoom)); + vid.y = -((FlxG.height - (FlxG.height * FlxG.camera.zoom)) * 0.75); + introSound = new FunkinSound(); introSound.loadEmbedded(Paths.sound('CS_Lights')); introSound.pitch = 1; @@ -64,7 +71,7 @@ class IntroSubState extends MusicBeatSubState { vid.zIndex = 0; - vid.finishCallback = onAttractEnd; + vid.finishCallback = onLightsEnd; add(vid); } @@ -88,7 +95,7 @@ class IntroSubState extends MusicBeatSubState if (vid != null) { vid.zIndex = 0; - vid.bitmap.onEndReached.add(onAttractEnd); + vid.bitmap.onEndReached.add(onLightsEnd); add(vid); vid.play(filePath, false); @@ -104,30 +111,33 @@ class IntroSubState extends MusicBeatSubState { super.update(elapsed); - if (controls.ACCEPT) - { - onAttractEnd(); - } + // if (!introSound.paused) + // { + // #if html5 + // @:privateAccess + // vid.netStream.seek(introSound.time); + // #elseif hxCodec + // vid.bitmap.time = Std.int(introSound.time); + // #end + // } } /** - * When the attraction state ends (after the video ends or the user presses any button), - * switch immediately to the title screen. + * When the lights video finishes, it will close the substate */ - function onAttractEnd():Void + function onLightsEnd():Void { - #if (html5 || hxCodec) if (vid != null) { #if hxCodec vid.stop(); #end remove(vid); - vid.destroy(); vid = null; } - #end + + FlxG.camera.zoom = 1; close(); } From cfcfc773daa7ffc26dffe9574a443f5807fa4a94 Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Wed, 11 Sep 2024 20:53:05 +0200 Subject: [PATCH 730/870] readd Save from char unlock --- source/funkin/save/Save.hx | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx index 80b05e5ac..1fa283b26 100644 --- a/source/funkin/save/Save.hx +++ b/source/funkin/save/Save.hx @@ -125,6 +125,7 @@ class Save { // Default to having seen the default character. charactersSeen: ["bf"], + oldChar: false }, optionsChartEditor: @@ -406,6 +407,18 @@ class Save return data.unlocks.charactersSeen; } + public var oldChar(get, set):Bool; + + function get_oldChar():Bool + { + return data.unlocks.oldChar; + } + + function set_oldChar(value:Bool):Bool + { + return data.unlocks.oldChar = value; + } + /** * When we've seen a character unlock, add it to the list of characters seen. * @param character @@ -1027,6 +1040,12 @@ typedef SaveDataUnlocks = * add it to this list so that we don't show it again. */ var charactersSeen:Array; + + /** + * This is a conditional when the player enters the character state + * For the first time ever + */ + var oldChar:Bool; } /** From 70ab000be42f62a25fb33440a3d6eee34ce163ac Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Wed, 11 Sep 2024 21:16:02 +0200 Subject: [PATCH 731/870] Readd CharSelectSubState from char unlock --- assets | 2 +- .../ui/charSelect/CharSelectSubState.hx | 68 ++++++++----------- 2 files changed, 30 insertions(+), 40 deletions(-) diff --git a/assets b/assets index 26ab9a1dc..f1813c9e4 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 26ab9a1dc8eec563717711b290c21d0e9e56a005 +Subproject commit f1813c9e4f88426554293b68d8a46f5baa5b6228 diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index e075abca3..bd55bfdd9 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -35,55 +35,44 @@ import openfl.filters.ShaderFilter; import funkin.util.FramesJSFLParser; import funkin.util.FramesJSFLParser.FramesJSFLInfo; import funkin.util.FramesJSFLParser.FramesJSFLFrame; +import funkin.graphics.FunkinSprite; class CharSelectSubState extends MusicBeatSubState { var cursor:FlxSprite; + var cursorBlue:FlxSprite; var cursorDarkBlue:FlxSprite; - var grpCursors:FlxTypedGroup; - var cursorConfirmed:FlxSprite; var cursorDenied:FlxSprite; - var cursorX:Int = 0; var cursorY:Int = 0; - var cursorFactor:Float = 110; var cursorOffsetX:Float = -16; var cursorOffsetY:Float = -48; - var cursorLocIntended:FlxPoint = new FlxPoint(0, 0); var lerpAmnt:Float = 0.95; - var tmrFrames:Int = 60; - var currentStage:Stage; - var playerChill:CharSelectPlayer; var playerChillOut:CharSelectPlayer; var gfChill:CharSelectGF; var gfChillOut:CharSelectGF; - var barthing:FlxAtlasSprite; var dipshitBacking:FlxSprite; var chooseDipshit:FlxSprite; var dipshitBlur:FlxSprite; var transitionGradient:FlxSprite; - var curChar(default, set):String = "pico"; var nametag:Nametag; var camFollow:FlxObject; var autoFollow:Bool = false; - var availableChars:Map = new Map(); var pressedSelect:Bool = false; - var selectTimer:FlxTimer = new FlxTimer(); var selectSound:FunkinSound; var unlockSound:FunkinSound; - var charSelectCam:FunkinCamera; var selectedBizz:Array = [ @@ -92,6 +81,7 @@ class CharSelectSubState extends MusicBeatSubState ]; var bopInfo:FramesJSFLInfo; + var blackScreen:FunkinSprite; public function new() { @@ -125,11 +115,6 @@ class CharSelectSubState extends MusicBeatSubState override public function create():Void { - openSubState(new IntroSubState()); - subStateClosed.addOnce((_) -> { - camera.flash(); - checkNewChar(); - }); super.create(); bopInfo = FramesJSFLParser.parse(Paths.file("images/charSelect/iconBopInfo/iconBopInfo.txt")); @@ -239,7 +224,7 @@ class CharSelectSubState extends MusicBeatSubState // FlxG.debugger.track(bfChill, "bf chill"); // FlxG.debugger.track(playerChill, "player"); // FlxG.debugger.track(nametag, "nametag"); - // FlxG.debugger.track(selectSound, "selectSound"); + FlxG.debugger.track(selectSound, "selectSound"); // FlxG.debugger.track(chooseDipshit, "choose dipshit"); // FlxG.debugger.track(barthing, "barthing"); // FlxG.debugger.track(fgBlur, "fgBlur"); @@ -365,6 +350,20 @@ class CharSelectSubState extends MusicBeatSubState FlxG.camera.follow(camFollow, LOCKON, 0.01); } }); + + var blackScreen = new FunkinSprite().makeSolidColor(FlxG.width * 2, FlxG.height * 2, 0xFF000000); + blackScreen.x = -(FlxG.width * 0.5); + blackScreen.y = -(FlxG.height * 0.5); + add(blackScreen); + + openSubState(new IntroSubState()); + subStateClosed.addOnce((_) -> { + remove(blackScreen); + if (!Save.instance.oldChar) camera.flash(); + checkNewChar(); + + Save.instance.oldChar = true; + }); } function checkNewChar():Void @@ -396,7 +395,6 @@ class CharSelectSubState extends MusicBeatSubState var grpIcons:FlxSpriteGroup; var grpXSpread(default, set):Float = 107; var grpYSpread(default, set):Float = 127; - var nonLocks = []; function initLocks():Void @@ -426,9 +424,9 @@ class CharSelectSubState extends MusicBeatSubState var temp:Lock = new Lock(0, 0, i); temp.ID = 1; - temp.onAnimationComplete.add(function(anim) { - if (anim == "unlock") playerChill.playAnimation("unlock", true); - }); + // temp.onAnimationComplete.add(function(anim) { + // if (anim == "unlock") playerChill.playAnimation("unlock", true); + // }); grpIcons.add(temp); } @@ -443,7 +441,7 @@ class CharSelectSubState extends MusicBeatSubState { var index = nonLocks[0]; - // pressedSelect = true; + pressedSelect = true; var copy = 3; @@ -478,7 +476,7 @@ class CharSelectSubState extends MusicBeatSubState syncLock = lock; - // sync = true; + sync = true; lock.onAnimationComplete.addOnce(function(_) { syncLock = null; @@ -561,9 +559,7 @@ class CharSelectSubState extends MusicBeatSubState } var sync:Bool = false; - var syncLock:Lock = null; - var audioBizz:Float = 0; function syncAudio(elapsed:Float):Void @@ -580,8 +576,6 @@ class CharSelectSubState extends MusicBeatSubState playerChillOut.anim._tick = 0; if (syncLock != null) syncLock.anim._tick = 0; - trace(unlockSound.time); - if ((unlockSound.time - audioBizz) >= (delay * 1000)) { if (syncLock != null) syncLock.anim._tick = delay; @@ -738,7 +732,7 @@ class CharSelectSubState extends MusicBeatSubState { curChar = availableChars.get(getCurrentSelected()); - if (controls.ACCEPT) + if (!pressedSelect && controls.ACCEPT) { cursorConfirmed.visible = true; cursorConfirmed.x = cursor.x - 2; @@ -775,6 +769,7 @@ class CharSelectSubState extends MusicBeatSubState FlxTween.tween(FlxG.sound.music, {pitch: 1.0, volume: 1.0}, 1, {ease: FlxEase.quartInOut}); playerChill.playAnimation("deselect"); gfChill.playAnimation("deselect"); + pressedSelect = false; FlxTween.tween(FlxG.sound.music, {pitch: 1.0}, 1, { ease: FlxEase.quartInOut, @@ -783,7 +778,6 @@ class CharSelectSubState extends MusicBeatSubState gfChill.playAnimation("idle", true, false, true); } }); - pressedSelect = false; selectTimer.cancel(); } } @@ -797,7 +791,7 @@ class CharSelectSubState extends MusicBeatSubState cursorDenied.x = cursor.x - 2; cursorDenied.y = cursor.y - 4; - playerChill.playAnimation("cannot select", true); + playerChill.playAnimation("cannot select Label", true); cursorDenied.animation.play("idle", true); cursorDenied.animation.finishCallback = (_) -> { cursorDenied.visible = false; @@ -831,13 +825,9 @@ class CharSelectSubState extends MusicBeatSubState } var bopTimer:Float = 0; - var delay = 1 / 24; - var bopFr = 0; - var bopPlay:Bool = false; - var bopRefX:Float = 0; var bopRefY:Float = 0; @@ -957,10 +947,10 @@ class CharSelectSubState extends MusicBeatSubState memb.filters = selectedBizz; memb.scale.set(2.6, 2.6); } - if (controls.ACCEPT && memb.animation.curAnim.name == "confirm") memb.animation.play("confirm"); - if (pressedSelect && controls.BACK) + if (pressedSelect && memb.animation.curAnim.name == "idle") memb.animation.play("confirm"); + if (!pressedSelect && memb.animation.curAnim.name != "idle") { - memb.animation.play("confirm", true, true); + memb.animation.play("confirm", false, true); member.animation.finishCallback = (_) -> { member.animation.play("idle"); member.animation.finishCallback = null; From fded5892c5bde073118fa91cf3a1bd5d841db98f Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 11 Sep 2024 15:55:38 -0400 Subject: [PATCH 732/870] Update audio compression (via Saru) --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 638a44fdd..acf6f9ddf 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 638a44fdd7635814db89e96bdfdc9a9be54b39c9 +Subproject commit acf6f9ddfdb5867550ae90e5871cce3d8d3808f0 From e32dd0e5048fe77326f38a227f5336ffc85c7afc Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 11 Sep 2024 17:09:45 -0400 Subject: [PATCH 733/870] Update assets submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 638a44fdd..abe1deb43 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 638a44fdd7635814db89e96bdfdc9a9be54b39c9 +Subproject commit abe1deb4372b9bc5b97d7d30ed8eb4e70d721eb9 From 3553d008cf29147e5f878e1088236de72796efca Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Thu, 12 Sep 2024 01:37:32 +0200 Subject: [PATCH 734/870] tinkering shit --- assets | 2 +- source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx | 10 ++++++++-- source/funkin/play/ResultState.hx | 5 ++++- source/funkin/ui/charSelect/CharSelectPlayer.hx | 2 +- source/funkin/ui/freeplay/FreeplayDJ.hx | 2 ++ source/funkin/ui/title/TitleState.hx | 7 +++++-- 6 files changed, 21 insertions(+), 7 deletions(-) diff --git a/assets b/assets index f1813c9e4..6b84e5b48 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit f1813c9e4f88426554293b68d8a46f5baa5b6228 +Subproject commit 6b84e5b4830cbdb21f0e92bd8def16b1446f2d84 diff --git a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx index 6f91dbac5..f245afec7 100644 --- a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx +++ b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx @@ -154,6 +154,10 @@ class FlxAtlasSprite extends FlxAnimate { if (!anim.isPlaying) { + if (fr != null) anim.curFrame = fr.index + startFrame; + else + anim.curFrame = startFrame; + // Resume animation if it's paused. anim.resume(); } @@ -183,7 +187,9 @@ class FlxAtlasSprite extends FlxAnimate trace('Playing animation $id'); if (this.anim.symbolDictionary.exists(id) || (this.anim.getByName(id) != null)) { - this.anim.play(id, true, false, startFrame); + this.anim.play(id, restart, false, startFrame); + + if (id == "Boyfriend DJ fist pump" || startFrame == 4) trace("PUMP COMMAND: " + anim.curFrame); fr = null; } // Only call goToFrameLabel if there is a frame label with that name. This prevents annoying warnings! @@ -296,7 +302,7 @@ class FlxAtlasSprite extends FlxAnimate anim.curFrame = (fr != null) ? fr.index : 0; anim.resume(); } - else if (fr != null) + else if (fr != null && anim.curFrame != anim.length - 1) { anim.curFrame--; } diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index e7087e340..e0ac3579d 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -194,6 +194,7 @@ class ResultState extends MusicBeatSubState { // Animation is not looped. animation.onAnimationComplete.add((_name:String) -> { + trace("AHAHAH 2"); if (animation != null) { animation.anim.pause(); @@ -203,9 +204,10 @@ class ResultState extends MusicBeatSubState else if (animData.loopFrameLabel != null) { animation.onAnimationComplete.add((_name:String) -> { + trace("AHAHAH 2"); if (animation != null) { - animation.playAnimation(animData.loopFrameLabel ?? ''); // unpauses this anim, since it's on PlayOnce! + animation.playAnimation(animData.loopFrameLabel ?? '', true, false, true); // unpauses this anim, since it's on PlayOnce! } }); } @@ -214,6 +216,7 @@ class ResultState extends MusicBeatSubState animation.onAnimationComplete.add((_name:String) -> { if (animation != null) { + trace("AHAHAH"); animation.anim.curFrame = animData.loopFrame ?? 0; animation.anim.play(); // unpauses this anim, since it's on PlayOnce! } diff --git a/source/funkin/ui/charSelect/CharSelectPlayer.hx b/source/funkin/ui/charSelect/CharSelectPlayer.hx index 710bdd45a..b6319f16d 100644 --- a/source/funkin/ui/charSelect/CharSelectPlayer.hx +++ b/source/funkin/ui/charSelect/CharSelectPlayer.hx @@ -27,7 +27,7 @@ class CharSelectPlayer extends FlxAtlasSprite implements IBPMSyncedScriptedClass case "deselect": playAnimation("deselect loop start", true, false, true); - case "slidein idle point", "cannot select", "unlock": + case "slidein idle point", "cannot select Label", "unlock": playAnimation("idle", true, false, false); case "idle": trace('Waiting for onBeatHit'); diff --git a/source/funkin/ui/freeplay/FreeplayDJ.hx b/source/funkin/ui/freeplay/FreeplayDJ.hx index 51829d44d..a6cbab440 100644 --- a/source/funkin/ui/freeplay/FreeplayDJ.hx +++ b/source/funkin/ui/freeplay/FreeplayDJ.hx @@ -141,6 +141,7 @@ class FreeplayDJ extends FlxAtlasSprite } else if (getCurrentAnimation() == animPrefixB) { + trace("Loss Intro"); var endFrame = playableCharData.getFistPumpIntroBadEndFrame(); if (endFrame > -1 && anim.curFrame >= endFrame) { @@ -166,6 +167,7 @@ class FreeplayDJ extends FlxAtlasSprite } else if (getCurrentAnimation() == animPrefixB) { + trace("Loss GYATT"); var endFrame = playableCharData.getFistPumpLoopBadEndFrame(); if (endFrame > -1 && anim.curFrame >= endFrame) { diff --git a/source/funkin/ui/title/TitleState.hx b/source/funkin/ui/title/TitleState.hx index df628fa87..f5c641d0c 100644 --- a/source/funkin/ui/title/TitleState.hx +++ b/source/funkin/ui/title/TitleState.hx @@ -273,8 +273,11 @@ class TitleState extends MusicBeatState } #end - if (Save.instance.charactersSeen.contains("pico")) Save.instance.charactersSeen.remove("pico"); - + if (Save.instance.charactersSeen.contains("pico")) + { + Save.instance.charactersSeen.remove("pico"); + Save.instance.oldChar = false; + } Conductor.instance.update(); /* if (FlxG.onMobile) From bfcbc54ced6cc4e186547ffc49f1a2530bb58b6a Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 11 Sep 2024 20:39:31 -0400 Subject: [PATCH 735/870] Update assets submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index abe1deb43..cbf695dd6 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit abe1deb4372b9bc5b97d7d30ed8eb4e70d721eb9 +Subproject commit cbf695dd622625d11abbed594832aa41fe6a20de From e12ed47162f709ea53e7bd6bcb056726c219c9f6 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Thu, 12 Sep 2024 09:25:42 +0100 Subject: [PATCH 736/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 638a44fdd..d7e9f6e15 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 638a44fdd7635814db89e96bdfdc9a9be54b39c9 +Subproject commit d7e9f6e15331f6d2dfee3d380e804e8274d6661d From b7fb6105a773053162b11596865c538079e503dd Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Thu, 12 Sep 2024 17:50:46 +0100 Subject: [PATCH 737/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 638a44fdd..3306aab5b 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 638a44fdd7635814db89e96bdfdc9a9be54b39c9 +Subproject commit 3306aab5b747aa5b19508d88ffb801403218b2ca From 2c80701855cae07efd3c13185090e0fe1c5b5a32 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 12 Sep 2024 14:26:11 -0400 Subject: [PATCH 738/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index acf6f9ddf..bd1bdcf5e 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit acf6f9ddfdb5867550ae90e5871cce3d8d3808f0 +Subproject commit bd1bdcf5e1349e6199d9d32e617cbefa2cea093b From d3e8938888f7c4feb27c806ca222f6a54e69b087 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 12 Sep 2024 14:28:51 -0400 Subject: [PATCH 739/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 5822338a5..3954e9564 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 5822338a50cafbb277a91d949681baea2627fa80 +Subproject commit 3954e95646643dfc729607d0da57ba0bbf273521 From 19f332ea7e0858c2998392b98ee5c09a9588718d Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 12 Sep 2024 14:30:14 -0400 Subject: [PATCH 740/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index cbf695dd6..a00554b4c 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit cbf695dd622625d11abbed594832aa41fe6a20de +Subproject commit a00554b4c78d3d1da18436bc285ccbe1f4ea98f2 From 96f306471cca18550cdfd6cb3d50d241d97ff07e Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 12 Sep 2024 14:31:56 -0400 Subject: [PATCH 741/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 6b84e5b48..335fac6af 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 6b84e5b4830cbdb21f0e92bd8def16b1446f2d84 +Subproject commit 335fac6af6b3362b1de5f233865486eaf9fbae11 From 0b13e0fdd5f3f66a9efc81b76e8a26067109f983 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 12 Sep 2024 14:33:31 -0400 Subject: [PATCH 742/870] art submod (char select stuff) --- art | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/art b/art index 1206249aa..0bb988c49 160000 --- a/art +++ b/art @@ -1 +1 @@ -Subproject commit 1206249aa65e13df2d6a196c35222f768ad4a3f4 +Subproject commit 0bb988c49788fd25a230b56dd9e4448838bc79c9 From 260946f44f1303762cd18de0ce096926c3c66f79 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 12 Sep 2024 14:35:19 -0400 Subject: [PATCH 743/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index d7e9f6e15..f1fe21240 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit d7e9f6e15331f6d2dfee3d380e804e8274d6661d +Subproject commit f1fe21240bac58a7ab729b351cb36f3f9ed07e7a From 07c5c5d5a7affa04102357060e29e305fd7c8d03 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 12 Sep 2024 14:38:29 -0400 Subject: [PATCH 744/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 3306aab5b..bd4e2421c 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 3306aab5b747aa5b19508d88ffb801403218b2ca +Subproject commit bd4e2421c87c31e244bc9c162850b842582c5de4 From bfb19cc67ebd82fea3133301637fd96404a38389 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 12 Sep 2024 14:46:29 -0400 Subject: [PATCH 745/870] lastTime error fix --- source/Main.hx | 1 - 1 file changed, 1 deletion(-) diff --git a/source/Main.hx b/source/Main.hx index 63e2b5878..7f7d25235 100644 --- a/source/Main.hx +++ b/source/Main.hx @@ -73,7 +73,6 @@ class Main extends Sprite var timeToCall = 0; var id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall); - lastTime = currTime + timeToCall; return id; }"); #end From cdd78818a7f9ca47b95fd9d24e7df21231c118e9 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 12 Sep 2024 15:20:12 -0400 Subject: [PATCH 746/870] Update assets submodule and changelog --- CHANGELOG.md | 9 ++++++++- art | 2 +- assets | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22a36fa8e..a2031ba24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,8 +29,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Implemented support for a new Instrumental Selector in Freeplay - Beating a Pico remix lets you use that instrumental when playing as Boyfriend - Added the first batch of Erect Stages! These graphical overhauls of the original stages will be used when playing Erect remixes and Pico remixes + - Week 1 Erect Stage + - Week 2 Erect Stage + - Week 3 Erect Stage + - Week 4 Erect Stage + - Week 5 Erect Stage + - Weekend 1 Erect Stage +- Implemented alternate animations and music for Pico in the results screen. + - These display on Pico remixes, as well as when playing Weekend 1. - Implemented support for scripted Note Kinds. You can use HScript define a different note style to display for these notes as well as custom behavior. (community feature by lemz1) -- Implemented a new Strumline Background option, to display a darkened background behind the strumline with your choice of opacity. - Implemented support for Numeric and Selector options in the Options menu. (community feature by FlooferLand) ## Changed - Girlfriend and Nene now perform previously unused animations when you achieve a large combo, or drop a large combo. diff --git a/art b/art index 0bb988c49..42ac06e51 160000 --- a/art +++ b/art @@ -1 +1 @@ -Subproject commit 0bb988c49788fd25a230b56dd9e4448838bc79c9 +Subproject commit 42ac06e51207bda89144fd20a407ed3c3e0c6673 diff --git a/assets b/assets index bd4e2421c..90865213b 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit bd4e2421c87c31e244bc9c162850b842582c5de4 +Subproject commit 90865213be704f88df8398f28b8880c13f468546 From b2b16ff2d310169c8390329c2546af6556346789 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 12 Sep 2024 15:31:58 -0400 Subject: [PATCH 747/870] Update vocal delay again --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 90865213b..934468c04 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 90865213be704f88df8398f28b8880c13f468546 +Subproject commit 934468c0472504c282b12c63b473e9f74b5b4517 From 386dc22d7b24464a63a4f95c6fa2aa8cc854da86 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 12 Sep 2024 15:34:16 -0400 Subject: [PATCH 748/870] Debug hotkey properly resets char select cutscene --- source/funkin/ui/mainmenu/MainMenuState.hx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index 4e416abeb..13d68da6d 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -437,7 +437,10 @@ class MainMenuState extends MusicBeatState if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.N) { @:privateAccess - funkin.save.Save.instance.data.unlocks.charactersSeen = ["bf"]; + { + funkin.save.Save.instance.data.unlocks.charactersSeen = ["bf"]; + funkin.save.Save.instance.data.unlocks.oldChar = false; + } } if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.E) From e5673549cf7c17c58dfc340279c4ac0ed4377dd7 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 12 Sep 2024 15:38:20 -0400 Subject: [PATCH 749/870] Fix issues with the difficulty selector showing non-existant difficulties in Freeplay --- source/funkin/ui/freeplay/FreeplayState.hx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index a908e54c6..ec80a1ff6 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -354,10 +354,6 @@ class FreeplayState extends MusicBeatSubState if (availableDifficultiesForSong.length == 0) continue; songs.push(new FreeplaySongData(levelId, songId, song, displayedVariations)); - for (difficulty in availableDifficultiesForSong) - { - diffIdsTotal.pushUnique(difficulty); - } for (difficulty in unsuffixedDifficulties) { diffIdsTotal.pushUnique(difficulty); @@ -1764,12 +1760,13 @@ class FreeplayState extends MusicBeatSubState var songScore:Null = Save.instance.getSongScore(daSong.songId, suffixedDifficulty); intendedScore = songScore?.score ?? 0; intendedCompletion = songScore == null ? 0.0 : ((songScore.tallies.sick + songScore.tallies.good) / songScore.tallies.totalNotes); - rememberedDifficulty = currentDifficulty; + rememberedDifficulty = suffixedDifficulty; } else { intendedScore = 0; intendedCompletion = 0.0; + rememberedDifficulty = currentDifficulty; } if (intendedCompletion == Math.POSITIVE_INFINITY || intendedCompletion == Math.NEGATIVE_INFINITY || Math.isNaN(intendedCompletion)) From 721cecd271fb8b40fe1ed26ee7908d94bd1f522e Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 12 Sep 2024 15:38:44 -0400 Subject: [PATCH 750/870] add preference option for framerate capping --- source/Main.hx | 11 ++--- source/funkin/Preferences.hx | 53 +++++++++++++++++++++ source/funkin/save/Save.hx | 7 +++ source/funkin/ui/options/PreferencesMenu.hx | 6 +++ 4 files changed, 69 insertions(+), 8 deletions(-) diff --git a/source/Main.hx b/source/Main.hx index 7f7d25235..724b118f8 100644 --- a/source/Main.hx +++ b/source/Main.hx @@ -67,14 +67,9 @@ class Main extends Sprite function init(?event:Event):Void { #if web - untyped js.Syntax.code(" - window.requestAnimationFrame = function(callback, element) { - var currTime = new Date().getTime(); - var timeToCall = 0; - var id = window.setTimeout(function() { callback(currTime + timeToCall); }, - timeToCall); - return id; - }"); + // set this variable (which is a function) from the lime version at lime/_internal/backend/html5/HTML5Application.hx + // The framerate cap will more thoroughly initialize via Preferences in InitState.hx + funkin.Preferences.lockedFramerateFunction = untyped js.Syntax.code("window.requestAnimationFrame"); #end if (hasEventListener(Event.ADDED_TO_STAGE)) diff --git a/source/funkin/Preferences.hx b/source/funkin/Preferences.hx index b2050c6a2..daeded897 100644 --- a/source/funkin/Preferences.hx +++ b/source/funkin/Preferences.hx @@ -128,6 +128,48 @@ class Preferences return value; } + public static var unlockedFramerate(get, set):Bool; + + static function get_unlockedFramerate():Bool + { + return Save?.instance?.options?.unlockedFramerate; + } + + static function set_unlockedFramerate(value:Bool):Bool + { + if (value != Save.instance.options.unlockedFramerate) + { + #if web + toggleFramerateCap(value); + #end + } + + var save:Save = Save.instance; + save.options.unlockedFramerate = value; + save.flush(); + return value; + } + + #if web + // We create a haxe version of this just for readability. + // We use these to override `window.requestAnimationFrame` in Javascript to uncap the framerate / "animation" request rate + // Javascript is crazy since u can just do stuff like that lol + + public static function unlockedFramerateFunction(callback, element) + { + var currTime = Date.now().getTime(); + var timeToCall = 0; + var id = js.Browser.window.setTimeout(function() { + callback(currTime + timeToCall); + }, timeToCall); + return id; + } + + // Lime already implements their own little framerate cap, so we can just use that + // This also gets set in the init function in Main.hx, since we need to definitely override it + public static var lockedFramerateFunction = untyped js.Syntax.code("window.requestAnimationFrame"); + #end + /** * Loads the user's preferences from the save data and apply them. */ @@ -137,6 +179,17 @@ class Preferences FlxG.autoPause = Preferences.autoPause; // Apply the debugDisplay setting (enables the FPS and RAM display). toggleDebugDisplay(Preferences.debugDisplay); + #if web + toggleFramerateCap(Preferences.unlockedFramerate); + #end + } + + static function toggleFramerateCap(unlocked:Bool):Void + { + #if web + var framerateFunction = unlocked ? unlockedFramerateFunction : lockedFramerateFunction; + untyped js.Syntax.code("window.requestAnimationFrame = framerateFunction;"); + #end } static function toggleDebugDisplay(show:Bool):Void diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx index 1fa283b26..4b1649c5b 100644 --- a/source/funkin/save/Save.hx +++ b/source/funkin/save/Save.hx @@ -97,6 +97,7 @@ class Save autoPause: true, inputOffset: 0, audioVisualOffset: 0, + unlockedFramerate: false, controls: { @@ -1171,6 +1172,12 @@ typedef SaveDataOptions = */ var audioVisualOffset:Int; + /** + * If we want the framerate to be unlocked on HTML5. + * @default `false + */ + var unlockedFramerate:Bool; + var controls: { var p1: diff --git a/source/funkin/ui/options/PreferencesMenu.hx b/source/funkin/ui/options/PreferencesMenu.hx index 5fbefceed..eb7b88792 100644 --- a/source/funkin/ui/options/PreferencesMenu.hx +++ b/source/funkin/ui/options/PreferencesMenu.hx @@ -72,6 +72,12 @@ class PreferencesMenu extends Page createPrefItemCheckbox('Auto Pause', 'Automatically pause the game when it loses focus', function(value:Bool):Void { Preferences.autoPause = value; }, Preferences.autoPause); + + #if web + createPrefItemCheckbox('Unlocked Framerate', 'Enable to unlock the framerate', function(value:Bool):Void { + Preferences.unlockedFramerate = value; + }, Preferences.unlockedFramerate); + #end } override function update(elapsed:Float):Void From 3970189fe92dbbdac9256687174f1a9953ee83cf Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 12 Sep 2024 15:43:40 -0400 Subject: [PATCH 751/870] Ensure save data gets flushed when you see a character --- source/funkin/save/Save.hx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx index 1fa283b26..43b7667da 100644 --- a/source/funkin/save/Save.hx +++ b/source/funkin/save/Save.hx @@ -407,6 +407,9 @@ class Save return data.unlocks.charactersSeen; } + /** + * Marks whether the player has seen the spotlight animation, which should only display once per save file ever. + */ public var oldChar(get, set):Bool; function get_oldChar():Bool @@ -416,7 +419,9 @@ class Save function set_oldChar(value:Bool):Bool { - return data.unlocks.oldChar = value; + data.unlocks.oldChar = value; + flush(); + return data.unlocks.oldChar; } /** @@ -425,7 +430,11 @@ class Save */ public function addCharacterSeen(character:String):Void { - if (!data.unlocks.charactersSeen.contains(character)) data.unlocks.charactersSeen.push(character); + if (!data.unlocks.charactersSeen.contains(character)) + { + data.unlocks.charactersSeen.push(character); + flush(); + } } /** From a9667c54f377a1207b70ba163ceebd8f239a5822 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 12 Sep 2024 15:48:41 -0400 Subject: [PATCH 752/870] Fix FlxAtlasSprite completion handling and music looping --- source/funkin/audio/FunkinSound.hx | 2 ++ .../funkin/graphics/adobeanimate/FlxAtlasSprite.hx | 9 +++++++-- source/funkin/play/ResultState.hx | 6 ++---- source/funkin/play/scoring/Scoring.hx | 13 ------------- 4 files changed, 11 insertions(+), 19 deletions(-) diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx index 18a0b4da2..dae31cd07 100644 --- a/source/funkin/audio/FunkinSound.hx +++ b/source/funkin/audio/FunkinSound.hx @@ -340,6 +340,8 @@ class FunkinSound extends FlxSound implements ICloneable if (songMusicData != null) { Conductor.instance.mapTimeChanges(songMusicData.timeChanges); + + if (songMusicData.looped != null && params.loop == null) params.loop = songMusicData.looped; } else { diff --git a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx index f245afec7..952fa8b71 100644 --- a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx +++ b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx @@ -185,11 +185,12 @@ class FlxAtlasSprite extends FlxAnimate // Move to the first frame of the animation. // goToFrameLabel(id); trace('Playing animation $id'); - if (this.anim.symbolDictionary.exists(id) || (this.anim.getByName(id) != null)) + if ((id == null || id == "") || this.anim.symbolDictionary.exists(id) || (this.anim.getByName(id) != null)) { this.anim.play(id, restart, false, startFrame); - if (id == "Boyfriend DJ fist pump" || startFrame == 4) trace("PUMP COMMAND: " + anim.curFrame); + this.currentAnimation = anim.curSymbol.name; + fr = null; } // Only call goToFrameLabel if there is a frame label with that name. This prevents annoying warnings! @@ -316,6 +317,10 @@ class FlxAtlasSprite extends FlxAnimate { onAnimationComplete.dispatch(currentAnimation); } + else + { + onAnimationComplete.dispatch(''); + } } var prevFrames:Map = []; diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index e0ac3579d..739df167d 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -418,8 +418,7 @@ class ResultState extends MusicBeatSubState { startingVolume: 1.0, overrideExisting: true, - restartTrack: true, - loop: rank.shouldMusicLoop() + restartTrack: true }); }); } @@ -429,8 +428,7 @@ class ResultState extends MusicBeatSubState { startingVolume: 1.0, overrideExisting: true, - restartTrack: true, - loop: rank.shouldMusicLoop() + restartTrack: true }); } }); diff --git a/source/funkin/play/scoring/Scoring.hx b/source/funkin/play/scoring/Scoring.hx index 6c9f9bd97..dae098638 100644 --- a/source/funkin/play/scoring/Scoring.hx +++ b/source/funkin/play/scoring/Scoring.hx @@ -577,19 +577,6 @@ enum abstract ScoringRank(String) } } - 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) From f7f311d6f2dc356b363efc8c2f6d7cdf50fd4e35 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Thu, 12 Sep 2024 21:07:40 +0100 Subject: [PATCH 753/870] assets submod....... --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index bd4e2421c..e9cb3eb69 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit bd4e2421c87c31e244bc9c162850b842582c5de4 +Subproject commit e9cb3eb6922b60f43ab25b4695acfd15893ae96e From 33df8936b10e5ee216f6c3817550945993d9466c Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 12 Sep 2024 16:41:14 -0400 Subject: [PATCH 754/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 934468c04..7b5fc3055 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 934468c0472504c282b12c63b473e9f74b5b4517 +Subproject commit 7b5fc3055235c401dd711da9617b3719df1dcf27 From 1ee351c83d13b1c616ac3751675389943a715f83 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 12 Sep 2024 16:42:57 -0400 Subject: [PATCH 755/870] art submod --- art | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/art b/art index 42ac06e51..0dee03f11 160000 --- a/art +++ b/art @@ -1 +1 @@ -Subproject commit 42ac06e51207bda89144fd20a407ed3c3e0c6673 +Subproject commit 0dee03f11afc01c2883da223fa10405f7011dd33 From a4e977f60f531b90699473640be2ff0027c26b78 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 12 Sep 2024 16:45:20 -0400 Subject: [PATCH 756/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index e9cb3eb69..8762fd51c 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit e9cb3eb6922b60f43ab25b4695acfd15893ae96e +Subproject commit 8762fd51c26abdc9a45657eab9018aa48e972cd6 From 395de4ee9571daab95fc8f32bf7fb1c309d7d0b0 Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Thu, 12 Sep 2024 22:53:01 +0200 Subject: [PATCH 757/870] Char select subs stuff --- assets | 2 +- .../ui/charSelect/CharSelectSubState.hx | 142 ++++++++++++------ 2 files changed, 94 insertions(+), 50 deletions(-) diff --git a/assets b/assets index 26ab9a1dc..ff425d983 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 26ab9a1dc8eec563717711b290c21d0e9e56a005 +Subproject commit ff425d983e3b017b3a7dc241f03ae51f1fae9116 diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index e075abca3..b83b3a6af 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -35,63 +35,58 @@ import openfl.filters.ShaderFilter; import funkin.util.FramesJSFLParser; import funkin.util.FramesJSFLParser.FramesJSFLInfo; import funkin.util.FramesJSFLParser.FramesJSFLFrame; +import funkin.graphics.FunkinSprite; class CharSelectSubState extends MusicBeatSubState { var cursor:FlxSprite; + var cursorBlue:FlxSprite; var cursorDarkBlue:FlxSprite; - var grpCursors:FlxTypedGroup; - var cursorConfirmed:FlxSprite; var cursorDenied:FlxSprite; - var cursorX:Int = 0; var cursorY:Int = 0; - var cursorFactor:Float = 110; var cursorOffsetX:Float = -16; var cursorOffsetY:Float = -48; - var cursorLocIntended:FlxPoint = new FlxPoint(0, 0); var lerpAmnt:Float = 0.95; - var tmrFrames:Int = 60; - var currentStage:Stage; - var playerChill:CharSelectPlayer; var playerChillOut:CharSelectPlayer; var gfChill:CharSelectGF; var gfChillOut:CharSelectGF; - var barthing:FlxAtlasSprite; var dipshitBacking:FlxSprite; var chooseDipshit:FlxSprite; var dipshitBlur:FlxSprite; var transitionGradient:FlxSprite; - var curChar(default, set):String = "pico"; var nametag:Nametag; var camFollow:FlxObject; var autoFollow:Bool = false; - var availableChars:Map = new Map(); var pressedSelect:Bool = false; - var selectTimer:FlxTimer = new FlxTimer(); + var selectSound:FunkinSound; var unlockSound:FunkinSound; + var lockedSound:FunkinSound; + var introSound:FunkinSound; + var staticSound:FunkinSound; var charSelectCam:FunkinCamera; var selectedBizz:Array = [ - new DropShadowFilter(0, 0, 0xFFFFFF, 1, 2, 2, 21, 1, false, false, false), + new DropShadowFilter(0, 0, 0xFFFFFF, 1, 2, 2, 19, 1, false, false, false), new DropShadowFilter(5, 45, 0x000000, 1, 2, 2, 1, 1, false, false, false) ]; var bopInfo:FramesJSFLInfo; + var blackScreen:FunkinSprite; public function new() { @@ -125,11 +120,6 @@ class CharSelectSubState extends MusicBeatSubState override public function create():Void { - openSubState(new IntroSubState()); - subStateClosed.addOnce((_) -> { - camera.flash(); - checkNewChar(); - }); super.create(); bopInfo = FramesJSFLParser.parse(Paths.file("images/charSelect/iconBopInfo/iconBopInfo.txt")); @@ -140,7 +130,7 @@ class CharSelectSubState extends MusicBeatSubState add(bg); var crowd:FlxAtlasSprite = new FlxAtlasSprite(0, 0, Paths.animateAtlas("charSelect/crowd")); - crowd.anim.play(""); + crowd.anim.play(); crowd.scrollFactor.set(0.3, 0.3); add(crowd); @@ -301,8 +291,25 @@ class CharSelectSubState extends MusicBeatSubState unlockSound.volume = 0; unlockSound.play(true); - FlxG.sound.defaultSoundGroup.add(unlockSound); - FlxG.sound.list.add(unlockSound); + lockedSound = new FunkinSound(); + lockedSound.loadEmbedded(Paths.sound('CS_locked')); + lockedSound.pitch = 1; + + lockedSound.volume = 1.; + + FlxG.sound.defaultSoundGroup.add(lockedSound); + FlxG.sound.list.add(lockedSound); + + staticSound = new FunkinSound(); + staticSound.loadEmbedded(Paths.sound('static loop')); + staticSound.pitch = 1; + + staticSound.looped = true; + + staticSound.volume = 0.6; + + FlxG.sound.defaultSoundGroup.add(staticSound); + FlxG.sound.list.add(staticSound); // playing it here to preload it. not doing this makes a super awkward pause at the end of the intro // TODO: probably make an intro thing for funkinSound itself that preloads the next audio? @@ -365,6 +372,34 @@ class CharSelectSubState extends MusicBeatSubState FlxG.camera.follow(camFollow, LOCKON, 0.01); } }); + + var blackScreen = new FunkinSprite().makeSolidColor(FlxG.width * 2, FlxG.height * 2, 0xFF000000); + blackScreen.x = -(FlxG.width * 0.5); + blackScreen.y = -(FlxG.height * 0.5); + add(blackScreen); + + introSound = new FunkinSound(); + introSound.loadEmbedded(Paths.sound('CS_Lights')); + introSound.pitch = 1; + introSound.volume = 0; + + FlxG.sound.defaultSoundGroup.add(introSound); + FlxG.sound.list.add(introSound); + + openSubState(new IntroSubState()); + subStateClosed.addOnce((_) -> { + remove(blackScreen); + if (!Save.instance.oldChar) + { + camera.flash(); + + introSound.volume = 1; + introSound.play(true); + } + checkNewChar(); + + Save.instance.oldChar = true; + }); } function checkNewChar():Void @@ -396,7 +431,6 @@ class CharSelectSubState extends MusicBeatSubState var grpIcons:FlxSpriteGroup; var grpXSpread(default, set):Float = 107; var grpYSpread(default, set):Float = 127; - var nonLocks = []; function initLocks():Void @@ -426,9 +460,9 @@ class CharSelectSubState extends MusicBeatSubState var temp:Lock = new Lock(0, 0, i); temp.ID = 1; - temp.onAnimationComplete.add(function(anim) { - if (anim == "unlock") playerChill.playAnimation("unlock", true); - }); + // temp.onAnimationComplete.add(function(anim) { + // if (anim == "unlock") playerChill.playAnimation("unlock", true); + // }); grpIcons.add(temp); } @@ -443,7 +477,7 @@ class CharSelectSubState extends MusicBeatSubState { var index = nonLocks[0]; - // pressedSelect = true; + pressedSelect = true; var copy = 3; @@ -505,7 +539,7 @@ class CharSelectSubState extends MusicBeatSubState updateIconPositions(); playerChillOut.onAnimationComplete.addOnce((_) -> if (_ == "death") { - sync = false; + // sync = false; playerChillOut.visible = false; playerChillOut.switchChar(char); }); @@ -515,6 +549,9 @@ class CharSelectSubState extends MusicBeatSubState { pressedSelect = false; @:bypassAccessor curChar = char; + + staticSound.stop(); + FunkinSound.playMusic('stayFunky', { startingVolume: 1, @@ -561,15 +598,13 @@ class CharSelectSubState extends MusicBeatSubState } var sync:Bool = false; - var syncLock:Lock = null; - var audioBizz:Float = 0; function syncAudio(elapsed:Float):Void { @:privateAccess - if (sync && !unlockSound.paused) + if (sync && unlockSound.time > 0) { // if (playerChillOut.anim.framerate > 0) // { @@ -580,14 +615,12 @@ class CharSelectSubState extends MusicBeatSubState playerChillOut.anim._tick = 0; if (syncLock != null) syncLock.anim._tick = 0; - trace(unlockSound.time); - - if ((unlockSound.time - audioBizz) >= (delay * 1000)) + if ((unlockSound.time - audioBizz) >= ((delay) * 100)) { if (syncLock != null) syncLock.anim._tick = delay; playerChillOut.anim._tick = delay; - audioBizz += delay * 1000; + audioBizz += delay * 100; } } } @@ -734,11 +767,14 @@ class CharSelectSubState extends MusicBeatSubState cursorY = -1; } - if (availableChars.exists(getCurrentSelected()) && Save.instance.charactersSeen.contains(availableChars[getCurrentSelected()])) + if (autoFollow + && availableChars.exists(getCurrentSelected()) + && Save.instance.charactersSeen.contains(availableChars[getCurrentSelected()])) { + gfChill.visible = true; curChar = availableChars.get(getCurrentSelected()); - if (controls.ACCEPT) + if (!pressedSelect && controls.ACCEPT) { cursorConfirmed.visible = true; cursorConfirmed.x = cursor.x - 2; @@ -752,7 +788,7 @@ class CharSelectSubState extends MusicBeatSubState FlxTween.tween(FlxG.sound.music, {pitch: 0.1}, 1, {ease: FlxEase.quadInOut}); FlxTween.tween(FlxG.sound.music, {volume: 0.0}, 1.5, {ease: FlxEase.quadInOut}); playerChill.playAnimation("select"); - gfChill.playAnimation("confirm"); + gfChill.playAnimation("confirm", true, false, true); pressedSelect = true; selectTimer.start(1.5, (_) -> { // pressedSelect = false; @@ -775,29 +811,37 @@ class CharSelectSubState extends MusicBeatSubState FlxTween.tween(FlxG.sound.music, {pitch: 1.0, volume: 1.0}, 1, {ease: FlxEase.quartInOut}); playerChill.playAnimation("deselect"); gfChill.playAnimation("deselect"); + pressedSelect = false; FlxTween.tween(FlxG.sound.music, {pitch: 1.0}, 1, { ease: FlxEase.quartInOut, onComplete: (_) -> { - playerChill.playAnimation("idle", true, false, true); - gfChill.playAnimation("idle", true, false, true); + if (playerChill.getCurrentAnimation() == "deselect loop start" || playerChill.getCurrentAnimation() == "deselect") + { + playerChill.playAnimation("idle", true, false, true); + gfChill.playAnimation("idle", true, false, true); + } } }); - pressedSelect = false; selectTimer.cancel(); } } - else + else if (autoFollow) { curChar = "locked"; + gfChill.visible = false; + if (controls.ACCEPT) { cursorDenied.visible = true; cursorDenied.x = cursor.x - 2; cursorDenied.y = cursor.y - 4; - playerChill.playAnimation("cannot select", true); + playerChill.playAnimation("cannot select Label", true); + + lockedSound.play(true); + cursorDenied.animation.play("idle", true); cursorDenied.animation.finishCallback = (_) -> { cursorDenied.visible = false; @@ -831,13 +875,9 @@ class CharSelectSubState extends MusicBeatSubState } var bopTimer:Float = 0; - var delay = 1 / 24; - var bopFr = 0; - var bopPlay:Bool = false; - var bopRefX:Float = 0; var bopRefY:Float = 0; @@ -957,10 +997,10 @@ class CharSelectSubState extends MusicBeatSubState memb.filters = selectedBizz; memb.scale.set(2.6, 2.6); } - if (controls.ACCEPT && memb.animation.curAnim.name == "confirm") memb.animation.play("confirm"); - if (pressedSelect && controls.BACK) + if (pressedSelect && memb.animation.curAnim.name == "idle") memb.animation.play("confirm"); + if (autoFollow && !pressedSelect && memb.animation.curAnim.name != "idle") { - memb.animation.play("confirm", true, true); + memb.animation.play("confirm", false, true); member.animation.finishCallback = (_) -> { member.animation.play("idle"); member.animation.finishCallback = null; @@ -991,6 +1031,10 @@ class CharSelectSubState extends MusicBeatSubState curChar = value; + if (value == "locked") staticSound.play(); + else + staticSound.stop(); + nametag.switchChar(value); playerChill.visible = false; playerChillOut.visible = true; From f0ac09f949f7f56789e08ceaacbbbdb456a8ad03 Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Thu, 12 Sep 2024 22:53:11 +0200 Subject: [PATCH 758/870] Art master bizz --- art | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/art b/art index 1206249aa..0bb988c49 160000 --- a/art +++ b/art @@ -1 +1 @@ -Subproject commit 1206249aa65e13df2d6a196c35222f768ad4a3f4 +Subproject commit 0bb988c49788fd25a230b56dd9e4448838bc79c9 From 2a9814e03061ee6b18dc61a93d17b5616eae46d1 Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Thu, 12 Sep 2024 22:58:31 +0200 Subject: [PATCH 759/870] port SAVE from develop --- source/funkin/save/Save.hx | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx index 80b05e5ac..43b7667da 100644 --- a/source/funkin/save/Save.hx +++ b/source/funkin/save/Save.hx @@ -125,6 +125,7 @@ class Save { // Default to having seen the default character. charactersSeen: ["bf"], + oldChar: false }, optionsChartEditor: @@ -406,13 +407,34 @@ class Save return data.unlocks.charactersSeen; } + /** + * Marks whether the player has seen the spotlight animation, which should only display once per save file ever. + */ + public var oldChar(get, set):Bool; + + function get_oldChar():Bool + { + return data.unlocks.oldChar; + } + + function set_oldChar(value:Bool):Bool + { + data.unlocks.oldChar = value; + flush(); + return data.unlocks.oldChar; + } + /** * When we've seen a character unlock, add it to the list of characters seen. * @param character */ public function addCharacterSeen(character:String):Void { - if (!data.unlocks.charactersSeen.contains(character)) data.unlocks.charactersSeen.push(character); + if (!data.unlocks.charactersSeen.contains(character)) + { + data.unlocks.charactersSeen.push(character); + flush(); + } } /** @@ -1027,6 +1049,12 @@ typedef SaveDataUnlocks = * add it to this list so that we don't show it again. */ var charactersSeen:Array; + + /** + * This is a conditional when the player enters the character state + * For the first time ever + */ + var oldChar:Bool; } /** From 6dca858fd7370d23626d76b64c50eedafc36519c Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Thu, 12 Sep 2024 23:13:30 +0200 Subject: [PATCH 760/870] Introbizz --- source/funkin/ui/charSelect/IntroSubState.hx | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/source/funkin/ui/charSelect/IntroSubState.hx b/source/funkin/ui/charSelect/IntroSubState.hx index 04503cbb9..8706013b0 100644 --- a/source/funkin/ui/charSelect/IntroSubState.hx +++ b/source/funkin/ui/charSelect/IntroSubState.hx @@ -20,8 +20,6 @@ class IntroSubState extends MusicBeatSubState { static final ATTRACT_VIDEO_PATH:String = Paths.stripLibrary(Paths.videos('introSelect')); - var introSound:FunkinSound = null; - public override function create():Void { // Pause existing music. @@ -40,15 +38,6 @@ class IntroSubState extends MusicBeatSubState trace('Playing native video ${ATTRACT_VIDEO_PATH}'); playVideoNative(ATTRACT_VIDEO_PATH); #end - - introSound = new FunkinSound(); - introSound.loadEmbedded(Paths.sound('CS_Lights')); - introSound.pitch = 1; - - FlxG.sound.defaultSoundGroup.add(introSound); - FlxG.sound.list.add(introSound); - - introSound.play(true); } #if html5 From a4bdeeaf5f9b3a7aa57a87c6d28b190e860e7749 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 12 Sep 2024 17:13:40 -0400 Subject: [PATCH 761/870] Update polymod to fix a crash on missing imports --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index 50b81bb85..d967a69b3 100644 --- a/hmm.json +++ b/hmm.json @@ -194,7 +194,7 @@ "name": "polymod", "type": "git", "dir": null, - "ref": "96cfc5fa693b017e47f7cb13b765cc68698fa6b6", + "ref": "0fbdf27fe124549730accd540cec8a183f8652c0", "url": "https://github.com/larsiusprime/polymod" }, { From ae6f431b6a9f7a05bf819c908794a16b2fb073f2 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 12 Sep 2024 17:13:46 -0400 Subject: [PATCH 762/870] Update credits --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 8762fd51c..dd2aab796 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 8762fd51c26abdc9a45657eab9018aa48e972cd6 +Subproject commit dd2aab796d2a54cf01c534402aa922da1f820080 From 34d1c568ea949740837bd7c1c4e9a685e4187d94 Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Thu, 12 Sep 2024 23:22:20 +0200 Subject: [PATCH 763/870] locked fixin --- assets | 2 +- source/funkin/ui/charSelect/CharSelectPlayer.hx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/assets b/assets index ff425d983..6b97a5ce8 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit ff425d983e3b017b3a7dc241f03ae51f1fae9116 +Subproject commit 6b97a5ce8bb09944e466bc6c342139462820f81f diff --git a/source/funkin/ui/charSelect/CharSelectPlayer.hx b/source/funkin/ui/charSelect/CharSelectPlayer.hx index 710bdd45a..b6319f16d 100644 --- a/source/funkin/ui/charSelect/CharSelectPlayer.hx +++ b/source/funkin/ui/charSelect/CharSelectPlayer.hx @@ -27,7 +27,7 @@ class CharSelectPlayer extends FlxAtlasSprite implements IBPMSyncedScriptedClass case "deselect": playAnimation("deselect loop start", true, false, true); - case "slidein idle point", "cannot select", "unlock": + case "slidein idle point", "cannot select Label", "unlock": playAnimation("idle", true, false, false); case "idle": trace('Waiting for onBeatHit'); From 703e8992882b8b3e70a74e74c31aa5e52137d6c2 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Thu, 12 Sep 2024 22:43:12 +0100 Subject: [PATCH 764/870] apply shader filter --- source/funkin/ui/charSelect/CharSelectSubState.hx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index bd55bfdd9..00e15a299 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -324,6 +324,9 @@ class CharSelectSubState extends MusicBeatSubState // FlxG.camera.follow(camFollow, LOCKON, 0.01); FlxG.camera.follow(camFollow, LOCKON); + var fadeShaderFilter:ShaderFilter = new ShaderFilter(fadeShader); + FlxG.camera.filters = [fadeShaderFilter]; + var temp:FlxSprite = new FlxSprite(); temp.loadGraphic(Paths.image('charSelect/placement')); add(temp); From 5f60be6d7569862486c9eb062da60ee23305f008 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Thu, 12 Sep 2024 22:44:22 +0100 Subject: [PATCH 765/870] allow controls to get dialouge name from control + ignore brackets --- source/funkin/input/Controls.hx | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/source/funkin/input/Controls.hx b/source/funkin/input/Controls.hx index b5aefd08d..da5aaac58 100644 --- a/source/funkin/input/Controls.hx +++ b/source/funkin/input/Controls.hx @@ -395,20 +395,37 @@ class Controls extends FlxActionSet return result; } - public function getDialogueName(action:FlxActionDigital):String + public function getDialogueName(action:FlxActionDigital, ?ignoreSurrounding:Bool = false):String { var input = action.inputs[0]; - return switch (input.device) + if (ignoreSurrounding == false) { - case KEYBOARD: return '[${(input.inputID : FlxKey)}]'; - case GAMEPAD: return '(${(input.inputID : FlxGamepadInputID)})'; - case device: throw 'unhandled device: $device'; + return switch (input.device) + { + case KEYBOARD: return '[${(input.inputID : FlxKey)}]'; + case GAMEPAD: return '(${(input.inputID : FlxGamepadInputID)})'; + case device: throw 'unhandled device: $device'; + } + } + else + { + return switch (input.device) + { + case KEYBOARD: return '${(input.inputID : FlxKey)}'; + case GAMEPAD: return '${(input.inputID : FlxGamepadInputID)}'; + case device: throw 'unhandled device: $device'; + } } } - public function getDialogueNameFromToken(token:String):String + public function getDialogueNameFromToken(token:String, ?ignoreSurrounding:Bool = false):String { - return getDialogueName(getActionFromControl(Control.createByName(token.toUpperCase()))); + return getDialogueName(getActionFromControl(Control.createByName(token.toUpperCase())), ignoreSurrounding); + } + + public function getDialogueNameFromControl(control:Control, ?ignoreSurrounding:Bool = false):String + { + return getDialogueName(getActionFromControl(control), ignoreSurrounding); } function getActionFromControl(control:Control):FlxActionDigital From bc86f1f459605450b092121ea295b8a3ef23541e Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Thu, 12 Sep 2024 22:44:40 +0100 Subject: [PATCH 766/870] character select hint text --- source/funkin/ui/freeplay/FreeplayState.hx | 29 ++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index a908e54c6..23b9dd0bd 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -9,6 +9,7 @@ import flixel.group.FlxGroup.FlxTypedGroup; import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup; import flixel.input.touch.FlxTouch; import flixel.math.FlxAngle; +import flixel.math.FlxMath; import flixel.math.FlxPoint; import flixel.system.debug.watch.Tracker.TrackerProfile; import flixel.text.FlxText; @@ -180,6 +181,8 @@ class FreeplayState extends MusicBeatSubState var ostName:FlxText; var albumRoll:AlbumRoll; + var charSelectHint:FlxText; + var letterSort:LetterSort; var exitMovers:ExitMoverData = new Map(); @@ -279,6 +282,7 @@ class FreeplayState extends MusicBeatSubState txtCompletion = new AtlasText(1185, 87, '69', AtlasFont.FREEPLAY_CLEAR); ostName = new FlxText(8, 8, FlxG.width - 8 - 8, 'OFFICIAL OST', 48); + charSelectHint = new FlxText(-40, 18, FlxG.width - 8 - 8, 'Press [ LOL ] to change characters', 32); bgDad = new FlxSprite(backingCard.pinkBack.width * 0.74, 0).loadGraphic(styleData == null ? 'freeplay/freeplayBGdad' : styleData.getBgAssetGraphic()); } @@ -498,7 +502,14 @@ class FreeplayState extends MusicBeatSubState ostName.alignment = RIGHT; ostName.visible = false; - exitMovers.set([overhangStuff, fnfFreeplay, ostName], + charSelectHint.alignment = CENTER; + charSelectHint.font = "5by7"; + charSelectHint.color = 0xFF5F5F5F; + charSelectHint.text = 'Press [ ${controls.getDialogueNameFromControl(FREEPLAY_CHAR_SELECT, true)} ] to change characters'; + charSelectHint.y -= 100; + FlxTween.tween(charSelectHint, {y: charSelectHint.y + 100}, 0.8, {ease: FlxEase.quartOut}); + + exitMovers.set([overhangStuff, fnfFreeplay, ostName, charSelectHint], { y: -overhangStuff.height, x: 0, @@ -506,7 +517,7 @@ class FreeplayState extends MusicBeatSubState wait: 0 }); - exitMoversCharSel.set([overhangStuff, fnfFreeplay, ostName], + exitMoversCharSel.set([overhangStuff, fnfFreeplay, ostName, charSelectHint], { y: -300, speed: 0.8, @@ -604,6 +615,11 @@ class FreeplayState extends MusicBeatSubState add(fnfFreeplay); add(ostName); + if (PlayerRegistry.instance.hasNewCharacter() == true) + { + add(charSelectHint); + } + // be careful not to "add()" things in here unless it's to a group that's already added to the state // otherwise it won't be properly attatched to funnyCamera (relavent code should be at the bottom of create()) var onDJIntroDone = function() { @@ -1348,10 +1364,19 @@ class FreeplayState extends MusicBeatSubState var originalPos:FlxPoint = new FlxPoint(); + var hintTimer:Float = 0; + override function update(elapsed:Float):Void { super.update(elapsed); + if (charSelectHint != null) + { + hintTimer += elapsed * 2; + var targetAmt:Float = (Math.sin(hintTimer) + 1) / 2; + charSelectHint.alpha = FlxMath.lerp(0.3, 0.9, targetAmt); + } + #if FEATURE_DEBUG_FUNCTIONS if (FlxG.keys.justPressed.P) { From f96532f104dfc126b89824c6d0a570b6817d4ace Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Thu, 12 Sep 2024 22:47:58 +0100 Subject: [PATCH 767/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index bd4e2421c..350910d80 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit bd4e2421c87c31e244bc9c162850b842582c5de4 +Subproject commit 350910d8094853d11deb2ee27cacbe3ada27af32 From 1e9c6f0c4cabaaf439e493c619dc65f564e0a7c7 Mon Sep 17 00:00:00 2001 From: CheemsAndFriends Date: Fri, 13 Sep 2024 00:31:52 +0200 Subject: [PATCH 768/870] Add Char Select stuff --- assets | 2 +- source/funkin/ui/charSelect/CharSelectSubState.hx | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/assets b/assets index 6b97a5ce8..f4cf1d372 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 6b97a5ce8bb09944e466bc6c342139462820f81f +Subproject commit f4cf1d3721155e16ab4e547b6baabc1238b66dae diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index b83b3a6af..6839d5a21 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -291,6 +291,9 @@ class CharSelectSubState extends MusicBeatSubState unlockSound.volume = 0; unlockSound.play(true); + FlxG.sound.defaultSoundGroup.add(unlockSound); + FlxG.sound.list.add(unlockSound); + lockedSound = new FunkinSound(); lockedSound.loadEmbedded(Paths.sound('CS_locked')); lockedSound.pitch = 1; @@ -404,7 +407,7 @@ class CharSelectSubState extends MusicBeatSubState function checkNewChar():Void { - if (nonLocks.length > 0) selectTimer.start(0.5, (_) -> { + if (nonLocks.length > 0) selectTimer.start(2, (_) -> { unLock(); }); else From 2dc4e13b001de00318884dbbf635e26240586622 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 12 Sep 2024 19:08:13 -0400 Subject: [PATCH 769/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index dd2aab796..41d20d45d 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit dd2aab796d2a54cf01c534402aa922da1f820080 +Subproject commit 41d20d45d7503aaf1dfac825239620cffb512166 From fdc5bc6b79880390851559278df94de71b551f98 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Fri, 13 Sep 2024 00:37:47 +0100 Subject: [PATCH 770/870] assets submod... --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 8762fd51c..51d053723 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 8762fd51c26abdc9a45657eab9018aa48e972cd6 +Subproject commit 51d0537239debf699efa90591b10995c5b765095 From 47f3c6f00a18b50a614ffd09f9200ee18c89f499 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 12 Sep 2024 19:56:04 -0400 Subject: [PATCH 771/870] vid sizing --- source/funkin/ui/charSelect/IntroSubState.hx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/funkin/ui/charSelect/IntroSubState.hx b/source/funkin/ui/charSelect/IntroSubState.hx index 261b7b35c..2c2908473 100644 --- a/source/funkin/ui/charSelect/IntroSubState.hx +++ b/source/funkin/ui/charSelect/IntroSubState.hx @@ -41,10 +41,10 @@ class IntroSubState extends MusicBeatSubState playVideoNative(LIGHTS_VIDEO_PATH); #end - // Im TOO lazy to even care, so uh, yep - FlxG.camera.zoom = 0.66666666666666666666666666666667; - vid.x = -(FlxG.width - (FlxG.width * FlxG.camera.zoom)); - vid.y = -((FlxG.height - (FlxG.height * FlxG.camera.zoom)) * 0.75); + // // Im TOO lazy to even care, so uh, yep + // FlxG.camera.zoom = 0.66666666666666666666666666666667; + // vid.x = -(FlxG.width - (FlxG.width * FlxG.camera.zoom)); + // vid.y = -((FlxG.height - (FlxG.height * FlxG.camera.zoom)) * 0.75); } #if html5 From 0aa2ccd1cd6ddfb0c002a31d9bf408017cc24154 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 12 Sep 2024 20:05:14 -0400 Subject: [PATCH 772/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 51d053723..a3a8c4a15 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 51d0537239debf699efa90591b10995c5b765095 +Subproject commit a3a8c4a1535140a1e8127c862c28c86000fe8403 From 172c90b1bd6d6baedf06b6170bf64528b92f4adb Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 12 Sep 2024 20:12:20 -0400 Subject: [PATCH 773/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index a3a8c4a15..3d096c3b8 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit a3a8c4a1535140a1e8127c862c28c86000fe8403 +Subproject commit 3d096c3b89e1b4c92c0a3f058e80f19585126e1e From af31be5436423422379c824d0c421dd66c6f7252 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 12 Sep 2024 20:14:48 -0400 Subject: [PATCH 774/870] makeship linky --- 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 1653311df..57fc484b8 100644 --- a/source/funkin/util/Constants.hx +++ b/source/funkin/util/Constants.hx @@ -63,7 +63,7 @@ class Constants /** * Link to buy merch for the game. */ - public static final URL_MERCH:String = 'https://needlejuicerecords.com/pages/friday-night-funkin'; + public static final URL_MERCH:String = 'https://www.makeship.com/shop/creator/friday-night-funkin'; /** * Preloader sitelock. From c6bdd36959cb0f85b429d6d66e5842a006a3d8e2 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 12 Sep 2024 20:32:19 -0400 Subject: [PATCH 775/870] Fix blazin offsets --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index a3a8c4a15..96e5401f7 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit a3a8c4a1535140a1e8127c862c28c86000fe8403 +Subproject commit 96e5401f7e1facbf9a59a52a2d8f59523cb83b3c From c9d6c194201da048becb9d6c6577e95d0d08d18e Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 12 Sep 2024 20:35:13 -0400 Subject: [PATCH 776/870] Update fresh audio --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 96e5401f7..4e1827f7a 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 96e5401f7e1facbf9a59a52a2d8f59523cb83b3c +Subproject commit 4e1827f7a53e07a70e1b489f2aaf91c93407be7d From 0e225c9bae809b59b303e0dff540b0a29fcc33f6 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 12 Sep 2024 20:51:02 -0400 Subject: [PATCH 777/870] Update eggnog vocals again --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 4e1827f7a..9306f9b41 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 4e1827f7a53e07a70e1b489f2aaf91c93407be7d +Subproject commit 9306f9b4104cccb0988405c9d07fb2465f4ac8f2 From 80868ccbba3058b8292c5ee0156596982f113d73 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 12 Sep 2024 21:53:38 -0400 Subject: [PATCH 778/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 9306f9b41..35395f8f9 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 9306f9b4104cccb0988405c9d07fb2465f4ac8f2 +Subproject commit 35395f8f9c4ef1603cb33ea5f8e9fce58e01158b From d3d998d9947ebced6b245f1ee33ec103db6892d0 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 12 Sep 2024 21:57:48 -0400 Subject: [PATCH 779/870] saru fixies --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 35395f8f9..bc7009b42 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 35395f8f9c4ef1603cb33ea5f8e9fce58e01158b +Subproject commit bc7009b4242691faa5c4552f7ca8a2f28e8cb1d2 From d59594ee453b54dc48a3e4b969e6a5940c5d9b7a Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 12 Sep 2024 21:55:12 -0400 Subject: [PATCH 780/870] Fix animations not looping on Char Select --- source/funkin/ui/charSelect/CharSelectSubState.hx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index dd5b2a3a2..3109dc8f1 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -131,6 +131,9 @@ class CharSelectSubState extends MusicBeatSubState var crowd:FlxAtlasSprite = new FlxAtlasSprite(0, 0, Paths.animateAtlas("charSelect/crowd")); crowd.anim.play(); + crowd.anim.onComplete.add(function() { + crowd.anim.play(); + }); crowd.scrollFactor.set(0.3, 0.3); add(crowd); @@ -147,6 +150,9 @@ class CharSelectSubState extends MusicBeatSubState barthing = new FlxAtlasSprite(0, 0, Paths.animateAtlas("charSelect/barThing")); barthing.anim.play(""); + barthing.anim.onComplete.add(function() { + barthing.anim.play(""); + }); barthing.blend = BlendMode.MULTIPLY; barthing.scrollFactor.set(0, 0); add(barthing); @@ -176,6 +182,9 @@ class CharSelectSubState extends MusicBeatSubState var speakers:FlxAtlasSprite = new FlxAtlasSprite(0, 0, Paths.animateAtlas("charSelect/charSelectSpeakers")); speakers.anim.play(""); + speakers.anim.onComplete.add(function() { + speakers.anim.play(""); + }); speakers.scrollFactor.set(1.8, 1.8); add(speakers); From 178389ea0bd00bb7d1822abaff2aa3524f3f3f61 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 12 Sep 2024 23:28:43 -0400 Subject: [PATCH 781/870] Fix two song credits --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index bc7009b42..c3041be56 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit bc7009b4242691faa5c4552f7ca8a2f28e8cb1d2 +Subproject commit c3041be56396cda92f87d071f74d36113ed25e1f From 3fba55a4229139de0f64925f2bfc77ce1f689b0f Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Fri, 13 Sep 2024 21:36:20 +0100 Subject: [PATCH 782/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 8762fd51c..eaab81b1a 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 8762fd51c26abdc9a45657eab9018aa48e972cd6 +Subproject commit eaab81b1a76d18f356cf0a38f3feed463aed28cb From 517984d1200f0fe43a7a7bec4bd62cd6032a8997 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 13 Sep 2024 18:46:49 -0400 Subject: [PATCH 783/870] Fix a bug where Shit judgement would always display with anti-aliasing. --- source/funkin/play/notes/notestyle/NoteStyle.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/play/notes/notestyle/NoteStyle.hx b/source/funkin/play/notes/notestyle/NoteStyle.hx index ee07703f1..83aae6fcf 100644 --- a/source/funkin/play/notes/notestyle/NoteStyle.hx +++ b/source/funkin/play/notes/notestyle/NoteStyle.hx @@ -575,7 +575,7 @@ class NoteStyle implements IRegistryEntry var result = _data.assets.judgementBad?.isPixel; if (result == null && fallback != null) result = fallback.isJudgementSpritePixel(rating); return result ?? false; - case "GO": + case "shit": var result = _data.assets.judgementShit?.isPixel; if (result == null && fallback != null) result = fallback.isJudgementSpritePixel(rating); return result ?? false; From df87d677e1b155049bc254904a965989b53fa160 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 14 Sep 2024 17:00:41 -0400 Subject: [PATCH 784/870] Typo lol --- source/funkin/modding/PolymodHandler.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/modding/PolymodHandler.hx b/source/funkin/modding/PolymodHandler.hx index 75c69e506..e0b27e744 100644 --- a/source/funkin/modding/PolymodHandler.hx +++ b/source/funkin/modding/PolymodHandler.hx @@ -258,7 +258,7 @@ class PolymodHandler Polymod.blacklistImport('cpp.Lib'); // `Unserializer` - // Unserializerr.DEFAULT_RESOLVER.resolveClass() can access blacklisted packages + // Unserializer.DEFAULT_RESOLVER.resolveClass() can access blacklisted packages Polymod.blacklistImport('Unserializer'); // `lime.system.CFFI` From 0a8719088da94f295481d17a167e1875646a4d92 Mon Sep 17 00:00:00 2001 From: Til Tjardes Date: Sat, 14 Sep 2024 15:06:03 -0600 Subject: [PATCH 785/870] techniktil coming back with another typo lets go --- source/funkin/modding/events/ScriptEvent.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/modding/events/ScriptEvent.hx b/source/funkin/modding/events/ScriptEvent.hx index dd55de23b..cc1d00b58 100644 --- a/source/funkin/modding/events/ScriptEvent.hx +++ b/source/funkin/modding/events/ScriptEvent.hx @@ -103,7 +103,7 @@ class NoteScriptEvent extends ScriptEvent public var comboCount(default, null):Int; /** - * Whether to play the record scratch sound (if this eventn type is `NOTE_MISS`). + * Whether to play the record scratch sound (if this event type is `NOTE_MISS`). */ public var playSound(default, default):Bool; From 688abb557134d6b786628c206db126cfcba6d579 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 14 Sep 2024 20:25:45 -0400 Subject: [PATCH 786/870] Update example mod's API version so it actually loads. --- example_mods/introMod/_polymod_meta.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example_mods/introMod/_polymod_meta.json b/example_mods/introMod/_polymod_meta.json index 4dc0cd804..74c4a2504 100644 --- a/example_mods/introMod/_polymod_meta.json +++ b/example_mods/introMod/_polymod_meta.json @@ -6,7 +6,7 @@ "name": "EliteMasterEric" } ], - "api_version": "0.1.0", + "api_version": "0.5.0", "mod_version": "1.0.0", "license": "Apache-2.0" } From d5c7e4ffdb0076d1c54ee9e9703fb0a3a682fd96 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 14 Sep 2024 20:26:19 -0400 Subject: [PATCH 787/870] Fix bug where Pico would become locked on every game restart. --- source/funkin/save/Save.hx | 20 +++++++--- source/funkin/save/changelog.md | 6 +++ source/funkin/ui/mainmenu/MainMenuState.hx | 43 ++++++++++++---------- source/funkin/ui/title/TitleState.hx | 5 --- 4 files changed, 43 insertions(+), 31 deletions(-) diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx index 2bbda15c0..eb9f6005e 100644 --- a/source/funkin/save/Save.hx +++ b/source/funkin/save/Save.hx @@ -17,7 +17,7 @@ import thx.semver.Version; @:nullSafety class Save { - public static final SAVE_DATA_VERSION:thx.semver.Version = "2.0.5"; + 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. @@ -34,19 +34,19 @@ class Save { if (_instance == null) { - _instance = new Save(FlxG.save.data); + return _instance = load(); } return _instance; } var data:RawSaveData; - public static function load():Void + public static function load():Save { trace("[SAVE] Loading save..."); // Bind save data. - loadFromSlot(1); + return loadFromSlot(1); } /** @@ -65,7 +65,9 @@ class Save public static function getDefault():RawSaveData { return { - version: Save.SAVE_DATA_VERSION, + // Version number is an abstract(Array) internally. + // This means it copies by reference, so merging save data overides the version number lol. + version: thx.Dynamics.clone(Save.SAVE_DATA_VERSION), volume: 1.0, mute: false, @@ -433,7 +435,9 @@ class Save { if (!data.unlocks.charactersSeen.contains(character)) { + trace('Character seen: ' + character); data.unlocks.charactersSeen.push(character); + trace('New characters seen list: ' + data.unlocks.charactersSeen); flush(); } } @@ -832,7 +836,7 @@ class Save * If you set slot to `2`, it will load an independe * @param slot */ - static function loadFromSlot(slot:Int):Void + static function loadFromSlot(slot:Int):Save { trace("[SAVE] Loading save from slot " + slot + "..."); @@ -850,12 +854,14 @@ class Save trace('[SAVE] Found legacy save data, converting...'); var gameSave = SaveDataMigrator.migrateFromLegacy(legacySaveData); FlxG.save.mergeData(gameSave.data, true); + return gameSave; } else { trace('[SAVE] No legacy save data found.'); var gameSave = new Save(); FlxG.save.mergeData(gameSave.data, true); + return gameSave; } } else @@ -863,6 +869,8 @@ class Save trace('[SAVE] Found existing save data.'); var gameSave = SaveDataMigrator.migrate(FlxG.save.data); FlxG.save.mergeData(gameSave.data, true); + + return gameSave; } } diff --git a/source/funkin/save/changelog.md b/source/funkin/save/changelog.md index e3038373d..41d6e68ae 100644 --- a/source/funkin/save/changelog.md +++ b/source/funkin/save/changelog.md @@ -5,6 +5,12 @@ 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-09-12 +Note to self: Only update to 2.1.0 when migration is needed. +### Added +- `unlocks.charactersSeen:Array` to `Save` +- `unlocks.oldChar:Bool` to `Save` + ## [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. diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index 13d68da6d..a436848d2 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -356,7 +356,7 @@ class MainMenuState extends MusicBeatState #if FEATURE_DEBUG_FUNCTIONS // Ctrl+Alt+Shift+P = Character Unlock screen // Ctrl+Alt+Shift+W = Meet requirements for Pico Unlock - // Ctrl+Alt+Shift+L = Revoke requirements for Pico Unlock + // Ctrl+Alt+Shift+M = Revoke requirements for Pico Unlock // Ctrl+Alt+Shift+R = Score/Rank conflict test // Ctrl+Alt+Shift+N = Mark all characters as not seen // Ctrl+Alt+Shift+E = Dump save data @@ -369,7 +369,7 @@ class MainMenuState extends MusicBeatState if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.W) { FunkinSound.playOnce(Paths.sound('confirmMenu')); - // Give the user a score of 1 point on Weekend 1 story mode. + // Give the user a score of 1 point on Weekend 1 story mode (Easy difficulty). // This makes the level count as cleared and displays the songs in Freeplay. funkin.save.Save.instance.setLevelScore('weekend1', 'easy', { @@ -389,27 +389,30 @@ class MainMenuState extends MusicBeatState }); } - if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.L) + if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.M) { FunkinSound.playOnce(Paths.sound('confirmMenu')); - // Give the user a score of 0 points on Weekend 1 story mode. + // Give the user a score of 0 points on Weekend 1 story mode (all difficulties). // This makes the level count as uncleared and no longer displays the songs in Freeplay. - funkin.save.Save.instance.setLevelScore('weekend1', 'easy', - { - score: 1, - tallies: - { - sick: 0, - good: 0, - bad: 0, - shit: 0, - missed: 0, - combo: 0, - maxCombo: 0, - totalNotesHit: 0, - totalNotes: 0, - } - }); + for (diff in ['easy', 'normal', 'hard']) + { + funkin.save.Save.instance.setLevelScore('weekend1', diff, + { + score: 0, + tallies: + { + sick: 0, + good: 0, + bad: 0, + shit: 0, + missed: 0, + combo: 0, + maxCombo: 0, + totalNotesHit: 0, + totalNotes: 0, + } + }); + } } if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.R) diff --git a/source/funkin/ui/title/TitleState.hx b/source/funkin/ui/title/TitleState.hx index f5c641d0c..10e7dfaae 100644 --- a/source/funkin/ui/title/TitleState.hx +++ b/source/funkin/ui/title/TitleState.hx @@ -273,11 +273,6 @@ class TitleState extends MusicBeatState } #end - if (Save.instance.charactersSeen.contains("pico")) - { - Save.instance.charactersSeen.remove("pico"); - Save.instance.oldChar = false; - } Conductor.instance.update(); /* if (FlxG.onMobile) From fd6ca6e267d5ffbbb63f9e01e7ca92935a6785f4 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 14 Sep 2024 20:26:33 -0400 Subject: [PATCH 788/870] Remove some spammy log traces. --- source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx | 2 +- source/funkin/ui/charSelect/CharSelectPlayer.hx | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx index 952fa8b71..7ea97e39b 100644 --- a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx +++ b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx @@ -184,7 +184,7 @@ class FlxAtlasSprite extends FlxAnimate // Move to the first frame of the animation. // goToFrameLabel(id); - trace('Playing animation $id'); + // trace('Playing animation $id'); if ((id == null || id == "") || this.anim.symbolDictionary.exists(id) || (this.anim.getByName(id) != null)) { this.anim.play(id, restart, false, startFrame); diff --git a/source/funkin/ui/charSelect/CharSelectPlayer.hx b/source/funkin/ui/charSelect/CharSelectPlayer.hx index b6319f16d..1eef52bed 100644 --- a/source/funkin/ui/charSelect/CharSelectPlayer.hx +++ b/source/funkin/ui/charSelect/CharSelectPlayer.hx @@ -47,7 +47,6 @@ class CharSelectPlayer extends FlxAtlasSprite implements IBPMSyncedScriptedClass // if (getCurrentAnimation() == "idle") { - trace('Player beat hit'); playAnimation("idle", true, false, false); } }; From e23a85682a89c049c41cd0b67e434fcce6cc0b29 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 14 Sep 2024 20:26:39 -0400 Subject: [PATCH 789/870] Update some script files. --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index bc7009b42..616551146 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit bc7009b4242691faa5c4552f7ca8a2f28e8cb1d2 +Subproject commit 61655114603807b651109af282c2e2aefa9dccf2 From 9f3af1ab944d41ba56edc7336b6b795fdae89c32 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 14 Sep 2024 20:56:21 -0400 Subject: [PATCH 790/870] Add a separate Gold Perfect animation for modders --- assets | 2 +- source/funkin/data/freeplay/player/PlayerData.hx | 1 + source/funkin/ui/freeplay/charselect/PlayableCharacter.hx | 4 +++- source/funkin/util/Constants.hx | 4 ---- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/assets b/assets index bc7009b42..ef7386d74 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit bc7009b4242691faa5c4552f7ca8a2f28e8cb1d2 +Subproject commit ef7386d741e715bd809c913a7d50dfa7b8176e2d diff --git a/source/funkin/data/freeplay/player/PlayerData.hx b/source/funkin/data/freeplay/player/PlayerData.hx index de293c24e..867fe7113 100644 --- a/source/funkin/data/freeplay/player/PlayerData.hx +++ b/source/funkin/data/freeplay/player/PlayerData.hx @@ -270,6 +270,7 @@ typedef PlayerResultsData = { var music:PlayerResultsMusicData; + var perfectGold:Array; var perfect:Array; var excellent:Array; var great:Array; diff --git a/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx b/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx index 93d643ae4..408a91672 100644 --- a/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx +++ b/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx @@ -113,7 +113,9 @@ class PlayableCharacter implements IRegistryEntry switch (rank) { - case PERFECT | PERFECT_GOLD: + case PERFECT_GOLD: + return _data.results.perfectGold; + case PERFECT: return _data.results.perfect; case EXCELLENT: return _data.results.excellent; diff --git a/source/funkin/util/Constants.hx b/source/funkin/util/Constants.hx index 57fc484b8..cf58d191a 100644 --- a/source/funkin/util/Constants.hx +++ b/source/funkin/util/Constants.hx @@ -481,10 +481,6 @@ 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; From 16aff6e7c35152c4b3fd86ec73fc798b75847016 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 14 Sep 2024 21:37:02 -0400 Subject: [PATCH 791/870] Fix bugs with highscore display in Freeplay --- source/funkin/ui/freeplay/FreeplayState.hx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index af0a9b841..15633ff9d 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -586,13 +586,13 @@ class FreeplayState extends MusicBeatSubState } }; - exitMovers.set([fp, txtCompletion, fnfHighscoreSpr, txtCompletion, clearBoxSprite], + exitMovers.set([fp, txtCompletion, fnfHighscoreSpr, clearBoxSprite], { x: FlxG.width, speed: 0.3 }); - exitMoversCharSel.set([fp, txtCompletion, fnfHighscoreSpr, txtCompletion, clearBoxSprite], + exitMoversCharSel.set([fp, txtCompletion, fnfHighscoreSpr, clearBoxSprite], { y: -270, speed: 0.8, @@ -1376,7 +1376,7 @@ class FreeplayState extends MusicBeatSubState #if FEATURE_DEBUG_FUNCTIONS if (FlxG.keys.justPressed.P) { - FlxG.switchState(FreeplayState.build( + FlxG.switchState(() -> FreeplayState.build( { { character: currentCharacterId == "pico" ? Constants.DEFAULT_CHARACTER : "pico", @@ -1777,12 +1777,13 @@ class FreeplayState extends MusicBeatSubState FlxG.log.warn('WARN: could not find song with id (${daSong.songId})'); return; } - var targetVariation:String = targetSong.getFirstValidVariation(currentDifficulty) ?? ''; + var targetVariation:String = targetSong.getFirstValidVariation(currentDifficulty, currentCharacter) ?? ''; // TODO: This line of code makes me sad, but you can't really fix it without a breaking migration. var suffixedDifficulty = (targetVariation != Constants.DEFAULT_VARIATION && targetVariation != 'erect') ? '$currentDifficulty-${targetVariation}' : currentDifficulty; var songScore:Null = Save.instance.getSongScore(daSong.songId, suffixedDifficulty); + trace(songScore); intendedScore = songScore?.score ?? 0; intendedCompletion = songScore == null ? 0.0 : ((songScore.tallies.sick + songScore.tallies.good) / songScore.tallies.totalNotes); rememberedDifficulty = suffixedDifficulty; From 1f21e1114b6e58487bedc3261046079da46938a0 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 16 Sep 2024 17:12:11 -0400 Subject: [PATCH 792/870] pub modules --- .gitmodules | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 452c0089b..df142df35 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.assets From a27c4ae24f99d7c1eaa0bf48726dd94a420ec012 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 16 Sep 2024 17:14:45 -0400 Subject: [PATCH 793/870] pub modules art --- .gitmodules | 2 +- art | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index df142df35..be5e0aaa8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,4 +3,4 @@ url = https://github.com/FunkinCrew/funkin.assets [submodule "art"] path = art - url = https://github.com/FunkinCrew/funkin.assets + url = https://github.com/FunkinCrew/funkin.art diff --git a/art b/art index 0dee03f11..bfca2ea98 160000 --- a/art +++ b/art @@ -1 +1 @@ -Subproject commit 0dee03f11afc01c2883da223fa10405f7011dd33 +Subproject commit bfca2ea98d11a0f4dee4a27b9390951fbc5701ea From 367e3e90083f95a13a5b4e76339f2d4eac534203 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 16 Sep 2024 17:18:42 -0400 Subject: [PATCH 794/870] priv modules --- .gitmodules | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index be5e0aaa8..ad8099e60 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 0b531c5b21931bc690ebe9f46d7111800e23704f Mon Sep 17 00:00:00 2001 From: Abnormal <86753001+AbnormalPoof@users.noreply.github.com> Date: Mon, 16 Sep 2024 22:13:16 +0000 Subject: [PATCH 795/870] add getPath --- source/funkin/Assets.hx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/funkin/Assets.hx b/source/funkin/Assets.hx index 5351676d4..05423c572 100644 --- a/source/funkin/Assets.hx +++ b/source/funkin/Assets.hx @@ -11,6 +11,11 @@ class Assets return openfl.utils.Assets.getText(path); } + public static function getPath(path:String):String + { + return openfl.utils.Assets.getPath(path); + } + public static function getMusic(path:String):openfl.media.Sound { return openfl.utils.Assets.getMusic(path); From 80fc0cd526d9dc22fe7c6afd141ee5c6814a3b84 Mon Sep 17 00:00:00 2001 From: lemz Date: Tue, 17 Sep 2024 00:16:27 +0200 Subject: [PATCH 796/870] Update Preferences.hx --- source/funkin/Preferences.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/Preferences.hx b/source/funkin/Preferences.hx index 7a322283d..25bc32163 100644 --- a/source/funkin/Preferences.hx +++ b/source/funkin/Preferences.hx @@ -15,7 +15,7 @@ class Preferences static function get_framerate():Int { - #if web + #if (web || CHEEMS) return 60; #else return Save?.instance?.options?.framerate ?? 60; @@ -24,7 +24,7 @@ class Preferences static function set_framerate(value:Int):Int { - #if web + #if (web || CHEEMS) return 60; #else var save:Save = Save.instance; From f8d0ddef3456b31f729d9110f106b0594baaaf4a Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 16 Sep 2024 18:17:07 -0400 Subject: [PATCH 797/870] Update troubleshooting guide --- docs/troubleshooting.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 3b93bab64..54ba396c4 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -1,4 +1,4 @@ -# Troubleshooting Common Issues +# Troubleshooting Common Compilation Issues - Weird macro error with a very tall call stack: Restart Visual Studio Code - NOTE: This is caused by Polymod somewhere, and seems to only occur when there is another compile error somewhere in the program. There is a bounty up for it. @@ -13,3 +13,11 @@ - `LINK : fatal error LNK1201: error writing to program database ''; check for insufficient disk space, invalid path, or insufficient privilege` - This error occurs if the PDB file located in your `export` folder is in use or exceeds 4 GB. Try deleting the `export` folder and building again from scratch. + +- `error: RPC failed; curl 92 HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR (err 1)` + - This error can happen during cloning as a result of poor network connectivity. A common fix is to run ` git config --global http.postBuffer 4096M` in your terminal. + +- Repository is missing an `assets` folder, or `assets` folder is empty. + - You did not clone the repository correctly! Copy the path to your `funkin` folder and run `cd the\path\you\copied`. Then follow the compilation guide starting from **Step 4**. + +- Other compilation issues may be caused by installing bad library versions. Try deleting the `.haxelib` folder and following the guide starting from **Step 5**. From 224d930ae6e7b41f8c79b19f842a9175374f87c9 Mon Sep 17 00:00:00 2001 From: lemz Date: Tue, 17 Sep 2024 00:17:56 +0200 Subject: [PATCH 798/870] Update PreferencesMenu.hx --- source/funkin/ui/options/PreferencesMenu.hx | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/funkin/ui/options/PreferencesMenu.hx b/source/funkin/ui/options/PreferencesMenu.hx index ca18c45be..adbe1d356 100644 --- a/source/funkin/ui/options/PreferencesMenu.hx +++ b/source/funkin/ui/options/PreferencesMenu.hx @@ -6,8 +6,6 @@ import flixel.FlxSprite; import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup; import funkin.ui.AtlasText.AtlasFont; import funkin.ui.options.OptionsState.Page; -import funkin.ui.options.items.CheckboxPreferenceItem; -import funkin.ui.options.items.NumberPreferenceItem; import funkin.graphics.FunkinCamera; import funkin.ui.TextMenuList.TextMenuItem; import funkin.audio.FunkinSound; From 535ac0e5283ecd83866907920cac52444fcd0e9c Mon Sep 17 00:00:00 2001 From: Kade <26305836+Kade-github@users.noreply.github.com> Date: Mon, 16 Sep 2024 15:25:13 -0700 Subject: [PATCH 799/870] add milliseconds to the playbar in charting state remove laggy redundant traces Revert "remove laggy redundant traces" This reverts commit 204113840473dd5069f5d508d50e15e21104b45a. --- source/funkin/ui/debug/charting/ChartEditorState.hx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 811e08e5d..f778b11f3 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -5139,10 +5139,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState } var songPos:Float = Conductor.instance.songPosition + Conductor.instance.instrumentalOffset; + var songPosMilliseconds:String = Std.string(Math.floor(Math.abs(songPos) % 1000)).lpad('0', 2); var songPosSeconds:String = Std.string(Math.floor((Math.abs(songPos) / 1000) % 60)).lpad('0', 2); var songPosMinutes:String = Std.string(Math.floor((Math.abs(songPos) / 1000) / 60)).lpad('0', 2); if (songPos < 0) songPosMinutes = '-' + songPosMinutes; - var songPosString:String = '${songPosMinutes}:${songPosSeconds}'; + var songPosString:String = '${songPosMinutes}:${songPosSeconds}:${songPosMilliseconds}'; if (playbarSongPos.value != songPosString) playbarSongPos.value = songPosString; From 5a877a14a0d468d0592be6edfaa21b05dc8b3ebf Mon Sep 17 00:00:00 2001 From: Kade <26305836+Kade-github@users.noreply.github.com> Date: Mon, 16 Sep 2024 15:39:56 -0700 Subject: [PATCH 800/870] only show last two digits digit --- source/funkin/ui/debug/charting/ChartEditorState.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index f778b11f3..024de8ec6 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -5139,7 +5139,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState } var songPos:Float = Conductor.instance.songPosition + Conductor.instance.instrumentalOffset; - var songPosMilliseconds:String = Std.string(Math.floor(Math.abs(songPos) % 1000)).lpad('0', 2); + var songPosMilliseconds:String = Std.string(Math.floor(Math.abs(songPos) % 1000)).lpad('0', 2).substr(0, 2); var songPosSeconds:String = Std.string(Math.floor((Math.abs(songPos) / 1000) % 60)).lpad('0', 2); var songPosMinutes:String = Std.string(Math.floor((Math.abs(songPos) / 1000) / 60)).lpad('0', 2); if (songPos < 0) songPosMinutes = '-' + songPosMinutes; From 7d2b946e9c1f885af6ccc9a937ed5af4774d9599 Mon Sep 17 00:00:00 2001 From: Kade <26305836+Kade-github@users.noreply.github.com> Date: Mon, 16 Sep 2024 16:42:53 -0700 Subject: [PATCH 801/870] depreciated screen X/Y to view X/Y --- .../ui/debug/charting/ChartEditorState.hx | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 024de8ec6..c0c2e6309 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -700,7 +700,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState function get_isCursorOverHaxeUI():Bool { - return Screen.instance.hasSolidComponentUnderPoint(FlxG.mouse.screenX, FlxG.mouse.screenY); + return Screen.instance.hasSolidComponentUnderPoint(FlxG.mouse.viewX, FlxG.mouse.viewY); } /** @@ -3830,7 +3830,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState function handleScrollKeybinds():Void { // Don't scroll when the user is interacting with the UI, unless a playbar button (the << >> ones) is pressed. - if ((isHaxeUIFocused || isCursorOverHaxeUI) && playbarButtonPressed == null) return; + if ((isHaxeUIFocused || isHaxeUIDialogOpen) && playbarButtonPressed == null) return; var scrollAmount:Float = 0; // Amount to scroll the grid. var playheadAmount:Float = 0; // Amount to scroll the playhead relative to the grid. @@ -3840,7 +3840,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState // Handle scroll anchor if (scrollAnchorScreenPos != null) { - var currentScreenPos = new FlxPoint(FlxG.mouse.screenX, FlxG.mouse.screenY); + var currentScreenPos = new FlxPoint(FlxG.mouse.viewX, FlxG.mouse.viewX); var distance = currentScreenPos - scrollAnchorScreenPos; var verticalDistance = distance.y; @@ -4121,8 +4121,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState var overlapsRenderedEvents:Bool = FlxG.mouse.overlaps(renderedEvents); // Cursor position relative to the grid. - var cursorX:Float = FlxG.mouse.screenX - gridTiledSprite.x; - var cursorY:Float = FlxG.mouse.screenY - gridTiledSprite.y; + var cursorX:Float = FlxG.mouse.viewX - gridTiledSprite.x; + var cursorY:Float = FlxG.mouse.viewY - gridTiledSprite.y; var overlapsSelectionBorder:Bool = overlapsGrid && ((cursorX % 40) < (GRID_SELECTION_BORDER_WIDTH / 2) @@ -4137,7 +4137,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState { if (scrollAnchorScreenPos == null) { - scrollAnchorScreenPos = new FlxPoint(FlxG.mouse.screenX, FlxG.mouse.screenY); + scrollAnchorScreenPos = new FlxPoint(FlxG.mouse.viewX, FlxG.mouse.viewY); selectionBoxStartPos = null; } else @@ -4159,11 +4159,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState else if (notePreview != null && FlxG.mouse.overlaps(notePreview) && !isCursorOverHaxeUI) { // Clicked note preview - notePreviewScrollAreaStartPos = new FlxPoint(FlxG.mouse.screenX, FlxG.mouse.screenY); + notePreviewScrollAreaStartPos = new FlxPoint(FlxG.mouse.viewX, FlxG.mouse.viewY); } else if (!isCursorOverHaxeUI && (!overlapsGrid || overlapsSelectionBorder)) { - selectionBoxStartPos = new FlxPoint(FlxG.mouse.screenX, FlxG.mouse.screenY); + selectionBoxStartPos = new FlxPoint(FlxG.mouse.viewX, FlxG.mouse.viewY); // Drawing selection box. targetCursorMode = Crosshair; } @@ -4188,7 +4188,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState { // Clicked on the playhead scroll area. // Move the playhead to the cursor position. - this.playheadPositionInPixels = FlxG.mouse.screenY - (GRID_INITIAL_Y_POS); + this.playheadPositionInPixels = FlxG.mouse.viewY - (GRID_INITIAL_Y_POS); moveSongToScrollPosition(); // Cursor should be a grabby hand. @@ -4313,27 +4313,27 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState // Clicking and dragging. // Scroll the screen if the mouse is above or below the grid. - if (FlxG.mouse.screenY < MENU_BAR_HEIGHT) + if (FlxG.mouse.viewY < MENU_BAR_HEIGHT) { // Scroll up. - var diff:Float = MENU_BAR_HEIGHT - FlxG.mouse.screenY; + var diff:Float = MENU_BAR_HEIGHT - FlxG.mouse.viewY; scrollPositionInPixels -= diff * 0.5; // Too fast! moveSongToScrollPosition(); } - else if (FlxG.mouse.screenY > (playbarHeadLayout?.y ?? 0.0)) + else if (FlxG.mouse.viewY > (playbarHeadLayout?.y ?? 0.0)) { // Scroll down. - var diff:Float = FlxG.mouse.screenY - (playbarHeadLayout?.y ?? 0.0); + var diff:Float = FlxG.mouse.viewY - (playbarHeadLayout?.y ?? 0.0); scrollPositionInPixels += diff * 0.5; // Too fast! moveSongToScrollPosition(); } // Render the selection box. var selectionRect:FlxRect = new FlxRect(); - selectionRect.x = Math.min(FlxG.mouse.screenX, selectionBoxStartPos.x); - selectionRect.y = Math.min(FlxG.mouse.screenY, selectionBoxStartPos.y); - selectionRect.width = Math.abs(FlxG.mouse.screenX - selectionBoxStartPos.x); - selectionRect.height = Math.abs(FlxG.mouse.screenY - selectionBoxStartPos.y); + selectionRect.x = Math.min(FlxG.mouse.viewX, selectionBoxStartPos.x); + selectionRect.y = Math.min(FlxG.mouse.viewY, selectionBoxStartPos.y); + selectionRect.width = Math.abs(FlxG.mouse.viewX - selectionBoxStartPos.x); + selectionRect.height = Math.abs(FlxG.mouse.viewY - selectionBoxStartPos.y); setSelectionBoxBounds(selectionRect); targetCursorMode = Crosshair; @@ -4461,8 +4461,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState // Player is clicking and holding on note preview to scrub around. targetCursorMode = Grabbing; - var clickedPosInPixels:Float = FlxMath.remapToRange(FlxG.mouse.screenY, (notePreview?.y ?? 0.0), - (notePreview?.y ?? 0.0) + (notePreview?.height ?? 0.0), 0, songLengthInPixels); + var clickedPosInPixels:Float = FlxMath.remapToRange(FlxG.mouse.viewY, (notePreview?.y ?? 0.0), (notePreview?.y ?? 0.0) + (notePreview?.height ?? 0.0), + 0, songLengthInPixels); scrollPositionInPixels = clickedPosInPixels; moveSongToScrollPosition(); @@ -4520,17 +4520,17 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState targetCursorMode = Grabbing; // Scroll the screen if the mouse is above or below the grid. - if (FlxG.mouse.screenY < MENU_BAR_HEIGHT) + if (FlxG.mouse.viewY < MENU_BAR_HEIGHT) { // Scroll up. - var diff:Float = MENU_BAR_HEIGHT - FlxG.mouse.screenY; + var diff:Float = MENU_BAR_HEIGHT - FlxG.mouse.viewY; scrollPositionInPixels -= diff * 0.5; // Too fast! moveSongToScrollPosition(); } - else if (FlxG.mouse.screenY > (playbarHeadLayout?.y ?? 0.0)) + else if (FlxG.mouse.viewY > (playbarHeadLayout?.y ?? 0.0)) { // Scroll down. - var diff:Float = FlxG.mouse.screenY - (playbarHeadLayout?.y ?? 0.0); + var diff:Float = FlxG.mouse.viewY - (playbarHeadLayout?.y ?? 0.0); scrollPositionInPixels += diff * 0.5; // Too fast! moveSongToScrollPosition(); } @@ -4811,11 +4811,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState // Show the context menu connected to the note. if (useSingleNoteContextMenu) { - this.openNoteContextMenu(FlxG.mouse.screenX, FlxG.mouse.screenY, highlightedNote.noteData); + this.openNoteContextMenu(FlxG.mouse.viewX, FlxG.mouse.viewY, highlightedNote.noteData); } else { - this.openSelectionContextMenu(FlxG.mouse.screenX, FlxG.mouse.screenY); + this.openSelectionContextMenu(FlxG.mouse.viewX, FlxG.mouse.viewY); } } else @@ -4835,11 +4835,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState || (isHighlightedEventSelected && currentEventSelection.length == 1); if (useSingleEventContextMenu) { - this.openEventContextMenu(FlxG.mouse.screenX, FlxG.mouse.screenY, highlightedEvent.eventData); + this.openEventContextMenu(FlxG.mouse.viewX, FlxG.mouse.viewY, highlightedEvent.eventData); } else { - this.openSelectionContextMenu(FlxG.mouse.screenX, FlxG.mouse.screenY); + this.openSelectionContextMenu(FlxG.mouse.viewX, FlxG.mouse.viewY); } } else @@ -4860,11 +4860,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState // Show the context menu connected to the note. if (useSingleNoteContextMenu) { - this.openHoldNoteContextMenu(FlxG.mouse.screenX, FlxG.mouse.screenY, highlightedHoldNote.noteData); + this.openHoldNoteContextMenu(FlxG.mouse.viewX, FlxG.mouse.viewY, highlightedHoldNote.noteData); } else { - this.openSelectionContextMenu(FlxG.mouse.screenX, FlxG.mouse.screenY); + this.openSelectionContextMenu(FlxG.mouse.viewX, FlxG.mouse.viewY); } } else From 9624b57e4447925a3f7764ffae8442585221bde3 Mon Sep 17 00:00:00 2001 From: Kade <26305836+Kade-github@users.noreply.github.com> Date: Mon, 16 Sep 2024 17:23:49 -0700 Subject: [PATCH 802/870] This does fix it now --- source/funkin/ui/debug/charting/ChartEditorState.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index c0c2e6309..922138a10 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -3830,7 +3830,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState function handleScrollKeybinds():Void { // Don't scroll when the user is interacting with the UI, unless a playbar button (the << >> ones) is pressed. - if ((isHaxeUIFocused || isHaxeUIDialogOpen) && playbarButtonPressed == null) return; + if ((isHaxeUIFocused || isCursorOverHaxeUI) && playbarButtonPressed == null) return; var scrollAmount:Float = 0; // Amount to scroll the grid. var playheadAmount:Float = 0; // Amount to scroll the playhead relative to the grid. From d710318830c73d333fdaf347c8250169dc856857 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 16 Sep 2024 21:54:24 -0400 Subject: [PATCH 803/870] Update HaxeUI --- hmm.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hmm.json b/hmm.json index d967a69b3..edc0529aa 100644 --- a/hmm.json +++ b/hmm.json @@ -77,14 +77,14 @@ "name": "haxeui-core", "type": "git", "dir": null, - "ref": "22f7c5a8ffca90d4677cffd6e570f53761709fbc", + "ref": "c9d96b168ea2a19274ad7c766ab1a34b57baa793", "url": "https://github.com/haxeui/haxeui-core" }, { "name": "haxeui-flixel", "type": "git", "dir": null, - "ref": "28bb710d0ae5d94b5108787593052165be43b980", + "ref": "013b9d4e56bfe9a034e028a8d685f0b274cb73c4", "url": "https://github.com/haxeui/haxeui-flixel" }, { From 811caf6b704674ffd0c9dd31ed6be5f8575c1b1f Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 16 Sep 2024 21:54:33 -0400 Subject: [PATCH 804/870] Suppress a spammy log trace --- source/funkin/ui/debug/charting/ChartEditorState.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 922138a10..2e259d3f5 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -5615,7 +5615,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState } else { - trace('Ignoring keybinds for View menu items because we are in live input mode (${currentLiveInputStyle}).'); + // trace('Ignoring keybinds for View menu items because we are in live input mode (${currentLiveInputStyle}).'); } } From b7c3f5ac9f3221efafc65196079a15b6fd435c3e Mon Sep 17 00:00:00 2001 From: Til Tjardes Date: Mon, 16 Sep 2024 20:04:04 -0600 Subject: [PATCH 805/870] Chart Editor Icons are fixed now! --- source/funkin/play/character/CharacterData.hx | 78 ++++++++++++++----- .../ChartEditorCharacterIconSelectorMenu.hx | 2 +- .../toolboxes/ChartEditorMetadataToolbox.hx | 6 +- 3 files changed, 62 insertions(+), 24 deletions(-) diff --git a/source/funkin/play/character/CharacterData.hx b/source/funkin/play/character/CharacterData.hx index bac2c7141..40957818a 100644 --- a/source/funkin/play/character/CharacterData.hx +++ b/source/funkin/play/character/CharacterData.hx @@ -12,6 +12,7 @@ import funkin.util.assets.DataAssets; import funkin.util.VersionUtil; import haxe.Json; import openfl.utils.Assets; +import flixel.graphics.frames.FlxFrame; class CharacterDataParser { @@ -281,41 +282,78 @@ class CharacterDataParser } /** - * TODO: Hardcode this. + * Returns the idle frame of a character. */ - public static function getCharPixelIconAsset(char:String):String + public static function getCharPixelIconAsset(char:String):FlxFrame { - var icon:String = char; + var charPath:String = "freeplay/icons/"; - switch (icon) + // FunkinCrew please dont skin me alive for copying pixelated icon and changing it a tiny bit + switch (char) { - case "bf-christmas" | "bf-car" | "bf-pixel" | "bf-holding-gf": - icon = "bf"; + case "bf-christmas" | "bf-car" | "bf-pixel" | "bf-holding-gf" | "bf-dark": + charPath += "bfpixel"; case "monster-christmas": - icon = "monster"; + charPath += "monsterpixel"; case "mom" | "mom-car": - icon = "mommy"; + charPath += "mommypixel"; case "pico-blazin" | "pico-playable" | "pico-speaker": - icon = "pico"; - case "gf-christmas" | "gf-car" | "gf-pixel" | "gf-tankmen": - icon = "gf"; + charPath += "picopixel"; + case "gf-christmas" | "gf-car" | "gf-pixel" | "gf-tankmen" | "gf-dark": + charPath += "gfpixel"; case "dad": - icon = "daddy"; + charPath += "dadpixel"; case "darnell-blazin": - icon = "darnell"; + charPath += "darnellpixel"; case "senpai-angry": - icon = "senpai"; + charPath += "senpaipixel"; case "spooky-dark": - icon = "spooky"; + charPath += "spookypixel"; case "tankman-atlas": - icon = "tankman"; + charPath += "tankmanpixel"; + case "pico-christmas" | "pico-dark": + charPath += "picopixel"; + default: + charPath += '${char}pixel'; } - var path = Paths.image("freeplay/icons/" + icon + "pixel"); - if (Assets.exists(path)) return path; + if (!Assets.exists(Paths.image(charPath))) + { + trace('[WARN] Character ${char} has no freeplay icon.'); + return null; + } - // TODO: Hardcode some additional behavior or a fallback. - return null; + var isAnimated = Assets.exists(Paths.file('images/$charPath.xml')); + var frame:FlxFrame = null; + + if (isAnimated) + { + var frames = Paths.getSparrowAtlas(charPath); + + var idleFrame:FlxFrame = frames.frames.find(function(frame:FlxFrame):Bool { + return frame.name.startsWith('idle'); + }); + + if (idleFrame == null) + { + trace('[WARN] Character ${char} has no idle in their freeplay icon.'); + return null; + } + + // so, haxe.ui.backend.AssetsImpl uses the parent width and height, which makes the image go crazy when rendered + // so this is a work around so that it uses the actual width and height + var imageGraphic = flixel.graphics.FlxGraphic.fromFrame(idleFrame, false, null, false); + + var imageFrame = flixel.graphics.frames.FlxImageFrame.fromImage(imageGraphic); + frame = imageFrame.frame; + } + else + { + var imageFrame = flixel.graphics.frames.FlxImageFrame.fromImage(Paths.image(charPath)); + frame = imageFrame.frame; + } + + return frame; } /** diff --git a/source/funkin/ui/debug/charting/dialogs/ChartEditorCharacterIconSelectorMenu.hx b/source/funkin/ui/debug/charting/dialogs/ChartEditorCharacterIconSelectorMenu.hx index 1edbb6c00..90d998a02 100644 --- a/source/funkin/ui/debug/charting/dialogs/ChartEditorCharacterIconSelectorMenu.hx +++ b/source/funkin/ui/debug/charting/dialogs/ChartEditorCharacterIconSelectorMenu.hx @@ -95,7 +95,7 @@ class ChartEditorCharacterIconSelectorMenu extends ChartEditorBaseMenu } var LIMIT = 6; - charButton.icon = CharacterDataParser.getCharPixelIconAsset(charId); + charButton.icon = haxe.ui.util.Variant.fromImageData(CharacterDataParser.getCharPixelIconAsset(charId)); charButton.text = charData.name.length > LIMIT ? '${charData.name.substr(0, LIMIT)}.' : '${charData.name}'; charButton.onClick = _ -> { diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx index c97e8142d..f68776cab 100644 --- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx +++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx @@ -221,7 +221,7 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox var charDataOpponent:Null = CharacterDataParser.fetchCharacterData(chartEditorState.currentSongMetadata.playData.characters.opponent); if (charDataOpponent != null) { - buttonCharacterOpponent.icon = CharacterDataParser.getCharPixelIconAsset(chartEditorState.currentSongMetadata.playData.characters.opponent); + buttonCharacterOpponent.icon = haxe.ui.util.Variant.fromImageData(CharacterDataParser.getCharPixelIconAsset(chartEditorState.currentSongMetadata.playData.characters.opponent)); buttonCharacterOpponent.text = charDataOpponent.name.length > LIMIT ? '${charDataOpponent.name.substr(0, LIMIT)}.' : '${charDataOpponent.name}'; } else @@ -233,7 +233,7 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox var charDataGirlfriend:Null = CharacterDataParser.fetchCharacterData(chartEditorState.currentSongMetadata.playData.characters.girlfriend); if (charDataGirlfriend != null) { - buttonCharacterGirlfriend.icon = CharacterDataParser.getCharPixelIconAsset(chartEditorState.currentSongMetadata.playData.characters.girlfriend); + buttonCharacterGirlfriend.icon = haxe.ui.util.Variant.fromImageData(CharacterDataParser.getCharPixelIconAsset(chartEditorState.currentSongMetadata.playData.characters.girlfriend)); buttonCharacterGirlfriend.text = charDataGirlfriend.name.length > LIMIT ? '${charDataGirlfriend.name.substr(0, LIMIT)}.' : '${charDataGirlfriend.name}'; } else @@ -245,7 +245,7 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox var charDataPlayer:Null = CharacterDataParser.fetchCharacterData(chartEditorState.currentSongMetadata.playData.characters.player); if (charDataPlayer != null) { - buttonCharacterPlayer.icon = CharacterDataParser.getCharPixelIconAsset(chartEditorState.currentSongMetadata.playData.characters.player); + buttonCharacterPlayer.icon = haxe.ui.util.Variant.fromImageData(CharacterDataParser.getCharPixelIconAsset(chartEditorState.currentSongMetadata.playData.characters.player)); buttonCharacterPlayer.text = charDataPlayer.name.length > LIMIT ? '${charDataPlayer.name.substr(0, LIMIT)}.' : '${charDataPlayer.name}'; } else From e6525d0129ae9e61ddd7941f50d9cd38904efe6e Mon Sep 17 00:00:00 2001 From: Til Tjardes Date: Mon, 16 Sep 2024 20:44:29 -0600 Subject: [PATCH 806/870] stop being on the kickstarter crack me --- source/funkin/play/character/CharacterData.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/play/character/CharacterData.hx b/source/funkin/play/character/CharacterData.hx index 40957818a..052310a7e 100644 --- a/source/funkin/play/character/CharacterData.hx +++ b/source/funkin/play/character/CharacterData.hx @@ -342,7 +342,7 @@ class CharacterDataParser // so, haxe.ui.backend.AssetsImpl uses the parent width and height, which makes the image go crazy when rendered // so this is a work around so that it uses the actual width and height - var imageGraphic = flixel.graphics.FlxGraphic.fromFrame(idleFrame, false, null, false); + var imageGraphic = flixel.graphics.FlxGraphic.fromFrame(idleFrame); var imageFrame = flixel.graphics.frames.FlxImageFrame.fromImage(imageGraphic); frame = imageFrame.frame; From aae7dcdada565307a22c80a82666a8e4e1837d2e Mon Sep 17 00:00:00 2001 From: AbnormalPoof Date: Mon, 16 Sep 2024 23:35:23 -0500 Subject: [PATCH 807/870] fix crash when opening urls --- source/funkin/ui/mainmenu/MainMenuState.hx | 4 ++-- source/funkin/util/WindowUtil.hx | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index 13d68da6d..588e4cb29 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -123,7 +123,7 @@ class MainMenuState extends MusicBeatState })); }); - #if CAN_OPEN_LINKS + #if FEATURE_OPEN_URL // In order to prevent popup blockers from triggering, // we need to open the link as an immediate result of a keypress event, // so we can't wait for the flicker animation to complete. @@ -234,7 +234,7 @@ class MainMenuState extends MusicBeatState camFollow.setPosition(selected.getGraphicMidpoint().x, selected.getGraphicMidpoint().y); } - #if CAN_OPEN_LINKS + #if FEATURE_OPEN_URL function selectDonate() { WindowUtil.openURL(Constants.URL_ITCH); diff --git a/source/funkin/util/WindowUtil.hx b/source/funkin/util/WindowUtil.hx index 0fe63fe32..aabaa495b 100644 --- a/source/funkin/util/WindowUtil.hx +++ b/source/funkin/util/WindowUtil.hx @@ -22,7 +22,7 @@ class WindowUtil */ public static function openURL(targetUrl:String):Void { - #if CAN_OPEN_LINKS + #if FEATURE_OPEN_URL #if linux Sys.command('/usr/bin/xdg-open $targetUrl &'); #else @@ -40,7 +40,7 @@ class WindowUtil */ public static function openFolder(targetPath:String):Void { - #if CAN_OPEN_LINKS + #if FEATURE_OPEN_URL #if windows Sys.command('explorer', [targetPath.replace('/', '\\')]); #elseif mac @@ -59,7 +59,7 @@ class WindowUtil */ public static function openSelectFile(targetPath:String):Void { - #if CAN_OPEN_LINKS + #if FEATURE_OPEN_URL #if windows Sys.command('explorer', ['/select,' + targetPath.replace('/', '\\')]); #elseif mac From 0706192cbe7863954351009a9825adf2bfbdd8c4 Mon Sep 17 00:00:00 2001 From: dombomb64 <49823019+dombomb64@users.noreply.github.com> Date: Tue, 17 Sep 2024 13:50:59 -0400 Subject: [PATCH 808/870] Fix note scaling with one simple trick! --- source/funkin/play/notes/StrumlineNote.hx | 2 +- source/funkin/play/notes/notestyle/NoteStyle.hx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/play/notes/StrumlineNote.hx b/source/funkin/play/notes/StrumlineNote.hx index d8230aa28..c33c8b578 100644 --- a/source/funkin/play/notes/StrumlineNote.hx +++ b/source/funkin/play/notes/StrumlineNote.hx @@ -85,7 +85,7 @@ class StrumlineNote extends FlxSprite noteStyle.applyStrumlineFrames(this); noteStyle.applyStrumlineAnimations(this, this.direction); - this.setGraphicSize(Std.int(Strumline.STRUMLINE_SIZE * noteStyle.getStrumlineScale())); + this.scale.set(noteStyle.getStrumlineScale()); this.updateHitbox(); noteStyle.applyStrumlineOffsets(this); diff --git a/source/funkin/play/notes/notestyle/NoteStyle.hx b/source/funkin/play/notes/notestyle/NoteStyle.hx index ee07703f1..9079fee64 100644 --- a/source/funkin/play/notes/notestyle/NoteStyle.hx +++ b/source/funkin/play/notes/notestyle/NoteStyle.hx @@ -93,7 +93,7 @@ class NoteStyle implements IRegistryEntry buildNoteAnimations(target); // Set the scale. - target.setGraphicSize(Strumline.STRUMLINE_SIZE * getNoteScale()); + target.scale.set(getNoteScale()); target.updateHitbox(); } From 6e33cac9ec0636333156a308b65438c311bc92be Mon Sep 17 00:00:00 2001 From: dombomb64 <49823019+dombomb64@users.noreply.github.com> Date: Tue, 17 Sep 2024 16:47:16 -0400 Subject: [PATCH 809/870] ...Okay it wasn't that simple --- source/funkin/play/notes/StrumlineNote.hx | 3 ++- source/funkin/play/notes/SustainTrail.hx | 5 +++-- .../funkin/play/notes/notestyle/NoteStyle.hx | 19 +++++++++++++++++-- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/source/funkin/play/notes/StrumlineNote.hx b/source/funkin/play/notes/StrumlineNote.hx index c33c8b578..16df9f502 100644 --- a/source/funkin/play/notes/StrumlineNote.hx +++ b/source/funkin/play/notes/StrumlineNote.hx @@ -85,7 +85,8 @@ class StrumlineNote extends FlxSprite noteStyle.applyStrumlineFrames(this); noteStyle.applyStrumlineAnimations(this, this.direction); - this.scale.set(noteStyle.getStrumlineScale()); + var scale = noteStyle.getStrumlineScale(); + this.scale.set(scale, scale); this.updateHitbox(); noteStyle.applyStrumlineOffsets(this); diff --git a/source/funkin/play/notes/SustainTrail.hx b/source/funkin/play/notes/SustainTrail.hx index 90b36b009..a9af468b9 100644 --- a/source/funkin/play/notes/SustainTrail.hx +++ b/source/funkin/play/notes/SustainTrail.hx @@ -87,6 +87,7 @@ class SustainTrail extends FlxSprite public var bottomClip:Float = 0.9; public var isPixel:Bool; + public var noteStyleOffsets:Array; var graphicWidth:Float = 0; var graphicHeight:Float = 0; @@ -107,6 +108,7 @@ class SustainTrail extends FlxSprite this.noteDirection = noteDirection; setupHoldNoteGraphic(noteStyle); + noteStyleOffsets = noteStyle.getHoldNoteOffsets(); indices = new DrawData(12, true, TRIANGLE_VERTEX_INDICES); @@ -137,7 +139,6 @@ class SustainTrail extends FlxSprite zoom = 1.0; zoom *= noteStyle.fetchHoldNoteScale(); - zoom *= 0.7; // CALCULATE SIZE graphicWidth = graphic.width / 8 * zoom; // amount of notes * 2 @@ -202,7 +203,7 @@ class SustainTrail extends FlxSprite { width = graphicWidth; height = graphicHeight; - offset.set(0, 0); + offset.set(noteStyleOffsets[0], noteStyleOffsets[1]); origin.set(width * 0.5, height * 0.5); } diff --git a/source/funkin/play/notes/notestyle/NoteStyle.hx b/source/funkin/play/notes/notestyle/NoteStyle.hx index 9079fee64..a5ff19cba 100644 --- a/source/funkin/play/notes/notestyle/NoteStyle.hx +++ b/source/funkin/play/notes/notestyle/NoteStyle.hx @@ -93,7 +93,8 @@ class NoteStyle implements IRegistryEntry buildNoteAnimations(target); // Set the scale. - target.scale.set(getNoteScale()); + var scale = getNoteScale(); + target.scale.set(scale, scale); target.updateHitbox(); } @@ -224,6 +225,13 @@ class NoteStyle implements IRegistryEntry return data?.scale ?? 1.0; } + public function getHoldNoteOffsets():Array + { + var data = _data?.assets?.holdNote; + if (data == null && fallback != null) return fallback.getHoldNoteOffsets(); + return data?.offsets ?? [0.0, 0.0]; + } + public function applyStrumlineFrames(target:StrumlineNote):Void { // TODO: Add support for multi-Sparrow. @@ -304,9 +312,16 @@ class NoteStyle implements IRegistryEntry return thx.Arrays.filterNull(result); } + public function getStrumlineOffsets():Array + { + var data = _data?.assets?.noteStrumline; + if (data == null && fallback != null) return fallback.getStrumlineOffsets(); + return data?.offsets ?? [0.0, 0.0]; + } + public function applyStrumlineOffsets(target:StrumlineNote):Void { - var offsets = _data?.assets?.noteStrumline?.offsets ?? [0.0, 0.0]; + var offsets = getStrumlineOffsets(); target.x += offsets[0]; target.y += offsets[1]; } From f2b3f47e73d4f29590fe1f4fd401a1c81cb9cb50 Mon Sep 17 00:00:00 2001 From: Michael <15317421+ActualMandM@users.noreply.github.com> Date: Tue, 17 Sep 2024 15:46:47 -0700 Subject: [PATCH 810/870] Disable input in CharSelect until stayFunky plays --- source/funkin/ui/charSelect/CharSelectSubState.hx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index 3109dc8f1..c2dd18fd8 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -71,6 +71,7 @@ class CharSelectSubState extends MusicBeatSubState var availableChars:Map = new Map(); var pressedSelect:Bool = false; var selectTimer:FlxTimer = new FlxTimer(); + var allowInput:Bool = false; var selectSound:FunkinSound; var unlockSound:FunkinSound; @@ -430,6 +431,8 @@ class CharSelectSubState extends MusicBeatSubState overrideExisting: true, restartTrack: true, onLoad: function() { + allowInput = true; + @:privateAccess gfChill.analyzer = new SpectralAnalyzer(FlxG.sound.music._channel.__audioSource, 7, 0.1); #if desktop @@ -573,6 +576,8 @@ class CharSelectSubState extends MusicBeatSubState overrideExisting: true, restartTrack: true, onLoad: function() { + allowInput = true; + @:privateAccess gfChill.analyzer = new SpectralAnalyzer(FlxG.sound.music._channel.__audioSource, 7, 0.1); #if desktop @@ -642,6 +647,7 @@ class CharSelectSubState extends MusicBeatSubState function goToFreeplay():Void { + allowInput = false; autoFollow = false; FlxTween.tween(cursor, {alpha: 0}, 0.8, {ease: FlxEase.expoOut}); @@ -695,7 +701,7 @@ class CharSelectSubState extends MusicBeatSubState syncAudio(elapsed); - if (!pressedSelect) + if (allowInput && !pressedSelect) { if (controls.UI_UP) holdTmrUp += elapsed; if (controls.UI_UP_R) @@ -789,7 +795,7 @@ class CharSelectSubState extends MusicBeatSubState gfChill.visible = true; curChar = availableChars.get(getCurrentSelected()); - if (!pressedSelect && controls.ACCEPT) + if (allowInput && !pressedSelect && controls.ACCEPT) { cursorConfirmed.visible = true; cursorConfirmed.x = cursor.x - 2; @@ -817,7 +823,7 @@ class CharSelectSubState extends MusicBeatSubState }); } - if (pressedSelect && controls.BACK) + if (allowInput && pressedSelect && controls.BACK) { cursorConfirmed.visible = false; grpCursors.visible = true; @@ -847,7 +853,7 @@ class CharSelectSubState extends MusicBeatSubState gfChill.visible = false; - if (controls.ACCEPT) + if (allowInput && controls.ACCEPT) { cursorDenied.visible = true; cursorDenied.x = cursor.x - 2; From ea9dab4b73cec21ffa5585b4915d386e6497834c Mon Sep 17 00:00:00 2001 From: Lethrial Date: Wed, 18 Sep 2024 00:25:20 +0100 Subject: [PATCH 811/870] Update Main.hx --- source/Main.hx | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/Main.hx b/source/Main.hx index 724b118f8..56634c86b 100644 --- a/source/Main.hx +++ b/source/Main.hx @@ -123,8 +123,6 @@ class Main extends Sprite game.debugger.interaction.addTool(new funkin.util.TrackerToolButtonUtil()); #end - addChild(fpsCounter); - #if hxcpp_debug_server trace('hxcpp_debug_server is enabled! You can now connect to the game with a debugger.'); #else From de07497ae3967b981cc026d26997d717443dc280 Mon Sep 17 00:00:00 2001 From: Kade <26305836+Kade-github@users.noreply.github.com> Date: Tue, 17 Sep 2024 17:29:12 -0700 Subject: [PATCH 812/870] Make addCharacter actually set the characters type --- source/funkin/play/stage/Stage.hx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/funkin/play/stage/Stage.hx b/source/funkin/play/stage/Stage.hx index c42e41cad..ad768769c 100644 --- a/source/funkin/play/stage/Stage.hx +++ b/source/funkin/play/stage/Stage.hx @@ -464,6 +464,9 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements #end } + // Set the characters type + character.characterType = charType; + // Add the character to the scene. this.add(character); From b70983a0e4c17f4be05d25449c5ddca04fb901a5 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 17 Sep 2024 20:50:09 -0400 Subject: [PATCH 813/870] Build arguments for Tracy --- .vscode/settings.json | 5 +++++ project.hxp | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/.vscode/settings.json b/.vscode/settings.json index 227cb94ec..af5986fbf 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -96,6 +96,11 @@ "target": "windows", "args": ["-debug", "-DFEATURE_DEBUG_FUNCTIONS"] }, + { + "label": "Windows / Debug (Tracy)", + "target": "windows", + "args": ["-debug", "-DFEATURE_DEBUG_TRACY", "-DFEATURE_DEBUG_FUNCTIONS"] + }, { "label": "Linux / Debug", "target": "linux", diff --git a/project.hxp b/project.hxp index 1193a9cd4..934cc1d2d 100644 --- a/project.hxp +++ b/project.hxp @@ -149,6 +149,14 @@ class Project extends HXProject { */ static final FEATURE_DEBUG_FUNCTIONS:FeatureFlag = "FEATURE_DEBUG_FUNCTIONS"; + /** + * `-DFEATURE_DEBUG_TRACY` + * If this flag is enabled, the game will have the necessary hooks for the Tracy profiler. + * Only enable this if you're using the correct fork of Haxe to support this. + * @see https://github.com/HaxeFoundation/hxcpp/pull/1153 + */ + static final FEATURE_DEBUG_TRACY:FeatureFlag = "FEATURE_DEBUG_TRACY"; + /** * `-DFEATURE_DISCORD_RPC` * If this flag is enabled, the game will enable the Discord Remote Procedure Call library. @@ -516,6 +524,16 @@ class Project extends HXProject { // Cleaner looking compiler errors. setHaxedef("message.reporting", "pretty"); + + if (FEATURE_DEBUG_TRACY.isEnabled(this)) { + setHaxedef("HXCPP_TELEMETRY"); // Enable telemetry + setHaxedef("HXCPP_TRACY"); // Enable Tracy telemetry + setHaxedef("HXCPP_TRACY_MEMORY"); // Track memory allocations + setHaxedef("HXCPP_TRACY_ON_DEMAND"); // Only collect telemetry when Tracy is open and reachable + // setHaxedef("HXCPP_TRACY_INCLUDE_CALLSTACKS"); // Inspect callstacks per zone, inflating telemetry data + + setHaxedef("absolute-paths"); // Fix source locations so Tracy can see them + } } /** From 61d23b9985d629ef40b2630898aed006d5edfb41 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 17 Sep 2024 20:56:54 -0400 Subject: [PATCH 814/870] Use branch of HXCPP --- hmm.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hmm.json b/hmm.json index d967a69b3..4c473ed37 100644 --- a/hmm.json +++ b/hmm.json @@ -105,8 +105,8 @@ "name": "hxcpp", "type": "git", "dir": null, - "ref": "904ea40643b050a5a154c5e4c33a83fd2aec18b1", - "url": "https://github.com/HaxeFoundation/hxcpp" + "ref": "c6bac3d6c7d683f25104296b2f4c50f8c90b8349", + "url": "https://github.com/cortex-engine/hxcpp" }, { "name": "hxcpp-debug-server", From 119148acf0b25de8af2f030c56d99cdfefcb4934 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 18 Sep 2024 02:11:31 -0400 Subject: [PATCH 815/870] Define for enabling/disabling log trace --- project.hxp | 8 ++++++++ source/funkin/util/logging/AnsiTrace.hx | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/project.hxp b/project.hxp index 934cc1d2d..73a12538a 100644 --- a/project.hxp +++ b/project.hxp @@ -157,6 +157,13 @@ class Project extends HXProject { */ static final FEATURE_DEBUG_TRACY:FeatureFlag = "FEATURE_DEBUG_TRACY"; + /** + * `-DFEATURE_LOG_TRACE` + * If this flag is enabled, the game will print debug traces to the console. + * Disable to improve performance a bunch. + */ + static final FEATURE_LOG_TRACE:FeatureFlag = "FEATURE_LOG_TRACE"; + /** * `-DFEATURE_DISCORD_RPC` * If this flag is enabled, the game will enable the Discord Remote Procedure Call library. @@ -461,6 +468,7 @@ class Project extends HXProject { // Should be true on debug builds or if GITHUB_BUILD is enabled. FEATURE_DEBUG_FUNCTIONS.apply(this, isDebug() || GITHUB_BUILD.isEnabled(this)); + FEATURE_LOG_TRACE.apply(this, isDebug()); // Should default to true on workspace builds and false on release builds. REDIRECT_ASSETS_FOLDER.apply(this, isDebug() && isDesktop()); diff --git a/source/funkin/util/logging/AnsiTrace.hx b/source/funkin/util/logging/AnsiTrace.hx index 322a66820..18c6d1d92 100644 --- a/source/funkin/util/logging/AnsiTrace.hx +++ b/source/funkin/util/logging/AnsiTrace.hx @@ -6,7 +6,7 @@ class AnsiTrace // but adds nice cute ANSI things public static function trace(v:Dynamic, ?info:haxe.PosInfos) { - #if TREMOVE + #if NO_FEATURE_LOG_TRACE return; #end var str = formatOutput(v, info); From f7fb640e52ff8820579ae90d2fef6b001f54e6a3 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 18 Sep 2024 02:29:11 -0400 Subject: [PATCH 816/870] Copy TracyProfiler from pull request --- source/cpp/vm/tracy/TracyProfiler.hx | 102 +++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 source/cpp/vm/tracy/TracyProfiler.hx diff --git a/source/cpp/vm/tracy/TracyProfiler.hx b/source/cpp/vm/tracy/TracyProfiler.hx new file mode 100644 index 000000000..1bedd521d --- /dev/null +++ b/source/cpp/vm/tracy/TracyProfiler.hx @@ -0,0 +1,102 @@ +/* + * Pulled from Tracey profiler PR + * @see https://github.com/HaxeFoundation/haxe/pull/11772 + */ + +package cpp.vm.tracy; + +#if (!HXCPP_TRACY) +#error "This class cannot be used without -D HXCPP_TRACY" +#end +enum abstract PlotFormatType(cpp.UInt8) from cpp.UInt8 to cpp.UInt8 +{ + var Number = 0; + var Memory = 1; + var Percentage = 2; +} + +@:include('hx/TelemetryTracy.h') +extern class Native_TracyProfiler +{ + /** + Mark a frame. Call this at the end of each frame loop. + **/ + @:native('::__hxcpp_tracy_framemark') + public static function frameMark():Void; + + /** + Print a message into Tracy's log. + **/ + @:native('::__hxcpp_tracy_message') + public static function message(_msg:String, ?_color:Int = 0x000000):Void; + + /** + Tracy can collect additional information about the profiled application, + which will be available in the trace description. + This can include data such as the source repository revision, + the application’s environment (dev/prod), etc. + **/ + @:native('::__hxcpp_tracy_message_app_info') + public static function messageAppInfo(_info:String):Void; + + /** + Plot a named value to tracy. This will generate a graph in the profiler for you. + **/ + @:native('::__hxcpp_tracy_plot') + public static function plot(_name:String, _val:cpp.Float32):Void; + + /** + Configure how values are plotted and displayed. + **/ + @:native('::__hxcpp_tracy_plot_config') + public static function plotConfig(_name:String, _format:PlotFormatType, ?_step:Bool = false, ?_fill:Bool = false, ?_color:Int = 0x000000):Void; + + /** + Set a name for the current thread this function is called in. Supply an optional groupHint so threads become grouped in Tracy's UI. + **/ + @:native('::__hxcpp_tracy_set_thread_name_and_group') + public static function setThreadName(_name:String, ?_groupHint:Int = 1):Void; + + /** + Create a custom named scoped zone in your code. + **/ + @:native('HXCPP_TRACY_ZONE') + public static function zoneScoped(_name:String):Void; +} + +#if (scriptable || cppia) +class Cppia_TracyProfiler +{ + @:inheritDoc(cpp.vm.tracy.Native_TracyProfiler.frameMark) + public static function frameMark() + Native_TracyProfiler.frameMark(); + + @:inheritDoc(cpp.vm.tracy.Native_TracyProfiler.message) + public static function message(_msg:String, ?_color:Int = 0x000000) + Native_TracyProfiler.message(_msg, _color); + + @:inheritDoc(cpp.vm.tracy.Native_TracyProfiler.messageAppInfo) + public static function messageAppInfo(_info:String) + Native_TracyProfiler.messageAppInfo(_info); + + @:inheritDoc(cpp.vm.tracy.Native_TracyProfiler.plot) + public static function plot(_name:String, _val:Float) + Native_TracyProfiler.plot(_name, _val); + + @:inheritDoc(cpp.vm.tracy.Native_TracyProfiler.plotConfig) + public static function plotConfig(_name:String, _format:PlotFormatType, ?_step:Bool = false, ?_fill:Bool = false, ?_color:Int = 0x000000) + Native_TracyProfiler.plotConfig(_name, _format, _step, _fill, _color); + + @:inheritDoc(cpp.vm.tracy.Native_TracyProfiler.setThreadName) + public static function setThreadName(_name:String, ?_groupHint:Int = 1) + Native_TracyProfiler.setThreadName(_name, _groupHint); + + @:inheritDoc(cpp.vm.tracy.Native_TracyProfiler.zoneScoped) + public static function zoneScoped(_name:String) + Native_TracyProfiler.zoneScoped(_name); +} + +typedef TracyProfiler = Cppia_TracyProfiler; +#else +typedef TracyProfiler = Native_TracyProfiler; +#end From 2a5269c2a755068d0b1ad94de7030d7988671942 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 18 Sep 2024 02:30:48 -0400 Subject: [PATCH 817/870] Disable on demand telemetry --- project.hxp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project.hxp b/project.hxp index 73a12538a..74402016f 100644 --- a/project.hxp +++ b/project.hxp @@ -537,7 +537,7 @@ class Project extends HXProject { setHaxedef("HXCPP_TELEMETRY"); // Enable telemetry setHaxedef("HXCPP_TRACY"); // Enable Tracy telemetry setHaxedef("HXCPP_TRACY_MEMORY"); // Track memory allocations - setHaxedef("HXCPP_TRACY_ON_DEMAND"); // Only collect telemetry when Tracy is open and reachable + // setHaxedef("HXCPP_TRACY_ON_DEMAND"); // Only collect telemetry when Tracy is open and reachable // setHaxedef("HXCPP_TRACY_INCLUDE_CALLSTACKS"); // Inspect callstacks per zone, inflating telemetry data setHaxedef("absolute-paths"); // Fix source locations so Tracy can see them From 19e6029fb27ef0c52aeb632d8c0ce941cd133623 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 18 Sep 2024 03:13:10 -0400 Subject: [PATCH 818/870] Fix some compilation errors --- source/funkin/play/PlayState.hx | 1 - source/funkin/play/components/PopUpStuff.hx | 9 --------- source/funkin/ui/debug/anim/DebugBoundingState.hx | 2 +- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index a25d3b231..1c82eb6b1 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -3046,7 +3046,6 @@ class PlayState extends MusicBeatSubState GameOverSubState.reset(); PauseSubState.reset(); Countdown.reset(); - PopUpStuff.reset(); // Clear the static reference to this state. instance = null; diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx index e5e9b4681..a02291e4e 100644 --- a/source/funkin/play/components/PopUpStuff.hx +++ b/source/funkin/play/components/PopUpStuff.hx @@ -125,13 +125,4 @@ class PopUpStuff extends FlxTypedGroup daLoop++; } } - - /** - * Reset the popup configuration to the default. - */ - public static function reset() - { - noteStyle = NoteStyleRegistry.instance.fetchDefault(); - isPixel = false; - } } diff --git a/source/funkin/ui/debug/anim/DebugBoundingState.hx b/source/funkin/ui/debug/anim/DebugBoundingState.hx index 19391f8d9..d2a27999f 100644 --- a/source/funkin/ui/debug/anim/DebugBoundingState.hx +++ b/source/funkin/ui/debug/anim/DebugBoundingState.hx @@ -77,7 +77,7 @@ class DebugBoundingState extends FlxState { // get the screen position, according to the HUD camera, temp default to FlxG.camera juuust in case? var hudMousePos:FlxPoint = FlxG.mouse.getScreenPosition(hudCam ?? FlxG.camera); - return Screen.instance.hasSolidComponentUnderPoint(hudMousePos.x, hudMousePos.y) || FlxG.mouse.overlaps(animDropDownMenu, hudCam); + return Screen.instance.hasSolidComponentUnderPoint(hudMousePos.x, hudMousePos.y); } override function create() From 7b7d5deed5e56613b5ba10f2e2ad7dfe393a1a42 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 18 Sep 2024 03:13:21 -0400 Subject: [PATCH 819/870] Tweaks to framerate preference --- source/funkin/Preferences.hx | 4 ++-- source/funkin/ui/options/PreferencesMenu.hx | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/source/funkin/Preferences.hx b/source/funkin/Preferences.hx index 1eac9f47f..648880ad4 100644 --- a/source/funkin/Preferences.hx +++ b/source/funkin/Preferences.hx @@ -15,7 +15,7 @@ class Preferences static function get_framerate():Int { - #if (web || CHEEMS) + #if web return 60; #else return Save?.instance?.options?.framerate ?? 60; @@ -24,7 +24,7 @@ class Preferences static function set_framerate(value:Int):Int { - #if (web || CHEEMS) + #if web return 60; #else var save:Save = Save.instance; diff --git a/source/funkin/ui/options/PreferencesMenu.hx b/source/funkin/ui/options/PreferencesMenu.hx index adbe1d356..fb4980762 100644 --- a/source/funkin/ui/options/PreferencesMenu.hx +++ b/source/funkin/ui/options/PreferencesMenu.hx @@ -54,11 +54,6 @@ class PreferencesMenu extends Page */ function createPrefItems():Void { - #if !web - createPrefItemNumber('FPS', 'The framerate that the game is running on', function(value:Float) { - Preferences.framerate = Std.int(value); - }, null, Preferences.framerate, 60, 360, 1, 0); - #end createPrefItemCheckbox('Naughtyness', 'Toggle displaying raunchy content', function(value:Bool):Void { Preferences.naughtyness = value; }, Preferences.naughtyness); @@ -82,6 +77,10 @@ class PreferencesMenu extends Page createPrefItemCheckbox('Unlocked Framerate', 'Enable to unlock the framerate', function(value:Bool):Void { Preferences.unlockedFramerate = value; }, Preferences.unlockedFramerate); + #else + createPrefItemNumber('FPS', 'The maximum framerate that the game targets', function(value:Float) { + Preferences.framerate = Std.int(value); + }, null, Preferences.framerate, 30, 300, 5, 0); #end } From d30fe61ca07d9565a2142d5a044f2cd4558e7aa6 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 18 Sep 2024 05:03:04 -0400 Subject: [PATCH 820/870] Add a bunch of other functions to funkin.Assets, and add documentation --- source/funkin/Assets.hx | 150 +++++++++++++++++++++++++++++++++++----- 1 file changed, 134 insertions(+), 16 deletions(-) diff --git a/source/funkin/Assets.hx b/source/funkin/Assets.hx index 05423c572..967e4b0ca 100644 --- a/source/funkin/Assets.hx +++ b/source/funkin/Assets.hx @@ -1,43 +1,161 @@ package funkin; +import openfl.utils.Future; + /** * A wrapper around `openfl.utils.Assets` which disallows access to the harmful functions. * Later we'll add Funkin-specific caching to this. */ class Assets { - public static function getText(path:String):String - { - return openfl.utils.Assets.getText(path); - } - + /** + * Get the file system path for an asset + * @param path The asset path to load from, relative to the assets folder + * @return The path to the asset on the file system + */ public static function getPath(path:String):String { return openfl.utils.Assets.getPath(path); } - public static function getMusic(path:String):openfl.media.Sound - { - return openfl.utils.Assets.getMusic(path); - } - - public static function getBitmapData(path:String):openfl.display.BitmapData - { - return openfl.utils.Assets.getBitmapData(path); - } - + /** + * Load bytes from an asset + * May cause stutters or throw an error if the asset is not cached + * @param path The asset path to load from + * @return The byte contents of the file + */ public static function getBytes(path:String):haxe.io.Bytes { return openfl.utils.Assets.getBytes(path); } + /** + * Load bytes from an asset asynchronously + * @param path The asset path to load from + * @return A future which promises to return the byte contents of the file + */ + public static function loadBytes(path:String):Future + { + return openfl.utils.Assets.loadBytes(path); + } + + /** + * Load text from an asset. + * May cause stutters or throw an error if the asset is not cached + * @param path The asset path to load from + * @return The text contents of the file + */ + public static function getText(path:String):String + { + return openfl.utils.Assets.getText(path); + } + + /** + * Load text from an asset asynchronously + * @param path The asset path to load from + * @return A future which promises to return the text contents of the file + */ + public static function loadText(path:String):Future + { + return openfl.utils.Assets.loadText(path); + } + + /** + * Load a Sound file from an asset + * May cause stutters or throw an error if the asset is not cached + * @param path The asset path to load from + * @return The loaded sound + */ + public static function getSound(path:String):openfl.media.Sound + { + return openfl.utils.Assets.getSound(path); + } + + /** + * Load a Sound file from an asset asynchronously + * @param path The asset path to load from + * @return A future which promises to return the loaded sound + */ + public static function loadSound(path:String):Future + { + return openfl.utils.Assets.loadSound(path); + } + + /** + * Load a Sound file from an asset, with optimizations specific to long-duration music + * May cause stutters or throw an error if the asset is not cached + * @param path The asset path to load from + * @return The loaded sound + */ + public static function getMusic(path:String):openfl.media.Sound + { + return openfl.utils.Assets.getMusic(path); + } + + /** + * Load a Sound file from an asset asynchronously, with optimizations specific to long-duration music + * @param path The asset path to load from + * @return A future which promises to return the loaded sound + */ + public static function loadMusic(path:String):Future + { + return openfl.utils.Assets.loadMusic(path); + } + + /** + * Load a Bitmap from an asset + * May cause stutters or throw an error if the asset is not cached + * @param path The asset path to load from + * @return The loaded Bitmap image + */ + public static function getBitmapData(path:String):openfl.display.BitmapData + { + return openfl.utils.Assets.getBitmapData(path); + } + + /** + * Load a Bitmap from an asset asynchronously + * @param path The asset path to load from + * @return The future which promises to return the loaded Bitmap image + */ + public static function loadBitmapData(path:String):Future + { + return openfl.utils.Assets.loadBitmapData(path); + } + + /** + * Determines whether the given asset of the given type exists. + * @param path The asset path to check + * @param type The asset type to check + * @return Whether the asset exists + */ public static function exists(path:String, ?type:openfl.utils.AssetType):Bool { return openfl.utils.Assets.exists(path, type); } - public static function list(type:openfl.utils.AssetType):Array + /** + * Retrieve a list of all assets of the given type + * @param type The asset type to check + * @return A list of asset paths + */ + public static function list(?type:openfl.utils.AssetType):Array { return openfl.utils.Assets.list(type); } + + public static function hasLibrary(name:String):Bool + { + return openfl.utils.Assets.hasLibrary(name); + } + + public static function getLibrary(name:String):lime.utils.AssetLibrary + { + return openfl.utils.Assets.getLibrary(name); + } + + public static function loadLibrary(name:String):Future + { + return openfl.utils.Assets.loadLibrary(name); + } } From b6b2248aa389143b855eab86c19c656f9edc4376 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 18 Sep 2024 05:04:10 -0400 Subject: [PATCH 821/870] Make funkin.Assets and funkin.Paths default imports for all scripts --- assets | 2 +- source/funkin/modding/PolymodHandler.hx | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/assets b/assets index bc7009b42..16c1d3047 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit bc7009b4242691faa5c4552f7ca8a2f28e8cb1d2 +Subproject commit 16c1d30478875a5acbe92e4ec7d11234d1028286 diff --git a/source/funkin/modding/PolymodHandler.hx b/source/funkin/modding/PolymodHandler.hx index 75c69e506..258491552 100644 --- a/source/funkin/modding/PolymodHandler.hx +++ b/source/funkin/modding/PolymodHandler.hx @@ -228,6 +228,8 @@ class PolymodHandler static function buildImports():Void { // Add default imports for common classes. + Polymod.addDefaultImport(funkin.Assets); + Polymod.addDefaultImport(funkin.Paths); // Add import aliases for certain classes. // NOTE: Scripted classes are automatically aliased to their parent class. From 1beb21e57a2c0ac6d1a04df8fa699b25f1aee504 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 18 Sep 2024 05:04:32 -0400 Subject: [PATCH 822/870] Replace all instances of openfl/lime Assets with funkin.Assets --- source/funkin/Paths.hx | 5 ++--- .../funkin/graphics/adobeanimate/FlxAtlasSprite.hx | 1 - .../funkin/graphics/shaders/AdjustColorShader.hx | 2 -- source/funkin/graphics/shaders/BlendModesShader.hx | 2 -- .../funkin/graphics/shaders/GaussianBlurShader.hx | 2 -- source/funkin/graphics/shaders/Grayscale.hx | 2 -- source/funkin/graphics/shaders/HSVShader.hx | 2 -- source/funkin/graphics/shaders/MosaicEffect.hx | 2 -- .../graphics/shaders/RuntimeCustomBlendShader.hx | 1 - .../funkin/graphics/shaders/RuntimeRainShader.hx | 1 - source/funkin/import.hx | 1 + source/funkin/input/Cursor.hx | 1 - source/funkin/play/Countdown.hx | 1 - source/funkin/play/GameOverSubState.hx | 1 - source/funkin/play/character/CharacterData.hx | 1 - source/funkin/play/components/HealthIcon.hx | 1 - source/funkin/play/components/PopUpStuff.hx | 1 - source/funkin/play/song/Song.hx | 1 - source/funkin/ui/debug/anim/DebugBoundingState.hx | 1 - .../charting/components/ChartEditorEventSprite.hx | 1 - .../charting/handlers/ChartEditorAudioHandler.hx | 1 - source/funkin/ui/freeplay/AlbumRoll.hx | 1 - source/funkin/ui/freeplay/FreeplayState.hx | 3 +-- source/funkin/ui/freeplay/backcards/BackingCard.hx | 1 - .../funkin/ui/freeplay/backcards/BoyfriendCard.hx | 14 +++++++------- .../ui/freeplay/backcards/NewCharacterCard.hx | 1 - source/funkin/ui/freeplay/backcards/PicoCard.hx | 14 +++++++------- source/funkin/ui/options/FunkinSoundTray.hx | 1 - source/funkin/ui/story/StoryMenuState.hx | 1 - source/funkin/ui/transition/LoadingState.hx | 9 ++++----- source/funkin/ui/transition/StickerSubState.hx | 5 ++--- 31 files changed, 24 insertions(+), 57 deletions(-) diff --git a/source/funkin/Paths.hx b/source/funkin/Paths.hx index 285af7ca2..ae77ac2da 100644 --- a/source/funkin/Paths.hx +++ b/source/funkin/Paths.hx @@ -2,7 +2,6 @@ package funkin; import flixel.graphics.frames.FlxAtlasFrames; import openfl.utils.AssetType; -import openfl.utils.Assets as OpenFlAssets; /** * A core class which handles determining asset paths. @@ -44,11 +43,11 @@ class Paths if (currentLevel != null) { var levelPath:String = getLibraryPathForce(file, currentLevel); - if (OpenFlAssets.exists(levelPath, type)) return levelPath; + if (Assets.exists(levelPath, type)) return levelPath; } var levelPath:String = getLibraryPathForce(file, 'shared'); - if (OpenFlAssets.exists(levelPath, type)) return levelPath; + if (Assets.exists(levelPath, type)) return levelPath; return getPreloadPath(file); } diff --git a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx index 952fa8b71..8a51e8c8b 100644 --- a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx +++ b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx @@ -7,7 +7,6 @@ import flxanimate.frames.FlxAnimateFrames; import flixel.graphics.frames.FlxFrame; import flixel.system.FlxAssets.FlxGraphicAsset; import openfl.display.BitmapData; -import openfl.utils.Assets; import flixel.math.FlxPoint; import flxanimate.animate.FlxKeyFrame; diff --git a/source/funkin/graphics/shaders/AdjustColorShader.hx b/source/funkin/graphics/shaders/AdjustColorShader.hx index 2b0970eeb..a6efc3e65 100644 --- a/source/funkin/graphics/shaders/AdjustColorShader.hx +++ b/source/funkin/graphics/shaders/AdjustColorShader.hx @@ -1,8 +1,6 @@ package funkin.graphics.shaders; import flixel.addons.display.FlxRuntimeShader; -import funkin.Paths; -import openfl.utils.Assets; class AdjustColorShader extends FlxRuntimeShader { diff --git a/source/funkin/graphics/shaders/BlendModesShader.hx b/source/funkin/graphics/shaders/BlendModesShader.hx index b7a405dd1..e6ae45dd7 100644 --- a/source/funkin/graphics/shaders/BlendModesShader.hx +++ b/source/funkin/graphics/shaders/BlendModesShader.hx @@ -1,8 +1,6 @@ package funkin.graphics.shaders; import flixel.addons.display.FlxRuntimeShader; -import funkin.Paths; -import openfl.utils.Assets; import openfl.display.BitmapData; import openfl.display.ShaderInput; diff --git a/source/funkin/graphics/shaders/GaussianBlurShader.hx b/source/funkin/graphics/shaders/GaussianBlurShader.hx index cecfdab80..023a66853 100644 --- a/source/funkin/graphics/shaders/GaussianBlurShader.hx +++ b/source/funkin/graphics/shaders/GaussianBlurShader.hx @@ -1,8 +1,6 @@ package funkin.graphics.shaders; import flixel.addons.display.FlxRuntimeShader; -import funkin.Paths; -import openfl.utils.Assets; /** * Note... not actually gaussian! diff --git a/source/funkin/graphics/shaders/Grayscale.hx b/source/funkin/graphics/shaders/Grayscale.hx index fbd0970e5..6fbdd1881 100644 --- a/source/funkin/graphics/shaders/Grayscale.hx +++ b/source/funkin/graphics/shaders/Grayscale.hx @@ -1,8 +1,6 @@ package funkin.graphics.shaders; import flixel.addons.display.FlxRuntimeShader; -import funkin.Paths; -import openfl.utils.Assets; class Grayscale extends FlxRuntimeShader { diff --git a/source/funkin/graphics/shaders/HSVShader.hx b/source/funkin/graphics/shaders/HSVShader.hx index 587008ce2..dda841ad9 100644 --- a/source/funkin/graphics/shaders/HSVShader.hx +++ b/source/funkin/graphics/shaders/HSVShader.hx @@ -1,8 +1,6 @@ package funkin.graphics.shaders; import flixel.addons.display.FlxRuntimeShader; -import funkin.Paths; -import openfl.utils.Assets; class HSVShader extends FlxRuntimeShader { diff --git a/source/funkin/graphics/shaders/MosaicEffect.hx b/source/funkin/graphics/shaders/MosaicEffect.hx index fc3737aff..76a6b6f3d 100644 --- a/source/funkin/graphics/shaders/MosaicEffect.hx +++ b/source/funkin/graphics/shaders/MosaicEffect.hx @@ -1,8 +1,6 @@ package funkin.graphics.shaders; import flixel.addons.display.FlxRuntimeShader; -import openfl.utils.Assets; -import funkin.Paths; import flixel.math.FlxPoint; class MosaicEffect extends FlxRuntimeShader diff --git a/source/funkin/graphics/shaders/RuntimeCustomBlendShader.hx b/source/funkin/graphics/shaders/RuntimeCustomBlendShader.hx index 3e8dfedd3..74ce7f4ea 100644 --- a/source/funkin/graphics/shaders/RuntimeCustomBlendShader.hx +++ b/source/funkin/graphics/shaders/RuntimeCustomBlendShader.hx @@ -2,7 +2,6 @@ package funkin.graphics.shaders; import openfl.display.BitmapData; import openfl.display.BlendMode; -import openfl.utils.Assets; class RuntimeCustomBlendShader extends RuntimePostEffectShader { diff --git a/source/funkin/graphics/shaders/RuntimeRainShader.hx b/source/funkin/graphics/shaders/RuntimeRainShader.hx index d0c036623..5d8df3f2c 100644 --- a/source/funkin/graphics/shaders/RuntimeRainShader.hx +++ b/source/funkin/graphics/shaders/RuntimeRainShader.hx @@ -5,7 +5,6 @@ import openfl.display.BitmapData; import openfl.display.ShaderParameter; import openfl.display.ShaderParameterType; import flixel.util.FlxColor; -import openfl.utils.Assets; typedef Light = { diff --git a/source/funkin/import.hx b/source/funkin/import.hx index c8431be33..a29e19977 100644 --- a/source/funkin/import.hx +++ b/source/funkin/import.hx @@ -3,6 +3,7 @@ package; #if !macro // Only import these when we aren't in a macro. import funkin.util.Constants; +import funkin.Assets; import funkin.Paths; import funkin.Preferences; import flixel.FlxG; // This one in particular causes a compile error if you're using macros. diff --git a/source/funkin/input/Cursor.hx b/source/funkin/input/Cursor.hx index 39f399465..554a6b2c1 100644 --- a/source/funkin/input/Cursor.hx +++ b/source/funkin/input/Cursor.hx @@ -1,7 +1,6 @@ package funkin.input; import haxe.ui.backend.flixel.CursorHelper; -import openfl.utils.Assets; import lime.app.Future; import openfl.display.BitmapData; diff --git a/source/funkin/play/Countdown.hx b/source/funkin/play/Countdown.hx index 643883a43..94a7548b9 100644 --- a/source/funkin/play/Countdown.hx +++ b/source/funkin/play/Countdown.hx @@ -11,7 +11,6 @@ import funkin.modding.events.ScriptEvent.CountdownScriptEvent; import flixel.util.FlxTimer; import funkin.util.EaseUtil; import funkin.audio.FunkinSound; -import openfl.utils.Assets; import funkin.data.notestyle.NoteStyleRegistry; import funkin.play.notes.notestyle.NoteStyle; diff --git a/source/funkin/play/GameOverSubState.hx b/source/funkin/play/GameOverSubState.hx index f6a7148f8..bf8735647 100644 --- a/source/funkin/play/GameOverSubState.hx +++ b/source/funkin/play/GameOverSubState.hx @@ -15,7 +15,6 @@ import funkin.ui.freeplay.FreeplayState; import funkin.ui.MusicBeatSubState; import funkin.ui.story.StoryMenuState; import funkin.util.MathUtil; -import openfl.utils.Assets; import funkin.effects.RetroCameraFade; import flixel.math.FlxPoint; diff --git a/source/funkin/play/character/CharacterData.hx b/source/funkin/play/character/CharacterData.hx index bac2c7141..3a790bcf2 100644 --- a/source/funkin/play/character/CharacterData.hx +++ b/source/funkin/play/character/CharacterData.hx @@ -11,7 +11,6 @@ import funkin.play.character.ScriptedCharacter.ScriptedSparrowCharacter; import funkin.util.assets.DataAssets; import funkin.util.VersionUtil; import haxe.Json; -import openfl.utils.Assets; class CharacterDataParser { diff --git a/source/funkin/play/components/HealthIcon.hx b/source/funkin/play/components/HealthIcon.hx index c11850b2a..c7854871c 100644 --- a/source/funkin/play/components/HealthIcon.hx +++ b/source/funkin/play/components/HealthIcon.hx @@ -5,7 +5,6 @@ import flixel.FlxSprite; import flixel.math.FlxMath; import flixel.math.FlxPoint; import funkin.play.character.CharacterData.CharacterDataParser; -import openfl.utils.Assets; import funkin.graphics.FunkinSprite; import funkin.util.MathUtil; diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx index a02291e4e..fbc97283f 100644 --- a/source/funkin/play/components/PopUpStuff.hx +++ b/source/funkin/play/components/PopUpStuff.hx @@ -8,7 +8,6 @@ import funkin.graphics.FunkinSprite; import funkin.play.PlayState; import funkin.util.TimerUtil; import funkin.util.EaseUtil; -import openfl.utils.Assets; import funkin.data.notestyle.NoteStyleRegistry; import funkin.play.notes.notestyle.NoteStyle; diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx index 9d35902b0..9023b872e 100644 --- a/source/funkin/play/song/Song.hx +++ b/source/funkin/play/song/Song.hx @@ -16,7 +16,6 @@ import funkin.modding.IScriptedClass.IPlayStateScriptedClass; import funkin.modding.events.ScriptEvent; import funkin.ui.freeplay.charselect.PlayableCharacter; import funkin.util.SortUtil; -import openfl.utils.Assets; /** * This is a data structure managing information about the current song. diff --git a/source/funkin/ui/debug/anim/DebugBoundingState.hx b/source/funkin/ui/debug/anim/DebugBoundingState.hx index 7bb42c89e..5ed000e90 100644 --- a/source/funkin/ui/debug/anim/DebugBoundingState.hx +++ b/source/funkin/ui/debug/anim/DebugBoundingState.hx @@ -24,7 +24,6 @@ import haxe.ui.core.Screen; import haxe.ui.events.UIEvent; import haxe.ui.RuntimeComponentBuilder; import lime.utils.Assets as LimeAssets; -import openfl.Assets; import openfl.events.Event; import openfl.events.IOErrorEvent; import openfl.geom.Rectangle; diff --git a/source/funkin/ui/debug/charting/components/ChartEditorEventSprite.hx b/source/funkin/ui/debug/charting/components/ChartEditorEventSprite.hx index c996079bc..4c4a8d200 100644 --- a/source/funkin/ui/debug/charting/components/ChartEditorEventSprite.hx +++ b/source/funkin/ui/debug/charting/components/ChartEditorEventSprite.hx @@ -3,7 +3,6 @@ package funkin.ui.debug.charting.components; import funkin.data.event.SongEventRegistry; import flixel.graphics.frames.FlxAtlasFrames; import openfl.display.BitmapData; -import openfl.utils.Assets; import flixel.FlxObject; import flixel.FlxBasic; import flixel.FlxSprite; diff --git a/source/funkin/ui/debug/charting/handlers/ChartEditorAudioHandler.hx b/source/funkin/ui/debug/charting/handlers/ChartEditorAudioHandler.hx index 26e246371..329873d68 100644 --- a/source/funkin/ui/debug/charting/handlers/ChartEditorAudioHandler.hx +++ b/source/funkin/ui/debug/charting/handlers/ChartEditorAudioHandler.hx @@ -13,7 +13,6 @@ import funkin.audio.waveform.WaveformSprite; import flixel.util.FlxColor; import haxe.io.Bytes; import haxe.io.Path; -import openfl.utils.Assets; /** * Functions for loading audio for the chart editor. diff --git a/source/funkin/ui/freeplay/AlbumRoll.hx b/source/funkin/ui/freeplay/AlbumRoll.hx index 4107369d2..81a9fe858 100644 --- a/source/funkin/ui/freeplay/AlbumRoll.hx +++ b/source/funkin/ui/freeplay/AlbumRoll.hx @@ -11,7 +11,6 @@ import funkin.data.freeplay.album.AlbumRegistry; import funkin.util.assets.FlxAnimationUtil; import funkin.graphics.FunkinSprite; import funkin.util.SortUtil; -import openfl.utils.Assets; /** * The graphic for the album roll in the FreeplayState. diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index af0a9b841..c368c6632 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -51,7 +51,6 @@ import funkin.ui.transition.LoadingState; import funkin.ui.transition.StickerSubState; import funkin.util.MathUtil; import funkin.util.SortUtil; -import lime.utils.Assets; import openfl.display.BlendMode; import funkin.data.freeplay.style.FreeplayStyleRegistry; import funkin.data.song.SongData.SongMusicData; @@ -1859,7 +1858,7 @@ class FreeplayState extends MusicBeatSubState 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) + // Clears the cache of songs to free up memory, they'll have to be loaded in later tho function clearDaCache(actualSongTho:String):Void { for (song in songs) diff --git a/source/funkin/ui/freeplay/backcards/BackingCard.hx b/source/funkin/ui/freeplay/backcards/BackingCard.hx index bb662cc8d..713b6edcf 100644 --- a/source/funkin/ui/freeplay/backcards/BackingCard.hx +++ b/source/funkin/ui/freeplay/backcards/BackingCard.hx @@ -18,7 +18,6 @@ import funkin.graphics.adobeanimate.FlxAtlasSprite; import funkin.graphics.FunkinSprite; import funkin.ui.freeplay.charselect.PlayableCharacter; import funkin.ui.MusicBeatSubState; -import lime.utils.Assets; import openfl.display.BlendMode; import flixel.group.FlxSpriteGroup; diff --git a/source/funkin/ui/freeplay/backcards/BoyfriendCard.hx b/source/funkin/ui/freeplay/backcards/BoyfriendCard.hx index 597fd1a34..a049c4f42 100644 --- a/source/funkin/ui/freeplay/backcards/BoyfriendCard.hx +++ b/source/funkin/ui/freeplay/backcards/BoyfriendCard.hx @@ -18,7 +18,6 @@ import funkin.graphics.adobeanimate.FlxAtlasSprite; import funkin.graphics.FunkinSprite; import funkin.ui.freeplay.charselect.PlayableCharacter; import funkin.ui.MusicBeatSubState; -import lime.utils.Assets; import openfl.display.BlendMode; import flixel.group.FlxSpriteGroup; @@ -177,20 +176,21 @@ class BoyfriendCard extends BackingCard } var beatFreq:Int = 1; - var beatFreqList:Array = [1,2,4,8]; + var beatFreqList:Array = [1, 2, 4, 8]; - public override function beatHit():Void { + public override function beatHit():Void + { // increases the amount of beats that need to go by to pulse the glow because itd flash like craazy at high bpms..... - beatFreq = beatFreqList[Math.floor(Conductor.instance.bpm/140)]; + beatFreq = beatFreqList[Math.floor(Conductor.instance.bpm / 140)]; - if(Conductor.instance.currentBeat % beatFreq != 0) return; + if (Conductor.instance.currentBeat % beatFreq != 0) return; FlxTween.cancelTweensOf(glow); FlxTween.cancelTweensOf(glowDark); glow.alpha = 0.8; - FlxTween.tween(glow, {alpha: 0}, 16/24, {ease: FlxEase.quartOut}); + FlxTween.tween(glow, {alpha: 0}, 16 / 24, {ease: FlxEase.quartOut}); glowDark.alpha = 0; - FlxTween.tween(glowDark, {alpha: 0.6}, 18/24, {ease: FlxEase.quartOut}); + FlxTween.tween(glowDark, {alpha: 0.6}, 18 / 24, {ease: FlxEase.quartOut}); } public override function introDone():Void diff --git a/source/funkin/ui/freeplay/backcards/NewCharacterCard.hx b/source/funkin/ui/freeplay/backcards/NewCharacterCard.hx index a44ff88a6..1e3d81299 100644 --- a/source/funkin/ui/freeplay/backcards/NewCharacterCard.hx +++ b/source/funkin/ui/freeplay/backcards/NewCharacterCard.hx @@ -20,7 +20,6 @@ import funkin.graphics.adobeanimate.FlxAtlasSprite; import funkin.graphics.FunkinSprite; import funkin.ui.freeplay.charselect.PlayableCharacter; import funkin.ui.MusicBeatSubState; -import lime.utils.Assets; import openfl.display.BlendMode; import flixel.group.FlxSpriteGroup; import funkin.graphics.shaders.AdjustColorShader; diff --git a/source/funkin/ui/freeplay/backcards/PicoCard.hx b/source/funkin/ui/freeplay/backcards/PicoCard.hx index f5db1ccc3..8cfe7756e 100644 --- a/source/funkin/ui/freeplay/backcards/PicoCard.hx +++ b/source/funkin/ui/freeplay/backcards/PicoCard.hx @@ -20,7 +20,6 @@ import funkin.graphics.adobeanimate.FlxAtlasSprite; import funkin.graphics.FunkinSprite; import funkin.ui.freeplay.charselect.PlayableCharacter; import funkin.ui.MusicBeatSubState; -import lime.utils.Assets; import openfl.display.BlendMode; import flixel.group.FlxSpriteGroup; import funkin.graphics.shaders.AdjustColorShader; @@ -233,20 +232,21 @@ class PicoCard extends BackingCard } var beatFreq:Int = 1; - var beatFreqList:Array = [1,2,4,8]; + var beatFreqList:Array = [1, 2, 4, 8]; - public override function beatHit():Void { + public override function beatHit():Void + { // increases the amount of beats that need to go by to pulse the glow because itd flash like craazy at high bpms..... - beatFreq = beatFreqList[Math.floor(Conductor.instance.bpm/140)]; + beatFreq = beatFreqList[Math.floor(Conductor.instance.bpm / 140)]; - if(Conductor.instance.currentBeat % beatFreq != 0) return; + if (Conductor.instance.currentBeat % beatFreq != 0) return; FlxTween.cancelTweensOf(glow); FlxTween.cancelTweensOf(glowDark); glow.alpha = 1; - FlxTween.tween(glow, {alpha: 0}, 16/24, {ease: FlxEase.quartOut}); + FlxTween.tween(glow, {alpha: 0}, 16 / 24, {ease: FlxEase.quartOut}); glowDark.alpha = 0; - FlxTween.tween(glowDark, {alpha: 1}, 18/24, {ease: FlxEase.quartOut}); + FlxTween.tween(glowDark, {alpha: 1}, 18 / 24, {ease: FlxEase.quartOut}); } public override function introDone():Void diff --git a/source/funkin/ui/options/FunkinSoundTray.hx b/source/funkin/ui/options/FunkinSoundTray.hx index 170ad8497..8ae53524a 100644 --- a/source/funkin/ui/options/FunkinSoundTray.hx +++ b/source/funkin/ui/options/FunkinSoundTray.hx @@ -6,7 +6,6 @@ import flixel.system.FlxAssets; import flixel.tweens.FlxEase; import openfl.display.Bitmap; import openfl.display.BitmapData; -import openfl.utils.Assets; import funkin.util.MathUtil; /** diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx index 18614d414..c0ed2712a 100644 --- a/source/funkin/ui/story/StoryMenuState.hx +++ b/source/funkin/ui/story/StoryMenuState.hx @@ -23,7 +23,6 @@ import funkin.ui.MusicBeatState; import funkin.ui.transition.LoadingState; import funkin.ui.transition.StickerSubState; import funkin.util.MathUtil; -import openfl.utils.Assets; class StoryMenuState extends MusicBeatState { diff --git a/source/funkin/ui/transition/LoadingState.hx b/source/funkin/ui/transition/LoadingState.hx index 5b82cc741..ef95da6c9 100644 --- a/source/funkin/ui/transition/LoadingState.hx +++ b/source/funkin/ui/transition/LoadingState.hx @@ -3,24 +3,23 @@ package funkin.ui.transition; import flixel.FlxSprite; import flixel.math.FlxMath; import flixel.tweens.FlxEase; -import funkin.graphics.FunkinSprite; import flixel.tweens.FlxTween; import flixel.util.FlxTimer; +import flixel.util.typeLimit.NextState; +import funkin.graphics.FunkinSprite; import funkin.graphics.shaders.ScreenWipeShader; import funkin.play.PlayState; import funkin.play.PlayStatePlaylist; import funkin.play.song.Song.SongDifficulty; import funkin.ui.MusicBeatState; import haxe.io.Path; -import funkin.graphics.FunkinSprite; import lime.app.Future; import lime.app.Promise; import lime.utils.AssetLibrary; import lime.utils.AssetManifest; import lime.utils.Assets as LimeAssets; import openfl.filters.ShaderFilter; -import openfl.utils.Assets; -import flixel.util.typeLimit.NextState; +import openfl.utils.Assets as OpenFLAssets; class LoadingState extends MusicBeatSubState { @@ -98,7 +97,7 @@ class LoadingState extends MusicBeatSubState function checkLoadSong(path:String):Void { - if (!Assets.cache.hasSound(path)) + if (!OpenFLAssets.cache.hasSound(path)) { var library = Assets.getLibrary('songs'); var symbolPath = path.split(':').pop(); diff --git a/source/funkin/ui/transition/StickerSubState.hx b/source/funkin/ui/transition/StickerSubState.hx index e5abef872..e8d6877d8 100644 --- a/source/funkin/ui/transition/StickerSubState.hx +++ b/source/funkin/ui/transition/StickerSubState.hx @@ -2,7 +2,6 @@ package funkin.ui.transition; import flixel.FlxSprite; import haxe.Json; -import lime.utils.Assets; import funkin.graphics.FunkinSprite; // import flxtyped group import funkin.ui.MusicBeatSubState; @@ -56,7 +55,7 @@ class StickerSubState extends MusicBeatSubState // make sure that ONLY plays mp3/ogg files // if there's no mp3/ogg file, then it regenerates/reloads the random folder - var assetsInList = openfl.utils.Assets.list(); + var assetsInList = Assets.list(); var soundFilterFunc = function(a:String) { return a.startsWith('assets/shared/sounds/stickersounds/'); @@ -84,7 +83,7 @@ class StickerSubState extends MusicBeatSubState var filterFunc = function(a:String) { return a.startsWith('assets/shared/sounds/stickersounds/' + soundSelection + '/'); }; - var assetsInList3 = openfl.utils.Assets.list(); + var assetsInList3 = Assets.list(); sounds = assetsInList3.filter(filterFunc); for (i in 0...sounds.length) { From b28af79eb3246b7e540288230a59000654fe4aa5 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 18 Sep 2024 05:18:16 -0400 Subject: [PATCH 823/870] Fix build issues --- source/funkin/play/PlayState.hx | 1 - source/funkin/play/components/PopUpStuff.hx | 9 --------- source/funkin/ui/debug/anim/DebugBoundingState.hx | 2 +- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index a25d3b231..1c82eb6b1 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -3046,7 +3046,6 @@ class PlayState extends MusicBeatSubState GameOverSubState.reset(); PauseSubState.reset(); Countdown.reset(); - PopUpStuff.reset(); // Clear the static reference to this state. instance = null; diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx index e5e9b4681..a02291e4e 100644 --- a/source/funkin/play/components/PopUpStuff.hx +++ b/source/funkin/play/components/PopUpStuff.hx @@ -125,13 +125,4 @@ class PopUpStuff extends FlxTypedGroup daLoop++; } } - - /** - * Reset the popup configuration to the default. - */ - public static function reset() - { - noteStyle = NoteStyleRegistry.instance.fetchDefault(); - isPixel = false; - } } diff --git a/source/funkin/ui/debug/anim/DebugBoundingState.hx b/source/funkin/ui/debug/anim/DebugBoundingState.hx index 19391f8d9..d2a27999f 100644 --- a/source/funkin/ui/debug/anim/DebugBoundingState.hx +++ b/source/funkin/ui/debug/anim/DebugBoundingState.hx @@ -77,7 +77,7 @@ class DebugBoundingState extends FlxState { // get the screen position, according to the HUD camera, temp default to FlxG.camera juuust in case? var hudMousePos:FlxPoint = FlxG.mouse.getScreenPosition(hudCam ?? FlxG.camera); - return Screen.instance.hasSolidComponentUnderPoint(hudMousePos.x, hudMousePos.y) || FlxG.mouse.overlaps(animDropDownMenu, hudCam); + return Screen.instance.hasSolidComponentUnderPoint(hudMousePos.x, hudMousePos.y); } override function create() From b5ed7f40d4621006d5dc906020050095e2733e9c Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 18 Sep 2024 05:24:57 -0400 Subject: [PATCH 824/870] Remove redundant character type assignment --- source/funkin/play/PlayState.hx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 0b2b8846d..b304381cc 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1612,7 +1612,7 @@ class PlayState extends MusicBeatSubState if (girlfriend != null) { - girlfriend.characterType = CharacterType.GF; + // Don't need to do anything. } else if (currentCharacterData.girlfriend != '') { @@ -1630,8 +1630,6 @@ class PlayState extends MusicBeatSubState if (dad != null) { - dad.characterType = CharacterType.DAD; - // // OPPONENT HEALTH ICON // @@ -1650,8 +1648,6 @@ class PlayState extends MusicBeatSubState if (boyfriend != null) { - boyfriend.characterType = CharacterType.BF; - // // PLAYER HEALTH ICON // @@ -1993,6 +1989,7 @@ class PlayState extends MusicBeatSubState // Skip this if the music is paused (GameOver, Pause menu, start-of-song offset, etc.) if (!(FlxG.sound.music?.playing ?? false)) return; + var timeToPlayAt:Float = Conductor.instance.songPosition - Conductor.instance.instrumentalOffset; FlxG.sound.music.pause(); vocals.pause(); From d54dc6179a305d05d33ebb360410076dcf03a566 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 18 Sep 2024 06:02:13 -0400 Subject: [PATCH 825/870] Add several new Github Actions for issue management --- .github/label-actions.yml | 23 ++++++++ .github/workflows/label-actions.yml | 29 +++++++++++ .github/workflows/label-issue.yml | 52 +++++++++++++++++++ .../{labeler.yml => label-pull-request.yml} | 2 + 4 files changed, 106 insertions(+) create mode 100644 .github/label-actions.yml create mode 100644 .github/workflows/label-actions.yml create mode 100644 .github/workflows/label-issue.yml rename .github/workflows/{labeler.yml => label-pull-request.yml} (84%) diff --git a/.github/label-actions.yml b/.github/label-actions.yml new file mode 100644 index 000000000..00fb390aa --- /dev/null +++ b/.github/label-actions.yml @@ -0,0 +1,23 @@ +# Configuration for Label Actions - https://github.com/dessant/label-actions + +# Automatically close issues and pull requests when the `status: duplicate` label is applied +'status: duplicate': + issues: + # Post a comment + comment: > + This issue is a duplicate. Please direct all discussion to the original issue. + # Close the issue + close: true + # Remove other status labels + unlabel: + - 'status: pending triage' + # Set a close reason + close-reason: 'not planned' + prs: + # Post a comment + comment: > + This pull request is a duplicate. Please direct all discussion to the original pull request. + # Close the pull request + close: true + # Set a close reason + close-reason: 'not planned' diff --git a/.github/workflows/label-actions.yml b/.github/workflows/label-actions.yml new file mode 100644 index 000000000..bc4cf0add --- /dev/null +++ b/.github/workflows/label-actions.yml @@ -0,0 +1,29 @@ +# Perform actions when labels are applied to issues, discussions, or pull requests +# See .github/label-actions.yml +name: 'Label Actions' + +on: + issues: + types: + - labeled + - unlabeled + pull_request_target: + types: + - labeled + - unlabeled + discussion: + types: + - labeled + - unlabeled + +permissions: + contents: read + issues: write + pull-requests: write + discussions: write + +jobs: + action: + runs-on: ubuntu-latest + steps: + - uses: dessant/label-actions@v4 diff --git a/.github/workflows/label-issue.yml b/.github/workflows/label-issue.yml new file mode 100644 index 000000000..eeb83350c --- /dev/null +++ b/.github/workflows/label-issue.yml @@ -0,0 +1,52 @@ +name: "Issue Labeler" +on: + issues: + types: + - opened + - reopened + - edited + +jobs: + # When an issue is opened, perform a similarity check for potential duplicates. + # If some are found, add a label and comment listing the potential duplicate issues. + potential-duplicate: + name: Detect potential duplicate issues + runs-on: ubuntu-latest + steps: + - uses: wow-actions/potential-duplicates@v1 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Issue title filter work with anymatch https://www.npmjs.com/package/anymatch. + # Any matched issue will stop detection immediately. + # You can specify multi filters in each line. + filter: '' + # Exclude keywords in title before detecting. + exclude: '' + # Label to set, when potential duplicates are detected. + label: 'potential duplicate' + # Get issues with state to compare. Supported state: 'all', 'closed', 'open'. + state: all + # If similarity is higher than this threshold([0,1]), issue will be marked as duplicate. + # Turn this up if the detection is too sensitive + threshold: 0.6 + # Reactions to be add to comment when potential duplicates are detected. + # Available reactions: "-1", "+1", "confused", "laugh", "heart", "hooray", "rocket", "eyes" + # reactions: '-1' + # Comment to post when potential duplicates are detected. + comment: > + Potential duplicates: {{#issues}} + - [#{{ number }}] {{ title }} ({{ accuracy }}%) + {{/issues}} + # When an issue is opened, detect if it has an empty body or incomplete issue form. + # If it does, close the issue immediately. + empty-issues: + name: Close empty issues + runs-on: ubuntu-latest + steps: + - name: Run empty issues closer action + uses: rickstaa/empty-issues-closer-action@v1 + env: + github_token: ${{ secrets.GITHUB_TOKEN }} + with: + close_comment: Closing this issue because it appears to be empty. Please update the issue for it to be reopened. + open_comment: Reopening this issue because the author provided more information. diff --git a/.github/workflows/labeler.yml b/.github/workflows/label-pull-request.yml similarity index 84% rename from .github/workflows/labeler.yml rename to .github/workflows/label-pull-request.yml index a861af578..525e1b5a6 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/label-pull-request.yml @@ -3,6 +3,7 @@ on: - pull_request_target jobs: + # Apply labels to pull requests based on which files were edited labeler: permissions: contents: read @@ -13,6 +14,7 @@ jobs: uses: actions/labeler@v5 with: sync-labels: true + # Apply labels to pull requests based on how many lines were edited changed-lines-count-labeler: permissions: contents: read From ba90a6abe04b15058a9c32a0ba1dd5338605c57a Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 18 Sep 2024 06:08:18 -0400 Subject: [PATCH 826/870] Add behavior when setting status: rejected --- .github/label-actions.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/.github/label-actions.yml b/.github/label-actions.yml index 00fb390aa..1234d1526 100644 --- a/.github/label-actions.yml +++ b/.github/label-actions.yml @@ -17,7 +17,28 @@ # Post a comment comment: > This pull request is a duplicate. Please direct all discussion to the original pull request. + # Remove other status labels + unlabel: + - 'status: pending triage' # Close the pull request close: true # Set a close reason close-reason: 'not planned' + +'status: rejected': + issues: + # Close the issue + close: true + # Remove other status labels + unlabel: + - 'status: pending triage' + # Set a close reason + close-reason: 'not planned' + prs: + # Close the pull request + close: true + # Remove other status labels + unlabel: + - 'status: pending triage' + # Set a close reason + close-reason: 'not planned' From a469385cdba4288d166682874938b124fd2b7fcf Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 18 Sep 2024 06:22:02 -0400 Subject: [PATCH 827/870] Resolve merge issues --- source/funkin/play/PlayState.hx | 1 - source/funkin/play/components/PopUpStuff.hx | 9 --------- source/funkin/ui/debug/anim/DebugBoundingState.hx | 2 +- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index a25d3b231..1c82eb6b1 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -3046,7 +3046,6 @@ class PlayState extends MusicBeatSubState GameOverSubState.reset(); PauseSubState.reset(); Countdown.reset(); - PopUpStuff.reset(); // Clear the static reference to this state. instance = null; diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx index e5e9b4681..a02291e4e 100644 --- a/source/funkin/play/components/PopUpStuff.hx +++ b/source/funkin/play/components/PopUpStuff.hx @@ -125,13 +125,4 @@ class PopUpStuff extends FlxTypedGroup daLoop++; } } - - /** - * Reset the popup configuration to the default. - */ - public static function reset() - { - noteStyle = NoteStyleRegistry.instance.fetchDefault(); - isPixel = false; - } } diff --git a/source/funkin/ui/debug/anim/DebugBoundingState.hx b/source/funkin/ui/debug/anim/DebugBoundingState.hx index 19391f8d9..d2a27999f 100644 --- a/source/funkin/ui/debug/anim/DebugBoundingState.hx +++ b/source/funkin/ui/debug/anim/DebugBoundingState.hx @@ -77,7 +77,7 @@ class DebugBoundingState extends FlxState { // get the screen position, according to the HUD camera, temp default to FlxG.camera juuust in case? var hudMousePos:FlxPoint = FlxG.mouse.getScreenPosition(hudCam ?? FlxG.camera); - return Screen.instance.hasSolidComponentUnderPoint(hudMousePos.x, hudMousePos.y) || FlxG.mouse.overlaps(animDropDownMenu, hudCam); + return Screen.instance.hasSolidComponentUnderPoint(hudMousePos.x, hudMousePos.y); } override function create() From 5efbff044b1a04cd28006124e0305671d6b709e7 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 18 Sep 2024 06:32:06 -0400 Subject: [PATCH 828/870] Resolve merge issues --- source/funkin/play/PlayState.hx | 1 - source/funkin/play/components/PopUpStuff.hx | 9 --------- source/funkin/ui/debug/anim/DebugBoundingState.hx | 2 +- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index a25d3b231..1c82eb6b1 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -3046,7 +3046,6 @@ class PlayState extends MusicBeatSubState GameOverSubState.reset(); PauseSubState.reset(); Countdown.reset(); - PopUpStuff.reset(); // Clear the static reference to this state. instance = null; diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx index e5e9b4681..a02291e4e 100644 --- a/source/funkin/play/components/PopUpStuff.hx +++ b/source/funkin/play/components/PopUpStuff.hx @@ -125,13 +125,4 @@ class PopUpStuff extends FlxTypedGroup daLoop++; } } - - /** - * Reset the popup configuration to the default. - */ - public static function reset() - { - noteStyle = NoteStyleRegistry.instance.fetchDefault(); - isPixel = false; - } } diff --git a/source/funkin/ui/debug/anim/DebugBoundingState.hx b/source/funkin/ui/debug/anim/DebugBoundingState.hx index 19391f8d9..d2a27999f 100644 --- a/source/funkin/ui/debug/anim/DebugBoundingState.hx +++ b/source/funkin/ui/debug/anim/DebugBoundingState.hx @@ -77,7 +77,7 @@ class DebugBoundingState extends FlxState { // get the screen position, according to the HUD camera, temp default to FlxG.camera juuust in case? var hudMousePos:FlxPoint = FlxG.mouse.getScreenPosition(hudCam ?? FlxG.camera); - return Screen.instance.hasSolidComponentUnderPoint(hudMousePos.x, hudMousePos.y) || FlxG.mouse.overlaps(animDropDownMenu, hudCam); + return Screen.instance.hasSolidComponentUnderPoint(hudMousePos.x, hudMousePos.y); } override function create() From 9d5cde0bf1889be63b45016b4a292c69697befc8 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 18 Sep 2024 06:48:45 -0400 Subject: [PATCH 829/870] Update assets submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index bc7009b42..68520d9eb 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit bc7009b4242691faa5c4552f7ca8a2f28e8cb1d2 +Subproject commit 68520d9eb9ff9a4e8aa52852eab1ef56db302b91 From a4b59d14bf34270bf04520320eabf3f11b5f2d29 Mon Sep 17 00:00:00 2001 From: Kolo <67389779+JustKolosaki@users.noreply.github.com> Date: Wed, 18 Sep 2024 13:40:02 +0200 Subject: [PATCH 830/870] applySongRank fix fixes the bug with the percent being overriden when the song has the same letter rank but lower percent (eg. E Rank with 99% being overriden by E Rank with 93%) --- source/funkin/save/Save.hx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx index 2bbda15c0..74af9994e 100644 --- a/source/funkin/save/Save.hx +++ b/source/funkin/save/Save.hx @@ -598,11 +598,15 @@ class Save return; } + //percent also accounts for different ranks + var oldPerc = (previousScoreData.tallies.sick + previousScoreData.tallies.good) / previousScoreData.tallies.totalNotes; + var newPerc = (newScoreData.tallies.sick + newScoreData.tallies.good) / newScoreData.tallies.totalNotes; + // Set the high score and the high rank separately. var newScore:SaveScoreData = { - score: (previousScoreData.score > newScoreData.score) ? previousScoreData.score : newScoreData.score, - tallies: (previousRank > newRank) ? previousScoreData.tallies : newScoreData.tallies + score: Std.int(Math.max(previousScoreData.score, newScoreData.score)), + tallies: (oldPerc > newPerc ? previousScoreData.tallies : newScoreData.tallies) }; song.set(difficultyId, newScore); From 50a5304ad48b210cba62e8bc756b417b3c69cc96 Mon Sep 17 00:00:00 2001 From: Kolo <67389779+JustKolosaki@users.noreply.github.com> Date: Wed, 18 Sep 2024 17:30:23 +0200 Subject: [PATCH 831/870] Update PlayerData.hx --- source/funkin/data/freeplay/player/PlayerData.hx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/funkin/data/freeplay/player/PlayerData.hx b/source/funkin/data/freeplay/player/PlayerData.hx index de293c24e..a5bf086f6 100644 --- a/source/funkin/data/freeplay/player/PlayerData.hx +++ b/source/funkin/data/freeplay/player/PlayerData.hx @@ -264,6 +264,12 @@ class PlayerCharSelectData */ @:optional public var position:Null; + + /** + * The GF name to assign for this character. + */ + @:optional + public var assignedGF:Null; } typedef PlayerResultsData = From 3bb981adb03371e1be5034d7997dc5135a7d8f04 Mon Sep 17 00:00:00 2001 From: Kolo <67389779+JustKolosaki@users.noreply.github.com> Date: Wed, 18 Sep 2024 17:32:37 +0200 Subject: [PATCH 832/870] Update CharSelectGF.hx --- source/funkin/ui/charSelect/CharSelectGF.hx | 37 ++++++++++++--------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/source/funkin/ui/charSelect/CharSelectGF.hx b/source/funkin/ui/charSelect/CharSelectGF.hx index e8eeded40..79cfb585c 100644 --- a/source/funkin/ui/charSelect/CharSelectGF.hx +++ b/source/funkin/ui/charSelect/CharSelectGF.hx @@ -11,6 +11,7 @@ import funkin.modding.IScriptedClass.IBPMSyncedScriptedClass; import flixel.math.FlxMath; import funkin.modding.events.ScriptEvent; import funkin.vis.dsp.SpectralAnalyzer; +import funkin.data.freeplay.player.PlayerRegistry; class CharSelectGF extends FlxAtlasSprite implements IBPMSyncedScriptedClass { @@ -27,7 +28,7 @@ class CharSelectGF extends FlxAtlasSprite implements IBPMSyncedScriptedClass var analyzer:SpectralAnalyzer; - var curGF:GFChar = GF; + var curGF:String = "gf"; public function new() { @@ -97,7 +98,7 @@ class CharSelectGF extends FlxAtlasSprite implements IBPMSyncedScriptedClass function drawFFT() { - if (curGF == NENE) + if (curGF == "nene") { var levels = analyzer.getLevels(); var frame = anim.curSymbol.timeline.get("VIZ_bars").get(anim.curFrame); @@ -172,16 +173,21 @@ class CharSelectGF extends FlxAtlasSprite implements IBPMSyncedScriptedClass */ public function switchGF(bf:String):Void { - var prevGF:GFChar = curGF; - switch (bf) - { - case "pico": - curGF = NENE; - case "bf": - curGF = GF; - default: - curGF = GF; - } + var prevGF = curGF; + + var bfObj = PlayerRegistry.instance.fetchEntry(bf); + curGF = bfObj?.getCharSelectData()?.assignedGF ?? "gf"; + + /*var prevGF:GFChar = curGF; + switch (bf) + { + case "pico": + curGF = NENE; + case "bf": + curGF = GF; + default: + curGF = GF; + }*/ // We don't need to update any anims if we didn't change GF if (prevGF != curGF) @@ -213,9 +219,8 @@ enum FadeStatus FADE_OUT; FADE_IN; } - -enum abstract GFChar(String) from String to String -{ +/*enum abstract GFChar(String) from String to String + { var GF = "gf"; var NENE = "nene"; -} +}*/ From 99657da1f984ff5842d714b2cde398cca6785e06 Mon Sep 17 00:00:00 2001 From: Kolo <67389779+JustKolosaki@users.noreply.github.com> Date: Wed, 18 Sep 2024 17:46:13 +0200 Subject: [PATCH 833/870] accidentally also put the save changes oops --- source/funkin/save/Save.hx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx index 74af9994e..2bbda15c0 100644 --- a/source/funkin/save/Save.hx +++ b/source/funkin/save/Save.hx @@ -598,15 +598,11 @@ class Save return; } - //percent also accounts for different ranks - var oldPerc = (previousScoreData.tallies.sick + previousScoreData.tallies.good) / previousScoreData.tallies.totalNotes; - var newPerc = (newScoreData.tallies.sick + newScoreData.tallies.good) / newScoreData.tallies.totalNotes; - // Set the high score and the high rank separately. var newScore:SaveScoreData = { - score: Std.int(Math.max(previousScoreData.score, newScoreData.score)), - tallies: (oldPerc > newPerc ? previousScoreData.tallies : newScoreData.tallies) + score: (previousScoreData.score > newScoreData.score) ? previousScoreData.score : newScoreData.score, + tallies: (previousRank > newRank) ? previousScoreData.tallies : newScoreData.tallies }; song.set(difficultyId, newScore); From ab3b976f3c979d04e713b47de607335a58917db7 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 18 Sep 2024 15:07:15 -0400 Subject: [PATCH 834/870] fix rounding for sound results sfx --- source/funkin/play/ResultState.hx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index 739df167d..33f3587ea 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -472,9 +472,12 @@ class ResultState extends MusicBeatSubState { ease: FlxEase.quartOut, onUpdate: _ -> { + clearPercentLerp = Math.round(clearPercentLerp); + clearPercentCounter.curNumber = Math.round(clearPercentCounter.curNumber); // Only play the tick sound if the number increased. if (clearPercentLerp != clearPercentCounter.curNumber) { + trace('$clearPercentLerp and ${clearPercentCounter.curNumber}'); clearPercentLerp = clearPercentCounter.curNumber; FunkinSound.playOnce(Paths.sound('scrollMenu')); } From 62149aea39687fc84f79e7a7ce4edf636cef416e Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 18 Sep 2024 15:16:56 -0400 Subject: [PATCH 835/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 616551146..da96dc519 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 61655114603807b651109af282c2e2aefa9dccf2 +Subproject commit da96dc519a00bb8eb24a164bae64a4c6c064e87d From fc6e194d20968d010c5d4c22511cd8fd400d9058 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 18 Sep 2024 15:20:15 -0400 Subject: [PATCH 836/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index ef7386d74..252d48f4c 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit ef7386d741e715bd809c913a7d50dfa7b8176e2d +Subproject commit 252d48f4c996d5832cb981fb2f3ed945c020f289 From 472d41a893a3610ff6935844ecb50d44949e1851 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 18 Sep 2024 16:15:10 -0400 Subject: [PATCH 837/870] close sys.io.Process stuff when we're done with them --- project.hxp | 6 ++++++ source/funkin/util/macro/GitCommit.hx | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/project.hxp b/project.hxp index 1193a9cd4..ac047ff91 100644 --- a/project.hxp +++ b/project.hxp @@ -941,6 +941,8 @@ class Project extends HXProject { var commitHash:String = process.stdout.readLine(); var commitHashSplice:String = commitHash.substr(0, 7); + process.close(); + return commitHashSplice; } @@ -955,6 +957,8 @@ class Project extends HXProject { var branchName:String = branchProcess.stdout.readLine(); + branchProcess.close(); + return branchName; } @@ -979,6 +983,8 @@ class Project extends HXProject { } } + branchProcess.close(); + return output.length > 0; } diff --git a/source/funkin/util/macro/GitCommit.hx b/source/funkin/util/macro/GitCommit.hx index 161856caa..9e3305c41 100644 --- a/source/funkin/util/macro/GitCommit.hx +++ b/source/funkin/util/macro/GitCommit.hx @@ -23,6 +23,8 @@ class GitCommit var commitHash:String = process.stdout.readLine(); var commitHashSplice:String = commitHash.substr(0, 7); + process.close(); + trace('Git Commit ID: ${commitHashSplice}'); // Generates a string expression @@ -52,6 +54,7 @@ class GitCommit } var branchName:String = branchProcess.stdout.readLine(); + branchProcess.close(); trace('Git Branch Name: ${branchName}'); // Generates a string expression @@ -84,6 +87,7 @@ class GitCommit try { output = branchProcess.stdout.readLine(); + branchProcess.close(); } catch (e) { From 9f0bc2bd521f274f8ad9d214966538d95894277a Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 19 Sep 2024 04:16:40 -0400 Subject: [PATCH 838/870] Refactor char select GF data handling. --- assets | 2 +- .../funkin/data/freeplay/player/PlayerData.hx | 15 +++++- source/funkin/ui/charSelect/CharSelectGF.hx | 46 +++++++++---------- .../ui/charSelect/CharSelectSubState.hx | 1 - 4 files changed, 36 insertions(+), 28 deletions(-) diff --git a/assets b/assets index bc7009b42..4f7e8bb5c 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit bc7009b4242691faa5c4552f7ca8a2f28e8cb1d2 +Subproject commit 4f7e8bb5cd2e9eb8f68d88c060e9cbe5bccc9e2f diff --git a/source/funkin/data/freeplay/player/PlayerData.hx b/source/funkin/data/freeplay/player/PlayerData.hx index a5bf086f6..9110854c8 100644 --- a/source/funkin/data/freeplay/player/PlayerData.hx +++ b/source/funkin/data/freeplay/player/PlayerData.hx @@ -269,7 +269,20 @@ class PlayerCharSelectData * The GF name to assign for this character. */ @:optional - public var assignedGF:Null; + public var gf:PlayerCharSelectGFData; +} + +typedef PlayerCharSelectGFData = +{ + @:optional + public var assetPath:String; + + @:optional + public var animInfoPath:String; + + @:optional + @:default(false) + public var visualizer:Bool; } typedef PlayerResultsData = diff --git a/source/funkin/ui/charSelect/CharSelectGF.hx b/source/funkin/ui/charSelect/CharSelectGF.hx index 79cfb585c..89fc6deb0 100644 --- a/source/funkin/ui/charSelect/CharSelectGF.hx +++ b/source/funkin/ui/charSelect/CharSelectGF.hx @@ -28,7 +28,8 @@ class CharSelectGF extends FlxAtlasSprite implements IBPMSyncedScriptedClass var analyzer:SpectralAnalyzer; - var curGF:String = "gf"; + var currentGFPath:Null; + var enableVisualizer:Bool = false; public function new() { @@ -98,7 +99,7 @@ class CharSelectGF extends FlxAtlasSprite implements IBPMSyncedScriptedClass function drawFFT() { - if (curGF == "nene") + if (enableVisualizer) { var levels = analyzer.getLevels(); var frame = anim.curSymbol.timeline.get("VIZ_bars").get(anim.curFrame); @@ -173,33 +174,33 @@ class CharSelectGF extends FlxAtlasSprite implements IBPMSyncedScriptedClass */ public function switchGF(bf:String):Void { - var prevGF = curGF; + var previousGFPath = currentGFPath; var bfObj = PlayerRegistry.instance.fetchEntry(bf); - curGF = bfObj?.getCharSelectData()?.assignedGF ?? "gf"; - - /*var prevGF:GFChar = curGF; - switch (bf) - { - case "pico": - curGF = NENE; - case "bf": - curGF = GF; - default: - curGF = GF; - }*/ + var gfData = bfObj?.getCharSelectData()?.gf; + currentGFPath = gfData?.assetPath != null ? Paths.animateAtlas(gfData?.assetPath) : null; // We don't need to update any anims if we didn't change GF - if (prevGF != curGF) + trace('currentGFPath(${currentGFPath})'); + if (currentGFPath == null) { - loadAtlas(Paths.animateAtlas("charSelect/" + curGF + "Chill")); + this.visible = false; + return; + } + else if (previousGFPath != currentGFPath) + { + this.visible = true; + loadAtlas(currentGFPath); - animInInfo = FramesJSFLParser.parse(Paths.file("images/charSelect/" + curGF + "AnimInfo/" + curGF + "In.txt")); - animOutInfo = FramesJSFLParser.parse(Paths.file("images/charSelect/" + curGF + "AnimInfo/" + curGF + "Out.txt")); + enableVisualizer = gfData?.visualizer ?? false; + + var animInfoPath = Paths.file('images/${gfData?.animInfoPath}'); + + animInInfo = FramesJSFLParser.parse(animInfoPath + '/In.txt'); + animOutInfo = FramesJSFLParser.parse(animInfoPath + '/Out.txt'); } playAnimation("idle", true, false, false); - // addFrameCallback(getNextFrameLabel("idle"), () -> playAnimation("idle", true, false, false)); updateHitbox(); } @@ -219,8 +220,3 @@ enum FadeStatus FADE_OUT; FADE_IN; } -/*enum abstract GFChar(String) from String to String - { - var GF = "gf"; - var NENE = "nene"; -}*/ diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index 3109dc8f1..e7a87ade6 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -786,7 +786,6 @@ class CharSelectSubState extends MusicBeatSubState && availableChars.exists(getCurrentSelected()) && Save.instance.charactersSeen.contains(availableChars[getCurrentSelected()])) { - gfChill.visible = true; curChar = availableChars.get(getCurrentSelected()); if (!pressedSelect && controls.ACCEPT) From 25cafe7550304d20581da661948fc480ae82c39b Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 19 Sep 2024 04:22:05 -0400 Subject: [PATCH 839/870] Resolve merge issues. --- source/funkin/play/PlayState.hx | 1 - source/funkin/play/components/PopUpStuff.hx | 9 --------- source/funkin/ui/debug/anim/DebugBoundingState.hx | 2 +- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index a25d3b231..1c82eb6b1 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -3046,7 +3046,6 @@ class PlayState extends MusicBeatSubState GameOverSubState.reset(); PauseSubState.reset(); Countdown.reset(); - PopUpStuff.reset(); // Clear the static reference to this state. instance = null; diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx index e5e9b4681..a02291e4e 100644 --- a/source/funkin/play/components/PopUpStuff.hx +++ b/source/funkin/play/components/PopUpStuff.hx @@ -125,13 +125,4 @@ class PopUpStuff extends FlxTypedGroup daLoop++; } } - - /** - * Reset the popup configuration to the default. - */ - public static function reset() - { - noteStyle = NoteStyleRegistry.instance.fetchDefault(); - isPixel = false; - } } diff --git a/source/funkin/ui/debug/anim/DebugBoundingState.hx b/source/funkin/ui/debug/anim/DebugBoundingState.hx index 19391f8d9..d2a27999f 100644 --- a/source/funkin/ui/debug/anim/DebugBoundingState.hx +++ b/source/funkin/ui/debug/anim/DebugBoundingState.hx @@ -77,7 +77,7 @@ class DebugBoundingState extends FlxState { // get the screen position, according to the HUD camera, temp default to FlxG.camera juuust in case? var hudMousePos:FlxPoint = FlxG.mouse.getScreenPosition(hudCam ?? FlxG.camera); - return Screen.instance.hasSolidComponentUnderPoint(hudMousePos.x, hudMousePos.y) || FlxG.mouse.overlaps(animDropDownMenu, hudCam); + return Screen.instance.hasSolidComponentUnderPoint(hudMousePos.x, hudMousePos.y); } override function create() From 3cbba8ba29dda790597e29e01c9e7d620953169d Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 19 Sep 2024 04:22:05 -0400 Subject: [PATCH 840/870] Resolve merge issues. --- source/funkin/play/PlayState.hx | 1 - source/funkin/play/components/PopUpStuff.hx | 9 --------- source/funkin/ui/debug/anim/DebugBoundingState.hx | 2 +- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index a25d3b231..1c82eb6b1 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -3046,7 +3046,6 @@ class PlayState extends MusicBeatSubState GameOverSubState.reset(); PauseSubState.reset(); Countdown.reset(); - PopUpStuff.reset(); // Clear the static reference to this state. instance = null; diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx index e5e9b4681..a02291e4e 100644 --- a/source/funkin/play/components/PopUpStuff.hx +++ b/source/funkin/play/components/PopUpStuff.hx @@ -125,13 +125,4 @@ class PopUpStuff extends FlxTypedGroup daLoop++; } } - - /** - * Reset the popup configuration to the default. - */ - public static function reset() - { - noteStyle = NoteStyleRegistry.instance.fetchDefault(); - isPixel = false; - } } diff --git a/source/funkin/ui/debug/anim/DebugBoundingState.hx b/source/funkin/ui/debug/anim/DebugBoundingState.hx index 19391f8d9..d2a27999f 100644 --- a/source/funkin/ui/debug/anim/DebugBoundingState.hx +++ b/source/funkin/ui/debug/anim/DebugBoundingState.hx @@ -77,7 +77,7 @@ class DebugBoundingState extends FlxState { // get the screen position, according to the HUD camera, temp default to FlxG.camera juuust in case? var hudMousePos:FlxPoint = FlxG.mouse.getScreenPosition(hudCam ?? FlxG.camera); - return Screen.instance.hasSolidComponentUnderPoint(hudMousePos.x, hudMousePos.y) || FlxG.mouse.overlaps(animDropDownMenu, hudCam); + return Screen.instance.hasSolidComponentUnderPoint(hudMousePos.x, hudMousePos.y); } override function create() From b03c8a9cf8cfe8c00d88ed64d488dceac4992378 Mon Sep 17 00:00:00 2001 From: Kade <26305836+Kade-github@users.noreply.github.com> Date: Thu, 19 Sep 2024 00:02:59 -0700 Subject: [PATCH 841/870] Limit the song time to 0 and the songs max length use the new bool to tell if we should start the song add a public static bool to countdown: finished --- source/funkin/Conductor.hx | 10 +++++++--- source/funkin/play/Countdown.hx | 7 +++++++ source/funkin/play/PlayState.hx | 20 ++++++++++++++------ 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/source/funkin/Conductor.hx b/source/funkin/Conductor.hx index e73b2860c..3211f31f5 100644 --- a/source/funkin/Conductor.hx +++ b/source/funkin/Conductor.hx @@ -397,9 +397,12 @@ class Conductor */ public function update(?songPos:Float, applyOffsets:Bool = true, forceDispatch:Bool = false) { + var currentTime:Float = (FlxG.sound.music != null) ? FlxG.sound.music.time : 0.0; + var currentLength:Float = (FlxG.sound.music != null) ? FlxG.sound.music.length : 0.0; + if (songPos == null) { - songPos = (FlxG.sound.music != null) ? FlxG.sound.music.time : 0.0; + songPos = currentTime; } // Take into account instrumental and file format song offsets. @@ -410,7 +413,7 @@ class Conductor var oldStep:Float = this.currentStep; // Set the song position we are at (for purposes of calculating note positions, etc). - this.songPosition = songPos; + this.songPosition = Math.min(currentLength, Math.max(0, songPos)); currentTimeChange = timeChanges[0]; if (this.songPosition > 0.0) @@ -430,7 +433,8 @@ class Conductor else if (currentTimeChange != null && this.songPosition > 0.0) { // roundDecimal prevents representing 8 as 7.9999999 - this.currentStepTime = FlxMath.roundDecimal((currentTimeChange.beatTime * Constants.STEPS_PER_BEAT) + (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); diff --git a/source/funkin/play/Countdown.hx b/source/funkin/play/Countdown.hx index 643883a43..c883006a0 100644 --- a/source/funkin/play/Countdown.hx +++ b/source/funkin/play/Countdown.hx @@ -29,6 +29,11 @@ class Countdown */ public static var soundSuffix:String = ''; + /** + * Whether the countdown has finished. + */ + public static var finished:Bool = false; + /** * Which alternate graphic on countdown to use. * You can set this via script. @@ -53,6 +58,7 @@ class Countdown */ public static function performCountdown():Bool { + finished = false; countdownStep = BEFORE; var cancelled:Bool = propagateCountdownEvent(countdownStep); if (cancelled) @@ -101,6 +107,7 @@ class Countdown if (countdownStep == AFTER) { + finished = true; stopCountdown(); } }, 5); // Before, 3, 2, 1, GO!, After diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 0b2b8846d..06dd5f95e 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -915,7 +915,11 @@ class PlayState extends MusicBeatSubState { // Do NOT apply offsets at this point, because they already got applied the previous frame! Conductor.instance.update(Conductor.instance.songPosition + elapsed * 1000, false); - if (Conductor.instance.songPosition >= (startTimestamp)) startSong(); + if (Conductor.instance.songPosition - Conductor.instance.instrumentalOffset >= (startTimestamp) && Countdown.finished) + { + trace("started song at " + Conductor.instance.songPosition); + startSong(); + } } } else @@ -1391,14 +1395,16 @@ class PlayState extends MusicBeatSubState // activeNotes.sort(SortUtil.byStrumtime, FlxSort.DESCENDING); } + var correctSync:Float = Math.min(FlxG.sound.music.length, Math.max(0, Conductor.instance.songPosition - Conductor.instance.instrumentalOffset)); + if (!startingSong && FlxG.sound.music != null - && (Math.abs(FlxG.sound.music.time - (Conductor.instance.songPosition + Conductor.instance.instrumentalOffset)) > 100 - || Math.abs(vocals.checkSyncError(Conductor.instance.songPosition + Conductor.instance.instrumentalOffset)) > 100)) + && (Math.abs(FlxG.sound.music.time - correctSync) > 100 || Math.abs(vocals.checkSyncError(correctSync)) > 100)) { trace("VOCALS NEED RESYNC"); - if (vocals != null) trace(vocals.checkSyncError(Conductor.instance.songPosition + Conductor.instance.instrumentalOffset)); - trace(FlxG.sound.music.time - (Conductor.instance.songPosition + Conductor.instance.instrumentalOffset)); + if (vocals != null) trace(vocals.checkSyncError(correctSync)); + trace(FlxG.sound.music.time); + trace(correctSync); resyncVocals(); } @@ -1993,7 +1999,9 @@ class PlayState extends MusicBeatSubState // Skip this if the music is paused (GameOver, Pause menu, start-of-song offset, etc.) if (!(FlxG.sound.music?.playing ?? false)) return; - var timeToPlayAt:Float = Conductor.instance.songPosition - Conductor.instance.instrumentalOffset; + + var timeToPlayAt:Float = Math.min(FlxG.sound.music.length, Math.max(0, Conductor.instance.songPosition - Conductor.instance.instrumentalOffset)); + trace('Resyncing vocals to ${timeToPlayAt}'); FlxG.sound.music.pause(); vocals.pause(); From 4d73e0cc475f7195261cfff3592eb01b9192aac2 Mon Sep 17 00:00:00 2001 From: Kade <26305836+Kade-github@users.noreply.github.com> Date: Thu, 19 Sep 2024 01:20:16 -0700 Subject: [PATCH 842/870] fix some interesting issues with this redundant trace removal --- source/funkin/Conductor.hx | 11 ++++++++++- source/funkin/play/Countdown.hx | 7 ------- source/funkin/play/PlayState.hx | 29 +++++++++++++++++------------ 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/source/funkin/Conductor.hx b/source/funkin/Conductor.hx index 3211f31f5..bd7c7196f 100644 --- a/source/funkin/Conductor.hx +++ b/source/funkin/Conductor.hx @@ -412,8 +412,17 @@ class Conductor var oldBeat:Float = this.currentBeat; var oldStep:Float = this.currentStep; + // If the song is playing, limit the song position to the length of the song or beginning of the song. + if (FlxG.sound.music != null && FlxG.sound.music.playing) + { + this.songPosition = Math.min(currentLength, Math.max(0, songPos)); + } + else + { + this.songPosition = songPos; + } + // Set the song position we are at (for purposes of calculating note positions, etc). - this.songPosition = Math.min(currentLength, Math.max(0, songPos)); currentTimeChange = timeChanges[0]; if (this.songPosition > 0.0) diff --git a/source/funkin/play/Countdown.hx b/source/funkin/play/Countdown.hx index c883006a0..643883a43 100644 --- a/source/funkin/play/Countdown.hx +++ b/source/funkin/play/Countdown.hx @@ -29,11 +29,6 @@ class Countdown */ public static var soundSuffix:String = ''; - /** - * Whether the countdown has finished. - */ - public static var finished:Bool = false; - /** * Which alternate graphic on countdown to use. * You can set this via script. @@ -58,7 +53,6 @@ class Countdown */ public static function performCountdown():Bool { - finished = false; countdownStep = BEFORE; var cancelled:Bool = propagateCountdownEvent(countdownStep); if (cancelled) @@ -107,7 +101,6 @@ class Countdown if (countdownStep == AFTER) { - finished = true; stopCountdown(); } }, 5); // Before, 3, 2, 1, GO!, After diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 06dd5f95e..4e81d3a83 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -687,7 +687,11 @@ class PlayState extends MusicBeatSubState } Conductor.instance.mapTimeChanges(currentChart.timeChanges); - Conductor.instance.update((Conductor.instance.beatLengthMs * -5) + startTimestamp); + var pre:Float = (Conductor.instance.beatLengthMs * -5) + startTimestamp; + + trace('Attempting to start at ' + pre); + + Conductor.instance.update(pre); // The song is now loaded. We can continue to initialize the play state. initCameras(); @@ -915,7 +919,7 @@ class PlayState extends MusicBeatSubState { // Do NOT apply offsets at this point, because they already got applied the previous frame! Conductor.instance.update(Conductor.instance.songPosition + elapsed * 1000, false); - if (Conductor.instance.songPosition - Conductor.instance.instrumentalOffset >= (startTimestamp) && Countdown.finished) + if (Conductor.instance.songPosition >= (startTimestamp + Conductor.instance.instrumentalOffset)) { trace("started song at " + Conductor.instance.songPosition); startSong(); @@ -1395,17 +1399,18 @@ class PlayState extends MusicBeatSubState // activeNotes.sort(SortUtil.byStrumtime, FlxSort.DESCENDING); } - var correctSync:Float = Math.min(FlxG.sound.music.length, Math.max(0, Conductor.instance.songPosition - Conductor.instance.instrumentalOffset)); - - if (!startingSong - && FlxG.sound.music != null - && (Math.abs(FlxG.sound.music.time - correctSync) > 100 || Math.abs(vocals.checkSyncError(correctSync)) > 100)) + if (FlxG.sound.music != null) { - trace("VOCALS NEED RESYNC"); - if (vocals != null) trace(vocals.checkSyncError(correctSync)); - trace(FlxG.sound.music.time); - trace(correctSync); - resyncVocals(); + var correctSync:Float = Math.min(FlxG.sound.music.length, Math.max(0, Conductor.instance.songPosition - Conductor.instance.instrumentalOffset)); + + if (!startingSong && (Math.abs(FlxG.sound.music.time - correctSync) > 100 || Math.abs(vocals.checkSyncError(correctSync)) > 100)) + { + trace("VOCALS NEED RESYNC"); + if (vocals != null) trace(vocals.checkSyncError(correctSync)); + trace(FlxG.sound.music.time); + trace(correctSync); + resyncVocals(); + } } // Only bop camera if zoom level is below 135% From a8aeae4f7fa97d99310a327cc0f218e404662d2c Mon Sep 17 00:00:00 2001 From: Kade <26305836+Kade-github@users.noreply.github.com> Date: Thu, 19 Sep 2024 10:24:02 -0700 Subject: [PATCH 843/870] do not include offset in vocal (they're offset by inst) Fix a tiny little issue with vocal resync @ start --- 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 4e81d3a83..96bce85e5 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1979,6 +1979,7 @@ class PlayState extends MusicBeatSubState vocals.play(); vocals.volume = 1.0; vocals.pitch = playbackRate; + vocals.time = startTimestamp; resyncVocals(); #if FEATURE_DISCORD_RPC From f9186b67a7df74f81137374f9d0972114fa4b786 Mon Sep 17 00:00:00 2001 From: Kade <26305836+Kade-github@users.noreply.github.com> Date: Thu, 19 Sep 2024 17:00:52 -0700 Subject: [PATCH 844/870] less tolerance --- 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 96bce85e5..e2bff164e 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1403,7 +1403,7 @@ class PlayState extends MusicBeatSubState { var correctSync:Float = Math.min(FlxG.sound.music.length, Math.max(0, Conductor.instance.songPosition - Conductor.instance.instrumentalOffset)); - if (!startingSong && (Math.abs(FlxG.sound.music.time - correctSync) > 100 || Math.abs(vocals.checkSyncError(correctSync)) > 100)) + if (!startingSong && (Math.abs(FlxG.sound.music.time - correctSync) > 5 || Math.abs(vocals.checkSyncError(correctSync)) > 5)) { trace("VOCALS NEED RESYNC"); if (vocals != null) trace(vocals.checkSyncError(correctSync)); From 9045ae2d9c65b870bb8079f69e94209050c70127 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 20 Sep 2024 00:25:38 -0400 Subject: [PATCH 845/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 252d48f4c..b029e0678 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 252d48f4c996d5832cb981fb2f3ed945c020f289 +Subproject commit b029e067835b80be35ee4de149ac3c6cf2bb4c4c From 143ef88e6ff5a680328099e9f253e644ea9b81ac Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 20 Sep 2024 03:42:48 -0400 Subject: [PATCH 846/870] Update assets submodule --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 252d48f4c..2c9025b00 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 252d48f4c996d5832cb981fb2f3ed945c020f289 +Subproject commit 2c9025b007b3823807404b73a11035c41e032e50 From 5f64d89d0e47f7c062f746ed8880b6287748a351 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 20 Sep 2024 16:51:21 -0400 Subject: [PATCH 847/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 2c9025b00..41980de1c 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 2c9025b007b3823807404b73a11035c41e032e50 +Subproject commit 41980de1c2ec851ce99a33cb397ba0550b68ea2d From 78cde16af29f4f4ef5ef2cc3563592aeb1769528 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 20 Sep 2024 18:10:47 -0400 Subject: [PATCH 848/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 4f7e8bb5c..2a0bc4f66 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 4f7e8bb5cd2e9eb8f68d88c060e9cbe5bccc9e2f +Subproject commit 2a0bc4f66d79a6f590e7ed2c04884d8c1fa8c45e From a41d3033d5e7f518b3db1cd5943105bb22260052 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 20 Sep 2024 18:20:40 -0400 Subject: [PATCH 849/870] small Assets -> OpenFLAssets fix --- source/funkin/ui/transition/LoadingState.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/transition/LoadingState.hx b/source/funkin/ui/transition/LoadingState.hx index 3b4661425..f3620c893 100644 --- a/source/funkin/ui/transition/LoadingState.hx +++ b/source/funkin/ui/transition/LoadingState.hx @@ -276,7 +276,7 @@ class LoadingState extends MusicBeatSubState #if NO_PRELOAD_ALL static function isSoundLoaded(path:String):Bool { - return Assets.cache.hasSound(path); + return OpenFLAssets.cache.hasSound(path); } static function isLibraryLoaded(library:String):Bool From 690f3090b728a84a91e2878412eaf9049c1d8116 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 20 Sep 2024 20:11:12 -0400 Subject: [PATCH 850/870] proper audio scaling for hxcodec / desktop --- .../graphics/video/FunkinVideoSprite.hx | 32 +++++++++++++++++++ source/funkin/play/cutscene/VideoCutscene.hx | 6 ++-- source/funkin/ui/charSelect/IntroSubState.hx | 6 ++-- source/funkin/ui/title/AttractState.hx | 6 ++-- 4 files changed, 41 insertions(+), 9 deletions(-) create mode 100644 source/funkin/graphics/video/FunkinVideoSprite.hx diff --git a/source/funkin/graphics/video/FunkinVideoSprite.hx b/source/funkin/graphics/video/FunkinVideoSprite.hx new file mode 100644 index 000000000..e0086784b --- /dev/null +++ b/source/funkin/graphics/video/FunkinVideoSprite.hx @@ -0,0 +1,32 @@ +package funkin.graphics.video; + +import hxcodec.flixel.FlxVideoSprite; + +/** + * Not to be confused with FlxVideo, this is a hxcodec based video class + * We override it simply to correct/control our volume easier. + */ +class FunkinVideoSprite extends FlxVideoSprite +{ + public var volume(default, set):Float = 1; + + public function new(x:Float = 0, y:Float = 0) + { + super(x, y); + + set_volume(1); + } + + override public function update(elapsed:Float):Void + { + super.update(elapsed); + set_volume(volume); + } + + function set_volume(value:Float):Float + { + volume = value; + bitmap.volume = Std.int((FlxG.sound.muted ? 0 : 1) * (FlxG.sound.logToLinear(FlxG.sound.volume) * 100) * volume); + return volume; + } +} diff --git a/source/funkin/play/cutscene/VideoCutscene.hx b/source/funkin/play/cutscene/VideoCutscene.hx index 60454b881..b6e04004b 100644 --- a/source/funkin/play/cutscene/VideoCutscene.hx +++ b/source/funkin/play/cutscene/VideoCutscene.hx @@ -11,7 +11,7 @@ import flixel.util.FlxTimer; import funkin.graphics.video.FlxVideo; #end #if hxCodec -import hxcodec.flixel.FlxVideoSprite; +import funkin.graphics.video.FunkinVideoSprite; #end /** @@ -26,7 +26,7 @@ class VideoCutscene static var vid:FlxVideo; #end #if hxCodec - static var vid:FlxVideoSprite; + static var vid:FunkinVideoSprite; #end /** @@ -138,7 +138,7 @@ class VideoCutscene static function playVideoNative(filePath:String):Void { // Video displays OVER the FlxState. - vid = new FlxVideoSprite(0, 0); + vid = new FunkinVideoSprite(0, 0); if (vid != null) { diff --git a/source/funkin/ui/charSelect/IntroSubState.hx b/source/funkin/ui/charSelect/IntroSubState.hx index 2c2908473..e731e5e9a 100644 --- a/source/funkin/ui/charSelect/IntroSubState.hx +++ b/source/funkin/ui/charSelect/IntroSubState.hx @@ -4,7 +4,7 @@ package funkin.ui.charSelect; import funkin.graphics.video.FlxVideo; #end #if hxCodec -import hxcodec.flixel.FlxVideoSprite; +import funkin.graphics.video.FunkinVideoSprite; #end import funkin.ui.MusicBeatSubState; import funkin.audio.FunkinSound; @@ -72,12 +72,12 @@ class IntroSubState extends MusicBeatSubState #end #if hxCodec - var vid:FlxVideoSprite; + var vid:FunkinVideoSprite; function playVideoNative(filePath:String):Void { // Video displays OVER the FlxState. - vid = new FlxVideoSprite(0, 0); + vid = new FunkinVideoSprite(0, 0); vid.scrollFactor.set(); diff --git a/source/funkin/ui/title/AttractState.hx b/source/funkin/ui/title/AttractState.hx index c5a3d0504..f5f266b0d 100644 --- a/source/funkin/ui/title/AttractState.hx +++ b/source/funkin/ui/title/AttractState.hx @@ -4,7 +4,7 @@ package funkin.ui.title; import funkin.graphics.video.FlxVideo; #end #if hxCodec -import hxcodec.flixel.FlxVideoSprite; +import funkin.graphics.video.FunkinVideoSprite; #end import funkin.ui.MusicBeatState; @@ -62,12 +62,12 @@ class AttractState extends MusicBeatState #end #if hxCodec - var vid:FlxVideoSprite; + var vid:FunkinVideoSprite; function playVideoNative(filePath:String):Void { // Video displays OVER the FlxState. - vid = new FlxVideoSprite(0, 0); + vid = new FunkinVideoSprite(0, 0); if (vid != null) { From 2c73b241e8f7f6be5a4af7b4a5f180bb8444c199 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 21 Sep 2024 06:33:47 -0400 Subject: [PATCH 851/870] Rework offset+vocal sync handling to fix the "Swing Mode" bug --- source/funkin/Conductor.hx | 7 +++++++ source/funkin/play/PlayState.hx | 25 +++++++++++++++++-------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/source/funkin/Conductor.hx b/source/funkin/Conductor.hx index bd7c7196f..ff72b1e12 100644 --- a/source/funkin/Conductor.hx +++ b/source/funkin/Conductor.hx @@ -275,6 +275,13 @@ class Conductor return Save.instance.options.audioVisualOffset; } + public var combinedOffset(get, never):Float; + + function get_combinedOffset():Float + { + return instrumentalOffset + audioVisualOffset + inputOffset; + } + /** * The number of beats in a measure. May be fractional depending on the time signature. */ diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index e2bff164e..ad52dd6e6 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -861,7 +861,7 @@ class PlayState extends MusicBeatSubState // Reset music properly. if (FlxG.sound.music != null) { - FlxG.sound.music.time = startTimestamp - Conductor.instance.instrumentalOffset; + FlxG.sound.music.time = startTimestamp - Conductor.instance.combinedOffset; FlxG.sound.music.pitch = playbackRate; FlxG.sound.music.pause(); } @@ -878,7 +878,7 @@ class PlayState extends MusicBeatSubState } } vocals.pause(); - vocals.time = 0; + vocals.time = 0 - Conductor.instance.combinedOffset; if (FlxG.sound.music != null) FlxG.sound.music.volume = 1; vocals.volume = 1; @@ -919,7 +919,7 @@ class PlayState extends MusicBeatSubState { // Do NOT apply offsets at this point, because they already got applied the previous frame! Conductor.instance.update(Conductor.instance.songPosition + elapsed * 1000, false); - if (Conductor.instance.songPosition >= (startTimestamp + Conductor.instance.instrumentalOffset)) + if (Conductor.instance.songPosition >= (startTimestamp + Conductor.instance.combinedOffset)) { trace("started song at " + Conductor.instance.songPosition); startSong(); @@ -1401,7 +1401,7 @@ class PlayState extends MusicBeatSubState if (FlxG.sound.music != null) { - var correctSync:Float = Math.min(FlxG.sound.music.length, Math.max(0, Conductor.instance.songPosition - Conductor.instance.instrumentalOffset)); + var correctSync:Float = Math.min(FlxG.sound.music.length, Math.max(0, Conductor.instance.songPosition - Conductor.instance.combinedOffset)); if (!startingSong && (Math.abs(FlxG.sound.music.time - correctSync) > 5 || Math.abs(vocals.checkSyncError(correctSync)) > 5)) { @@ -1411,6 +1411,13 @@ class PlayState extends MusicBeatSubState trace(correctSync); resyncVocals(); } + else + { + trace("NO VOCAL SYNC NEEDED"); + if (vocals != null) trace(vocals.checkSyncError(correctSync)); + trace(FlxG.sound.music.time); + trace(correctSync); + } } // Only bop camera if zoom level is below 135% @@ -1967,7 +1974,7 @@ class PlayState extends MusicBeatSubState }; // A negative instrumental offset means the song skips the first few milliseconds of the track. // This just gets added into the startTimestamp behavior so we don't need to do anything extra. - FlxG.sound.music.play(true, startTimestamp - Conductor.instance.instrumentalOffset); + FlxG.sound.music.play(true, Math.max(0, startTimestamp - Conductor.instance.combinedOffset)); FlxG.sound.music.pitch = playbackRate; // Prevent the volume from being wrong. @@ -1979,7 +1986,9 @@ class PlayState extends MusicBeatSubState vocals.play(); vocals.volume = 1.0; vocals.pitch = playbackRate; - vocals.time = startTimestamp; + vocals.time = FlxG.sound.music.time; + trace('${FlxG.sound.music.time}'); + trace('${vocals.time}'); resyncVocals(); #if FEATURE_DISCORD_RPC @@ -1989,7 +1998,7 @@ class PlayState extends MusicBeatSubState if (startTimestamp > 0) { - // FlxG.sound.music.time = startTimestamp - Conductor.instance.instrumentalOffset; + // FlxG.sound.music.time = startTimestamp - Conductor.instance.combinedOffset; handleSkippedNotes(); } @@ -2006,7 +2015,7 @@ class PlayState extends MusicBeatSubState // Skip this if the music is paused (GameOver, Pause menu, start-of-song offset, etc.) if (!(FlxG.sound.music?.playing ?? false)) return; - var timeToPlayAt:Float = Math.min(FlxG.sound.music.length, Math.max(0, Conductor.instance.songPosition - Conductor.instance.instrumentalOffset)); + var timeToPlayAt:Float = Math.min(FlxG.sound.music.length, Math.max(0, Conductor.instance.songPosition - Conductor.instance.combinedOffset)); trace('Resyncing vocals to ${timeToPlayAt}'); FlxG.sound.music.pause(); vocals.pause(); From 01e9888839d8d498ba9868c96b52c2e5253a8d10 Mon Sep 17 00:00:00 2001 From: JVN-Pixels <146671762+JVNpixels@users.noreply.github.com> Date: Sat, 21 Sep 2024 10:07:41 -0700 Subject: [PATCH 852/870] Update CHANGELOG.md Fixes changelog for the 0.5.0 update! --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2031ba24..469ba9bd0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,14 +10,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Modding isn't 100% there but we're working on it! - Added Pico as a playable character! Unlock him by completing Weekend 1 (if you haven't already done that) - The songs from Weekend 1 have moved; you must now switch to Pico in Freeplay to access them -- Added 10 new Pico remixes! Access them by selecting Pico from in the Character Select screen +- Added 11 new Pico remixes! Access them by selecting Pico from in the Character Select screen - Bopeebo (Pico Mix) - Fresh (Pico Mix) - DadBattle (Pico Mix) - Spookeez (Pico Mix) - South (Pico Mix) + - Pico (Pico Mix) - Philly Nice (Pico Mix) - - Blammed (Pico Mix) + - Blammed (Pico Mix) - Eggnog (Pico Mix) - Ugh (Pico Mix) - Guns (Pico Mix) From ec8ecc616343bf52a2b3837c2a661f4402981b24 Mon Sep 17 00:00:00 2001 From: JVN-Pixels <146671762+JVNpixels@users.noreply.github.com> Date: Sat, 21 Sep 2024 10:14:09 -0700 Subject: [PATCH 853/870] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 469ba9bd0..e4053c1e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Eggnog (Pico Mix) - Ugh (Pico Mix) - Guns (Pico Mix) -- Added 1 new Boyfriend remix! Access it by selecting Pico from in the Character Select screen +- Added 1 new Boyfriend remix! Access it by completing Weekend 1 as Pico and then selecting Boyfriend from in the Character Select screen - Darnell (BF Mix) - Added 2 new Erect remixes! Access them by switching difficulty on the song - Cocoa Erect From e535ae4ca61c05e0b44e5d5b76523f76629f145d Mon Sep 17 00:00:00 2001 From: JVN-Pixels <146671762+JVNpixels@users.noreply.github.com> Date: Sat, 21 Sep 2024 10:19:00 -0700 Subject: [PATCH 854/870] Change line 12 The songs from Weekend 1 have moved line --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4053c1e5..66926bd13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added a new Character Select screen to switch between playable characters in Freeplay - Modding isn't 100% there but we're working on it! - Added Pico as a playable character! Unlock him by completing Weekend 1 (if you haven't already done that) - - The songs from Weekend 1 have moved; you must now switch to Pico in Freeplay to access them + - The songs from Weekend 1 have moved; you must now switch to Pico via Character Select screen in Freeplay to access them - Added 11 new Pico remixes! Access them by selecting Pico from in the Character Select screen - Bopeebo (Pico Mix) - Fresh (Pico Mix) From 3601b50e322d46e1f3fbfc94f3825f03de18c442 Mon Sep 17 00:00:00 2001 From: JVN-Pixels <146671762+JVNpixels@users.noreply.github.com> Date: Sat, 21 Sep 2024 10:29:08 -0700 Subject: [PATCH 855/870] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66926bd13..a21455ef5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - These display on Pico remixes, as well as when playing Weekend 1. - Implemented support for scripted Note Kinds. You can use HScript define a different note style to display for these notes as well as custom behavior. (community feature by lemz1) - Implemented support for Numeric and Selector options in the Options menu. (community feature by FlooferLand) +- Implemented new animations for Tankman and Pico ## Changed - Girlfriend and Nene now perform previously unused animations when you achieve a large combo, or drop a large combo. - The pixel character icons in the Freeplay menu now display an animation! From e978f5df7624781f2b179a9039110fe818e896ba Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sat, 21 Sep 2024 16:32:44 -0400 Subject: [PATCH 856/870] fix for spirit's trail --- assets | 2 +- hmm.json | 4 +-- source/funkin/effects/FunkTrail.hx | 40 ++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 source/funkin/effects/FunkTrail.hx diff --git a/assets b/assets index 72bb24ac9..59546b1ac 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 72bb24ac9b0b9db4b2f9c38ef091e146ef16a1a4 +Subproject commit 59546b1ac78f591d1f7403b7a2209278bedfe63d diff --git a/hmm.json b/hmm.json index bbe4897b7..c6e3e7115 100644 --- a/hmm.json +++ b/hmm.json @@ -25,7 +25,7 @@ "name": "flixel-addons", "type": "git", "dir": null, - "ref": "9c6fb47968e894eb36bf10e94725cd7640c49281", + "ref": "e7789a32cf068eaa0abcaebc8dc07f6cf8f0632c", "url": "https://github.com/FunkinCrew/flixel-addons" }, { @@ -205,4 +205,4 @@ "url": "https://github.com/fponticelli/thx.semver" } ] -} +} \ No newline at end of file diff --git a/source/funkin/effects/FunkTrail.hx b/source/funkin/effects/FunkTrail.hx new file mode 100644 index 000000000..021a0e9b4 --- /dev/null +++ b/source/funkin/effects/FunkTrail.hx @@ -0,0 +1,40 @@ +package funkin.effects; + +import flixel.addons.effects.FlxTrail; +import funkin.play.stage.Bopper; +import flixel.FlxSprite; +import flixel.system.FlxAssets; + +/** + * An offshoot of FlxTrail, but accomodates the way Funkin + * does offsets for characters. example, fixes Spirits trail + */ +class FunkTrail extends FlxTrail +{ + /** + * Creates a new FunkTrail effect for a specific FlxSprite. + * + * @param Target The FlxSprite the trail is attached to. + * @param Graphic The image to use for the trailsprites. Optional, uses the sprite's graphic if null. + * @param Length The amount of trailsprites to create. + * @param Delay How often to update the trail. 0 updates every frame. + * @param Alpha The alpha value for the very first trailsprite. + * @param Diff How much lower the alpha of the next trailsprite is. + */ + public function new(Target:FlxSprite, ?Graphic:FlxGraphicAsset, Length:Int = 10, Delay:Int = 3, Alpha:Float = 0.4, Diff:Float = 0.05) + { + super(Target, Graphic, Length, Delay, Alpha, Diff); + } + + override public function updateTrail():Void + { + if (target is Bopper) + { + var targ:Bopper = cast target; + @:privateAccess effectOffset.set((targ.animOffsets[0] - targ.globalOffsets[0]) * targ.scale.x, + (targ.animOffsets[1] - targ.globalOffsets[1]) * targ.scale.y); + } + + super.updateTrail(); + } +} From 6c743b3b89b278f8250061b5110c28d1852a91b5 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 21 Sep 2024 20:33:51 -0400 Subject: [PATCH 857/870] Remove some spammy trace calls. --- source/funkin/play/PlayState.hx | 11 ++--------- source/funkin/play/components/PopUpStuff.hx | 1 - source/funkin/ui/mainmenu/MainMenuState.hx | 2 ++ 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index ad52dd6e6..9b6015b67 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1411,13 +1411,6 @@ class PlayState extends MusicBeatSubState trace(correctSync); resyncVocals(); } - else - { - trace("NO VOCAL SYNC NEEDED"); - if (vocals != null) trace(vocals.checkSyncError(correctSync)); - trace(FlxG.sound.music.time); - trace(correctSync); - } } // Only bop camera if zoom level is below 135% @@ -2396,9 +2389,9 @@ class PlayState extends MusicBeatSubState if (targetNote == null) continue; // Judge and hit the note. - trace('Hit note! ${targetNote.noteData}'); + // trace('Hit note! ${targetNote.noteData}'); goodNoteHit(targetNote, input); - trace('Score: ${songScore}'); + // trace('Score: ${songScore}'); notesInDirection.remove(targetNote); diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx index a02291e4e..7ea5650f1 100644 --- a/source/funkin/play/components/PopUpStuff.hx +++ b/source/funkin/play/components/PopUpStuff.hx @@ -95,7 +95,6 @@ class PopUpStuff extends FlxTypedGroup if (numScore == null) continue; numScore.x = (FlxG.width * 0.507) - (36 * daLoop) - 65; - trace('numScore($daLoop) = ${numScore.x}'); numScore.y = (FlxG.camera.height * 0.44); numScore.x += offsets[0]; diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index 13d68da6d..3f36dad81 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -344,6 +344,8 @@ class MainMenuState extends MusicBeatState } } + Conductor.instance.update(); + // Open the debug menu, defaults to ` / ~ // This includes stuff like the Chart Editor, so it should be present on all builds. if (controls.DEBUG_MENU) From 5548fd52f4458520935814ac241a6a079fe72beb Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 21 Sep 2024 20:33:59 -0400 Subject: [PATCH 858/870] Update default mod so it actually loads --- example_mods/introMod/_polymod_meta.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example_mods/introMod/_polymod_meta.json b/example_mods/introMod/_polymod_meta.json index 4dc0cd804..74c4a2504 100644 --- a/example_mods/introMod/_polymod_meta.json +++ b/example_mods/introMod/_polymod_meta.json @@ -6,7 +6,7 @@ "name": "EliteMasterEric" } ], - "api_version": "0.1.0", + "api_version": "0.5.0", "mod_version": "1.0.0", "license": "Apache-2.0" } From 29a7005d8a5ca63f69531792b86d9ec457efae09 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sun, 22 Sep 2024 00:44:57 -0400 Subject: [PATCH 859/870] Fix a bug where you can hear the game a little when setting the volume to 0 ticks --- source/funkin/ui/options/FunkinSoundTray.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/options/FunkinSoundTray.hx b/source/funkin/ui/options/FunkinSoundTray.hx index 8ae53524a..eea30ae17 100644 --- a/source/funkin/ui/options/FunkinSoundTray.hx +++ b/source/funkin/ui/options/FunkinSoundTray.hx @@ -121,7 +121,7 @@ class FunkinSoundTray extends FlxSoundTray active = true; var globalVolume:Int = Math.round(FlxG.sound.logToLinear(FlxG.sound.volume) * 10); - if (FlxG.sound.muted) + if (FlxG.sound.muted || FlxG.sound.volume == 0) { globalVolume = 0; } From c7238fcfd114352924a6cca436e069523a86cced Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sun, 22 Sep 2024 00:45:30 -0400 Subject: [PATCH 860/870] Stop the volume tray from hiding as long as the game is muted --- source/funkin/ui/options/FunkinSoundTray.hx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/funkin/ui/options/FunkinSoundTray.hx b/source/funkin/ui/options/FunkinSoundTray.hx index eea30ae17..b2fb7fc04 100644 --- a/source/funkin/ui/options/FunkinSoundTray.hx +++ b/source/funkin/ui/options/FunkinSoundTray.hx @@ -79,10 +79,12 @@ class FunkinSoundTray extends FlxSoundTray y = MathUtil.coolLerp(y, lerpYPos, 0.1); alpha = MathUtil.coolLerp(alpha, alphaTarget, 0.25); + var shouldHide = (FlxG.sound.muted == false && FlxG.sound.volume > 0); + // Animate sound tray thing if (_timer > 0) { - _timer -= (MS / 1000); + if (shouldHide) _timer -= (MS / 1000); alphaTarget = 1; } else if (y >= -height) From 58508755f99600a676c8424389e9c776e4ef3c2d Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sun, 22 Sep 2024 10:57:00 -0400 Subject: [PATCH 861/870] revert extra flxtrail function --- hmm.json | 2 +- source/funkin/effects/FunkTrail.hx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hmm.json b/hmm.json index c6e3e7115..bf4f39fea 100644 --- a/hmm.json +++ b/hmm.json @@ -25,7 +25,7 @@ "name": "flixel-addons", "type": "git", "dir": null, - "ref": "e7789a32cf068eaa0abcaebc8dc07f6cf8f0632c", + "ref": "7424db4e9164ff46f224a7c47de1b732d2542dd7", "url": "https://github.com/FunkinCrew/flixel-addons" }, { diff --git a/source/funkin/effects/FunkTrail.hx b/source/funkin/effects/FunkTrail.hx index 021a0e9b4..9633f830f 100644 --- a/source/funkin/effects/FunkTrail.hx +++ b/source/funkin/effects/FunkTrail.hx @@ -26,7 +26,7 @@ class FunkTrail extends FlxTrail super(Target, Graphic, Length, Delay, Alpha, Diff); } - override public function updateTrail():Void + override public function update(elapsed:Float):Void { if (target is Bopper) { @@ -35,6 +35,6 @@ class FunkTrail extends FlxTrail (targ.animOffsets[1] - targ.globalOffsets[1]) * targ.scale.y); } - super.updateTrail(); + super.update(elapsed); } } From 0bf1bead03f1b477ebbd82781283e63cf6c2a3e9 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sun, 22 Sep 2024 12:14:15 -0400 Subject: [PATCH 862/870] Fix some issues causing the Input Offsets view to crash on web. --- source/funkin/play/notes/notestyle/NoteStyle.hx | 6 +++++- source/funkin/ui/debug/latency/LatencyState.hx | 12 ++++++++++-- source/funkin/ui/options/OptionsState.hx | 5 +++++ source/funkin/ui/transition/LoadingState.hx | 5 +++++ 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/source/funkin/play/notes/notestyle/NoteStyle.hx b/source/funkin/play/notes/notestyle/NoteStyle.hx index c2f7ec009..3318e9086 100644 --- a/source/funkin/play/notes/notestyle/NoteStyle.hx +++ b/source/funkin/play/notes/notestyle/NoteStyle.hx @@ -103,7 +103,11 @@ class NoteStyle implements IRegistryEntry function buildNoteFrames(force:Bool = false):Null { var noteAssetPath = getNoteAssetPath(); - if (noteAssetPath == null) return null; + if (noteAssetPath == null) + { + FlxG.log.warn('Note asset path not found: ${id}'); + return null; + } if (!FunkinSprite.isTextureCached(Paths.image(noteAssetPath))) { diff --git a/source/funkin/ui/debug/latency/LatencyState.hx b/source/funkin/ui/debug/latency/LatencyState.hx index 962438154..63595655c 100644 --- a/source/funkin/ui/debug/latency/LatencyState.hx +++ b/source/funkin/ui/debug/latency/LatencyState.hx @@ -16,6 +16,7 @@ import funkin.ui.debug.latency.CoolStatsGraph; import openfl.events.KeyboardEvent; import funkin.input.PreciseInputManager; import funkin.play.notes.Strumline; +import funkin.ui.mainmenu.MainMenuState; import funkin.play.notes.notestyle.NoteStyle; import funkin.data.notestyle.NoteStyleData; import funkin.data.notestyle.NoteStyleRegistry; @@ -188,6 +189,12 @@ class LatencyState extends MusicBeatSubState } override public function close():Void + { + cleanup(); + super.close(); + } + + function cleanup():Void { PreciseInputManager.instance.onInputPressed.remove(preciseInputPressed); PreciseInputManager.instance.onInputReleased.remove(preciseInputReleased); @@ -200,7 +207,6 @@ class LatencyState extends MusicBeatSubState FlxG.state.persistentDraw = prevPersistentDraw; FlxG.state.persistentUpdate = prevPersistentUpdate; - super.close(); } function regenNoteData() @@ -311,7 +317,9 @@ class LatencyState extends MusicBeatSubState if (controls.BACK) { - close(); + // close(); + cleanup(); + FlxG.switchState(() -> new MainMenuState()); } super.update(elapsed); diff --git a/source/funkin/ui/options/OptionsState.hx b/source/funkin/ui/options/OptionsState.hx index a2301e6a3..6bf637eb9 100644 --- a/source/funkin/ui/options/OptionsState.hx +++ b/source/funkin/ui/options/OptionsState.hx @@ -1,5 +1,6 @@ package funkin.ui.options; +import funkin.ui.transition.LoadingState; import funkin.ui.debug.latency.LatencyState; import flixel.FlxSprite; import flixel.FlxSubState; @@ -185,7 +186,11 @@ class OptionsMenu extends Page createItem("PREFERENCES", function() switchPage(Preferences)); createItem("CONTROLS", function() switchPage(Controls)); createItem("INPUT OFFSETS", function() { + #if web + LoadingState.transitionToState(() -> new LatencyState()); + #else FlxG.state.openSubState(new LatencyState()); + #end }); #if newgrounds diff --git a/source/funkin/ui/transition/LoadingState.hx b/source/funkin/ui/transition/LoadingState.hx index f3620c893..a4fee0f8d 100644 --- a/source/funkin/ui/transition/LoadingState.hx +++ b/source/funkin/ui/transition/LoadingState.hx @@ -451,6 +451,11 @@ class LoadingState extends MusicBeatSubState return promise.future; } + + public static function transitionToState(state:NextState, stopMusic:Bool = false):Void + { + FlxG.switchState(() -> new LoadingState(state, stopMusic)); + } } class MultiCallback From 2edb31890140a79396095ca477e20bde7cd8dd4b Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Sun, 22 Sep 2024 20:11:37 +0100 Subject: [PATCH 863/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 72bb24ac9..d586f038f 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 72bb24ac9b0b9db4b2f9c38ef091e146ef16a1a4 +Subproject commit d586f038fb3b851398909904fc969e5b6755cd4a From 84ce43eff7b95670b3ade17b23be8b3bc18382da Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Mon, 23 Sep 2024 03:46:14 +0100 Subject: [PATCH 864/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 72bb24ac9..17894c11f 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 72bb24ac9b0b9db4b2f9c38ef091e146ef16a1a4 +Subproject commit 17894c11fbc0f189b1f725b6c736aefc115ce566 From 299f4840cfc9e5144037b98232e32da9def903bf Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 23 Sep 2024 13:10:44 -0400 Subject: [PATCH 865/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index d586f038f..9723dfaa3 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit d586f038fb3b851398909904fc969e5b6755cd4a +Subproject commit 9723dfaa3fb882143b9904d59bcc09ee1af7bd5d From a86cfded2ac683610281ebf376c91257bda36bb6 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 23 Sep 2024 13:11:36 -0400 Subject: [PATCH 866/870] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 17894c11f..f672c8ef4 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 17894c11fbc0f189b1f725b6c736aefc115ce566 +Subproject commit f672c8ef43893b207829dd2b1445c89501409ab9 From 0389cd676082ca9d6c6aa4082d32c2a77a73fd16 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 23 Sep 2024 14:45:12 -0400 Subject: [PATCH 867/870] Fix a compile issue on HTML5 with video sprites --- art | 2 +- source/funkin/graphics/video/FunkinVideoSprite.hx | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/art b/art index bfca2ea98..1f64f3e74 160000 --- a/art +++ b/art @@ -1 +1 @@ -Subproject commit bfca2ea98d11a0f4dee4a27b9390951fbc5701ea +Subproject commit 1f64f3e7403a090b164f4442d10152b2be5d3d0a diff --git a/source/funkin/graphics/video/FunkinVideoSprite.hx b/source/funkin/graphics/video/FunkinVideoSprite.hx index e0086784b..2b7f42c03 100644 --- a/source/funkin/graphics/video/FunkinVideoSprite.hx +++ b/source/funkin/graphics/video/FunkinVideoSprite.hx @@ -1,5 +1,6 @@ package funkin.graphics.video; +#if hxcodec import hxcodec.flixel.FlxVideoSprite; /** @@ -30,3 +31,4 @@ class FunkinVideoSprite extends FlxVideoSprite return volume; } } +#end From 52f5c24f9696d30eb68cc4110f3852374e1b388b Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 23 Sep 2024 16:09:34 -0400 Subject: [PATCH 868/870] Add frame market support, and enable on demand tracing. --- project.hxp | 2 +- source/funkin/util/WindowUtil.hx | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/project.hxp b/project.hxp index 74402016f..73a12538a 100644 --- a/project.hxp +++ b/project.hxp @@ -537,7 +537,7 @@ class Project extends HXProject { setHaxedef("HXCPP_TELEMETRY"); // Enable telemetry setHaxedef("HXCPP_TRACY"); // Enable Tracy telemetry setHaxedef("HXCPP_TRACY_MEMORY"); // Track memory allocations - // setHaxedef("HXCPP_TRACY_ON_DEMAND"); // Only collect telemetry when Tracy is open and reachable + setHaxedef("HXCPP_TRACY_ON_DEMAND"); // Only collect telemetry when Tracy is open and reachable // setHaxedef("HXCPP_TRACY_INCLUDE_CALLSTACKS"); // Inspect callstacks per zone, inflating telemetry data setHaxedef("absolute-paths"); // Fix source locations so Tracy can see them diff --git a/source/funkin/util/WindowUtil.hx b/source/funkin/util/WindowUtil.hx index 0fe63fe32..d9d43614a 100644 --- a/source/funkin/util/WindowUtil.hx +++ b/source/funkin/util/WindowUtil.hx @@ -91,6 +91,14 @@ class WindowUtil windowExit.dispatch(exitCode); }); + #if FEATURE_DEBUG_TRACY + // Apply a marker to indicate frame end for the Tracy profiler. + // Do this only if Tracy is configured to prevent lag. + openfl.Lib.current.stage.addEventListener(openfl.events.Event.EXIT_FRAME, (e:openfl.events.Event) -> { + cpp.vm.tracy.TracyProfiler.frameMark(); + }); + #end + openfl.Lib.current.stage.addEventListener(openfl.events.KeyboardEvent.KEY_DOWN, (e:openfl.events.KeyboardEvent) -> { for (key in PlayerSettings.player1.controls.getKeysForAction(WINDOW_FULLSCREEN)) { From 7e7530842393e661771c7689dbc405ea391d7e3d Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 23 Sep 2024 18:51:48 -0400 Subject: [PATCH 869/870] capitalization hxCodec --- source/funkin/graphics/video/FunkinVideoSprite.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/graphics/video/FunkinVideoSprite.hx b/source/funkin/graphics/video/FunkinVideoSprite.hx index 2b7f42c03..356699b4d 100644 --- a/source/funkin/graphics/video/FunkinVideoSprite.hx +++ b/source/funkin/graphics/video/FunkinVideoSprite.hx @@ -1,6 +1,6 @@ package funkin.graphics.video; -#if hxcodec +#if hxCodec import hxcodec.flixel.FlxVideoSprite; /** From ec9b5db2109ab39ed90f5e1d291de35471128884 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Mon, 23 Sep 2024 21:41:48 -0400 Subject: [PATCH 870/870] Create shader for Week 5 once and reuse it rather than recreating it every frame. --- assets | 2 +- source/funkin/graphics/shaders/AdjustColorShader.hx | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/assets b/assets index f672c8ef4..8140f8255 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit f672c8ef43893b207829dd2b1445c89501409ab9 +Subproject commit 8140f8255c0db78135dbfa7b6d329f52c363f51b diff --git a/source/funkin/graphics/shaders/AdjustColorShader.hx b/source/funkin/graphics/shaders/AdjustColorShader.hx index a6efc3e65..cd3ac228b 100644 --- a/source/funkin/graphics/shaders/AdjustColorShader.hx +++ b/source/funkin/graphics/shaders/AdjustColorShader.hx @@ -50,4 +50,9 @@ class AdjustColorShader extends FlxRuntimeShader return this.contrast; } + + public override function toString():String + { + return 'AdjustColorShader(${this.hue}, ${this.saturation}, ${this.brightness}, ${this.contrast})'; + } }