Create mod packs

From Of Life and Land Wiki
Jump to navigation Jump to search
Icon CreateModPacks.png

You've created custom 3D models, balanced the game, added a new language, created a new scenario, offer new settings or created new shaders?

Wonderful! You can share most modification directly with friends without additional effort, simply by placing the files in the right location. However, this is not always enough. Extended rights are required to make far-reaching changes. And may be you want to make the custom content available to everyone, for example in the Steam Workshop. Please follow the Steam rules and the rules for modding the game.


Create a mod package

Of Life and Land uses the Godot Mod Loader to load mod packages. You can find their wiki here with all the basics. Important: Of Life and Land was developed with Godot Mono and does not require a GodotSteam build to create mods.

To get started with mod packages, you need to create two files to tell the Godot Mod Loader what to do:

  1. manifest.json
  2. mod_main.gd

Navigate to your game files and create a folder called "mods-unpacked". There create a folder with your author name, add a minus and add your mod name. E.g. "AuthorName-ModName". In this new folder, create the two files above. As a reference, there is an example mod with all files you can use as a starting point or to compare.


manifest.json

This json contains the basic information what your mod is and how it should be treated. You can find more infos here.

Example from the demo mod:

{
	"name": "ModName",
	"namespace": "AuthorName",
	"version_number": "1.1.0",
	"description": "Example mod description",
	"website_url": "https://steamcommunity.com/app/1733110/workshop/",
	"dependencies": [],
	"id": 0,
	"extra": {
		"godot": {
			"authors": ["Author"],
			"optional_dependencies": [],
			"compatible_game_version": [],
			"compatible_mod_loader_version": [ "6.2.0" ],
			"incompatibilities": [],
			"load_before": [],
			"tags": ["Scenario", "Map", "Localization"],
			"config_schema": { },
			"description_rich": "Example mod rich description",
			"image": null
		}
	}
}

Replace the values with the values you need.

  • The "id" is only important if you are uploading a mod to the Steam Workshop. Leave it at 0 and as soon as you get an ID, copy it into this field so you don't lose it. It is the same ID as the URL in the Workshop for your item. You can also set the ID in the upload UI.
  • You can add tags to your mod. They must match the tags in the workshop.
  • There are as well advanced things you can do. See here.


mod_main.gd

This GDScript file is the entry point where you can tell the engine what you want to do. Here you can load translations, edit scenes, call methods, create events, change values - basically anything you want. You can find the GDScript reference here.

Example from the demo mod:

extends Node

const AUTHORNAME_MODNAME_DIR = "AuthorName-ModName/" # name of the folder that this file is in
const AUTHORNAME_MODNAME_LOG_NAME = "AuthorName-ModName" # full ID of your mod (AuthorName-ModName)

var mod_dir_path := ""
var extensions_dir_path := ""
var translations_dir_path := ""

func _init() -> void:
	mod_dir_path = ModLoaderMod.get_unpacked_dir().plus_file(AUTHORNAME_MODNAME_DIR)
	install_script_extensions()
	add_translations()
	install_virtual_files()

func install_script_extensions() -> void:
	extensions_dir_path = mod_dir_path.plus_file("extensions")
	# ModLoaderMod.install_script_extension(extensions_dir_path.plus_file(...))

func add_translations() -> void:
	translations_dir_path = mod_dir_path.plus_file("translations")
	ModLoaderMod.add_translation(translations_dir_path.plus_file("modname.en.translation"))
	ModLoaderMod.add_translation(translations_dir_path.plus_file("modname.de.translation"))
	ModLoaderMod.add_translation(translations_dir_path.plus_file("modname.de_CH.translation"))

func install_virtual_files() -> void:
	var zip_file_path = mod_dir_path.plus_file("res.zip")
	var result = ProjectSettings.load_resource_pack(zip_file_path)
	ModLoaderLog.info("install_virtual_files result: " + str(result), AUTHORNAME_MODNAME_LOG_NAME)

func _ready() -> void:
	ModLoaderLog.info("Test Mod Ready!", AUTHORNAME_MODNAME_LOG_NAME)
	ModLoaderLog.info(str("Translation Demo: ", tr("MODNAME_READY_TEXT")), AUTHORNAME_MODNAME_LOG_NAME)
A new scenario with localized text, provided by the example mod.

In this file we add new languages and add new text to the game in add_translations, we add files in res.zip to the engine's virtual file directory in install_virtual_files, and we could add script extensions in install_script_extensions.

_ready is optional and will be called by the engine. We print some text to the logfile and test our translation.

As this script extends a Godot Engine node, we can do whatever is necessary to get our mod to run. We could add a _process(float delta) method that is called by the engine on every frame, or we could instantiate new scenes with new nodes that also have new scripts that do their thing. Basically, we could add a Tetris mini-game without much effort.


Add a new language or new text

You can add new languages, create new keys to translate or fix existing translations. In the example repository you will find modname.csv which follows the Localization schema. When we open the Godot Engine and set the correct import setting by choosing ';' as a delimiter, localization files are created. These files can be loaded in mod_main.gd.

Add a new scenario

Creating a new map and a new scenario for the example mod.

With the World editor we can edit or create maps, we can edit the scenario, Create, import or export maps or edit the mission file. As soon as we have all files together, we can zip them respecting the relative path to the base game (so that they have the same path when you would unpack it in the game base directory). See mod structure

In the example mod we packed a custom scenario in res.zip which can be loaded in the mod_main.gd. This is already everything we need to do.


Load custom content

Similar as in Add a new scenario, we can override any file we want. For example meshes, scenes, images etc. But of course if we provide a file that does not exist you, it simply is added to the virtual memory an can be loaded and used.

For more fine grained control, you can load and configure assets by code.


Further reads

As Of Life and Lands use the same mod loader as Dome Keeper or Brotato, you can have a look to their guides and examples.


Loading a package

If enabled in the options, mod packages are loaded in /mods and as well in ../../workshop/content/*. So you can load mods by placing the zip in a folder called "mods" right next to your executables. But it will as well automatically load mods from the workshop.


File loading order

The loading sequence is generally as follows:

  1. Base game files
  2. Mod files
  3. Real local files in your directory

The general mod loading order is defined according to the manifest.json specification.

Upload a mod

You can still edit almost everything in Steam. You can find the ID in the URL to be able to update the content.

You can upload a mod in the game settings. Make sure it matches the mod data structure and follows the Steam workshop rules and the rules for modding the game.


Instructions

  1. Select the mod you want to upload (only *.zip)
  2. Select a preview image if it's the first time uploading the mod or if you want to change it
  3. Add the mod's workshop ID if you're updating it, leave empty if it's a new mod
  4. Check your tags and infos
  5. Upload it and take note of the workshop ID if it's a new mod. Use it when you want to update it
  6. Check and edit your mod in the Steam Workshop, then set it public when it's ready