Reference · Updated 2552.10.23.16.45

Game Types

What a match is played as (Slayer, Team Slayer), how the host's choice gets from the lobby into the match, and how the match counts down, scores and ends. The design reasons are in

What a match is played as (Slayer, Team Slayer), how the host's choice gets from the lobby into the match, and how the match counts down, scores and ends. The design reasons are in MultiplayerPlan.md §6; this is how it is built.

#1. A game type is a data asset

  • USLGameTypeDefinition: a primary asset (type SLGameType) holding a DisplayName, a Description, an
  • optional Icon, a SortOrder and the rules, FSLGameTypeSettings.

  • Where they live: /Game/SystemLink/Game/GameTypes, the only folder DefaultGame.ini scans. An asset saved
  • anywhere else is not found.

  • Adding one is a new asset, never a screen edit. The lobby lists every definition it finds, ordered by
  • SortOrder; the first is the one a new lobby opens on.

The shipped types:

AssetTeamsKill goalNotes
GT_Slayeroff25Free-for-all
GT_TeamSlayeron50Red against Blue
GT_TestTeamSlayeron3For testing a whole match quickly. Not for players
GT_TestSlayeroff3Free-for-all to 3, for quick playtests. Not for players

#The rules: FSLGameTypeSettings

A plain struct rather than an asset, so the same block can come from a shipped definition now and from a player's saved custom type later (SL-46), and travel to the match either way.

SettingDefaultEffect
bTeamsoffRed against Blue. Off is a free-for-all: everyone on no team, everyone else an opponent
KillGoal25The score that wins: a player's in a free-for-all, a team's in a team game
CountdownSeconds5 sHow long everyone waits at their spawn, able to look but not move or shoot. 0 starts at once

It starts with only what Slayer needs. Friendly fire, respawn, loadout and modifiers join it as they are built.

#2. From the lobby into the match

  1. The host picks in the lobby. ASLLobbyGameState::SetSelectedGameType is server only and replicates the
  2. choice. Before anyone's lobby redraws, it moves everyone to the new type's teams (SLTeams::ApplyGameType):

    • a free-for-all puts everyone on no team
    • a team game keeps everyone already on a side and balances the rest
  1. Start (ASLLobbyGameMode::TravelToSelectedMap) hands the type and the number of players in the lobby,
  2. split-screen guests included, to USLMatchSettingsSubsystem, then hard travels with ?listen.

  1. Why a game instance subsystem: a hard travel rebuilds the game mode, the game state and every PlayerState.
  2. The game instance is the one thing that survives it. The subsystem is server side only; clients learn the rules from the match's replicated state.

  1. The match picks them up. ASLGameModeBase::InitGameState copies the settings onto ASLMatchGameState,
  2. which replicates them. Arriving players get their teams in InitNewPlayer (SLTeams::AssignOnArrival); a team brought from the lobby is ignored in a free-for-all.

  1. Back in the lobby, it opens on the type the last match used (GetLastGameTypeId), so the host doesn't have
  2. to pick it again.

A map opened directly, as TestMap is in development, has no lobby and no settings in the subsystem. The match then uses the game mode's SettingsWithoutLobby (teams on), skips the wait and countdown, and never returns to a lobby.

#3. The match

ASLMatchGameState holds the phase, the team scores and the winner, and every machine reacts to them itself.

#Phases (ESLMatchPhase)

PhaseWhat players can do
CountdownLook, but not move or shoot. First waiting for everyone to load, then counting down
InProgressPlay
OverNothing: input stops and the score is final

#Countdown

  1. Wait for everyone. A lobby-started match begins in Countdown (WaitForPlayers). Each player controller
  2. reports in once it has a pawn and its loading screen is gone (Server_ReportReadyForCountdown).

  1. Count down when everyone from the lobby has reported, or after MaxWaitForPlayers (15 s) if someone is slow
  2. or dropped. StartCountdown ignores a second call, so both can try.

  1. The end time is replicated, not a count each second, so every machine counts down on its own and stays in
  2. step.

  1. USLCountdownWidget shows "5, 4, 3, 2, 1" and then "Go!". Place a subclass anywhere in the HUD; it reads
  2. the match state itself, and each split-screen player's HUD shows its own. Its tick and go sounds play once per machine, not once per split-screen player. Waiting for players shows nothing.

Eliminations during the countdown are not scored. A fall out of the world still kills.

#Scoring (SLScoring)

World-free, so the automation tests run it directly.

  • A player's score is kills, less suicides and betrayals. Being killed costs nothing.
  • A team's score moves with each elimination: a kill is +1 to the killer's team, a suicide −1 to the victim's,
  • a betrayal −1 to the killer's. It is the team's own tally, so a player who leaves doesn't take their points with them.

  • The report's ranking (RankPlayers): equal scores share a place and the next place skips past them
  • (1st, 1st, 3rd). Kills, then fewer deaths, only order rows within a tie.

#The end

  1. The server scores each elimination (ScoreElimination) after RecordElimination has applied it to the
  2. tallies. When a player (free-for-all) or team reaches the kill goal, the phase goes to Over with the winner and the final results (FSLMatchResults) in the same update, so a client never sees the end before the numbers.

  1. Every machine ends it locally from OnRep_Phase: gameplay input stops for its own players, and each reads
  2. who won, or USLAnnouncerSettings::LoseMessage ("You Lose") if they didn't. The announcer's "game over" line plays once per machine.

  1. The server cancels every ability, so an automatic weapon already firing stops.
  1. After ReturnToLobbyDelay (5 s) the host hard travels everyone back to the lobby, where each machine shows
  2. its results until one of its players dismisses them.

The announcer's lines and the losing text are under Project Settings > System Link > System Link Announcer.

#4. Testing

  • Automation tests: SystemLink.Scoring. (player score, team score changes, ranking) and SystemLink.Teams.
  • (including ChooseForGameType).

  • PIE or LAN checks for the live match, with GT_TestTeamSlayer so it ends at 3:
    • Changing the game type in the lobby moves everyone's teams, and every player sees the new type.
    • Starting from the lobby, everyone waits at their spawn until all have loaded, then sees the same countdown,
    • and nobody can move or shoot until "Go!".

    • A kill, a suicide and a betrayal move the scores as above.
    • Reaching the kill goal stops everyone, shows the winner (or "You Lose"), and returns to the lobby, which opens
    • on the same game type.

    • In split-screen, each player gets their own countdown and result, and each sound plays once.