---
title: "Teams team based matches and shared team score"
description: "Players split into red and blue, share a team score, and cannot hurt teammates. Teams are declared in the multiplayer blueprint and read at runtime with the `team.v1` host op. The default blueprint has NO teams, so team play is opt-in."
engineVersion: v1.0.234
date: 2026-09-28
license: "(c) Gessa, proprietary. Cite with attribution to https://gessa.ai/docs/. Terms: https://gessa.ai/terms/."
canonical: https://gessa.ai/docs/knowledge/playbooks/teams-and-team-play/
---

# Teams team based matches and shared team score

## When to use

Players split into red and blue, share a team score, and cannot hurt teammates.
Teams are declared in the multiplayer blueprint and read at runtime with the
`team.v1` host op. The default blueprint has NO teams, so team play is opt-in.

## The recipe

1. Declare teams: set a multiplayer blueprint with `project_set_multiplayer_blueprint`
   (`game.multiplayer_blueprint.set`) whose team policies carry the `teamKeys`
   (for example `["red","blue"]`), `teamCount`, and `teamCapacity`. See
   multiplayer-replication-and-rooms for the surrounding room and queue fields.
   Assign players to a team at join with the character policy's
   `teams.assignAtAdmission` (`none`, `round_robin`, or `least_players`); it
   defaults to no team, so team play is opt-in. The team vocabulary is these team
   policies, or the `teamKey` values your Spawn Points name when the blueprint
   declares no team policies.
2. Read a player's side: in a whole-body GessaScript body
   (`replaceScriptFromGessaScript`) call `ctx.team.getAssignment` to get the
   current entity or player's team key. Author with
   `project_apply_script_semantic_patch` and the `ai_safe` op pack.
3. Team score: on a scoring event, pass the team key as the subject to
   `ctx.match.addScore` (subject keys can be a player id or a team key), and read
   standings with `ctx.match.getScore`. Show both team totals with
   `wireHudStateBinding`.
4. Friendly fire and team gates: before applying damage (see
   combat-damage-and-respawn) compare the attacker's and target's assignments and
   skip same-team hits. For team spawns, place per-team Spawn Point entities whose
   `SpawnPointComponent` carries the matching `teamKey` (see
   spawn-points-and-checkpoints).
5. Team messages: send a team-only signal with `ctx.network.sendMessage` on a
   team channel for pings or callouts.

## Pitfalls

- `ctx.team.getAssignment` is READ ONLY; assignment comes from the blueprint's
  team policies, the character policy's `teams.assignAtAdmission`, and
  matchmaking, not from a script setter. To change team structure, edit the
  blueprint.
- The default blueprint ships without teams; if `getAssignment` returns nothing,
  the blueprint has no `teamPolicies` set.
- Score per team by using the team key as the score subject; do not keep a
  separate local per-team tally, it drifts across clients.
- `ctx.network.sendMessage` channels are allowlisted and rate-limited
  (`network.channel_allowlist`, `network.rate_limit`); use a declared channel.
- Friendly-fire skipping is script logic; there is no built-in team-damage rule.

## Verify

- `simulation_run` (`qa.run.start`) to prove players land on teams, team score
  accrues to the right side, and same-team damage is skipped.
- `project_get_graph_snapshot` to confirm the scoring and assignment handlers,
  and read the blueprint back to confirm the team policies.
