diff --git a/.gitignore b/.gitignore index 9f24f450e..8a4d131df 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,4 @@ export/ .vscode/ APIStuff.hx .DS_STORE - -example_mods/enaSkin/ - -example_mods/tricky/ +RECOVER_*.fla \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 4afcd170e..9a277f85c 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -12,6 +12,21 @@ "name": "Haxe Eval", "type": "haxe-eval", "request": "launch" - } + }, + { + "name": "HTML5 Debug", + "type": "chrome", + "request": "launch", + "url": "http://127.0.0.1:3001", + "sourceMaps": true, + "webRoot": "${workspaceFolder}", + "preLaunchTask": "debug: html" + }, + { + "name": "Mac (Debug)", + "type": "hxcpp", + "request": "launch", + "program": "${workspaceRoot}/export/debug/macos/bin/Funkin.app/Contents/MacOS/Funkin", + "preLaunchTask": "debug: mac" ] } diff --git a/Project.xml b/Project.xml index 4c6ad39a6..81f017853 100644 --- a/Project.xml +++ b/Project.xml @@ -96,7 +96,13 @@ - + @@ -192,7 +198,7 @@ - + diff --git a/example_mods/introMod/_polymod_meta.json b/example_mods/introMod/_polymod_meta.json index ccd7405d8..4c7fd742e 100644 --- a/example_mods/introMod/_polymod_meta.json +++ b/example_mods/introMod/_polymod_meta.json @@ -1,7 +1,9 @@ { "title": "Intro Mod", "description": "An introductory mod.", - "author": "MasterEric", + "contributors": [{ + "name": "MasterEric" + }], "api_version": "0.1.0", "mod_version": "1.0.0", "license": "Apache-2.0" diff --git a/example_mods/testing123/_polymod_meta.json b/example_mods/testing123/_polymod_meta.json index 0c134dd9f..1a7766820 100644 --- a/example_mods/testing123/_polymod_meta.json +++ b/example_mods/testing123/_polymod_meta.json @@ -1,7 +1,9 @@ { "title": "Testing123", "description": "Newgrounds? More like OLDGROUNDS lol.", - "author": "MasterEric", + "contributors": [{ + "name": "MasterEric" + }], "api_version": "0.1.0", "mod_version": "1.0.0", "license": "Apache-2.0" diff --git a/source/Main.hx b/source/Main.hx index 32b7433f3..191ebef53 100644 --- a/source/Main.hx +++ b/source/Main.hx @@ -1,9 +1,9 @@ package; -import funkin.InitState; -import funkin.MemoryCounter; import flixel.FlxGame; import flixel.FlxState; +import funkin.InitState; +import funkin.MemoryCounter; import openfl.Lib; import openfl.display.FPS; import openfl.display.Sprite; @@ -37,13 +37,7 @@ class Main extends Sprite { super(); - // TODO: Ideally this should change to utilize a user interface. - // 1. Call PolymodHandler.getAllMods(). This gives you an array of ModMetadata items, - // each of which contains information about the mod including an icon. - // 2. Provide an interface to enable, disable, and reorder enabled mods. - // A design similar to that of Minecraft resource packs would be intuitive. - // 3. The interface should save (to the save file) and output an ordered array of mod IDs. - // 4. Replace the call to PolymodHandler.loadAllMods() with a call to PolymodHandler.loadModsById(ids:Array). + // TODO: Replace this with loadEnabledMods(). funkin.modding.PolymodHandler.loadAllMods(); if (stage != null) diff --git a/source/funkin/FreeplayState.hx b/source/funkin/FreeplayState.hx index bacde05e8..7f37eff18 100644 --- a/source/funkin/FreeplayState.hx +++ b/source/funkin/FreeplayState.hx @@ -1,6 +1,5 @@ package funkin; -import funkin.Controls.Control; import flash.text.TextField; import flixel.FlxCamera; import flixel.FlxGame; @@ -21,17 +20,18 @@ import flixel.tweens.FlxTween; import flixel.util.FlxColor; import flixel.util.FlxSpriteUtil; import flixel.util.FlxTimer; +import funkin.Controls.Control; import funkin.freeplayStuff.BGScrollingText; import funkin.freeplayStuff.DJBoyfriend; import funkin.freeplayStuff.FreeplayScore; import funkin.freeplayStuff.SongMenuItem; import funkin.play.HealthIcon; -import lime.app.Future; -import lime.utils.Assets; +import funkin.play.PlayState; import funkin.shaderslmfao.AngleMask; import funkin.shaderslmfao.PureColor; import funkin.shaderslmfao.StrokeShader; -import funkin.play.PlayState; +import lime.app.Future; +import lime.utils.Assets; using StringTools; @@ -499,6 +499,9 @@ class FreeplayState extends MusicBeatSubstate if (controls.BACK) { FlxG.sound.play(Paths.sound('cancelMenu')); + + FlxTransitionableState.skipNextTransIn = true; + FlxTransitionableState.skipNextTransOut = true; FlxG.switchState(new MainMenuState()); } diff --git a/source/funkin/GameOverSubstate.hx b/source/funkin/GameOverSubstate.hx index fe957af25..113e64b63 100644 --- a/source/funkin/GameOverSubstate.hx +++ b/source/funkin/GameOverSubstate.hx @@ -1,17 +1,14 @@ package funkin; -import funkin.modding.events.ScriptEventDispatcher; -import funkin.modding.events.ScriptEvent; -import funkin.play.character.BaseCharacter; import flixel.FlxObject; -import flixel.FlxSubState; -import flixel.math.FlxPoint; import flixel.system.FlxSound; import flixel.util.FlxColor; import flixel.util.FlxTimer; -import haxe.display.Display; -import funkin.ui.PreferencesMenu; +import funkin.modding.events.ScriptEvent; +import funkin.modding.events.ScriptEventDispatcher; import funkin.play.PlayState; +import funkin.play.character.BaseCharacter; +import funkin.ui.PreferencesMenu; using StringTools; diff --git a/source/funkin/InitState.hx b/source/funkin/InitState.hx index f7ec0ff4b..bfde8c327 100644 --- a/source/funkin/InitState.hx +++ b/source/funkin/InitState.hx @@ -1,9 +1,5 @@ package funkin; -import funkin.play.character.CharacterData.CharacterDataParser; -import funkin.modding.module.ModuleHandler; -import funkin.play.stage.StageData; -import funkin.charting.ChartingState; import flixel.addons.transition.FlxTransitionSprite.GraphicTransTileDiamond; import flixel.addons.transition.FlxTransitionableState; import flixel.addons.transition.TransitionData; @@ -11,12 +7,17 @@ import flixel.graphics.FlxGraphic; import flixel.math.FlxPoint; import flixel.math.FlxRect; import flixel.util.FlxColor; -import openfl.display.BitmapData; +import funkin.charting.ChartingState; +import funkin.modding.module.ModuleHandler; import funkin.play.PicoFight; +import funkin.play.PlayState; +import funkin.play.character.CharacterData.CharacterDataParser; +import funkin.play.stage.StageData; import funkin.ui.PreferencesMenu; +import funkin.ui.animDebugShit.DebugBoundingState; import funkin.ui.stageBuildShit.StageBuilderState; import funkin.util.macro.MacroUtil; -import funkin.play.PlayState; +import openfl.display.BitmapData; using StringTools; @@ -178,7 +179,11 @@ class InitState extends FlxTransitionableState #elseif FIGHT FlxG.switchState(new PicoFight()); #elseif ANIMDEBUG +<<<<<<< HEAD FlxG.switchState(new funkin.ui.animDebugShit.DebugBoundingState()); +======= + FlxG.switchState(new DebugBoundingState()); +>>>>>>> origin/feature/scripted-modules #elseif NETTEST FlxG.switchState(new netTest.NetTest()); #else diff --git a/source/funkin/LoadingState.hx b/source/funkin/LoadingState.hx index bbe20ff2d..ad649bb03 100644 --- a/source/funkin/LoadingState.hx +++ b/source/funkin/LoadingState.hx @@ -2,9 +2,9 @@ package funkin; import flixel.FlxSprite; import flixel.FlxState; -import flixel.graphics.frames.FlxAtlasFrames; import flixel.math.FlxMath; import flixel.util.FlxTimer; +import funkin.play.PlayState; import haxe.io.Path; import lime.app.Future; import lime.app.Promise; @@ -12,7 +12,6 @@ import lime.utils.AssetLibrary; import lime.utils.AssetManifest; import lime.utils.Assets as LimeAssets; import openfl.utils.Assets; -import funkin.play.PlayState; class LoadingState extends MusicBeatState { @@ -21,7 +20,6 @@ class LoadingState extends MusicBeatState var target:FlxState; var stopMusic = false; var callbacks:MultiCallback; - var danceLeft = false; var loadBar:FlxSprite; @@ -123,13 +121,7 @@ class LoadingState extends MusicBeatState if (!super.beatHit()) return false; - // logo.animation.play('bump'); danceLeft = !danceLeft; - /* - if (danceLeft) - gfDance.animation.play('danceRight'); - else - gfDance.animation.play('danceLeft'); */ return true; } diff --git a/source/funkin/MainMenuState.hx b/source/funkin/MainMenuState.hx index 39eeb87e7..1f99b067f 100644 --- a/source/funkin/MainMenuState.hx +++ b/source/funkin/MainMenuState.hx @@ -1,10 +1,10 @@ package funkin; -import flixel.addons.transition.FlxTransitionableState; -import flixel.effects.FlxFlicker; import flixel.FlxObject; import flixel.FlxSprite; import flixel.FlxState; +import flixel.addons.transition.FlxTransitionableState; +import flixel.effects.FlxFlicker; import flixel.graphics.frames.FlxAtlasFrames; import flixel.group.FlxGroup.FlxTypedGroup; import flixel.input.touch.FlxTouch; @@ -14,13 +14,13 @@ import flixel.tweens.FlxTween; import flixel.ui.FlxButton; import flixel.util.FlxColor; import flixel.util.FlxTimer; +import funkin.NGio; import funkin.modding.events.ScriptEvent.UpdateScriptEvent; import funkin.modding.module.ModuleHandler; -import funkin.NGio; import funkin.shaderslmfao.ScreenWipeShader; import funkin.ui.AtlasMenuList; -import funkin.ui.MenuList; import funkin.ui.MenuList.MenuItem; +import funkin.ui.MenuList; import funkin.ui.OptionsState; import funkin.ui.PreferencesMenu; import funkin.ui.Prompt; @@ -35,8 +35,8 @@ using StringTools; import Discord.DiscordClient; #end #if newgrounds -import io.newgrounds.NG; import funkin.ui.NgPrompt; +import io.newgrounds.NG; #end class MainMenuState extends MusicBeatState @@ -104,14 +104,9 @@ class MainMenuState extends MusicBeatState } }); - menuItems.enabled = false; // disable for intro - - createMenuItem('storymode', 'mainmenu/storymode', function() - { - startExitState(new StoryMenuState()); - }); - - createMenuItem('freeplay', 'mainmenu/freeplay', function() + menuItems.enabled = true; // can move on intro + menuItems.createItem('story mode', function() startExitState(new StoryMenuState())); + menuItems.createItem('freeplay', function() { persistentDraw = true; persistentUpdate = false; @@ -184,7 +179,7 @@ class MainMenuState extends MusicBeatState { super.finishTransIn(); - menuItems.enabled = true; + // menuItems.enabled = true; // #if newgrounds // if (NGio.savedSessionFailed) diff --git a/source/funkin/MusicBeatState.hx b/source/funkin/MusicBeatState.hx index a11d468ca..5e86ea022 100644 --- a/source/funkin/MusicBeatState.hx +++ b/source/funkin/MusicBeatState.hx @@ -1,18 +1,18 @@ package funkin; -import flixel.util.FlxSort; -import funkin.util.SortUtil; -import funkin.play.stage.StageData.StageDataParser; -import funkin.play.character.CharacterData.CharacterDataParser; import flixel.FlxState; import flixel.FlxSubState; -import flixel.util.FlxColor; +import flixel.addons.ui.FlxUIState; import flixel.text.FlxText; +import flixel.util.FlxColor; +import flixel.util.FlxSort; +import funkin.Conductor.BPMChangeEvent; +import funkin.modding.PolymodHandler; import funkin.modding.events.ScriptEvent; import funkin.modding.module.ModuleHandler; -import funkin.modding.events.ScriptEvent.UpdateScriptEvent; -import funkin.Conductor.BPMChangeEvent; -import flixel.addons.ui.FlxUIState; +import funkin.play.character.CharacterData.CharacterDataParser; +import funkin.play.stage.StageData.StageDataParser; +import funkin.util.SortUtil; /** * MusicBeatState actually represents the core utility FlxState of the game. @@ -68,6 +68,8 @@ class MusicBeatState extends FlxUIState if (oldStep != curStep && curStep >= 0) stepHit(); + FlxG.watch.addQuick("songPos", Conductor.songPosition); + dispatchEvent(new UpdateScriptEvent(elapsed)); } @@ -97,20 +99,7 @@ class MusicBeatState extends FlxUIState function debug_refreshModules() { - // Forcibly clear scripts so that scripts can be edited. - ModuleHandler.clearModuleCache(); - polymod.hscript.PolymodScriptClass.clearScriptClasses(); - - // Forcibly reload Polymod so it finds any new files. - polymod.Polymod.reload(); - - // Reload scripted classes so stages and modules will update. - polymod.hscript.PolymodScriptClass.registerAllScriptClasses(); - - // Reload the stages in cache. This might cause a lag spike but who cares this is a debug utility. - StageDataParser.loadStageCache(); - CharacterDataParser.loadCharacterCache(); - ModuleHandler.loadModuleCache(); + PolymodHandler.forceReloadAssets(); // Restart the current state, so old data is cleared. FlxG.resetState(); diff --git a/source/funkin/MusicBeatSubstate.hx b/source/funkin/MusicBeatSubstate.hx index 12cb56cff..db20bce34 100644 --- a/source/funkin/MusicBeatSubstate.hx +++ b/source/funkin/MusicBeatSubstate.hx @@ -1,9 +1,9 @@ package funkin; -import funkin.modding.module.ModuleHandler; -import funkin.modding.events.ScriptEvent; -import funkin.Conductor.BPMChangeEvent; import flixel.FlxSubState; +import funkin.Conductor.BPMChangeEvent; +import funkin.modding.events.ScriptEvent; +import funkin.modding.module.ModuleHandler; /** * MusicBeatSubstate reincorporates the functionality of MusicBeatState into an FlxSubState. diff --git a/source/funkin/Note.hx b/source/funkin/Note.hx index 32a5b19a8..433a1e727 100644 --- a/source/funkin/Note.hx +++ b/source/funkin/Note.hx @@ -80,8 +80,8 @@ class Note extends FlxSprite public static var RED_NOTE:Int = 3; // SCORING STUFF - public static var safeFrames:Int = 10; - public static var HIT_WINDOW:Float = (safeFrames / 60) * 1000; // 166.67 ms hit window + public static var HIT_WINDOW:Float = (10 / 60) * 1000; // 166.67 ms hit window (10 frames at 60fps) + // thresholds are fractions of HIT_WINDOW ^^ // anything above bad threshold is shit public static var BAD_THRESHOLD:Float = 0.8; // 125ms , 8 frames public static var GOOD_THRESHOLD:Float = 0.55; // 91.67ms , 5.5 frames diff --git a/source/funkin/NoteSplash.hx b/source/funkin/NoteSplash.hx index 64169c48b..3e4d3a3b5 100644 --- a/source/funkin/NoteSplash.hx +++ b/source/funkin/NoteSplash.hx @@ -22,6 +22,8 @@ class NoteSplash extends FlxSprite setupNoteSplash(x, y, noteData); + antialiasing = true; + // alpha = 0.75; } diff --git a/source/funkin/PauseSubState.hx b/source/funkin/PauseSubState.hx index 81e6fb9f5..8a9648795 100644 --- a/source/funkin/PauseSubState.hx +++ b/source/funkin/PauseSubState.hx @@ -1,6 +1,5 @@ package funkin; -import funkin.Controls.Control; import flixel.FlxSprite; import flixel.FlxSubState; import flixel.addons.transition.FlxTransitionableState; @@ -11,6 +10,7 @@ import flixel.text.FlxText; import flixel.tweens.FlxEase; import flixel.tweens.FlxTween; import flixel.util.FlxColor; +import funkin.Controls.Control; import funkin.play.PlayState; class PauseSubState extends MusicBeatSubstate @@ -33,43 +33,53 @@ class PauseSubState extends MusicBeatSubstate var practiceText:FlxText; + var exitingToMenu:Bool = false; + var bg:FlxSprite; + var metaDataGrp:FlxTypedGroup; + public function new(x:Float, y:Float) { super(); menuItems = pauseOG; - pauseMusic = new FlxSound().loadEmbedded(Paths.music('breakfast'), true, true); + if (PlayState.storyWeek == 6) // consistent with logic that decides asset lib!! + pauseMusic = new FlxSound().loadEmbedded(Paths.music('breakfast-pixel'), true, true); + else + pauseMusic = new FlxSound().loadEmbedded(Paths.music('breakfast'), true, true); pauseMusic.volume = 0; pauseMusic.play(false, FlxG.random.int(0, Std.int(pauseMusic.length / 2))); FlxG.sound.list.add(pauseMusic); - var bg:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK); + bg = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK); bg.alpha = 0; bg.scrollFactor.set(); add(bg); + metaDataGrp = new FlxTypedGroup(); + add(metaDataGrp); + var levelInfo:FlxText = new FlxText(20, 15, 0, "", 32); levelInfo.text += PlayState.currentSong.song; levelInfo.scrollFactor.set(); levelInfo.setFormat(Paths.font("vcr.ttf"), 32); levelInfo.updateHitbox(); - add(levelInfo); + metaDataGrp.add(levelInfo); var levelDifficulty:FlxText = new FlxText(20, 15 + 32, 0, "", 32); levelDifficulty.text += CoolUtil.difficultyString(); levelDifficulty.scrollFactor.set(); levelDifficulty.setFormat(Paths.font('vcr.ttf'), 32); levelDifficulty.updateHitbox(); - add(levelDifficulty); + metaDataGrp.add(levelDifficulty); var deathCounter:FlxText = new FlxText(20, 15 + 64, 0, "", 32); deathCounter.text = "Blue balled: " + PlayState.deathCounter; deathCounter.scrollFactor.set(); deathCounter.setFormat(Paths.font('vcr.ttf'), 32); deathCounter.updateHitbox(); - add(deathCounter); + metaDataGrp.add(deathCounter); practiceText = new FlxText(20, 15 + 64 + 32, 0, "PRACTICE MODE", 32); practiceText.scrollFactor.set(); @@ -77,7 +87,7 @@ class PauseSubState extends MusicBeatSubstate practiceText.updateHitbox(); practiceText.x = FlxG.width - (practiceText.width + 20); practiceText.visible = PlayState.isPracticeMode; - add(practiceText); + metaDataGrp.add(practiceText); levelDifficulty.alpha = 0; levelInfo.alpha = 0; @@ -130,71 +140,103 @@ class PauseSubState extends MusicBeatSubstate var downP = controls.UI_DOWN_P; var accepted = controls.ACCEPT; - if (upP) + #if debug + // to pause the game and get screenshots easy, press H on pause menu! + if (FlxG.keys.justPressed.H) { - changeSelection(-1); + bg.visible = !bg.visible; + grpMenuShit.visible = !grpMenuShit.visible; + metaDataGrp.visible = !metaDataGrp.visible; } - if (downP) - { - changeSelection(1); - } - - var androidPause:Bool = false; - - #if android - androidPause = FlxG.android.justPressed.BACK; #end - if (androidPause) - close(); - - if (accepted) + if (!exitingToMenu) { - var daSelected:String = menuItems[curSelected]; - - switch (daSelected) + if (upP) { - case "Resume": - close(); - case "EASY" | 'NORMAL' | "HARD": - PlayState.currentSong = SongLoad.loadFromJson(PlayState.currentSong.song.toLowerCase(), PlayState.currentSong.song.toLowerCase()); - SongLoad.curDiff = daSelected.toLowerCase(); - - PlayState.storyDifficulty = curSelected; - - PlayState.needsReset = true; - - close(); - - case 'Toggle Practice Mode': - PlayState.isPracticeMode = !PlayState.isPracticeMode; - practiceText.visible = PlayState.isPracticeMode; - - case 'Change Difficulty': - menuItems = difficultyChoices; - regenMenu(); - case 'BACK': - menuItems = pauseOG; - regenMenu(); - case "Restart Song": - PlayState.needsReset = true; - - close(); - // FlxG.resetState(); - case "Exit to menu": - PlayState.seenCutscene = false; - PlayState.deathCounter = 0; - if (PlayState.isStoryMode) - FlxG.switchState(new StoryMenuState()); - else - FlxG.switchState(new FreeplayState()); + changeSelection(-1); + } + if (downP) + { + changeSelection(1); } - } - if (FlxG.keys.justPressed.J) - { - // for reference later! - // PlayerSettings.player1.controls.replaceBinding(Control.LEFT, Keys, FlxKey.J, null); + var androidPause:Bool = false; + + #if android + androidPause = FlxG.android.justPressed.BACK; + #end + + if (androidPause) + close(); + + if (accepted) + { + var daSelected:String = menuItems[curSelected]; + + switch (daSelected) + { + case "Resume": + close(); + case "EASY" | 'NORMAL' | "HARD": + PlayState.currentSong = SongLoad.loadFromJson(PlayState.currentSong.song.toLowerCase(), PlayState.currentSong.song.toLowerCase()); + SongLoad.curDiff = daSelected.toLowerCase(); + + PlayState.storyDifficulty = curSelected; + + PlayState.needsReset = true; + + close(); + + case 'Toggle Practice Mode': + PlayState.isPracticeMode = !PlayState.isPracticeMode; + practiceText.visible = PlayState.isPracticeMode; + + case 'Change Difficulty': + menuItems = difficultyChoices; + regenMenu(); + case 'BACK': + menuItems = pauseOG; + regenMenu(); + case "Restart Song": + PlayState.needsReset = true; + + close(); + // FlxG.resetState(); + case "Exit to menu": + exitingToMenu = true; + PlayState.seenCutscene = false; + PlayState.deathCounter = 0; + + for (item in grpMenuShit.members) + { + item.targetY = -3; + item.alpha = 0.6; + } + + FlxTween.tween(bg, {alpha: 1}, 0.4, { + ease: FlxEase.quartInOut, + onComplete: function(_) + { + FlxTransitionableState.skipNextTransIn = true; + FlxTransitionableState.skipNextTransOut = true; + + FlxG.cameras.list[1].alpha = 0; // bullshit for the UI camera??? + + if (PlayState.isStoryMode) + FlxG.switchState(new StoryMenuState()); + else + FlxG.switchState(new FreeplayState()); + } + }); + } + } + + if (FlxG.keys.justPressed.J) + { + // for reference later! + // PlayerSettings.player1.controls.replaceBinding(Control.LEFT, Keys, FlxKey.J, null); + } } } @@ -216,12 +258,9 @@ class PauseSubState extends MusicBeatSubstate if (curSelected >= menuItems.length) curSelected = 0; - var bullShit:Int = 0; - - for (item in grpMenuShit.members) + for (index => item in grpMenuShit.members) { - item.targetY = bullShit - curSelected; - bullShit++; + item.targetY = index - curSelected; item.alpha = 0.6; // item.setGraphicSize(Std.int(item.width * 0.8)); diff --git a/source/funkin/TitleState.hx b/source/funkin/TitleState.hx index df91a5841..6dfd5c8b7 100644 --- a/source/funkin/TitleState.hx +++ b/source/funkin/TitleState.hx @@ -1,48 +1,32 @@ package funkin; -import funkin.ui.AtlasText.BoldText; -import funkin.audiovis.SpectogramSprite; import flixel.FlxObject; import flixel.FlxSprite; import flixel.FlxState; import flixel.group.FlxGroup; -import flixel.input.android.FlxAndroidKey; -import flixel.input.android.FlxAndroidKeys; import flixel.input.gamepad.FlxGamepad; -import flixel.input.gamepad.id.SwitchJoyconLeftID; -import flixel.math.FlxPoint; -import flixel.math.FlxRect; -import flixel.text.FlxText; import flixel.tweens.FlxEase; import flixel.tweens.FlxTween; import flixel.util.FlxColor; import flixel.util.FlxTimer; -import lime.app.Application; -import lime.graphics.Image; -import lime.media.AudioContext; -import lime.ui.Window; -import openfl.Assets; -import openfl.display.Sprite; -import openfl.events.AsyncErrorEvent; -import openfl.events.Event; -import openfl.events.MouseEvent; -import openfl.events.NetStatusEvent; -import openfl.media.Video; -import openfl.net.NetConnection; -import openfl.net.NetStream; +import funkin.audiovis.SpectogramSprite; import funkin.shaderslmfao.BuildingShaders; import funkin.shaderslmfao.ColorSwap; import funkin.shaderslmfao.TitleOutline; -import funkin.ui.PreferencesMenu; +import funkin.ui.AtlasText; +import funkin.util.Constants; +import openfl.Assets; +import openfl.display.Sprite; +import openfl.events.AsyncErrorEvent; +import openfl.events.MouseEvent; +import openfl.events.NetStatusEvent; +import openfl.media.Video; +import openfl.net.NetStream; using StringTools; #if desktop -import sys.FileSystem; -import sys.io.File; -import sys.thread.Thread; #end - class TitleState extends MusicBeatState { public static var initialized:Bool = false; @@ -74,33 +58,33 @@ class TitleState extends MusicBeatState super.create(); /* - #elseif web + #elseif web - if (!initialized) - { + if (!initialized) + { - video = new Video(); - FlxG.stage.addChild(video); + video = new Video(); + FlxG.stage.addChild(video); - var netConnection = new NetConnection(); - netConnection.connect(null); + var netConnection = new NetConnection(); + netConnection.connect(null); - netStream = new NetStream(netConnection); - netStream.client = {onMetaData: client_onMetaData}; - netStream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, netStream_onAsyncError); - netConnection.addEventListener(NetStatusEvent.NET_STATUS, netConnection_onNetStatus); - // netStream.addEventListener(NetStatusEvent.NET_STATUS) // netStream.play(Paths.file('music/kickstarterTrailer.mp4')); + netStream = new NetStream(netConnection); + netStream.client = {onMetaData: client_onMetaData}; + netStream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, netStream_onAsyncError); + netConnection.addEventListener(NetStatusEvent.NET_STATUS, netConnection_onNetStatus); + // netStream.addEventListener(NetStatusEvent.NET_STATUS) // netStream.play(Paths.file('music/kickstarterTrailer.mp4')); - overlay = new Sprite(); - overlay.graphics.beginFill(0, 0.5); - overlay.graphics.drawRect(0, 0, 1280, 720); - overlay.addEventListener(MouseEvent.MOUSE_DOWN, overlay_onMouseDown); + overlay = new Sprite(); + overlay.graphics.beginFill(0, 0.5); + overlay.graphics.drawRect(0, 0, 1280, 720); + overlay.addEventListener(MouseEvent.MOUSE_DOWN, overlay_onMouseDown); - overlay.buttonMode = true; - // FlxG.stage.addChild(overlay); + overlay.buttonMode = true; + // FlxG.stage.addChild(overlay); - } + } */ // netConnection.addEventListener(MouseEvent.MOUSE_DOWN, overlay_onMouseDown); @@ -159,9 +143,9 @@ class TitleState extends MusicBeatState { FlxG.sound.playMusic(Paths.music('freakyMenu'), 0); FlxG.sound.music.fadeIn(4, 0, 0.7); + Conductor.bpm = Constants.FREAKY_MENU_BPM; } - Conductor.bpm = 102; persistentUpdate = true; var bg:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK); @@ -290,13 +274,13 @@ class TitleState extends MusicBeatState #end /* if (FlxG.onMobile) + { + if (gfDance != null) { - if (gfDance != null) - { - gfDance.x = (FlxG.width / 2) + (FlxG.accelerometer.x * (FlxG.width / 2)); - // gfDance.y = (FlxG.height / 2) + (FlxG.accelerometer.y * (FlxG.height / 2)); - } + gfDance.x = (FlxG.width / 2) + (FlxG.accelerometer.x * (FlxG.width / 2)); + // gfDance.y = (FlxG.height / 2) + (FlxG.accelerometer.y * (FlxG.height / 2)); } + } */ if (FlxG.keys.justPressed.I) { @@ -313,37 +297,37 @@ class TitleState extends MusicBeatState } /* - FlxG.watch.addQuick('cur display', FlxG.stage.window.display.id); - if (FlxG.keys.justPressed.Y) + FlxG.watch.addQuick('cur display', FlxG.stage.window.display.id); + if (FlxG.keys.justPressed.Y) + { + // trace(FlxG.stage.window.display.name); + + if (FlxG.gamepads.firstActive != null) { - // trace(FlxG.stage.window.display.name); - - if (FlxG.gamepads.firstActive != null) - { - trace(FlxG.gamepads.firstActive.model); - FlxG.gamepads.firstActive.id - } - else - trace('gamepad null'); - - // FlxG.stage.window.title = Std.string(FlxG.random.int(0, 20000)); - // FlxG.stage.window.setIcon(Image.fromFile('assets/images/icon16.png')); - // FlxG.stage.window.readPixels; - - if (FlxG.stage.window.width == Std.int(FlxG.stage.window.display.bounds.width)) - { - FlxG.stage.window.width = 1280; - FlxG.stage.window.height = 720; - FlxG.stage.window.y = 30; - } - else - { - FlxG.stage.window.width = Std.int(FlxG.stage.window.display.bounds.width); - FlxG.stage.window.height = Std.int(FlxG.stage.window.display.bounds.height); - FlxG.stage.window.x = Std.int(FlxG.stage.window.display.bounds.x); - FlxG.stage.window.y = Std.int(FlxG.stage.window.display.bounds.y); - } + trace(FlxG.gamepads.firstActive.model); + FlxG.gamepads.firstActive.id } + else + trace('gamepad null'); + + // FlxG.stage.window.title = Std.string(FlxG.random.int(0, 20000)); + // FlxG.stage.window.setIcon(Image.fromFile('assets/images/icon16.png')); + // FlxG.stage.window.readPixels; + + if (FlxG.stage.window.width == Std.int(FlxG.stage.window.display.bounds.width)) + { + FlxG.stage.window.width = 1280; + FlxG.stage.window.height = 720; + FlxG.stage.window.y = 30; + } + else + { + FlxG.stage.window.width = Std.int(FlxG.stage.window.display.bounds.width); + FlxG.stage.window.height = Std.int(FlxG.stage.window.display.bounds.height); + FlxG.stage.window.x = Std.int(FlxG.stage.window.display.bounds.x); + FlxG.stage.window.y = Std.int(FlxG.stage.window.display.bounds.y); + } + } */ #if debug @@ -434,16 +418,16 @@ class TitleState extends MusicBeatState if (pressedEnter && !skippedIntro && initialized) skipIntro(); /* - #if web - if (!initialized && controls.ACCEPT) - { - // netStream.dispose(); - // FlxG.stage.removeChild(video); + #if web + if (!initialized && controls.ACCEPT) + { + // netStream.dispose(); + // FlxG.stage.removeChild(video); - startIntro(); - skipIntro(); - } - #end + startIntro(); + skipIntro(); + } + #end */ if (controls.UI_LEFT) @@ -509,7 +493,7 @@ class TitleState extends MusicBeatState for (i in 0...textArray.length) { - var money:BoldText = new BoldText(0, 0, textArray[i]); + var money:AtlasText = new AtlasText(0, 0, textArray[i], AtlasFont.BOLD); money.screenCenter(X); money.y += (i * 60) + 200; // credGroup.add(money); @@ -524,10 +508,9 @@ class TitleState extends MusicBeatState lime.ui.Haptic.vibrate(100, 100); - var coolText:BoldText = new BoldText(0, 0, text); + var coolText:AtlasText = new AtlasText(0, 0, text, AtlasFont.BOLD); coolText.screenCenter(X); coolText.y += (textGroup.length * 60) + 200; - // credGroup.add(coolText); textGroup.add(coolText); } diff --git a/source/funkin/VoicesGroup.hx b/source/funkin/VoicesGroup.hx index bb9dd419f..ae34bb0c6 100644 --- a/source/funkin/VoicesGroup.hx +++ b/source/funkin/VoicesGroup.hx @@ -38,6 +38,31 @@ class VoicesGroup extends FlxTypedGroup } } + /** + * Finds the largest deviation from the desired time inside this VoicesGroup. + * + * @param targetTime The time to check against. + * If none is provided, it checks the time of all members against the first member of this VoicesGroup. + * @return The largest deviation from the target time found. + */ + public function checkSyncError(?targetTime:Float):Float + { + var error:Float = 0; + + forEachAlive(function(snd) + { + if (targetTime == null) + targetTime = snd.time; + else + { + var diff:Float = snd.time - targetTime; + if (Math.abs(diff) > Math.abs(error)) + error = diff; + } + }); + return error; + } + // prob a better / cleaner way to do all these forEach stuff? public function pause() { diff --git a/source/funkin/animate/ParseAnimate.hx b/source/funkin/animate/ParseAnimate.hx index 9c2fa17a4..c41aba0f7 100644 --- a/source/funkin/animate/ParseAnimate.hx +++ b/source/funkin/animate/ParseAnimate.hx @@ -4,7 +4,9 @@ import haxe.format.JsonParser; import openfl.Assets; import openfl.geom.Matrix3D; import openfl.geom.Matrix; +#if sys import sys.io.File; +#end /** * Generally designed / written in a way that can be easily taken out of FNF and used elsewhere diff --git a/source/funkin/charting/ChartingState.hx b/source/funkin/charting/ChartingState.hx index 507d8dec6..ba34f2281 100644 --- a/source/funkin/charting/ChartingState.hx +++ b/source/funkin/charting/ChartingState.hx @@ -1,14 +1,6 @@ package funkin.charting; -import funkin.Conductor.BPMChangeEvent; -import funkin.Note.NoteData; -import funkin.Section.SwagSection; -import funkin.SongLoad.SwagSong; -import funkin.audiovis.ABotVis; -import funkin.audiovis.PolygonSpectogram; -import funkin.audiovis.SpectogramSprite; import flixel.FlxSprite; -import funkin.play.HealthIcon; import flixel.addons.display.FlxGridOverlay; import flixel.addons.transition.FlxTransitionableState; import flixel.addons.ui.FlxInputText; @@ -24,14 +16,22 @@ import flixel.system.FlxSound; import flixel.text.FlxText; import flixel.ui.FlxButton; import flixel.util.FlxColor; +import funkin.Conductor.BPMChangeEvent; +import funkin.Note.NoteData; +import funkin.Section.SwagSection; +import funkin.SongLoad.SwagSong; +import funkin.audiovis.ABotVis; +import funkin.audiovis.PolygonSpectogram; +import funkin.audiovis.SpectogramSprite; +import funkin.play.HealthIcon; +import funkin.play.PlayState; +import funkin.rendering.MeshRender; import haxe.Json; import lime.media.AudioBuffer; import lime.utils.Assets; import openfl.events.Event; import openfl.events.IOErrorEvent; import openfl.net.FileReference; -import funkin.rendering.MeshRender; -import funkin.play.PlayState; using Lambda; using StringTools; @@ -976,9 +976,9 @@ class ChartingState extends MusicBeatState _song.bpm = tempBpm; /* if (FlxG.keys.justPressed.UP) - Conductor.bpm += 1; + Conductor.bpm = Conductor.bpm + 1; if (FlxG.keys.justPressed.DOWN) - Conductor.bpm -= 1; */ + Conductor.bpm = Conductor.bpm - 1; */ var shiftThing:Int = 1; if (FlxG.keys.pressed.SHIFT) diff --git a/source/funkin/modding/PolymodHandler.hx b/source/funkin/modding/PolymodHandler.hx index 882dc86fe..1fe2b0682 100644 --- a/source/funkin/modding/PolymodHandler.hx +++ b/source/funkin/modding/PolymodHandler.hx @@ -1,10 +1,9 @@ package funkin.modding; -import polymod.Polymod.ModMetadata; +import funkin.modding.module.ModuleHandler; +import funkin.play.stage.StageData; import polymod.Polymod; -import polymod.backends.OpenFLBackend; import polymod.backends.PolymodAssets.PolymodAssetType; -import polymod.format.ParseRules.LinesParseFormat; import polymod.format.ParseRules.TextFileFormat; class PolymodHandler @@ -31,6 +30,15 @@ class PolymodHandler loadModsById(getAllModIds()); } + /** + * Loads the game with configured mods enabled with Polymod. + */ + public static function loadEnabledMods() + { + trace("Initializing Polymod (using configured mods)..."); + loadModsById(getEnabledModIds()); + } + /** * Loads the game without any mods enabled with Polymod. */ @@ -167,4 +175,61 @@ class PolymodHandler var modIds = [for (i in getAllMods()) i.id]; return modIds; } + + public static function setEnabledMods(newModList:Array):Void + { + FlxG.save.data.enabledMods = newModList; + // Make sure to COMMIT the changes. + FlxG.save.flush(); + } + + /** + * Returns the list of enabled mods. + * @return Array + */ + public static function getEnabledModIds():Array + { + if (FlxG.save.data.enabledMods == null) + { + // NOTE: If the value is null, the enabled mod list is unconfigured. + // Currently, we default to disabling newly installed mods. + // If we want to auto-enable new mods, but otherwise leave the configured list in place, + // we will need some custom logic. + FlxG.save.data.enabledMods = []; + } + return FlxG.save.data.enabledMods; + } + + public static function getEnabledMods():Array + { + var modIds = getEnabledModIds(); + var modMetadata = getAllMods(); + var enabledMods = []; + for (item in modMetadata) + { + if (modIds.indexOf(item.id) != -1) + { + enabledMods.push(item); + } + } + return enabledMods; + } + + public static function forceReloadAssets() + { + // Forcibly clear scripts so that scripts can be edited. + ModuleHandler.clearModuleCache(); + polymod.hscript.PolymodScriptClass.clearScriptClasses(); + + // Forcibly reload Polymod so it finds any new files. + loadEnabledMods(); + + // Reload scripted classes so stages and modules will update. + polymod.hscript.PolymodScriptClass.registerAllScriptClasses(); + + // Reload the stages in cache. + // TODO: Currently this causes lag since you're reading a lot of files, how to fix? + StageDataParser.loadStageCache(); + ModuleHandler.loadModuleCache(); + } } diff --git a/source/funkin/modding/events/ScriptEventDispatcher.hx b/source/funkin/modding/events/ScriptEventDispatcher.hx index bfb62b9d1..474d1a18c 100644 --- a/source/funkin/modding/events/ScriptEventDispatcher.hx +++ b/source/funkin/modding/events/ScriptEventDispatcher.hx @@ -1,7 +1,7 @@ package funkin.modding.events; -import funkin.modding.IScriptedClass; import funkin.modding.IScriptedClass.IPlayStateScriptedClass; +import funkin.modding.IScriptedClass; /** * Utility functions to assist with handling scripted classes. diff --git a/source/funkin/modding/module/Module.hx b/source/funkin/modding/module/Module.hx index 74f04c3bd..d337ad719 100644 --- a/source/funkin/modding/module/Module.hx +++ b/source/funkin/modding/module/Module.hx @@ -1,13 +1,8 @@ package funkin.modding.module; -import funkin.modding.events.ScriptEvent; -import funkin.modding.events.ScriptEvent.UpdateScriptEvent; -import funkin.modding.events.ScriptEvent.KeyboardInputScriptEvent; -import funkin.modding.events.ScriptEvent.NoteScriptEvent; -import funkin.modding.events.ScriptEvent.SongTimeScriptEvent; -import funkin.modding.events.ScriptEvent.CountdownScriptEvent; import funkin.modding.IScriptedClass.IPlayStateScriptedClass; import funkin.modding.IScriptedClass.IStateChangingScriptedClass; +import funkin.modding.events.ScriptEvent; /** * A module is a scripted class which receives all events without requiring a specific context. diff --git a/source/funkin/play/PicoFight.hx b/source/funkin/play/PicoFight.hx index 016fada3f..a5dddac3a 100644 --- a/source/funkin/play/PicoFight.hx +++ b/source/funkin/play/PicoFight.hx @@ -1,14 +1,13 @@ package funkin.play; -import funkin.Note.NoteData; -import funkin.audiovis.PolygonSpectogram; import flixel.FlxObject; import flixel.FlxSprite; import flixel.addons.effects.FlxTrail; import flixel.group.FlxGroup.FlxTypedGroup; import flixel.math.FlxMath; import flixel.util.FlxColor; -import flixel.util.FlxTimer; +import funkin.Note.NoteData; +import funkin.audiovis.PolygonSpectogram; class PicoFight extends MusicBeatState { @@ -202,7 +201,6 @@ class PicoFight extends MusicBeatState picoHealth += 1; makeNotes(); - return true; } } diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 09cdc0c06..87e8d9e69 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1,12 +1,12 @@ package funkin.play; -import funkin.play.character.BaseCharacter; -import flixel.addons.transition.FlxTransitionableState; import flixel.FlxCamera; import flixel.FlxObject; import flixel.FlxSprite; import flixel.FlxState; import flixel.FlxSubState; +import flixel.addons.transition.FlxTransitionableState; +import flixel.addons.transition.FlxTransitionableState; import flixel.group.FlxGroup; import flixel.math.FlxMath; import flixel.math.FlxPoint; @@ -18,22 +18,27 @@ import flixel.ui.FlxBar; import flixel.util.FlxColor; import flixel.util.FlxSort; import flixel.util.FlxTimer; -import funkin.charting.ChartingState; -import funkin.modding.events.ScriptEvent; -import funkin.modding.events.ScriptEvent.SongTimeScriptEvent; -import funkin.modding.events.ScriptEvent.UpdateScriptEvent; -import funkin.modding.events.ScriptEventDispatcher; -import funkin.modding.IHook; -import funkin.modding.module.ModuleHandler; import funkin.Note; -import funkin.play.character.CharacterData; -import funkin.play.stage.Stage; -import funkin.play.HealthIcon; -import funkin.play.stage.StageData; -import funkin.play.Strumline.StrumlineArrow; -import funkin.play.Strumline.StrumlineStyle; +import funkin.Note; +import funkin.Section.SwagSection; import funkin.Section.SwagSection; import funkin.SongLoad.SwagSong; +import funkin.SongLoad.SwagSong; +import funkin.charting.ChartingState; +import funkin.modding.IHook; +import funkin.modding.IHook; +import funkin.modding.events.ScriptEvent; +import funkin.modding.events.ScriptEventDispatcher; +import funkin.modding.module.ModuleHandler; +import funkin.play.HealthIcon; +import funkin.play.Strumline.StrumlineArrow; +import funkin.play.Strumline.StrumlineArrow; +import funkin.play.Strumline.StrumlineStyle; +import funkin.play.Strumline.StrumlineStyle; +import funkin.play.character.BaseCharacter; +import funkin.play.character.CharacterData; +import funkin.play.stage.Stage; +import funkin.play.stage.StageData; import funkin.ui.PopUpStuff; import funkin.ui.PreferencesMenu; import funkin.util.Constants; @@ -838,7 +843,7 @@ class PlayState extends MusicBeatState implements IHook var gottaHitNote:Bool = section.mustHitSection; - if (songNotes.highStakes) + if (songNotes.highStakes) // noteData > 3 gottaHitNote = !section.mustHitSection; var oldNote:Note; @@ -848,7 +853,9 @@ class PlayState extends MusicBeatState implements IHook oldNote = null; var swagNote:Note = new Note(daStrumTime, daNoteData, oldNote); - swagNote.data = songNotes; + // swagNote.data = songNotes; + swagNote.data.sustainLength = songNotes.sustainLength; + swagNote.data.altNote = songNotes.altNote; swagNote.scrollFactor.set(0, 0); var susLength:Float = swagNote.data.sustainLength; @@ -950,6 +957,7 @@ class PlayState extends MusicBeatState implements IHook vocals.pause(); FlxG.sound.music.time = 0; + regenNoteData(); // loads the note data from start health = 1; songScore = 0; @@ -1597,7 +1605,7 @@ class PlayState extends MusicBeatState implements IHook } } - if (PlayState.instance.currentStage == null) + if (PlayState.instance == null || PlayState.instance.currentStage == null) return; for (keyId => isPressed in pressArray) @@ -1709,9 +1717,8 @@ class PlayState extends MusicBeatState implements IHook if (!super.stepHit()) return false; - if (!isInCutscene - && Math.abs(FlxG.sound.music.time - (Conductor.songPosition - Conductor.offset)) > 20 - || (currentSong.needsVoices && Math.abs(vocals.time - (Conductor.songPosition - Conductor.offset)) > 20)) + if (Math.abs(FlxG.sound.music.time - (Conductor.songPosition - Conductor.offset)) > 20 + || Math.abs(vocals.checkSyncError(Conductor.songPosition - Conductor.offset)) > 20) { resyncVocals(); } diff --git a/source/funkin/play/VanillaCutscenes.hx b/source/funkin/play/VanillaCutscenes.hx index 9cbcd8736..71587eeb9 100644 --- a/source/funkin/play/VanillaCutscenes.hx +++ b/source/funkin/play/VanillaCutscenes.hx @@ -1,10 +1,12 @@ package funkin.play; -import flixel.util.FlxTimer; -import flixel.tweens.FlxTween; -import flixel.tweens.FlxEase; -import flixel.util.FlxColor; import flixel.FlxSprite; +import flixel.tweens.FlxEase; +import flixel.tweens.FlxEase; +import flixel.tweens.FlxTween; +import flixel.tweens.FlxTween; +import flixel.util.FlxColor; +import flixel.util.FlxTimer; /** * Static methods for playing cutscenes in the PlayState. @@ -43,8 +45,8 @@ class VanillaCutscenes PlayState.instance.add(blackScreen); #if html5 - vid:FlxVideo = new FlxVideo(path); - vid.finishCallback = finishVideoCutscene(); + var vid:FlxVideo = new FlxVideo(path); + vid.finishCallback = finishVideoCutscene; #else finishVideoCutscene(); #end diff --git a/source/funkin/play/stage/Bopper.hx b/source/funkin/play/stage/Bopper.hx index 0b026ed22..dfb91607c 100644 --- a/source/funkin/play/stage/Bopper.hx +++ b/source/funkin/play/stage/Bopper.hx @@ -1,12 +1,8 @@ package funkin.play.stage; -import funkin.modding.events.ScriptEvent; -import funkin.modding.events.ScriptEvent.UpdateScriptEvent; -import funkin.modding.events.ScriptEvent.NoteScriptEvent; -import funkin.modding.events.ScriptEvent.SongTimeScriptEvent; -import funkin.modding.events.ScriptEvent.CountdownScriptEvent; -import funkin.modding.IScriptedClass.IPlayStateScriptedClass; import flixel.FlxSprite; +import funkin.modding.IScriptedClass.IPlayStateScriptedClass; +import funkin.modding.events.ScriptEvent; /** * A Bopper is a stage prop which plays a dance animation. @@ -97,14 +93,14 @@ class Bopper extends FlxSprite implements IPlayStateScriptedClass { if (danceEvery > 0 && event.beat % danceEvery == 0) { - dance(); + dance(true); } } /** * Called every `danceEvery` beats of the song. */ - function dance(force:Bool = false):Void + public function dance(force:Bool = false):Void { if (this.animation == null) { @@ -120,17 +116,17 @@ class Bopper extends FlxSprite implements IPlayStateScriptedClass { if (hasDanced) { - playAnimation('danceRight$idleSuffix'); + playAnimation('danceRight$idleSuffix', force); } else { - playAnimation('danceLeft$idleSuffix'); + playAnimation('danceLeft$idleSuffix', force); } hasDanced = !hasDanced; } else { - playAnimation('idle$idleSuffix'); + playAnimation('idle$idleSuffix', force); } } @@ -213,7 +209,6 @@ class Bopper extends FlxSprite implements IPlayStateScriptedClass public function setAnimationOffsets(name:String, xOffset:Float, yOffset:Float):Void { animationOffsets.set(name, [xOffset, yOffset]); - applyAnimationOffsets(name); } /** diff --git a/source/funkin/play/stage/ScriptedBopper.hx b/source/funkin/play/stage/ScriptedBopper.hx index 4dd98e82c..405ef57f6 100644 --- a/source/funkin/play/stage/ScriptedBopper.hx +++ b/source/funkin/play/stage/ScriptedBopper.hx @@ -2,7 +2,5 @@ package funkin.play.stage; import funkin.modding.IHook; -// -// @:hscriptClass -// @:keep -// class ScriptedBopper extends Bopper implements IHook {} +@:hscriptClass +class ScriptedBopper extends Bopper implements IHook {} diff --git a/source/funkin/play/stage/Stage.hx b/source/funkin/play/stage/Stage.hx index 2b8c46acb..8e2713b2c 100644 --- a/source/funkin/play/stage/Stage.hx +++ b/source/funkin/play/stage/Stage.hx @@ -1,20 +1,16 @@ package funkin.play.stage; -import funkin.util.assets.FlxAnimationUtil; -import funkin.play.character.BaseCharacter; -import funkin.modding.events.ScriptEventDispatcher; -import funkin.modding.events.ScriptEvent; -import funkin.modding.events.ScriptEvent.CountdownScriptEvent; -import funkin.modding.events.ScriptEvent.KeyboardInputScriptEvent; -import funkin.modding.IScriptedClass; import flixel.FlxSprite; import flixel.group.FlxSpriteGroup; -import flixel.math.FlxPoint; import flixel.util.FlxSort; import funkin.modding.IHook; -import funkin.play.character.BaseCharacter.CharacterType; +import funkin.modding.IScriptedClass; +import funkin.modding.events.ScriptEvent; +import funkin.modding.events.ScriptEventDispatcher; +import funkin.play.character.Character.CharacterType; import funkin.play.stage.StageData.StageDataParser; import funkin.util.SortUtil; +import funkin.util.assets.FlxAnimationUtil; /** * A Stage is a group of objects rendered in the PlayState. @@ -149,6 +145,18 @@ class Stage extends FlxSpriteGroup implements IHook implements IPlayStateScripte if (Std.isOfType(propSprite, Bopper)) { cast(propSprite, Bopper).setAnimationOffsets(propAnim.name, propAnim.offsets[0], propAnim.offsets[1]); +<<<<<<< HEAD +======= + } + } + default: // "sparrow" + FlxAnimationUtil.addAtlasAnimations(propSprite, dataProp.animations); + if (Std.isOfType(propSprite, Bopper)) + { + for (propAnim in dataProp.animations) + { + cast(propSprite, Bopper).setAnimationOffsets(propAnim.name, propAnim.offsets[0], propAnim.offsets[1]); +>>>>>>> origin/feature/scripted-modules } } default: // "sparrow" @@ -427,33 +435,45 @@ class Stage extends FlxSpriteGroup implements IHook implements IPlayStateScripte for (prop in this.namedProps) { - remove(prop); - prop.kill(); - prop.destroy(); + if (prop != null) + { + remove(prop); + prop.kill(); + prop.destroy(); + } } namedProps.clear(); for (char in this.characters) { - remove(char); - char.kill(); - char.destroy(); + if (char != null) + { + remove(char); + char.kill(); + char.destroy(); + } } characters.clear(); for (bopper in boppers) { - remove(bopper); - bopper.kill(); - bopper.destroy(); + if (bopper != null) + { + remove(bopper); + bopper.kill(); + bopper.destroy(); + } } boppers = []; for (sprite in this.group) { - remove(sprite); - sprite.kill(); - sprite.destroy(); + if (sprite != null) + { + sprite.kill(); + sprite.destroy(); + remove(sprite); + } } group.clear(); } @@ -497,9 +517,6 @@ class Stage extends FlxSpriteGroup implements IHook implements IPlayStateScripte public function onCountdownEnd(event:CountdownScriptEvent) {} - /** - * A function that should get called every frame. - */ public function onUpdate(event:UpdateScriptEvent) {} public function onNoteHit(event:NoteScriptEvent) {} diff --git a/source/funkin/play/stage/StageData.hx b/source/funkin/play/stage/StageData.hx index 4e240b8b6..dc5538bac 100644 --- a/source/funkin/play/stage/StageData.hx +++ b/source/funkin/play/stage/StageData.hx @@ -1,7 +1,7 @@ package funkin.play.stage; -import funkin.util.VersionUtil; import flixel.util.typeLimit.OneOfTwo; +import funkin.util.VersionUtil; import funkin.util.assets.DataAssets; import haxe.Json; import openfl.Assets; diff --git a/source/funkin/ui/AtlasText.hx b/source/funkin/ui/AtlasText.hx index 3006f3994..b07aca240 100644 --- a/source/funkin/ui/AtlasText.hx +++ b/source/funkin/ui/AtlasText.hx @@ -1,19 +1,10 @@ package funkin.ui; import flixel.FlxSprite; -import flixel.group.FlxSpriteGroup; import flixel.graphics.frames.FlxAtlasFrames; +import flixel.group.FlxSpriteGroup; import flixel.util.FlxStringUtil; -@:forward -abstract BoldText(AtlasText) from AtlasText to AtlasText -{ - inline public function new(x = 0.0, y = 0.0, text:String) - { - this = new AtlasText(x, y, text, AtlasFont.BOLD); - } -} - /** * AtlasText is an improved version of Alphabet and FlxBitmapText. * It supports animations on the letters, and is less buggy than Alphabet. diff --git a/source/funkin/ui/ControlsMenu.hx b/source/funkin/ui/ControlsMenu.hx index 62445be96..e5e3e44b0 100644 --- a/source/funkin/ui/ControlsMenu.hx +++ b/source/funkin/ui/ControlsMenu.hx @@ -1,6 +1,5 @@ package funkin.ui; -import funkin.Controls; import flixel.FlxCamera; import flixel.FlxObject; import flixel.FlxSprite; @@ -8,6 +7,7 @@ import flixel.group.FlxGroup; import flixel.input.actions.FlxActionInput; import flixel.input.gamepad.FlxGamepadInputID; import flixel.input.keyboard.FlxKey; +import funkin.Controls; import funkin.ui.AtlasText; import funkin.ui.MenuList; import funkin.ui.TextMenuList; @@ -87,20 +87,20 @@ class ControlsMenu extends funkin.ui.OptionsState.Page if (currentHeader != "UI_" && name.indexOf("UI_") == 0) { currentHeader = "UI_"; - headers.add(new BoldText(0, y, "UI")).screenCenter(X); + headers.add(new AtlasText(0, y, "UI", AtlasFont.BOLD)).screenCenter(X); y += spacer; } else if (currentHeader != "NOTE_" && name.indexOf("NOTE_") == 0) { currentHeader = "NOTE_"; - headers.add(new BoldText(0, y, "NOTES")).screenCenter(X); + headers.add(new AtlasText(0, y, "NOTES", AtlasFont.BOLD)).screenCenter(X); y += spacer; } if (currentHeader != null && name.indexOf(currentHeader) == 0) name = name.substr(currentHeader.length); - var label = labels.add(new BoldText(150, y, name)); + var label = labels.add(new AtlasText(150, y, name, AtlasFont.BOLD)); label.alpha = 0.6; for (i in 0...COLUMNS) createItem(label.x + 400 + i * 300, y, control, i); diff --git a/source/funkin/ui/OptionsState.hx b/source/funkin/ui/OptionsState.hx index 32b511d3e..3a74ef3f8 100644 --- a/source/funkin/ui/OptionsState.hx +++ b/source/funkin/ui/OptionsState.hx @@ -5,9 +5,9 @@ import flixel.FlxSubState; import flixel.addons.transition.FlxTransitionableState; import flixel.group.FlxGroup; import flixel.util.FlxSignal; +import funkin.util.Constants; +import funkin.util.WindowUtil; -// typedef OptionsState = OptionsMenu_old; -// class OptionsState_new extends MusicBeatState class OptionsState extends MusicBeatState { var pages = new Map(); @@ -30,17 +30,12 @@ class OptionsState extends MusicBeatState var options = addPage(Options, new OptionsMenu(false)); var preferences = addPage(Preferences, new PreferencesMenu()); var controls = addPage(Controls, new ControlsMenu()); - // var colors = addPage(Colors, new ColorsMenu()); - - var mods = addPage(Mods, new ModMenu()); if (options.hasMultipleOptions()) { options.onExit.add(exitToMainMenu); controls.onExit.add(switchPage.bind(Options)); - // colors.onExit.add(switchPage.bind(Options)); preferences.onExit.add(switchPage.bind(Options)); - mods.onExit.add(switchPage.bind(Options)); } else { @@ -66,12 +61,18 @@ class OptionsState extends MusicBeatState function setPage(name:PageName) { if (pages.exists(currentName)) + { currentPage.exists = false; + currentPage.visible = false; + } currentName = name; if (pages.exists(currentName)) + { currentPage.exists = true; + currentPage.visible = true; + } } override function finishTransIn() @@ -90,7 +91,7 @@ class OptionsState extends MusicBeatState function exitToMainMenu() { currentPage.enabled = false; - // Todo animate? + // TODO: Animate this transition? FlxG.switchState(new MainMenuState()); } } @@ -174,7 +175,6 @@ class OptionsMenu extends Page createItem("PREFERENCES", function() switchPage(Preferences)); createItem("CONTROLS", function() switchPage(Controls)); // createItem("COLORS", function() switchPage(Colors)); - createItem("MODS", function() switchPage(Mods)); #if CAN_OPEN_LINKS if (showDonate) @@ -218,11 +218,7 @@ class OptionsMenu extends Page #if CAN_OPEN_LINKS function selectDonate() { - #if linux - Sys.command('/usr/bin/xdg-open', ["https://ninja-muffin24.itch.io/funkin", "&"]); - #else - FlxG.openURL('https://ninja-muffin24.itch.io/funkin'); - #end + WindowUtil.openURL(Constants.URL_ITCH); } #end diff --git a/source/funkin/ui/PreferencesMenu.hx b/source/funkin/ui/PreferencesMenu.hx index a5aa4e368..94158bcce 100644 --- a/source/funkin/ui/PreferencesMenu.hx +++ b/source/funkin/ui/PreferencesMenu.hx @@ -4,8 +4,8 @@ import flixel.FlxCamera; import flixel.FlxObject; import flixel.FlxSprite; import funkin.ui.AtlasText.AtlasFont; -import funkin.ui.TextMenuList.TextMenuItem; import funkin.ui.OptionsState.Page; +import funkin.ui.TextMenuList.TextMenuItem; class PreferencesMenu extends Page { diff --git a/source/funkin/ui/Prompt.hx b/source/funkin/ui/Prompt.hx index 1679d3886..76d85744b 100644 --- a/source/funkin/ui/Prompt.hx +++ b/source/funkin/ui/Prompt.hx @@ -1,12 +1,12 @@ package funkin.ui; import flixel.FlxSprite; -import flixel.graphics.frames.FlxAtlasFrames; -import flixel.text.FlxText; -import flixel.util.FlxColor; -import funkin.ui.AtlasText; +import funkin.ui.AtlasText.AtlasFont; import funkin.ui.MenuList; +/** + * Opens a yes/no dialog box as a substate over the current state. + */ class Prompt extends flixel.FlxSubState { inline static var MARGIN = 100; @@ -26,7 +26,7 @@ class Prompt extends flixel.FlxSubState buttons = new TextMenuList(Horizontal); - field = new BoldText(text); + field = new AtlasText(text, AtlasFont.BOLD); field.scrollFactor.set(0, 0); } diff --git a/source/funkin/util/Constants.hx b/source/funkin/util/Constants.hx index af775babe..a93578c20 100644 --- a/source/funkin/util/Constants.hx +++ b/source/funkin/util/Constants.hx @@ -1,7 +1,7 @@ package funkin.util; -import lime.app.Application; import flixel.util.FlxColor; +import lime.app.Application; class Constants { @@ -18,6 +18,8 @@ class Constants public static final VERSION_SUFFIX = ' PROTOTYPE'; public static var VERSION(get, null):String; + public static final FREAKY_MENU_BPM = 102; + #if debug public static final GIT_HASH = funkin.util.macro.GitCommit.getGitCommitHash(); diff --git a/source/funkin/util/VersionUtil.hx b/source/funkin/util/VersionUtil.hx index a5c7e71f4..57e1f80ed 100644 --- a/source/funkin/util/VersionUtil.hx +++ b/source/funkin/util/VersionUtil.hx @@ -1,7 +1,7 @@ package funkin.util; -import thx.semver.VersionRule; import thx.semver.Version; +import thx.semver.VersionRule; /** * Remember, increment the patch version (1.0.x) if you make a bugfix, diff --git a/source/funkin/util/assets/FlxAnimationUtil.hx b/source/funkin/util/assets/FlxAnimationUtil.hx index ac07e6065..d40dfa73c 100644 --- a/source/funkin/util/assets/FlxAnimationUtil.hx +++ b/source/funkin/util/assets/FlxAnimationUtil.hx @@ -1,7 +1,7 @@ package funkin.util.assets; -import funkin.play.AnimationData; import flixel.FlxSprite; +import funkin.play.AnimationData; class FlxAnimationUtil {