Mod Scripting
Mod Root
Essentially every mod needs a Mod Root class definition. This is your hook into the mod activation and deactivation events, as well as additional hooks.
Your mod root class can be anywhere in the mod's Scripts folder within a .cs file.
There are two main methods you probably want to override:
Initialize(string id): Called when the mod is initialized. This happens on boot (if the mod is active), or whenever the mod is activated.
Uninitialize(string id): Called when the mod is uninitialized. This happens whenever the mod is deactivated.
Barebones Example:
using Ardenfall;
using UnityEngine;
using System;
namespace ExampleMod
{
public class ExampleMod : ModRoot
{
public override void Initialize(string id)
{
base.Initialize(id);
Debug.Log("Loaded Example Mod! WOW!");
}
public override void Uninitialize()
{
base.Uninitialize();
Debug.Log("Unloaded Example Mod! WOW!");
}
}
}Mod Saving
By default, mods do not save custom data. But you can do it!
Override the following methods:
void CreateState(): Run when a new game is made, or when the mod is loaded for a save for the first time. Use this to initialize a default state.
void LoadState(string state): Load your state from previously saved data.
string SaveState(): Save your state to a string.
If you want to serialize data, you can use JsonUtility, or whatever other serializer you get your hands on, as long as its a string.
Example of a mod that saves state.
using Ardenfall;
using UnityEngine;
using System;
namespace ExampleSaveMod
{
public class ExampleSaveMod : ModRoot
{
private float randomNumber;
public override void Initialize(string id)
{
base.Initialize(id);
Debug.Log("Loaded Example Mod! WOW!");
}
public override void Uninitialize()
{
base.Uninitialize();
Debug.Log("Unloaded Example Mod! WOW!");
}
public override void CreateState()
{
randomNumber = UnityEngine.Random.value;
}
//Save state. You can save it as json or any format, it just needs to be a string.
public override string SaveState()
{
var state = new ExampleModSaveState()
{
randomNumber = randomNumber
};
return JsonUtility.ToJson(state);
}
//Load the state as a string.
public override void LoadState(string jsonState)
{
var state = JsonUtility.FromJson<ExampleModSaveState>(jsonState);
randomNumber = state.randomNumber;
Debug.Log(randomNumber);
}
}
[System.Serializable]
public class ExampleModSaveState
{
public float randomNumber;
}
}Debugging Mods
TODO (IMGUI Debugging)
TODO (Graph Debugging)
Lookup Table Registration
To register or modify assets, you can hook into the lookup table initialization step.
The Lookup Table is a big list of assets that is commonly used in the engine, tied to an id. Beyond modding, it's used by the save system - any asset that is referenced in the save file (such as an item in the inventory) must be registered to the lookup table. The lookup table does not contain EVERY asset, however.
If you ever run into needing a certain asset in the lookup table, throw me (joshcamas) a message on discord.
Non scripting methods to create/modify assets is planned in the future.
Example of creating a new asset and registering it to the lookup table
TODO
Lookup Table Tools
TODO
Records Registration
You may also want to create Records with your mods. Records are objects in the world that can be accessed / manipulated at any time. The most common Record is the CharacterRecord, but there are others.
TODO
NOTE: If a mod spawns or modifies a record, and then the user disables the mod, this record will still exist in old save files. No immediate solutions for this, since players should expect odd things to happen when disabling mods and then loading an old save.
Mod Version Patching
TODO: Add built in Mod Version Patching Support
Mod Settings
TODO: Add Mod settings support.
A note on Hot Reloading / Refreshing
Ardenfall's modding systems supports hot reloading. That is to say, reloading the mod without restarting the game.
The mod user can always turn your mod on and off in the main menu, and you should ensure your mods correctly clean up during this state, otherwise it will cause problems for your users. However, users should expect weird things to occur on old save files that used to have the mod, of course.
As a mod developer, you can also turn your mod on and off / refresh it while actually playing the game. You don't officially need support for this (no one will know) but making your mod work in this circumstance as much as possible is great from a developmental standpoint - you can super quickly work on your mods without needing to restart the application, or even maybe not reloading the save file sometimes.