Home

Getting Started

This guide walks you through creating your first mod for Fall of an Empire, from setting up the folder structure to seeing your content in-game.

Prerequisites#

  • Fall of an Empire installed
  • A text editor (VS Code, Notepad++, or any editor with syntax highlighting)

No special tools or SDKs are required. Mods are written in AngelScript, a scripting language that compiles at game startup.

Creating Your Mod#

1. Create the Folder

Create a new folder inside the Mods/ directory at the root of the game installation:

File Structure
Mods
MyFirstMod

The folder name becomes your mod's internal ID.

2. Add mod.json

Create Mods/MyFirstMod/mod.json with your mod's metadata:

json
{
    "id": "my_first_mod",
    "name": "My First Mod",
    "version": "1.0.0",
    "author": "Your Name",
    "description": "A simple mod to learn the basics.",
    "load_order": 100,
    "dependencies": [],
    "incompatible": []
}

Field reference:

FieldTypeRequiredDescriptionidstringYesUnique identifier for your mod. Use lowercase with underscores.namestringNoDisplay name shown in the mod list.versionstringNoSemantic version (e.g., "1.0.0").authorstringNoYour name or team name.descriptionstringNoShort description of what the mod does.load_orderintegerNoLoading priority. Lower numbers load first. Default: 100.dependenciesstring[]NoIDs of mods that must be loaded before this one.incompatiblestring[]NoIDs of mods that conflict with this one.

Load order ranges:

RangePurpose0Base game (reserved)1--50Core framework mods51--99Content base mods100--199Standard mods (default)200+Patches and overrides

3. Create the Directory Structure

Organise your script files by content type:

File Structure
Mods
MyFirstMod
mod.json
Script
Traits# Character traits
Buildings# Settlement buildings
Units# Army units
Events# Scripted events
Interactions# Person, diplomacy, spy, power bloc
...
Content# DataTables, textures (optional)
Data
TraitIcons# Icon DataTables (optional)

You only need to create directories for the content types you are adding. The Script/ directory is discovered automatically by the mod loader.

AngelScript Basics for Modders#

AngelScript is the scripting language used by Fall of an Empire. It resembles C++ but with several simplifications. Here are the essentials you need to know.

Class Declaration

Every moddable content type is a class that extends a base type:

angelscript
UCLASS()
class UMyTrait : UTrait
{
    // Properties and methods go here
}
  • The UCLASS() decorator registers the class with the engine.
  • Class names must start with U (for UObject-derived types).
  • No semicolons after the closing brace of a class.

Setting Default Properties

Use the default keyword to set class default object (CDO) properties:

angelscript
default TraitName = Localization::GetText("MyMod", "MyTrait_Name");
default Authority = 10.0f;
default bCanBeGained = true;
default IconKey = n"MyTrait";

These are evaluated once when the class is loaded, not per-instance.

Constructors

Constructors are used for operations that cannot be expressed as simple default assignments, such as adding to arrays or maps:

angelscript
UMyTrait()
{
    ConflictingTraits.Add(USomeTrait::StaticClass());
    ResourceCost.Add(n"Iron", 15.0f);
}

Overriding Methods

Override base class methods using UFUNCTION(BlueprintOverride):

angelscript
UFUNCTION(BlueprintOverride)
bool CanBeGained(UPerson Character) const
{
    return Character.Stats.GetAuthority() > 60.0f;
}

FName Literals

Many identifiers in the engine use FName, a lightweight hashed string. In AngelScript, create them with the n"..." syntax:

angelscript
default IconKey = n"MyTrait";
RequiredConditions.Add(EContextSlotType::AtPeace);
ResourceCost.Add(n"Iron", 15.0f);

Localised Text

All user-facing text must use the localisation system. Never use hardcoded strings.

angelscript
// Get localised text (returns FText)
Localization::GetText("Namespace", "Key")

// Convert to FString for string operations
Localization::GetText("MyMod", "Description").ToString()

// Dynamic text with placeholders
Localization::GetText("MyMod", "Effect").ToString().Replace("{Bonus}", "" + Bonus)

The first argument is the namespace (use your mod ID), and the second is a unique key. You will add the actual text to a PO file later (see Assets & Packaging).

Arrays and Maps

AngelScript arrays and maps use methods rather than initialiser syntax:

angelscript
// Arrays
TArray<FName> MyArray;
MyArray.Add(n"Value");

// Maps
TMap<FName, float> MyMap;
MyMap.Add(n"Key", 1.0f);

// Checking map contents
if (MyMap.Contains(n"Key"))
{
    float Value = MyMap[n"Key"];
}

Common Types

TypeUsageFTextLocalised display text. Use for anything the player sees.FStringGeneral-purpose string. Use for internal operations.FNameHashed identifier. Use for keys, tags, and lookups.int3232-bit integer.floatFloating-point number. Append f to literals: 1.0f.boolBoolean. true or false.TArray<T>Dynamic array.TMap<K, V>Key-value map.TSubclassOf<T>Reference to a class type. Use UMyClass::StaticClass().

UObject References

In AngelScript, UObject types are automatically references (no pointers):

angelscript
// These are references, not pointers
UPerson Character;          // Not UPerson* Character
AFaction PlayerFaction;     // Not AFaction* PlayerFaction

// Null check with nullptr
if (Character != nullptr)
{
    // Use dot syntax, not arrow syntax
    Character.Stats.GetAuthority();
}

Accessing the Player Faction

angelscript
AFaction PlayerFaction = StrategyGameplay::PlayerFaction;

Tutorial: Creating a Trait#

Let's create a complete trait from scratch. This trait, "Stoic", will grant governance and loyalty bonuses to characters with high constitution.

Step 1: Create the Script File

Create Mods/MyFirstMod/Script/Traits/Stoic.as:

angelscript
UCLASS()
class UStoic : UTrait
{
    UStoic()
    {
        ConflictingTraits.Add(UTimid::StaticClass());
    }

    // Display properties
    default TraitName = Localization::GetText("MyFirstMod", "Stoic_Name");
    default Description = Localization::GetText("MyFirstMod", "Stoic_Description");
    default SortOrder = 10;
    default IconKey = n"Stoic";

    // Generation properties
    default Heritability = 0.15f;   // 15% chance to inherit from parent
    default Probability = 0.08f;    // 8% base generation chance

    // Stat modifiers (added to character's stats)
    default Tactics = 0.0f;
    default Authority = 0.0f;
    default Cunning = -5.0f;
    default Loyalty = 10.0f;
    default Governance = 10.0f;
    default Constitution = 5.0f;

    // Gain/loss behaviour
    default bCanBeGained = true;
    default bIsTemporary = false;

    // Event shown when the trait is gained
    default GainedEvent.Title = Localization::GetText("MyFirstMod", "Stoic_GainedTitle");
    default GainedEvent.Message = Localization::GetText("MyFirstMod", "Stoic_GainedMessage");
    default GainedEvent.Option = Localization::GetText("MyFirstMod", "Stoic_GainedOption");

    UFUNCTION(BlueprintOverride)
    bool CanBeGained(UPerson Character) const
    {
        // Only characters with high constitution can gain this trait
        return Character.Stats.GetConstitution() > 60.0f;
    }

    UFUNCTION(BlueprintOverride)
    bool CanBeLost(UPerson Character) const
    {
        return false;
    }
}

Step 2: Add Localisation Strings

Create or edit a PO file for your mod. For now, you can add entries directly to Content/Localization/Game/en/Game.po (see Assets & Packaging for details on the PO format):

po
#: MyFirstMod,Stoic_Name
msgctxt "MyFirstMod,Stoic_Name"
msgid ""
msgstr "Stoic"

#: MyFirstMod,Stoic_Description
msgctxt "MyFirstMod,Stoic_Description"
msgid ""
msgstr "This character maintains composure under pressure, earning respect through steady governance."

#: MyFirstMod,Stoic_GainedTitle
msgctxt "MyFirstMod,Stoic_GainedTitle"
msgid ""
msgstr "A Quiet Strength"

#: MyFirstMod,Stoic_GainedMessage
msgctxt "MyFirstMod,Stoic_GainedMessage"
msgid ""
msgstr "Through years of measured decisions and calm resolve, this character has earned a reputation for unshakeable composure."

#: MyFirstMod,Stoic_GainedOption
msgctxt "MyFirstMod,Stoic_GainedOption"
msgid ""
msgstr "A valuable quality."

Step 3: Test Your Mod

  1. Launch the game.
  2. Start a new campaign.
  3. Your trait will appear in the trait pool and may be assigned to newly generated characters whose constitution exceeds 60.

To verify the mod loaded correctly, check the log file at Saved/Logs/FallOfAnEmpire.log for:

  • LogModLoading: Discovered mod: MyFirstMod -- confirms the mod was found
  • LogAngelscript: Compiled module messages -- confirms scripts compiled
  • LogGameData: Discovered X Trait classes -- confirms your trait was registered

How Auto-Discovery Works#

When the game starts, UGameDataSubsystem calls GetDerivedClasses() for each base type (UTrait, UBuilding, etc.). This finds every class in the entire class hierarchy -- including those defined in mod scripts. Your class is registered alongside the base game classes with no additional setup.

This means:

  • You do not need to register your class anywhere.
  • You do not need to modify any configuration files.
  • The class name itself is the unique identifier.

Common Mistakes#

ProblemCauseFixClass not discoveredMissing UCLASS() decoratorAdd UCLASS() above the class declarationScript compilation errorSyntax differences from C++Check for missing f suffix on floats, wrong string types, or pointer syntaxText shows as key namesMissing PO file entriesAdd entries to Game.po and run the import/compile commandsConflicting class namesAnother mod uses the same class namePrefix your class names with your mod name: UMyMod_StoicTrait never appearsCanBeGained() returns false for all charactersLower the stat threshold or check your condition logicIcon not showingWrong IconKey valueEnsure the key matches a row in the TraitIcons DataTable (see Assets & Packaging)Array/map compile errorUsing initialiser syntaxUse .Add() instead: MyArray.Add(Value)Cannot call Super:: methodParent class is C++Inline the parent logic instead. Super:: only works when the parent is also AngelScript.

Next Steps#

  • Content Types -- Full property and method reference for all content types
  • Interactions -- Create diplomacy, espionage, and character interactions
  • Events -- Build scripted events with branching options
  • Assets & Packaging -- Add icons, package your mod, and distribute it