diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 430dd74..a0146ed 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -29,11 +29,11 @@ jobs: haxelib list - name: Compile Linux run: haxelib run lime build Project.xml linux - - name: Publish Artifact - uses: actions/upload-artifact@v4 - with: - name: Universe-Linux - path: 'export/release/linux/bin' + # - name: Publish Artifact + # uses: actions/upload-artifact@v4 + # with: + # name: Universe-Linux + # path: 'export/release/linux/bin' Windows-Build: runs-on: windows-latest @@ -52,11 +52,11 @@ jobs: shell: cmd - name: Compile Windows run: haxelib run lime build windows - - name: Publish Artifact - uses: actions/upload-artifact@v4 - with: - name: Universe-Windows - path: export/release/windows/bin + # - name: Publish Artifact + # uses: actions/upload-artifact@v4 + # with: + # name: Universe-Windows + # path: export/release/windows/bin MacOS-INTEL-Build: runs-on: macos-latest @@ -74,32 +74,33 @@ jobs: haxelib list - name: Compile MacOS ARM run: haxelib run lime build mac -64 - - name: Publish Artifact - uses: actions/upload-artifact@v4 - with: - name: Universe-MacOS-INTEL - path: export/release/macos/bin - # MacOS On ARM (M1 to M4 chips) Will be commented until we figure it out. - - # MacOS-ARM-Build: - # runs-on: macos-latest + # - name: Publish Artifact + # uses: actions/upload-artifact@v4 + # with: + # name: Universe-MacOS-INTEL + # path: export/release/macos/bin + + # MacOS On ARM (M1 to M4 chips) Was originally broken, but found out it was lime. + MacOS-ARM-Build: + runs-on: macos-latest - # steps: - # - uses: actions/checkout@v4.1.7 + steps: + - uses: actions/checkout@v4.1.7 - # - uses: krdlab/setup-haxe@master - # with: - # haxe-version: 4.3.4 - # - name: Install Haxelib - # run: | - # haxelib setup ~/haxelib - # chmod +x ./compile/workflow/unix.sh - # sh ./compile/workflow/unix.sh - # haxelib list - # - name: Compile MacOS ARM - # run: haxelib run lime build mac -arm64 - # - name: Publish Artifact - # uses: actions/upload-artifact@v4 - # with: - # name: Universe-MacOS-ARM - # path: export/release/macos/bin + - uses: krdlab/setup-haxe@master + with: + haxe-version: 4.3.4 + - name: Install Haxelib + run: | + haxelib setup ~/haxelib + chmod +x ./compile/workflow/unix.sh + sh ./compile/workflow/unix.sh + haxelib list + haxelib install lime 8.2.2 && haxelib set lime 8.2.2 + - name: Compile MacOS ARM + run: haxelib run lime build mac -arm64 + # - name: Publish Artifact + # uses: actions/upload-artifact@v4 + # with: + # name: Universe-MacOS-ARM + # path: export/release/macos/bin diff --git a/.gitignore b/.gitignore index 454766e..36f7915 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ export/* !.vscode/settings.json !.vscode/tasks.json !.vscode/launch.json -!.vscode/extensions.json \ No newline at end of file +!.vscode/extensions.json +*.DS_STORE \ No newline at end of file diff --git a/Project.xml b/Project.xml index f242a31..e020e14 100644 --- a/Project.xml +++ b/Project.xml @@ -2,7 +2,12 @@ - +
+ +
+
+ +
@@ -45,23 +50,17 @@ - - - - - - @@ -135,6 +134,7 @@ NOT USING A DIRECT THING TO THE ASSET!!! --> + @@ -143,9 +143,7 @@ - - - + @@ -157,12 +155,18 @@ - + + + + + + + diff --git a/README.md b/README.md index 1ecd459..3de25d2 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ - + @@ -74,7 +74,7 @@ - + diff --git a/assets/preload/images/.DS_Store b/assets/preload/images/.DS_Store new file mode 100644 index 0000000..396f094 Binary files /dev/null and b/assets/preload/images/.DS_Store differ diff --git a/assets/preload/images/credits/char.png b/assets/preload/images/credits/char.png index 75e4117..aeecf26 100644 Binary files a/assets/preload/images/credits/char.png and b/assets/preload/images/credits/char.png differ diff --git a/assets/preload/images/templates/mods/templateIcon.png b/assets/preload/images/templates/mods/templateIcon.png new file mode 100644 index 0000000..825cc0e Binary files /dev/null and b/assets/preload/images/templates/mods/templateIcon.png differ diff --git a/assets/preload/uescript/.DS_Store b/assets/preload/uescript/.DS_Store new file mode 100644 index 0000000..7fa4103 Binary files /dev/null and b/assets/preload/uescript/.DS_Store differ diff --git a/assets/shared/.DS_Store b/assets/shared/.DS_Store new file mode 100644 index 0000000..ae7613d Binary files /dev/null and b/assets/shared/.DS_Store differ diff --git a/assets/shared/images/.DS_Store b/assets/shared/images/.DS_Store new file mode 100644 index 0000000..70df296 Binary files /dev/null and b/assets/shared/images/.DS_Store differ diff --git a/compile/.DS_Store b/compile/.DS_Store new file mode 100644 index 0000000..f4ae30c Binary files /dev/null and b/compile/.DS_Store differ diff --git a/compile/Test_Build_Mac.sh b/compile/Test_Build_Mac.sh new file mode 100644 index 0000000..fca271d --- /dev/null +++ b/compile/Test_Build_Mac.sh @@ -0,0 +1,2 @@ +lime test mac -DTEST_BUILD +read -n1 -r -p "Press any key to continue..." key diff --git a/compile/workflow/unix.sh b/compile/workflow/unix.sh index 3c3d90b..3df0362 100644 --- a/compile/workflow/unix.sh +++ b/compile/workflow/unix.sh @@ -1,9 +1,14 @@ -haxelib install lime 8.1.3 && haxelib set lime 8.1.3 -haxelib install openfl 9.2.2 && haxelib set openfl 9.2.2 -haxelib install flixel 5.6.2 && haxelib set flixel 5.6.2 +haxelib install lime 8.2.2 && haxelib set lime 8.2.2 +haxelib install openfl 9.4.1 && haxelib set openfl 9.4.1 +haxelib install flixel 5.5.0 && haxelib set flixel 5.5.0 haxelib install flixel-addons 3.2.0 && haxelib set flixel-addons 3.2.0 haxelib install flixel-ui 2.5.0 && haxelib set flixel-ui 2.5.0 haxelib install hxvlc 1.9.3 && haxelib set hxvlc 1.9.3 +haxelib install polymod +haxelib git jsonpatch https://github.com/EliteMasterEric/jsonpatch f9b83215acd586dc28754b4ae7f69d4c06c3b4d3 +haxelib git jsonpath https://github.com/EliteMasterEric/jsonpath 7a24193717b36393458c15c0435bb7c4470ecdda +haxelib git thx.core https://github.com/fponticelli/thx.core 2bf2b992e06159510f595554e6b952e47922f128 +haxelib git thx.semver https://github.com/fponticelli/thx.semver bdb191fe7cf745c02a980749906dbf22719e200b haxelib run lime setup flixel haxelib run lime setup @@ -13,5 +18,4 @@ haxelib install hxcpp-debug-server haxelib install hxdiscord_rpc haxelib git hxcpp https://github.com/moxie-coder/hxcpp-compiled -haxelib git linc_luajit https://github.com/superpowers04/linc_luajit -haxelib git hscript-improved https://github.com/CodenameCrew/hscript-improved \ No newline at end of file +haxelib git linc_luajit https://github.com/superpowers04/linc_luajit \ No newline at end of file diff --git a/compile/workflow/windows.bat b/compile/workflow/windows.bat index 3c3d90b..3df0362 100644 --- a/compile/workflow/windows.bat +++ b/compile/workflow/windows.bat @@ -1,9 +1,14 @@ -haxelib install lime 8.1.3 && haxelib set lime 8.1.3 -haxelib install openfl 9.2.2 && haxelib set openfl 9.2.2 -haxelib install flixel 5.6.2 && haxelib set flixel 5.6.2 +haxelib install lime 8.2.2 && haxelib set lime 8.2.2 +haxelib install openfl 9.4.1 && haxelib set openfl 9.4.1 +haxelib install flixel 5.5.0 && haxelib set flixel 5.5.0 haxelib install flixel-addons 3.2.0 && haxelib set flixel-addons 3.2.0 haxelib install flixel-ui 2.5.0 && haxelib set flixel-ui 2.5.0 haxelib install hxvlc 1.9.3 && haxelib set hxvlc 1.9.3 +haxelib install polymod +haxelib git jsonpatch https://github.com/EliteMasterEric/jsonpatch f9b83215acd586dc28754b4ae7f69d4c06c3b4d3 +haxelib git jsonpath https://github.com/EliteMasterEric/jsonpath 7a24193717b36393458c15c0435bb7c4470ecdda +haxelib git thx.core https://github.com/fponticelli/thx.core 2bf2b992e06159510f595554e6b952e47922f128 +haxelib git thx.semver https://github.com/fponticelli/thx.semver bdb191fe7cf745c02a980749906dbf22719e200b haxelib run lime setup flixel haxelib run lime setup @@ -13,5 +18,4 @@ haxelib install hxcpp-debug-server haxelib install hxdiscord_rpc haxelib git hxcpp https://github.com/moxie-coder/hxcpp-compiled -haxelib git linc_luajit https://github.com/superpowers04/linc_luajit -haxelib git hscript-improved https://github.com/CodenameCrew/hscript-improved \ No newline at end of file +haxelib git linc_luajit https://github.com/superpowers04/linc_luajit \ No newline at end of file diff --git a/new_example_mods/.DS_Store b/new_example_mods/.DS_Store new file mode 100644 index 0000000..1562fcf Binary files /dev/null and b/new_example_mods/.DS_Store differ diff --git a/new_example_mods/test_folder/.DS_Store b/new_example_mods/test_folder/.DS_Store new file mode 100644 index 0000000..d27ed64 Binary files /dev/null and b/new_example_mods/test_folder/.DS_Store differ diff --git a/new_example_mods/test_folder/icon.png b/new_example_mods/test_folder/icon.png new file mode 100644 index 0000000..825cc0e Binary files /dev/null and b/new_example_mods/test_folder/icon.png differ diff --git a/new_example_mods/test_folder/images/AnnaBelleAnnoyed.png b/new_example_mods/test_folder/images/AnnaBelleAnnoyed.png new file mode 100644 index 0000000..8a12dba Binary files /dev/null and b/new_example_mods/test_folder/images/AnnaBelleAnnoyed.png differ diff --git a/new_example_mods/test_folder/meta.json b/new_example_mods/test_folder/meta.json new file mode 100644 index 0000000..bd70ebe --- /dev/null +++ b/new_example_mods/test_folder/meta.json @@ -0,0 +1,6 @@ +{ + "title":"Test Mod", + "description":"This mod is for testing the polymod mod loader framework", + "api_version":"1.0.0", + "mod_version":"1.0.0" +} \ No newline at end of file diff --git a/new_example_mods/test_folder/yuh.json b/new_example_mods/test_folder/yuh.json deleted file mode 100644 index 4186449..0000000 --- a/new_example_mods/test_folder/yuh.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "value": "key" -} \ No newline at end of file diff --git a/source/ClientPrefs.hx b/source/ClientPrefs.hx index 44c923f..1a1b129 100644 --- a/source/ClientPrefs.hx +++ b/source/ClientPrefs.hx @@ -9,7 +9,7 @@ import flixel.util.FlxColor; class SaveVariables { - public var lastLoadedMod:String = null; + public var lastLoadedMod:Array = []; public var downScroll:Bool = false; public var middleScroll:Bool = false; public var opponentStrums:Bool = true; @@ -263,12 +263,12 @@ class ClientPrefs { PlayerSettings.player1.controls.setKeyboardScheme(KeyboardScheme.Solo); - TitleState.muteKeys = copyKey(keyBinds.get('volume_mute')); - TitleState.volumeDownKeys = copyKey(keyBinds.get('volume_down')); - TitleState.volumeUpKeys = copyKey(keyBinds.get('volume_up')); - FlxG.sound.muteKeys = TitleState.muteKeys; - FlxG.sound.volumeDownKeys = TitleState.volumeDownKeys; - FlxG.sound.volumeUpKeys = TitleState.volumeUpKeys; + modding.LoadState.muteKeys = copyKey(keyBinds.get('volume_mute')); + modding.LoadState.volumeDownKeys = copyKey(keyBinds.get('volume_down')); + modding.LoadState.volumeUpKeys = copyKey(keyBinds.get('volume_up')); + FlxG.sound.muteKeys = modding.LoadState.muteKeys; + FlxG.sound.volumeDownKeys = modding.LoadState.volumeDownKeys; + FlxG.sound.volumeUpKeys = modding.LoadState.volumeUpKeys; } public static function copyKey(arrayToCopy:Array):Array diff --git a/source/CoolUtil.hx b/source/CoolUtil.hx index 7fec21b..991ba77 100644 --- a/source/CoolUtil.hx +++ b/source/CoolUtil.hx @@ -1,5 +1,7 @@ package; +import sys.Watermark; +import haxe.PosInfos; import flixel.FlxG; import openfl.utils.Assets; import lime.utils.Assets as LimeAssets; @@ -191,30 +193,73 @@ class CoolUtil return maxKey; } - public static function coolError(message:Null = null, title:Null = null):Void + static function openSubState(s:flixel.FlxSubState) { - #if !linux - lime.app.Application.current.window.alert(message, title); + FlxG.state.openSubState(s); + } + + public static function coolError(message:String = "", title:String = "", ?backer:FlxSprite = null, fadeDelay:Int = 2, ?infos:PosInfos):Void + { + #if CLASSIC_ERROR + #if !linux + lime.app.Application.current.window.alert(message, title); + #else + Logs.traceNew(title + " - " + message, ERROR); + + var text:FlxText = new FlxText(8, 0, 1280, title + " - " + message, 24); + text.color = FlxColor.RED; + text.borderSize = 1.5; + text.borderColor = FlxColor.BLACK; + text.scrollFactor.set(); + text.cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]]; + + FlxG.state.add(text); + + FlxTween.tween(text, {alpha: 0, y: 8}, 5, { + onComplete: function(_) + { + FlxG.state.remove(text); + text.destroy(); + } + }); + #end #else - trace(title + " - " + message, ERROR); + openSubState(new CoolErrorSubstate(message, title, backer, fadeDelay, infos)); + #end + } - var text:FlxText = new FlxText(8, 0, 1280, title + " - " + message, 24); - text.color = FlxColor.RED; - text.borderSize = 1.5; - text.borderColor = FlxColor.BLACK; - text.scrollFactor.set(); - text.cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]]; + static var watermarks:Array = []; + public static function spawnWatermark(text:String, color:Int = 0xFFFFFF, size:Int = 100) + { + var watermark:sys.Watermark = new sys.Watermark(text, color, size); + watermark.screenCenter(); + Main.instance.addChild(watermark); + watermarks.push(watermark); + } + + public static function removeWatermark(watermark:Watermark) + { + try + { + Main.instance.removeChild(watermark); + watermarks.remove(watermark); + } + catch(e:Dynamic) {} + } - FlxG.state.add(text); + public static function clearWatermarks() + { + for (watermark in watermarks) + { + Main.instance.removeChild(watermark); + watermarks.remove(watermark); + } + } - FlxTween.tween(text, {alpha: 0, y: 8}, 5, { - onComplete: function(_) - { - FlxG.state.remove(text); - text.destroy(); - } - }); - #end + public static function addToCurrentState(o:FlxBasic, topCam:Bool = true):FlxBasic + { + if (topCam) o.camera = FlxG.cameras.list[FlxG.cameras.list.length - 1]; + return FlxG.state.add(o); } public static function numberArray(max:Int, ?min = 0):Array diff --git a/source/FreeplayState.hx b/source/FreeplayState.hx index 2af6087..4c42eb4 100644 --- a/source/FreeplayState.hx +++ b/source/FreeplayState.hx @@ -723,7 +723,7 @@ class FreeplayState extends MusicBeatState } catch (e:Dynamic) { - Logs.traceNew('Error loading/playing file! $e', ERROR); + CoolUtil.coolError('Error loading song! $e', "Freeplay | Missing File or Chart"); FlxG.sound.play(Paths.sound('cancelMenu')); } #end @@ -741,7 +741,7 @@ class FreeplayState extends MusicBeatState } catch (e:Dynamic) { - lime.app.Application.current.window.alert('Error loading song!\n$e'); + CoolUtil.coolError('Error loading song! $e', "Freeplay | Missing File or Chart"); return; } /*#if MODS_ALLOWED diff --git a/source/HealthIcon.hx b/source/HealthIcon.hx index 1112357..d4deb4a 100644 --- a/source/HealthIcon.hx +++ b/source/HealthIcon.hx @@ -34,7 +34,7 @@ class HealthIcon extends FlxSprite else changeIcon('bf'); } - private var iconOffsets:Array = [0, 0]; + private var iconOffsets:Array = [0, 0, 0]; public var imageFile:String; public function changeIcon(char:String) { if(this.char != char) { @@ -45,12 +45,19 @@ class HealthIcon extends FlxSprite var file:Dynamic = Paths.image(name); loadGraphic(file); //Load stupidly first for getting the file size - loadGraphic(file, true, Math.floor(width / 2), Math.floor(height)); //Then load it fr - iconOffsets[0] = (width - 150) / 2; - iconOffsets[1] = (width - 150) / 2; + var amountOfFrames:Int = Math.round(width / height); + //trace('result of amount Of Frames for $name: $amountOfFrames'); + var width2 = width; + loadGraphic(file, true, Math.floor(width / amountOfFrames), Math.floor(height)); // actually load it now. + var framesArray:Array = []; + for (i in 0...amountOfFrames) + { + iconOffsets[i] = (width - 150) / amountOfFrames; + framesArray.insert(Std.int(1 * i), i); // theoretically it'll do this, 1 * 0 = 0, 1 * 1 = 1, etc. + } updateHitbox(); - animation.add(char, [0, 1], 0, false, isPlayer); + animation.add(char, framesArray, 0, false, isPlayer); animation.play(char); this.char = char; diff --git a/source/Main.hx b/source/Main.hx index 8287bc0..760230e 100644 --- a/source/Main.hx +++ b/source/Main.hx @@ -1,5 +1,6 @@ package; +import sys.Watermark; import flixel.graphics.FlxGraphic; import flixel.FlxG; import flixel.FlxGame; @@ -10,8 +11,7 @@ import openfl.display.FPS; import openfl.display.Sprite; import openfl.events.Event; import openfl.display.StageScaleMode; -import codename.modding.ModsFolder; -import codename.backend.system.Logs; +import sys.logger.Logs; //crash handler stuff #if CRASH_HANDLER @@ -25,20 +25,25 @@ import sys.io.File; import sys.io.Process; #end -import codename.backend.assets.AssetsLibraryList; +#if MODS_ALLOWED +import modding.PolymodHandler as Modding; +#end using StringTools; class Main extends Sprite { - var gameWidth:Int = 1280; // Width of the game in pixels (might be less / more in actual pixels depending on your zoom). - var gameHeight:Int = 720; // Height of the game in pixels (might be less / more in actual pixels depending on your zoom). - var initialState:Class = TitleState; // The FlxState the game starts with. - var zoom:Float = -1; // If -1, zoom is automatically calculated to fit the window dimensions. - var framerate:Int = 60; // How many frames per second the game should run at. - var skipSplash:Bool = true; // Whether to skip the flixel splash screen that appears in release mode. - var startFullscreen:Bool = false; // Whether to start the game in fullscreen on desktop targets - var modToLoad:String = null; + var game = { + width: 1280, + height: 720, + initialState: modding.LoadState, + zoom: -1.0, + fps: 60, + skipSplash: true, + startFullscreen: false, + }; + public static var instance:Main = null; + var gameArgs:Array = []; // Used for allowing mods to define custom commandline arguments. public static var fpsVar:FPS; public static var noTerminalColor:Bool = false; @@ -79,23 +84,31 @@ class Main extends Sprite private function setupGame():Void { + gameArgs = Sys.args(); + trace(gameArgs); var stageWidth:Int = Lib.current.stage.stageWidth; var stageHeight:Int = Lib.current.stage.stageHeight; - if (zoom == -1) + if (game.zoom == -1) { - var ratioX:Float = stageWidth / gameWidth; - var ratioY:Float = stageHeight / gameHeight; - zoom = Math.min(ratioX, ratioY); - gameWidth = Math.ceil(stageWidth / zoom); - gameHeight = Math.ceil(stageHeight / zoom); + var ratioX:Float = stageWidth / game.width; + var ratioY:Float = stageHeight / game.height; + game.zoom = Math.min(ratioX, ratioY); + game.width = Math.ceil(stageWidth / game.zoom); + game.height = Math.ceil(stageHeight / game.zoom); } - Paths.assetsTree = new AssetsLibraryList(); + FlxG.save.bind('funkin', 'universe'); + Logs.init(); ClientPrefs.loadDefaultStuff(); - addChild(new FlxGame(gameWidth, gameHeight, initialState, framerate, framerate, skipSplash, startFullscreen)); + addChild(new FlxGame(game.width, game.height, game.initialState, game.fps, game.fps, game.skipSplash, game.startFullscreen)); + #if BETA_WATERMARK + var watermark:sys.Watermark = new sys.Watermark("UNIVERSE ENGINE PRIVATE BUILD\nDO NOT LEAK!!", 0xAAAAAA, 70); + watermark.screenCenter(); + addChild(watermark); + #end #if !mobile fpsVar = new FPS(10, 3, 0xFFFFFF); @@ -115,15 +128,8 @@ class Main extends Sprite #if CRASH_HANDLER Lib.current.loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, onCrash); #end - - #if GLOBAL_SCRIPT - codename.scripting.GlobalScript.init(); - #end - ModsFolder.init(); - #if MOD_SUPPORT - ModsFolder.switchMod(modToLoad = ClientPrefs.data.lastLoadedMod); - #end + instance = this; } // Code was entirely made by sqirra-rng for their fnf engine named "Izzy Engine", big props to them!!! diff --git a/source/MainMenuState.hx b/source/MainMenuState.hx index d5a9f10..5175f9a 100644 --- a/source/MainMenuState.hx +++ b/source/MainMenuState.hx @@ -46,6 +46,8 @@ class MainMenuState extends MusicBeatState var camFollowPos:FlxObject; var debugKeys:Array; + var modShit:FlxText; + override function create() { optionShit = [ @@ -191,7 +193,7 @@ class MainMenuState extends MusicBeatState FlxG.camera.follow(camFollowPos, null, 1); - var versionShit:FlxText = new FlxText(12, FlxG.height - 112, 0, "Current Mod Folder: " + ClientPrefs.data.lastLoadedMod, 12); + var versionShit:FlxText = new FlxText(12, FlxG.height - 112, 0, "Current Mod Folder: " + modding.PolymodHandler.getLoadedMod(), 12); versionShit.scrollFactor.set(); versionShit.setFormat(Paths.font('funkin.ttf'), 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); add(versionShit); @@ -208,6 +210,12 @@ class MainMenuState extends MusicBeatState versionShit.setFormat(Paths.font('funkin.ttf'), 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); add(versionShit); + modShit = new FlxText(0, 0, FlxG.width, "Mods List:\n" + modding.PolymodHandler.formattedModList(), 8); + modShit.scrollFactor.set(); + modShit.setFormat(Paths.font('funkin.ttf'), 16, FlxColor.WHITE, RIGHT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); + add(modShit); + modShit.visible = false; + var textBG:FlxSprite = new FlxSprite(0, FlxG.height - 30).makeGraphic(FlxG.width, 30, 0xFF000000); textBG.scrollFactor.set(); textBG.alpha = 0.6; @@ -268,6 +276,7 @@ class MainMenuState extends MusicBeatState if (!selectedSomethin && !dev.DevSubState.inShortcutMenu) { + if (FlxG.keys.justPressed.F9) modShit.visible = !modShit.visible; if (controls.RESET) { ClientPrefs.saveSettings(); @@ -349,12 +358,12 @@ class MainMenuState extends MusicBeatState MusicBeatState.switchState(new FreeplayState()); #if MODS_ALLOWED case 'mods': - openSubState(new codename.substates.ModSwitchMenu()); + MusicBeatState.switchState(new modding.ModMenuSelectorState()); #end case 'awards': MusicBeatState.switchState(new AchievementsMenuState()); case 'credits': - MusicBeatState.switchState(new credits.CreditsState()); + MusicBeatState.switchState(new credits.PECreditsState()); case 'options': LoadingState.loadAndSwitchState(new options.SelectThing()); } diff --git a/source/ModsMenuState.hx b/source/ModsMenuState.hx index 01b5e83..ec710bf 100644 --- a/source/ModsMenuState.hx +++ b/source/ModsMenuState.hx @@ -515,7 +515,7 @@ class ModsMenuState extends MusicBeatState } else { - MusicBeatState.switchState(new MainMenuState()); + MusicBeatState.switchState(new modding.ModMenuSelectorState()); } } diff --git a/source/MusicBeatState.hx b/source/MusicBeatState.hx index ca35c17..3e84ec2 100644 --- a/source/MusicBeatState.hx +++ b/source/MusicBeatState.hx @@ -1,5 +1,7 @@ package; +import modding.PolymodHandler; +import modding.LoadState; import Conductor.BPMChangeEvent; import flixel.FlxG; import flixel.addons.ui.FlxUIState; @@ -15,9 +17,6 @@ import flixel.FlxState; import flixel.FlxCamera; import flixel.FlxBasic; import flixel.sound.FlxSound; -// scripting -import codename.scripting.ScriptPack; -import codename.scripting.DummyScript; #if sys import sys.FileSystem; import sys.io.File; @@ -42,9 +41,6 @@ class MusicBeatState extends modchart.modcharting.ModchartMusicBeatState inline function get_controls():Controls return PlayerSettings.player1.controls; - // scripting - public var stateScripts:ScriptPack; - public var scriptsAllowed:Bool = true; public static var lastScriptName:String = null; @@ -52,22 +48,9 @@ class MusicBeatState extends modchart.modcharting.ModchartMusicBeatState public var scriptName:String = null; - public function new(scriptsAllowed:Bool = true, ?scriptName:String) - { - super(); - this.scriptsAllowed = #if SOFTCODED_STATES scriptsAllowed #else false #end; - - if (lastStateName != (lastStateName = Type.getClassName(Type.getClass(this)))) - { - lastScriptName = null; - } - this.scriptName = scriptName != null ? scriptName : lastScriptName; - lastScriptName = this.scriptName; - } - - function loadScript() + function loadScript() // Stubbed untill later, this will be re-used for loading polymod scripts. { - var className = Type.getClassName(Type.getClass(this)); +/* var className = Type.getClassName(Type.getClass(this)); if (stateScripts == null) (stateScripts = new ScriptPack(className)).setParent(this); if (scriptsAllowed) @@ -88,7 +71,7 @@ class MusicBeatState extends modchart.modcharting.ModchartMusicBeatState } else stateScripts.reload(); - } + } */ } override function create() @@ -108,10 +91,12 @@ class MusicBeatState extends modchart.modcharting.ModchartMusicBeatState FlxTransitionableState.skipNextTransOut = false; } - public function call(name:String, ?args:Array, ?defaultVal:Dynamic):Dynamic { - // calls the function on the assigned script + public function call(name:String, ?args:Array, ?defaultVal:Dynamic):Dynamic { // Stubbed untill polymod loader finished. + /* // calls the function on the assigned script if(stateScripts != null) return stateScripts.call(name, args); + return defaultVal; */ + return defaultVal; } @@ -140,14 +125,25 @@ class MusicBeatState extends modchart.modcharting.ModchartMusicBeatState if (FlxG.save.data != null) FlxG.save.data.fullscreen = FlxG.fullscreen; - if (FlxG.keys.justPressed.F5) - loadScript(); - call("update", [elapsed]); + if (FlxG.keys.justPressed.F5) + { + if (!Std.isOfType(FlxG.state, LoadState)) + { + PolymodHandler.isInit = false; // make it recheck the mods folder + switchState(new LoadState(true, FlxG.state)); // Reload that shit + } + } + super.update(elapsed); } + public override function startOutro(onOutroComplete:() -> Void) { + CoolUtil.clearWatermarks(); // Don't want them piling up. + super.startOutro(onOutroComplete); + } + private function updateSection():Void { if (stepsToDo < 1) diff --git a/source/MusicBeatSubstate.hx b/source/MusicBeatSubstate.hx index 777af68..bd31d6b 100644 --- a/source/MusicBeatSubstate.hx +++ b/source/MusicBeatSubstate.hx @@ -1,6 +1,5 @@ package; -import codename.scripting.ScriptPack; import Conductor.BPMChangeEvent; import flixel.FlxG; import flixel.FlxSubState; @@ -10,11 +9,6 @@ import flixel.FlxSprite; class MusicBeatSubstate extends FlxSubState { - /** - * Current injected script attached to the state. To add one, create a file at path "data/states/stateName" (ex: "data/states/PauseMenuSubstate.hx") - */ - public var stateScripts:ScriptPack; - public var scriptsAllowed:Bool = true; public var scriptName:String = null; diff --git a/source/Paths.hx b/source/Paths.hx index c73ec3b..32cd891 100644 --- a/source/Paths.hx +++ b/source/Paths.hx @@ -23,10 +23,6 @@ import haxe.Json; import flash.media.Sound; import flixel.graphics.frames.FlxFramesCollection; import flixel.animation.FlxAnimationController; -import codename.backend.assets.AssetsLibraryList; - -import codename.scripting.HScript; -import codename.backend.Script; using StringTools; @@ -40,8 +36,6 @@ class Paths public static var noteSkinFramesMap:Map = new Map(); public static var noteSkinAnimsMap:Map = new Map(); - public static var assetsTree:AssetsLibraryList; - #if MODS_ALLOWED public static var ignoreModFolders:Array = [ 'characters', @@ -63,9 +57,9 @@ class Paths ]; #end - static public function getFolderDirectories(key:String, addPath:Bool = false, source:codename.backend.assets.AssetsLibraryList.AssetSource = BOTH):Array + static public function getFolderDirectories(key:String, addPath:Bool = false):Array // Stubbed for later polymod use { - if (!key.endsWith("/")) + /* if (!key.endsWith("/")) key += "/"; var content = assetsTree.getFolders('assets/$key', source); if (addPath) @@ -73,12 +67,13 @@ class Paths for (k => e in content) content[k] = '$key$e'; } - return content; + return content; */ + return []; } - static public function getFolderContent(key:String, addPath:Bool = false, source:codename.backend.assets.AssetsLibraryList.AssetSource = BOTH):Array + static public function getFolderContent(key:String, addPath:Bool = false):Array // Stubbed for later polymod use { - // designed to work both on windows and web + /* // designed to work both on windows and web if (!key.endsWith("/")) key += "/"; var content = assetsTree.getFiles('assets/$key', source); @@ -87,7 +82,8 @@ class Paths for (k => e in content) content[k] = '$key$e'; } - return content; + return content; */ + return []; } public static var defaultSkin = 'NOTE_assets' + Note.getNoteSkinPostfix(); @@ -494,21 +490,6 @@ class Paths return ""; } - inline static public function hscript(key:String, ?library:String, isAssetsPath:Bool = false) { - var scriptPath = isAssetsPath ? key : cne_getPath(key, library); - if (!OpenFlAssets.exists(scriptPath)) { - var p:String; - for(ex in Script.scriptExtensions) { - p = '$scriptPath.$ex'; - if (OpenFlAssets.exists(p)) { - scriptPath = p; - break; - } - } - } - return scriptPath; - } - public static function returnSound(path:String, key:String, ?library:String) { #if MODS_ALLOWED diff --git a/source/PlayState.hx b/source/PlayState.hx index 7b550e5..817f42c 100644 --- a/source/PlayState.hx +++ b/source/PlayState.hx @@ -3525,6 +3525,8 @@ class PlayState extends MusicBeatState { if (healthBar.percent < 20) iconP1.animation.curAnim.curFrame = 1; + else if (healthBar.percent > 80 && iconP1.animation.curAnim.numFrames == 3) + iconP1.animation.curAnim.curFrame = 2; else iconP1.animation.curAnim.curFrame = 0; } @@ -3552,6 +3554,8 @@ class PlayState extends MusicBeatState { if (healthBar.percent > 80) iconP2.animation.curAnim.curFrame = 1; + else if (healthBar.percent < 20 && iconP2.animation.curAnim.numFrames == 3) + iconP2.animation.curAnim.curFrame = 2; else iconP2.animation.curAnim.curFrame = 0; } diff --git a/source/TitleState.hx b/source/TitleState.hx index f221fb9..aa7edbc 100644 --- a/source/TitleState.hx +++ b/source/TitleState.hx @@ -1,5 +1,7 @@ package; +import modding.LoadState; +import modding.PolymodHandler; #if desktop import Discord.DiscordClient; import sys.thread.Thread; @@ -61,10 +63,6 @@ typedef TitleData = class TitleState extends MusicBeatState { - public static var muteKeys:Array = [FlxKey.ZERO]; - public static var volumeDownKeys:Array = [FlxKey.NUMPADMINUS, FlxKey.MINUS]; - public static var volumeUpKeys:Array = [FlxKey.NUMPADPLUS, FlxKey.PLUS]; - public static var initialized:Bool = false; var blackScreen:FlxSprite; @@ -127,12 +125,6 @@ class TitleState extends MusicBeatState Paths.clearStoredMemory(); Paths.clearUnusedMemory(); - #if LUA_ALLOWED - Paths.pushGlobalMods(); - #end - // Just to load a mod on start up if ya got one. For mods that change the menu music and bg - WeekData.loadTheFirstEnabledMod(); - // trace(path, FileSystem.exists(path)); /*#if (polymod && !html5) @@ -150,14 +142,6 @@ class TitleState extends MusicBeatState } #end */ - FlxG.game.focusLostFramerate = 60; - FlxG.sound.muteKeys = muteKeys; - FlxG.sound.volumeDownKeys = volumeDownKeys; - FlxG.sound.volumeUpKeys = volumeUpKeys; - FlxG.keys.preventDefaultKeys = [TAB]; - - PlayerSettings.init(); - curWacky = FlxG.random.getObject(getIntroTextShit()); unWackyourwacky = FlxG.random.getObject(getUETextShit()); @@ -166,12 +150,6 @@ class TitleState extends MusicBeatState swagShader = new ColorSwap(); super.create(); - FlxG.save.bind('funkin', 'universe'); - - ClientPrefs.loadPrefs(); - - Highscore.load(); - // IGNORE THIS!!! titleJSON = Json.parse(Paths.getTextFromFile('images/gfDanceTitle.json')); if (ClientPrefs.data.mmm == "DNB Old") diff --git a/source/codename/backend/Script.hx b/source/codename_ref/backend/Script.hx similarity index 100% rename from source/codename/backend/Script.hx rename to source/codename_ref/backend/Script.hx diff --git a/source/codename/backend/assets/AssetsLibraryList.hx b/source/codename_ref/backend/assets/AssetsLibraryList.hx similarity index 100% rename from source/codename/backend/assets/AssetsLibraryList.hx rename to source/codename_ref/backend/assets/AssetsLibraryList.hx diff --git a/source/codename/backend/assets/IModsAssetLibrary.hx b/source/codename_ref/backend/assets/IModsAssetLibrary.hx similarity index 100% rename from source/codename/backend/assets/IModsAssetLibrary.hx rename to source/codename_ref/backend/assets/IModsAssetLibrary.hx diff --git a/source/codename/backend/assets/ModsFolderLibrary.hx b/source/codename_ref/backend/assets/ModsFolderLibrary.hx similarity index 100% rename from source/codename/backend/assets/ModsFolderLibrary.hx rename to source/codename_ref/backend/assets/ModsFolderLibrary.hx diff --git a/source/codename/backend/assets/ScriptedAssetLibrary.hx b/source/codename_ref/backend/assets/ScriptedAssetLibrary.hx similarity index 100% rename from source/codename/backend/assets/ScriptedAssetLibrary.hx rename to source/codename_ref/backend/assets/ScriptedAssetLibrary.hx diff --git a/source/codename/backend/import.hx b/source/codename_ref/backend/import.hx similarity index 100% rename from source/codename/backend/import.hx rename to source/codename_ref/backend/import.hx diff --git a/source/codename/backend/options/ArrayTools.hx b/source/codename_ref/backend/options/ArrayTools.hx similarity index 100% rename from source/codename/backend/options/ArrayTools.hx rename to source/codename_ref/backend/options/ArrayTools.hx diff --git a/source/codename/backend/options/OptionsScreen.hx b/source/codename_ref/backend/options/OptionsScreen.hx similarity index 100% rename from source/codename/backend/options/OptionsScreen.hx rename to source/codename_ref/backend/options/OptionsScreen.hx diff --git a/source/codename/backend/options/OptionsTree.hx b/source/codename_ref/backend/options/OptionsTree.hx similarity index 100% rename from source/codename/backend/options/OptionsTree.hx rename to source/codename_ref/backend/options/OptionsTree.hx diff --git a/source/codename/backend/options/TreeMenu.hx b/source/codename_ref/backend/options/TreeMenu.hx similarity index 100% rename from source/codename/backend/options/TreeMenu.hx rename to source/codename_ref/backend/options/TreeMenu.hx diff --git a/source/codename/backend/options/import.hx b/source/codename_ref/backend/options/import.hx similarity index 100% rename from source/codename/backend/options/import.hx rename to source/codename_ref/backend/options/import.hx diff --git a/source/codename/backend/options/type/OptionType.hx b/source/codename_ref/backend/options/type/OptionType.hx similarity index 100% rename from source/codename/backend/options/type/OptionType.hx rename to source/codename_ref/backend/options/type/OptionType.hx diff --git a/source/codename/backend/options/type/PortraitOption.hx b/source/codename_ref/backend/options/type/PortraitOption.hx similarity index 100% rename from source/codename/backend/options/type/PortraitOption.hx rename to source/codename_ref/backend/options/type/PortraitOption.hx diff --git a/source/codename/backend/options/type/TextOption.hx b/source/codename_ref/backend/options/type/TextOption.hx similarity index 100% rename from source/codename/backend/options/type/TextOption.hx rename to source/codename_ref/backend/options/type/TextOption.hx diff --git a/source/codename/backend/shaders/CustomShader.hx b/source/codename_ref/backend/shaders/CustomShader.hx similarity index 100% rename from source/codename/backend/shaders/CustomShader.hx rename to source/codename_ref/backend/shaders/CustomShader.hx diff --git a/source/codename/backend/shaders/FunkinShader.hx b/source/codename_ref/backend/shaders/FunkinShader.hx similarity index 100% rename from source/codename/backend/shaders/FunkinShader.hx rename to source/codename_ref/backend/shaders/FunkinShader.hx diff --git a/source/codename/backend/system/import.hx b/source/codename_ref/backend/system/import.hx similarity index 100% rename from source/codename/backend/system/import.hx rename to source/codename_ref/backend/system/import.hx diff --git a/source/codename/backend/utils/CoolUtil.hx b/source/codename_ref/backend/utils/CoolUtil.hx similarity index 100% rename from source/codename/backend/utils/CoolUtil.hx rename to source/codename_ref/backend/utils/CoolUtil.hx diff --git a/source/codename/backend/utils/FileAttributeWrapper.hx b/source/codename_ref/backend/utils/FileAttributeWrapper.hx similarity index 100% rename from source/codename/backend/utils/FileAttributeWrapper.hx rename to source/codename_ref/backend/utils/FileAttributeWrapper.hx diff --git a/source/codename/backend/utils/LogUtils.hx b/source/codename_ref/backend/utils/LogUtils.hx similarity index 100% rename from source/codename/backend/utils/LogUtils.hx rename to source/codename_ref/backend/utils/LogUtils.hx diff --git a/source/codename/backend/utils/NativeAPI.hx b/source/codename_ref/backend/utils/NativeAPI.hx similarity index 100% rename from source/codename/backend/utils/NativeAPI.hx rename to source/codename_ref/backend/utils/NativeAPI.hx diff --git a/source/codename/backend/utils/ScriptUtils.hx b/source/codename_ref/backend/utils/ScriptUtils.hx similarity index 100% rename from source/codename/backend/utils/ScriptUtils.hx rename to source/codename_ref/backend/utils/ScriptUtils.hx diff --git a/source/codename/backend/utils/native/Windows.hx b/source/codename_ref/backend/utils/native/Windows.hx similarity index 100% rename from source/codename/backend/utils/native/Windows.hx rename to source/codename_ref/backend/utils/native/Windows.hx diff --git a/source/codename/import.hx b/source/codename_ref/import.hx similarity index 71% rename from source/codename/import.hx rename to source/codename_ref/import.hx index 4c2c109..39f6435 100644 --- a/source/codename/import.hx +++ b/source/codename_ref/import.hx @@ -3,5 +3,4 @@ package ue; #if !macro import codename.backend.*; import codename.backend.assets.*; -import codename.modding.ModsFolder; #end \ No newline at end of file diff --git a/source/codename/modding/ModsFolder.hx b/source/codename_ref/modding/ModsFolder.hx similarity index 100% rename from source/codename/modding/ModsFolder.hx rename to source/codename_ref/modding/ModsFolder.hx diff --git a/source/codename/scripting/DummyScript.hx b/source/codename_ref/scripting/DummyScript.hx similarity index 100% rename from source/codename/scripting/DummyScript.hx rename to source/codename_ref/scripting/DummyScript.hx diff --git a/source/codename/scripting/GlobalScript.hx b/source/codename_ref/scripting/GlobalScript.hx similarity index 100% rename from source/codename/scripting/GlobalScript.hx rename to source/codename_ref/scripting/GlobalScript.hx diff --git a/source/codename/scripting/HScript.hx b/source/codename_ref/scripting/HScript.hx similarity index 100% rename from source/codename/scripting/HScript.hx rename to source/codename_ref/scripting/HScript.hx diff --git a/source/codename/scripting/ModState.hx b/source/codename_ref/scripting/ModState.hx similarity index 100% rename from source/codename/scripting/ModState.hx rename to source/codename_ref/scripting/ModState.hx diff --git a/source/codename/scripting/ModSubState.hx b/source/codename_ref/scripting/ModSubState.hx similarity index 100% rename from source/codename/scripting/ModSubState.hx rename to source/codename_ref/scripting/ModSubState.hx diff --git a/source/codename/scripting/ScriptPack.hx b/source/codename_ref/scripting/ScriptPack.hx similarity index 100% rename from source/codename/scripting/ScriptPack.hx rename to source/codename_ref/scripting/ScriptPack.hx diff --git a/source/codename/scripting/import.hx b/source/codename_ref/scripting/import.hx similarity index 100% rename from source/codename/scripting/import.hx rename to source/codename_ref/scripting/import.hx diff --git a/source/codename/states/MainState.hx b/source/codename_ref/states/MainState.hx similarity index 100% rename from source/codename/states/MainState.hx rename to source/codename_ref/states/MainState.hx diff --git a/source/codename/substates/ModSwitchMenu.hx b/source/codename_ref/substates/ModSwitchMenu.hx similarity index 100% rename from source/codename/substates/ModSwitchMenu.hx rename to source/codename_ref/substates/ModSwitchMenu.hx diff --git a/source/credits/.DS_Store b/source/credits/.DS_Store new file mode 100644 index 0000000..dda4cb8 Binary files /dev/null and b/source/credits/.DS_Store differ diff --git a/source/credits/BaseCreditsState.hx b/source/credits/BaseCreditsState.hx new file mode 100644 index 0000000..7b37999 --- /dev/null +++ b/source/credits/BaseCreditsState.hx @@ -0,0 +1,6 @@ +package credits.old; + +class BaseCreditsState extends MusicBeatState +{ + // Stubbed for now. +} \ No newline at end of file diff --git a/source/credits/PECreditsState.hx b/source/credits/PECreditsState.hx new file mode 100644 index 0000000..1b0c276 --- /dev/null +++ b/source/credits/PECreditsState.hx @@ -0,0 +1,609 @@ +package credits; + +#if desktop +import Discord.DiscordClient; +#end +import flash.text.TextField; +import flixel.FlxG; +import flixel.FlxSprite; +import flixel.addons.display.FlxGridOverlay; +import flixel.group.FlxGroup.FlxTypedGroup; +import flixel.math.FlxMath; +import flixel.text.FlxText; +import flixel.util.FlxColor; +import flixel.tweens.FlxTween; +import flixel.tweens.FlxEase; +#if MODS_ALLOWED +import sys.FileSystem; +import sys.io.File; +#end +import lime.utils.Assets; +import flixel.addons.display.FlxBackdrop; +import flixel.addons.display.FlxGridOverlay; + +using StringTools; +/** +* The original Credits State from PE, used in snapshot y25v01a +*/ +class PECreditsState extends MusicBeatState +{ + var curSelected:Int = -1; + + private var grpOptions:FlxTypedGroup; + private var iconArray:Array = []; + private var creditsStuff:Array> = []; + + var bg:FlxSprite; + var descText:FlxText; + var intendedColor:Int; + var colorTween:FlxTween; + var descBox:AttachedSprite; + + var offsetThing:Float = -75; + + var pisspoop:Array>; + + override function create() + { + #if desktop + // Updating Discord Rich Presence + DiscordClient.changePresence("In the Credits Menu", null); + #end + + persistentUpdate = true; + if (ClientPrefs.data.darkmode) + { + bg = new FlxSprite(0, 0).loadGraphic(Paths.image("aboutMenu", "preload")); + add(bg); + bg.screenCenter(); + } + else + { + bg = new FlxSprite().loadGraphic(Paths.image('menuDesat')); + add(bg); + bg.screenCenter(); + } + + var grid:FlxBackdrop = new FlxBackdrop(FlxGridOverlay.createGrid(80, 80, 160, 160, true, 0x33FFFFFF, 0x0)); + grid.velocity.set(20, 20); + grid.alpha = 0; + FlxTween.tween(grid, {alpha: 1}, 0.5, {ease: FlxEase.quadOut}); + add(grid); + + grpOptions = new FlxTypedGroup(); + add(grpOptions); + + #if MODS_ALLOWED + var path:String = 'modsList.txt'; + if (FileSystem.exists(path)) + { + var leMods:Array = CoolUtil.coolTextFile(path); + for (i in 0...leMods.length) + { + if (leMods.length > 1 && leMods[0].length > 0) + { + var modSplit:Array = leMods[i].split('|'); + if (!Paths.ignoreModFolders.contains(modSplit[0].toLowerCase()) && !modsAdded.contains(modSplit[0])) + { + if (modSplit[1] == '1') + pushModCreditsToList(modSplit[0]); + else + modsAdded.push(modSplit[0]); + } + } + } + } + + var arrayOfFolders:Array = Paths.getModDirectories(); + arrayOfFolders.push(''); + for (folder in arrayOfFolders) + { + pushModCreditsToList(folder); + } + #end + + if (!ClientPrefs.data.hideOriCredits) + { + pisspoop = [ + // Name - Icon name - Description - Link - BG Color + ['Universe Engine DEVs'], + [ + 'Video Bot', + 'videobot', + 'First DEV, In charge of the HX files', + 'https://linktr.ee/videobot', + '14FFFF' + ], + [ + 'CharGoldenYT', + 'char', + "I guess I'll join the team - Me\nThird DEV In charge of HX Files, and the POLYMOD MOD LOADER!", + 'https://bsky.app/profile/vschar-official.com', + 'FFA600' + ], + [''], + ['Former UE DEVs'], + [ + 'Daveberry', + 'dave', + 'Former DEV, (No Longer) In charge of the LUA, HX files and other', + 'https://daveberry.netlify.app/', + '008BFF' + ], + [ + 'BaranMuzu', + 'baranmuzu', + 'Former DEV, (No Longer) In charge of the LUA files and other', + 'https://linktr.ee/baranmuzu', + 'BE9877' + ], + [''], + ['UE Borrowed Code'], + ['Edwhak', 'Edwhak', 'Modchart Tool', 'https://www.youtube.com/@EDWHAK', '00FF00'], + [ + 'Rozebud', + 'rozebud', + "Chart Editor's Lil' Buddies", + 'https://x.com/helpme_thebigt', + '6D2F83' + ], + [ + ' SilverSpringing', + 'invis', + 'Combo Counter', + 'https://gamebanana.com/members/1823951', + '00FFFF' + ], + [ + ' Unholywanderer', + 'invis', + 'Smooth HP', + 'https://gamebanana.com/members/1908754', + '00FFFF' + ], + [ + ' Kiruwu', + 'invis', + 'Weekend 1 Port', + 'https://gamebanana.com/mods/512609', + 'B3715F' + ], + [ + ' Spelo', + 'invis', + 'Play Both Sides', + 'https://www.youtube.com/watch?v=xmUQUi8rd9M', + 'FFFFFF' + ], + [''], + ['UE Special Thanks'], + [ + 'Blitz', + 'Blitz', + 'Universe Logo And Playtester', + 'https://www.youtube.com/@fireballfurby', + '00FFFF' + ], + [ + 'An Ammar', + 'Ammar', + 'Hype Mode, Detached Health Bar, Playtester', + 'https://gamebanana.com/mods/381804', + '00FF00' + ], + [ + 'Dinus Game', + 'Dinus Game', + 'freakyMenu Universe Engine music. Also made the design of the Fancy Main Menu', + 'https://gamebanana.com/members/2053946', + '27FF27' + ], + [ + 'idiotxd', + 'idiotxd', + 'His own freakyMenu music and Universe Banner', + 'https://x.com/IdiottLool', + '5656FF' + ], + [ + 'JordanSantiago', + 'jor', + 'Most of the code of UE comes from JS', + 'https://gamebanana.com/tools/13575', + '32CD32' + ], + [''], + ["UE PR's"], + [ + 'MoxieCoder', + 'moxie', + "Lua Jit Fork superpowers04 PR", + 'https://x.com/moxie_specalist', + '00FFFF' + ], + [ + ' soushimiya', + 'invis', + "Crediting Rozebud", + 'https://github.com/soushimiya', + 'FFFFFF' + ], + [''], + ['Psych Engine Team'], + [ + 'Shadow Mario', + 'shadowmario', + 'Main Programmer of Psych Engine', + 'https://twitter.com/Shadow_Mario_', + '444444' + ], + [ + 'RiverOaken', + 'river', + 'Main Artist/Animator of Psych Engine', + 'https://twitter.com/RiverOaken', + 'B42F71' + ], + [ + 'shubs', + 'shubs', + 'Additional Programmer of Psych Engine', + 'https://twitter.com/yoshubs', + '5E99DF' + ], + [''], + ['Former Engine Members'], + [ + 'bb-panzu', + 'bb', + 'Ex-Programmer of Psych Engine', + 'https://twitter.com/bbsub3', + '3E813A' + ], + [""], + ['Engine Contributors'], + [ + 'iFlicky', + 'flicky', + 'Composer of Psync and Tea Time\nMade the Dialogue Sounds', + 'https://twitter.com/flicky_i', + '9E29CF' + ], + [ + 'SqirraRNG', + 'sqirra', + 'Crash Handler and Base code for\nChart Editor\'s Waveform', + 'https://twitter.com/gedehari', + 'E1843A' + ], + [ + 'EliteMasterEric', + 'mastereric', + 'Runtime Shaders support', + 'https://twitter.com/EliteMasterEric', + 'FFBD40' + ], + [ + 'PolybiusProxy', + 'proxy', + '.MP4 Video Loader Library (hxCodec)', + 'https://twitter.com/polybiusproxy', + 'DCD294' + ], + [ + 'KadeDev', + 'kade', + 'Fixed some cool stuff on Chart Editor\nand other PRs', + 'https://twitter.com/kade0912', + '64A250' + ], + [ + 'Keoiki', + 'keoiki', + 'Note Splash Animations', + 'https://twitter.com/Keoiki_', + 'D2D2D2' + ], + [ + "superpowers04", + "superpowers04", + "LUA JIT Fork", + "https://x.com/superpowers04", + "B957ED" + ], + [ + 'Smokey', + 'smokey', + 'Sprite Atlas Support', + 'https://twitter.com/Smokey_5_', + '483D92' + ], + [""], + ["Funkin' Crew"], + [ + "ninjamuffin99", + "ninjamuffin99", + "Programmer of Friday Night Funkin'", + "https://x.com/ninja_muffin99", + "CF2D2D" + ], + [ + "PhantomArcade", + "phantomarcade", + "Animator of Friday Night Funkin'", + "https://x.com/PhantomArcade3K", + "FADC45" + ], + [ + "evilsk8r", + "evilsk8r", + "Artist of Friday Night Funkin'", + "https://x.com/evilsk8r", + "5ABD4B" + ], + [ + "kawaisprite", + "kawaisprite", + "Composer of Friday Night Funkin'", + "https://x.com/kawaisprite", + "378FC7" + ], + ]; + } + else + { // prevents crash lol + pisspoop = [ + [ + '', + 'invis', + 'this is just here to prevent crash when theres no credits lol', + '', + '000000' + ] + ]; + } + + for (i in pisspoop) + { + creditsStuff.push(i); + } + + for (i in 0...creditsStuff.length) + { + var isSelectable:Bool = !unselectableCheck(i); + var optionText:Alphabet = new Alphabet(FlxG.width / 2, 300, creditsStuff[i][0], !isSelectable); + optionText.isMenuItem = true; + optionText.targetY = i; + optionText.changeX = false; + optionText.snapToPosition(); + grpOptions.add(optionText); + + if (isSelectable) + { + if (creditsStuff[i][5] != null) + { + Paths.currentModDirectory = creditsStuff[i][5]; + } + + var icon:AttachedSprite = new AttachedSprite('credits/' + creditsStuff[i][1]); + icon.xAdd = optionText.width + 10; + icon.sprTracker = optionText; + + // using a FlxGroup is too much fuss! + iconArray.push(icon); + add(icon); + Paths.currentModDirectory = ''; + + if (curSelected == -1) + curSelected = i; + } + else + optionText.alignment = CENTERED; + } + + descBox = new AttachedSprite(); + descBox.makeGraphic(1, 1, FlxColor.BLACK); + descBox.xAdd = -10; + descBox.yAdd = -10; + descBox.alphaMult = 0.6; + descBox.alpha = 0.6; + add(descBox); + + descText = new FlxText(50, FlxG.height + offsetThing - 25, 1180, "", 32); + descText.setFormat(Paths.font("funkin.ttf"), 32, FlxColor.WHITE, CENTER /*, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK*/); + descText.scrollFactor.set(); + // descText.borderSize = 2.4; + descBox.sprTracker = descText; + add(descText); + + bg.color = getCurrentBGColor(); + intendedColor = bg.color; + changeSelection(); + super.create(); + } + + var quitting:Bool = false; + var holdTime:Float = 0; + + override function update(elapsed:Float) + { + if (FlxG.sound.music.volume < 0.7) + { + FlxG.sound.music.volume += 0.5 * FlxG.elapsed; + } + + if (!quitting) + { + if (creditsStuff.length > 1) + { + var shiftMult:Int = 1; + if (FlxG.keys.pressed.SHIFT) + shiftMult = 3; + + var upP = controls.UI_UP_P; + var downP = controls.UI_DOWN_P; + + if (upP) + { + changeSelection(-shiftMult); + holdTime = 0; + } + if (downP) + { + changeSelection(shiftMult); + holdTime = 0; + } + + if (controls.UI_DOWN || controls.UI_UP) + { + var checkLastHold:Int = Math.floor((holdTime - 0.5) * 10); + holdTime += elapsed; + var checkNewHold:Int = Math.floor((holdTime - 0.5) * 10); + + if (holdTime > 0.5 && checkNewHold - checkLastHold > 0) + { + changeSelection((checkNewHold - checkLastHold) * (controls.UI_UP ? -shiftMult : shiftMult)); + } + } + } + + if (controls.ACCEPT && (creditsStuff[curSelected][3] == null || creditsStuff[curSelected][3].length > 4)) + { + CoolUtil.browserLoad(creditsStuff[curSelected][3]); + } + if (controls.BACK) + { + if (colorTween != null) + { + colorTween.cancel(); + } + FlxG.sound.play(Paths.sound('cancelMenu')); + MusicBeatState.switchState(new MainMenuState()); + quitting = true; + } + } + + for (item in grpOptions.members) + { + if (!item.bold) + { + var lerpVal:Float = CoolUtil.boundTo(elapsed * 12, 0, 1); + if (item.targetY == 0) + { + var lastX:Float = item.x; + item.screenCenter(X); + item.x = FlxMath.lerp(lastX, item.x - 70, lerpVal); + } + else + { + item.x = FlxMath.lerp(item.x, 200 + -40 * Math.abs(item.targetY), lerpVal); + } + } + } + super.update(elapsed); + } + + var moveTween:FlxTween = null; + + function changeSelection(change:Int = 0) + { + FlxG.sound.play(Paths.sound('scrollMenu'), 0.4); + do + { + curSelected += change; + if (curSelected < 0) + curSelected = creditsStuff.length - 1; + if (curSelected >= creditsStuff.length) + curSelected = 0; + } + while (unselectableCheck(curSelected)); + + var newColor:Int = getCurrentBGColor(); + if (newColor != intendedColor) + { + if (colorTween != null) + { + colorTween.cancel(); + } + intendedColor = newColor; + colorTween = FlxTween.color(bg, 1, bg.color, intendedColor, { + onComplete: function(twn:FlxTween) + { + colorTween = null; + } + }); + } + + var bullShit:Int = 0; + + for (item in grpOptions.members) + { + item.targetY = bullShit - curSelected; + bullShit++; + + if (!unselectableCheck(bullShit - 1)) + { + item.alpha = 0.6; + if (item.targetY == 0) + { + item.alpha = 1; + } + } + } + + descText.text = creditsStuff[curSelected][2]; + descText.y = FlxG.height - descText.height + offsetThing - 60; + + if (moveTween != null) + moveTween.cancel(); + moveTween = FlxTween.tween(descText, {y: descText.y + 75}, 0.25, {ease: FlxEase.sineOut}); + + descBox.setGraphicSize(Std.int(descText.width + 20), Std.int(descText.height + 25)); + descBox.updateHitbox(); + } + + #if MODS_ALLOWED + private var modsAdded:Array = []; + + function pushModCreditsToList(folder:String) + { + if (modsAdded.contains(folder)) + return; + + var creditsFile:String = null; + if (folder != null && folder.trim().length > 0) + creditsFile = Paths.mods(folder + '/data/credits.txt'); + else + creditsFile = Paths.mods('data/credits.txt'); + + if (FileSystem.exists(creditsFile)) + { + var firstarray:Array = File.getContent(creditsFile).split('\n'); + for (i in firstarray) + { + var arr:Array = i.replace('\\n', '\n').split("::"); + if (arr.length >= 5) + arr.push(folder); + creditsStuff.push(arr); + } + creditsStuff.push(['']); + } + modsAdded.push(folder); + } + #end + + function getCurrentBGColor() + { + var bgColor:String = creditsStuff[curSelected][4]; + if (!bgColor.startsWith('0x')) + { + bgColor = '0xFF' + bgColor; + } + return Std.parseInt(bgColor); + } + + private function unselectableCheck(num:Int):Bool + { + return creditsStuff[num].length <= 1; + } +} \ No newline at end of file diff --git a/source/credits/CreditsState.hx b/source/credits/old/CreditsState.hx similarity index 100% rename from source/credits/CreditsState.hx rename to source/credits/old/CreditsState.hx diff --git a/source/credits/FNFCredits.hx b/source/credits/old/FNFCredits.hx similarity index 100% rename from source/credits/FNFCredits.hx rename to source/credits/old/FNFCredits.hx diff --git a/source/credits/PECredits.hx b/source/credits/old/PECredits.hx similarity index 100% rename from source/credits/PECredits.hx rename to source/credits/old/PECredits.hx diff --git a/source/credits/UECredits.hx b/source/credits/old/UECredits.hx similarity index 100% rename from source/credits/UECredits.hx rename to source/credits/old/UECredits.hx diff --git a/source/credits/import.hx b/source/credits/old/import.hx similarity index 100% rename from source/credits/import.hx rename to source/credits/old/import.hx diff --git a/source/editors/CharacterEditorState.hx b/source/editors/CharacterEditorState.hx index b94bf95..516d085 100644 --- a/source/editors/CharacterEditorState.hx +++ b/source/editors/CharacterEditorState.hx @@ -1564,9 +1564,9 @@ class CharacterEditorState extends MusicBeatState return; } } - FlxG.sound.muteKeys = TitleState.muteKeys; - FlxG.sound.volumeDownKeys = TitleState.volumeDownKeys; - FlxG.sound.volumeUpKeys = TitleState.volumeUpKeys; + FlxG.sound.muteKeys = modding.LoadState.muteKeys; + FlxG.sound.volumeDownKeys = modding.LoadState.volumeDownKeys; + FlxG.sound.volumeUpKeys = modding.LoadState.volumeUpKeys; if (!charDropDown.dropPanel.visible) { diff --git a/source/editors/ChartingState.hx b/source/editors/ChartingState.hx index e025b53..819bab2 100644 --- a/source/editors/ChartingState.hx +++ b/source/editors/ChartingState.hx @@ -2037,9 +2037,9 @@ class ChartingState extends MusicBeatState if (!blockInput) { - FlxG.sound.muteKeys = TitleState.muteKeys; - FlxG.sound.volumeDownKeys = TitleState.volumeDownKeys; - FlxG.sound.volumeUpKeys = TitleState.volumeUpKeys; + FlxG.sound.muteKeys = modding.LoadState.muteKeys; + FlxG.sound.volumeDownKeys = modding.LoadState.volumeDownKeys; + FlxG.sound.volumeUpKeys = modding.LoadState.volumeUpKeys; for (dropDownMenu in blockPressWhileScrolling) { if (dropDownMenu.dropPanel.visible) diff --git a/source/editors/DialogueCharacterEditorState.hx b/source/editors/DialogueCharacterEditorState.hx index 0f1c74c..1aff4ac 100644 --- a/source/editors/DialogueCharacterEditorState.hx +++ b/source/editors/DialogueCharacterEditorState.hx @@ -585,9 +585,9 @@ class DialogueCharacterEditorState extends MusicBeatState if (!blockInput && !animationDropDown.dropPanel.visible) { - FlxG.sound.muteKeys = TitleState.muteKeys; - FlxG.sound.volumeDownKeys = TitleState.volumeDownKeys; - FlxG.sound.volumeUpKeys = TitleState.volumeUpKeys; + FlxG.sound.muteKeys = modding.LoadState.muteKeys; + FlxG.sound.volumeDownKeys = modding.LoadState.volumeDownKeys; + FlxG.sound.volumeUpKeys = modding.LoadState.volumeUpKeys; if (FlxG.keys.justPressed.SPACE && UI_mainbox.selected_tab_id == 'Character') { character.playAnim(character.jsonFile.animations[curAnim].anim); diff --git a/source/editors/DialogueEditorState.hx b/source/editors/DialogueEditorState.hx index 9592209..7dd5cf7 100644 --- a/source/editors/DialogueEditorState.hx +++ b/source/editors/DialogueEditorState.hx @@ -418,9 +418,9 @@ class DialogueEditorState extends MusicBeatState if (!blockInput) { - FlxG.sound.muteKeys = TitleState.muteKeys; - FlxG.sound.volumeDownKeys = TitleState.volumeDownKeys; - FlxG.sound.volumeUpKeys = TitleState.volumeUpKeys; + FlxG.sound.muteKeys = modding.LoadState.muteKeys; + FlxG.sound.volumeDownKeys = modding.LoadState.volumeDownKeys; + FlxG.sound.volumeUpKeys = modding.LoadState.volumeUpKeys; if (FlxG.keys.justPressed.SPACE) { reloadText(false); diff --git a/source/editors/MenuCharacterEditorState.hx b/source/editors/MenuCharacterEditorState.hx index 415bbc8..fb058ab 100644 --- a/source/editors/MenuCharacterEditorState.hx +++ b/source/editors/MenuCharacterEditorState.hx @@ -282,9 +282,9 @@ class MenuCharacterEditorState extends MusicBeatState } if(!blockInput) { - FlxG.sound.muteKeys = TitleState.muteKeys; - FlxG.sound.volumeDownKeys = TitleState.volumeDownKeys; - FlxG.sound.volumeUpKeys = TitleState.volumeUpKeys; + FlxG.sound.muteKeys = modding.LoadState.muteKeys; + FlxG.sound.volumeDownKeys = modding.LoadState.volumeDownKeys; + FlxG.sound.volumeUpKeys = modding.LoadState.volumeUpKeys; if(FlxG.keys.justPressed.ESCAPE) { MusicBeatState.switchState(new editors.MasterEditorMenu()); FlxG.sound.playMusic(Paths.music("freakyMenu-" + ClientPrefs.data.mmm)); diff --git a/source/editors/WeekEditorState.hx b/source/editors/WeekEditorState.hx index 0dc0d95..27b893d 100644 --- a/source/editors/WeekEditorState.hx +++ b/source/editors/WeekEditorState.hx @@ -490,9 +490,9 @@ class WeekEditorState extends MusicBeatState if (!blockInput) { - FlxG.sound.muteKeys = TitleState.muteKeys; - FlxG.sound.volumeDownKeys = TitleState.volumeDownKeys; - FlxG.sound.volumeUpKeys = TitleState.volumeUpKeys; + FlxG.sound.muteKeys = modding.LoadState.muteKeys; + FlxG.sound.volumeDownKeys = modding.LoadState.volumeDownKeys; + FlxG.sound.volumeUpKeys = modding.LoadState.volumeUpKeys; if (FlxG.keys.justPressed.ESCAPE) { MusicBeatState.switchState(new editors.MasterEditorMenu()); @@ -1056,9 +1056,9 @@ class WeekEditorFreeplayState extends MusicBeatState } else { - FlxG.sound.muteKeys = TitleState.muteKeys; - FlxG.sound.volumeDownKeys = TitleState.volumeDownKeys; - FlxG.sound.volumeUpKeys = TitleState.volumeUpKeys; + FlxG.sound.muteKeys = modding.LoadState.muteKeys; + FlxG.sound.volumeDownKeys = modding.LoadState.volumeDownKeys; + FlxG.sound.volumeUpKeys = modding.LoadState.volumeUpKeys; if (FlxG.keys.justPressed.ESCAPE) { MusicBeatState.switchState(new editors.MasterEditorMenu()); diff --git a/source/import.hx b/source/import.hx index eb1af41..f236d75 100644 --- a/source/import.hx +++ b/source/import.hx @@ -1,7 +1,21 @@ #if !macro // Fix for haxe 4.3+ import Paths; +import sys.logger.Logs; +using StringTools; +import sys.CoolErrorSubstate; -import codename.backend.assets.AssetsLibraryList; -import codename.backend.Script; -import codename.backend.system.Logs; +//fuckass imports that should have been here from the start +import flixel.FlxSprite; +import flixel.text.FlxText; +import flixel.util.FlxTimer; +import flixel.tweens.FlxTween; +import flixel.tweens.FlxEase; +import flixel.FlxBasic; +import flixel.FlxG; +import flixel.FlxCamera; +import flixel.FlxState; +import flixel.input.keyboard.FlxKey; +import flixel.sound.FlxSound; +import flixel.FlxObject; +import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup; #end \ No newline at end of file diff --git a/source/modchart/modcharting/ModchartEditorState.hx b/source/modchart/modcharting/ModchartEditorState.hx index 95aeb69..9401cc6 100644 --- a/source/modchart/modcharting/ModchartEditorState.hx +++ b/source/modchart/modcharting/ModchartEditorState.hx @@ -797,9 +797,9 @@ class ModchartEditorState extends #if SCEModchartingTools states.MusicBeatState #if (PSYCH && PSYCHVERSION >= "0.7") ClientPrefs.toggleVolumeKeys(true); #elseif (PSYCH && !(PSYCHVERSION >= "0.7")) - FlxG.sound.muteKeys = TitleState.muteKeys; - FlxG.sound.volumeDownKeys = TitleState.volumeDownKeys; - FlxG.sound.volumeUpKeys = TitleState.volumeUpKeys; + FlxG.sound.muteKeys = modding.LoadState.muteKeys; + FlxG.sound.volumeDownKeys = modding.LoadState.volumeDownKeys; + FlxG.sound.volumeUpKeys = modding.LoadState.volumeUpKeys; #end if (FlxG.keys.justPressed.SPACE) { @@ -1082,9 +1082,9 @@ class ModchartEditorState extends #if SCEModchartingTools states.MusicBeatState #if (PSYCH && PSYCHVERSION >= "0.7") ClientPrefs.toggleVolumeKeys(true); #elseif (PSYCH && !(PSYCHVERSION >= "0.7")) - FlxG.sound.muteKeys = TitleState.muteKeys; - FlxG.sound.volumeDownKeys = TitleState.volumeDownKeys; - FlxG.sound.volumeUpKeys = TitleState.volumeUpKeys; + FlxG.sound.muteKeys = modding.LoadState.muteKeys; + FlxG.sound.volumeDownKeys = modding.LoadState.volumeDownKeys; + FlxG.sound.volumeUpKeys = modding.LoadState.volumeUpKeys; #end FlxG.mouse.visible = false; inst.stop(); diff --git a/source/modding/LoadState.hx b/source/modding/LoadState.hx new file mode 100644 index 0000000..343c508 --- /dev/null +++ b/source/modding/LoadState.hx @@ -0,0 +1,67 @@ +package modding; + +import polymod.Polymod; + +class LoadState extends MusicBeatState +{ + public static var muteKeys:Array = [FlxKey.ZERO]; + public static var volumeDownKeys:Array = [FlxKey.NUMPADMINUS, FlxKey.MINUS]; + public static var volumeUpKeys:Array = [FlxKey.NUMPADPLUS, FlxKey.PLUS]; + + var stateToLoad:Class; + public function new(?hotReload:Bool = false, ?lastState:FlxState = null) + { + super(); + + if (hotReload) + { + stateToLoad = Type.getClass(lastState); + Polymod.clearScripts(); + } + } + + public override function create() { + super.create(); + + Logs.traceNew("Game Setup - Loading Prefs/Mods", INFO); + + if (!PolymodHandler.isInit) + { + Paths.clearStoredMemory(); + Paths.clearUnusedMemory(); + } + + #if LUA_ALLOWED + Paths.pushGlobalMods(); + #end + // Just to load a mod on start up if ya got one. For mods that change the menu music and bg + WeekData.loadTheFirstEnabledMod(); + + FlxG.game.focusLostFramerate = 10; + FlxG.sound.muteKeys = muteKeys; + FlxG.sound.volumeDownKeys = volumeDownKeys; + FlxG.sound.volumeUpKeys = volumeUpKeys; + FlxG.keys.preventDefaultKeys = [TAB]; + + PlayerSettings.init(); + + ClientPrefs.loadPrefs(); + + Highscore.load(); + #if MODS_ALLOWED + PolymodHandler.init(); + #end + + Logs.traceNew("Finished loading!", INFO); + + PolymodHandler.isInit = true; + if (stateToLoad != null) + { + FlxG.switchState(Type.createInstance(stateToLoad, [])); + } + else + { + FlxG.switchState(new TitleState()); + } + } +} \ No newline at end of file diff --git a/source/modding/ModFolder.hx b/source/modding/ModFolder.hx new file mode 100644 index 0000000..ae3ca3f --- /dev/null +++ b/source/modding/ModFolder.hx @@ -0,0 +1,13 @@ +package modding; + +class ModFolder +{ + public var id:String; // The assosciated mod id polymod uses for this mod folder + public var name:String; // To make sure there are no folder conflicts.. somehow. + public var enabled:Bool = true; // Whether this mod is enabled + + public function new(id:String, name:String, enabled:Bool) + { + this.id = id; this.name = name; this.enabled = enabled; + } +} \ No newline at end of file diff --git a/source/modding/ModMenuSelectorState.hx b/source/modding/ModMenuSelectorState.hx new file mode 100644 index 0000000..9366ef8 --- /dev/null +++ b/source/modding/ModMenuSelectorState.hx @@ -0,0 +1,103 @@ +package modding; + +import flixel.addons.transition.FlxTransitionableState; + +// Truly a classic Psych State setup +class ModMenuSelectorState extends MusicBeatState +{ + var bg:FlxSprite; + var options:Array = ["Psych Engine Mods", "UE Mod Switcher"]; + var grpOptions:FlxTypedSpriteGroup = new FlxTypedSpriteGroup(); + var curSelected:Int = 0; + var camFollow:FlxObject; + + var camBG:FlxCamera; + var camOptions:FlxCamera; + + public override function create() { + super.create(); + + //Camera Setup + camBG = new FlxCamera(); + camOptions = new FlxCamera(); + camOptions.bgColor.alpha = 0; + + camFollow = new FlxObject(); + camFollow.screenCenter(X); + camOptions.follow(camFollow, LOCKON, 0.06); + FlxG.cameras.add(camBG); + FlxG.cameras.add(camOptions, false); + + bg = new FlxSprite().loadGraphic(Paths.image("menuBG")); + bg.scrollFactor.set(0, 0); + bg.setGraphicSize(Std.int(bg.width * 1.175)); + bg.updateHitbox(); + bg.screenCenter(); + bg.antialiasing = ClientPrefs.data.globalAntialiasing; + add(bg); + + grpOptions.cameras = [camOptions]; + add(grpOptions); + + for (i in 0...options.length) + { + var option = options[i]; + var text:Alphabet = new Alphabet(0, 150 * i, option, true); + text.screenCenter(X); + grpOptions.add(text); + } + + changeSelection(); + } + + public override function update(elapsed:Float) { + super.update(elapsed); + + if (controls.BACK) FlxG.switchState(new MainMenuState()); + if (controls.UI_DOWN_P) + { + changeSelection(1); + } + if (controls.UI_UP_P) + { + changeSelection(-1); + } + if (controls.ACCEPT) + { + FlxTransitionableState.skipNextTransIn = true; + FlxTransitionableState.skipNextTransOut = true; + switch(options[curSelected]) + { + case "Psych Engine Mods": + FlxG.switchState(new ModsMenuState()); + case "UE Mod Switcher": + FlxG.switchState(new modding.UEModSwitchState()); + } + } + } + + function changeSelection(change:Int = 0):Void + { + FlxG.sound.play(Paths.sound('scrollMenu')); + curSelected += change; + if (curSelected > options.length - 1) + curSelected = 0; + if (curSelected < 0) + curSelected = options.length - 1; + + for (i in 0...grpOptions.members.length) + { + var text = grpOptions.members[i]; + + if (i == curSelected) + { + text.alpha = 1; + camFollow.y = text.y; + } + else + { + text.alpha = 0.5; + } + } + } +} \ No newline at end of file diff --git a/source/modding/PolymodHandler.hx b/source/modding/PolymodHandler.hx new file mode 100644 index 0000000..6930c76 --- /dev/null +++ b/source/modding/PolymodHandler.hx @@ -0,0 +1,178 @@ +package modding; + +import haxe.Log; +import haxe.PosInfos; +#if MODS_ALLOWED +import polymod.Polymod; +import polymod.Polymod.PolymodError; +import polymod.util.DefineUtil.getDefineString; +import polymod.util.DefineUtil.getDefineBool; + +import modding.ModFolder; +import modding.ScriptContext; +import modding.ScriptContext.ModScriptContexts; + +import sys.FileSystem as Fs; +import sys.io.File; + +class PolymodHandler { + static var modRoot:String = #if TEST_BUILD "../../../new_example_mods" #else "mods" #end; + static var apiVersion:String = "1.0.0"; // This should match the current engine version. + static var scriptContexts:Array = []; + + static var modsList:Array = []; + static var customAssetLibrary:Map = [ + #if VIDEOS_ALLOWED "videos" => "./videos", #end + "songs" => "./songs", + "shared" => "shared", + "week2" => "./week1", + "week3" => "./week2", + "week4" => "./week3", + "week5" => "./week4", + "week6" => "./week5", + "week7" => "./week7", + "shaders" => "./shaders" + ]; + static var selectedMod:Array; + + public static var isInit:Bool = false; + + public static function initModList() + { + modsList = []; + scriptContexts = []; + + trace("Searching for mods!"); + + modsList = Polymod.scan({ + modRoot: modRoot, + apiVersionRule: '>=$apiVersion', + errorCallback: function(e:PolymodError) errorCallback(e) + }); + + trace("Scan finished!"); + } + + public static function init() + { + trace("Let's have a load.. /ref"); + if (!isInit) initModList(); + selectedMod = ClientPrefs.data.lastLoadedMod ?? []; + var modExists:Bool = false; + for (mod in modsList) + { + if (mod.id == selectedMod[0]) + modExists = true; + } + + if (!modExists) + { + selectedMod = []; // Prevent an error due to missing mod id + } + + Polymod.init({ + modRoot: modRoot, + apiVersionRule: '<=$apiVersion', + errorCallback: function(e:PolymodError) errorCallback(e), + frameworkParams: { + assetLibraryPaths: customAssetLibrary + }, + dirs: selectedMod + }); + trace("Finished loading mods!"); + } + + public static function getLoadedMod():String + { + if (selectedMod.length > 0) return selectedMod[0]; + + return "None"; + } + + public static function getAvailableMods():Array + { + var a:Array = []; + + for (mod in modsList) + { + a.push(mod.title); + } + + return a; + } + + public static function getAvailableModsIDs():Array + { + var a:Array = []; + + for (mod in modsList) + { + a.push(mod.id); + } + + return a; + } + + /* + * Meant for string representation of the current mods list. + */ + public static function formattedModList():String + { + var s:String = ''; + for (mod in getAvailableMods()) + { + s += mod + '\n'; + } + + return s.trim(); + } + + static function errorCallback(e:PolymodError, ?infos:Null):Void + { + if (e.severity == NOTICE) + { + Logs.traceNew(e.message, INFO, infos); + } + + if (e.severity == WARNING) + { + Logs.traceNew(e.message, WARNING, infos); + } + + if (e.severity == ERROR) + { + Logs.traceNew(e.message, ERROR, infos); + } + + if (isInit) visual_errorCallback(e, infos); + } + + /* + * Creates a visible, in-window error (DIFFERENT FROM CoolUtil.coolError) + */ + public static function visual_errorCallback(e:Dynamic, ?infos:Null):Void + { + var text:FlxText = new FlxText(0, 0, FlxG.width, Log.formatOutput(e, infos)); + text.setFormat(Paths.font("funkin.ttf"), 8, 0xFFFFFFFF, LEFT, OUTLINE, 0xFF000000); + CoolUtil.addToCurrentState(text); + } + + public static function createModFromTemplate(name:String) + { + Fs.createDirectory('mods/$name'); + File.saveContent('mods/$name/${getDefineString("POLYMOD_MOD_METADATA_FILE")}', getTemplateJSON(name)); + File.copy('assets/images/templates/mods/templateIcon.png', 'mods/$name/${getDefineString("POLYMOD_MOD_ICON_FILE")}'); + } + + static function getTemplateJSON(name:String):String + { + return '{ + "title":"$name", + "description":"Add your description here!", + "api_version":"1.0.0", + "mod_version":"0.0.1" +} + '; + } +} +#end \ No newline at end of file diff --git a/source/modding/ScriptContext.hx b/source/modding/ScriptContext.hx new file mode 100644 index 0000000..d830342 --- /dev/null +++ b/source/modding/ScriptContext.hx @@ -0,0 +1,27 @@ +package modding; + +class ScriptContext +{ + public var folder:String; + public var script:String; + + /* + * f - Folder + * s - Script + */ + public function new(f:String, s:String) + { + folder = f; script = s; + } +} + +class ModScriptContexts +{ + public var mod_id:String; + public var contexts:Array; + + public function new(id:String, cs:Array) + { + mod_id = id; contexts = cs; + } +} \ No newline at end of file diff --git a/source/modding/UEModSwitchState.hx b/source/modding/UEModSwitchState.hx new file mode 100644 index 0000000..d7e6097 --- /dev/null +++ b/source/modding/UEModSwitchState.hx @@ -0,0 +1,232 @@ +package modding; + +import polymod.Polymod; +import flixel.addons.ui.FlxUIInputText; +import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup; +import modding.PolymodHandler.getAvailableMods; +import modding.PolymodHandler.getAvailableModsIDs; + +class UEModSwitchState extends MusicBeatState +{ + var bg:FlxSprite; + var grpMods:FlxTypedSpriteGroup = new FlxTypedSpriteGroup(); + public var curSelected:Int = 0; + var camFollow:FlxObject; + var init:Bool = false; + + var camBG:FlxCamera; + var camOptions:FlxCamera; + + var modsList:Array; + var modIdList:Array; + + public override function create() { + super.create(); + + modsList = getAvailableMods(); + modIdList = getAvailableModsIDs(); + modsList.insert(0, "Disable Mods"); + modIdList.insert(0, "disableMods"); + modsList.push("Create New Mod"); + modIdList.push("newMod"); + + //Camera Setup + camBG = new FlxCamera(); + camOptions = new FlxCamera(); + camOptions.bgColor.alpha = 0; + + camFollow = new FlxObject(); + camFollow.screenCenter(X); + camOptions.follow(camFollow, LOCKON, 0.06); + FlxG.cameras.add(camBG); + FlxG.cameras.add(camOptions, false); + + bg = new FlxSprite().loadGraphic(Paths.image("menuBG")); + bg.scrollFactor.set(0, 0); + bg.setGraphicSize(Std.int(bg.width * 1.175)); + bg.updateHitbox(); + bg.screenCenter(); + bg.antialiasing = ClientPrefs.data.globalAntialiasing; + add(bg); + + grpMods.cameras = [camOptions]; + add(grpMods); + + // Temp until full mod details are coded in + for (i in 0...modsList.length) + { + var option = modsList[i]; + var text:Alphabet = new Alphabet(0, 150 * i, option, true); + text.screenCenter(X); + grpMods.add(text); + } + + changeSelection(); + var delayTimer = new FlxTimer().start(0.1, function(_) { + init = true; + selectable = true; + }); + } + + var selectable:Bool = false; + public override function update(elapsed:Float) { + super.update(elapsed); + + if (controls.BACK) FlxG.switchState(new MainMenuState()); + if (controls.UI_DOWN_P) + { + changeSelection(1); + } + if (controls.UI_UP_P) + { + changeSelection(-1); + } + if (controls.ACCEPT && selectable) + { + selectable = false; + // Swap that mod in! + if (modIdList[curSelected] == "newMod") + { + openSubState(new NewModSubstate(this)); + } + else + { + modSwitchCallback(); + } + } + } + + public function modSwitchCallback(resetState:Bool = false) + { + if (modIdList[curSelected] != "disableMods") + ClientPrefs.data.lastLoadedMod = [modIdList[curSelected]]; + else + ClientPrefs.data.lastLoadedMod = []; + + ClientPrefs.saveSettings(); + MusicBeatState.switchState(new LoadState(true, !resetState ? new MainMenuState() : new UEModSwitchState())); + } + + public function changeSelection(change:Int = 0):Void + { + FlxG.sound.play(Paths.sound('scrollMenu')); + curSelected += change; + if (curSelected > modsList.length - 1) + curSelected = 0; + if (curSelected < 0) + curSelected = modsList.length - 1; + + for (i in 0...grpMods.members.length) + { + var text = grpMods.members[i]; + + if (i == curSelected) + { + text.alpha = 1; + camFollow.y = text.y; + } + else + { + text.alpha = 0.5; + } + } + } + + public override function startOutro(onOutroComplete:() -> Void) { + super.startOutro(onOutroComplete); + FlxG.cameras.remove(camBG); + FlxG.cameras.remove(camOptions); + } +} + + +class NewModSubstate extends MusicBeatSubstate +{ + var bg:FlxSprite; + var text1:Alphabet; + var modTitle:Alphabet; + var camNewMod:FlxCamera; + + var newModName:String = "newmod"; + var bgTween:FlxTween; + var text1Tween:FlxTween; + var modTitleTween:FlxTween; + + var initialized:Bool = false; + var inputBox:FlxUIInputText; + var instance:UEModSwitchState; + + public function new(i:UEModSwitchState) + { + super(); + instance = i; + } + + public override function create() { + super.create(); + + camNewMod = new FlxCamera(); + FlxG.cameras.add(camNewMod, false); + this.cameras = [camNewMod]; + + inputBox = new FlxUIInputText(0, 0, FlxG.width, newModName, 1); + add(inputBox); + bg = new FlxSprite().loadGraphic(Paths.image("aboutMenu")); + bg.alpha = 0; + add(bg); + + text1 = new Alphabet(0, 100, "MOD NAME"); + text1.alpha = 0; + text1.screenCenter(X); + add(text1); + + modTitle = new Alphabet(0, 0, newModName); + modTitle.alpha = 0; + modTitle.screenCenter(); + add(modTitle); + + bgTween = FlxTween.tween(bg, {alpha: 1}, 2); + text1Tween = FlxTween.tween(text1, {alpha: 1}, 2); + modTitleTween = FlxTween.tween(modTitle, {alpha: 1}, 2); + var delayTimer = new FlxTimer().start(2.5, function(_) initialized = true); + } + + public override function update(elapsed:Float) { + super.update(elapsed); + + if (!initialized) return; + var exit:Bool = FlxG.keys.justPressed.ESCAPE; + var accept:Bool = FlxG.keys.justPressed.ENTER; + if (accept) + { + PolymodHandler.createModFromTemplate(newModName); + tweenOut(); + } + if (exit) + { + tweenOut(); + } + inputBox.hasFocus = true; + modTitle.text = newModName = inputBox.text; + } + + function tweenOut() + { + bgTween = FlxTween.tween(bg, {alpha: 0}, 2); + text1Tween = FlxTween.tween(text1, {alpha: 0}, 2); + modTitleTween = FlxTween.tween(modTitle, {alpha: 0}, 2); + var delayTimer = new FlxTimer().start(2.5, function(_) + { + close(); + PolymodHandler.initModList(); + instance.curSelected = 0; + instance.changeSelection(); + instance.modSwitchCallback(); + }); + } + + public override function close() { + super.close(); + FlxG.cameras.remove(camNewMod); + } +} \ No newline at end of file diff --git a/source/sys/CoolErrorSubstate.hx b/source/sys/CoolErrorSubstate.hx new file mode 100644 index 0000000..e94e25c --- /dev/null +++ b/source/sys/CoolErrorSubstate.hx @@ -0,0 +1,90 @@ +package sys; + +import haxe.PosInfos; + +class CoolErrorSubstate extends MusicBeatSubstate +{ + var back:FlxSprite; + var text:FlxText; + var title:FlxText; + + var stateCam:FlxCamera; + var finishedInit:Bool = false; + var initDelay:FlxTimer = new FlxTimer(); // make sure you can actually SEE the error. + var fadeDelay:Int = 2; + + /* + * Creates a new substate that shows an error with a title. + * + * @param backRef The FlxSprite to use as the backdrop. + * @param fadeDelay How many seconds should the fade be delayed by + * @param infos Don't touch this unless you know how `haxe.PosInfos` works. + */ + public function new(errMsg:String, errTitle:String = "", ?backRef:FlxSprite = null, fadeDelay:Int = 2, ?infos:PosInfos) + { + this.fadeDelay = fadeDelay; + if (backRef != null) + { + back = backRef; + back.setGraphicSize(FlxG.width, FlxG.height); + back.updateHitbox(); + } + else + { + back = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, 0xFF000000); + } + back.alpha = 0.6; + + text = new FlxText(0, 0, FlxG.width, haxe.Log.formatOutput(errMsg, infos)); + text.setFormat(Paths.font('funkin.ttf'), 15, 0xFFFFFFFF, CENTER, OUTLINE, 0xFF000000); + text.screenCenter(Y); + + title = new FlxText(0, 100, FlxG.width, errTitle); + title.setFormat(Paths.font('funkin.ttf'), 50, 0xFFFFFFFF, CENTER, OUTLINE, 0xFF000000); + + if (errTitle.length > 0) + errTitle += ' - '; + + Logs.traceNew(errTitle + errMsg, ERROR, infos); + + super(); + } + + var errTween:FlxTween; + public override function create() { + super.create(); + + stateCam = new FlxCamera(); + stateCam.bgColor.alpha = 0; + FlxG.cameras.add(stateCam, false); + + add(back); + add(text); + add(title); + + this.cameras = [stateCam]; + initDelay.start(0.2, function(tmr:FlxTimer){ + finishedInit = true; + }); + + errTween = FlxTween.tween(stateCam, {alpha: 0}, 5, {onComplete: function(twn:FlxTween) close(), startDelay: fadeDelay}); + } + + public override function update(elapsed:Float) { + super.update(elapsed); + + var keys:Array = [controls.ACCEPT, controls.BACK, controls.UI_DOWN, controls.UI_UP, controls.UI_LEFT, controls.UI_RIGHT, controls.NOTE_DOWN, controls.NOTE_UP, controls.NOTE_LEFT, controls.NOTE_RIGHT]; + + for (k in keys) + { + if (k && finishedInit) close(); + } + } + + public override function close() { + super.close(); + + if (errTween != null) errTween.cancel(); + FlxG.cameras.remove(stateCam); + } +} \ No newline at end of file diff --git a/source/sys/LuaIterator.hx b/source/sys/LuaIterator.hx new file mode 100644 index 0000000..c227c29 --- /dev/null +++ b/source/sys/LuaIterator.hx @@ -0,0 +1,51 @@ +package sys; + +/* +* This class recreates the functionality of a lua iterator +*/ +class LuaIterator +{ + var min:Float; + var max:Float; + var step:Float; + + /** + Iterates from `min` (inclusive) to `max` (exclusive) by `step`. + + If `max <= min`, the iterator will not act as a countdown. + If `step` is a whole number, but `min` and/or `max` aren't, `min` and/or `max` will be `Math.floor()`'d + **/ + public inline function new(min:Float, max:Float, step:Float = 1) + { + this.min = min; + this.max = max; + this.step = step; + + if (Std.int(step) == step) + { + min = Math.floor(min); + max = Math.floor(max); + } + } + + /** + Returns true if the iterator has other items, false otherwise. + **/ + public inline function hasNext():Bool + { + var nextCalc:Float = min + step; + + return nextCalc < max; + } + + /** + Moves to the next item of the iterator. + + If this is called while hasNext() is false, the result is unspecified. + **/ + public inline function next():Float + { + var nextCalc:Float = min + step; + return (min = nextCalc); + } +} \ No newline at end of file diff --git a/source/sys/Watermark.hx b/source/sys/Watermark.hx new file mode 100644 index 0000000..6b11616 --- /dev/null +++ b/source/sys/Watermark.hx @@ -0,0 +1,35 @@ +package sys; + +import flixel.util.FlxAxes; +import openfl.text.TextField; +import openfl.text.TextFormat; + +/* +* This class let's you put an entire watermark over the screen. +*/ +class Watermark extends TextField +{ + public function new(s:String, color:Int = 0xFFFFFFFF, size:Int = 100) + { + super(); + + selectable = false; + mouseEnabled = false; + defaultTextFormat = new TextFormat(Paths.font('funkin.ttf'), size, color); + autoSize = CENTER; + multiline = true; + text = s; + alpha = 0.3; + } + + public function screenCenter(axes:FlxAxes = XY):Watermark + { + if (axes.x) + x = (FlxG.width - width) / 2; + + if (axes.y) + y = (FlxG.height - height) / 2; + + return this; + } +} \ No newline at end of file diff --git a/source/codename/backend/system/Logs.hx b/source/sys/logger/AnsiColors.hx similarity index 62% rename from source/codename/backend/system/Logs.hx rename to source/sys/logger/AnsiColors.hx index 9e13a3a..2079c87 100644 --- a/source/codename/backend/system/Logs.hx +++ b/source/sys/logger/AnsiColors.hx @@ -1,80 +1,4 @@ -package codename.backend.system; - -import haxe.Log; -import haxe.PosInfos; -import lime.app.Application; -using codename.backend.system.Logs.LogTools; - -class LogTools -{ - public static inline function levelToString(level:Level):String - { - switch (level) - { - case INFO: - return AnsiColors.LightPurple + '[ INFO ]'; - case WARNING: - return AnsiColors.LightYellow + '[ WARNING ]'; - case ERROR: - return AnsiColors.Error + '[ ERROR ]'; - default: - return '[ MISC ]'; - } - } -} - -class Logs -{ - public static var nativeTrace = Log.trace; - - public static function init() - { - Log.trace = traceOverride; - } - - static function levelToInt(l:Level):Int - { - switch(l) - { - case INFO: - return 0; - case MISC: - return 1; - case NONE: - return 2; - case WARNING: - return 3; - case ERROR: - return 4; - } - } - - static function traceOverride(v:Dynamic, ?infos:PosInfos):Void traceNew(v, NONE, infos); - - public static function traceNew(v:Dynamic, level:Level = NONE, ?infos:PosInfos):Void - { - var str = '${level.levelToString()} : ' + Log.formatOutput(v, infos).replace('\n\n', '\n').replace('\n', '\n${level.levelToString()} : ${infos.fileName}:${infos.lineNumber}: ') + AnsiColors.Reset; - #if js - if (js.Syntax.typeof(untyped console) != "undefined" && (untyped console).log != null) - (untyped console).log(str); - #elseif lua - untyped __define_feature__("use._hx_print", _hx_print(str)); - #elseif sys - Sys.println(str); - #else - throw new haxe.exceptions.NotImplementedException() - #end - } -} - -enum abstract Level(Int) -{ - var INFO = 0; - var MISC = 1; - var NONE = 2; - var WARNING = 3; - var ERROR = 4; -} +package sys.logger; // Thank you @notbilly in the Haxe Discord for the color codes! enum abstract AnsiColors(String) to String { diff --git a/source/sys/logger/Level.hx b/source/sys/logger/Level.hx new file mode 100644 index 0000000..fcebf8c --- /dev/null +++ b/source/sys/logger/Level.hx @@ -0,0 +1,10 @@ +package sys.logger; + +enum abstract Level(Int) +{ + var INFO = 0; + var MISC = 1; + var NONE = 2; + var WARNING = 3; + var ERROR = 4; +} \ No newline at end of file diff --git a/source/sys/logger/LogTools.hx b/source/sys/logger/LogTools.hx new file mode 100644 index 0000000..3bc776e --- /dev/null +++ b/source/sys/logger/LogTools.hx @@ -0,0 +1,22 @@ +package sys.logger; + +import sys.logger.AnsiColors; +import sys.logger.Level; + +class LogTools +{ + public static inline function levelToString(level:Level):String + { + switch (level) + { + case INFO: + return AnsiColors.LightPurple + '[ INFO ]'; + case WARNING: + return AnsiColors.LightYellow + '[ WARNING ]'; + case ERROR: + return AnsiColors.Error + '[ ERROR ]'; + default: + return '[ MISC ]'; + } + } +} \ No newline at end of file diff --git a/source/sys/logger/Logs.hx b/source/sys/logger/Logs.hx new file mode 100644 index 0000000..0af738d --- /dev/null +++ b/source/sys/logger/Logs.hx @@ -0,0 +1,54 @@ +package sys.logger; // This is MY log script, so it's under charengine :3c - CharGoldenYT + +import haxe.Log; +import haxe.PosInfos; +import lime.app.Application; +import sys.logger.AnsiColors; +using sys.logger.LogTools; +import sys.logger.Level; + +class Logs +{ + public static var nativeTrace = Log.trace; + + public static function init() + { + Log.trace = traceOverride; + } + + public static dynamic function trace(v:Dynamic, level:Level = NONE, ?infos:PosInfos):Void traceNew(v, level, infos); + + static function levelToInt(l:Level):Int + { + switch(l) + { + case INFO: + return 0; + case MISC: + return 1; + case NONE: + return 2; + case WARNING: + return 3; + case ERROR: + return 4; + } + } + + static function traceOverride(v:Dynamic, ?infos:PosInfos):Void traceNew(v, NONE, infos); + + public static function traceNew(v:Dynamic, level:Level = NONE, ?infos:PosInfos):Void + { + var str = '${level.levelToString()} : ' + Log.formatOutput(v, infos).replace('\n\n', '\n').replace('\n', '\n${level.levelToString()} : ${infos.fileName}:${infos.lineNumber}: ') + AnsiColors.Reset; + #if js + if (js.Syntax.typeof(untyped console) != "undefined" && (untyped console).log != null) + (untyped console).log(str); + #elseif lua + untyped __define_feature__("use._hx_print", _hx_print(str)); + #elseif sys + Sys.println(str); + #else + throw new haxe.exceptions.NotImplementedException() + #end + } +} \ No newline at end of file
Contributor Names Daveberry Daveberry VideoBot BaranMuzu CharGoldenYT Role Former Developer Main Developer Invited Developer Former Developer Invited Developer