Hello Everybody! I have just nearly completed a modding implementation for Armory and I think it is going to be awesome. I’m opening this topic to tell everybody how it works. I still have an issue that I still have to figure out before I am finished, but I figured I’d post how everything works here and open up a different topic to discuss the problem I’m having.
How Modding Works
These explanations apply to my in-progress modifications to Armory that can be found in my forks of Iron and Armory. As soon as I get everything figured out I will add example to the Armory examples as well.
Runtime
Right now, modding will only work for the Krom target because it needs a way to load code at runtime and Javascript is the only easy enough solution for that at the moment. Apparently Krom is benchmarked to be faster than the C++ target for Armory, anyway, so this shouldn’t be much of an issue. Additionally Krom is going to be coming to game consoles soon so that will not be an issue for it either.
Setup
I have designed Armory mods so that they are hardly different than any other Armory game and can have full access to the game, kha, iron, and armory APIs allowing for the maximum amount of customization.
A Moddable Game
It is very easy to take any Armory game and make it moddable. All you need to do is set the Render->Armory Project->Modding->Mode setting to Game.
This makes some small changes to the build process including enabling arm_shaderload
which packages the shaders as a sub-folder of the game data instead of building them into generated krom.js
file.
The other change to the build is that certain classes can be exposed to mods. The Expose Classes
option in the screenshot above shows an example regex that exposes all classes in the Kha, Iron, and Armory APIs to mods. Any valid regex can be used to control which classes are exposed.
Running The Game
If you run the game as it is right now, everything should work fine and you would hardly know anything was different. Perfect .
Mods
So now that you have a moddable game you need to make a mod for it? Well, what exactly is a mod?
Mods are just Blend files, like any other Armory game, with the modding mode set to Mod. They contain objects and scenes and nodes and Haxe just like any other Armory game. The build process is also nearly identical to building games. The only difference is that the krom.js
file exported by building a mod only contains code that is specific to the mod.
So, if Armory mods are pretty much the same as Armory games, how does a mod, you know, “mod”, a game?
As you saw earlier, when you make a game moddable, you specify classes that will get exposed to mods. When a mod runs, you can use those exposed classes to register hooks, change settings, or do whatever the exposed API lets you do. Additionally, any scene that is created in a mod’s blend file can be loaded by the game. This means that characters, weapons, or maps can be implemented as mods and loaded dynamically into the main game.
Making a Mod
As I’ve already explained, mods are just Armory games so all you have to do to get started is create a blend. A sensible place to put this blend would be in a Mods
subfolder of your main game so you have something like:
mygame/
mygame.blend
Mods/
mod1/
mod1.blend
mod2/
mod2.blend
In the Armory Project panel set the modding mode to Mod and set the armory package name to the name of the mod:
You will also need to set the Game Blend
path to the blend file for the game that you want to mod. This simply lets it know where to install the built mod.
In your mod you can create a new object, change its material, and add a Logic Node trait that makes it move.
If you click Play or press F5 to build the mod now, it will build and leave a message in the console without running the game:
Done.
Finished in 15.975870609283447
Mod was built and installed at: " ../../build_moddable_game/debug/krom/Mods/mod1 "
Magic!
But it doesn’t do anything. We’ll get to that.
Loading Mods
OK, now that we have a game and a mod, we just need to load the mod into the game. In this instance that simply means switching the scene from the scene in the game to the scene in the mod. We just have to create a quick Haxe trait for the game:
package arm;
import armory.system.Modding;
import iron.Scene;
import iron.system.Input;
class LoadMod extends iron.Trait {
public function new() {
super();
notifyOnInit(function() {
Modding.loadModsFromListFile("enabled-mods.txt", () -> {
trace("Mods Loaded!");
});
});
notifyOnUpdate(function() {
if (Input.getMouse().down() == true) {
Scene.setActive("Mods/mod1/Scene");
trace("Switched Scene!");
}
});
}
}
In the init function we use a utility that loads all of the mods that are listed in an enabled-mods.txt
file. This is to get around an issue where the haxe.sys
package is not implemented in Krom yet and I don’t have a way to get a list of mods in the Mods
folder. Loading the enabled mods executes the krom.js
file from all listed mods, which adds all of their traits, like the trait we use to move the monkey head.
You can now run the game! The game will run, and when you click with the mouse, the game will load the scene out of the mod and you should see our spinning monkey head!
Notes
If you have any thoughts, tell me what you think about the setup. Like I said I still have a minor issue to work out and I’m going to open another topic about that, but I have gotten exactly what I just described to work so everything is looking promising and going very well.