-
Notifications
You must be signed in to change notification settings - Fork 38
Unified FGD
The FGD syntax used in this repository is enhanced compared to Valve's format with a number of changes. This allows the same set of definitions to adapt to different game branches, and accurately describe the type of each keyvalue. The primary change is to allow defining "tags" for each of the various properties in an entity, inside squarebrackets:
@PointClass base(Base1, Base2) helper1() helper2() = classname: "Description"
[
keyvalue[tag1, tag2](integer) : "Pretty Name" : 0
keyvalue2[tag3](choices) : "Choices Keyvalue" : 0 =
[
0: "Option 1"
1: "Option 2"
2: "Extra Option" [tag]
3: "Removed Option" [!tag]
]
input Input[tag](void) : "Description"
output Output[tag](void) : "Description"
]
All tags are optional, but if present they allow only outputting the associated section if the tags are met. Names can appear multiple times with different tags specified, to allow you to swap between two options. In this case the tagged value overrides the untagged value.
Each tag is a comma-separated list of names which must be satisfied to add the associated section. Several prefixes can be placed before the name to change how it behaves:
-
tag
: For unprefixed tags, at least 1 of them must be true to succeed. For example,[EP1, EP2]
would match either Episode. -
+tag
: This specifies that this tag must be present to succeed. For example[L4D, L4D2, ASW, +flower]
would match any of those three games plus theflower
feature. -
-tag
,!tag
: This specifies that the tag must not be present. For example,[!P2]
would match any game other than Portal 2.
Tags mainly are used to match the specific game which will be exported, as well as a few special names:
-
HL2
,EP1
,EP2
,TF2
,P1
,L4D
,L4D2
,ASW
,P2
,INFRA
,CSGO
,SFM
: These match the associated games. -
SINCE_<game>
: This tag matches the specified game, plus any game which released after it (based on the above list). Sosince_L4D
will succeed for Left 4 Dead 2, Portal 2, etc. -
UNTIL_<game>
: This tag will match any game released before the specified game (based on the above list). This allows specifying features removed in a specific game. -
MBASE
: Specifies features exclusive to Mapbase - should be used in conjunction withHL2
orEP1, EP2
, as appropriate. -
INSTANCING
: Specifies engines which supportfunc_instance
- which has been backported to several games. -
INST_IO
: Specifies engines which additionally supportfunc_instance_io_proxy
. -
VSCRIPT
: Specifies engines which support VScript. -
PROP_SCALING
: Specifies engines which suppport the "prop scale" option onprop_static
. -
SRCTOOLS
: Should be used for options/entities requiring the postcompiler to function. -
PROPPER
: Set on all the pseudo-entities used for Propper support. -
ENGINE
: This tag is used for some very special situations, see below.
The unified FGD database is split into individual files for each entity. If duplicate definitions occur, the order in which files are parsed could affect the final result. Some special functionality is implemented to avoid this.
- Entity bases are not evaluated immediately, but evaluated after all files are parsed. Checks are done to ensure two files do not define ents with the same name (but it is permitted to do so within the same file).
- Only snippets within the
snippets/
folder are shared - for all other files, snippets are local to that file (but override shared ones). - The additional "extra" FGD folder is not isolated, and can overwrite all defintions (or use
@ExtendClass
).
The full parse order is as follows:
- Base
snippets/
folder - Any extra files named
snippet_XXX.fgd
- Auto Visgroups config file
- All other base files
- All other extra files
The syntax uses two additional helper()
commands in the header of entities. Neither are inherited through base()
.
-
appliesto(tag1, tag2)
: This allows specifying tags for an entire entity, removing it it from the output FGD for games that do not match. For base classes that fail this check, they will also not be exported and will be stripped from any entities that had inherited from them. This allows adding/removing a set of helpers or keyvalues. -
autovis(vigroup1, visgroup2, visgroup3, ...)
: This helper provides an easier method to specify a nested set of auto-visgroups an entity will be placed in. First, an impliedAuto
group is added to the beginning if not already present. Then each group is nested successively in the previous, with the entity added to all of them. For example,autovis(Auto, Entities, Point Entities, Filters)
might be appropriate for a filter entity.
The ENGINE
tag is used for a number of special purposes, mainly to indicate if the actual game itself does or does not use a keyvalue - as opposed for it being there for compilers or other uses. This is used by parts of the postcompiler to know that it can ignore or specially handle these options. It is used as follows:
-
choices
is not really a data type keyvalues can have - it merely provides a number of preset strings. So the compiler can know what the real type of the value is, allchoices
values should have a[ENGINE]
-tagged copy of the keyvalue with a real type and default value. -
appliesto(-engine)
is used to indicate so-called "internal" entities likefunc_detail
that are removed during compilation, and so don't appear ingame. This allows code to know that it not appearing in game dumps is fine. -
appliesto(engine)
can be used to define "hidden" entities which do exist, but aren't usually placed by a mapper directly. For example theplayer
entity would be marked this way. This prevents it from being exported into the normal FGD.
Snippets are a system that allows reusing sections of the file to reduce duplication. When read in, they get expanded to a full definition. The syntax is in two parts, the definition and usage.
Definitions are as follows:
@snippet type replace "somename" = ...
The name is a unique identifier for this bit of data. The type specifies what sort of section this is, and controls what appears after the =
. Once a snippet is defined, it can be used by writing #snippet "somename"
in a relevant location in the file.
replace
is an optional keyword - if specified, this
snippet must already exist, and this definition will overwrite the existing one.
Otherwise for most types it is an error to define the same name twice. This is
intended to be used in "extra" FGD definitions to override regular snippets.
The current snippet types are as follows:
This type comprises a long description, and can be used in an entity header or the end of a keyvalue/IO definition to reuse a description multiple times.
These correspond to the = [...]
array of options for these keyvalue types, and can be used to reuse them in multiple locations. The #snippet
can be used directly after the =
at the end of a keyvalue, or inside the []
brackets to have the options added onto a larger list.
This is an entire keyvalue or IO definition, allowing it to be inserted in a specific location in an entity definition. Multiple definitions can be specified
for these - when inserted, all values will be added together. As a shorthand,
the value can be wrapped in []
to allow specifying the whole block together.
Here is an example of various snippet types:
@snippet description "SomeDescription" = "A long description that might " +
"be used multiple times."
@snippet choices "Binary" = [
0: "No"
1: "Yes"
]
@snippet choices "Ternary" = [
#snippet Binary // Merges the values.
-1: "Missing"
]
// These two are combined, both are added.
@snippet input "KillEnt" = Kill(void) : "Kill the entity."
@snippet input "KillEnt" = Resurrect(void) : "Saves the entity from death."
// This is a shorthand to specify a full block.
@snippet output "UserOutputs" = [
OnUser1(void) : "User1"
OnUser2(void) : "User2"
]
@snippet keyvalue "Enable" = enabled(choices) : "Enabled" : #snippet "SomeDescription" = #snippet Ternary
@snippet description replace "SomeDescription" = "Changes the existing description."
@PointClass base(BaseEntityPoint) = sample_entity
[
disabled(choices) : "Disabled" : #snippet "SomeDescription" = [
#snippet Ternary
2: "Extra value"
]
#snippet keyvalue Enable // Appears in between these, unlike a base.
message(string) : "Message"
#snippet input "KillEnt"
#snippet output "UserOutputs" // Adds both at once.
]
@PointClass = another_entity
[
#snippet input KillEnt
]
In addition to tags, this repository includes @resources
definitions for entities, to specify the resources (materials, models, sounds etc) that the entity is coded to use automatically. This allows packing of resources in more unusual circumstances. The definition looks like so:
@PointClass = classname
[
...
@resources [
material "tools/toolsblack.vmt" [-episodic]
func npc_base
entity env_alyxemp [+episodic]
sound "World.WaterImpact"
]
]
Each line defines a resource, composed of a type, a name/path, and optionally some tags. The tags follow the same syntax, but the names used here are different to the other FGD tags. This is because these tags are evaluated by the compiler, instead of being evaluated when the output FGD file is generated. Resources may be defined on a base class, and will be inherited automatically if specified there.
The following types are supported:
-
file
: Specifies a generic file relative to the game folder, with no special handling. -
entity
: Indicates that this entity itself spawns another entity, so the resources defined there should be recursively included. -
func
: This executes code insrctools._class_resources
to handle conditional resources and other special cases. These are passed the actual entity involved if possible. An example use case is thefunc_button_sounds
func, which includes theButton.sndXX
soundscriptsfunc_button
and similar entities use for their sounds.
-
snd
,sound
: Specifies either a soundscript entry, or a raw WAV sound. -
particle
: Specifies the name of a particle system, causing the relevant.pcf
to be located. -
vscript_squirrel
: Specifies a Squirrel.nut
VScript file. -
mat
,material
: Specifies a.vmt
material. Thematerials/
prefix and.vmt
extension are added automatically. -
tex
,texture
: Specifies a.vtf
texture. Thematerials/
prefix and.vtf
extension are added automatically. -
scene
,choreo
: Specifies a.vcd
choreo scene. Currently not yet implemented. -
mdl
,model
: Specifies a.mdl
model, along with the other required files. For this type, a path likemodels/some_prop.mdl#2,3,8
allows specifying that only certain skins are required. If not specified, all skins are included. -
break_chunk
: Specifies special names for generic gibs defined inscripts/propdata.txt
, likeCeilingTile
andWoodChunks
. -
weapon_script
: Specifies the path to a weapon script file, defining viewmodels, sounds and similar values.
These are the current list of tags required. Unlike the regular list, we only need them to distinguish different engine versions which have different behaviour for the same entity:
-
hls
: Half Life: Source causesfunc_breakable
to produce a different set of items. -
hl2
: HL2 has some Gravity-Gun specific behaviours on base prop entities. -
episodic
: If the engine is compiled withEPISODIC
, several things change like the existance of Antlion Workers. This is enabled for EP1/2 and Portal. -
tf2
: Currently doesn't affect resources. -
mapbase
: Includes resources for additional Mapbase features. -
entropyzero2
: Entropy Zero 2 adds variants for many entities. -
mesa
: Black Mesa totally overrides several entities with the same names as HL1 ents. -
p2
: Portal 1 and 2 use different designs for the same entity, like Turrets for example.