From dbab5a912db8805f58ef9ab0695c6c1a0c74d878 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 31 May 2023 03:03:10 -0400 Subject: [PATCH 01/33] death alt easter egg --- .../graphics/adobeanimate/FlxAtlasSprite.hx | 2 +- source/funkin/play/GameOverSubstate.hx | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx index aad9cd851..1c120a7c7 100644 --- a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx +++ b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx @@ -16,7 +16,7 @@ class FlxAtlasSprite extends FlxAnimate FrameRate: 24.0, Reversed: false, // ?OnComplete:Void -> Void, - ShowPivot: #if debug true #else false #end, + ShowPivot: #if debug false #else false #end, Antialiasing: true, ScrollFactor: new FlxPoint(1, 1), // Offset: new FlxPoint(0, 0), // This is just FlxSprite.offset diff --git a/source/funkin/play/GameOverSubstate.hx b/source/funkin/play/GameOverSubstate.hx index 3d5470324..b07f5786b 100644 --- a/source/funkin/play/GameOverSubstate.hx +++ b/source/funkin/play/GameOverSubstate.hx @@ -1,5 +1,7 @@ package funkin.play; +import funkin.graphics.adobeanimate.FlxAtlasSprite; +import flixel.FlxG; import flixel.FlxObject; import flixel.FlxSprite; import flixel.system.FlxSound; @@ -97,7 +99,21 @@ class GameOverSubstate extends MusicBeatSubstate boyfriend.isDead = true; add(boyfriend); boyfriend.resetCharacter(); - boyfriend.playAnimation('firstDeath', true, true); + + if (animationSuffix == "" && FlxG.random.bool((1 / 4000) * 100)) + { + var bfFake:FlxAtlasSprite = new FlxAtlasSprite(boyfriend.x - 440, boyfriend.y - 240, Paths.animateAtlas("characters/bfFakeOut", "shared"),); + add(bfFake); + bfFake.playAnimation(""); + bfFake.anim.onComplete = () -> { + bfFake.visible = false; + boyfriend.visible = true; + boyfriend.playAnimation('firstDeath', true, true); + }; + boyfriend.visible = false; + } + else + boyfriend.playAnimation('firstDeath', true, true); // Assign a camera follow point to the boyfriend's position. cameraFollowPoint = new FlxObject(PlayState.instance.cameraFollowPoint.x, PlayState.instance.cameraFollowPoint.y, 1, 1); From 2d16aab488841a1b541f50aeddda51882c7f01db Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 31 May 2023 03:28:53 -0400 Subject: [PATCH 02/33] snds effects --- source/funkin/play/GameOverSubstate.hx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/source/funkin/play/GameOverSubstate.hx b/source/funkin/play/GameOverSubstate.hx index b07f5786b..93cc47b57 100644 --- a/source/funkin/play/GameOverSubstate.hx +++ b/source/funkin/play/GameOverSubstate.hx @@ -100,8 +100,10 @@ class GameOverSubstate extends MusicBeatSubstate add(boyfriend); boyfriend.resetCharacter(); - if (animationSuffix == "" && FlxG.random.bool((1 / 4000) * 100)) + if (boyfriend.characterId == "bf" && animationSuffix == "" && FlxG.random.bool((1 / 4000) * 100)) { + FlxG.sound.play(Paths.sound("fakeout_death")); + var bfFake:FlxAtlasSprite = new FlxAtlasSprite(boyfriend.x - 440, boyfriend.y - 240, Paths.animateAtlas("characters/bfFakeOut", "shared"),); add(bfFake); bfFake.playAnimation(""); @@ -109,11 +111,17 @@ class GameOverSubstate extends MusicBeatSubstate bfFake.visible = false; boyfriend.visible = true; boyfriend.playAnimation('firstDeath', true, true); + // Play the "blue balled" sound. May play a variant if one has been assigned. + playBlueBalledSFX(); }; boyfriend.visible = false; } else + { boyfriend.playAnimation('firstDeath', true, true); + // Play the "blue balled" sound. May play a variant if one has been assigned. + playBlueBalledSFX(); + } // Assign a camera follow point to the boyfriend's position. cameraFollowPoint = new FlxObject(PlayState.instance.cameraFollowPoint.x, PlayState.instance.cameraFollowPoint.y, 1, 1); @@ -134,9 +142,6 @@ class GameOverSubstate extends MusicBeatSubstate // The conductor now represents the BPM of the game over music. Conductor.songPosition = 0; - - // Play the "blue balled" sound. May play a variant if one has been assigned. - playBlueBalledSFX(); } override function update(elapsed:Float) From 374f03dae30a90051ac761c04ea45de80d865df2 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 1 Jun 2023 00:31:32 -0400 Subject: [PATCH 03/33] Fakeout death now uses HScript --- source/funkin/play/GameOverSubstate.hx | 44 +++++++++++--------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/source/funkin/play/GameOverSubstate.hx b/source/funkin/play/GameOverSubstate.hx index 93cc47b57..041831962 100644 --- a/source/funkin/play/GameOverSubstate.hx +++ b/source/funkin/play/GameOverSubstate.hx @@ -1,6 +1,5 @@ package funkin.play; -import funkin.graphics.adobeanimate.FlxAtlasSprite; import flixel.FlxG; import flixel.FlxObject; import flixel.FlxSprite; @@ -100,29 +99,6 @@ class GameOverSubstate extends MusicBeatSubstate add(boyfriend); boyfriend.resetCharacter(); - if (boyfriend.characterId == "bf" && animationSuffix == "" && FlxG.random.bool((1 / 4000) * 100)) - { - FlxG.sound.play(Paths.sound("fakeout_death")); - - var bfFake:FlxAtlasSprite = new FlxAtlasSprite(boyfriend.x - 440, boyfriend.y - 240, Paths.animateAtlas("characters/bfFakeOut", "shared"),); - add(bfFake); - bfFake.playAnimation(""); - bfFake.anim.onComplete = () -> { - bfFake.visible = false; - boyfriend.visible = true; - boyfriend.playAnimation('firstDeath', true, true); - // Play the "blue balled" sound. May play a variant if one has been assigned. - playBlueBalledSFX(); - }; - boyfriend.visible = false; - } - else - { - boyfriend.playAnimation('firstDeath', true, true); - // Play the "blue balled" sound. May play a variant if one has been assigned. - playBlueBalledSFX(); - } - // 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; @@ -144,10 +120,28 @@ class GameOverSubstate extends MusicBeatSubstate Conductor.songPosition = 0; } + var hasStartedAnimation:Bool = false; + override function update(elapsed:Float) { super.update(elapsed); + if (!hasStartedAnimation) + { + hasStartedAnimation = true; + + if (boyfriend.hasAnimation('fakeoutDeath') && (FlxG.random.bool((1 / 4000) * 100) || true)) + { + boyfriend.playAnimation('fakeoutDeath', true, true); + } + else + { + boyfriend.playAnimation('firstDeath', true, true); + // Play the "blue balled" sound. May play a variant if one has been assigned. + playBlueBalledSFX(); + } + } + // // Handle user inputs. // @@ -279,7 +273,7 @@ class GameOverSubstate extends MusicBeatSubstate * Play the sound effect that occurs when * boyfriend's testicles get utterly annihilated. */ - function playBlueBalledSFX() + public static function playBlueBalledSFX() { FlxG.sound.play(Paths.sound('fnf_loss_sfx' + blueBallSuffix)); } From b49a2857e583d3eb5d2e29c5d49917f3e7ee9a7e Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 1 Jun 2023 00:33:30 -0400 Subject: [PATCH 04/33] Revert guaranteed fakeout --- source/funkin/play/GameOverSubstate.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/play/GameOverSubstate.hx b/source/funkin/play/GameOverSubstate.hx index 041831962..01e8e568d 100644 --- a/source/funkin/play/GameOverSubstate.hx +++ b/source/funkin/play/GameOverSubstate.hx @@ -130,7 +130,7 @@ class GameOverSubstate extends MusicBeatSubstate { hasStartedAnimation = true; - if (boyfriend.hasAnimation('fakeoutDeath') && (FlxG.random.bool((1 / 4000) * 100) || true)) + if (boyfriend.hasAnimation('fakeoutDeath') && (FlxG.random.bool((1 / 4000) * 100))) { boyfriend.playAnimation('fakeoutDeath', true, true); } From 2d772a526b33b8205b36b3bd8b2eede7d8d6531e Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 2 Jun 2023 15:56:40 -0400 Subject: [PATCH 05/33] no skipping easter egg!! --- source/funkin/play/GameOverSubstate.hx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/source/funkin/play/GameOverSubstate.hx b/source/funkin/play/GameOverSubstate.hx index 01e8e568d..da7c68df7 100644 --- a/source/funkin/play/GameOverSubstate.hx +++ b/source/funkin/play/GameOverSubstate.hx @@ -130,7 +130,7 @@ class GameOverSubstate extends MusicBeatSubstate { hasStartedAnimation = true; - if (boyfriend.hasAnimation('fakeoutDeath') && (FlxG.random.bool((1 / 4000) * 100))) + if (boyfriend.hasAnimation('fakeoutDeath') && (true || FlxG.random.bool((1 / 4000) * 100))) { boyfriend.playAnimation('fakeoutDeath', true, true); } @@ -160,7 +160,7 @@ class GameOverSubstate extends MusicBeatSubstate } // KEYBOARD ONLY: Restart the level when pressing the assigned key. - if (controls.ACCEPT) + if (controls.ACCEPT && blueballed) { confirmDeath(); } @@ -269,12 +269,15 @@ class GameOverSubstate extends MusicBeatSubstate } } + var blueballed:Bool = false; + /** * Play the sound effect that occurs when * boyfriend's testicles get utterly annihilated. */ public static function playBlueBalledSFX() { + blueballed = true; FlxG.sound.play(Paths.sound('fnf_loss_sfx' + blueBallSuffix)); } From 7a04a2d7747a11ee0e9fa5562d6c3aef93ee80b9 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sun, 4 Jun 2023 01:19:08 -0400 Subject: [PATCH 06/33] blueball check --- 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 da7c68df7..2f55a8e79 100644 --- a/source/funkin/play/GameOverSubstate.hx +++ b/source/funkin/play/GameOverSubstate.hx @@ -162,12 +162,14 @@ class GameOverSubstate extends MusicBeatSubstate // KEYBOARD ONLY: Restart the level when pressing the assigned key. if (controls.ACCEPT && blueballed) { + blueballed = false; confirmDeath(); } // KEYBOARD ONLY: Return to the menu when pressing the assigned key. if (controls.BACK) { + blueballed = false; PlayState.deathCounter = 0; PlayState.seenCutscene = false; gameOverMusic.stop(); @@ -269,7 +271,7 @@ class GameOverSubstate extends MusicBeatSubstate } } - var blueballed:Bool = false; + static var blueballed:Bool = false; /** * Play the sound effect that occurs when From 8671846a7370a6d0736ae931119b9fd1a0dd3098 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 9 Jun 2023 13:37:38 -0400 Subject: [PATCH 07/33] updated hxcodec in hmm --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index b07f8c50a..89aa6acc7 100644 --- a/hmm.json +++ b/hmm.json @@ -68,7 +68,7 @@ "name": "hxcodec", "type": "git", "dir": null, - "ref": "91adeec", + "ref": "c42ab99", "url": "https://github.com/polybiusproxy/hxCodec" }, { From 89535cb5cdbb51c31d70c413c0a8701e5cd036ac Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 9 Jun 2023 14:02:45 -0400 Subject: [PATCH 08/33] simple lime update... lol! --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index 89aa6acc7..9652d9440 100644 --- a/hmm.json +++ b/hmm.json @@ -95,7 +95,7 @@ "name": "lime", "type": "git", "dir": null, - "ref": "deecd6c", + "ref": "5634ad7", "url": "https://github.com/openfl/lime" }, { From a7eb91ce296de5ce24ea8a75514841d0780a095d Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 9 Jun 2023 15:44:29 -0400 Subject: [PATCH 09/33] the SubState... --- source/funkin/ButtonRemapSubstate.hx | 2 +- source/funkin/FreeplayState.hx | 2 +- source/funkin/LatencyState.hx | 2 +- source/funkin/MusicBeatState.hx | 14 +++++++------- .../{MusicBeatSubstate.hx => MusicBeatSubState.hx} | 4 ++-- source/funkin/PauseSubState.hx | 2 +- source/funkin/modding/IScriptedClass.hx | 8 ++++---- .../modding/base/ScriptedMusicBeatSubState.hx | 8 ++++++++ .../modding/base/ScriptedMusicBeatSubstate.hx | 8 -------- .../funkin/modding/events/ScriptEventDispatcher.hx | 8 ++++---- source/funkin/modding/module/Module.hx | 8 ++++---- .../{GameOverSubstate.hx => GameOverSubState.hx} | 6 +++--- source/funkin/play/PlayState.hx | 10 +++++----- source/funkin/play/ResultState.hx | 2 +- source/funkin/play/character/BaseCharacter.hx | 2 +- source/funkin/ui/StickerSubState.hx | 2 +- source/funkin/ui/debug/DebugMenuSubState.hx | 4 ++-- source/funkin/ui/haxeui/HaxeUISubState.hx | 2 +- .../funkin/ui/stageBuildShit/StageEditorCommand.hx | 12 ++++++------ ...ageOffsetSubstate.hx => StageOffsetSubState.hx} | 2 +- 20 files changed, 54 insertions(+), 54 deletions(-) rename source/funkin/{MusicBeatSubstate.hx => MusicBeatSubState.hx} (94%) create mode 100644 source/funkin/modding/base/ScriptedMusicBeatSubState.hx delete mode 100644 source/funkin/modding/base/ScriptedMusicBeatSubstate.hx rename source/funkin/play/{GameOverSubstate.hx => GameOverSubState.hx} (98%) rename source/funkin/ui/stageBuildShit/{StageOffsetSubstate.hx => StageOffsetSubState.hx} (99%) diff --git a/source/funkin/ButtonRemapSubstate.hx b/source/funkin/ButtonRemapSubstate.hx index 376cc4d54..8905ec8ba 100644 --- a/source/funkin/ButtonRemapSubstate.hx +++ b/source/funkin/ButtonRemapSubstate.hx @@ -2,7 +2,7 @@ package funkin; import flixel.FlxSubState; -class ButtonRemapSubstate extends FlxSubState +class ButtonRemapSubState extends FlxSubState { public function new() { diff --git a/source/funkin/FreeplayState.hx b/source/funkin/FreeplayState.hx index bab9b95a2..bcf6bfc18 100644 --- a/source/funkin/FreeplayState.hx +++ b/source/funkin/FreeplayState.hx @@ -37,7 +37,7 @@ import funkin.shaderslmfao.StrokeShader; import lime.app.Future; import lime.utils.Assets; -class FreeplayState extends MusicBeatSubstate +class FreeplayState extends MusicBeatSubState { var songs:Array = []; diff --git a/source/funkin/LatencyState.hx b/source/funkin/LatencyState.hx index ad803b963..694e9c3e5 100644 --- a/source/funkin/LatencyState.hx +++ b/source/funkin/LatencyState.hx @@ -14,7 +14,7 @@ import funkin.ui.CoolStatsGraph; import haxe.Timer; import openfl.events.KeyboardEvent; -class LatencyState extends MusicBeatSubstate +class LatencyState extends MusicBeatSubState { var offsetText:FlxText; var noteGrp:FlxTypedGroup; diff --git a/source/funkin/MusicBeatState.hx b/source/funkin/MusicBeatState.hx index 3614695c0..6c6591c62 100644 --- a/source/funkin/MusicBeatState.hx +++ b/source/funkin/MusicBeatState.hx @@ -35,8 +35,8 @@ class MusicBeatState extends FlxUIState function initCallbacks() { - subStateOpened.add(onOpenSubstateComplete); - subStateClosed.add(onCloseSubstateComplete); + subStateOpened.add(onOpenSubStateComplete); + subStateClosed.add(onCloseSubStateComplete); } override function create() @@ -162,18 +162,18 @@ class MusicBeatState extends FlxUIState } } - public override function openSubState(targetSubstate:FlxSubState):Void + public override function openSubState(targetSubState:FlxSubState):Void { - var event = new SubStateScriptEvent(ScriptEvent.SUBSTATE_OPEN_BEGIN, targetSubstate, true); + var event = new SubStateScriptEvent(ScriptEvent.SUBSTATE_OPEN_BEGIN, targetSubState, true); dispatchEvent(event); if (event.eventCanceled) return; - super.openSubState(targetSubstate); + super.openSubState(targetSubState); } - function onOpenSubstateComplete(targetState:FlxSubState):Void + function onOpenSubStateComplete(targetState:FlxSubState):Void { dispatchEvent(new SubStateScriptEvent(ScriptEvent.SUBSTATE_OPEN_END, targetState, true)); } @@ -189,7 +189,7 @@ class MusicBeatState extends FlxUIState super.closeSubState(); } - function onCloseSubstateComplete(targetState:FlxSubState):Void + function onCloseSubStateComplete(targetState:FlxSubState):Void { dispatchEvent(new SubStateScriptEvent(ScriptEvent.SUBSTATE_CLOSE_END, targetState, true)); } diff --git a/source/funkin/MusicBeatSubstate.hx b/source/funkin/MusicBeatSubState.hx similarity index 94% rename from source/funkin/MusicBeatSubstate.hx rename to source/funkin/MusicBeatSubState.hx index 802022a67..440e25c96 100644 --- a/source/funkin/MusicBeatSubstate.hx +++ b/source/funkin/MusicBeatSubState.hx @@ -7,9 +7,9 @@ import funkin.modding.events.ScriptEvent; import funkin.modding.module.ModuleHandler; /** - * MusicBeatSubstate reincorporates the functionality of MusicBeatState into an FlxSubState. + * MusicBeatSubState reincorporates the functionality of MusicBeatState into an FlxSubState. */ -class MusicBeatSubstate extends FlxSubState +class MusicBeatSubState extends FlxSubState { public function new(bgColor:FlxColor = FlxColor.TRANSPARENT) { diff --git a/source/funkin/PauseSubState.hx b/source/funkin/PauseSubState.hx index 67b58f41d..890b51cb7 100644 --- a/source/funkin/PauseSubState.hx +++ b/source/funkin/PauseSubState.hx @@ -11,7 +11,7 @@ import flixel.util.FlxColor; import funkin.play.PlayState; import funkin.play.song.SongData.SongDataParser; -class PauseSubState extends MusicBeatSubstate +class PauseSubState extends MusicBeatSubState { var grpMenuShit:FlxTypedGroup; diff --git a/source/funkin/modding/IScriptedClass.hx b/source/funkin/modding/IScriptedClass.hx index ee57de6be..abcce483f 100644 --- a/source/funkin/modding/IScriptedClass.hx +++ b/source/funkin/modding/IScriptedClass.hx @@ -24,10 +24,10 @@ interface IStateChangingScriptedClass extends IScriptedClass public function onStateChangeBegin(event:StateChangeScriptEvent):Void; public function onStateChangeEnd(event:StateChangeScriptEvent):Void; - public function onSubstateOpenBegin(event:SubStateScriptEvent):Void; - public function onSubstateOpenEnd(event:SubStateScriptEvent):Void; - public function onSubstateCloseBegin(event:SubStateScriptEvent):Void; - public function onSubstateCloseEnd(event:SubStateScriptEvent):Void; + public function onSubStateOpenBegin(event:SubStateScriptEvent):Void; + public function onSubStateOpenEnd(event:SubStateScriptEvent):Void; + public function onSubStateCloseBegin(event:SubStateScriptEvent):Void; + public function onSubStateCloseEnd(event:SubStateScriptEvent):Void; } /** diff --git a/source/funkin/modding/base/ScriptedMusicBeatSubState.hx b/source/funkin/modding/base/ScriptedMusicBeatSubState.hx new file mode 100644 index 000000000..7dab3d7dd --- /dev/null +++ b/source/funkin/modding/base/ScriptedMusicBeatSubState.hx @@ -0,0 +1,8 @@ +package funkin.modding.base; + +/** + * A script that can be tied to a MusicBeatSubState. + * Create a scripted class that extends MusicBeatSubState to use this. + */ +@:hscriptClass +class ScriptedMusicBeatSubState extends funkin.MusicBeatSubState implements HScriptedClass {} diff --git a/source/funkin/modding/base/ScriptedMusicBeatSubstate.hx b/source/funkin/modding/base/ScriptedMusicBeatSubstate.hx deleted file mode 100644 index d0d764aeb..000000000 --- a/source/funkin/modding/base/ScriptedMusicBeatSubstate.hx +++ /dev/null @@ -1,8 +0,0 @@ -package funkin.modding.base; - -/** - * A script that can be tied to a MusicBeatSubstate. - * Create a scripted class that extends MusicBeatSubstate to use this. - */ -@:hscriptClass -class ScriptedMusicBeatSubstate extends funkin.MusicBeatSubstate implements HScriptedClass {} diff --git a/source/funkin/modding/events/ScriptEventDispatcher.hx b/source/funkin/modding/events/ScriptEventDispatcher.hx index 18181a1d1..a816d748a 100644 --- a/source/funkin/modding/events/ScriptEventDispatcher.hx +++ b/source/funkin/modding/events/ScriptEventDispatcher.hx @@ -113,16 +113,16 @@ class ScriptEventDispatcher t.onStateChangeEnd(cast event); return; case ScriptEvent.SUBSTATE_OPEN_BEGIN: - t.onSubstateOpenBegin(cast event); + t.onSubStateOpenBegin(cast event); return; case ScriptEvent.SUBSTATE_OPEN_END: - t.onSubstateOpenEnd(cast event); + t.onSubStateOpenEnd(cast event); return; case ScriptEvent.SUBSTATE_CLOSE_BEGIN: - t.onSubstateCloseBegin(cast event); + t.onSubStateCloseBegin(cast event); return; case ScriptEvent.SUBSTATE_CLOSE_END: - t.onSubstateCloseEnd(cast event); + t.onSubStateCloseEnd(cast event); return; } } diff --git a/source/funkin/modding/module/Module.hx b/source/funkin/modding/module/Module.hx index 4d5e3457c..f50c9936a 100644 --- a/source/funkin/modding/module/Module.hx +++ b/source/funkin/modding/module/Module.hx @@ -107,13 +107,13 @@ class Module implements IPlayStateScriptedClass implements IStateChangingScripte public function onStateChangeEnd(event:StateChangeScriptEvent) {} - public function onSubstateOpenBegin(event:SubStateScriptEvent) {} + public function onSubStateOpenBegin(event:SubStateScriptEvent) {} - public function onSubstateOpenEnd(event:SubStateScriptEvent) {} + public function onSubStateOpenEnd(event:SubStateScriptEvent) {} - public function onSubstateCloseBegin(event:SubStateScriptEvent) {} + public function onSubStateCloseBegin(event:SubStateScriptEvent) {} - public function onSubstateCloseEnd(event:SubStateScriptEvent) {} + public function onSubStateCloseEnd(event:SubStateScriptEvent) {} public function onSongRetry(event:ScriptEvent) {} } diff --git a/source/funkin/play/GameOverSubstate.hx b/source/funkin/play/GameOverSubState.hx similarity index 98% rename from source/funkin/play/GameOverSubstate.hx rename to source/funkin/play/GameOverSubState.hx index 2c46fa10f..35365beb6 100644 --- a/source/funkin/play/GameOverSubstate.hx +++ b/source/funkin/play/GameOverSubState.hx @@ -18,7 +18,7 @@ import funkin.ui.PreferencesMenu; * * The newest implementation uses a substate, which prevents having to reload the song and stage each reset. */ -class GameOverSubstate extends MusicBeatSubstate +class GameOverSubState extends MusicBeatSubState { /** * Which alternate animation on the character to use. @@ -91,7 +91,7 @@ class GameOverSubstate extends MusicBeatSubstate bg.scrollFactor.set(); add(bg); - // Pluck Boyfriend from the PlayState and place him (in the same position) in the GameOverSubstate. + // Pluck Boyfriend from the PlayState and place him (in the same position) in the GameOverSubState. // We can then play the character's `firstDeath` animation. boyfriend = PlayState.instance.currentStage.getBoyfriend(true); boyfriend.isDead = true; @@ -212,7 +212,7 @@ class GameOverSubstate extends MusicBeatSubstate new FlxTimer().start(0.7, function(tmr:FlxTimer) { // ...fade out the graphics. Then after that happens... FlxG.camera.fade(FlxColor.BLACK, 2, false, function() { - // ...close the GameOverSubstate. + // ...close the GameOverSubState. FlxG.camera.fade(FlxColor.BLACK, 1, true, null, true); PlayState.needsReset = true; diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 987243585..cdc968609 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -45,7 +45,7 @@ import funkin.SongLoad.SwagSong; import funkin.audio.VoicesGroup; import funkin.ui.PopUpStuff; import funkin.ui.PreferencesMenu; -import funkin.ui.stageBuildShit.StageOffsetSubstate; +import funkin.ui.stageBuildShit.StageOffsetSubState; import funkin.util.Constants; import funkin.util.SerializerUtil; import funkin.util.SortUtil; @@ -1405,7 +1405,7 @@ class PlayState extends MusicBeatState // hack for HaxeUI generation, doesn't work unless persistentUpdate is false at state creation!! disableKeys = true; persistentUpdate = false; - openSubState(new StageOffsetSubstate()); + openSubState(new StageOffsetSubState()); } updateHealthBar(); @@ -1643,8 +1643,8 @@ class PlayState extends MusicBeatState } #end - var gameOverSubstate = new GameOverSubstate(); - openSubState(gameOverSubstate); + var gameOverSubState = new GameOverSubState(); + openSubState(gameOverSubState); #if discord_rpc // Game Over doesn't get his own variable because it's only used here @@ -2739,7 +2739,7 @@ class PlayState extends MusicBeatState currentStage = null; } - GameOverSubstate.reset(); + GameOverSubState.reset(); // Clear the static reference to this state. instance = null; diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index bdf4c19c9..6b9167846 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -19,7 +19,7 @@ import funkin.shaderslmfao.LeftMaskShader; import funkin.ui.TallyCounter; import flxanimate.FlxAnimate.Settings; -class ResultState extends MusicBeatSubstate +class ResultState extends MusicBeatSubState { var resultsVariation:ResultVariations; var songName:FlxBitmapText; diff --git a/source/funkin/play/character/BaseCharacter.hx b/source/funkin/play/character/BaseCharacter.hx index a2830f2a8..f4db7f66f 100644 --- a/source/funkin/play/character/BaseCharacter.hx +++ b/source/funkin/play/character/BaseCharacter.hx @@ -401,7 +401,7 @@ class BaseCharacter extends Bopper { if (force || (getCurrentAnimation().startsWith('firstDeath') && isAnimationFinished())) { - playAnimation('deathLoop' + GameOverSubstate.animationSuffix); + playAnimation('deathLoop' + GameOverSubState.animationSuffix); } } diff --git a/source/funkin/ui/StickerSubState.hx b/source/funkin/ui/StickerSubState.hx index 9658275e9..333d4bf57 100644 --- a/source/funkin/ui/StickerSubState.hx +++ b/source/funkin/ui/StickerSubState.hx @@ -17,7 +17,7 @@ import openfl.geom.Matrix; import openfl.display.Sprite; import openfl.display.Bitmap; -class StickerSubState extends MusicBeatSubstate +class StickerSubState extends MusicBeatSubState { public var grpStickers:FlxTypedGroup; diff --git a/source/funkin/ui/debug/DebugMenuSubState.hx b/source/funkin/ui/debug/DebugMenuSubState.hx index 5d00c03b8..9f18acd35 100644 --- a/source/funkin/ui/debug/DebugMenuSubState.hx +++ b/source/funkin/ui/debug/DebugMenuSubState.hx @@ -2,11 +2,11 @@ package funkin.ui.debug; import flixel.FlxObject; import flixel.FlxSprite; -import funkin.MusicBeatSubstate; +import funkin.MusicBeatSubState; import funkin.ui.TextMenuList; import funkin.ui.debug.charting.ChartEditorState; -class DebugMenuSubState extends MusicBeatSubstate +class DebugMenuSubState extends MusicBeatSubState { var items:TextMenuList; diff --git a/source/funkin/ui/haxeui/HaxeUISubState.hx b/source/funkin/ui/haxeui/HaxeUISubState.hx index 963223619..ba218f37c 100644 --- a/source/funkin/ui/haxeui/HaxeUISubState.hx +++ b/source/funkin/ui/haxeui/HaxeUISubState.hx @@ -7,7 +7,7 @@ import haxe.ui.core.Component; import haxe.ui.events.MouseEvent; import haxe.ui.events.UIEvent; -class HaxeUISubState extends MusicBeatSubstate +class HaxeUISubState extends MusicBeatSubState { // The component representing the main UI. public var component:Component; diff --git a/source/funkin/ui/stageBuildShit/StageEditorCommand.hx b/source/funkin/ui/stageBuildShit/StageEditorCommand.hx index e6ce2777b..1e19914da 100644 --- a/source/funkin/ui/stageBuildShit/StageEditorCommand.hx +++ b/source/funkin/ui/stageBuildShit/StageEditorCommand.hx @@ -9,8 +9,8 @@ import flixel.FlxSprite; */ interface StageEditorCommand { - public function execute(state:StageOffsetSubstate):Void; - public function undo(state:StageOffsetSubstate):Void; + public function execute(state:StageOffsetSubState):Void; + public function undo(state:StageOffsetSubState):Void; public function toString():String; } @@ -27,7 +27,7 @@ class MovePropCommand implements StageEditorCommand this.realMove = realMove; } - public function execute(state:StageOffsetSubstate):Void + public function execute(state:StageOffsetSubState):Void { if (realMove) { @@ -36,7 +36,7 @@ class MovePropCommand implements StageEditorCommand } } - public function undo(state:StageOffsetSubstate):Void + public function undo(state:StageOffsetSubState):Void { state.char.x -= xDiff; state.char.y -= yDiff; @@ -58,13 +58,13 @@ class SelectPropCommand implements StageEditorCommand this.prop = prop; } - public function execute(state:StageOffsetSubstate):Void + public function execute(state:StageOffsetSubState):Void { this.prevProp = state.char; state.char = prop; } - public function undo(state:StageOffsetSubstate):Void + public function undo(state:StageOffsetSubState):Void { var funnyShader = state.char.shader; if (state.char != null) state.char.shader = null; diff --git a/source/funkin/ui/stageBuildShit/StageOffsetSubstate.hx b/source/funkin/ui/stageBuildShit/StageOffsetSubState.hx similarity index 99% rename from source/funkin/ui/stageBuildShit/StageOffsetSubstate.hx rename to source/funkin/ui/stageBuildShit/StageOffsetSubState.hx index 15140b2a7..4a36bb21d 100644 --- a/source/funkin/ui/stageBuildShit/StageOffsetSubstate.hx +++ b/source/funkin/ui/stageBuildShit/StageOffsetSubState.hx @@ -28,7 +28,7 @@ import openfl.net.FileReference; */ // Give other classes access to private instance fields @:allow(funkin.ui.stageBuildShit.StageEditorCommand) -class StageOffsetSubstate extends HaxeUISubState +class StageOffsetSubState extends HaxeUISubState { var uiStuff:Component; From 4fae8bcad2bf4eaa38f30140da0dc28f8f077aca Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 9 Jun 2023 16:02:57 -0400 Subject: [PATCH 10/33] file renames... --- source/funkin/{MusicBeatSubstate.hx => MusicBeatSubState.hx} | 0 ...{ScriptedMusicBeatSubstate.hx => ScriptedMusicBeatSubState.hx} | 0 source/funkin/play/{GameOverSubstate.hx => GameOverSubState.hx} | 0 .../{StageOffsetSubstate.hx => StageOffsetSubState.hx} | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename source/funkin/{MusicBeatSubstate.hx => MusicBeatSubState.hx} (100%) rename source/funkin/modding/base/{ScriptedMusicBeatSubstate.hx => ScriptedMusicBeatSubState.hx} (100%) rename source/funkin/play/{GameOverSubstate.hx => GameOverSubState.hx} (100%) rename source/funkin/ui/stageBuildShit/{StageOffsetSubstate.hx => StageOffsetSubState.hx} (100%) diff --git a/source/funkin/MusicBeatSubstate.hx b/source/funkin/MusicBeatSubState.hx similarity index 100% rename from source/funkin/MusicBeatSubstate.hx rename to source/funkin/MusicBeatSubState.hx diff --git a/source/funkin/modding/base/ScriptedMusicBeatSubstate.hx b/source/funkin/modding/base/ScriptedMusicBeatSubState.hx similarity index 100% rename from source/funkin/modding/base/ScriptedMusicBeatSubstate.hx rename to source/funkin/modding/base/ScriptedMusicBeatSubState.hx diff --git a/source/funkin/play/GameOverSubstate.hx b/source/funkin/play/GameOverSubState.hx similarity index 100% rename from source/funkin/play/GameOverSubstate.hx rename to source/funkin/play/GameOverSubState.hx diff --git a/source/funkin/ui/stageBuildShit/StageOffsetSubstate.hx b/source/funkin/ui/stageBuildShit/StageOffsetSubState.hx similarity index 100% rename from source/funkin/ui/stageBuildShit/StageOffsetSubstate.hx rename to source/funkin/ui/stageBuildShit/StageOffsetSubState.hx From 4daf6442846b58603f1cd13fda7a56af776be4d5 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 9 Jun 2023 16:03:45 -0400 Subject: [PATCH 11/33] ree --- source/funkin/modding/base/ScriptedMusicBeatSubState.hx | 8 -------- 1 file changed, 8 deletions(-) diff --git a/source/funkin/modding/base/ScriptedMusicBeatSubState.hx b/source/funkin/modding/base/ScriptedMusicBeatSubState.hx index 5090bf2b4..7dab3d7dd 100644 --- a/source/funkin/modding/base/ScriptedMusicBeatSubState.hx +++ b/source/funkin/modding/base/ScriptedMusicBeatSubState.hx @@ -1,16 +1,8 @@ package funkin.modding.base; /** -<<<<<<< HEAD - * A script that can be tied to a MusicBeatSubstate. - * Create a scripted class that extends MusicBeatSubstate to use this. - */ -@:hscriptClass -class ScriptedMusicBeatSubstate extends funkin.MusicBeatSubstate implements HScriptedClass {} -======= * A script that can be tied to a MusicBeatSubState. * Create a scripted class that extends MusicBeatSubState to use this. */ @:hscriptClass class ScriptedMusicBeatSubState extends funkin.MusicBeatSubState implements HScriptedClass {} ->>>>>>> f73c34bcbea4289202f6ef90522808b211d1cf44 From 4dcdca51ae019362e169ed9638da3a858032d415 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 9 Jun 2023 16:54:13 -0400 Subject: [PATCH 12/33] Fix camera issue with stickers --- source/funkin/PauseSubState.hx | 2 +- source/funkin/ui/StickerSubState.hx | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/source/funkin/PauseSubState.hx b/source/funkin/PauseSubState.hx index 7349052aa..77fdfabf1 100644 --- a/source/funkin/PauseSubState.hx +++ b/source/funkin/PauseSubState.hx @@ -225,7 +225,7 @@ class PauseSubState extends MusicBeatSubState if (PlayStatePlaylist.isStoryMode) openSubState(new funkin.ui.StickerSubState(null, STORY)); else - openSubState(new funkin.ui.StickerSubState()); + openSubState(new funkin.ui.StickerSubState(null, FREEPLAY)); } } diff --git a/source/funkin/ui/StickerSubState.hx b/source/funkin/ui/StickerSubState.hx index 333d4bf57..981c79dfa 100644 --- a/source/funkin/ui/StickerSubState.hx +++ b/source/funkin/ui/StickerSubState.hx @@ -36,7 +36,8 @@ class StickerSubState extends MusicBeatSubState add(grpStickers); // makes the stickers on the most recent camera, which is more often than not... a UI camera!! - grpStickers.cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]]; + // grpStickers.cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]]; + grpStickers.cameras = FlxG.cameras.list; if (oldStickers != null) { @@ -208,8 +209,10 @@ class StickerSubState extends MusicBeatSubState FlxG.switchState(new FreeplayState(this)); case STORY: FlxG.switchState(new StoryMenuState(this)); + case MAIN_MENU: + FlxG.switchState(new MainMenuState()); default: - FlxG.switchState(new FreeplayState(this)); + FlxG.switchState(new MainMenuState()); } } @@ -354,6 +357,7 @@ typedef StickerShit = enum abstract NEXTSTATE(String) { + var MAIN_MENU = 'mainmenu'; var FREEPLAY = 'freeplay'; var STORY = 'story'; } From 109676522ac46ada28371fa34adb3eedb5ec0b01 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 9 Jun 2023 18:25:21 -0400 Subject: [PATCH 13/33] Rewrite freeplay state to use correct week IDs. --- source/funkin/FreeplayState.hx | 44 +++++++++++++++++----------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/source/funkin/FreeplayState.hx b/source/funkin/FreeplayState.hx index 73e1b7cb5..322e79e31 100644 --- a/source/funkin/FreeplayState.hx +++ b/source/funkin/FreeplayState.hx @@ -41,7 +41,7 @@ import lime.utils.Assets; class FreeplayState extends MusicBeatSubState { - var songs:Array = []; + var songs:Array = []; // var selector:FlxText; var curSelected:Int = 0; @@ -114,15 +114,15 @@ class FreeplayState extends MusicBeatSubState #if debug isDebug = true; - addSong('Test', 1, 'bf-pixel'); - addSong('Pyro', 8, 'darnell'); + addSong('Test', 'tutorial', 'bf-pixel'); + addSong('Pyro', 'weekend1', 'darnell'); #end var initSonglist = CoolUtil.coolTextFile(Paths.txt('freeplaySonglist')); for (i in 0...initSonglist.length) { - songs.push(new SongMetadata(initSonglist[i], 1, 'gf')); + songs.push(new FreeplaySongData(initSonglist[i], 'tutorial', 'gf')); } if (FlxG.sound.music != null) @@ -131,27 +131,27 @@ class FreeplayState extends MusicBeatSubState } // if (StoryMenuState.weekUnlocked[2] || isDebug) - addWeek(['Bopeebo', 'Fresh', 'Dadbattle'], 1, ['dad']); + addWeek(['Bopeebo', 'Fresh', 'Dadbattle'], 'week1', ['dad']); // if (StoryMenuState.weekUnlocked[2] || isDebug) - addWeek(['Spookeez', 'South', 'Monster'], 2, ['spooky', 'spooky', 'monster']); + addWeek(['Spookeez', 'South', 'Monster'], 'week2', ['spooky', 'spooky', 'monster']); // if (StoryMenuState.weekUnlocked[3] || isDebug) - addWeek(['Pico', 'Philly-Nice', 'Blammed'], 3, ['pico']); + addWeek(['Pico', 'Philly-Nice', 'Blammed'], 'week3', ['pico']); // if (StoryMenuState.weekUnlocked[4] || isDebug) - addWeek(['Satin-Panties', 'High', 'MILF'], 4, ['mom']); + addWeek(['Satin-Panties', 'High', 'MILF'], 'week4', ['mom']); // if (StoryMenuState.weekUnlocked[5] || isDebug) - addWeek(['Cocoa', 'Eggnog', 'Winter-Horrorland'], 5, ['parents-christmas', 'parents-christmas', 'monster-christmas']); + addWeek(['Cocoa', 'Eggnog', 'Winter-Horrorland'], 'week5', ['parents-christmas', 'parents-christmas', 'monster-christmas']); // if (StoryMenuState.weekUnlocked[6] || isDebug) - addWeek(['Senpai', 'Roses', 'Thorns'], 6, ['senpai', 'senpai', 'spirit']); + addWeek(['Senpai', 'Roses', 'Thorns'], 'week6', ['senpai', 'senpai', 'spirit']); // if (StoryMenuState.weekUnlocked[7] || isDebug) - addWeek(['Ugh', 'Guns', 'Stress'], 7, ['tankman']); + addWeek(['Ugh', 'Guns', 'Stress'], 'week7', ['tankman']); - addWeek(["Darnell", "lit-up", "2hot", "blazin"], 8, ['darnell']); + addWeek(["Darnell", "lit-up", "2hot", "blazin"], 'weekend1', ['darnell']); // LOAD MUSIC @@ -472,7 +472,7 @@ class FreeplayState extends MusicBeatSubState grpCapsules.clear(); // var regexp:EReg = regexp; - var tempSongs:Array = songs; + var tempSongs:Array = songs; if (filterStuff != null) { @@ -561,19 +561,19 @@ class FreeplayState extends MusicBeatSubState changeDiff(); } - public function addSong(songName:String, weekNum:Int, songCharacter:String) + public function addSong(songName:String, levelId:String, songCharacter:String) { - songs.push(new SongMetadata(songName, weekNum, songCharacter)); + songs.push(new FreeplaySongData(songName, levelId, songCharacter)); } - public function addWeek(songs:Array, weekNum:Int, ?songCharacters:Array) + public function addWeek(songs:Array, levelId:String, ?songCharacters:Array) { if (songCharacters == null) songCharacters = ['bf']; var num:Int = 0; for (song in songs) { - addSong(song, weekNum, songCharacters[num]); + addSong(song, levelId, songCharacters[num]); if (songCharacters.length != 1) num++; } @@ -885,7 +885,7 @@ class FreeplayState extends MusicBeatSubState targetCharacter = 'pico'; } - // PlayState.storyWeek = songs[curSelected].week; + PlayStatePlaylist.campaignId = songs[curSelected].levelId; // Visual and audio effects. FlxG.sound.play(Paths.sound('confirmMenu')); @@ -1047,17 +1047,17 @@ enum abstract FilterType(String) var ALL; } -class SongMetadata +class FreeplaySongData { public var songName:String = ""; - public var week:Int = 0; + public var levelId:String = ""; public var songCharacter:String = ""; public var isFav:Bool = false; - public function new(song:String, week:Int, songCharacter:String, ?isFav:Bool = false) + public function new(song:String, levelId:String, songCharacter:String, ?isFav:Bool = false) { this.songName = song; - this.week = week; + this.levelId = levelId; this.songCharacter = songCharacter; this.isFav = isFav; } From 6f676a5896ffdbfd2db818aceae8302393e4ef83 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 10 Jun 2023 02:56:03 -0400 Subject: [PATCH 14/33] Added new "Mods" story menu section (hidden when no mods are installed) --- source/funkin/ui/story/Level.hx | 5 +++- source/funkin/ui/story/LevelProp.hx | 4 ++- source/funkin/ui/story/StoryMenuState.hx | 31 +++++++++++++++++++----- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/source/funkin/ui/story/Level.hx b/source/funkin/ui/story/Level.hx index 3ff0a5321..83682fec9 100644 --- a/source/funkin/ui/story/Level.hx +++ b/source/funkin/ui/story/Level.hx @@ -156,7 +156,10 @@ class Level implements IRegistryEntry for (propIndex in 0..._data.props.length) { var propData = _data.props[propIndex]; - var propSprite:LevelProp = LevelProp.build(propData); + + var propSprite:Null = LevelProp.build(propData); + if (propSprite == null) continue; + propSprite.x += FlxG.width * 0.25 * propIndex; props.push(propSprite); } diff --git a/source/funkin/ui/story/LevelProp.hx b/source/funkin/ui/story/LevelProp.hx index a474b363c..4dce7bfb3 100644 --- a/source/funkin/ui/story/LevelProp.hx +++ b/source/funkin/ui/story/LevelProp.hx @@ -16,8 +16,10 @@ class LevelProp extends Bopper playAnimation('confirm', true, true); } - public static function build(propData:LevelPropData):Null + public static function build(propData:Null):Null { + if (propData == null) return null; + var isAnimated:Bool = propData.animations.length > 0; var prop:LevelProp = new LevelProp(propData.danceEvery); diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx index b61f1bdee..1dc59f3ec 100644 --- a/source/funkin/ui/story/StoryMenuState.hx +++ b/source/funkin/ui/story/StoryMenuState.hx @@ -52,6 +52,11 @@ class StoryMenuState extends MusicBeatState */ var scoreText:FlxText; + /** + * The mode text at the top-middle. + */ + var modeText:FlxText; + /** * The list of songs on the left. */ @@ -146,16 +151,22 @@ class StoryMenuState extends MusicBeatState updateProps(); - scoreText = new FlxText(10, 10, 0, 'HIGH SCORE: 42069420'); - scoreText.setFormat("VCR OSD Mono", 32); - add(scoreText); - tracklistText = new FlxText(FlxG.width * 0.05, levelBackground.x + levelBackground.height + 100, 0, "Tracks", 32); tracklistText.setFormat("VCR OSD Mono", 32); tracklistText.alignment = CENTER; tracklistText.color = 0xFFe55777; add(tracklistText); + scoreText = new FlxText(10, 10, 0, 'HIGH SCORE: 42069420'); + scoreText.setFormat("VCR OSD Mono", 32); + add(scoreText); + + modeText = new FlxText(10, 10, 0, 'Base Game Levels [TAB to switch]'); + modeText.setFormat("VCR OSD Mono", 32); + modeText.screenCenter(X); + modeText.visible = hasModdedLevels(); + add(modeText); + levelTitleText = new FlxText(FlxG.width * 0.7, 10, 0, 'LEVEL 1'); levelTitleText.setFormat("VCR OSD Mono", 32, FlxColor.WHITE, RIGHT); levelTitleText.alpha = 0.7; @@ -256,7 +267,7 @@ class StoryMenuState extends MusicBeatState displayingModdedLevels = moddedLevels; buildLevelTitles(); - changeLevel(0); + changeLevel(999999); // Jump past the end of the list to the beginning. changeDifficulty(0); } @@ -268,6 +279,9 @@ class StoryMenuState extends MusicBeatState scoreText.text = 'LEVEL SCORE: ${Math.round(highScoreLerp)}'; + modeText.text = displayingModdedLevels ? 'Mods [TAB to switch]' : 'Base Game [TAB to switch]'; + modeText.screenCenter(X); + levelTitleText.text = currentLevel.getTitle(); levelTitleText.x = FlxG.width - (levelTitleText.width + 10); // Right align. @@ -322,7 +336,7 @@ class StoryMenuState extends MusicBeatState changeDifficulty(-1); } - if (FlxG.keys.justPressed.TAB) + if (FlxG.keys.justPressed.TAB && modeText.visible) { switchMode(!displayingModdedLevels); } @@ -342,6 +356,11 @@ class StoryMenuState extends MusicBeatState } } + function hasModdedLevels():Bool + { + return LevelRegistry.instance.listModdedLevelIds().length > 0; + } + /** * Changes the selected level. * @param change +1 (down), -1 (up) From c17d48f39e06c223fd31184f73c5dfbd201e3c43 Mon Sep 17 00:00:00 2001 From: Hazel Date: Mon, 12 Jun 2023 17:20:51 +0200 Subject: [PATCH 15/33] fix ci builds (#106) (common ravy W) * maybe fix html5 builds? * sudo apt -y i need to use debian based distros more dont i * also needs randr extensions * fuck it lets install all the x extensions and hope this is enough * libmesa is now libgl1-mesa * also needs alsa lib for sound man i love undocumented dependencies --- .github/workflows/build-shit.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-shit.yml b/.github/workflows/build-shit.yml index 11cecd138..7115f2f6d 100644 --- a/.github/workflows/build-shit.yml +++ b/.github/workflows/build-shit.yml @@ -27,6 +27,7 @@ jobs: - uses: ./.github/actions/setup-haxeshit - name: Build game? run: | + sudo apt-get install -y libx11-dev libxinerama-dev libxrandr-dev libgl1-mesa-dev libgl-dev libxi-dev libxext-dev libasound2-dev haxelib run lime build html5 -debug --times ls - uses: ./.github/actions/upload-itch From b564ad087bf3421d86748db5bde6737de0aff6e3 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 13 Jun 2023 01:04:29 -0400 Subject: [PATCH 16/33] vocals fix... lol! --- source/funkin/play/PlayState.hx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 3ea278f46..e8cfb1402 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1,5 +1,6 @@ package funkin.play; +import flixel.sound.FlxSound; import funkin.ui.story.StoryMenuState; import flixel.addons.display.FlxPieDial; import flixel.addons.transition.FlxTransitionableState; @@ -867,6 +868,7 @@ class PlayState extends MusicBeatState FlxG.sound.music.onComplete = endSong; trace('Playing vocals...'); + add(vocals); vocals.play(); #if discord_rpc From a42daecdc1ea0efceb3d178b6d4c4e8295d75369 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 13 Jun 2023 01:31:41 -0400 Subject: [PATCH 17/33] Delete ScriptedMusicBeatSubstate.hx --- source/funkin/modding/base/ScriptedMusicBeatSubstate.hx | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 source/funkin/modding/base/ScriptedMusicBeatSubstate.hx diff --git a/source/funkin/modding/base/ScriptedMusicBeatSubstate.hx b/source/funkin/modding/base/ScriptedMusicBeatSubstate.hx deleted file mode 100644 index 7dab3d7dd..000000000 --- a/source/funkin/modding/base/ScriptedMusicBeatSubstate.hx +++ /dev/null @@ -1,8 +0,0 @@ -package funkin.modding.base; - -/** - * A script that can be tied to a MusicBeatSubState. - * Create a scripted class that extends MusicBeatSubState to use this. - */ -@:hscriptClass -class ScriptedMusicBeatSubState extends funkin.MusicBeatSubState implements HScriptedClass {} From b78327145150f2a5b6e47af98d649bf89d0f0530 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 15 Jun 2023 00:11:20 -0400 Subject: [PATCH 18/33] ComboCounter->ComboMilestone --- source/funkin/{ComboCounter.hx => ComboMilestone.hx} | 0 source/funkin/play/PlayState.hx | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename source/funkin/{ComboCounter.hx => ComboMilestone.hx} (100%) diff --git a/source/funkin/ComboCounter.hx b/source/funkin/ComboMilestone.hx similarity index 100% rename from source/funkin/ComboCounter.hx rename to source/funkin/ComboMilestone.hx diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index e8cfb1402..38cdca905 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -2209,7 +2209,7 @@ class PlayState extends MusicBeatState if (shouldShowComboText) { - var animShit:ComboCounter = new ComboCounter(-100, 300, Highscore.tallies.combo); + var animShit:ComboMilestone = new ComboMilestone(-100, 300, Highscore.tallies.combo); animShit.scrollFactor.set(0.6, 0.6); animShit.cameras = [camHUD]; add(animShit); From 6ac4db48d9c736fb1fa08ad5c4e209f9abf6f018 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 15 Jun 2023 00:12:35 -0400 Subject: [PATCH 19/33] Rename combo milestone --- source/funkin/ComboMilestone.hx | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/source/funkin/ComboMilestone.hx b/source/funkin/ComboMilestone.hx index 28aed4560..b72eda2fa 100644 --- a/source/funkin/ComboMilestone.hx +++ b/source/funkin/ComboMilestone.hx @@ -5,14 +5,14 @@ import flixel.group.FlxGroup.FlxTypedGroup; import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup; import flixel.util.FlxTimer; -class ComboCounter extends FlxTypedSpriteGroup +class ComboMilestone extends FlxTypedSpriteGroup { var effectStuff:FlxSprite; var wasComboSetup:Bool = false; var daCombo:Int = 0; - var grpNumbers:FlxTypedGroup; + var grpNumbers:FlxTypedGroup; var onScreenTime:Float = 0; @@ -23,7 +23,7 @@ class ComboCounter extends FlxTypedSpriteGroup this.daCombo = daCombo; effectStuff = new FlxSprite(0, 0); - effectStuff.frames = Paths.getSparrowAtlas('noteCombo'); + effectStuff.frames = Paths.getSparrowAtlas('comboMilestone'); effectStuff.animation.addByPrefix('funny', 'NOTE COMBO animation', 24, false); effectStuff.animation.play('funny'); effectStuff.antialiasing = true; @@ -33,7 +33,7 @@ class ComboCounter extends FlxTypedSpriteGroup effectStuff.setGraphicSize(Std.int(effectStuff.width * 0.7)); add(effectStuff); - grpNumbers = new FlxTypedGroup(); + grpNumbers = new FlxTypedGroup(); // add(grpNumbers); } @@ -41,7 +41,7 @@ class ComboCounter extends FlxTypedSpriteGroup { if (onScreenTime < 0.9) { - new FlxTimer().start((Conductor.crochet / 1000) * 0.25, function(tmr) { + new FlxTimer().start((Conductor.beatLengthMs / 1000) * 0.25, function(tmr) { forceFinish(); }); } @@ -62,14 +62,14 @@ class ComboCounter extends FlxTypedSpriteGroup if (effectStuff.animation.curAnim.curFrame == 18) { - grpNumbers.forEach(function(spr:ComboNumber) { + grpNumbers.forEach(function(spr:ComboMilestoneNumber) { spr.animation.reset(); }); } if (effectStuff.animation.curAnim.curFrame == 20) { - grpNumbers.forEach(function(spr:ComboNumber) { + grpNumbers.forEach(function(spr:ComboMilestoneNumber) { spr.kill(); }); } @@ -86,7 +86,7 @@ class ComboCounter extends FlxTypedSpriteGroup while (daCombo > 0) { - var comboNumber:ComboNumber = new ComboNumber(450 - (100 * loopNum), 20 + 14 * loopNum, daCombo % 10); + var comboNumber:ComboMilestoneNumber = new ComboMilestoneNumber(450 - (100 * loopNum), 20 + 14 * loopNum, daCombo % 10); comboNumber.setGraphicSize(Std.int(comboNumber.width * 0.7)); grpNumbers.add(comboNumber); add(comboNumber); @@ -95,27 +95,17 @@ class ComboCounter extends FlxTypedSpriteGroup daCombo = Math.floor(daCombo / 10); } - - // var comboNumber:ComboNumber = new ComboNumber(420, 0, 0); - - // add to both, in the group just for ez organize/accessing - // grpNumbers.add(comboNumber); - // add(comboNumber); - - // var comboNumber2:ComboNumber = new ComboNumber(420 - 134, 44, 0); - // grpNumbers.add(comboNumber2); - // add(comboNumber2); } } -class ComboNumber extends FlxSprite +class ComboMilestoneNumber extends FlxSprite { public function new(x:Float, y:Float, digit:Int) { super(x - 20, y); var stringNum:String = Std.string(digit); - frames = Paths.getSparrowAtlas('noteComboNumbers'); + frames = Paths.getSparrowAtlas('comboMilestoneNumbers'); animation.addByPrefix(stringNum, stringNum, 24, false); animation.play(stringNum); antialiasing = true; From f6c38f9bdd8b488ec07adcd79b340b743cd7a27a Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 15 Jun 2023 00:13:18 -0400 Subject: [PATCH 20/33] Refactor conductor (crochet->lengthMs) --- source/funkin/Conductor.hx | 225 ++++++++++++++++++++----------------- 1 file changed, 125 insertions(+), 100 deletions(-) diff --git a/source/funkin/Conductor.hx b/source/funkin/Conductor.hx index e31b6d501..7f7e2b356 100644 --- a/source/funkin/Conductor.hx +++ b/source/funkin/Conductor.hx @@ -1,9 +1,8 @@ package funkin; -import flixel.util.FlxSignal; -import funkin.SongLoad.SwagSong; -import funkin.play.song.Song.SongDifficulty; import funkin.play.song.SongData.SongTimeChange; +import flixel.util.FlxSignal; +import funkin.play.song.Song.SongDifficulty; typedef BPMChangeEvent = { @@ -12,18 +11,27 @@ typedef BPMChangeEvent = var bpm:Float; } +/** + * A global source of truth for timing information. + */ class Conductor { - /** - * The list of time changes in the song. - * There should be at least one time change (at the beginning of the song) to define the BPM. - */ - static var timeChanges:Array = []; + static final STEPS_PER_BEAT:Int = 4; - /** - * The current time change. - */ - static var currentTimeChange:SongTimeChange; + // onBeatHit is called every quarter note + // onStepHit is called every sixteenth note + // 4/4 = 4 beats per measure = 16 steps per measure + // 120 BPM = 120 quarter notes per minute = 2 onBeatHit per second + // 120 BPM = 480 sixteenth notes per minute = 8 onStepHit per second + // 60 BPM = 60 quarter notes per minute = 1 onBeatHit per second + // 60 BPM = 240 sixteenth notes per minute = 4 onStepHit per second + // 3/4 = 3 beats per measure = 12 steps per measure + // (IDENTICAL TO 4/4 but shorter measure length) + // 120 BPM = 120 quarter notes per minute = 2 onBeatHit per second + // 120 BPM = 480 sixteenth notes per minute = 8 onStepHit per second + // 60 BPM = 60 quarter notes per minute = 1 onBeatHit per second + // 60 BPM = 240 sixteenth notes per minute = 4 onStepHit per second + // 7/8 = 3.5 beats per measure = 14 steps per measure /** * The current position in the song in milliseconds. @@ -47,8 +55,25 @@ class Conductor static var bpmOverride:Null = null; - // OLD, replaced with timeChanges. - public static var bpmChangeMap:Array = []; + /** + * Current position in the song, in whole measures. + */ + public static var currentMeasure(default, null):Int; + + /** + * Current position in the song, in whole beats. + **/ + public static var currentBeat(default, null):Int; + + /** + * Current position in the song, in whole steps. + */ + public static var currentStep(default, null):Int; + + /** + * Current position in the song, in steps and fractions of a step. + */ + public static var currentStepTime(default, null):Float; /** * Duration of a measure in milliseconds. Calculated based on bpm. @@ -57,29 +82,33 @@ class Conductor static function get_measureLengthMs():Float { - return crochet * timeSignatureNumerator; + return beatLengthMs * timeSignatureNumerator; } /** - * Duration of a beat in millisecond. Calculated based on bpm. + * Duration of a beat (quarter note) in milliseconds. Calculated based on bpm. */ - public static var crochet(get, null):Float; + public static var beatLengthMs(get, null):Float; - static function get_crochet():Float + static function get_beatLengthMs():Float { + // Tied directly to BPM. return ((60 / bpm) * 1000); } /** - * Duration of a step (quarter) in milliseconds. Calculated based on bpm. + * Duration of a step (sixteenth) in milliseconds. Calculated based on bpm. */ - public static var stepCrochet(get, null):Float; + public static var stepLengthMs(get, null):Float; - static function get_stepCrochet():Float + static function get_stepLengthMs():Float { - return crochet / timeSignatureNumerator; + return beatLengthMs / STEPS_PER_BEAT; } + /** + * The numerator of the current time signature (number of notes in a measure) + */ public static var timeSignatureNumerator(get, null):Int; static function get_timeSignatureNumerator():Int @@ -89,6 +118,9 @@ class Conductor return currentTimeChange.timeSignatureNum; } + /** + * The numerator of the current time signature (length of notes in a measure) + */ public static var timeSignatureDenominator(get, null):Int; static function get_timeSignatureDenominator():Int @@ -98,30 +130,57 @@ class Conductor return currentTimeChange.timeSignatureDen; } - /** - * Current position in the song, in beats. - **/ - public static var currentBeat(default, null):Int; - - /** - * Current position in the song, in steps. - */ - public static var currentStep(default, null):Int; - - /** - * Current position in the song, in steps and fractions of a step. - */ - public static var currentStepTime(default, null):Float; - - public static var beatHit(default, null):FlxSignal = new FlxSignal(); - public static var stepHit(default, null):FlxSignal = new FlxSignal(); - - public static var lastSongPos:Float; - public static var visualOffset:Float = 0; - public static var audioOffset:Float = 0; public static var offset:Float = 0; - // TODO: Add code to update this. + // TODO: What's the difference between visualOffset and audioOffset? + public static var visualOffset:Float = 0; + public static var audioOffset:Float = 0; + + // + // Signals + // + + /** + * Signal that is dispatched every measure. + * At 120 BPM 4/4, this is dispatched every 2 seconds. + * At 120 BPM 3/4, this is dispatched every 1.5 seconds. + */ + public static var measureHit(default, null):FlxSignal = new FlxSignal(); + + /** + * Signal that is dispatched every beat. + * At 120 BPM 4/4, this is dispatched every 0.5 seconds. + * At 120 BPM 3/4, this is dispatched every 0.5 seconds. + */ + public static var beatHit(default, null):FlxSignal = new FlxSignal(); + + /** + * Signal that is dispatched when a step is hit. + * At 120 BPM 4/4, this is dispatched every 0.125 seconds. + * At 120 BPM 3/4, this is dispatched every 0.125 seconds. + */ + public static var stepHit(default, null):FlxSignal = new FlxSignal(); + + // + // Internal Variables + // + + /** + * The list of time changes in the song. + * There should be at least one time change (at the beginning of the song) to define the BPM. + */ + static var timeChanges:Array = []; + + /** + * The current time change. + */ + static var currentTimeChange:SongTimeChange; + + public static var lastSongPos:Float; + + /** + * The number of beats (whole notes) in a measure. + */ public static var beatsPerMeasure(get, null):Int; static function get_beatsPerMeasure():Int @@ -129,33 +188,17 @@ class Conductor return timeSignatureNumerator; } + /** + * The number of steps (quarter-notes) in a measure. + */ public static var stepsPerMeasure(get, null):Int; static function get_stepsPerMeasure():Int { - // Is this always x4? + // This is always 4, b return timeSignatureNumerator * 4; } - function new() {} - - public static function getLastBPMChange() - { - var lastChange:BPMChangeEvent = - { - stepTime: 0, - songTime: 0, - bpm: 0 - } - for (i in 0...Conductor.bpmChangeMap.length) - { - if (Conductor.songPosition >= Conductor.bpmChangeMap[i].songTime) lastChange = Conductor.bpmChangeMap[i]; - - if (Conductor.songPosition < Conductor.bpmChangeMap[i].songTime) break; - } - return lastChange; - } - /** * Forcibly defines the current BPM of the song. * Useful for things like the chart editor that need to manipulate BPM in real time. @@ -165,11 +208,16 @@ class Conductor * WARNING: Avoid this for things like setting the BPM of the title screen music, * you should have a metadata file for it instead. */ - public static function forceBPM(?bpm:Float = null) + public static function forceBPM(?bpm:Float = null):Void { - if (bpm != null) trace('[CONDUCTOR] Forcing BPM to ' + bpm); + if (bpm != null) + { + trace('[CONDUCTOR] Forcing BPM to ' + bpm); + } else + { trace('[CONDUCTOR] Resetting BPM to default'); + } Conductor.bpmOverride = bpm; } @@ -180,15 +228,15 @@ class Conductor * @param songPosition The current position in the song in milliseconds. * Leave blank to use the FlxG.sound.music position. */ - public static function update(songPosition:Float = null) + public static function update(songPosition:Float = null):Void { if (songPosition == null) songPosition = (FlxG.sound.music != null) ? FlxG.sound.music.time + Conductor.offset : 0.0; - var oldBeat = currentBeat; - var oldStep = currentStep; + var oldMeasure:Int = currentMeasure; + var oldBeat:Int = currentBeat; + var oldStep:Int = currentStep; Conductor.songPosition = songPosition; - // Conductor.bpm = Conductor.getLastBPMChange().bpm; currentTimeChange = timeChanges[0]; for (i in 0...timeChanges.length) @@ -204,14 +252,14 @@ class Conductor } else if (currentTimeChange != null) { - currentStepTime = (currentTimeChange.beatTime * 4) + (songPosition - currentTimeChange.timeStamp) / stepCrochet; + currentStepTime = (currentTimeChange.beatTime * 4) + (songPosition - currentTimeChange.timeStamp) / stepLengthMs; currentStep = Math.floor(currentStepTime); currentBeat = Math.floor(currentStep / 4); } else { // Assume a constant BPM equal to the forced value. - currentStepTime = (songPosition / stepCrochet); + currentStepTime = (songPosition / stepLengthMs); currentStep = Math.floor(currentStepTime); currentBeat = Math.floor(currentStep / 4); } @@ -226,37 +274,14 @@ class Conductor { beatHit.dispatch(); } - } - @:deprecated // Switch to TimeChanges instead. - public static function mapBPMChanges(song:SwagSong) - { - bpmChangeMap = []; - - var curBPM:Float = song.bpm; - var totalSteps:Int = 0; - var totalPos:Float = 0; - for (i in 0...SongLoad.getSong().length) + if (currentMeasure != oldMeasure) { - if (SongLoad.getSong()[i].changeBPM && SongLoad.getSong()[i].bpm != curBPM) - { - curBPM = SongLoad.getSong()[i].bpm; - var event:BPMChangeEvent = - { - stepTime: totalSteps, - songTime: totalPos, - bpm: curBPM - }; - bpmChangeMap.push(event); - } - - var deltaSteps:Int = SongLoad.getSong()[i].lengthInSteps; - totalSteps += deltaSteps; - totalPos += ((60 / curBPM) * 1000 / 4) * deltaSteps; + measureHit.dispatch(); } } - public static function mapTimeChanges(songTimeChanges:Array) + public static function mapTimeChanges(songTimeChanges:Array):Void { timeChanges = []; @@ -278,7 +303,7 @@ class Conductor if (timeChanges.length == 0) { // Assume a constant BPM equal to the forced value. - return Math.floor(ms / stepCrochet); + return Math.floor(ms / stepLengthMs); } else { @@ -299,7 +324,7 @@ class Conductor } } - resultStep += Math.floor((ms - lastTimeChange.timeStamp) / stepCrochet); + resultStep += Math.floor((ms - lastTimeChange.timeStamp) / stepLengthMs); return resultStep; } From 506e4bf6806cf900d2a4e35f2629b6454c4f88f0 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 15 Jun 2023 00:15:57 -0400 Subject: [PATCH 21/33] Propagate Conductor rework to dependent classes. --- source/funkin/LatencyState.hx | 28 ++--- source/funkin/MusicBeatSubState.hx | 108 ++++++++++++------ source/funkin/Note.hx | 2 +- source/funkin/play/Countdown.hx | 6 +- source/funkin/play/character/BaseCharacter.hx | 2 +- .../funkin/play/event/ZoomCameraSongEvent.hx | 11 +- source/funkin/play/song/SongData.hx | 4 +- source/funkin/play/stage/Stage.hx | 2 +- source/funkin/ui/PopUpStuff.hx | 6 +- .../ui/debug/charting/ChartEditorState.hx | 24 ++-- 10 files changed, 118 insertions(+), 75 deletions(-) diff --git a/source/funkin/LatencyState.hx b/source/funkin/LatencyState.hx index 694e9c3e5..347454253 100644 --- a/source/funkin/LatencyState.hx +++ b/source/funkin/LatencyState.hx @@ -88,14 +88,14 @@ class LatencyState extends MusicBeatSubState // // musSpec.visType = FREQUENCIES; // add(musSpec); - for (beat in 0...Math.floor(FlxG.sound.music.length / Conductor.crochet)) + for (beat in 0...Math.floor(FlxG.sound.music.length / Conductor.beatLengthMs)) { - var beatTick:FlxSprite = new FlxSprite(songPosToX(beat * Conductor.crochet), FlxG.height - 15); + var beatTick:FlxSprite = new FlxSprite(songPosToX(beat * Conductor.beatLengthMs), FlxG.height - 15); beatTick.makeGraphic(2, 15); beatTick.alpha = 0.3; add(beatTick); - var offsetTxt:FlxText = new FlxText(songPosToX(beat * Conductor.crochet), FlxG.height - 26, 0, "swag"); + var offsetTxt:FlxText = new FlxText(songPosToX(beat * Conductor.beatLengthMs), FlxG.height - 26, 0, "swag"); offsetTxt.alpha = 0.5; diffGrp.add(offsetTxt); @@ -127,7 +127,7 @@ class LatencyState extends MusicBeatSubState for (i in 0...32) { - var note:Note = new Note(Conductor.crochet * i, 1); + var note:Note = new Note(Conductor.beatLengthMs * i, 1); noteGrp.add(note); } @@ -143,9 +143,9 @@ class LatencyState extends MusicBeatSubState override function stepHit():Bool { - if (curStep % 4 == 2) + if (Conductor.currentStep % 4 == 2) { - blocks.members[((curBeat % 8) + 1) % 8].alpha = 0.5; + blocks.members[((Conductor.currentBeat % 8) + 1) % 8].alpha = 0.5; } return super.stepHit(); @@ -153,11 +153,11 @@ class LatencyState extends MusicBeatSubState override function beatHit():Bool { - if (curBeat % 8 == 0) blocks.forEach(blok -> { + if (Conductor.currentBeat % 8 == 0) blocks.forEach(blok -> { blok.alpha = 0; }); - blocks.members[curBeat % 8].alpha = 1; + blocks.members[Conductor.currentBeat % 8].alpha = 1; // block.visible = !block.visible; return super.beatHit(); @@ -198,8 +198,8 @@ class LatencyState extends MusicBeatSubState offsetText.text = "AUDIO Offset: " + Conductor.audioOffset + "ms"; offsetText.text += "\nVIDOE Offset: " + Conductor.visualOffset + "ms"; - offsetText.text += "\ncurStep: " + curStep; - offsetText.text += "\ncurBeat: " + curBeat; + offsetText.text += "\ncurrentStep: " + Conductor.currentStep; + offsetText.text += "\ncurrentBeat: " + Conductor.currentBeat; var avgOffsetInput:Float = 0; @@ -255,7 +255,7 @@ class LatencyState extends MusicBeatSubState if (daNote.y < 0 - daNote.height) { daNote.alpha = 1; - // daNote.data.strumTime += Conductor.crochet * 8; + // daNote.data.strumTime += Conductor.beatLengthMs * 8; } }); @@ -266,12 +266,12 @@ class LatencyState extends MusicBeatSubState { Conductor.songPosition = swagSong.getTimeWithDiff(); - var closestBeat:Int = Math.round(Conductor.songPosition / Conductor.crochet) % diffGrp.members.length; - var getDiff:Float = Conductor.songPosition - (closestBeat * Conductor.crochet); + var closestBeat:Int = Math.round(Conductor.songPosition / Conductor.beatLengthMs) % diffGrp.members.length; + var getDiff:Float = Conductor.songPosition - (closestBeat * Conductor.beatLengthMs); getDiff -= Conductor.visualOffset; // lil fix for end of song - if (closestBeat == 0 && getDiff >= Conductor.crochet * 2) getDiff -= FlxG.sound.music.length; + if (closestBeat == 0 && getDiff >= Conductor.beatLengthMs * 2) getDiff -= FlxG.sound.music.length; trace("\tDISTANCE TO CLOSEST BEAT: " + getDiff + "ms"); trace("\tCLOSEST BEAT: " + closestBeat); diff --git a/source/funkin/MusicBeatSubState.hx b/source/funkin/MusicBeatSubState.hx index 440e25c96..5c6635a02 100644 --- a/source/funkin/MusicBeatSubState.hx +++ b/source/funkin/MusicBeatSubState.hx @@ -5,62 +5,96 @@ import flixel.util.FlxColor; import funkin.Conductor.BPMChangeEvent; import funkin.modding.events.ScriptEvent; import funkin.modding.module.ModuleHandler; +import flixel.text.FlxText; +import funkin.modding.PolymodHandler; /** * MusicBeatSubState reincorporates the functionality of MusicBeatState into an FlxSubState. */ class MusicBeatSubState extends FlxSubState { + public var leftWatermarkText:FlxText = null; + public var rightWatermarkText:FlxText = null; + public function new(bgColor:FlxColor = FlxColor.TRANSPARENT) { super(bgColor); } - var curStep:Int = 0; - var curBeat:Int = 0; var controls(get, never):Controls; inline function get_controls():Controls return PlayerSettings.player1.controls; - override function update(elapsed:Float) + override function create():Void { - // everyStep(); - var oldStep:Int = curStep; + super.create(); - updateCurStep(); - curBeat = Math.floor(curStep / 4); + createWatermarkText(); - if (oldStep != curStep && curStep >= 0) stepHit(); + Conductor.beatHit.add(this.beatHit); + Conductor.stepHit.add(this.stepHit); + } + public override function destroy():Void + { + super.destroy(); + Conductor.beatHit.remove(this.beatHit); + Conductor.stepHit.remove(this.stepHit); + } + + override function update(elapsed:Float):Void + { super.update(elapsed); + + // Rebindable volume keys. + if (controls.VOLUME_MUTE) FlxG.sound.toggleMuted(); + else if (controls.VOLUME_UP) FlxG.sound.changeVolume(0.1); + else if (controls.VOLUME_DOWN) FlxG.sound.changeVolume(-0.1); + + // 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(); } - function updateCurStep():Void + function debug_refreshModules() { - var lastChange:BPMChangeEvent = - { - stepTime: 0, - songTime: 0, - bpm: 0 - } - for (i in 0...Conductor.bpmChangeMap.length) - { - if (Conductor.songPosition > Conductor.bpmChangeMap[i].songTime) lastChange = Conductor.bpmChangeMap[i]; - } + PolymodHandler.forceReloadAssets(); - curStep = lastChange.stepTime + Math.floor(((Conductor.songPosition - Conductor.audioOffset) - lastChange.songTime) / Conductor.stepCrochet); + // Restart the current state, so old data is cleared. + FlxG.resetState(); } + /** + * Called when a step is hit in the current song. + * Continues outside of PlayState, for things like animations in menus. + * @return Whether the event should continue (not canceled). + */ public function stepHit():Bool { - var event = new SongTimeScriptEvent(ScriptEvent.SONG_STEP_HIT, curBeat, curStep); + var event:ScriptEvent = new SongTimeScriptEvent(ScriptEvent.SONG_STEP_HIT, Conductor.currentBeat, Conductor.currentStep); dispatchEvent(event); if (event.eventCanceled) return false; - if (curStep % 4 == 0) beatHit(); + return true; + } + + /** + * Called when a beat is hit in the current song. + * Continues outside of PlayState, for things like animations in menus. + * @return Whether the event should continue (not canceled). + */ + public function beatHit():Bool + { + var event:ScriptEvent = new SongTimeScriptEvent(ScriptEvent.SONG_BEAT_HIT, Conductor.currentBeat, Conductor.currentStep); + + dispatchEvent(event); + + if (event.eventCanceled) return false; return true; } @@ -70,6 +104,25 @@ class MusicBeatSubState extends FlxSubState ModuleHandler.callEvent(event); } + function createWatermarkText():Void + { + // Both have an xPos of 0, but a width equal to the full screen. + // The rightWatermarkText is right aligned, which puts the text in the correct spot. + leftWatermarkText = new FlxText(0, FlxG.height - 18, FlxG.width, '', 12); + rightWatermarkText = new FlxText(0, FlxG.height - 18, FlxG.width, '', 12); + + // 100,000 should be good enough. + leftWatermarkText.zIndex = 100000; + rightWatermarkText.zIndex = 100000; + leftWatermarkText.scrollFactor.set(0, 0); + rightWatermarkText.scrollFactor.set(0, 0); + leftWatermarkText.setFormat('VCR OSD Mono', 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); + rightWatermarkText.setFormat('VCR OSD Mono', 16, FlxColor.WHITE, RIGHT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); + + add(leftWatermarkText); + add(rightWatermarkText); + } + /** * Close this substate and replace it with a different one. */ @@ -78,15 +131,4 @@ class MusicBeatSubState extends FlxSubState this.close(); this._parentState.openSubState(substate); } - - public function beatHit():Bool - { - var event = new SongTimeScriptEvent(ScriptEvent.SONG_BEAT_HIT, curBeat, curStep); - - dispatchEvent(event); - - if (event.eventCanceled) return false; - - return true; - } } diff --git a/source/funkin/Note.hx b/source/funkin/Note.hx index 71c63a94e..ea99449b1 100644 --- a/source/funkin/Note.hx +++ b/source/funkin/Note.hx @@ -207,7 +207,7 @@ class Note extends FlxSprite prevNote.animation.play(prevNote.colorName + 'hold'); prevNote.updateHitbox(); - var scaleThing:Float = Math.round((Conductor.stepCrochet) * (0.45 * FlxMath.roundDecimal(SongLoad.getSpeed(), 2))); + var scaleThing:Float = Math.round((Conductor.stepLengthMs) * (0.45 * FlxMath.roundDecimal(PlayState.instance.currentChart.scrollSpeed, 2))); // get them a LIL closer together cuz the antialiasing blurs the edges if (antialiasing) scaleThing *= 1.0 + (1.0 / prevNote.frameHeight); prevNote.scale.y = scaleThing / prevNote.frameHeight; diff --git a/source/funkin/play/Countdown.hx b/source/funkin/play/Countdown.hx index 016b21c6c..169bda24b 100644 --- a/source/funkin/play/Countdown.hx +++ b/source/funkin/play/Countdown.hx @@ -38,7 +38,7 @@ class Countdown stopCountdown(); PlayState.instance.isInCountdown = true; - Conductor.songPosition = Conductor.crochet * -5; + Conductor.songPosition = Conductor.beatLengthMs * -5; // Handle onBeatHit events manually @:privateAccess PlayState.instance.dispatchEvent(new SongTimeScriptEvent(ScriptEvent.SONG_BEAT_HIT, 0, 0)); @@ -46,7 +46,7 @@ class Countdown // The timer function gets called based on the beat of the song. countdownTimer = new FlxTimer(); - countdownTimer.start(Conductor.crochet / 1000, function(tmr:FlxTimer) { + countdownTimer.start(Conductor.beatLengthMs / 1000, function(tmr:FlxTimer) { countdownStep = decrement(countdownStep); // Handle onBeatHit events manually @@ -212,7 +212,7 @@ class Countdown countdownSprite.screenCenter(); // Fade sprite in, then out, then destroy it. - FlxTween.tween(countdownSprite, {y: countdownSprite.y += 100, alpha: 0}, Conductor.crochet / 1000, + FlxTween.tween(countdownSprite, {y: countdownSprite.y += 100, alpha: 0}, Conductor.beatLengthMs / 1000, { ease: FlxEase.cubeInOut, onComplete: function(twn:FlxTween) { diff --git a/source/funkin/play/character/BaseCharacter.hx b/source/funkin/play/character/BaseCharacter.hx index f4db7f66f..bdf7ef591 100644 --- a/source/funkin/play/character/BaseCharacter.hx +++ b/source/funkin/play/character/BaseCharacter.hx @@ -367,7 +367,7 @@ class BaseCharacter extends Bopper // This lets you add frames to the end of the sing animation to ease back into the idle! holdTimer += event.elapsed; - var singTimeSec:Float = singTimeSec * (Conductor.crochet * 0.001); // x beats, to ms. + var singTimeSec:Float = singTimeSec * (Conductor.beatLengthMs * 0.001); // x beats, to ms. if (getCurrentAnimation().endsWith('miss')) singTimeSec *= 2; // makes it feel more awkward when you miss diff --git a/source/funkin/play/event/ZoomCameraSongEvent.hx b/source/funkin/play/event/ZoomCameraSongEvent.hx index e6e9c843d..79425d564 100644 --- a/source/funkin/play/event/ZoomCameraSongEvent.hx +++ b/source/funkin/play/event/ZoomCameraSongEvent.hx @@ -10,7 +10,7 @@ import funkin.play.event.SongEventData.SongEventFieldType; /** * This class represents a handler for camera zoom events. - * + * * Example: Zoom to 1.3x: * ``` * { @@ -18,8 +18,8 @@ import funkin.play.event.SongEventData.SongEventFieldType; * 'v': 1.3 * } * ``` - * - * Example: Zoom to 1.3x + * + * Example: Zoom to 1.3x * ``` * { * 'e': 'FocusCamera', @@ -29,7 +29,7 @@ import funkin.play.event.SongEventData.SongEventFieldType; * } * } * ``` - * + * * Example: Focus on (100, 100): * ``` * { @@ -76,7 +76,8 @@ class ZoomCameraSongEvent extends SongEvent return; } - FlxTween.tween(PlayState.instance, {defaultCameraZoom: zoom * FlxCamera.defaultZoom}, (Conductor.stepCrochet * duration / 1000), {ease: easeFunction}); + FlxTween.tween(PlayState.instance, {defaultCameraZoom: zoom * FlxCamera.defaultZoom}, (Conductor.stepLengthMs * duration / 1000), + {ease: easeFunction}); } } diff --git a/source/funkin/play/song/SongData.hx b/source/funkin/play/song/SongData.hx index 78593c6c0..282734d10 100644 --- a/source/funkin/play/song/SongData.hx +++ b/source/funkin/play/song/SongData.hx @@ -365,7 +365,7 @@ abstract SongNoteData(RawSongNoteData) public function get_stepTime():Float { // TODO: Account for changes in BPM. - return this.t / Conductor.stepCrochet; + return this.t / Conductor.stepLengthMs; } /** @@ -551,7 +551,7 @@ abstract SongEventData(RawSongEventData) public function get_stepTime():Float { // TODO: Account for changes in BPM. - return this.t / Conductor.stepCrochet; + return this.t / Conductor.stepLengthMs; } public var event(get, set):String; diff --git a/source/funkin/play/stage/Stage.hx b/source/funkin/play/stage/Stage.hx index 36d1600a6..ef2d28430 100644 --- a/source/funkin/play/stage/Stage.hx +++ b/source/funkin/play/stage/Stage.hx @@ -658,7 +658,7 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass public function onBeatHit(event:SongTimeScriptEvent):Void { // Override me in your scripted stage to perform custom behavior! - // Make sure to call super.onBeatHit(curBeat) if you want to keep the boppers dancing. + // Make sure to call super.onBeatHit(event) if you want to keep the boppers dancing. for (bopper in boppers) { diff --git a/source/funkin/ui/PopUpStuff.hx b/source/funkin/ui/PopUpStuff.hx index c5828dd0a..20380f50a 100644 --- a/source/funkin/ui/PopUpStuff.hx +++ b/source/funkin/ui/PopUpStuff.hx @@ -59,7 +59,7 @@ class PopUpStuff extends FlxTypedGroup remove(rating, true); rating.destroy(); }, - startDelay: Conductor.crochet * 0.001 + startDelay: Conductor.beatLengthMs * 0.001 }); } @@ -109,7 +109,7 @@ class PopUpStuff extends FlxTypedGroup remove(comboSpr, true); comboSpr.destroy(); }, - startDelay: Conductor.crochet * 0.001 + startDelay: Conductor.beatLengthMs * 0.001 }); var seperatedScore:Array = []; @@ -155,7 +155,7 @@ class PopUpStuff extends FlxTypedGroup remove(numScore, true); numScore.destroy(); }, - startDelay: Conductor.crochet * 0.002 + startDelay: Conductor.beatLengthMs * 0.002 }); daLoop++; diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index c61637536..18e34c72b 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -189,12 +189,12 @@ class ChartEditorState extends HaxeUIState function get_scrollPositionInMs():Float { - return scrollPositionInSteps * Conductor.stepCrochet; + return scrollPositionInSteps * Conductor.stepLengthMs; } function set_scrollPositionInMs(value:Float):Float { - scrollPositionInPixels = value / Conductor.stepCrochet; + scrollPositionInPixels = value / Conductor.stepLengthMs; return value; } @@ -223,7 +223,7 @@ class ChartEditorState extends HaxeUIState function get_playheadPositionInMs():Float { - return playheadPositionInSteps * Conductor.stepCrochet; + return playheadPositionInSteps * Conductor.stepLengthMs; } /** @@ -263,7 +263,7 @@ class ChartEditorState extends HaxeUIState function get_songLengthInMs():Float { - return songLengthInSteps * Conductor.stepCrochet; + return songLengthInSteps * Conductor.stepLengthMs; } function set_songLengthInMs(value:Float):Float @@ -1667,7 +1667,7 @@ class ChartEditorState extends HaxeUIState // The song position of the cursor, in steps. var cursorFractionalStep:Float = cursorY / GRID_SIZE / (16 / noteSnapQuant); var cursorStep:Int = Std.int(Math.floor(cursorFractionalStep)); - var cursorMs:Float = cursorStep * Conductor.stepCrochet * (16 / noteSnapQuant); + var cursorMs:Float = cursorStep * Conductor.stepLengthMs * (16 / noteSnapQuant); // The direction value for the column at the cursor. var cursorColumn:Int = Math.floor(cursorX / GRID_SIZE); if (cursorColumn < 0) cursorColumn = 0; @@ -1705,7 +1705,7 @@ class ChartEditorState extends HaxeUIState // We released the mouse. Select the notes in the box. var cursorFractionalStepStart:Float = cursorYStart / GRID_SIZE; var cursorStepStart:Int = Math.floor(cursorFractionalStepStart); - var cursorMsStart:Float = cursorStepStart * Conductor.stepCrochet; + var cursorMsStart:Float = cursorStepStart * Conductor.stepLengthMs; var cursorColumnBase:Int = Math.floor(cursorX / GRID_SIZE); var cursorColumnBaseStart:Int = Math.floor(cursorXStart / GRID_SIZE); @@ -1878,11 +1878,11 @@ class ChartEditorState extends HaxeUIState // Handle extending the note as you drag. // Since use Math.floor and stepCrochet here, the hold notes will be beat snapped. - var dragLengthSteps:Float = Math.floor((cursorMs - currentPlaceNoteData.time) / Conductor.stepCrochet); + var dragLengthSteps:Float = Math.floor((cursorMs - currentPlaceNoteData.time) / Conductor.stepLengthMs); // Without this, the newly placed note feels too short compared to the user's input. var INCREMENT:Float = 1.0; - var dragLengthMs:Float = (dragLengthSteps + INCREMENT) * Conductor.stepCrochet; + var dragLengthMs:Float = (dragLengthSteps + INCREMENT) * Conductor.stepLengthMs; // TODO: Add and update some sort of preview? @@ -2187,7 +2187,7 @@ class ChartEditorState extends HaxeUIState } // Get the position the note should be at. - var noteTimePixels:Float = noteData.time / Conductor.stepCrochet * GRID_SIZE; + var noteTimePixels:Float = noteData.time / Conductor.stepLengthMs * GRID_SIZE; // Make sure the note appears when scrolling up. var modifiedViewAreaTop = viewAreaTop - GRID_SIZE; @@ -2213,7 +2213,7 @@ class ChartEditorState extends HaxeUIState { // If the note is a hold, we need to make sure it's long enough. var noteLengthMs:Float = noteSprite.noteData.length; - var noteLengthSteps:Float = (noteLengthMs / Conductor.stepCrochet); + var noteLengthSteps:Float = (noteLengthMs / Conductor.stepLengthMs); var lastNoteSprite:ChartEditorNoteSprite = noteSprite; while (noteLengthSteps > 0) @@ -2237,7 +2237,7 @@ class ChartEditorState extends HaxeUIState // Make sure the last note sprite shows the end cap properly. lastNoteSprite.childNoteSprite = null; - // var noteLengthPixels:Float = (noteLengthMs / Conductor.stepCrochet + 1) * GRID_SIZE; + // var noteLengthPixels:Float = (noteLengthMs / Conductor.stepLengthMs + 1) * GRID_SIZE; // add(new FlxSprite(noteSprite.x, noteSprite.y - renderedNotes.y + noteLengthPixels).makeGraphic(40, 2, 0xFFFF0000)); } } @@ -2252,7 +2252,7 @@ class ChartEditorState extends HaxeUIState } // Get the position the event should be at. - var eventTimePixels:Float = eventData.time / Conductor.stepCrochet * GRID_SIZE; + var eventTimePixels:Float = eventData.time / Conductor.stepLengthMs * GRID_SIZE; // Make sure the event appears when scrolling up. var modifiedViewAreaTop = viewAreaTop - GRID_SIZE; From 1191fff913c143e8171a8d35fd17a543f44f5900 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 15 Jun 2023 00:28:40 -0400 Subject: [PATCH 22/33] Additional controls (volume, cutscene skip) --- source/funkin/Controls.hx | 339 ++++++++++++++++++++++++------- source/funkin/ui/ControlsMenu.hx | 125 ++++++++++-- 2 files changed, 373 insertions(+), 91 deletions(-) diff --git a/source/funkin/Controls.hx b/source/funkin/Controls.hx index 243570c27..46681adbd 100644 --- a/source/funkin/Controls.hx +++ b/source/funkin/Controls.hx @@ -41,12 +41,18 @@ enum Control ACCEPT; BACK; PAUSE; + CUTSCENE_ADVANCE; + CUTSCENE_SKIP; + VOLUME_UP; + VOLUME_DOWN; + VOLUME_MUTE; #if CAN_CHEAT CHEAT; #end } -enum abstract Action(String) to String from String +@:enum +abstract Action(String) to String from String { var UI_UP = "ui_up"; var UI_LEFT = "ui_left"; @@ -75,6 +81,11 @@ enum abstract Action(String) to String from String var ACCEPT = "accept"; var BACK = "back"; var PAUSE = "pause"; + var CUTSCENE_ADVANCE = "cutscene_advance"; + var CUTSCENE_SKIP = "cutscene_skip"; + var VOLUME_UP = "volume_up"; + var VOLUME_DOWN = "volume_down"; + var VOLUME_MUTE = "volume_mute"; var RESET = "reset"; #if CAN_CHEAT var CHEAT = "cheat"; @@ -129,6 +140,11 @@ class Controls extends FlxActionSet var _back = new FlxActionDigital(Action.BACK); var _pause = new FlxActionDigital(Action.PAUSE); var _reset = new FlxActionDigital(Action.RESET); + var _cutscene_advance = new FlxActionDigital(Action.CUTSCENE_ADVANCE); + var _cutscene_skip = new FlxActionDigital(Action.CUTSCENE_SKIP); + var _volume_up = new FlxActionDigital(Action.VOLUME_UP); + var _volume_down = new FlxActionDigital(Action.VOLUME_DOWN); + var _volume_mute = new FlxActionDigital(Action.VOLUME_MUTE); #if CAN_CHEAT var _cheat = new FlxActionDigital(Action.CHEAT); #end @@ -273,6 +289,31 @@ class Controls extends FlxActionSet inline function get_PAUSE() return _pause.check(); + public var CUTSCENE_ADVANCE(get, never):Bool; + + inline function get_CUTSCENE_ADVANCE() + return _cutscene_advance.check(); + + public var CUTSCENE_SKIP(get, never):Bool; + + inline function get_CUTSCENE_SKIP() + return _cutscene_skip.check(); + + public var VOLUME_UP(get, never):Bool; + + inline function get_VOLUME_UP() + return _volume_up.check(); + + public var VOLUME_DOWN(get, never):Bool; + + inline function get_VOLUME_DOWN() + return _volume_down.check(); + + public var VOLUME_MUTE(get, never):Bool; + + inline function get_VOLUME_MUTE() + return _volume_mute.check(); + public var RESET(get, never):Bool; inline function get_RESET() @@ -316,6 +357,11 @@ class Controls extends FlxActionSet add(_accept); add(_back); add(_pause); + add(_cutscene_advance); + add(_cutscene_skip); + add(_volume_up); + add(_volume_down); + add(_volume_mute); add(_reset); #if CAN_CHEAT add(_cheat); @@ -377,6 +423,11 @@ class Controls extends FlxActionSet case BACK: _back; case PAUSE: _pause; case RESET: _reset; + case CUTSCENE_ADVANCE: _cutscene_advance; + case CUTSCENE_SKIP: _cutscene_skip; + case VOLUME_UP: _volume_up; + case VOLUME_DOWN: _volume_down; + case VOLUME_MUTE: _volume_mute; #if CAN_CHEAT case CHEAT: _cheat; #end @@ -437,6 +488,16 @@ class Controls extends FlxActionSet func(_back, JUST_PRESSED); case PAUSE: func(_pause, JUST_PRESSED); + case CUTSCENE_ADVANCE: + func(_cutscene_advance, JUST_PRESSED); + case CUTSCENE_SKIP: + func(_cutscene_skip, PRESSED); + case VOLUME_UP: + func(_volume_up, JUST_PRESSED); + case VOLUME_DOWN: + func(_volume_down, JUST_PRESSED); + case VOLUME_MUTE: + func(_volume_mute, JUST_PRESSED); case RESET: func(_reset, JUST_PRESSED); #if CAN_CHEAT @@ -454,37 +515,70 @@ class Controls extends FlxActionSet switch(device) { case Keys: - forEachBound(control, function(action, _) replaceKey(action, toAdd, toRemove)); + forEachBound(control, function(action, state) replaceKey(action, toAdd, toRemove, state)); case Gamepad(id): - forEachBound(control, function(action, _) replaceButton(action, id, toAdd, toRemove)); + forEachBound(control, function(action, state) replaceButton(action, id, toAdd, toRemove, state)); } } - function replaceKey(action:FlxActionDigital, toAdd:Int, toRemove:Int) + function replaceKey(action:FlxActionDigital, toAdd:FlxKey, toRemove:FlxKey, state:FlxInputState) { + if (action.inputs.length == 0) { + // Add the keybind, don't replace. + addKeys(action, [toAdd], state); + return; + } + + var hasReplaced:Bool = false; for (i in 0...action.inputs.length) { var input = action.inputs[i]; + if (input == null) continue; + if (input.device == KEYBOARD && input.inputID == toRemove) { - @:privateAccess - action.inputs[i].inputID = toAdd; + if (toAdd == FlxKey.NONE) { + // Remove the keybind, don't replace. + action.inputs.remove(input); + } else { + // Replace the keybind. + @:privateAccess + action.inputs[i].inputID = toAdd; + } + hasReplaced = true; } } + + if (!hasReplaced) { + addKeys(action, [toAdd], state); + } } - function replaceButton(action:FlxActionDigital, deviceID:Int, toAdd:Int, toRemove:Int) + function replaceButton(action:FlxActionDigital, deviceID:Int, toAdd:FlxGamepadInputID, toRemove:FlxGamepadInputID, state:FlxInputState) { + if (action.inputs.length == 0) { + addButtons(action, [toAdd], state, deviceID); + return; + } + + var hasReplaced:Bool = false; for (i in 0...action.inputs.length) { var input = action.inputs[i]; + if (input == null) continue; + if (isGamepad(input, deviceID) && input.inputID == toRemove) { @:privateAccess action.inputs[i].inputID = toAdd; + hasReplaced = true; } } + + if (!hasReplaced) { + addButtons(action, [toAdd], state, deviceID); + } } public function copyFrom(controls:Controls, ?device:Device) @@ -558,10 +652,12 @@ class Controls extends FlxActionSet forEachBound(control, function(action, _) removeKeys(action, keys)); } - inline static function addKeys(action:FlxActionDigital, keys:Array, state:FlxInputState) + 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); + } } static function removeKeys(action:FlxActionDigital, keys:Array) @@ -582,54 +678,95 @@ class Controls extends FlxActionSet keyboardScheme = scheme; - switch(scheme) - { - case Solo: - bindKeys(Control.UI_UP, [W, FlxKey.UP]); - bindKeys(Control.UI_DOWN, [S, FlxKey.DOWN]); - bindKeys(Control.UI_LEFT, [A, FlxKey.LEFT]); - bindKeys(Control.UI_RIGHT, [D, FlxKey.RIGHT]); - bindKeys(Control.NOTE_UP, [W, FlxKey.UP]); - bindKeys(Control.NOTE_DOWN, [S, FlxKey.DOWN]); - bindKeys(Control.NOTE_LEFT, [A, FlxKey.LEFT]); - bindKeys(Control.NOTE_RIGHT, [D, FlxKey.RIGHT]); - bindKeys(Control.ACCEPT, [Z, SPACE, ENTER]); - bindKeys(Control.BACK, [X, BACKSPACE, ESCAPE]); - bindKeys(Control.PAUSE, [P, ENTER, ESCAPE]); - bindKeys(Control.RESET, [R]); - case Duo(true): - bindKeys(Control.UI_UP, [W]); - bindKeys(Control.UI_DOWN, [S]); - bindKeys(Control.UI_LEFT, [A]); - bindKeys(Control.UI_RIGHT, [D]); - bindKeys(Control.NOTE_UP, [W]); - bindKeys(Control.NOTE_DOWN, [S]); - bindKeys(Control.NOTE_LEFT, [A]); - bindKeys(Control.NOTE_RIGHT, [D]); - bindKeys(Control.ACCEPT, [G, Z]); - bindKeys(Control.BACK, [H, X]); - bindKeys(Control.PAUSE, [ONE]); - bindKeys(Control.RESET, [R]); - case Duo(false): - bindKeys(Control.UI_UP, [FlxKey.UP]); - bindKeys(Control.UI_DOWN, [FlxKey.DOWN]); - bindKeys(Control.UI_LEFT, [FlxKey.LEFT]); - bindKeys(Control.UI_RIGHT, [FlxKey.RIGHT]); - bindKeys(Control.NOTE_UP, [FlxKey.UP]); - bindKeys(Control.NOTE_DOWN, [FlxKey.DOWN]); - bindKeys(Control.NOTE_LEFT, [FlxKey.LEFT]); - bindKeys(Control.NOTE_RIGHT, [FlxKey.RIGHT]); - bindKeys(Control.ACCEPT, [O]); - bindKeys(Control.BACK, [P]); - bindKeys(Control.PAUSE, [ENTER]); - bindKeys(Control.RESET, [BACKSPACE]); - case None: // nothing - case Custom: // nothing - } + bindKeys(Control.UI_UP, getDefaultKeybinds(scheme, Control.UI_UP)); + bindKeys(Control.UI_DOWN, getDefaultKeybinds(scheme, Control.UI_DOWN)); + bindKeys(Control.UI_LEFT, getDefaultKeybinds(scheme, Control.UI_LEFT)); + bindKeys(Control.UI_RIGHT, getDefaultKeybinds(scheme, Control.UI_RIGHT)); + bindKeys(Control.NOTE_UP, getDefaultKeybinds(scheme, Control.NOTE_UP)); + bindKeys(Control.NOTE_DOWN, getDefaultKeybinds(scheme, Control.NOTE_DOWN)); + bindKeys(Control.NOTE_LEFT, getDefaultKeybinds(scheme, Control.NOTE_LEFT)); + bindKeys(Control.NOTE_RIGHT, getDefaultKeybinds(scheme, Control.NOTE_RIGHT)); + bindKeys(Control.ACCEPT, getDefaultKeybinds(scheme, Control.ACCEPT)); + bindKeys(Control.BACK, getDefaultKeybinds(scheme, Control.BACK)); + bindKeys(Control.PAUSE, getDefaultKeybinds(scheme, Control.PAUSE)); + bindKeys(Control.CUTSCENE_ADVANCE, getDefaultKeybinds(scheme, Control.CUTSCENE_ADVANCE)); + bindKeys(Control.CUTSCENE_SKIP, getDefaultKeybinds(scheme, Control.CUTSCENE_SKIP)); + 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)); bindMobileLol(); } + function getDefaultKeybinds(scheme:KeyboardScheme, control:Control):Array { + switch (scheme) { + case Solo: + 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]; + case Control.UI_RIGHT: return [D, FlxKey.RIGHT]; + case Control.NOTE_UP: return [W, FlxKey.UP]; + case Control.NOTE_DOWN: return [S, FlxKey.DOWN]; + case Control.NOTE_LEFT: return [A, FlxKey.LEFT]; + case Control.NOTE_RIGHT: return [D, FlxKey.RIGHT]; + case Control.ACCEPT: return [Z, SPACE, ENTER]; + case Control.BACK: return [X, BACKSPACE, ESCAPE]; + case Control.PAUSE: return [P, ENTER, ESCAPE]; + case Control.CUTSCENE_ADVANCE: return [Z, ENTER]; + case Control.CUTSCENE_SKIP: return [P, ESCAPE]; + case Control.VOLUME_UP: return [PLUS, NUMPADPLUS]; + case Control.VOLUME_DOWN: return [MINUS, NUMPADMINUS]; + case Control.VOLUME_MUTE: return [ZERO, NUMPADZERO]; + case Control.RESET: return [R]; + } + case Duo(true): + switch (control) { + case Control.UI_UP: return [W]; + case Control.UI_DOWN: return [S]; + case Control.UI_LEFT: return [A]; + case Control.UI_RIGHT: return [D]; + case Control.NOTE_UP: return [W]; + case Control.NOTE_DOWN: return [S]; + case Control.NOTE_LEFT: return [A]; + case Control.NOTE_RIGHT: return [D]; + case Control.ACCEPT: return [G, Z]; + case Control.BACK: return [H, X]; + case Control.PAUSE: return [ONE]; + case Control.CUTSCENE_ADVANCE: return [G, Z]; + case Control.CUTSCENE_SKIP: return [ONE]; + case Control.VOLUME_UP: return [PLUS]; + case Control.VOLUME_DOWN: return [MINUS]; + case Control.VOLUME_MUTE: return [ZERO]; + case Control.RESET: return [R]; + } + case Duo(false): + switch (control) { + case Control.UI_UP: return [FlxKey.UP]; + case Control.UI_DOWN: return [FlxKey.DOWN]; + case Control.UI_LEFT: return [FlxKey.LEFT]; + case Control.UI_RIGHT: return [FlxKey.RIGHT]; + case Control.NOTE_UP: return [FlxKey.UP]; + case Control.NOTE_DOWN: return [FlxKey.DOWN]; + case Control.NOTE_LEFT: return [FlxKey.LEFT]; + case Control.NOTE_RIGHT: return [FlxKey.RIGHT]; + case Control.ACCEPT: return [ENTER]; + case Control.BACK: return [ESCAPE]; + case Control.PAUSE: return [ONE]; + case Control.CUTSCENE_ADVANCE: return [ENTER]; + case Control.CUTSCENE_SKIP: return [ONE]; + case Control.VOLUME_UP: return [NUMPADPLUS]; + case Control.VOLUME_DOWN: return [NUMPADMINUS]; + case Control.VOLUME_MUTE: return [NUMPADZERO]; + case Control.RESET: return [R]; + } + default: + // Fallthrough. + } + + return []; + } + function bindMobileLol() { #if FLX_TOUCH @@ -704,23 +841,51 @@ class Controls extends FlxActionSet { addGamepadLiteral(id, [ - Control.ACCEPT => [#if switch B #else A #end], - Control.BACK => [#if switch A #else B #end, FlxGamepadInputID.BACK], - Control.UI_UP => [DPAD_UP, LEFT_STICK_DIGITAL_UP], - Control.UI_DOWN => [DPAD_DOWN, LEFT_STICK_DIGITAL_DOWN], - Control.UI_LEFT => [DPAD_LEFT, LEFT_STICK_DIGITAL_LEFT], - Control.UI_RIGHT => [DPAD_RIGHT, LEFT_STICK_DIGITAL_RIGHT], + 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 => [DPAD_UP, Y, LEFT_STICK_DIGITAL_UP, RIGHT_STICK_DIGITAL_UP], - Control.NOTE_DOWN => [DPAD_DOWN, A, LEFT_STICK_DIGITAL_DOWN, RIGHT_STICK_DIGITAL_DOWN], - Control.NOTE_LEFT => [DPAD_LEFT, X, LEFT_STICK_DIGITAL_LEFT, RIGHT_STICK_DIGITAL_LEFT], - Control.NOTE_RIGHT => [DPAD_RIGHT, B, LEFT_STICK_DIGITAL_RIGHT, RIGHT_STICK_DIGITAL_RIGHT], - Control.PAUSE => [START], - Control.RESET => [RIGHT_SHOULDER] - #if CAN_CHEAT, Control.CHEAT => [X] #end + 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.VOLUME_UP => [RIGHT_SHOULDER], + // Control.VOLUME_DOWN => [LEFT_SHOULDER], + // Control.VOLUME_MUTE => [RIGHT_TRIGGER], + Control.CUTSCENE_ADVANCE => getDefaultGamepadBinds(Control.CUTSCENE_ADVANCE), + Control.CUTSCENE_SKIP => getDefaultGamepadBinds(Control.CUTSCENE_SKIP), + Control.RESET => getDefaultGamepadBinds(Control.RESET), + #if CAN_CHEAT, Control.CHEAT => getDefaultGamepadBinds(Control.CHEAT) #end ]); } + 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.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.CUTSCENE_ADVANCE: return [A]; + case Control.CUTSCENE_SKIP: return [START]; + case Control.RESET: return [RIGHT_SHOULDER]; + #if CAN_CHEAT, Control.CHEAT: return [X]; #end + default: + // Fallthrough. + } + return []; + } + /** * Sets all actions that pertain to the binder to trigger when the supplied keys are used. * If binder is a literal you can inline this @@ -749,8 +914,10 @@ 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); + } } static function removeButtons(action:FlxActionDigital, gamepadID:Int, buttons:Array) @@ -798,6 +965,11 @@ class Controls extends FlxActionSet } } + /** + * NOTE: When loading controls: + * 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) { for (control in Control.createAll()) @@ -805,17 +977,44 @@ class Controls extends FlxActionSet var inputs:Array = Reflect.field(data, control.getName()); if (inputs != null) { + if (inputs.length == 0) { + trace('Control ${control} is missing bindings, resetting to default.'); + switch(device) + { + case Keys: + bindKeys(control, getDefaultKeybinds(Solo, control)); + case Gamepad(id): + bindButtons(control, id, getDefaultGamepadBinds(control)); + } + } else if (inputs == [FlxKey.NONE]) { + trace('Control ${control} is unbound, leaving it be.'); + } else { + switch(device) + { + case Keys: + bindKeys(control, inputs.copy()); + case Gamepad(id): + bindButtons(control, id, inputs.copy()); + } + } + } else { + trace('Control ${control} is missing bindings, resetting to default.'); switch(device) { case Keys: - bindKeys(control, inputs.copy()); + bindKeys(control, getDefaultKeybinds(Solo, control)); case Gamepad(id): - bindButtons(control, id, inputs.copy()); + bindButtons(control, id, getDefaultGamepadBinds(control)); } } } } + /** + * NOTE: When saving controls: + * 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 createSaveData(device:Device):Dynamic { var isEmpty = true; @@ -825,6 +1024,8 @@ class Controls extends FlxActionSet var inputs = getInputsFor(control, device); isEmpty = isEmpty && inputs.length == 0; + if (inputs.length == 0) inputs = [FlxKey.NONE]; + Reflect.setField(data, control.getName(), inputs); } diff --git a/source/funkin/ui/ControlsMenu.hx b/source/funkin/ui/ControlsMenu.hx index bd81cae5c..0d9db5b34 100644 --- a/source/funkin/ui/ControlsMenu.hx +++ b/source/funkin/ui/ControlsMenu.hx @@ -14,7 +14,7 @@ import funkin.ui.TextMenuList; class ControlsMenu extends funkin.ui.OptionsState.Page { - inline static public var COLUMNS = 2; + public static inline final COLUMNS = 2; static var controlList = Control.createAll(); /* * Defines groups of controls that cannot share inputs, like left and right. Say, if ACCEPT is Z, Back is X, @@ -23,7 +23,9 @@ class ControlsMenu extends funkin.ui.OptionsState.Page */ static var controlGroups:Array> = [ [NOTE_UP, NOTE_DOWN, NOTE_LEFT, NOTE_RIGHT], - [UI_UP, UI_DOWN, UI_LEFT, UI_RIGHT, ACCEPT, BACK] + [UI_UP, UI_DOWN, UI_LEFT, UI_RIGHT, ACCEPT, BACK], + [CUTSCENE_ADVANCE, CUTSCENE_SKIP], + [VOLUME_UP, VOLUME_DOWN, VOLUME_MUTE] ]; var itemGroups:Array> = [for (i in 0...controlGroups.length) []]; @@ -36,7 +38,7 @@ class ControlsMenu extends funkin.ui.OptionsState.Page var labels:FlxTypedGroup; var currentDevice:Device = Keys; - var deviceListSelected = false; + var deviceListSelected:Bool = false; public function new() { @@ -48,7 +50,7 @@ class ControlsMenu extends funkin.ui.OptionsState.Page camera = menuCamera; labels = new FlxTypedGroup(); - var headers = new FlxTypedGroup(); + var headers:FlxTypedGroup = new FlxTypedGroup(); controlGrid = new MenuTypedList(Columns(COLUMNS), Vertical); add(labels); @@ -57,20 +59,20 @@ class ControlsMenu extends funkin.ui.OptionsState.Page if (FlxG.gamepads.numActiveGamepads > 0) { - var devicesBg = new FlxSprite(); - devicesBg.makeGraphic(FlxG.width, 100, 0xFFfafd6d); + var devicesBg:FlxSprite = new FlxSprite(); + devicesBg.makeGraphic(FlxG.width, 100, 0xFFFAFD6D); add(devicesBg); deviceList = new TextMenuList(Horizontal, None); add(deviceList); deviceListSelected = true; - var item; + var item:TextMenuItem; - item = deviceList.createItem("Keyboard", AtlasFont.BOLD, selectDevice.bind(Keys)); + item = deviceList.createItem('Keyboard', AtlasFont.BOLD, selectDevice.bind(Keys)); item.x = FlxG.width / 2 - item.width - 30; item.y = (devicesBg.height - item.height) / 2; - item = deviceList.createItem("Gamepad", AtlasFont.BOLD, selectDevice.bind(Gamepad(FlxG.gamepads.firstActive.id))); + item = deviceList.createItem('Gamepad', AtlasFont.BOLD, selectDevice.bind(Gamepad(FlxG.gamepads.firstActive.id))); item.x = FlxG.width / 2 + 30; item.y = (devicesBg.height - item.height) / 2; } @@ -96,6 +98,18 @@ class ControlsMenu extends funkin.ui.OptionsState.Page headers.add(new AtlasText(0, y, "NOTES", AtlasFont.BOLD)).screenCenter(X); y += spacer; } + else if (currentHeader != "CUTSCENE_" && name.indexOf("CUTSCENE_") == 0) + { + currentHeader = "CUTSCENE_"; + headers.add(new AtlasText(0, y, "CUTSCENE", AtlasFont.BOLD)).screenCenter(X); + y += spacer; + } + else if (currentHeader != "VOLUME_" && name.indexOf("VOLUME_") == 0) + { + currentHeader = "VOLUME_"; + headers.add(new AtlasText(0, y, "VOLUME", AtlasFont.BOLD)).screenCenter(X); + y += spacer; + } if (currentHeader != null && name.indexOf(currentHeader) == 0) name = name.substr(currentHeader.length); @@ -128,7 +142,7 @@ class ControlsMenu extends funkin.ui.OptionsState.Page labels.members[Std.int(controlGrid.selectedIndex / COLUMNS)].alpha = 1.0; }); - prompt = new Prompt("\nPress any key to rebind\n\n\n\n Escape to cancel", None); + prompt = new Prompt("\nPress any key to rebind\n\n\nBackspace to unbind\n Escape to cancel", None); prompt.create(); prompt.createBgFromMargin(100, 0xFFfafd6d); prompt.back.scrollFactor.set(0, 0); @@ -149,6 +163,8 @@ class ControlsMenu extends funkin.ui.OptionsState.Page function onSelect():Void { + keyUsedToEnterPrompt = FlxG.keys.firstJustPressed(); + controlGrid.enabled = false; canExit = false; prompt.exists = true; @@ -187,7 +203,9 @@ class ControlsMenu extends funkin.ui.OptionsState.Page canExit = false; } - override function update(elapsed:Float) + var keyUsedToEnterPrompt:Null = null; + + override function update(elapsed:Float):Void { super.update(elapsed); @@ -200,18 +218,35 @@ class ControlsMenu extends funkin.ui.OptionsState.Page { case Keys: { - // check released otherwise bugs can happen when you change the BACK key + // Um? + // Checking pressed causes problems when you change the BACK key, + // but checking released causes problems when the prompt is instant. + + // keyUsedToEnterPrompt is my weird workaround. + var key = FlxG.keys.firstJustReleased(); - if (key != NONE) + if (key != NONE && key != keyUsedToEnterPrompt) { - if (key != ESCAPE) onInputSelect(key); - closePrompt(); + if (key == ESCAPE) + { + closePrompt(); + } + else if (key == BACKSPACE) + { + onInputSelect(NONE); + closePrompt(); + } + else + { + onInputSelect(key); + closePrompt(); + } } } case Gamepad(id): { var button = FlxG.gamepads.getByID(id).firstJustReleasedID(); - if (button != NONE) + if (button != NONE && button != keyUsedToEnterPrompt) { if (button != BACK) onInputSelect(button); closePrompt(); @@ -219,23 +254,32 @@ class ControlsMenu extends funkin.ui.OptionsState.Page } } } + + var keyJustReleased:Int = FlxG.keys.firstJustReleased(); + if (keyJustReleased != NONE && keyJustReleased == keyUsedToEnterPrompt) + { + keyUsedToEnterPrompt = null; + } } - function onInputSelect(input:Int) + function onInputSelect(input:Int):Void { var item = controlGrid.selectedItem; // check if that key is already set for this - var column0 = Math.floor(controlGrid.selectedIndex / 2) * 2; - for (i in 0...COLUMNS) + if (input != FlxKey.NONE) { - if (controlGrid.members[column0 + i].input == input) return; + var column0 = Math.floor(controlGrid.selectedIndex / 2) * 2; + for (i in 0...COLUMNS) + { + if (controlGrid.members[column0 + i].input == input) return; + } } // Check if items in the same group already have the new input for (group in itemGroups) { - if (group.contains(item)) + if (input != FlxKey.NONE && group.contains(item)) { for (otherItem in group) { @@ -252,10 +296,45 @@ class ControlsMenu extends funkin.ui.OptionsState.Page } PlayerSettings.player1.controls.replaceBinding(item.control, currentDevice, input, item.input); + // Don't use resetItem() since items share names/labels item.input = input; item.label.text = item.getLabel(input); + // Shift left on the grid if the item on the right is bound and the item on the left is unbound. + if (controlGrid.selectedIndex % 2 == 1) + { + trace('Modified item on right side of grid'); + var leftItem = controlGrid.members[controlGrid.selectedIndex - 1]; + if (leftItem != null && input != FlxKey.NONE && leftItem.input == FlxKey.NONE) + { + trace('Left item is unbound and right item is not!'); + // Swap them. + var temp = leftItem.input; + leftItem.input = item.input; + item.input = temp; + + leftItem.label.text = leftItem.getLabel(leftItem.input); + item.label.text = item.getLabel(item.input); + } + } + else + { + trace('Modified item on left side of grid'); + var rightItem = controlGrid.members[controlGrid.selectedIndex + 1]; + if (rightItem != null && input == FlxKey.NONE && rightItem.input != FlxKey.NONE) + { + trace('Left item is unbound and right item is not!'); + // Swap them. + var temp = item.input; + item.input = rightItem.input; + rightItem.input = temp; + + item.label.text = item.getLabel(item.input); + rightItem.label.text = rightItem.getLabel(rightItem.input); + } + } + PlayerSettings.player1.saveControls(); } @@ -306,6 +385,8 @@ class InputItem extends TextMenuItem this.input = getInput(); super(x, y, getLabel(input), DEFAULT, callback); + + this.fireInstantly = true; } public function updateDevice(device:Device) @@ -334,6 +415,6 @@ class InputItem extends TextMenuItem public function getLabel(input:Int) { - return input == -1 ? "---" : InputFormatter.format(input, device); + return input == FlxKey.NONE ? "---" : InputFormatter.format(input, device); } } From 5729eb04131eb7b295fafc32181ee28527b4d257 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 15 Jun 2023 00:28:52 -0400 Subject: [PATCH 23/33] Fix reloading song events --- source/funkin/modding/PolymodHandler.hx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/funkin/modding/PolymodHandler.hx b/source/funkin/modding/PolymodHandler.hx index 98f60ca86..d90c1386d 100644 --- a/source/funkin/modding/PolymodHandler.hx +++ b/source/funkin/modding/PolymodHandler.hx @@ -8,6 +8,7 @@ import funkin.play.stage.StageData; import polymod.Polymod; import polymod.backends.PolymodAssets.PolymodAssetType; import polymod.format.ParseRules.TextFileFormat; +import funkin.play.event.SongEventData.SongEventParser; import funkin.util.FileUtil; class PolymodHandler @@ -279,6 +280,11 @@ class PolymodHandler // TODO: Reload event callbacks funkin.data.level.LevelRegistry.instance.loadEntries(); + SongEventParser.loadEventCache(); + // TODO: Uncomment this once conversation data is implemented. + // ConversationDataParser.loadConversationCache(); + // DialogueBoxDataParser.loadDialogueBoxCache(); + // SpeakerDataParser.loadSpeakerCache(); SongDataParser.loadSongCache(); StageDataParser.loadStageCache(); CharacterDataParser.loadCharacterCache(); From 3c558ce1922c64d6b9aa24c6994da5fd47e11747 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 15 Jun 2023 00:29:18 -0400 Subject: [PATCH 24/33] Pixel fixes --- source/funkin/play/HealthIcon.hx | 3 +-- source/funkin/play/character/MultiSparrowCharacter.hx | 2 ++ source/funkin/play/character/PackerCharacter.hx | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/source/funkin/play/HealthIcon.hx b/source/funkin/play/HealthIcon.hx index a15c63060..e4802b99c 100644 --- a/source/funkin/play/HealthIcon.hx +++ b/source/funkin/play/HealthIcon.hx @@ -148,8 +148,7 @@ class HealthIcon extends FlxSprite { if (characterId == 'beta') { - // characterId = PlayState.instance.currentPlayerId; - characterId = 'bf'; + characterId = PlayState.instance.currentPlayerId; } else { diff --git a/source/funkin/play/character/MultiSparrowCharacter.hx b/source/funkin/play/character/MultiSparrowCharacter.hx index 45934c99b..34d89362f 100644 --- a/source/funkin/play/character/MultiSparrowCharacter.hx +++ b/source/funkin/play/character/MultiSparrowCharacter.hx @@ -56,10 +56,12 @@ class MultiSparrowCharacter extends BaseCharacter if (_data.isPixel) { + this.isPixel = true; this.antialiasing = false; } else { + this.isPixel = false; this.antialiasing = true; } } diff --git a/source/funkin/play/character/PackerCharacter.hx b/source/funkin/play/character/PackerCharacter.hx index 3ee276eb1..2bfac800a 100644 --- a/source/funkin/play/character/PackerCharacter.hx +++ b/source/funkin/play/character/PackerCharacter.hx @@ -41,10 +41,12 @@ class PackerCharacter extends BaseCharacter if (_data.isPixel) { + this.isPixel = true; this.antialiasing = false; } else { + this.isPixel = false; this.antialiasing = true; } From 3d8dd8d60411b69d3ab172a0ad4b8f17d0684158 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 15 Jun 2023 00:29:40 -0400 Subject: [PATCH 25/33] More conductor rework changes --- source/funkin/play/PlayState.hx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 38cdca905..f39000633 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -972,10 +972,10 @@ class PlayState extends MusicBeatState oldNote = newNote; // Generate X sustain notes. - var sustainSections = Math.round(songNote.length / Conductor.stepCrochet); + var sustainSections = Math.round(songNote.length / Conductor.stepLengthMs); for (noteIndex in 0...sustainSections) { - var noteTimeOffset:Float = Conductor.stepCrochet + (Conductor.stepCrochet * noteIndex); + var noteTimeOffset:Float = Conductor.stepLengthMs + (Conductor.stepLengthMs * noteIndex); var sustainNote:Note = new Note(songNote.time + noteTimeOffset, songNote.data, oldNote, true, strumlineStyle); sustainNote.mustPress = mustHitNote; sustainNote.data.noteKind = songNote.kind; @@ -2216,7 +2216,7 @@ class PlayState extends MusicBeatState var frameShit:Float = (1 / 24) * 2; // equals 2 frames in the animation - new FlxTimer().start(((Conductor.crochet / 1000) * 1.25) - frameShit, function(tmr) { + new FlxTimer().start(((Conductor.beatLengthMs / 1000) * 1.25) - frameShit, function(tmr) { animShit.forceFinish(); }); } From dddd0502688d5a331372b042d8fc9ef486862e87 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 15 Jun 2023 00:29:54 -0400 Subject: [PATCH 26/33] Move debug menu to main menu only --- source/funkin/MainMenuState.hx | 10 +++++++++- source/funkin/MusicBeatState.hx | 10 ---------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/source/funkin/MainMenuState.hx b/source/funkin/MainMenuState.hx index 57640bffa..82fcac77d 100644 --- a/source/funkin/MainMenuState.hx +++ b/source/funkin/MainMenuState.hx @@ -1,5 +1,6 @@ package funkin; +import funkin.ui.debug.DebugMenuSubState; import flixel.FlxObject; import flixel.FlxSprite; import flixel.FlxState; @@ -299,7 +300,14 @@ class MainMenuState extends MusicBeatState } } - // FlxG.camera.followLerp = CoolUtil.camLerpShit(0.06); + // ` / ~ to open the debug menu. + if (FlxG.keys.justPressed.GRAVEACCENT) + { + // TODO: Does this break anything? + this.persistentUpdate = false; + this.persistentDraw = false; + FlxG.state.openSubState(new DebugMenuSubState()); + } if (FlxG.sound.music.volume < 0.8) { diff --git a/source/funkin/MusicBeatState.hx b/source/funkin/MusicBeatState.hx index 6c6591c62..2b97951f9 100644 --- a/source/funkin/MusicBeatState.hx +++ b/source/funkin/MusicBeatState.hx @@ -9,7 +9,6 @@ import flixel.util.FlxSort; import funkin.modding.PolymodHandler; import funkin.modding.events.ScriptEvent; import funkin.modding.module.ModuleHandler; -import funkin.ui.debug.DebugMenuSubState; import funkin.util.SortUtil; /** @@ -66,15 +65,6 @@ class MusicBeatState extends FlxUIState // This can now be used in EVERY STATE YAY! if (FlxG.keys.justPressed.F5) debug_refreshModules(); - // ` / ~ to open the debug menu. - if (FlxG.keys.justPressed.GRAVEACCENT) - { - // TODO: Does this break anything? - this.persistentUpdate = false; - this.persistentDraw = false; - FlxG.state.openSubState(new DebugMenuSubState()); - } - // Display Conductor info in the watch window. FlxG.watch.addQuick("songPos", Conductor.songPosition); FlxG.watch.addQuick("currentStepTime", Conductor.currentStepTime); From 7a4722125090b37a2f34c82a10936665ea795fa6 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 15 Jun 2023 00:30:01 -0400 Subject: [PATCH 27/33] Fixes for FlxVideo --- source/funkin/graphics/video/FlxVideo.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/graphics/video/FlxVideo.hx b/source/funkin/graphics/video/FlxVideo.hx index 34b806f7e..393e2d49c 100644 --- a/source/funkin/graphics/video/FlxVideo.hx +++ b/source/funkin/graphics/video/FlxVideo.hx @@ -20,7 +20,7 @@ class FlxVideo extends FlxBasic /** * Doesn't actually interact with Flixel shit, only just a pleasant to use class */ - public function new(vidSrc:String) + public function new(videoPath:String) { super(); @@ -36,7 +36,7 @@ class FlxVideo extends FlxBasic netStream = new NetStream(netConnection); netStream.client = {onMetaData: client_onMetaData}; netConnection.addEventListener(NetStatusEvent.NET_STATUS, netConnection_onNetStatus); - netStream.play(Paths.file(vidSrc)); + netStream.play(videoPath); } public function finishVideo():Void From 594cec62ad3ada3e87eda1d6512e67f6f0b149d2 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 15 Jun 2023 00:30:20 -0400 Subject: [PATCH 28/33] Results screen now moves to Story menu if we are in story mode --- source/funkin/play/ResultState.hx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index 12be46fc8..302858f2f 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -1,5 +1,6 @@ package funkin.play; +import funkin.ui.story.StoryMenuState; import funkin.graphics.adobeanimate.FlxAtlasSprite; import flixel.FlxBasic; import flixel.FlxSprite; @@ -355,7 +356,17 @@ class ResultState extends MusicBeatSubState if (FlxG.keys.justPressed.COMMA) songName.angle -= 0.1; - if (controls.PAUSE) FlxG.switchState(new FreeplayState()); + if (controls.PAUSE) + { + if (PlayStatePlaylist.isStoryMode) + { + FlxG.switchState(new StoryMenuState()); + } + else + { + FlxG.switchState(new FreeplayState()); + } + } super.update(elapsed); } From 02632a623c4c063bf5253c28aed5394fce50c850 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 15 Jun 2023 03:48:52 -0400 Subject: [PATCH 29/33] Disable fakeout happening 100% of the time. --- source/funkin/play/GameOverSubstate.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/play/GameOverSubstate.hx b/source/funkin/play/GameOverSubstate.hx index 041831962..a2048149f 100644 --- a/source/funkin/play/GameOverSubstate.hx +++ b/source/funkin/play/GameOverSubstate.hx @@ -130,7 +130,7 @@ class GameOverSubstate extends MusicBeatSubstate { hasStartedAnimation = true; - if (boyfriend.hasAnimation('fakeoutDeath') && (FlxG.random.bool((1 / 4000) * 100) || true)) + if (boyfriend.hasAnimation('fakeoutDeath') && FlxG.random.bool((1 / 4096) * 100)) { boyfriend.playAnimation('fakeoutDeath', true, true); } From a7aafa9e3e4f0b381a0236795a2140219f4c012d Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 15 Jun 2023 14:09:19 -0400 Subject: [PATCH 30/33] .haxelib caching --- .github/actions/setup-haxeshit/action.yml | 2 +- .github/workflows/build-shit.yml | 44 +++-------------------- 2 files changed, 6 insertions(+), 40 deletions(-) diff --git a/.github/actions/setup-haxeshit/action.yml b/.github/actions/setup-haxeshit/action.yml index 21fab6fb2..2a8986c1f 100644 --- a/.github/actions/setup-haxeshit/action.yml +++ b/.github/actions/setup-haxeshit/action.yml @@ -16,5 +16,5 @@ runs: haxelib git haxelib https://github.com/HaxeFoundation/haxelib.git haxelib version haxelib --global install hmm - haxelib --global run hmm install --quiet + haxelib --global run hmm install shell: bash diff --git a/.github/workflows/build-shit.yml b/.github/workflows/build-shit.yml index 7115f2f6d..6c6a73c40 100644 --- a/.github/workflows/build-shit.yml +++ b/.github/workflows/build-shit.yml @@ -2,7 +2,7 @@ name: build-upload on: workflow_dispatch: push: - + jobs: check_date: runs-on: ubuntu-latest @@ -44,18 +44,14 @@ jobs: actions: write steps: - uses: actions/checkout@v3 - - name: Restore existing build cache for faster compilation - uses: actions/cache/restore@v3 - id: cache-windows-shit + - name: Restore/create existing haxelib cache for faster downloads + uses: actions/cache@v3 + id: cache-haxelib-windows with: # wha? - key: cache-build-win + key: cache-haxelib-windows-${{ hashFiles('**/hmm.json')}} path: | .haxelib/ - export/debug/windows/haxe/ - export/debug/windows/obj/ - restore-keys: | - cache-build-windows - uses: ./.github/actions/setup-haxeshit - name: Build game run: | @@ -66,33 +62,3 @@ jobs: butler-key: ${{ secrets.BUTLER_API_KEY}} build-dir: export/debug/windows/bin target: win - - name: Clearing already existing cache - uses: actions/github-script@v6 - with: - script: | - const caches = await github.rest.actions.getActionsCacheList({ - owner: context.repo.owner, - repo: context.repo.repo, - }) - for (const cache of caches.data.actions_caches) { - if (cache.key == "cache-build-windows") { - console.log('Clearing ' + cache.key + '...') - await github.rest.actions.deleteActionsCacheById({ - owner: context.repo.owner, - repo: context.repo.repo, - cache_id: cache.id, - }) - console.log("Cache cleared.") - } - } - - name: Uploading new cache - uses: actions/cache/save@v3 - with: - # caching again since for some reason it doesnt work with the first post cache shit - key: cache-build-windows - path: | - .haxelib/ - export/debug/windows/haxe/ - export/debug/windows/obj/ - restore-keys: | - cache-build-windows From 0b42b6e3053f4f8c7d045f17537ab2bd904bf0ac Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 15 Jun 2023 14:12:39 -0400 Subject: [PATCH 31/33] moved caching so html5 can also cache haxelibs --- .github/actions/setup-haxeshit/action.yml | 8 ++++++++ .github/workflows/build-shit.yml | 8 -------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/actions/setup-haxeshit/action.yml b/.github/actions/setup-haxeshit/action.yml index 2a8986c1f..bf81e0d6d 100644 --- a/.github/actions/setup-haxeshit/action.yml +++ b/.github/actions/setup-haxeshit/action.yml @@ -10,6 +10,14 @@ runs: run: | haxelib config shell: bash + - name: Restore/create existing haxelib cache for faster downloads + uses: actions/cache@v3 + id: cache-haxelib-windows + with: + # wha? + key: cache-haxelib-${{ runner.os }}-${{ hashFiles('**/hmm.json')}} + path: | + .haxelib/ - name: Installing Haxe lol run: | haxe -version diff --git a/.github/workflows/build-shit.yml b/.github/workflows/build-shit.yml index 6c6a73c40..35d436b2c 100644 --- a/.github/workflows/build-shit.yml +++ b/.github/workflows/build-shit.yml @@ -44,14 +44,6 @@ jobs: actions: write steps: - uses: actions/checkout@v3 - - name: Restore/create existing haxelib cache for faster downloads - uses: actions/cache@v3 - id: cache-haxelib-windows - with: - # wha? - key: cache-haxelib-windows-${{ hashFiles('**/hmm.json')}} - path: | - .haxelib/ - uses: ./.github/actions/setup-haxeshit - name: Build game run: | From 092dcb5a35aab4074cd4a0fe1019c34f3525d25e Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 15 Jun 2023 14:31:49 -0400 Subject: [PATCH 32/33] counter fix thing --- source/funkin/play/GameOverSubState.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/play/GameOverSubState.hx b/source/funkin/play/GameOverSubState.hx index 1b79d024b..7c39cef56 100644 --- a/source/funkin/play/GameOverSubState.hx +++ b/source/funkin/play/GameOverSubState.hx @@ -170,8 +170,8 @@ class GameOverSubState extends MusicBeatSubState if (controls.BACK) { blueballed = false; - PlayState.deathCounter = 0; - PlayState.seenCutscene = false; + PlayState.instance.deathCounter = 0; + // PlayState.seenCutscene = false; // old thing... gameOverMusic.stop(); if (PlayStatePlaylist.isStoryMode) FlxG.switchState(new StoryMenuState()); From d1333b9b24284ecea21b8f0444e2d00fab53b446 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 27 Jun 2023 12:45:41 -0400 Subject: [PATCH 33/33] new hxcodec stuff --- hmm.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hmm.json b/hmm.json index f45a94b08..dc403a5ab 100644 --- a/hmm.json +++ b/hmm.json @@ -68,8 +68,8 @@ "name": "hxCodec", "type": "git", "dir": null, - "ref": "c42ab99", - "url": "https://github.com/polybiusproxy/hxCodec" + "ref": "a56f4b4", + "url": "https://github.com/FunkinCrew/hxCodec" }, { "name": "hxcpp",