Skip to content

feat: let a custom game mode define its own team size - #574

Open
LCrew wants to merge 1 commit into
5stackgg:mainfrom
LCrew:feat/custom-mode-player-counts
Open

feat: let a custom game mode define its own team size#574
LCrew wants to merge 1 commit into
5stackgg:mainfrom
LCrew:feat/custom-mode-player-counts

Conversation

@LCrew

@LCrew LCrew commented Sep 5, 2026

Copy link
Copy Markdown

Depends on 5stackgg/api#<N>, which adds game_modes.players_per_team, game_modes.allow_short_handed_start and the startDraftGame action. Merge that first — this calls the action and reads the columns.

Why

A custom game mode can already change the plugins and cvars a match runs under, but not its shape. The api PR lets a mode declare its own team size; this is the UI for setting it and using it.

Where the setting lives

On the mode, not on each lobby — a mode is a set of plugins and cvars built for a particular shape of match, and a host picking "Retakes" shouldn't also have to know it's a 3v3.

So the two fields are edited in Settings → Application → Game Modes, and the draft wizard's mode step only reports them, as a badge on each mode card (3v3, Can start short). That also avoids an ordering problem: the mode is chosen on step 2, so a control on step 1 would be dead until then.

In the room

A mode that allows it unlocks Start Short-Handed once both sides hold at least one player, with a confirm step — starting short can't be walked back, as everyone still on their way in loses the seat. The confirm disarms itself if someone joins and the lobby fills.

start() now goes through the startDraftGame action instead of setting the status directly, because narrowing the lobby has to happen server-side before the trigger and the draft pick pattern read its capacity. Authorization is unchanged: the action's isOrganizerOrHost matches is_draft_game_organizer exactly (host, or match_organizer and above).

Zero change by default

With no custom mode selected, perTeam falls back to the match type's count and the start gate keeps its original equality. forceReady is false unless the mode opts in, so canStart === startReady — the button behaves exactly as before.

Tested

Deployed to a live install alongside the api change: a mode with players_per_team = 1 produces a 1v1 draft lobby and sends 2 players, which the game server then honours. Existing Competitive lobbies still require 10.

Notes for review

  • generated/zeus is untouched — worth a yarn codegen once the api migrations are applied.
  • Part of a three-repo change. Merge order: api → this → game-server.

Follows the api change that lets game_modes carry players_per_team and
allow_short_handed_start.

The size lives on the mode rather than on each lobby: a mode is a set of
plugins and cvars built for a particular shape of match, and a host
picking "Retakes" should not also have to know it is a 3v3. So the two
fields are edited in Application Settings -> Game Modes, and the draft
wizard's mode step only reports them, as a badge on each mode card.

In the room, a mode that allows it unlocks a Start Short-Handed button
once both sides hold at least one player, with a confirm step -- starting
short cannot be walked back, as everyone still on their way in loses the
seat. The confirm disarms itself if someone joins and the lobby fills.

start() now goes through the startDraftGame action instead of setting the
status directly, because narrowing the lobby has to happen server-side
before the trigger and the draft pick pattern read its capacity.

With no custom mode selected none of this engages: perTeam falls back to
the match type's count and the start gate keeps its original equality.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G8LmkD3i1HyGjbcxAZ5Crz
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant