Anatomy of a mod
The .ulmod file, where mods live, and which folder or extension each kind of content uses.
A mod is a folder with an .ulmod file in it. Everything else is optional: a mod can be a single scene, a single city, a furniture pack, or a whole module as big as ul_Base.
Where mods live
| Folder | What is there |
|---|---|
Mods/ in the game directory |
Mods you install or write. Created on first launch. |
Content/Modules/ |
The modules the game ships with: ul_Base, ul_Pregnancy, ul_Health… |
Mods/LoadOrder.txt |
Which mods are enabled, and in which order. Written by the game. |
Both roots are treated exactly the same way. The shipped modules are ordinary mods; they are only listed first by default so that yours can override them. See Load order and overrides.
The .ulmod file
One KEY: value per line. The game reads the first *.ulmod file it finds at the top of the folder.
iniMODULE_UNIQUEID: yourname_nightlife
MODULE_NAME: Nightlife Expanded
MODULE_AUTHOR: Your Name
MODULE_VERSION: 1.2.0
MODULE_CATEGORY: Gameplay
MODULE_LINK: https://example.org/nightlife
MODULE_DESCRIPTION: More to do after dark: new club scenes, bouncers, and last orders.
MODULE_REQUIREMENTS: ul_Base, ul_Health
| Key | Used for |
|---|---|
MODULE_UNIQUEID |
Your mod's id on the content hub. Keep it equal to the folder name. |
MODULE_NAME |
The name shown in the mod list. |
MODULE_AUTHOR |
Shown in the mod list and on the hub. |
MODULE_VERSION |
Shown in the mod list. Any string; major.minor.patch is the convention. |
MODULE_CATEGORY |
Groups the mod in the mod list (Gameplay, Clothing, UI…). Empty means General. |
MODULE_DESCRIPTION |
One paragraph, on one line. Say what the mod adds and what other mods can call. |
MODULE_REQUIREMENTS |
Comma-separated folder names (or MODULE_UNIQUEIDs) of mods yours needs. Enforced: see below. |
MODULE_LINK |
Your page. |
Put a thumbnail.png next to the .ulmod file to give the mod a picture in the mod list and on the hub.
The folder name is the mod's identity, not MODULE_UNIQUEID. The load order, enable/disable and Game:isModEnabled() all use the folder name. Renaming the folder makes it a different mod.
MODULE_REQUIREMENTS is enforced: a mod whose requirement is not installed, is turned off, or cannot load itself does not load either, and the Mods list shows it as Blocked with the reason. A requirement may name the other mod's folder or its MODULE_UNIQUEID. The game also keeps every mod below the mods it requires in the load order, so yours can override their files.
MODULE_LINK is not displayed anywhere yet.
What goes where
The game finds content in two ways, and the difference matters when you organise a big mod.
Found by extension, anywhere in the mod
These files can sit in any subfolder you like. The game searches the whole mod for them, so organise them however reads best to you.
| Extension | What it is | Page |
|---|---|---|
.ulscene |
A scene: story, dialogue, choices | Scenes |
.ulaction |
Something the player can do at a place | Actions |
.ulstat |
A stat people have | Stats |
.ulquest |
A quest in the journal | Quests |
.ulcharacter |
A character preset (appearance) | Presets |
.ulmajors |
University majors and their subjects | Jobs and university |
.ultip |
A loading-screen tip | Small content |
.uldesc, .ultalk |
Sex-scene narration and dirty talk | Sex scenes |
.ulanimtags |
Tags for sex animations | Animations |
The folder an action sits in still means something: its name is the action's category in the action list (Actions/food/… is listed under food).
Found in a fixed folder
These are looked up by folder name at the top of the mod.
| Folder | What it holds | Page |
|---|---|---|
Lua/ |
Libraries loaded once, before any scene | Libraries |
AI/, AI/high_priority/ |
NPC daily routines | NPC routines |
Map/Hud/, Menu/ |
Lua UI on the world map and in the Mods panel | Mod UI |
Map/ |
Venue list and hours, city styles, player panel, map icons | Map and venues |
Cities/ |
Cities (.ulcity, .osm) |
Cities |
Names/ |
First and last names | Cities |
Rooms/ |
Room recipes, grammars, furniture sets, layouts | Rooms |
Looks/ |
Lighting and colour profiles per venue | Looks |
History/ |
Life-event types for people's histories | History |
Items/, Shops/ |
Shop items and shops | Shops and items |
Clothes/ |
Clothing (.ulcloth + meshes) |
Clothing |
Hair/ |
Hairstyles (.ulhair) |
Hair |
Bodies/ |
Body definitions (.ulbody) |
Bodies |
Presets/ |
Character presets | Presets |
CharGen/ |
Character-creator morph lists, icons, backdrop | Character creator |
Animations/ |
Animation files and activities (.ulactivity) |
Animations |
Meshes/, Images/ |
Meshes and pictures referenced by other files | Assets |
Loading/ |
Loading-screen background and logo | Small content |
UI/ |
Themes (Themes/*.uluitheme), their fonts, icons and pictures |
Mod UI |
A typical mid-sized mod
textMods/yourname_nightlife/
├── yourname_nightlife.ulmod
├── thumbnail.png
├── Lua/
│ └── nightlife.lua -- shared helpers, Nightlife.* settings
├── Stats/
│ └── drunkenness.ulstat
├── Actions/
│ └── nightlife/ -- category "nightlife" in the action list
│ ├── order_shot.ulaction
│ └── dance.ulaction
├── Scenes/
│ ├── bouncer.ulscene
│ └── last_orders.ulscene
├── Menu/
│ └── nightlife.lua -- settings page in the Mods panel
└── Images/
└── Nightlife/
└── cocktail.png
Prefix everything that shares a namespace with other mods: scene file names, action and stat ids, global Lua tables, story globals. yourname_bouncer never collides; bouncer eventually will. See Load order and overrides.