IFO Format (Module Info Blueprint)
Description: The Module Info (.ifo) is the absolute root metadata file for any environment. It dictates global module behavior, handling everything from the starting spawn location, to the local calendar and time-of-day progression, to script execution for global module events.
At a Glance
| Property | Value |
|---|---|
| Extension(s) | .ifo |
| Magic Signature | IFO / V3.2 |
| Type | Module Blueprint |
| Rust Reference | View rakata_generics::Ifo in Rustdocs |
Data Model Structure
Rakata parses the raw GFF structure into the rakata_generics::Ifo struct.
- (Note:
rakata-lintdoes not currently implement behavioral validation for.ifoformats.)
Engine Audits & Decompilation
The following documents the engine’s exact load sequence and field requirements for .ifo files mapped from swkotor.exe.
(Decompilation logic for this section was entirely audited and verified via native Ghidra pipeline against swkotor.exe, explicitly pulling from CSWSModule::LoadModuleStart at 0x004c9050.)
Global State Configurations
| Field | Type | Engine Evaluation |
|---|---|---|
Mod_Entry_Area | ResRef | The primary spawning area ResRef. |
Mod_Entry_X / Mod_Entry_Y / Mod_Entry_Z | FLOAT | Exact spawning XYZ coordinates. |
Mod_Entry_Dir_X / Mod_Entry_Dir_Y | FLOAT | Entry Direction Fallback: If the engine cannot evaluate Mod_Entry_Dir_Y, it forces a hard graphical fallback rendering the entity facing east (X=1.0, Y=0.0). |
Mod_XPScale | BYTE | Globals XP multiplier scale. Defaults natively to 10. |
Time & Cycle Management
| Field | Type | Description |
|---|---|---|
Mod_DawnHour | BYTE | Dawn hour integer marker. |
Mod_DuskHour | BYTE | Dusk hour integer marker. |
Mod_MinPerHour | BYTE | Configuration for exactly how many real-time active gameplay minutes constitute a module hour limit. |
Note
Day/Night Cycle Computations The engine continuously computes localized day/night phases explicitly against
Mod_DawnHour,Mod_DuskHour, and thecurrent_hour. This dynamically updates an internal state flag denoting:1=Day,2=Night,3=Dawn,4=Dusk.
Global Event Scripts
Event scripts are universally evaluated as string ResRef pointers executing compiled NSS logic. The engine evaluates 15 separate global events (like Mod_OnHeartbeat, Mod_OnModLoad, Mod_OnClientEntr, Mod_OnPlrDeath, etc).
- Asymmetric I/O (Equipping): The
Mod_OnEquipItemarray natively loads during absolute module startup bounds (LoadModuleStart), however, it is entirely omitted and ignored during the save-game serialization cycle (SaveModuleIFOStart).
Safe-State Injection (Save Games Only)
Certain blocks of data inside the .ifo are deliberately evaluated only when the engine is mounting a module directly from a loaded .sav archive block.
| Engine Target | Description |
|---|---|
| Player / Mod Variables | Structures like Mod_PlayerList, Mod_Tokens, VarTable, and the EventQueue are strictly bypassed unless natively evaluated under is_save_game conditions. |
| Area Overrides | The Mod_Area_list technically supports arrays (for NWN legacy), but KOTOR strictly enforces a single active area boundary. The secondary ObjectId within this specific array is only ever read natively inside a save state flow. |
| Legacy Hak De-sync | “Hak Packs” are custom override archives natively used in Neverwinter Nights (the engine’s predecessor). While KOTOR’s save routine (SaveModuleIFOStart) blindly writes a Mod_Hak string into save-games as leftover legacy behavior, the actual load cycle (LoadModuleStart) completely ignores it. Modders cannot use this field to hook custom archives. |
Proposed Linter Rules (Rakata-Lint)
While rakata-lint does not currently implement .ifo validation, the exact engine behaviors discovered during decompilation dictate these static constraints:
- Direction Fallback: If
Mod_Entry_Dir_XandMod_Entry_Dir_Yboth evaluate unconditionally to0.0, the engine forces an unrecorded fallback direction locking the player spawn sequence toward(1.0, 0.0). - XP Dead-Scaling: Since the
Mod_XPScaledefault value evaluates to10, any unexpected baseline of0aggressively halts all localized XP acquisition flows. - Eternal Day/Night Bounds: If
Mod_DawnHourstrictly equalsMod_DuskHour, the module becomes hopelessly locked into perpetual daylight configurations. - Void Area Initialization: An empty
Mod_Area_listarray directly faults the load cycle, as the module has no physical payload layout to inject the player into. - Dangling NWM Structure: Setting
Mod_IsNWMFileto1without deploying the conditionally mandatoryMod_NWMResNameevaluates to an unstable execution state.