Skip to content
Spencer Brown edited this page Mar 14, 2024 · 4 revisions

Unified FGD Alterations

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.

Tag prefixes

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 the flower feature.
  • -tag, !tag: This specifies that the tag must not be present. For example, [!P2] would match any game other than Portal 2.

Available Tags

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). So since_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 or EP1, EP2, as appropriate.
  • INSTANCING: Specifies engines which support func_instance - which has been backported to several games.
  • INST_IO: Specifies engines which additionally support func_instance_io_proxy.
  • VSCRIPT: Specifies engines which support VScript.
  • PROP_SCALING: Specifies engines which suppport the "prop scale" option on prop_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.

Additional "helpers"

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 implied Auto 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

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, all choices 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 like func_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 the player entity would be marked this way. This prevents it from being exported into the normal FGD.

Snippets

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 "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.

The current snippet types are as follows:

description / desc

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.

choices / spawnflags

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.

keyvalues / kv / input / output

This is an entire keyvalue or IO definition, allowing it to be inserted in a specific location in an entity definition.

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
	-1: "Missing"
]

@snippet input "KillEnt" = Kill(void) : "Kill the entity."

@snippet keyvalue "Enable" = enabled(choices) : "Enabled" : #snippet "SomeDescription" = #snippet Ternary


@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"
]

@PointClass = another_entity
[
	#snippet input KillEnt
]

Resource definitions

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.

Resource types

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 in srctools._class_resources to handle conditional resources and other special cases. These are passed the actual entity involved if possible. An example use case is the func_button_sounds func, which includes the Button.sndXX soundscripts func_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. The materials/ prefix and .vmt extension are added automatically.
  • tex, texture: Specifies a .vtf texture. The materials/ 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 like models/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 in scripts/propdata.txt, like CeilingTile and WoodChunks.
  • weapon_script: Specifies the path to a weapon script file, defining viewmodels, sounds and similar values.

Resource tags:

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 causes func_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 with EPISODIC, 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.