diff --git a/README.md b/README.md index 604cd9c2..b4d4bcc9 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,8 @@ Make sure to read the wiki and join the Discord server linked there!
Latest builds for the engine can be found in the [Actions](https://github.com/YoshiCrafter29/CodenameEngine/actions) tab.
In the future (when the engine won't be a WIP anymore) we're gonna also publish the engine on platforms like Gamebanana; stay tuned! +If you don't have a github account please go onto https://fnf-cne-devs.github.io/ and click the download button for the respective operating system. +

How to build

@@ -76,7 +78,7 @@ In the future (when the engine won't be a WIP anymore) we're gonna also publish - Steal code from Codename Engine for another different project that is not Codename Engine related (Codename Engine mods excluded) without properly crediting - Release the entire Codename Engine on platforms (Mods that use Codename Engine as source are fine, if it's specified even better) - #### *If you need more info or feel like asking to do something which is not listed here, ask us directly on our discord (linked in the wiki)!* + #### *If you need more info or feel like asking to do something which is not listed here, ask us directly on our discord (linked on the website)!*
diff --git a/art/flashFiles/Editor_Icons.fla b/art/flashFiles/Editor_Icons.fla new file mode 100644 index 00000000..6ad80d3d Binary files /dev/null and b/art/flashFiles/Editor_Icons.fla differ diff --git a/assets/images/editors/icons.png b/assets/images/editors/icons.png index 41dee63c..cccc10f9 100644 Binary files a/assets/images/editors/icons.png and b/assets/images/editors/icons.png differ diff --git a/source/funkin/backend/scripting/Script.hx b/source/funkin/backend/scripting/Script.hx index 2f7f0344..6f90a0f9 100644 --- a/source/funkin/backend/scripting/Script.hx +++ b/source/funkin/backend/scripting/Script.hx @@ -283,7 +283,7 @@ class Script extends FlxBasic implements IFlxDestroyable { public function get(variable:String):Dynamic {return null;} /** - * Gets the variable `variable` from the script's variables. + * Sets the variable `variable` from the script's variables. * @param variable Name of the variable. * @return Variable (or null if it doesn't exists) */ diff --git a/source/funkin/backend/system/macros/EventMacro.hx b/source/funkin/backend/system/macros/EventMacro.hx index 810ff1fd..7219a528 100644 --- a/source/funkin/backend/system/macros/EventMacro.hx +++ b/source/funkin/backend/system/macros/EventMacro.hx @@ -75,34 +75,13 @@ class EventMacro { // add a "set this" expr for each variable for(v in values) { var name = v.name; - exprs.push({ - pos: Context.currentPos(), - expr: EBinop(OpAssign, { - pos: Context.currentPos(), - expr: EField({ - pos: Context.currentPos(), - expr: EConst(CIdent("this")) - }, name) - }, { - pos: Context.currentPos(), - expr: EConst(CIdent(name)) - }) - }); + exprs.push(macro this.$name = $i{name}); } // add a "set this" expr to reset each private/hidden variables for(v in hiddenValues) { var name = v.name; - exprs.push({ - pos: Context.currentPos(), - expr: EBinop(OpAssign, { - pos: Context.currentPos(), - expr: EField({ - pos: Context.currentPos(), - expr: EConst(CIdent("this")) - }, name) - }, v.expr) - }); + exprs.push(macro this.$name = ${v.expr}); } exprs.push(macro return this); diff --git a/source/funkin/editors/EditorPicker.hx b/source/funkin/editors/EditorPicker.hx index 50a93453..136b2efd 100644 --- a/source/funkin/editors/EditorPicker.hx +++ b/source/funkin/editors/EditorPicker.hx @@ -29,6 +29,14 @@ class EditorPicker extends MusicBeatSubstate { state: UIDebugState }, #end + { + name: "Wiki", + iconID: 5, + state: null, + onClick: function() { + CoolUtil.openURL("https://fnf-cne-devs.github.io/"); + } + }, { name: "Debug Options", iconID: 4, @@ -96,7 +104,9 @@ class EditorPicker extends MusicBeatSubstate { } if (controls.ACCEPT || FlxG.mouse.justReleased) { - if (options[curSelected].state != null) { + if(options[curSelected].onClick != null) + options[curSelected].onClick(); + else if (options[curSelected].state != null) { selected = true; CoolUtil.playMenuSFX(CONFIRM); @@ -147,6 +157,7 @@ typedef Editor = { var name:String; var iconID:Int; var state:Class; + var ?onClick:Void->Void; } class EditorPickerOption extends FlxTypedSpriteGroup { @@ -163,7 +174,6 @@ class EditorPickerOption extends FlxTypedSpriteGroup { public function new(name:String, iconID:Int, height:Float) { super(); - FlxG.mouse.visible = true; iconSpr = new FlxSprite(); iconSpr.loadGraphic(Paths.image('editors/icons'), true, 128, 128); diff --git a/source/funkin/game/PlayState.hx b/source/funkin/game/PlayState.hx index 28523240..ab117366 100644 --- a/source/funkin/game/PlayState.hx +++ b/source/funkin/game/PlayState.hx @@ -246,7 +246,7 @@ class PlayState extends MusicBeatState /** * Current stage name */ - public var curStage:String = ""; + public var curStage(get, set):String; /** * Interval at which Girlfriend dances. @@ -529,6 +529,14 @@ class PlayState extends MusicBeatState return this.maxHealth = v; } + private inline function get_curStage() + return stage == null ? "" : stage.stageName; + + private inline function set_curStage(name:String) { + if (stage != null) stage.stageName = name; + return name; + } + public inline function callOnCharacters(func:String, ?parameters:Array) { if(strumLines != null) strumLines.forEachAlive(function (strLine:StrumLine) { if (strLine.characters != null) for (character in strLine.characters) diff --git a/source/funkin/game/Stage.hx b/source/funkin/game/Stage.hx index b0282af8..85d57f94 100644 --- a/source/funkin/game/Stage.hx +++ b/source/funkin/game/Stage.hx @@ -13,19 +13,22 @@ import haxe.xml.Access; using StringTools; class Stage extends FlxBasic implements IBeatReceiver { + public var stageName:String = ""; public var stageXML:Access; public var stagePath:String; public var stageSprites:Map = []; public var stageScript:Script; public var state:FlxState; public var characterPoses:Map = []; - public var xmlImportedScripts:Map = []; + public var xmlImportedScripts:Array = []; private var spritesParentFolder = ""; - public function getSprite(name:String) { + public function getSprite(name:String) return stageSprites[name]; - } + + public function setStagesSprites(script:Script) + for (k=>e in stageSprites) script.set(k, e); public function new(stage:String, ?state:FlxState) { super(); @@ -35,11 +38,8 @@ class Stage extends FlxBasic implements IBeatReceiver { this.state = state; stagePath = Paths.xml('stages/$stage'); - try { - if (Assets.exists(stagePath)) stageXML = new Access(Xml.parse(Assets.getText(stagePath)).firstElement()); - } catch(e) { - Logs.trace('Couldn\'t load stage "$stage": ${e.message}', ERROR); - } + try if (Assets.exists(stagePath)) stageXML = new Access(Xml.parse(Assets.getText(stagePath)).firstElement()) + catch(e) Logs.trace('Couldn\'t load stage "$stage": ${e.message}', ERROR); if (PlayState.instance != null) { stageScript = Script.create(Paths.script('data/stages/$stage')); @@ -49,12 +49,13 @@ class Stage extends FlxBasic implements IBeatReceiver { var event = null; if (stageXML != null) { + stageName = stageXML.getAtt("name").getDefault(stage); + if (PlayState.instance != null) { var parsed:Null; if(stageXML.has.startCamPosX && (parsed = Std.parseFloat(stageXML.att.startCamPosX)) != null) PlayState.instance.camFollow.x = parsed; if(stageXML.has.startCamPosY && (parsed = Std.parseFloat(stageXML.att.startCamPosY)) != null) PlayState.instance.camFollow.y = parsed; if(stageXML.has.zoom && (parsed = Std.parseFloat(stageXML.att.zoom)) != null) PlayState.instance.defaultCamZoom = parsed; - PlayState.instance.curStage = stageXML.has.name ? stageXML.att.name : stage; } if (stageXML.has.folder) { spritesParentFolder = stageXML.att.folder; @@ -63,11 +64,8 @@ class Stage extends FlxBasic implements IBeatReceiver { var elems = []; for(node in stageXML.elements) { - if (node.name == "high-memory" && !Options.lowMemoryMode) - for(e in node.elements) - elems.push(e); - else - elems.push(node); + if (node.name == "high-memory" && !Options.lowMemoryMode) for(e in node.elements) __pushNcheckNode(elems, e); + else __pushNcheckNode(elems, node); } if (PlayState.instance != null) { @@ -138,20 +136,7 @@ class Stage extends FlxBasic implements IBeatReceiver { PlayState.instance.add(PlayState.instance.comboGroup); PlayState.instance.comboGroup; case "use-extension" | "extension" | "ext": - if (!node.has.script || PlayState.instance == null) continue; - - var folder = node.getAtt("folder").getDefault("data/scripts/"); - if (!folder.endsWith("/")) folder += "/"; - - var path = Paths.script(folder + node.getAtt("script")); - var daScript = Script.create(path); - if (daScript is DummyScript) Logs.trace('Script at ${path} does not exist.', ERROR); - else { - xmlImportedScripts.set(path, node.getAtt("isShortLived") == "true"); - PlayState.instance.scripts.add(daScript); - daScript.load(); - } - + if (__shouldLoadBefore(node) || XMLImportedScriptInfo.prepareInfos(node, this) == null) continue; null; default: null; } @@ -193,15 +178,20 @@ class Stage extends FlxBasic implements IBeatReceiver { if (PlayState.instance == null) return; - for (k=>e in stageSprites) - stageScript.set(k, e); + setStagesSprites(stageScript); + + // i know this for gets run twice under, but its better like this in case a script modifies the short lived ones, i dont wanna save them in an array; more dynamic like this - Nex + for (info in xmlImportedScripts) if (info.importStageSprites) { + var script = info.getScript(); + if (script != null) setStagesSprites(script); + } // idk lemme check anyways just in case scripts did smth - Nex if (event != null) PlayState.instance.gameAndCharsEvent("onPostStageCreation", event); // shortlived scripts destroy when the stage finishes setting up - Nex - for (p=>b in xmlImportedScripts) if (b) { - var script = PlayState.instance.scripts.getByPath(p); + for (info in xmlImportedScripts) if (info.shortLived) { + var script = info.getScript(); if (script == null) continue; PlayState.instance.scripts.remove(script); @@ -209,6 +199,15 @@ class Stage extends FlxBasic implements IBeatReceiver { } } + @:dox(hide) private function __pushNcheckNode(array:Array, node:Access) { + array.push(node); + if ((node.name == "use-extension" || node.name == "extension" || node.name == "ext") && __shouldLoadBefore(node)) + XMLImportedScriptInfo.prepareInfos(node, this); + } + + @:dox(hide) private static inline function __shouldLoadBefore(node:Access):Bool + return node.getAtt("loadBefore") != "false"; + public function addCharPos(name:String, node:Access, ?nonXMLInfo:StageCharPosInfo):StageCharPos { var charPos = new StageCharPos(); charPos.visible = charPos.active = false; @@ -318,4 +317,45 @@ typedef StageCharPosInfo = { var y:Float; var flip:Bool; var scroll:Float; +} + +class XMLImportedScriptInfo { + public var path:String; + public var shortLived:Bool = false; + public var loadBefore:Bool = true; + public var importStageSprites:Bool = false; + + public function new(path:String) + this.path = path; + + public function getScript():Script + return PlayState.instance == null ? null : PlayState.instance.scripts.getByPath(path); + + public static function prepareInfos(node:Access, ?stage:Stage):XMLImportedScriptInfo { + if (!node.has.script || PlayState.instance == null) return null; + + var folder = node.getAtt("folder").getDefault("data/scripts/"); + if (!folder.endsWith("/")) folder += "/"; + + var path = Paths.script(folder + node.getAtt("script")); + var daScript = Script.create(path); + if (daScript is DummyScript) { + var msg = 'Script Extension at ${path} does not exist'; + if (stage != null) msg += ' through stage "${stage.stageName}"'; + Logs.trace(msg + ".", ERROR); + return null; + } + + var infos = new XMLImportedScriptInfo(daScript.path); + infos.shortLived = node.getAtt("isShortLived") == "true"; + infos.importStageSprites = node.getAtt("importStageSprites") == "true"; + @:privateAccess infos.loadBefore = Stage.__shouldLoadBefore(node); + + if (stage != null) stage.xmlImportedScripts.push(infos); + PlayState.instance.scripts.add(daScript); + daScript.set("scriptInfo", infos); + daScript.load(); + + return infos; + } } \ No newline at end of file