Level Editor/Scripting/Zones

From TeamSpec Wiki
Revision as of 03:46, 20 October 2026 by TeamSpecBot (talk | contribs) (Level Editor: zones scripting guide)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

A zone is a volume your script reacts to: a capture point, a spawn room, a deposit area, a hazard. Every area trigger in the map is a zone, and your script decides what each one means by its name.

Making a zone

  1. Build a brush of the shape you want with any shape tool. It can be carved and subtracted like any brush, so a zone can follow the shape of a room.
  2. With it selected, tick Is Area in the inspector. The brush is no longer solid or visible in the game; it only marks out space.
  3. Set Trigger Name to the name your script will match, for example Capture Point. Left blank, the brush's own name is used.
  4. Set Zone Team if the zone belongs to a team (0 means neutral).

Zone brushes draw translucent in the editor. Edit > Click Through Zone Brushes lets you click what is behind them, and Area Trigger Opacity in Settings changes how strongly they draw.

Names, keys and labels

Several zones may share a name: one "Spawn Room" per team is the natural way to build a map, told apart by their team. So a zone has two names:

  • Its key, which the hooks hand you as zone. Every key is unique: when two zones share a name, the second one's key gets a number added.
  • Its label, exactly the name you typed. api.zone_label(zone) returns it.

Compare labels, not keys. zone == &"Capture Point" only ever matches the first zone with that name; api.zone_label(zone) == &"Capture Point" matches all of them. Tell same-named zones apart with api.zone_team, and find them all with api.zones_labelled. Names are matched exactly, including capitals and spaces.

Zone hooks

func _zone_entered(zone: StringName, entity_id: int) -> void:
	pass

func _zone_exited(zone: StringName, entity_id: int) -> void:
	pass

func _zone_tick(zone: StringName, occupants: Array, delta: float) -> void:
	pass
  • _zone_entered runs when a player comes into a zone.
  • _zone_exited runs when they go out of it, and also when they die or leave the match inside it. Do not assume an exit means they are alive somewhere else.
  • _zone_tick runs every server tick for every zone, including empty ones, so a capture meter can drain when nobody is on the point. occupants is sorted.
  • Only living players count. What counts is the player's position: they are inside when the point they stand on is inside the volume.
  • _zone_used runs when a player standing in a usable zone presses the use key. A zone is usable when it has a Use Prompt, which the HUD shows to anyone inside it. See _zone_used.

To ask at any other moment: api.zones, api.zone_occupants and api.zone_position. The hooks are the cheaper way; there is no need to check every zone yourself in _tick.

A zone can also act without a script: its Outputs in the inspector fire another entity's input (open a door, trigger a relay) when a player comes in or goes out. See Logic and outputs.

The world boundary

Place one World Boundary from the Functional menu, below everything a player can stand on. It is a flat plane through the marker: anybody whose position falls below it has left the world.

That does not arrive through _zone_entered. It calls _left_world(entity_id), which by default kills the player with nobody credited. Override it to do something else, such as putting them back:

func _left_world(entity_id: int) -> void:
	api.teleport(entity_id, _spawn_position(entity_id))

Do not name a zone WorldBoundary; that name belongs to the boundary.

Moving zones

A zone brush placed under a moving platform (Functional > Create Anchor Platform) moves with the platform, so a lift can carry a capture point. Nothing changes in the script: the zone arrives through the same hooks, and api.zone_position follows it.

A payload cart carries a zone of its own too; see Payload tracks.

TeamSpec Level Editor
Basics Getting started · Interface · Viewport and camera · Selecting and hiding · Keyboard shortcuts · Settings · Map Config · Troubleshooting
Menus File · Edit · View · Tools · Functional
Panels Scene tree · Inspector · Materials · Props · Snapping · UV editor · Displacement · Terrain
Tools Move, Rotate and Scale · Box · Sphere · Cylinder · Prism · Stairs · Spiral Stairs · Spiral Tower · Arch · Path Brush · Plane · Terrain · Clip · Duplicate · Ruler and Cordon · Edit Vertex and Edge · Edit Face · Loop Cut · Material Brush · Vertex Color Brush · Displacement · Prop Path
Entities Brush · Zone · Group · Mirror Node · Prop · Spawn Point · Supply Pickup · World Boundary · Lights · Water · Sounds · Anchor Platform · Payload Track · Boss Spawn · Map Marker · World Text · Decal · Door · Button · Logic entities · 3D Skybox · Nav Region
Workflows Your first map · Brushes and CSG · Materials and UVs · Lighting and lightmaps · Bots and navigation · Mirrored maps · Outputs and logic · Custom assets · Playtesting · Exporting and publishing · Importing Source maps
Scripting Overview · Server rules · Client HUD · Bots · Teams and spawning · Zones · Pickups · Payload tracks · Map entities · Sandbox limits · Testing · King of the Hill · Team Deathmatch · API reference · What a script may use