Modding

From FA Forever Wiki
Jump to: navigation, search

Introduction

Supreme Commander is extensible by mods, which can alter the whole gameplay (like PhantomX for example), change the balance of units, display information to the user or make the user automatically do things like renaming units or send messages to his allies when he starts upgrading. This is a page for you to get a basic idea of modding FA.

See also Tips for Modding Efficiently.


What we need

  • The Supcom FA installation files
  • A texteditor, preferably one with syntax highlighting. Notepad++ or Sublime do fine, a full IDE like IntelliJ with a LUA plugin is fine aswell
  • Basic LUA knowledge


Basic information

  • Supcom FA is using LUA
  • Mods are usually stored in C:\Users\%USERNAME%\Documents\My Games\Gas Powered Games\Supreme Commander Forged Alliance\Mods
  • Every mod needs a mod_info.lua file in its folder, containing infos such as Name, Description, UID etc.
  • Mods usually have a hook folder (usually /hook, can be configured to have another path in the mod_info) which contains all files that the user is hooking to (overwriting or adding code)
  • There is a SIM and a UI mod category. Sim mods affect everybody and usually alter the gameplay, so as example PhantomX and any balancemod is a sim mod. UI mods don't affect other players (directly), as example notify is messaging them about your upgrade, but it's not altering their game
  • The game files (.scd) aswell as the FAF mod files (.nx2, ...) are all just renamed .zip files. You can copy them somewhere to work with, rename their extension and unzip them to see their content.
  • You can use the default hotkey F9 to open the live LOG in your game, and use LOG(text), SPEW(text) or WARN(text) in your code to print to it


Other sources


Differences to default LUA

There are some things different to default LUA:

  • The # sign is used to comment in FA, the #mytable operation to get its length is not possible, you can use table.getn(mytable) instead
  • it's not necessary but still possible to use "for i, v in ipairs(mytable) do", "for i, v in mytable do" works aswell


Sim and UI

Sim UI communication
Basic communication.

Basically, this game is divided in two interacting components, Sim and UI. Both are moddable, here some info:

  • The Sim (simulation) of the game happens for every player and is deterministic, so the same input will always yield the same result, that is why the players in a multiplayer game usually do not desync. Many mods introduce changes that affect all players equally, every balance change does this.
  • The UI (user interface) component only has a part of the information that the Sim side is calculating. For example which units the user has, their health and vet points, and what they are ordered to. Orders about your opponent's units are also calculated on your PC, in the Sim, but your UI has no info about it. The UI also displays these infos, resulting for example in the ecopanel or the scoreboard.

Both sides are interacting, to keep the user updated about what's happening to his (and his allies') units, and to inform the Sim about what orders the user issued. This is done via two files:

  • SimCallbacks.lua is used by UI operations to inform the Sim about something it should know (commands, pings, ...)
  • UserSync.lua is used by the Sim to inform the UI about something it should know (eco, unit info, pings from teammates, ...)


Basic examples

A simple mod_info.lua

Explanation

name: mod name
uid: an ID every mod needs, you can generate a random one for example here: https://www.uuidgenerator.net/
version: use a versioning pattern of your choice, the current FAF mod vault will only display a single integer though
copyright: mention how you want copying to be treated
description: mod description
author: your name
url: if you have one, for example a forum thread that you could be making to show us your mod
selectable: true|false : whether the mod should be selectable in the ingame lobby
enabled = true|false
exclusive = true|false:
ui_only = true|false: whether all players need to mod for the game to run. SIM mods are needed by everyone, UI mods not
requires = {}: table of requirements for your mod (for example "common mod tools"), enter the UIDs here
conflicts = {}: table of conflicts, this way the lobby will warn the player that they don't work together
before = {}: mods that will have to be hooked in before your mod is hooked
after = {}: mods that have to be hooked in after your mod

Filled example

name = "Tutorial Mod Info"
uid = "431a0114-92a0-11e5-8994-feff819cdc9f"
version = 1
copyright = "nah, just copy it"
description = "A new description"
author = "Myxir"
url = ""
selectable = true
enabled = true
exclusive = false
ui_only = true
requires = {}
conflicts = {}
before = {}
after = {}


Understanding Hooking

Our way into modding the game is hooking. Hooking in FA is basically file concatenation, that means that the file we're hooking to will be extended by our file.

Paths:

\lua\ui\game\selection.lua is a UI side file handling what happens when we (de)select units
C:\Users\%USERNAME%\Documents\My Games\Gas Powered Games\Supreme Commander Forged Alliance\Mods\examplemod\hook\lua\ui\game\selection.lua is the full path to my own file, how i hook it
"/mods/examplemod/" is the path the mod can find its own files later

Ok so now i want to hook that file, i have created an empty selection.lua in the path as mentioned above. As said, hooking is file concatenation, so my empty file will be added at the bottom of the original selection.lua. Now i can overwrite a function, let's take PlaySelectionSound, which is playing the sounds of a selection when you select something.

-- original selection.lua file
function PlaySelectionSound(newSelection)
	-- the newSelection parameter is the table of units
	-- original code not displayed
end

Let's say i want it to do nothing, so i can just destructively hook (overwrite) it completely in my own selection.lua:

-- my own selection.lua file in /mods/examplemod/hook/lua/ui/game
function PlaySelectionSound(newSelection)
end

As this is simple file concatenation, my own function has the exact same name of the original function, but is mentioned later and is thus overwriting it. In result, nothing happens, no sound is played.

If i want to add something, instead of overwrite, i can construtively hook the function by saving a reference and calling the "old" function via that

-- my own selection.lua file in /mods/examplemod/hook/lua/ui/game
local oldPlaySelectionSound = PlaySelectionSound
function PlaySelectionSound(newSelection)
	oldPlaySelectionSound(newSelection)
	-- here i can execute my own code
end


FAQ

Q: I can't find files in the /lua path which should be there! Where are they?
A: Likely in the mohodata or schook folders (.scd files), they are mounted to the /lua path aswell