Configure a Game Project
Author .fomain, resource packs and sub-configs here. Configuration and Data Sources owns runtime rules; generated settings lists built-in names.
Source paths inspected
Source/Common/Settings.hSource/Common/Settings.cppSource/Common/Settings.incSource/Frontend/ApplicationInit.cppSource/Tests/Test_Settings.cppBuildTools/cmake/stages/ScriptsAndBaking.cmakeExamples/MinimalProject/CMakeLists.txtExamples/MinimalProject/FOnlineStarter.fomainExamples/MinimalMultiplayer/CMakeLists.txtExamples/MinimalMultiplayer/FOnlineMinimalMultiplayer.fomain
Start from an executable baseline
Start with MinimalProject (headless) or MinimalMultiplayer (client/server). Keep the game as CMake root and select its master config:
include(Engine/BuildTools/Init.cmake)
SetOption(FO_MAIN_CONFIG "MyGame.fomain")
SetOption(FO_DEV_NAME "MYGAME")
SetOption(FO_NICE_NAME "My Game")
FO_MAIN_CONFIG selects the project config at configure time; .fomain owns runtime/baking settings. Keep product values in the project, not Engine defaults.
Common.ResourcesPath is the runtime resource location, default Resources.
Server packages use its Client child for client distribution. There is no CMake
resource-directory option. Packaged bootstrap reads only this setting’s embedded
line before selecting the one full profile; CLI overrides remain supported.
Understand precedence
Unpackaged settings apply in this order:
- the selected
.fomain, found from-ApplyConfigor by walking upward forFO_MAIN_CONFIG; - each explicitly selected
-ApplySubConfig, in command-line order; - the installed-client local config stored in the writable cache, when present;
- ordinary command-line setting overrides;
- platform/build auto-settings.
Packaged startup chooses the resource profile, or the binary profile when optional
resources are missing, and applies that one profile directly to zero. No default
apply precedes it. The 40000-byte binary patch area is fixed and capacity-checked.
Profiles contain all nonzero declared values, rather than metadata deltas; omitted
typed values remain zero even after metadata loads. Local config, CLI and auto
settings follow. Packaged -ApplySubConfig is reported with FO_VERIFY_AND_CONTINUE; select the profile at packaging.
Author every required setting, including intentional zeros. Filtering belongs to
the baker. Baking.BootstrapGameSettings remains a declared-name check; all nonzero
game settings already reach ApplicationInitHook in the selected full profile.
Use fully qualified names such as Server.DbStorage in authored files and operational commands. The parser accepts short built-in names, but qualified names make ownership and review unambiguous.
Author the root settings
Keep one deliberate value per line:
Common.GameName = My Game
Common.GameVersion = 0.1.0
Network.ServerPort = 4000
Network.WebSocketPort = 4001
Server.DbStorage = Memory
ServerNetwork.DisableNetworking = False
Baking.BakeLanguages = engl russ
Baking.BakeOutput = Baking
Common.ResourcesPath = Resources
Common.PlatformBinariesPath = PlatformBinaries
Common.CachePath = Cache
ManagedScript.Assemblies = MyGame
ManagedScript.ProjectName = MyGame
ManagedScript.TargetFramework = net10.0
ManagedScript.MsBuild = dotnet msbuild
ManagedScript.Dirs = Engine/Source/Scripting/Managed/CoreScripts Scripts
ManagedScript.Analyzers = Engine/Source/Scripting/Managed/Analyzers/FOnline.Analyzers.csproj
Unknown names become project custom settings and are available through GetCustomSetting / FindCustomSetting. That is intentional for game-owned configuration, but a typo in a built-in setting can therefore look valid. Add a focused project test for every content ID, port/profile, prototype name, path, or custom setting that affects startup or gameplay.
Values beginning with + accumulate instead of replacing. String values append with a space, vectors append elements, numeric values add, booleans use logical OR, and enums use bitwise OR; use this deliberately and test the resulting value rather than assuming list-only behavior. $ENV{NAME} and $FILE{path} resolve while the authored config is read, including during baking, so their concrete values can enter generated internal configs. $TARGET_ENV{NAME} and $TARGET_FILE{path} remain directives while baking and resolve only when a target application reads them; the current packager does not provide a general target-directive resolver. Keep credentials outside tracked config, use target forms for runtime secrets, and follow Security and Secrets for command-line, logging, signing, CI, rotation, and artifact boundaries.
Define resource packs
A resource pack selects inputs, bakers, and runtime recipients:
[ResourcePack]
Name = Protos
InputDirs = Content Maps
IncludePatterns = **
ExcludePatterns = **/Draft/**
Bakers = Proto
[ResourcePack]
Name = Maps
InputDirs = Maps
IncludePatterns = **/*.fomap
Bakers = Map
[ResourcePack]
Name = ServerScripts
InputDirs = Scripts
IncludePatterns = **/*.fos
Bakers = AngelScript
ServerOnly = True
[ResourcePack]
Name = ManagedScripts
InputDirs = Engine/Source/Scripting/Managed/CoreScripts Scripts
IncludePatterns = *
Bakers = Managed
Choose the backend deliberately. An AngelScript pack bakes .fos modules through AngelScriptBaker; a Managed pack compiles the configured top-level .cs sources and generated API into target-specific assemblies. The Managed pack must include the Engine CoreScripts and project sources selected by ManagedScript.Dirs; keep its assembly, analyzer, extra-source/reference, and generated-directory settings aligned with the same build. See Managed C# Scripting for the complete backend contract.
The accepted fields are:
| Field | Meaning |
|---|---|
Name |
Required pack identity and generated resource entry |
ConfigDir |
Derived owning-config directory used to resolve relative inputs; not authored in the section |
InputDirs |
Space-separated directories, relative to the owning config |
InputFiles |
Space-separated explicit files, also config-relative |
IncludePatterns |
Optional input glob allowlist |
ExcludePatterns |
Optional input glob denylist |
Bakers |
Space-separated baker names |
ServerOnly |
Emit only a server resource entry |
ClientOnly |
Emit only a client resource entry |
MapperOnly |
Emit only a mapper resource entry |
At most one side-only flag may be true. With none set, the pack is delivered to server and client. Mapper-only packs are separate. RecursiveInput appears in older project files but is not a current ResourcePackInfo field; express recursion through IncludePatterns = **.
Use separate packs where ownership, release cadence, side visibility, or update policy differs. Do not use pack order as a hidden gameplay override system: duplicate resource identities need an explicit project policy and a test.
Add named sub-configs
Sub-configs are reviewed overlays for a launch mode:
[SubConfig]
Name = LocalDev
Server.DbStorage = Memory
ServerNetwork.DisableNetworking = False
Render.RenderDebug = True
[SubConfig]
Name = TutorialSmoke
Parent = LocalDev
Tutorial.Automation = True
Render.HeadlessWindow = True
Render.NullRenderer = True
Audio.DisableAudio = True
Parent names must refer to earlier sub-config sections. Multiple parents are applied left to right; later parents override earlier parents per key, then the child section wins. A launch may pass multiple -ApplySubConfig options, which are applied in command-line order.
Use -ApplySubConfig NONE for generation/baking commands that must consume only the master config. BuildTools does this for CompileAngelScript, CompileManagedScripts, BakeResources, and ForceBakeResources.
Keep sub-configs narrow:
- environment modes choose infrastructure and diagnostics;
- tests choose deterministic fixtures and headless behavior;
- scenes choose startup content;
- release modes choose product-safe settings;
- secrets stay out of sub-configs.
Validate a configuration change
- Reconfigure the embedding project if CMake options or the main config path changed.
- Run
CompileAngelScriptand/orCompileManagedScriptsfor every enabled backend whose script inputs, generated API, analyzers, or metadata changed. - Run
BakeResources; useForceBakeResourcesafter pack membership, baker selection, include/exclude patterns, language sets, or migration rules change. - Launch the smallest sub-config that consumes the changed setting.
- Inspect startup logs for
Apply config,Apply sub config, unknown/missing files, skipped languages, missing bakers, and side resource entries. - Run a project test that resolves custom settings and content-backed references.
- Build/package once when internal config or runtime resource entry composition changed.
The two Engine-owned examples are executable configuration fixtures:
(cd Examples/MinimalProject && python3 validate.py)
(cd Examples/MinimalMultiplayer && python3 validate.py)
Use the win64- equivalents on Windows.
Common failures
| Symptom | Cause | Recovery |
|---|---|---|
Config file not found |
Wrong working directory, FO_MAIN_CONFIG, or -ApplyConfig path |
Pass the explicit config path or launch below the project root |
Sub config not found |
Misspelled name or section not loaded | Check section order/name and the applied master config |
Parent sub config not found |
Parent appears later or is absent | Move parent before child or correct the name |
Resource pack name not specified |
Missing Name |
Add a unique pack name |
| Side receives an unexpected pack | Missing or incorrect side-only flag | Split packs and inspect generated resource entries |
| Incremental bake keeps old output | Pack membership or baker changed | Run ForceBakeResources and remove only documented disposable outputs if needed |
| Built-in setting appears ignored | Later sub-config/local config/CLI/auto layer wins | Inspect the complete precedence chain |
| Typo silently becomes a custom setting | Unknown names are project-owned by design | Add a settings/content validation test |
Update discipline
On Engine/project updates, inspect Settings.inc, Settings.cpp, ApplicationInit.cpp, BuildTools options/baking stages and project .fomain. Reconcile this guide, project config, tests and generated references in the same change when precedence, fields/defaults, pack routing or launch profiles change.
Optional native components
Select components with SetOptionValues before StartProjectGeneration: BOOL, OFF by default, numeric 0/1 definitions, no aggregate selector. Register/include all Engine sources/headers unconditionally; files guard optional contents.
SetOptionValues(
FO_DATABASE_SQLITE ON
FO_DATA_SOURCE_DAT ON
FO_IMAGE_FRM ON)
| Option | Owning role and dependency |
|---|---|
FO_DATA_SOURCE_DAT |
Common; DAT 2.0/2.1 and zlib |
FO_DATA_SOURCE_ZIP |
Common; external ZIP/BOS and bundled minizip |
FO_DATABASE_JSON |
Server; plain JSON, existing JSON dependency |
FO_DATABASE_SQLITE |
Server; SQLite and CBOR, no BSON |
FO_DATABASE_MONGO |
Server; mongoc and libbson |
FO_IMAGE_FRM |
Baker; FRM and split FRx, guarded Fallout palette |
FO_IMAGE_RIX, FO_IMAGE_ART, FO_IMAGE_SPR |
Baker; individual legacy importers |
FO_IMAGE_ZAR, FO_IMAGE_TIL |
Baker; independent importers and a shared guarded decoder |
FO_IMAGE_MOS, FO_IMAGE_BAM |
Baker; individual legacy importers |
FO_AUDIO_ACM |
Baker; Interplay ACM decoder, built-in Ogg Vorbis encoder |
Server requires Memory; Baker requires PNG/TGA/FOFRM and libpng, plus WAV/Ogg and Vorbis/Ogg for audio. Embedded/APK keep minizip with external ZIP OFF. Clients read baked sprites and Vorbis audio without source importers/database drivers.
Retired FO_DISABLE_MONGO/FO_DISABLE_SQLITE inputs fail; clear their cache/environment and choose positive options.
Baking configuration fingerprint
Declarations register type and baking impact. Mark DeclareBoolOption/DeclareValueOption, or a leading plural Declare*Options argument, with BAKING for inclusion in FO_BAKING_CONFIG_HASH. Unmarked options are excluded; option reference lists each decision.
Hash inputs: project identity/config, geometry, model/effect limits, 3D, particles, scripting and archive/image/audio importers. Database providers, diagnostics, allocators, output paths and native targets are excluded.
CMake computes SHA-256 just before codegen, after preceding stages and Codegen Pre. Registered names are sorted, BOOLs become 0/1 and string boundaries remain distinct. Marked project options join automatically; finalize values before SetupCodeGeneration.
Successful resource baking writes Resources.baking-config-hash and report bakingConfigHash. Missing/changed fingerprints clear stale outputs and force full bake independently of FO_BUILD_HASH; unchanged fingerprints allow incremental bake. Both markers are removed before work and written only on success. Reconfigure/rebuild/rebake before packaging.