SOC (an acronym for "Sonic Object Configuration") is a content definition language for SRB2. It allows users to modify game-relevant data and add custom data without editing the game's source code. Unlike Lua, however, it is not a full scripting language and cannot be used to write custom game logic. The term "SOC" is used to refer to both the language itself and the files created in that language – a file in the SOC language is often simply called "a SOC".
SOCs can be used to define a variety of data: The most prominent feature and namesake of SOCs is the ability to modify the properties and behavior of all Objects in the game, including their interaction with the environment and the graphics they display, and to create new ones. Other types of SOC-modifiable data include level headers, unlockables, emblems,cutscenes and text prompts. These features are essential for creating addon files such as custom levels or level packs.
SOCs consist of plain text and can be written in a text editor such as Notepad. A SOC is divided into blocks: Each block defines one piece of data and consists of a header, which identifies the piece of data, and a list of properties. While the properties vary depending of the type of data that is being defined, the general structure and syntax is always the same. For example, a definition for the state of an Object looks like this:
State S_FLAMEJETFLAMEB1 SpriteName = DFLM SpriteFrame = FF_FULLBRIGHT|TR_TRANS40|B Duration = 1 Action = A_MoveRelative Var1 = 0 Var2 = 5 Next = S_FLAMEJETFLAMEB2
The first line of this block (
State S_FLAMEJETFLAMEB1) is the header. The first word represents the type of data that is being defined (in this case
State). The second word identifies the specific piece of data. This is the slot number for the given data type. Most data types store their data in slots, and the slot number specifies the slot in which the piece of data is located. For example, a block with the header
Level 1 is the level header for the map in slot 1. Likewise, a block with the header
State 42 defines the state in slot 42. Some slots are already occupied by SRB2 itself, and if a block for such a slot is loaded, the piece of data in that slot will be overwritten. Other slots are empty by default and exist specifically to define new data; these slots are called freeslots.
For some types of data, it is more practical to refer to the pieces of data by name rather than a slot number. To achieve this, the game provides constants, which are essentially words that represent certain numbers. The above example makes use of this:
S_FLAMEJETFLAMEB1 is a constant whose value is 1226. Thus, it represents the state in slot 1226, which is a state for the flames that are thrown by the spinning flame jets. Unlike the raw number, however, the name is much easier to remember and also provides some information about the purpose of the state itself. When reading a SOC, the game replaces all constants with their corresponding numbers. The header is therefore converted to
State 1226, telling the game the slot number for the state without the user needing to know it.
After the header, the rest of the block consists of the properties for the piece of data that is being defined. Each line sets one property and is formatted like this:
[Property name] = [value]. In the above example, the line
Duration = 1 sets the duration of the state to one tic. Each property has a default value, and if it is omitted from the block, it will be set to this default value. In the above example, the line
Var1 = 0 could be omitted, since 0 is the default value for the
Var1. However, redundant lines like this one are often added anyway to make the SOC easier to read. The order of the properties within the block is irrelevant and may be changed at will, but for the purpose of consistency, it is advised to use the default order.
As with the header, constants can be used as values for properties that expect numbers. For example, the line
Next = S_FLAMEJETFLAMEB2 in the above example sets the next state that the Object will switch to after the current one. Normally, this property expects the slot number of the state, but here it is replaced by the corresponding constant, which has the same effect but is easier to read. Mathematical operations can also be used to calculate values for properties. See below for an explanation.
SOCs are generally case-insensitive, and when reading a SOC, the game will convert all characters to uppercase. The only exceptions are properties that are used to display case-sensitive text on the screen. The syntax of the blocks is fairly rigid: No additional characters, whitespaces or line breaks may be inserted anywhere inside a block (except for comments, see below), and the existing whitespaces may not be omitted. For example, the lines
Duration= 1 or
Duration = 1 would cause an error. Between blocks, however, line breaks are allowed and in fact encouraged for better readability.
Certain characters are used in SOCs for special purposes.
Mathematical operations can be used in nearly all fields that take numbers in a SOC. They include the standard arithmetic operations as well as bitwise operations. The tables below list the available operations, along with the symbol(s) used for each:
Mathematical operations can be freely mixed with constants, since the game replaces them with the corresponding numbers before performing the mathematical operations. No spaces should be placed inside a mathematical operation. For example,
Var1 = 5 << 16 + 1 will cause an error and should be written as
Var1 = 5<<16+1 instead.
), can also be used in mathematical operations to specify order of operations if needed. For example,
Var1 = (5<<16)+1 gives a different
Var1 value to
Var1 = 5<<(16+1).
Commenting/end of text (
#' (number sign, or hash) symbol is used to signify the start of a comment – i.e. text that is not read by the game, which is typically used for credits, reminders, easier reference, structuring and other relevant notes for the author and others to see. Comments always last until the end of the line, so using '
#' again within the following text will have no effect. Comments may be placed on their own lines, or directly following non-comment text on the same line (no spaces may be placed between the non-comment text and the comment). Because of its use as a comment signifier, the '
#' symbol itself cannot be used in non-comment text.
PlayerText property for custom characters and the
SceneText property for cutscenes allow multiple lines and even paragraphs of text as values. For these properties, the '
#' symbol is used to mark the end of the text.
Custom colors (
Colors can be used in various properties that are used to display text on the screen. To use a color, write the '
\8' (backslash, then eight) followed by a number or letter ranging from 0–F, with letters coming after numbers (see list below). This color will then be used for all following text, until a different color is set or the text ends. Use
\80 to reset the text color back to white where appropriate.
The usable colors include:
Another way to do it is to use a caret symbol (
^), but this does not support letters.
To place an actual caret into your text, use the caret twice in a row (e.g.:
Hexadecimal input (
\ (backslash) character followed by two hexadecimal digits – characters 0–9 and A–F – creates a hexadecimal input code. Hexadecimal input codes are mainly relevant for cutscenes, where they are used for special control codes. However, they can also be used to place ASCII characters. This can be used for obfuscation, as the game will interpret the code as whatever character is mapped to it (e.g.:
\48INT = will be read as
HINT = ).
Like with the caret, to place an actual backslash into your text, use it twice in a row (e.g.:
MainCfgSOC block, see MainCfg.
The most common way to load SOCs is to add them to a WAD or PK3 file as a text lump. In PK3 files, lumps in the
SOC/ folder are recognized as SOC lumps by SRB2 and are loaded automatically upon loading the PK3 file, in the order that they are found in the file. In WAD files, lumps with the name
OBJCTCFG and lumps with the name prefix
SOC_ (since v2.1.15) are loaded automatically. SOC lumps that do not meet these requirements are not loaded automatically. However, the console command
runsoc can be used to load them after the WAD or PK3 file has been added. The level header parameter
RunSOC can be used to load a SOC lump upon starting a certain level.
Alternatively, SOCs can be stored as standalone files with the file ending
.soc. They can be loaded via the Addons menu or by using the console command
runsoc. As with SOC lumps, the level header parameter
RunSOC can be used to load a SOC file upon starting a certain level.
Types of SOC-modifiable data
Document what the new SOC block types do!
The following is a list of all data types that can be modified via SOC. In bold at the start of each entry is the name of the identifier for the data type, which starts the block header. For more information on a specific data type, click on the corresponding link.
Clear: This is a special command that can be used to remove SRB2's own data for level headers, emblems, extra emblems, unlockables and/or condition sets. If this command is not used, all data that is not overwritten will remain unchanged.
MainCfg: This is a special block that is used to modify certain global game settings, such as the timers of various power-ups and other timed effects, the name of the gamedata and save files, the location of the Special Stages and the first Single Player stage, and other miscellaneous settings. Unlike other blocks, the header for this block consists only of the data type identifier and contains no slot number.
These entries control data relating to Objects in SRB2. Note that SOC is not meant to be used to create complex custom AI for Objects. While it is possible with SOC to create state sequences that make use of SRB2's pre-defined Object actions, this approach is very limited and can quickly become convoluted. For any behavior that cannot be easily recreated with SRB2's standard actions, Lua should be used to write custom behavior code.
Object: This data type sets the properties of an Object type, which are shared by all Objects belonging to the type and determines how they are spawned in-game. Properties include a set of anchors for special states and sounds, the default flags for an Object of this type, and other general settings. This data type is not to be confused with Objects themselves or their properties.
State: This data type sets the properties of states, which are used to control the behavior and appearance of Objects. Properties include the displayed sprites, the duration, the next state and the performed action.
Sound: This data type sets the properties of sound effects, which may be used to accompany Objects but can be used independently as well.
Freeslot: This is a special block that is used to declare new constants for Object types, states, sounds and sprites that are placed in freeslots. Unlike other blocks, the header for this block consists only of the data type identifier and contains no slot number.
More information on the entries in this category can be found in the Custom unlockables and emblems article.
Emblem: This data type sets the properties of map-specific emblems, including emblems that are hidden in a map itself and emblems that are awarded for Record Attack achievements.
ExtraEmblem: This data type sets the properties of extra emblems, which are awarded for meeting certain game-wide requirements.
Unlockable: This data type sets the properties of unlockables, such as their type and the conditions for unlocking them.
ConditionSet: This data type is used to create requirements for earning unlockables and extra emblems. The requirements can be chosen and combined from a large set of pre-defined conditions.
Wipes: This data type sets the properties of the screen fade effects that SRB2 uses in certain situations.
Character: This data type is used to define the character select entries for custom characters. It is not used to set the properties of the character itself.
Level: This data type is used to define level headers, which include metadata for maps such as their name, act number, background music, background sky and other properties.
Scene: These two data types are used to define custom cutscenes, which can be used as the intro, credits sequence, or between levels.
Prompt: This data type is used to define text prompts, like the ones seen in the Tutorial. Handles talksprites as well as images/image sequences such as the how-to-play animations.
HudItem: This data type sets the position of the text and graphic items that make up the head-up display.
- Constants: A list of constants which can be used in SOCs.
- Glossary: Lists, among others, important SOC terms.
- List of Object types: A list of all Object types, containing slot numbers, real names and descriptions.
- List of states: A list of all states, containing slot numbers, real names and descriptions.
- Actions: A list of all actions.
- List of sprites: A list of all sprites, containing slot numbers, real names and descriptions.
- List of sounds: A list of all sounds, containing slot numbers, real names and descriptions.
- List of HUD items: A list of all HUD items, containing slot numbers, real names and descriptions.
- Custom Object tutorial: A tutorial for creating and modifying Objects via SOCs.
|Sonic Object Configuration||[view]|
|Related links||Actions • Constants • Custom Object tutorial|