I'm Adding Modding to Armory! ( Similar to Prefabs )


#1

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.

image

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 :sunglasses:.

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:

image

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! :sparkles:

But it doesn’t do anything. :frowning: We’ll get to that. :slight_smile:

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.


[Solved] Why Can't I --macro include() Kha, Iron, or Armory ( Help me fix modding! )
#2

@zicklag looks like great work. Thanks for sharing. This could be big for building things a team if I understand it right. One person could work on main mechanics while others build levels as Mod’s. Do I understand that right?


#3

Yes, you can split out different levels, characters, weapons, etc. into different mods to make it easier to work on separately. Any scene should be able to be loaded from a mod the same as from the same game blend.

Armory does already have a Proxy setup that could help with this as well.


#4

Awesome - Well done sir.


#5

Thank you! :smiley: I just have to make it over this last ( I think ) hurdle.


#6

It is like replacing the main scene with the scene from the mod , this doesn’t mean modding ?
Modding is modify elements in the main scene, for example add a hat to a character, or change some building texture, or add buildings to the scene.

This should be automated , there is no need to code when you make mods for a game.
The game auto detect if there is mods, and auto load them.
Armory auto detect is there is mod enabled and enables the mod script.
When “mod” button is enabled, Armory check for mods automatically in some Blender list.

All mods must be in some Blender list, some new Blender tab or window.
You add mods with + / - buttons and select a file.
This is the modern way to edit things instead of using text files directly.

I mean, mod should be like those you make for games like fallout, as easy to import and include, all automated, add mods in a Blender list, no coding.

Well perhaps how you made it, is the way it should work in Armory to make game mods.
Some games doesn’t need mods.


#7

That wasn’t a particularly good example of modding, that was just the easiest. By switching the scene, I demonstrate the ability to load scenes outside of the original game with the included code and logic nodes. You can use this for any number of different ways to mod the game. That loaded scene could represent a new weapon that you can now use with your character, or it could represent a new map that you can play on, or a new character you can play as.

If you want to do stuff like changing textures of buildings or adding accessories, that is completely possible, but you do have to add the code or API’s to the game so that mods can call the APIs to register accessories or whatever else you want to change.

Note: It could also be possible to do code patching to replace portions of the original game code in the mod. I haven’t tried that yet.

You are correct that you shouldn’t need to code to make mods for the game game, but a game may need some extra code to facilitate the ability to mod it. You may want to load different mods at different times, or you may want to provide a modding API that mods can use to change the game. These things would require extra code written for the game.

It is a good point that it would be nice if there was a checkbox or something so that you could say “load all mods at startup” and it would add the most basic setup code for you, but that is currently blocked by the next point.

Yes it definitely should be able to do that. Right now, like I said, Krom doesn’t have the ability to list folders on the filesystem, so I had to come up with a temporary alternative. I’m not real C++ savvy so I wasn’t able to add the feature to Krom yet.

I don’t think that the mods should be listed in Blender. It kind of defeats the point of modding if you have to edit the game to add a new mod. Mods need to be discovered at runtime so that you can have a fully compiled and static game, add your mod to the Mods folder, start the game, and your mod will be automatically available in the game.

Any UI for a mod list should be implemented in the game, not in Blender. Still, we need the ability to list files in Krom to do this. That is the largest hole whole in the setup at the moment, but it is perfectly fixable.


#8

I think it is just about working! I’m going to finish and push my example tomorrow. I am not aware of anything that is broken at the moment. There are maybe a few different kinds of objects that won’t load correctly from mods ( like speakers, etc. ), but those are very easy fixes.

This picture shows two mods that have been spawned into a game scene.


#9

That looks great, but i am thinking a cheatcode system in game kinda like GTA, where you type comeflywithme and all cars are flyable. How do i implemented this, i know i can do it by typing the cheat and if it is same as one stored in code then the cheat is activated, but I don’t know how do i get input.


#10

So you want to make a mod that adds a cheat code?

You can get whether a keyboard button has been pressed like so:

iron.system.Input.getKeyboard().started("a");

If you just do that onUpdate then it should be easy to get the cheat code.


#11

I just pushed a modding example to GitHub:

It requires my forks of iron and armory on the branch modding-workflow.

I’ve got open PRs: iron#49, armory#969.


#12

Wow! this is incredible! I found this by coincidence but I must say this is something I’ll need for my future game, I really hope this gets into armory by default, but in case not, I wish you keep maintaining it :slight_smile:


#13

So glad you like it! It is a core feature that me and my team will depend on for our games, so if we can successfully start our game business then we will be able to keep this maintained. I definitely hope that it can get into Armory officially, though. For now I am using it with in my game demo, and I update Armory almost every day, so until it gets merged it should keep running well with the latest Armory.


#14

I hope that you do … because I can’t base my business around "more-than-one Armory." If it really is a wonderful feature, you need to persuade the powers-that-be to get it into the one and only core. I can’t afford to “chase ‘forks’ around.” Just saying.


#15

Don’t worry, that is fully my intention. :slight_smile: Knowing that there are more community members that also want the feature will make a difference. At the moment, Lubos is busy trying to get 0.6 out and it isn’t just a minor change so it will require more review than normal. I’m going to wait until 0.6 is released before trying to get his attention.


#16

Hi there,

I commented on GitHub about this, good stuff, keep up the great work.


#17

This is not a critical component of virtually any game that is more than a simple, single screen experience. It’s just not practical to make anything but the very smallest of games without the ability to bring in assets from external files, so I for one am extremely grateful you’re working on this!

I notice in the Github roadmap that @lubos has written down a prefab system being the main focus of 0.7. I’m guessing that that’s in anticipation of merging this?

PS. Describing this as just “Modding” is selling this feature short, in my opinion. It seems to me that really you’re talking about the ability to create and (re)use prefabs similar to in unity or even the BGE. Modding usually implies just modifying a pre-existing game. To me at least, this is a crucial part of creating the underlying game in the first place…

When I first saw this thread’s title I skipped over it as I’m interested in game dev, not basic modding, when actually what you’re describing is my #1 wish for Armory right now!


#18

Prefab system is not modding.

http://forums.armory3d.org/t/armory-prefabs-discussion/2133/5


#19

@Armored_Blob I’m glad you like it! Be aware that it only works for Krom at the moment, but I plan on integrating it with C builds that can run on consoles soon ( though you won’t be able to load “mods” dynamically like you can through Krom ).

It still might need a little bit of polish, and linked proxies might be a little more appropriate to some use-cases, if you want to be able to see included objects in your scene in Blender. Proxies get closer I think to a typical prefab system, and I’m still figuring out how the “modding” setup works in practical use, but I’m working on it as I discover what is needed and I’m glad to see people interested! :slight_smile:

PS. I’ll update the title to be more inclusive.