Sides system
Query and manage the faction/allegiance side of space objects.
Overview
Every space object has a side string that the simulation uses for targeting and IFF (Identify Friend or Foe). Common side values are "tsn", "tur", "tsc", "skaraan", "biomech", and "unsc". The side is set at spawn time and can be changed in flight.
The side is automatically added as a role, so role("tsn") matches all TSN objects and can be combined with other role queries:
tsn_stations = broad_test_around(pos, 5000) & role("tsn") & role("station")
get_side_for_display returns a human-readable faction name (e.g. "TSN" instead of "tsn"). side_set changes an object's side and the side_changed signal is emitted.
Quick example
== check_side ==
if get_side(target_id) == "tsc": jump enemy_detected
if get_side(target_id) == "tsn": jump friendly_detected
== defect ==
side_set(npc_id, "tsn")
log("Enemy ship has defected to TSN!")
->END
from sbs_utils.procedural.sides import side_set, get_side, get_side_for_display
# Check faction
if get_side(target_id) == "tsc":
target(ship_id, target_id)
# Change side mid-mission
side_set(npc_id, "tsn")
# Human-readable name
name = get_side_for_display(target_id) # e.g. "TSN"
Common side values
| Side | Faction |
|---|---|
"tsn" |
Terran Stellar Navy |
"tur" |
Tur (hostile) |
"tsc" |
Terran Stellar Command (hostile in some missions) |
"skaraan" |
Skaraan |
"biomech" |
Biomech (Hegemony) |
"unsc" |
UNSC |
API
is_allied_to_players(target, scope_role=None)
Return whether target is friendly to some player side (same side or
allied), optionally requiring a class role. The friend analog of
:func:is_hostile_to_players.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
str | int | Agent
|
The candidate to test. |
required |
scope_role
|
str
|
A role the target must hold. Defaults to None. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
|
is_hostile_combatant(observer, target, scope_role=None)
Return whether target is a hostile combatant relative to observer.
The boolean single source of truth for "may I treat this as an enemy": target
is diplomatically HOSTILE to observer's side AND still carries the combat
class role scope_role. This honours both "no longer my enemy" conventions at
once — a ceasefired/neutral side fails :func:side_are_enemies, and a
surrendered/defected ship has had scope_role removed. Pass
scope_role=None for a pure diplomacy test.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
observer
|
str | int | Agent
|
The point-of-view side/agent. |
required |
target
|
str | int | Agent
|
The candidate to test. |
required |
scope_role
|
str
|
Combat-class role the target must still hold.
Defaults to |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
|
is_hostile_to_players(target, scope_role=None)
Return whether target is a hostile combatant to at least one player side.
The player-perspective boolean (see :func:is_hostile_combatant): target
still carries the combat class role scope_role AND is diplomatically HOSTILE
to some current player side. A ceasefired/neutral or surrendered ship is False.
Pass scope_role=None for a pure diplomacy test.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
str | int | Agent
|
The candidate to test. |
required |
scope_role
|
str
|
Combat-class role the target must hold. Defaults
to |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
|
players_allied_members(scope_role=None)
Return the agent IDs on a PLAYER side or a side ALLIED to one (the "friendly to the players" set), optionally intersected with a class role.
The player-perspective ally set (friend analog of :func:players_hostile_members)
— for friendly-base / friendly-ship checks not tied to a single observer, e.g.
"all our stations are gone" lose conditions. Covers every player side and their
allies, so it works with a second player side or an allied faction instead of a
hardcoded side role like role("tsn").
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scope_role
|
str
|
A role to intersect with (e.g. |
None
|
Returns:
| Type | Description |
|---|---|
|
set[int]: IDs friendly to the players, optionally scoped to |
players_ceasefire(relation=None)
End the attack: make every side currently HOSTILE to a player side NEUTRAL.
The diplomacy expression of "call off the enemies" at the end of a game. The older
way to do this was to strip a shared combat tag from every ship
(remove_role(role("raider"), "raider")), which only stopped the consumers that
happened to scope by that tag -- the ships stayed diplomatically hostile, so brains
still shot and sensor contacts stayed red. Changing the RELATION stops all of them
at once, and is reversible (re-declare HOSTILE to resume).
Applies to whole sides, not individual ships; a single ship leaving the fight is
:func:side_surrender.
NOT self-inverse, and not idempotent in the useful direction: it reads the CURRENT
hostile pairs and neutralizes them, so a second call finds nothing hostile and
changes nothing. It does not remember what was hostile, so "undo" means
re-declaring HOSTILE (side_set_relations / re-running your side declaration),
not calling this again. Unlike :func:side_ensure / :func:side_create, replaying
it is therefore not a repair.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
relation
|
DIPLOMACY
|
Relation to set. Defaults to |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
int |
The number of side pairs changed. |
players_hostile_members(scope_role=None)
Return the agent IDs on a side HOSTILE to at least one current player ship's side, optionally intersected with a combat-class role.
The player-perspective form of :func:side_hostile_members — for checks that are
not tied to a single observer: "are there enemies left" (victory), "count the
threat", "was an enemy killed" (reward). Diplomacy-driven, so ceasefired/neutral
sides drop out and multiple player sides are all accounted for. Empty when there
are no player ships with a side.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scope_role
|
str
|
A combat-class role (e.g. |
None
|
Returns:
| Type | Description |
|---|---|
|
set[int]: IDs hostile to some player side, optionally scoped to |
players_hostile_ships()
Space objects hostile to at least one current PLAYER side and still in the fight.
Player-perspective form of :func:side_hostile_ships — for checks not tied to one
observer ("are there enemies left", "count the threat"). Replaces
players_hostile_members("raider") and the bare role("raider") sweeps.
Returns:
| Type | Description |
|---|---|
|
set[int]: IDs hostile to some player side. |
side_allied_members(observer, scope_role=None)
Return the agent IDs on observer's OWN side or a side ALLIED to it (the
"friendly" set from observer's point of view), optionally intersected with a
class role. The ally analog of :func:side_hostile_members.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
observer
|
str | int | Agent
|
Side key, side agent ID, or any object whose side is used as the point of view. |
required |
scope_role
|
str
|
A role to intersect the result with (e.g.
|
None
|
Returns:
| Type | Description |
|---|---|
|
set[int]: IDs of own-side and allied-side agents, optionally scoped. |
side_ally_members_set(side)
Return the set of agent IDs from all sides allied with the given side.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
side
|
str | int | Agent
|
Side key, side agent ID, or any space object whose side will be used. |
required |
Returns:
| Type | Description |
|---|---|
|
set[int]: IDs of all space objects on allied sides. |
side_are_allies(side1, side2)
Return whether two sides are allied.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
side1
|
str | int | Agent
|
First side — key, agent ID, or object. |
required |
side2
|
str | int | Agent
|
Second side — key, agent ID, or object. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
|
side_are_enemies(side1, side2)
Return whether two sides are hostile to each other.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
side1
|
str | int | Agent
|
First side — key, agent ID, or object. |
required |
side2
|
str | int | Agent
|
Second side — key, agent ID, or object. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
|
side_are_friendly(side1, side2)
Return whether two sides are friendly — the SAME side, or ALLIED.
The friendly counterpart of :func:side_are_enemies. Use this for "is this one
of ours" checks: :func:side_are_allies alone is not enough because a side is
not recorded as allied to itself, so a same-side ship would read as non-friendly.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
side1
|
str | int | Agent
|
First side — key, agent ID, or object. |
required |
side2
|
str | int | Agent
|
Second side — key, agent ID, or object. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
|
side_are_neutral(side1, side2)
Return whether two sides are neutral toward each other.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
side1
|
str | int | Agent
|
First side — key, agent ID, or object. |
required |
side2
|
str | int | Agent
|
Second side — key, agent ID, or object. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
|
side_are_same_side(side1, side2)
Return whether two references resolve to the same side.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
side1
|
str | int | Agent
|
First side — key, agent ID, or object. |
required |
side2
|
str | int | Agent
|
Second side — key, agent ID, or object. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
|
side_capture(ship, captor)
A surrendered ship JOINS its captor: move it onto the captor's side, so it is now friendly to the captor and hostile to the captor's enemies (by diplomacy), and clear the surrendered state.
The ship keeps its race/clan role for identity and is marked with a captured
role (so take_surrendered_home, which flies surrendered ships off and
deletes them, leaves it alone — it is a prize now, not a fugitive). Give it a
brain/objective afterwards if you want it to actively fight for you.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ship
|
Agent | int
|
The surrendered ship being taken as a prize. |
required |
captor
|
Agent | int | str
|
The capturing ship/console (its side is used), or a side key directly. |
required |
side_create(key, name=None, desc=None, color=None, icon_index=None, races=None, allies=None, enemies=None)
Create and configure a faction SIDE from data - the Python port of the
prefab_side_generic MAST prefab, so the same setup is callable from Python or a
declarative loader without the mast prefab.
Sets side_name / side_key / side_desc / side_races inventory, icon color + index, and
applies ally/enemy diplomacy (plus the self-ally that side_ensure seeds). Idempotent:
if the side already exists it is reconfigured in place (side_ensure returns the
existing id). races/allies/enemies accept a comma string or a list.
Returns the side agent id (None if key is falsy).
side_diplomacy_apply(overrides)
Re-apply saved per-pair diplomacy overrides via side_set_relations (call after the sides exist, e.g. on load).
side_diplomacy_key(a, b)
Order-independent key for a side PAIR.
Safe because overrides are re-applied via side_set_relations, which writes both
directions -- not because the engine treats a pair as unordered.
side_diplomacy_set(overrides, a, b, relation)
Record a per-pair diplomacy override in overrides (created if not a dict);
returns the dict. Persist it to carry live relation changes across saves.
side_display_name(key)
Return the display name of a side.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str | int | Agent
|
Side key, agent ID, or agent. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
str |
The side's display name, or |
side_enemy_members_set(side)
Return the set of agent IDs from all sides hostile to the given side.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
side
|
str | int | Agent
|
Side key, side agent ID, or any space object whose side will be used. |
required |
Returns:
| Type | Description |
|---|---|
|
set[int]: IDs of all space objects on hostile sides. |
side_ensure(key, name=None)
Ensure a side with key exists, creating a minimal one if missing, and
return its side-agent ID.
The programmatic (Python) counterpart of the prefab_side_generic MAST prefab
— use it before spawning ships on a new faction side so diplomacy can resolve
that side. Idempotent: returns the existing side's ID if already registered. The
new side is allied to itself (matching prefab_side_generic), so a same-side
pair reads friendly via :func:side_are_allies as well.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
The side key (e.g. |
required |
name
|
str
|
Display name. Defaults to |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
int |
The side agent's ID. |
side_get_description(key_or_id)
Return the description text of a side.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key_or_id
|
str | int | Agent
|
Side key, agent ID, or object. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
The side description, or |
side_get_display_name(key_or_id)
Return the display name of a side.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key_or_id
|
str | int | Agent
|
Side key, agent ID, or object. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
The side's display name, or |
side_get_relations(side1, side2)
Return the current diplomatic relationship between two sides.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
side1
|
str | int | Agent
|
First side — key, agent ID, or object. |
required |
side2
|
str | int | Agent
|
Second side — key, agent ID, or object. |
required |
Returns:
| Type | Description |
|---|---|
|
sbs.DIPLOMACY: One of |
side_get_side_color(key_or_id, default='#0F0')
Return the icon color assigned to a side.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key_or_id
|
str | int | Agent
|
Side key, agent ID, or object. |
required |
default
|
str
|
Color to return if the side has no color set.
Defaults to |
'#0F0'
|
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
The hex color code assigned to the side, or |
side_get_side_icon_index(key_or_id)
Return the icon index for a side.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key_or_id
|
str | int | Agent
|
Side key, agent ID, or object. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
The icon index, or |
side_hostile_members(observer, scope_role=None)
Return the agent IDs on any side HOSTILE to observer, optionally
intersected with a combat-class role.
The canonical "who may I fight" set: diplomacy decides allegiance (a side that
is neutral/allied — e.g. one you have ceasefired — drops out), and the optional
scope_role (such as "raider") scopes the result to combat ships. Because
a role like raider is removed on surrender/defection, scoping by it also
drops ships that have already struck their colours. Prefer this over a bare
role("raider") anywhere a set is tested for "is there an enemy".
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
observer
|
str | int | Agent
|
Side key, side agent ID, or any object whose side is used as the point of view. |
required |
scope_role
|
str
|
A role to intersect the result with (combat-ship scope). Defaults to None (all hostile-side members). |
None
|
Returns:
| Type | Description |
|---|---|
|
set[int]: IDs of hostile-side agents, optionally scoped to |
side_hostile_ships(observer)
Space objects HOSTILE to observer that are still in the fight.
The diplomacy-only answer to "who may I fight" — the replacement for scoping a
hostile set by a faction tag such as role("raider"). Allegiance comes from the
side relations alone, so a ceasefired or defected side drops out the moment its
diplomacy changes, with no tag to keep in sync; wrecks and surrendered ships are
excluded because they are not combatants, not because of who they belong to.
Includes hostile stations (they are on a hostile side like anything else). Intersect
with a CLASS role when you want a narrower kind, e.g.
side_hostile_ships(x) & role("station") or - role("station").
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
observer
|
str | int | Agent
|
Side key, side agent ID, or any object whose side is the point of view. |
required |
Returns:
| Type | Description |
|---|---|
|
set[int]: IDs of hostile, in-the-fight space objects. |
side_is_color_used(color)
Return whether any side is currently using a given icon color.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
color
|
str
|
Hex color code to check for. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
|
side_keys_set()
Return the set of key strings for all registered sides.
Returns:
| Type | Description |
|---|---|
|
set[str]: Side key strings (e.g. |
side_members_set(side)
Return the set of agent IDs that belong to a given side.
Prefer this over role(side) as it correctly excludes the side agent
itself from the result.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
side
|
str | int | Agent
|
Side key, side agent ID, side agent, or any space object whose side will be used. |
required |
Returns:
| Type | Description |
|---|---|
|
set[int]: IDs of all space objects on the specified side. |
side_set_description(key_or_id, desc)
Set the description text for a side.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key_or_id
|
str | int | Agent
|
Side key, agent ID, or object. |
required |
desc
|
str
|
The new description text. |
required |
side_set_display_name(key_or_id, name)
Set the display name for a side and update all ships on that side.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key_or_id
|
str | int | Agent
|
Side key, agent ID, or object. |
required |
name
|
str
|
The new display name. |
required |
side_set_hostile_to_players(faction_key, relation=None)
Make faction_key HOSTILE to every current player side (creating the
faction side if needed).
The programmatic generalisation of a mission's single side_set_relations
line: instead of lumping every enemy on one shared "raider" side, spawn a
faction on its OWN side and call this, so hostility is expressed by diplomacy —
which the migrated targeting / victory / quest consumers already honour, and
which a runtime ceasefire can flip. Applies the relation once per distinct side
among the current role("__player__") ships.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
faction_key
|
str
|
The enemy faction's side key. |
required |
relation
|
DIPLOMACY
|
Defaults to |
None
|
side_set_icon_color(key_or_id, color)
Set the icon color for a side, changing how its ships appear on the 2D map.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key_or_id
|
str | int | Agent
|
Side key, agent ID, or object. |
required |
color
|
str
|
Hex color code or named color (e.g. |
required |
side_set_object_side(id_or_obj, key)
Assign a side to one or more space objects.
Updates both the side (key) and side_display (name) attributes on
each object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
id_or_obj
|
int | Agent | list[int | Agent] | set[int | Agent]
|
The object(s) to update. |
required |
key
|
str | int | Agent
|
The target side — a key string, side agent ID, or any object whose side will be used. |
required |
side_set_relations(side1, side2, relation)
Set the diplomatic relationship between two sides.
Updates both the link-based relationship used by the scripting API and the
engine's own side relationship table for 2D map rendering. Emits the
side_relations_updated signal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
side1
|
str | int | Agent
|
First side — key, agent ID, or object. |
required |
side2
|
str | int | Agent
|
Second side — key, agent ID, or object. |
required |
relation
|
DIPLOMACY
|
New relationship value. Use
|
required |
side_set_ship_allies_and_enemies(ship)
No-op placeholder — deprecated as of v1.3.0, to be removed in a future version.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ship
|
Agent | int
|
Unused. |
required |
side_set_side_icon_index(key_or_id, icon_index)
Set the icon index for a side, changing how its ships appear on the 2D map.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key_or_id
|
str | int | Agent
|
Side key, agent ID, or object. |
required |
icon_index
|
int
|
The icon index to use. |
required |
side_surrender(ship, combat_role=None)
Move a ship to the neutral surrendered side (creating it if needed) and
mark it surrendered, recording its origin side for a later
:func:side_unsurrender.
Changing the SIDE (not merely stripping a combat role) makes the ship non-hostile
by diplomacy itself, so every side/relation consumer treats it as out of the fight
— not only the ones that scope by the combat role. The surrendered side is
created with no hostile links, so it is neutral to everyone. The ship keeps its
race/clan role, so its faction identity is preserved.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ship
|
Agent | int
|
The surrendering ship. |
required |
combat_role
|
str
|
Legacy compat only -- a combat-class role to drop
as well, for a mission that still scopes its own queries by one. Defaults
to |
None
|
side_unsurrender(ship, combat_role=None)
Reverse :func:side_surrender — restore the ship's origin side and re-arm it
(drop surrendered, restore the origin side, clear surrender_flag).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ship
|
Agent | int
|
The ship to re-arm. |
required |
combat_role
|
str
|
Legacy compat only -- a combat-class role to
restore, matching whatever was passed to :func: |
None
|
sides_set()
Return the set of IDs for all registered sides (agents with the __side__ role).
Returns:
| Type | Description |
|---|---|
|
set[int]: IDs of all side agents. |
to_side_id(key_or_id_or_object, warn=True)
Resolve any side reference to the side agent's ID.
Accepts a side key string, a side agent ID, a side agent object, or any space object (in which case its side property is used).
A leading # on a side key is a display-hide marker only (it tells the
engine not to draw the side name); it is not part of the side identity, so
"#raider" resolves to the "raider" side. An empty or all-# key
means the object has NO side (asteroids, cambots, hidden objects) and
resolves to None silently — that is a legitimate state, not a miss.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key_or_id_or_object
|
str | int | Agent
|
Side key, side agent ID, side agent, or a space object whose side should be resolved. |
required |
warn
|
bool
|
Warn (once per distinct key) when a genuinely-named side
can't be resolved. Pass |
True
|
Returns:
| Type | Description |
|---|---|
|
int | None: The side agent ID, or |
to_side_object(key_or_id)
Resolve any side reference to the side agent object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key_or_id
|
str | int | Agent
|
Side key, side agent ID, or any space object whose side will be resolved. |
required |
Returns:
| Type | Description |
|---|---|
|
Agent | None: The side agent, or |