-
Notifications
You must be signed in to change notification settings - Fork 18
EDT Map script format
Our edt file format takes some inspiration from Synergy, however, has been built from the ground up specifically for the needs of this project. It allows to configure a map with co-op related settings as well as do some significant modifications to it. It uses Valve's keyvalues syntax which can inherit properties from parent configs.
- Checkpoint system
- Equipment system
- Advanced entity editing system
- Conditions (if-then-else)
- Regex matching
- Delayed mapchange and delayed map start support
- Support for various map intros
- Setup convars, plugin features and more
To enable coop mode on desired map, an edt file for it needs to be created first. EDTs are searched at locations in this order:
- sourcemod/data/srccoop/mapname.edt
- maps/mapname.edt (This location can also be loaded from inside the bsp, therefore enabling embedded configs)
If you're adding a new edt, it's recommended to start with the included samples.
The entity list for current map can be dumped to a file with sc_dump
.
#base "..."
"config"
{
"param1" "value"
"param2" "another value"
// ..etc.. (this is a comment)
"features"
{}
"define"
{}
"console"
{}
"equipment"
{}
"entity"
{}
"checkpoint"
{}
}
- #base optionally specifies the parent config to inherit values from. The path is relative to the current file. Think of it as copying elements from the parent to this file, with this file taking precedence if property names clash. Multiple levels of nesting are allowed.
- config is the root element and is required. It can contain properties and other sub-elements.
- elements inside config are optional
- base configs may use entity_base_* instead of entity in order to not collide with other edt's entity modifications when merging the files.
By putting a value between forward slashes, you can create a regex match. This uses sourcemod's internal regex extension, that is PCRE. Regex is supported in most properties that match some value.
Examples:
Regex | Description |
---|---|
"/^(suit|weapons|ammo)$/" | Matches the values "suit", "weapon" or "ammo" |
"/^snds_conveyors/" | Matches all values starting with "snds_conveyors" |
"/.*/" | Matches all possible values |
Go to regex101.com to test and build your regexes.
Conditions allow to selectively parse sub-elements by testing the given condition against known states. The #else block is optional.
Basic - all conditions must be true:
#if
{
"condition1" "tested value"
"condition2" "tested value"
...
#then
{
...
}
#else
{
...
}
}
At least 1 condition must be true:
#if
{
#any
{
"condition1" "value"
"condition2" "value"
}
#then
{
...
}
#else
{
...
}
}
Mixing and nesting is possible - either condition 1 or both 2 and 3 must be true:
#if
{
#any
{
"condition1" "value"
#all
{
"condition2" "value"
"condition3" "value"
}
}
#then
{
...
}
#else
{
...
}
}
Conditions:
Condition | Description |
---|---|
globalstate | Tests whether the given engine global state is currently active |
prevmap | Tests for the name of previous map |
os | Tests the server operating system - linux or windows
|
To negate the condition, add !
in front of it.
When a condition is not found, the "define" list is searched. If the condition is not even found in defines, the result will be false.
Property | Plugin | Type | Description | Repeatable | Regex | Default |
---|---|---|---|---|---|---|
campaign | voting | string | The campaing, used as first category for map voting. | |||
chapter | voting | string | The chapter, used as second category for map voting. | |||
nextmap | core | string | Tells the mod which trigger_changelevel entities are allowed by comparing their map name with this value. Depending on the transitions in the map, can be specified to prevent players from backtracking. | ✔️ | ✔️ | |
intro_type | core | string | Used together with delayed entity outputs. "freeze" freezes players in place until everyone connects or the startup timer runs out, "none" - players walk around freely and "fade" - same as freeze but fades from black. |
none | ||
voting_skip_to | voting | string | If this is an intro map, set the map a successful skip vote will change to. | |||
voting_skip_autostart | voting | bool | If this is an intro map, whether to start a skip vote automatically. | 0 | ||
allow_server_download | workshop manager | bool |
1 to use direct server download for workshop maps. Not recommended - see "Authoring maps for SourceCoop". |
0 |
Sets up enabled plugin features for the map. Usually defaulted in base configs.
Example - disable first person death camera:
"features"
{
"FIRSTPERSON_DEATHCAM" "0"
}
Sets up defines, which consist of a name and value (like convars). Usually setup in base configs and overridden in map config to simplify the configuration between the two. For example, the base config can do a specific action, only if the define is set to 1. The map config can override the define to 0 to prevent the action.
Example - base/pizza_base.edt:
"define"
{
"all_is_pizza" "1"
}
"entity_base_pizza"
{
#if
{
"all_is_pizza" "1"
}
#then
{
"modify"
{
"model" "/.*/"
"set"
{
"model" "models/props_junk/interdimensional_pizza.mdl"
}
}
}
}
melon_map.edt:
"define"
{
"all_is_pizza" "0"
}
Lets you setup server console variables (convars) for the map. They are loaded before any server configs and will be reverted to their default value after the map ends.
Example - enable item spawn effects:
"console"
{
"sv_mp_spawneffect_item" "1"
}
Sets up the state and items players spawn with.
Example - Spawn with crowbar, mp5, 70 hp and 15 suit:
"equipment"
{
"item" "item_weapon_crowbar"
"item" "item_weapon_mp5"
"item" "item_suit"
"health" "70"
"armor" "15"
}
Example - Import equipment from the map:
"equipment"
{
"lookup"
{
"targetname" "items_at_start"
}
}
Note: Spawning with default MP equipment is controlled by enabled features.
This section allows modifying map's entities before the level starts.
Small number of entities are precompiled into the map and cannot be modified - for example static lights and props.
Brush entities have a "model" property which starts with * followed by number. The matching geometric model representation is saved separately in a different "lump" of the map and cannot be altered. SourceCoop can however create basic "box" brushes that can be used for invisible entities like triggers.
Alt: create
Adds an entity.
Example - add an ambient_generic:
"add"
{
"classname" "ambient_generic"
"targetname" "gman_offer_fix"
"spawnflags" "49"
"message" "endgame.gman.wiselydone01"
}
Alt: delete
Deletes entities with matching properties. Additional properties narrow down the filter. Supports regex in key and value.
Example - delete entity with name trigger_slamdoor:
"delete"
{
"targetname" "trigger_slamdoor"
}
Alt: edit
Modifies entities with matching properties. Additional properties narrow down the filter. Supports regex in key and value.
Alt: create
, replace
, set
Adds properties to the entity. Replaces existing.
Alt: delete
Removes properties from the entity. Only the key is matched, the value can be left empty.
Example - make a changelevel entity stay enabled:
"modify"
{
"targetname" "c1a4a_c1a4b_transition"
"add"
{
"StartDisabled" "0"
}
"remove"
{
"targetname" ""
}
}
* = Modify or Add
When modifying or adding an entity, there are additional helpers, used as subsections, which make precise editing easier.
Property | Plugin | Type | Description | Repeatable | Regex | Default |
---|---|---|---|---|---|---|
use_map_spawnpoint | core | bool | Add spawn point from map as the first checkpoint (currently just info_player_start). | 0 | ||
use_map_autosave | core | bool | Add autosave from map as checkpoints (currently just trigger_autosave). | 0 | ||
strict_order | core | bool | Whether checkpoints must activate in the same order as defined. Not applicable if using use_map_autosave. | 1 |
Property | Plugin | Type | Description | Repeatable | Regex | Default |
---|---|---|---|---|---|---|
origin | core | vector | Destination location | 0 0 0 | ||
angles | core | vector | Destination orientation | 0 0 0 | ||
triggerid | core | string | Entity which activates this checkpoint with an output. Accepts targetname or hammerid. | |||
output | core | string | Output from the trigger entity which activates this checkpoint. | |||
delay | core | float | Delays the checkpoint activation, in seconds. | 0 | ||
followid | core | string | Set to move the checkpoint with an entity. If set, origin and angles become relative to the entity. Accepts targetname or hammerid. | |||
touchid | core | string | Entity which activates this checkpoint when touched by a player. Accepts targetname or hammerid. | |||
portal | core | vector | Location of the portal teleporter to spawn when this checkpoint becomes active. | |||
bringall | core | bool | Teleport all players here upon activation. | 0 | ||
bringall_radius | core | float | Maximum range from the destination a player is allowed to be in order to not be teleported by bringall. | 0 |
Example:
"checkpoint"
{
"use_map_autosave" "1"
"spawn"
{
"origin" "-13200 -2544 9878"
"angles" "0 0 0"
}
"doubledoor"
{
"origin" "-10747 -1900 9573"
"angles" "0 30 0"
"triggerid" "bd_door"
"output" "OnOpen"
}
}
Checkpoints without a way to activate are assumed to be initial spawn points and will activate on start.
Checkpoint names can be anything descriptive, they are unused at the moment.