Scriptable Layers (Metroid Prime 2)
This article is for the scriptable layers format from Metroid Prime 2, 3, and Donkey Kong Country Returns. See Scriptable Layers (File Format) for other revisions of this format.
Scriptable layers are a data section found in the MREA format, denoted by the fourCC identifier
SCLY. It contains script object instances which are used to set the object layout of each room. Rooms can contain multiple layers, with each being able to be toggled on and off independently, allowing for the layout of a room to be updated after significant ingame events, which is done using a ScriptLayerController object. Each instance has a large number of parameters that can be toggled to customize the appearance and behavior of that instance, and they're capable of sending messages to other objects, allowing for fairly complex interactions between objects to be scripted.
In Echoes, the SCLY format was overhauled. The most notable change is that all properties now have a 32-bit ID and a size value listed, allowing the game to match properties in the file with data members by ID rather than by their position in the file; this was presumably done to avoid breaking cooked data when objects were modified during development, since this change meant the file could still be read correctly if properties were added or removed from an object and the script data hadn't been recooked. Another change is that there's now a separate layer for generated objects (ie objects that are spawned using a Generator or a PickupGenerator), which uses the fourCC
SCGN. Aside from minor changes in the header, the
SCGN layer is identical to
In Donkey Kong Country Returns, the format is identical, but the way the data is cooked was slightly modified. In every game starting with Prime 2, the engine assigns an arbitrary default value to every object property before reading in the values from the file. In the Prime series, this didn't have much of an effect, since (almost) every property for every object is written to the file anyway. But starting in Donkey Kong Country Returns, any properties whose value matches the internal default value are left out of the file in order to speed up loading times. This means a full list of properties and their internal default value is required to correctly read/write DKCR files. (This change could also be applied in the Prime series with custom script data.)
Although this format is primarily found in MREA files, it's also occasionally reused in other formats, such as SCAN.
|0x5||u32||1||Unknown||Appears to be layer self-index. Not present in SCGN.|
|0xA||u32||1||Instance Count||Count of instances in this layer.|
|0xE||Script Instance||Instance Count||Script Instances||Layer instance data.|
|End of layer|
|0x0||char||4||Instance Type||FourCC representing the type of object this is.|
|0x4||u16||1||Instance Size||Size of this instance, relative to after the size value.|
|0x6||u32||1||Instance ID||ID used by other objects to reference this instance. The bottom 16 bits is an area-relative instance ID. The next 10 bits up are the world-relative area index. The top 6 bits are the layer index. The layer index isn't technically part of the ID, as the game removes it for ID-based lookups.|
|0xA||u16||1||Connection Count||Count of outgoing script connections.|
|0xC||Connection||Connection Count||Connection Array||Array of outgoing script connections.|
|Property Struct||1||Base Struct||This is the instance's base struct, which contains all properties in this instance. The property ID is always 0xFFFFFFFF.|
|End of instance|
A connection is used to script interactions between objects; when this instance enters the given state, it sends the target instance the given message.
|0x0||char||4||State||When the instance enters this state, the connection will activate.|
|0x4||char||4||Message||Message that will be sent to the target instance when the connection activates.|
|0x8||u32||1||Target Instance ID||ID of the target instance.|
|0xC||End of connection|
A property struct is a property that contains other properties. These are often modular pieces that are present on multiple objects (for example, the PatternedAI struct that appears on all enemies). Structs can contain other structs as sub-properties.
|0x0||u32||1||Property ID||Property ID for this struct property.|
|0x4||u16||1||Property Size||Size of this struct including all sub-properties.|
|0x6||u16||1||Sub-Property Count||Count of sub-properties contained in this struct.|
|0x8||Property||Sub-Property Count||Sub-Properties||Array of this struct's sub-properties.|
|End of struct|
A property represents a single data value on a script instance. The type of each property varies depending on the ID.
|0x0||u32||1||Property ID||ID that uniquely identifies this property.|
|0x4||u16||1||Property Size||Size of this property. This is used by the game to skip over the property if it encounters an unrecognized ID.|
|0x6||Varies||1||Property Data||The actual data for this property. The type and size of this data varies depending on which property it is (ie. depending on the ID).|
|End of property|
Generated objects are stored on a separate layer, denoted with
SCGN. The SCGN layer isn't a real layer; it doesn't store a self-index and instances on the layer still contain the index of their original SCLY script layer in their instance ID. These are the stipulations that cause an instance to be written to SCGN:
- Any instance that receives a Generate/Activate message (MP2) or a Generate/Attach, Generate0/Attach, or Generate1/Attach message (MP3, DKCR) is written to SCGN instead of SCLY.
- In DKCR, all GenericCreature instances are written to both SCLY and SCGN. (The generated one is spawned if you scroll the creature offscreen and come back.)