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