UTD Format (Door Blueprint)
Description: The Door (.utd) blueprint defines interactive pathways on a level map. Beyond acting as physical barriers or transitions between areas, doors house lock mechanics, trap configurations, script hooks, and basic visual states (open, destroyed, jammed).
At a Glance
| Property | Value |
|---|---|
| Extension(s) | .utd |
| Magic Signature | UTD / V3.2 |
| Type | Door Blueprint |
| Rust Reference | View rakata_generics::Utd in Rustdocs |
Data Model Structure
Rakata maps the Door definition directly into the rakata_generics::Utd struct. To view the exhaustive binary schema and strict GFF field mappings, please refer to the Rustdocs for this struct, where each field is explicitly documented.
A Door breaks down into four main categories:
- Core Identity & Geometry: The configuration for what the door looks like, its faction, and the text displayed when targeted (e.g.,
Appearance,TemplateResRef,LocName). - Lock & Trap Mechanics: The parameters defining whether it’s locked, what key is needed, and rules for any attached traps (e.g.,
Locked,KeyName,TrapType,DisarmDC). - Transition Pathways: The linked destination used when a door acts as a loading zone to another area (e.g.,
LinkedTo,LinkedToFlags). - Behavioral Hooks (
Scripts): The scripts that run when a player opens, destroys, or fails to unlock the door (e.g.,OnOpen,OnFailToOpen,OnMeleeAttacked).
- Active Validation:
rakata-lintenforces checks against missing keys or invalid transition references before a module ever reaches the game engine.
Engine Audits & Decompilation
The following information documents the engine’s exact load sequence and field requirements for .utd 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 the primary dispatcher CSWSDoor::LoadDoor at 0x0058a1f0.)
Structural Load Phasing
The engine processes a Door structurally by mapping its sub-fields into distinct operational constraints.
| Domain | Sub-fields Evaluated | Purpose |
|---|---|---|
| Scales & State | 22 | Reads the physical health, visual appearance, and base traits determining whether the door is locked or indestructible. |
| Hooks | 15 | Attaches custom event scripts that fire when the door is opened, forced, unlocked, or trapped. |
| Mechanical | 9 | Configures the lock difficulty tiers and the specific skill hurdles required to detect and disarm any attached traps. |
| Transitions | 4 | Links the door strictly to another area (.are), turning it into a physical loading screen transition node. |
Core Structural Findings
The CSWSDoor parser natively guarantees strict state adjustments upon parsing.
| Engine Rule | Runtime Behavior |
|---|---|
| Appearance Truncation | The engine reads Appearance as a 32-bit integer but forcefully truncates it to a single byte ((byte)uVar5). Any ID above 255 automatically wraps to 0 and breaks the physical door model. |
| Static Enforcement | If the door is marked Static, the engine automatically forces plot = 1. This safely guarantees that static level architecture cannot be destroyed by players. |
| Portrait Shadowing | If PortraitId is 0, the engine hardcodes it to 0x22E. If PortraitId is < 0xFFFE, the engine completely ignores the Portrait string ResRef and relies entirely on the ID. Any value in the Portrait ResRef field is treated as dead data. |
| Trap Hook Fallback | If the OnTrapTriggered script is left empty, set to null, or literally named "default", the engine pulls the default standard script from traps.2da instead. |
| HP Synchronization | CurrentHP is securely clamped against the door’s maximum HP to prevent overflow bugs. |
Legacy & Ignored Data
| Finding Type | Explanation |
|---|---|
| Legacy Engine Artifacts | 7 explicitly mapped template structures (like AnimationState, NotBlastable, OpenLockDiff) are Neverwinter Nights or KOTOR 2 legacy dependencies inherently ignored by the K1 parser. |
Implemented Linter Rules (Rakata-Lint)
Phase 1 (intra-resource, no context)
Implemented under rakata_lint::rules::utd.
- UTD-001 (Static Parity): Warns when
Static=truebutPlot=false; the engine forces Plot to true at runtime. - UTD-002 (HP Bounds): Errors when
CurrentHP > HP; the engine clamps toHPon template load. - UTD-003 (Portrait Shadowing): Warns when
PortraitId < 0xFFFEandPortraitresref is set; the resref is ignored at runtime.
Phase 2 (range / 2DA / resref existence, requires LintContext)
Implemented under rakata_lint::rules::utd_range.
- UTD-004 (Generic Door Type Bounds): Errors when
GenericTypedoes not resolve to a row ingenericdoors.2da; engine renders missing model. - UTD-005 (Portrait Bounds): Errors when
PortraitId(when not the0xFFFE“use string Portrait” sentinel) does not resolve to a row inportraits.2da. - UTD-006 (Resref Existence): Warns when
Conversation(.dlg),Portrait(.tga), or any of the 15On*script hooks (.ncs) does not resolve in the configured resource sources.LinkedToModule(area transition) is deferred to Phase 3.
Pending
- Appearance Truncation: Flags legacy
Appearance(u32) values above 255 (engine truncates to a single byte). - Trap Hook Fallback Detection: Scans for empty / null / literally-named
"default"OnTrapTriggeredreferences that silently invoke thetraps.2dafallback. - Portrait Zero Hardcode: Detects
PortraitId == 0mappings since the engine hardcodes lookup to0x22E.