Level Editor/Scripting/Reference/GamemodeServerApi

Reached as api from server.gd. Reached as api from bot.gd.

What a server script can do: everything that changes the match.

Reached as api in server.gd, and in bot.gd, which shares the very same object. Players, zones, pickups and tracks are always plain ids and names.

See Level Editor/Scripting/Reference for every class, and Level Editor/Scripting/Reference/Sandbox for the rest of GDScript a script may use.

Methods

declare_player_counter

declare_player_counter(name: StringName, initial: int = 0, minimum: int = 0, maximum: int = 0x7FFFFFFF) -> void
Method · Available to server.gd, bot.gd

Declare a counter with one value per player. Only in _declare(). Every write is held between minimum and maximum, and every player starts at initial.

Parameters
  • name: StringName
  • initial: int, default 0
  • minimum: int, default 0
  • maximum: int, default 0x7FFFFFFF
    Returns: void

declare_team_counter

declare_team_counter(name: StringName, initial: int = 0, minimum: int = 0, maximum: int = 0x7FFFFFFF) -> void
Method · Available to server.gd, bot.gd

Declare a counter with one value per team. Only in _declare(). Every write is held between minimum and maximum, and every team starts at initial.

Parameters
  • name: StringName
  • initial: int, default 0
  • minimum: int, default 0
  • maximum: int, default 0x7FFFFFFF
    Returns: void

declare_global_counter

declare_global_counter(name: StringName, initial: int = 0, minimum: int = 0, maximum: int = 0x7FFFFFFF) -> void
Method · Available to server.gd, bot.gd

Declare a counter with one value for the whole match. Only in _declare(). Every write is held between minimum and maximum; it starts at initial.

Parameters
  • name: StringName
  • initial: int, default 0
  • minimum: int, default 0
  • maximum: int, default 0x7FFFFFFF
    Returns: void

get_player

get_player(entity_id: int, name: StringName) -> int
Method · Available to server.gd, bot.gd

A player counter's value for one player. 0 for a counter that was never declared.

Parameters
  • entity_id: int
  • name: StringName
    Returns: int

set_player

set_player(entity_id: int, name: StringName, value: int) -> int
Method · Available to server.gd, bot.gd

Set a player counter for one player, held to its declared range. Returns the value stored.

Parameters
  • entity_id: int
  • name: StringName
  • value: int
    Returns: int

add_player

add_player(entity_id: int, name: StringName, delta: int) -> int
Method · Available to server.gd, bot.gd

Add to a player counter for one player (a negative delta subtracts), held to its declared range. Returns the value stored.

Parameters
  • entity_id: int
  • name: StringName
  • delta: int
    Returns: int

get_team

get_team(team: int, name: StringName) -> int
Method · Available to server.gd, bot.gd

A team counter's value for one team. 0 for a counter that was never declared.

Parameters
  • team: int
  • name: StringName
    Returns: int

set_team

set_team(team: int, name: StringName, value: int) -> int
Method · Available to server.gd, bot.gd

Set a team counter for one team, held to its declared range. Returns the value stored.

Parameters
  • team: int
  • name: StringName
  • value: int
    Returns: int

add_team

add_team(team: int, name: StringName, delta: int) -> int
Method · Available to server.gd, bot.gd

Add to a team counter for one team (a negative delta subtracts), held to its declared range. Returns the value stored.

Parameters
  • team: int
  • name: StringName
  • delta: int
    Returns: int

get_global

get_global(name: StringName) -> int
Method · Available to server.gd, bot.gd

A global counter's value. 0 for a counter that was never declared.

Parameters
  • name: StringName
    Returns: int

set_global

set_global(name: StringName, value: int) -> int
Method · Available to server.gd, bot.gd

Set a global counter, held to its declared range. Returns the value stored.

Parameters
  • name: StringName
  • value: int
    Returns: int

add_global

add_global(name: StringName, delta: int) -> int
Method · Available to server.gd, bot.gd

Add to a global counter (a negative delta subtracts), held to its declared range. Returns the value stored.

Parameters
  • name: StringName
  • delta: int
    Returns: int

transfer_player

transfer_player(entity_id: int, name: StringName, amount: int) -> int
Method · Available to server.gd, bot.gd

Add as much of amount to a player counter as its range allows, and return how much actually moved. Always use the return value: adding 5 to a counter with room for 2 moves 2.

Parameters
  • entity_id: int
  • name: StringName
  • amount: int
    Returns: int

transfer_team

transfer_team(team: int, name: StringName, amount: int) -> int
Method · Available to server.gd, bot.gd

Add as much of amount to a team counter as its range allows, and return how much actually moved.

Parameters
  • team: int
  • name: StringName
  • amount: int
    Returns: int

reset_player_counters

reset_player_counters(entity_id: int) -> void
Method · Available to server.gd, bot.gd

Put every one of a player's counters back to its declared starting value. Counters keep their values through a death; call this in _player_spawned when dying should cost a player what they had.

Parameters
  • entity_id: int
    Returns: void

counter_maximum

counter_maximum(scope: int, name: StringName) -> int
Method · Available to server.gd, bot.gd

A counter's declared maximum. scope is SCOPE_PLAYER, SCOPE_TEAM or SCOPE_GLOBAL. 0 for a counter that was never declared. Lets bot.gd read the mode's limits instead of copying them.

Parameters
  • scope: int
  • name: StringName
    Returns: int

declare_team

declare_team(team_name: String, maximum: int = 0) -> int
Method · Available to server.gd, bot.gd

Declare a team and return its id. Only in _declare(). The first team declared is team 1, the next team 2, and so on. A map that declares none plays with two, "Team 1" and "Team 2". maximum caps how many players the team may hold; 0 means no limit.

Parameters
  • team_name: String
  • maximum: int, default 0
    Returns: int

teams

teams() -> PackedInt32Array
Method · Available to server.gd, bot.gd

Every playing team's id, in order. Never includes 0, which means "on no team" and covers both an unplaced player and a spectator.

Returns: PackedInt32Array

team_name

team_name(team: int) -> String
Method · Available to server.gd, bot.gd

A team's name, or "" for a team that does not exist.

Parameters
  • team: int
    Returns: String

team_maximum

team_maximum(team: int) -> int
Method · Available to server.gd, bot.gd

How many players a team may hold, or 0 when there is no limit.

Parameters
  • team: int
    Returns: int

set_spectating

set_spectating(entity_id: int, spectating: bool) -> void
Method · Available to server.gd, bot.gd

Take a player out of the round without disconnecting them, or put them back in with false. While spectating they take no damage, do not collide, cannot use weapons and are not drawn.

Parameters
  • entity_id: int
  • spectating: bool
    Returns: void

is_spectating

is_spectating(entity_id: int) -> bool
Method · Available to server.gd, bot.gd

Whether a player is spectating.

Parameters
  • entity_id: int
    Returns: bool

players

players() -> Array
Method · Available to server.gd, bot.gd

The entity ids of every player in the match, bots included, alive or not, sorted. The map's own bots (spawn_bot) are fixtures, not players, and are left out here and in players_on_team; their hooks still run.

Returns: Array

players_on_team

players_on_team(team: int) -> Array
Method · Available to server.gd, bot.gd

The entity ids of every player on one team, sorted.

Parameters
  • team: int
    Returns: Array

team_of

team_of(entity_id: int) -> int
Method · Available to server.gd, bot.gd

The team a player is on, or 0 for none (not placed yet, or spectating).

Parameters
  • entity_id: int
    Returns: int

party_team_of

party_team_of(entity_id: int) -> int
Method · Available to server.gd, bot.gd

The team this player's Steam party is playing on: where most of the party-mates already in the match are, or 0 when they came alone or none of them has a team yet. The default join seats a player there.

Parameters
  • entity_id: int
    Returns: int

set_team_of

set_team_of(entity_id: int, team: int) -> void
Method · Available to server.gd, bot.gd

Put a player on a team. The mode decides who is on which team.

Parameters
  • entity_id: int
  • team: int
    Returns: void

is_alive

is_alive(entity_id: int) -> bool
Method · Available to server.gd, bot.gd

Whether a player is alive and in play.

Parameters
  • entity_id: int
    Returns: bool

position_of

position_of(entity_id: int) -> Vector3
Method · Available to server.gd, bot.gd

Where a player is now, as of this server tick.

Parameters
  • entity_id: int
    Returns: Vector3

death_position

death_position() -> Vector3
Method · Available to server.gd, bot.gd

Where the player whose death _player_died is handling died. Drop whatever the body leaves behind here, not at position_of. Vector3.INF outside _player_died.

Returns: Vector3

spawn_points

spawn_points(team: int) -> PackedVector3Array
Method · Available to server.gd, bot.gd

The positions of a team's spawn points, as placed in the level editor.

Parameters
  • team: int
    Returns: PackedVector3Array

zones

zones() -> PackedStringArray
Method · Available to server.gd, bot.gd

The key of every zone in the map: every area trigger, the payload carts' push areas, and the world boundary. The zone hooks hand you these keys.

Returns: PackedStringArray

zone_label

zone_label(zone: StringName) -> StringName
Method · Available to server.gd, bot.gd

The name the author gave a zone in the editor. Compare this, not the key: several zones may share a name, but each key is unique.

Parameters
  • zone: StringName
    Returns: StringName

zones_labeled

zones_labeled(label: StringName) -> Array
Method · Available to server.gd, bot.gd

The keys of every zone the author gave this name, in map order.

Parameters
  • label: StringName
    Returns: Array

zone_team

zone_team(zone: StringName) -> int
Method · Available to server.gd, bot.gd

The team a zone belongs to, set as its Zone Team in the editor. 0 is neutral.

Parameters
  • zone: StringName
    Returns: int

zone_occupants

zone_occupants(zone: StringName) -> Array
Method · Available to server.gd, bot.gd

The entity ids of the living players inside a zone, sorted.

Parameters
  • zone: StringName
    Returns: Array

zone_position

zone_position(zone: StringName) -> Vector3
Method · Available to server.gd, bot.gd

Where a zone is in the world: the position of its origin. For pointing a bot at it.

Parameters
  • zone: StringName
    Returns: Vector3

forbid_building

forbid_building(zone: StringName) -> void
Method · Available to server.gd, bot.gd

Nobody may build inside a zone from now until the map ends: a building whose center would stand in it is refused. For your spawn rooms, from _start. A zone on a moving platform cannot be forbidden, and says so in the log.

Parameters
  • zone: StringName
    Returns: void

tracks

tracks() -> PackedStringArray
Method · Available to server.gd, bot.gd

Every payload track's name, in map order: the name the track has in the level editor. Every distance the track calls take or give is meters along the track, 0 at its start. An unknown track reads as 0 or empty, and commands to it are ignored.

Returns: PackedStringArray

track_length

track_length(track: StringName) -> float
Method · Available to server.gd, bot.gd

A track's length in meters.

Parameters
  • track: StringName
    Returns: float

track_checkpoints

track_checkpoints(track: StringName) -> PackedFloat32Array
Method · Available to server.gd, bot.gd

Each checkpoint's distance from the track's start in meters, in order. What reaching one means is up to the mode; usually set_track_floor to it.

Parameters
  • track: StringName
    Returns: PackedFloat32Array

track_markers

track_markers(track: StringName) -> PackedStringArray
Method · Available to server.gd, bot.gd

The names of a track's markers, in order along the track. A marker is a track anchor the map's author named in the editor; it means nothing until your script reads it. The cart passing one calls _track_marker.

Parameters
  • track: StringName
    Returns: PackedStringArray

track_marker

track_marker(track: StringName, marker: StringName) -> float
Method · Available to server.gd, bot.gd

A marker's distance from the track's start in meters, or -1.0 when the track has no marker by that name. For planning ahead of the cart, such as slowing it down before it reaches the marker.

Parameters
  • track: StringName
  • marker: StringName
    Returns: float

track_progress

track_progress(track: StringName) -> float
Method · Available to server.gd, bot.gd

How far the cart has come, in meters, as of this server tick.

Parameters
  • track: StringName
    Returns: float

track_point

track_point(track: StringName, distance: float) -> Vector3
Method · Available to server.gd, bot.gd

The world position a distance along the track, on the line the cart rides. A distance past either end gives that end. Safe in _spawn_position.

Parameters
  • track: StringName
  • distance: float
    Returns: Vector3

track_zone

track_zone(track: StringName) -> StringName
Method · Available to server.gd, bot.gd

The key of the zone the cart carries with it, or &"" for a cart without one. It arrives through the zone hooks like any other zone, and its label is the track's name.

Parameters
  • track: StringName
    Returns: StringName

set_track_speed

set_track_speed(track: StringName, speed: float) -> void
Method · Available to server.gd, bot.gd

Set the speed the cart heads for, in meters per second: negative rolls it back, 0 stops it. The cart speeds up and slows down smoothly, never past its top speed, and stops at either end and at its floor (set_track_floor). Setting the same speed again costs nothing, so set it every tick.

Parameters
  • track: StringName
  • speed: float
    Returns: void

track_speed

track_speed(track: StringName) -> float
Method · Available to server.gd, bot.gd

The speed last set with set_track_speed: where the cart is heading, not how fast it is moving while it gets there.

Parameters
  • track: StringName
    Returns: float

set_track_floor

set_track_floor(track: StringName, distance: float) -> void
Method · Available to server.gd, bot.gd

Stop the cart rolling back past a distance from the start. Raise it to a checkpoint once the cart reaches it, and the checkpoint holds. It never pulls the cart forward. Starts at 0.

Parameters
  • track: StringName
  • distance: float
    Returns: void

set_track_dispenser

set_track_dispenser(track: StringName, team: int) -> void
Method · Available to server.gd, bot.gd

Turn the cart's dispenser on for a team: every few tenths of a second it gives health and ammunition to that team's players standing near it and in its sight, as a built dispenser does, with a heal beam from the lamp on its roof to each of them. That team's bots go to it to heal and restock. 0 turns it off, and it starts off.

Parameters
  • track: StringName
  • team: int
    Returns: void

markers

markers() -> PackedStringArray
Method · Available to server.gd, bot.gd

The name of every Map Marker the map places, in map order. A marker is a named spot and facing the author put in the level editor for a script to read, so a station can move in the editor without the script changing.

Returns: PackedStringArray

marker

marker(marker_name: String) -> Vector3
Method · Available to server.gd, bot.gd

Where the marker named marker_name stands. The origin, and a line in the log, for a name the map does not place.

Parameters
  • marker_name: String
    Returns: Vector3

marker_facing

marker_facing(marker_name: String) -> Vector3
Method · Available to server.gd, bot.gd

The way the marker named marker_name faces, level and one meter long: the arrow at its feet in the editor. A point it looks at is api.marker(n) + api.marker_facing(n) * distance.

Parameters
  • marker_name: String
    Returns: Vector3

parts

parts() -> PackedStringArray
Method · Available to server.gd, bot.gd

The name of every switchable part the map has, in map order. A part is a group the author ticked Switchable in the level editor: everything in it, walls, props and all, comes and goes together, and it starts the way its Starts Enabled box says.

Returns: PackedStringArray

part_enabled

part_enabled(part_name: String) -> bool
Method · Available to server.gd, bot.gd

Whether the part named part_name is there now. False for a name the map does not have.

Parameters
  • part_name: String
    Returns: bool

set_part_enabled

set_part_enabled(part_name: String, enabled: bool) -> bool
Method · Available to server.gd, bot.gd

Put the part named part_name in the world, or take it out with false: it is seen and it blocks, or it is neither, on the server and on every player's screen, including players who join later. Switching it to the state it is in costs nothing. False, and a line in the log, for a name the map does not have.

Parameters
  • part_name: String
  • enabled: bool
    Returns: bool

doors

doors() -> PackedStringArray
Method · Available to server.gd, bot.gd

The name of every door the map has, in map order: the name the author gave it in the level editor.

Returns: PackedStringArray

door_open

door_open(door: StringName) -> bool
Method · Available to server.gd, bot.gd

Open the door named door, as walking up to it would. False if it is locked, and false with a line in the log for a name the map does not have. A door that is open or opening stays so.

Parameters
  • door: StringName
    Returns: bool

door_close

door_close(door: StringName) -> bool
Method · Available to server.gd, bot.gd

Close the door named door, locked or not. A door shut or shutting stays so.

Parameters
  • door: StringName
    Returns: bool

door_toggle

door_toggle(door: StringName) -> bool
Method · Available to server.gd, bot.gd

Close the door if it is open or opening, open it otherwise.

Parameters
  • door: StringName
    Returns: bool

door_lock

door_lock(door: StringName) -> bool
Method · Available to server.gd, bot.gd

Lock the door: walking up to it no longer opens it, nor does door_open, and bots stop pathing through it. An open door stays open until it closes.

Parameters
  • door: StringName
    Returns: bool

door_unlock

door_unlock(door: StringName) -> bool
Method · Available to server.gd, bot.gd

Unlock the door.

Parameters
  • door: StringName
    Returns: bool

door_state

door_state(door: StringName) -> int
Method · Available to server.gd, bot.gd

Where the door is: DOOR_CLOSED, DOOR_OPENING, DOOR_OPEN or DOOR_CLOSING. DOOR_CLOSED for a name the map does not have.

Parameters
  • door: StringName
    Returns: int

door_locked

door_locked(door: StringName) -> bool
Method · Available to server.gd, bot.gd

Whether the door is locked. False for a name the map does not have.

Parameters
  • door: StringName
    Returns: bool

fire_input

fire_input(target: StringName, input: StringName, parameter: String = "", delay: float = 0.0) -> bool
Method · Available to server.gd, bot.gd

Fire input at every entity named target, as an output would: a door (Open, Close, Toggle, Lock, Unlock), a zone by its trigger name (Enable, Disable, Toggle), a relay (Trigger, Enable, Disable, Toggle, CancelPending), a timer (Enable, Disable, Toggle, FireTimer, RefireTime), a counter (Add, Subtract, SetValue, Enable, Disable) or a button (Press, Lock, Unlock). parameter is the number some inputs take, as text ("5"); delay the seconds before it lands. False, with a line in the log, for a name the map does not have.

Parameters
  • target: StringName
  • input: StringName
  • parameter: String, default ""
  • delay: float, default 0.0
    Returns: bool

counter_value

counter_value(counter: StringName) -> float
Method · Available to server.gd, bot.gd

The value of the counter named counter, 0 for a name that is no counter.

Parameters
  • counter: StringName
    Returns: float

bosses

bosses() -> Array
Method · Available to server.gd, bot.gd

The entity id of every boss the map places with a Boss Spawn, in map order. Bosses are level content: they stand whether or not the mode mentions them, and _entity_damaged and _entity_died report what happens to them.

Returns: Array

entity_name

entity_name(entity_id: int) -> StringName
Method · Available to server.gd, bot.gd

The name the author gave the boss's spawn in the editor. Compare this to tell your bosses apart.

Parameters
  • entity_id: int
    Returns: StringName

entity_team

entity_team(entity_id: int) -> int
Method · Available to server.gd, bot.gd

The team whose base the boss guards, as set on its spawn. Its own team's weapons do not hurt it.

Parameters
  • entity_id: int
    Returns: int

entity_health

entity_health(entity_id: int) -> float
Method · Available to server.gd, bot.gd

The boss's health now. A boss heals itself if its spawn says so, once nobody has hurt it for a while; no weapon heals one.

Parameters
  • entity_id: int
    Returns: float

entity_max_health

entity_max_health(entity_id: int) -> float
Method · Available to server.gd, bot.gd

The health the boss started with, as set on its spawn.

Parameters
  • entity_id: int
    Returns: float

entity_alive

entity_alive(entity_id: int) -> bool
Method · Available to server.gd, bot.gd

Whether the boss is still alive. A dead boss sinks and stays dead until revive_boss.

Parameters
  • entity_id: int
    Returns: bool

revive_boss

revive_boss(entity_id: int) -> void
Method · Available to server.gd, bot.gd

Bring a dead boss back where it stood, at full health and idle, as if the round had just begun for it. Nothing happens to a living one. For a practice boss; a boss a match is played over should stay dead.

Parameters
  • entity_id: int
    Returns: void

entity_position

entity_position(entity_id: int) -> Vector3
Method · Available to server.gd, bot.gd

Where the boss stands. It never moves.

Parameters
  • entity_id: int
    Returns: Vector3

entity_zone

entity_zone(entity_id: int) -> StringName
Method · Available to server.gd, bot.gd

The key of the zone that is the boss's arena: the zone named by its spawn's Arena Zone that contains the boss. &"" when its spawn names none or the mode has no zones. It arrives through the zone hooks like any other zone.

Parameters
  • entity_id: int
    Returns: StringName

spawn_pickup

spawn_pickup(kind: StringName, position: Vector3, team: int = 0, lifetime: float = 0.0, radius: float = 1.5) -> int
Method · Available to server.gd, bot.gd

Put a pickup on the ground and return its handle. kind is soul, ammo_small, ammo_medium, ammo_large, health_small, health_medium or health_large. team is whose it is (0 for nobody's), lifetime the seconds it lasts untaken (0 for until somebody takes it), and radius how close a player has to come. It comes to rest on the floor below position.

Parameters
  • kind: StringName
  • position: Vector3
  • team: int, default 0
  • lifetime: float, default 0.0
  • radius: float, default 1.5
    Returns: int

scatter_pickups

scatter_pickups(kind: StringName, origin: Vector3, count: int, spread: float = 1.2, team: int = 0, lifetime: float = 0.0, radius: float = 1.5) -> Array
Method · Available to server.gd, bot.gd

Put count pickups in a ring of radius spread around origin, and return their handles. Every one stays on the near side of any wall between it and origin, so use this, not a loop of spawn_pickup, for what a death drops.

Parameters
  • kind: StringName
  • origin: Vector3
  • count: int
  • spread: float, default 1.2
  • team: int, default 0
  • lifetime: float, default 0.0
  • radius: float, default 1.5
    Returns: Array

despawn_pickup

despawn_pickup(handle: int) -> bool
Method · Available to server.gd, bot.gd

Remove a pickup. False when the handle names nothing. A supply station's pack comes back on the station's usual timer.

Parameters
  • handle: int
    Returns: bool

pickups

pickups() -> Array
Method · Available to server.gd, bot.gd

Every pickup's handle, sorted.

Returns: Array

pickup_kind

pickup_kind(handle: int) -> StringName
Method · Available to server.gd, bot.gd

What a pickup is, or &"" once it is gone.

Parameters
  • handle: int
    Returns: StringName

pickup_team

pickup_team(handle: int) -> int
Method · Available to server.gd, bot.gd

Whose a pickup is (0 for nobody's).

Parameters
  • handle: int
    Returns: int

pickup_position

pickup_position(handle: int) -> Vector3
Method · Available to server.gd, bot.gd

Where a pickup is.

Parameters
  • handle: int
    Returns: Vector3

teleport

teleport(entity_id: int, position: Vector3) -> void
Method · Available to server.gd, bot.gd

Move a player to a position.

Parameters
  • entity_id: int
  • position: Vector3
    Returns: void

kill

kill(entity_id: int) -> void
Method · Available to server.gd, bot.gd

Kill a player, for the mode's own hazards: a pit, a crusher, a trap. Nobody gets the kill. _player_died runs as for any other death.

Parameters
  • entity_id: int
    Returns: void

set_spawn_immunity

set_spawn_immunity(entity_id: int, immune: bool) -> void
Method · Available to server.gd, bot.gd

Make a player immune to damage and keep their reserve ammo topped up, while they move and shoot normally. Healing still works. It lasts until you turn it off; for a spawn room, turn it on in _zone_entered and off in _zone_exited.

Parameters
  • entity_id: int
  • immune: bool
    Returns: void

has_spawn_immunity

has_spawn_immunity(entity_id: int) -> bool
Method · Available to server.gd, bot.gd

Whether a player has spawn immunity.

Parameters
  • entity_id: int
    Returns: bool

set_class_change_allowed

set_class_change_allowed(entity_id: int, allowed: bool) -> void
Method · Available to server.gd, bot.gd

Let a living player change class where they stand, or stop them again with false. A player's first pick, and any pick made while dead, always works. For a spawn room, open it in _zone_entered and close it in _zone_exited.

Parameters
  • entity_id: int
  • allowed: bool
    Returns: void

may_change_class

may_change_class(entity_id: int) -> bool
Method · Available to server.gd, bot.gd

Whether a player may change class where they stand. Changing team costs a player a life unless this is true.

Parameters
  • entity_id: int
    Returns: bool

resupply

resupply(entity_id: int) -> void
Method · Available to server.gd, bot.gd

Refill a player: full health, and full ammo and reserve on every weapon, exactly as a respawn does. Call it from _zone_entered or _zone_tick to make a resupply zone.

Parameters
  • entity_id: int
    Returns: void

respawn_in

respawn_in(entity_id: int, seconds: float) -> void
Method · Available to server.gd, bot.gd

Bring a dead player back after seconds. Call it from _player_died with its default_seconds for the normal timer, or with your own number: "the losing team respawns faster" is a subtraction. A player nobody calls this for stays dead.

Parameters
  • entity_id: int
  • seconds: float
    Returns: void

bots

bots() -> Array
Method · Available to server.gd, bot.gd

The entity ids of every bot in the match, sorted. Bots are also in players. The map's own bots (spawn_bot) are not: they are in map_bots.

Returns: Array

is_bot

is_bot(entity_id: int) -> bool
Method · Available to server.gd, bot.gd

Whether a player is a bot, the map's own included.

Parameters
  • entity_id: int
    Returns: bool

spawn_bot

spawn_bot(bot_name: String, team: int, loadout: String, home: Vector3, bias: Vector3 = Vector3.ONE) -> int
Method · Available to server.gd, bot.gd

Spawn a bot that belongs to the map: a fixture such as a training dummy, not a stand-in for a player. Nobody can kick it, the quick-play filler never trims it, and it takes no player's seat or place in the server's bot count. It is on the scoreboard as bot_name, it obeys orders like any bot, and it is gone when the map is.

loadout names its items by slot, comma-separated, slot 1 first ("Shotgun,Pistol,Cast Iron Pan"); bias spreads the spec points its items leave free (pick, power, support), so Vector3(0, 1, 0) makes it as thicc as the items allow and Vector3(1, 0, 1) as thin. It keeps that loadout for life. Its team is team, set before _player_joined runs, and it appears at home every time it spawns, whatever _spawn_position says. Respawning it is up to _player_died, as for anybody.

Returns its entity id, or 0 when the loadout or the team does not exist (the reason goes to the log). Call it from _start.

Parameters
  • bot_name: String
  • team: int
  • loadout: String
  • home: Vector3
  • bias: Vector3, default Vector3.ONE
    Returns: int

is_map_bot

is_map_bot(entity_id: int) -> bool
Method · Available to server.gd, bot.gd

Whether a player is one of the map's own bots (spawn_bot).

Parameters
  • entity_id: int
    Returns: bool

map_bots

map_bots() -> Array
Method · Available to server.gd, bot.gd

The entity ids of the map's own bots, sorted.

Returns: Array

bot_attack

bot_attack(entity_id: int, target_id: int) -> bool
Method · Available to server.gd, bot.gd

Order a bot to hunt one player. It closes in, fights, and finds them again if it loses them. False when entity_id is not a bot, as for every order.

Parameters
  • entity_id: int
  • target_id: int
    Returns: bool

bot_move_to

bot_move_to(entity_id: int, position: Vector3, arrive_radius: float = 2.0) -> bool
Method · Available to server.gd, bot.gd

Order a bot to go somewhere. It shoots at what it passes but does not chase: the order for a carrier heading home.

Parameters
  • entity_id: int
  • position: Vector3
  • arrive_radius: float, default 2.0
    Returns: bool

bot_defend

bot_defend(entity_id: int, position: Vector3, radius: float = 10.0) -> bool
Method · Available to server.gd, bot.gd

Order a bot to hold ground. It fights anything that comes within radius and returns to position when nothing is there.

Parameters
  • entity_id: int
  • position: Vector3
  • radius: float, default 10.0
    Returns: bool

bot_collect

bot_collect(entity_id: int, handle: int) -> bool
Method · Available to server.gd, bot.gd

Order a bot to go and take a pickup. The order ends by itself when the pickup is gone, and is refused (false) for one that is already gone.

Parameters
  • entity_id: int
  • handle: int
    Returns: bool

bot_roam

bot_roam(entity_id: int) -> bool
Method · Available to server.gd, bot.gd

Hand a bot back to its own devices: hunting whoever is nearest, wandering when there is nobody. What a bot with no orders does.

Parameters
  • entity_id: int
    Returns: bool

bot_escort

bot_escort(entity_id: int, target_id: int) -> bool
Method · Available to server.gd, bot.gd

Order a bot to stay with a player and fight what threatens them first. Ends by itself when that player dies or leaves.

Parameters
  • entity_id: int
  • target_id: int
    Returns: bool

bot_idle

bot_idle(entity_id: int, look_at: Vector3) -> bool
Method · Available to server.gd, bot.gd

Stand still, never shoot, and face look_at: a training dummy.

Parameters
  • entity_id: int
  • look_at: Vector3
    Returns: bool

bot_dodge

bot_dodge(entity_id: int, center: Vector3, radius: float = 4.0) -> bool
Method · Available to server.gd, bot.gd

Strafe and jump at random about centre, staying within radius, facing the nearest enemy and never firing: a moving target for aim practice.

Parameters
  • entity_id: int
  • centre: Vector3
  • radius: float, default 4.0
    Returns: bool

bot_shoot

bot_shoot(entity_id: int, target_id: int) -> bool
Method · Available to server.gd, bot.gd

Stand where it is and fire at target_id and at nobody else, reloading as it runs dry; while the target is dead it waits for it. It does not resupply itself: keep it in ammunition with resupply.

Parameters
  • entity_id: int
  • target_id: int
    Returns: bool

edit_bot_loadout

edit_bot_loadout(entity_id: int, bots: Array, weapons_only: bool = false) -> bool
Method · Available to server.gd, bot.gd

Open the loadout editor for player entity_id on bots (entity ids; the editor shows the first) and let them give every one of them a new loadout: the class window, without the parts a bot cannot keep. Called from _zone_used, the permission lasts while the player stands in that zone; from anywhere else, until they leave the match. The bots take the new loadout at once, at full health. With weapons_only the editor hides the spec points and each bot keeps its own build, re-spread over what its new weapons cost: a range of thin and thicc targets stays thin and thicc. False when bots is empty, names anything that is not a bot, or entity_id is not a human player.

Parameters
  • entity_id: int
  • bots: Array
  • weapons_only: bool, default false
    Returns: bool

bot_build

bot_build(entity_id: int, kind: StringName, position: Vector3, look_at: Vector3, level: int = 1) -> bool
Method · Available to server.gd, bot.gd

Put up a building for one of the map's own bots (spawn_bot) holding a Struction Console, already built, at level (1 to 3), standing on the floor at position and facing look_at. kind is sentry, dispenser, teleporter_entrance or teleporter_exit. It is the bot's building as one it placed itself would be: on its team, upgraded by its wrench, credited to it. A builder has one of each kind, so building a kind it already has takes the old one down. The building outlives the bot's death and falls to damage like any other; bot_demolish or a new loadout for the bot takes it down. Free: it costs the bot no metal. False, and nothing built, for any other bot or player, a bot whose console is not in its hands yet (its loadout arrives a moment after spawn_bot: try again next tick), an unknown kind or a level out of range.

Parameters
  • entity_id: int
  • kind: StringName
  • position: Vector3
  • look_at: Vector3
  • level: int, default 1
    Returns: bool

bot_demolish

bot_demolish(entity_id: int, kind: StringName) -> bool
Method · Available to server.gd, bot.gd

Take down the kind building of one of the map's own bots. False when it has none standing.

Parameters
  • entity_id: int
  • kind: StringName
    Returns: bool

bot_has_building

bot_has_building(entity_id: int, kind: StringName) -> bool
Method · Available to server.gd, bot.gd

Whether one of the map's own bots has a kind building standing: false once players have destroyed it.

Parameters
  • entity_id: int
  • kind: StringName
    Returns: bool

place_building

place_building(key: StringName, kind: StringName, team: int, position: Vector3, look_at: Vector3, level: int = 1) -> bool
Method · Available to server.gd, bot.gd

Put up a building of the map's own, with no builder: kind (sentry, dispenser, teleporter_entrance or teleporter_exit) already built at level (1 to 3), for team, standing on the floor at position and facing look_at. key is the map's name for it: placing under a key that already holds one replaces it. It fights for team like any building, a wrench of that team upgrades and repairs it, and what it does is credited to itself, which the kill feed names: "Sentry Gun" killed you. False, and nothing built, for an unknown kind, a level out of range or a position that is not one.

Parameters
  • key: StringName
  • kind: StringName
  • team: int
  • position: Vector3
  • look_at: Vector3
  • level: int, default 1
    Returns: bool

remove_building

remove_building(key: StringName) -> bool
Method · Available to server.gd, bot.gd

Take down the map's building under key. False when none stands there.

Parameters
  • key: StringName
    Returns: bool

has_building

has_building(key: StringName) -> bool
Method · Available to server.gd, bot.gd

Whether the map's building under key stands: false once it is destroyed.

Parameters
  • key: StringName
    Returns: bool

bot_order

bot_order(entity_id: int) -> StringName
Method · Available to server.gd, bot.gd

What a bot was last ordered: attack, move, defend, collect, escort, roam, idle, dodge, shoot, or &"" for a bot nobody has ordered.

Parameters
  • entity_id: int
    Returns: StringName

bot_set_skill

bot_set_skill(entity_id: int, skill: float) -> bool
Method · Available to server.gd, bot.gd

How good a bot is at fighting, from 0 to 1: aim, reactions and accuracy together. The map decides how hard its bots are; set it in _player_joined.

Parameters
  • entity_id: int
  • skill: float
    Returns: bool

bot_skill

bot_skill(entity_id: int) -> float
Method · Available to server.gd, bot.gd

A bot's fighting skill, from 0 to 1. 0 for a player who is not a bot.

Parameters
  • entity_id: int
    Returns: float

bot_kit

bot_kit(entity_id: int) -> StringName
Method · Available to server.gd, bot.gd

The kit a bot was dealt, such as &"trooper" or &"medic"; &"custom" for a loadout given by hand; &"" for a human or a bot with no kit yet.

Parameters
  • entity_id: int
    Returns: StringName

bot_role

bot_role(entity_id: int) -> StringName
Method · Available to server.gd, bot.gd

What a bot's kit is for: &"assault", &"support", &"defense" or &"sniper", or &"" with no kit. Deal jobs by this: support escorts the carrier, defense holds the base.

Parameters
  • entity_id: int
    Returns: StringName

bot_kits

bot_kits() -> PackedStringArray
Method · Available to server.gd, bot.gd

The name of every kit there is.

Returns: PackedStringArray

bot_set_kit

bot_set_kit(entity_id: int, kit: StringName) -> bool
Method · Available to server.gd, bot.gd

Give a bot a different kit from its next life, never mid-fight. False for a human, a player who is gone, or a kit that does not exist.

Parameters
  • entity_id: int
  • kit: StringName
    Returns: bool

declare_winner

declare_winner(team: int, reason: String = "") -> void
Method · Available to server.gd, bot.gd

Declare the winner and end the round; team 0 is a draw. The game does the rest: the result screen goes up, players vote for the next map, and the server changes to it. reason is a short line the result screen prints under the winning team, such as "held the hill for 60 seconds".

Only the first call counts. Afterwards no zone, pickup or tick hook runs.

Parameters
  • team: int
  • reason: String, default ""
    Returns: void

match_state

match_state() -> int
Method · Available to server.gd, bot.gd

Which phase the match is in: MATCH_LIVE, MATCH_DECIDED, MATCH_RESULT, MATCH_VOTING or MATCH_LOADING. Once the round is decided the game already stops scoring, respawns and the mode's hooks, so a mode only needs this for something of its own that should stop too.

Returns: int

notify

notify(entity_id: int, title: String, body: String = "", warn: bool = false) -> void
Method · Available to server.gd, bot.gd

Flash a message across the top of one player's screen, under the gamemode's widgets, for a few seconds. title is the line; body is a shorter line under it; warn marks something they lose by ignoring, drawn in the warning color and held longer. A new message replaces the one on screen, so send what matters now (a checkpoint reached, your boss under attack), not every hit. Bots are skipped, so looping over players() is fine.

Parameters
  • entity_id: int
  • title: String
  • body: String, default ""
  • warn: bool, default false
    Returns: void

open_tile_map

open_tile_map(entity_id: int, form: StringName, title: String, columns: int, rows: int, options: Array, values: PackedInt32Array, door: float = 0.5) -> bool
Method · Available to server.gd, bot.gd

Open a plan of a grid on a player's screen, seen from its door, which is drawn at the bottom: title over columns x rows tiles, each holding one of your options, with Clear All, Apply and Close under it. Clicking a tile offers every option; Clear All puts option 0 on every tile.

Each option is a Dictionary {"label": "Sentry", "icon": "sentry", "level": 2}: what the picker's button says, the picture on the tile (empty, sentry, dispenser, teleporter, low_wall, high_wall, crates, or "" for the label alone), and a level the tile shows beside it (0 for none). values holds an option index per tile: row 0 is the row nearest the door, each row runs left to right as seen from the door, and the tiles are named that way, A1 in the door's left corner. Apply calls _form_submitted(entity_id, form, values) with the tiles in the same order; form is the name you give it here, so one script can tell its maps apart. Called from _zone_used, the map answers only while the player stands in that zone. door is where along the bottom edge the door is drawn, from 0 (the left end) to 1 (the right). At most 12 tiles a side and 24 options; long labels are cut short. A new map replaces the one on screen. False, and nothing shown, for a bot, a player who is gone, or a map that does not fit.

Parameters
  • entity_id: int
  • form: StringName
  • title: String
  • columns: int
  • rows: int
  • options: Array
  • values: PackedInt32Array
  • door: float, default 0.5
    Returns: bool

notify_all

notify_all(title: String, body: String = "", warn: bool = false) -> void
Method · Available to server.gd, bot.gd

Flash a message on every player's screen.

Parameters
  • title: String
  • body: String, default ""
  • warn: bool, default false
    Returns: void

notify_team

notify_team(team: int, title: String, body: String = "", warn: bool = false) -> void
Method · Available to server.gd, bot.gd

Flash a message on the screens of one team.

Parameters
  • team: int
  • title: String
  • body: String, default ""
  • warn: bool, default false
    Returns: void

log

log(message: String) -> void
Method · Available to server.gd, bot.gd

Print a line tagged with the map's name and server, for testing.

Parameters
  • message: String
    Returns: void

Constants

SCOPE_PLAYER

SCOPE_PLAYER
Constant · Available to server.gd, bot.gd

The player counters, for counter_maximum.

SCOPE_TEAM

SCOPE_TEAM
Constant · Available to server.gd, bot.gd

The team counters, for counter_maximum.

SCOPE_GLOBAL

SCOPE_GLOBAL
Constant · Available to server.gd, bot.gd

The global counters, for counter_maximum.

MATCH_LIVE

MATCH_LIVE
Constant · Available to server.gd, bot.gd

match_state(): the round is being played.

MATCH_DECIDED

MATCH_DECIDED
Constant · Available to server.gd, bot.gd

match_state(): a winner has been declared; the world plays on for a moment.

MATCH_RESULT

MATCH_RESULT
Constant · Available to server.gd, bot.gd

match_state(): the world is paused and the result is showing.

MATCH_VOTING

MATCH_VOTING
Constant · Available to server.gd, bot.gd

match_state(): players are voting for the next map.

MATCH_LOADING

MATCH_LOADING
Constant · Available to server.gd, bot.gd

match_state(): the next map is loading.

DOOR_CLOSED

DOOR_CLOSED
Constant · Available to server.gd, bot.gd

door_state(): shut.

DOOR_OPENING

DOOR_OPENING
Constant · Available to server.gd, bot.gd

door_state(): on its way open.

DOOR_OPEN

DOOR_OPEN
Constant · Available to server.gd, bot.gd

door_state(): open.

DOOR_CLOSING

DOOR_CLOSING
Constant · Available to server.gd, bot.gd

door_state(): on its way shut.

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