Modding Guide

From APICO Wiki
Jump to navigation Jump to search

To get started with creating mods you don't need to do anything special! You just need a basic understanding of LUA and your favourite code/text editor, as well as our handy API Reference.

You can submit your mod directly to the Mod List with this form.

If you want to make your mod "official" and directly visible in-game you need to get it approved through the APICO Modloader. Although players can choose to side-load any mod they download, they will get shown a warning around the mod when activated.

Modding

Getting Started

Language

As mentioned earlier, mods are written in LUA! All standard LUA libraries are available to use except io and os for security reasons. If there is something you specifically need let us know and we can look into a way of exposing it through the API! The LUA interface we are using into GameMaker is Apollo.

If you haven't written LUA before there are definitely a few quirks you'll have to get used to! Here's some common gotchas we have come across:

  • In LUA "not equals" is ~=, not !=. Using != will cause a compile error with no useful message
  • IF statements follow the format of if SOMETHING then SOMETHING end - missing the "then" will throw a compile error with no useful message
  • Lists start at 1! If you use list[0] somewhere you'll probably get "invalid key to 'next'" as you need to be using list[1] instead
  • If you see an "attempt to add a 'string' with a 'string'" error it means you used + instead of .. for string concatenation.

We recommend using the Online Lua Compiler to test the syntax of your LUA code before running it in APICO

If using VSCode, you can also use an extension like Lua Language Server to detect issues as you type

Process

In the game, a player can choose the mods they want to load from the home screen. They'll be able to download any of the official mods and choose which downloaded mods they want to activate or deactivate. When they load their game the mods will be loaded in the following processes:

  • First when the game loads it checks that the mods folder exists (where saves are stored), and if not it creates one
  • Then the game gets all the currently "active" mods from the players settings.json file
  • When the player picks a save file the game goes through each of these active mods and attempts to compile the main mod.lua file for each mod.
  • If the mod compiled successfully, the game tries to call the mods register() and init() methods, as well as adds in any Hooks the mod creator has specified
  • Once all mods have loaded the game calls the ready() hook for any mods that have subscribed to it, and then finally loads the save.
  • Any "undefined" instances in the player save file (created by mods) are refreshed at this point.

As mods are only loaded when the save file is clicked, you can make changes to your mod code up until that point. After that you can use CTRL+SHFT+R to reload the game without having to save + quit.

Mod Structure

For mods to work they need to follow a basic structure so that APICO can register and load mods correctly, as well as handle any errors that might occur when trying to compile your code.

For local development you simply need to add your mod folder into the /mods/ folder. This will be found in your local data folder on your computer, along with the game's save data i.e. %localappdata%% on windows. An example structure would look like this:



A breakdown of the above files is as follows:

File/Folder Description
saves save folder created automatically by the game
mods mod folder created automatically by the game (after loading 1.1+)
mods.txt autogen file created by the game to setup the mods folder
sample_mod your mods folder that you added, with the same name as your mod ID used in register(). When the game is live, mods downloaded by the player will automatically be created as folders like this example
mod.lua the main event, this is the file the game will load - you can require other files inside it
data.json when using api_set_data() or api_get_data() this is the file loaded / saved
modules you can put other folders inside your mod folder, in this example a folder to store other lua files
utility.lua an example of another lua file that you could require() in your mod.lua file (see below)

For local development you will also need to add your mod ID, i.e. sample_mod to the settings.json under the both download_mods and active_mods key. Your mod ID should be lowercase!. If it worked you'll see your mod show in the Mods section on the home screen.

The folder name should be your mod ID, (in the above case sample_mod and then every mod needs to start with a mod.lua file at the root of your mod folder. This is the main file that initially gets loaded - a basic mod file would look something like this:

function register()
  return {
    name = "sample_mod",
    hooks = {}
  }
end

function init() 
  api_create_log("init", "Hello World!")
  return "Success"
end

When the game loads, it'll retrieve the player's mod settings to get a list of all active mods. It will then try and init these mods through the sc_init_mod() method that you'll see in the Modding Console.

This method will first try and call a register() method in your mod, which will check for duplicate names, and will then call an init() method.

Your init() method is a place for you to setup all mod code you need at the start, and needs to return either Success or an error message - this lets the game know if your mod loaded correctly.

If there are any errors while trying to define an item you'll see one of the following codes logged in the Modding Console

Error Description
Mod Failed To Init this means your mods code could not be compiled correctly! You'll also see related LUA errors logged after this error message that should help narrow down the issue
Duplicate Mod Registered this means the mod id you have provided is already registered by the game, try a different mod id
Mod Failed To Load this is shown if your init() method does not return "Success", allowing you to debug your mods setup

Modding Console & In-Game Console

The Modding Console is a debugging tool available by pressing CTRL+. and it shows all messages from both the Modding API itself as well as any logs or errors from individual mods



When enabled with api_set_devmode() the In-Game Console is an inline command runner you can use while playing the game by typing / followed by a command.



For example to spawn in 5 logs you'd use /gimme log 5
You can create your own commands with api_define_command()