SpellForce: Conquest of Eo

SpellForce: Conquest of Eo

Not enough ratings
Modding Guide for Developers
By ObG_Chris and 1 collaborators
Describes how to create mods for Spellforce - Conquest of Eo
   
Award
Favorite
Favorited
Unfavorite
Prerequisites
  • Know how to use the windows explorer.
  • Have a text editor which you can use to edit mod files.
  • Knowledge how to properly format JSON files.
Mods Location
All Spellforce - Conquest of Eo mods live in your users Documents folder under

My Games\Spellforce - Conquest of Eo\Content



The Content folder will not be created by default and needs to be created by you
Mod Layout
Each mod you create is a separate folder inside the Content folder.

Naming
The naming of the mod is important because all mods need to be put inside the Content folder, so choose the name accordingly. The recommended approach is a prefix identifying you or reverse domain notation if you have one.
Example: username.modname → JDoe.MyMod
Be sure to choose a unique name to avoid name clashes with any other mods.

Content Package Info
For the game to detect a mod there MUST be a file named {foldername}.asset.json inside the folder named {foldername}. See the corresponding section for a description of the content of this file.



Content
All other files and folders in your mod folder are part of the content of your mod

Currently supported file types
  • .csv Text file used for translations
  • .png Image files
  • .odl Custom file format used to create new data entries
  • .odlo Custom file format used to override existing entry data.
Content Management System Overview
This section contains important info about how the whole content system for Spellforce - Conquest of Eo works and is considered a required read for all mod developers.

The basic idea of the content management system in Spellforce - Conquest of Eo is that there will be multiple content packages from different sources (base game, dlcs, mods) which all contribute to a virtual filesystem which is used to provide all the content of the game.

Virtual File System
All content packages contribute their files to the same “namespace” from which the game then loads them from well known locations and types.

Example: The archetype selection when starting a new campaign will load data objects of type CampaignStartArchetype from any location in this virtual file system. The base game package com.ownedbygravity.sf.base contributes the three base archetype files

Campaigns/MainCampaign/Setups/ArchetypeAlchemist.asset Campaigns/MainCampaign/Setups/ArchetypeNecromancer.asset Campaigns/MainCampaign/Setups/ArchetypeRunesmith.asset
While the DLC Demon Scourge (com.ownedbygravity.sf.dlc1) contributes the demonologist archetype as
Campaigns/MainCampaign/Setups/ArchetypeDemonologist.asset

The game itself sees all four archetypes in the same “folder” and thus loads all four of them if the the dlc is active or only the first three if it is not.

Asset Name, Path and Identity
The name of an asset and its path can play a big role in developing your mods.

The full path and filename (including extension unless otherwise specified) forms the ‘identity’ of a data object.

If a file with the same identity as another file is encountered in another package, the Content Package Order will always choose the latest asset and therefore override the original.

Example:

The com.ownedbygravity.sf.base package has a file named
Campaigns/MainCampaign/Setups/ArchetypeAlchemist.asset
and you add a file to your mod with the same identity, your file will override the original file.

Content Package Order

Packages have a defined loading order which becomes important if you want to overwrite existing data.

The order is determined by the information in the Content Package Info file.

Packages will be ordered by their
  • Hard Dependencies
  • Soft Dependencies
So mods can reorder themselves by taking dependencies on other mods if required. As a tie breaker if hard and soft dependencies are the same the name of the package is used to decide the order.


Savegame Compatibility
There are two conditions which cause a newly written savegame to depend on a mod to be loaded

  • The savegame contains content from this mod. See Asset Name, Path and Identity if any of the content of your mod is written to the savegame.
    Example: you added a new item or used .odl to overwrite an existing item the savegame will depend on the mod and will not be able to be loaded without it.
  • The Content Package Info file has IsDependencyForSavegames set to true
Content Package Info Layout
The content package info file is a well defined json with the following content

{ "HardDependencies": [ {"Package":"com.ownedbygravity.sf.base"} ], "SoftDependencies": [ {"Package":"com.ownedbygravity.sf.dlc1"} ], "IsDependencyForSavegames":false }

Properties
Name
Content
HardDependencies
Dependencies for the content package which must be present for it to work.
SoftDependencies
Dependencies for the content package which might be present so that it can be loaded after this dependency without requiring it.

Example: a mod should be loaded after any dlcs but it doesn’t require it.
IsDependencyForSavegames
false → Default

true → This mod should always be written as a requirement for loading a savegame created while this mod is active.

.odl File Format
his format can be used to create or replace assets in the game using just a text editor.

There are currently around 400 types of data assets you can create / replace / modify with this format. It is recommended to export an existing asset from the game to see and modify the data.

This only includes the data shown above and not meshes, animations and textures.

Identity
The identity of an imported .odl file doesn’t include the .odl file extension to make it easier to override existing data.

Example:
Campaigns/MainCampaign/Setups/ArchetypeAlchemist.asset.odl
will be imported into the virtual file system as
Campaigns/MainCampaign/Setups/ArchetypeAlchemist.asset

Basic Format
The file contains the name of the asset type, followed by a json document containing its properties.
It is important to have a well formed json document without missing or excessive commas or the game will fail to parse your file. See mods.log for details.

Example of a .odl file
CampaignStartArchetype { "DisplayName": { "Key": "#ArchetypeAlchemist.DisplayName", "ObjectId": { "mGuid": { "GuidPart1": 960871039, "GuidPart2": 1078022271, "GuidPart3": 1851887267, "GuidPart4": -61869183 }, "mSerializableLocalIdentifier": 11400000 } }, "Description": { "Key": "#ArchetypeAlchemist.Description", "ObjectId": { "mGuid": { "GuidPart1": 960871039, "GuidPart2": 1078022271, "GuidPart3": 1851887267, "GuidPart4": -61869183 }, "mSerializableLocalIdentifier": 11400000 } }, "SavegameIcon": { "ContentPath": "Campaigns/MainCampaign/Setups/ArchetypeAlchemist_SavegameIcon.png" }, "SelectableArchetype": true, "Location": { "ContentPath": "Campaigns/MainCampaign/Setups/CampaignStart_Alluvyan.asset" }, "Crafting": { "ContentPath": "Campaigns/MainCampaign/Setups/StartCrafting_Alchemist.asset" }, "PrimarySchool": { "ContentPath": "Campaigns/MainCampaign/Setups/StartSchool_Nature.asset" }, "SecondarySchool": { "ContentPath": "Campaigns/MainCampaign/Setups/StartSchool_Enchantment.asset" }, "Tower": { "ContentPath": "Campaigns/MainCampaign/Setups/CampaignStart_Tower_03.asset" } }

Specific Types / Patterns

Localization IDs
Exported localization ids look like this:
{ "Key": "#ArchetypeAlchemist.DisplayName", "ObjectId": { "mGuid": { "GuidPart1": 960871039, "GuidPart2": 1078022271, "GuidPart3": 1851887267, "GuidPart4": -61869183 }, "mSerializableLocalIdentifier": 11400000 } }
The only important property, when using it in your own .odl files, is the “Key” property. You can shorten them to improve readability when editing your content.
{ "Key": "#ArchetypeAlchemist.DisplayName" }

Content Paths
Content paths are used to refer to another object within the virtual file system. (See Asset Name, Path and Identity)
{ "ContentPath": "Campaigns/MainCampaign/Setups/StartSchool_Enchantment.asset" }
Unity References
References to unity objects are currently not supported in .old / .odlo files and MUST to be removed from any exported document to not crash the game.
{ "instanceID": 145574 }
or
{ "m_FileID": 125144, "m_PathID": 0 }
.odlo File Format
See .odl file format for a basic description.

The purpose of override files is to change specific values of an already existing asset in the game. The basic structure is the same as .odl files but properties which aren’t present in the .odlo file will retain their original values from the object you are overriding.

For an .odlo file to work, the path of the override file needs to be the same as the original file with the .odlo extension added.

Example:
Units/Unit Progression/Default Progression.asset.odlo
Will apply an override to the file
Units/Unit Progression/Default Progression.asset
The asset type set in the .odlo file must match the one you want to override. In the example shown above the asset type is “UnitProgressionDefinition”.

It is recommended to use the “Expose for Override ” function in the modding menu of the game and remove any properties you do not want to override, in order to maintain a correctly formated file.

Example from mod.levelingchoice
If I want to increase the number of available choices during levelup, I can create a .odlo file by using “expose for override” on Units/Unit Progression/Default Progression.asset in the mod menu, and add the following lines:
UnitProgressionDefinition { "NumberOfProvidedRewards": 25 }
Using this will cause the game to override NumberOfProvidedRewards in Default Progression.asset without changing any of the other properties.
Localization System
The localization system is based on the concept of mapping an id to a text and having different databases for each language.

Language Code
Currently supported language codes are:

  • Two Letter Codes
    EN, DE, RU
  • Four Letter Codes with a dash
    zh-CN, zh-TW

Please use the standard language code (ISO 639) for you language to avoid confusions and increase compatibility.

Two letter codes should be preferred instead of four letter ones.
Example: DE instead of de-DE

Localization ID Database
The database of ids for a specific language is created by

  • Creating a text file, ending in .{LANGUAGECODE}.csv in the Localization folder in your Mod Directory
    Example: MyMod.EN.csv
  • Each line in the .csv file is an entry consisting of the ID, a semicolon and the actual text that will be displayed in the game.
    Example: #Dwarf_MoleRider.NameId;Moleriders
  • If an ID exists more than once, the displayed text will be overridden by the latest one according to the package order.
  • As a fallback, if a package has an english localization but no localization for the currently selected language, the english localization will be displayed in game.

Localization Example
Base game file Localization/com.ownedbygravity.sf.base.EN.csv
#Dwarf_MoleRider.NameId;Moleriders

Mod file Localization/myloca_1.EN.csv
NewItem.Name;The awesome item
NewItem.Description;The description for an awesome item
#Dwarf_MoleRider.NameId;Moldy Riders

Mod file Localization/myloca_1.DE.csv
NewItem.Name;Der coole Gegenstand
NewItem.Description;Die Beschreibung des coolen Gegenstand

If the language is english the displayed text will be
#Dwarf_MoleRider.NameId -> Moldy Riders
NewItem.Name -> The awesome item
NewItem.Description -> The description for an awesome item

  • #Dwarf_MoleRider.NameId is taken from the latest loaded file. As myloca_1.EN.csv is loaded after the base game localization this one is taken.
  • NewItem.Name and NewItem.Description are taken from myloca_1.EN.csv as they are not present in the base loca and .EN.csv matches the current language code.
  • myloca_1.DE.csv is completely ignored because it doesn’t match the language code EN for english.

Localization Text File Rules
Using excel to directly open this .csv file might be tempting but will destroy everything as the default excel settings do not match our file format!
  • Anything within [ ] and { } are macros which MUST NOT be translated.
  • The first row MUST always start with Id;Text
  • The file MUST NOT contain a Byte Order Mark (BOM)
  • The file MUST be a UTF-8 text file
  • Type \n to add a linebreak
  • Semicolons MUST NOT be used in any text
  • Columns must be separated by semicolons ( ; )
  • There need to be at least two columns in each row

Localization Text Macros
{ } Substitutions
{ } are substitutional values that are replaced by the game. Depending on the ID, different macros are available.

Basic usage is a textual identifier to determine which “variable” to input here.
Example: {who} or {value}

You can reposition { } entries anywhere in your text and won’t need to keep the order they appear in if your language needs a different order.

Some variables can have sub entries (for example: item tooltips) which you can access individually using {a.b} or {a.b.c} syntax and knowing their names

Variables can have extra formatting using the {name:format} syntax. Multiple of the following can be combined.
  • p
    {value:p} if value is a number the number will be multiplied by 100 and a % sign will be added
    Example: value is 0.12 {value:p} will output “12%”.

  • +-
    {value:+-} If value is a number it will have a plus sign before a positive number.
    Example: value is 3 then {value:+-} will output “+3”.

  • c
    {value:c} If value is a number the color macros [bonus] or [malus] will be added depending on the sign of the number.
    Example: value is 3 then {value:c} will output “[bonus]3[/]”. If value is -2 then {value:c} will output “[malus]-2[/]”

  • i
    Same as {value:c} but inverted colors. So positive numbers will get [malus] and negative will get [bonus]

  • r
    {value:r} if value is a negative number output ∞ instead
    Example: value is -1 outputs “∞”. value is 2 outputs “2”

  • n
    {value:r} If value is negative add [malus] coloring
    Example: value is 1 outputs “1”, value is -2 outputs “[malus]-2[/]”

  • +fs
    {name:+fs} will put a space before whatever name is if name doesn’t resolve to no text.
    Example “Hello{name:+fs}, how are you?”
    If name is dave the text will contain “Hello<space>dave, how are you?”.
    If name is <empty> the text will contain “Hello, how are you?”.

  • +bs
    {name:+bs} will put a space after whatever name is if name doesn’t resolve to no text.
    Example “Hello {name:+fs}, how are you?”
    If name is dave the text will contain “Hello dave<space>, how are you?”.
    If name is <empty> the text will contain “Hello , how are you?”.
You might be able to identify available substitutions, for example item tooltips, by looking at the content of .odl files.

[ ] Macros
[ ] Macros come in two different forms

  • Simple Macros → [iarmor]
  • Grouping Macros → [bonus]+3 damage[/]

There are a number of predefined macros. Currently there is no way to add more through modding.

See attached document macros.xlsx for a list of all existing macros and TextMeshPro | Rich Text[docs.unity3d.com]

Ingame Mod Tools
Once you have created the Content folder under {Documents}\My Games\Spellforce - Conquest of Eo and started the game, you can see a new button in the top right corner of the main menu.

Clicking this button will take you to the Modding Menu.


A list of your currently installed mods will be displayed, as well as the buttons to exit this menu or access the Mod Developer Tools.



Mod Developer Tools
Here you can see a list of all mods and base packages and access utilities to create and modify your mods.
Packages starting with com.ownedbygravity.sf are part of the base content and will aid you in creating your own mods.


Package Creation
You can create a new mod by clicking the “New Package (MOD)” button.
You will then be prompted to give your mod a unique name (as described in Mod Layout > Naming).


Package Inspector
Select any package by clicking on it to view its content.


How to expose content
If an asset is exposable, there are two options you can choose from:
  • Expose Content in Packages
    By clicking this button, you can choose a target package in which to create a .odl file containting all the moddable properties for this asset.

  • Expose for Override
    By clicking this button, you can choose a target package in which to create a .odlo file containting all the moddable properties for this asset.

How to setup a New Translation
When clicking the “New Translation” button in the Mod Developer Tools, you will be prompted to enter the language code for the new language you want to implement into the game.

Once the package translation.yourlanguage has been created in your Content folder, you can open the .csv file in the Localization subfolder with any text editor of your choice (Notepad++ is recommended).

See Localization Text File Rules and Localization Text Macros for more information about that file.


mods.log
Once {Documents}\My Games\Spellforce - Conquest of Eo\Content has been created the game will create a mods.log file with information about mod file discovery and potential errors encountered during loading.

You can check this file and the Player.log if you have any issues with your mod.