Custom Game Setup
"Custom Game Setup" is a new game phase that custom games enter after all players have connected, but before hero selection occurs. It is intended to be a convenient place to implement team select, game mode voting, and similar setup.
By default, a custom game gets a team select UI. You can change the UI in the custom UI manifest as described in the Panorama documentation.
Setup Timer
Setting the initial timeout value
As with other game states, the Custom Game Setup is ultimately controlled by a timer, when this timer reaches zero the game will transition to the next state, in this case Hero selection. There are several ways in which the timer can be controlled. When the Custom Game Setup state is entered the timer is initially set a timeout value which may be specified by the addon. By default the custom game setup timeout for an addon is set to -1, meaning that the custom game setup will last indefinitely, however a custom game can configure the setup time by calling GameRules:SetCustomGameSetupTimeout()
. This function may be called any time before the Custom Game Setup state is entered. Typically it is simply called in the InitGameMode()
function of the addon to set the initial value:
function ExampleAddon:InitGameMode()
GameRules:SetCustomGameSetupTimeout( 60 ) -- set the custom game setup phase to last 60 seconds, set to 0 skip the custom game setup, or -1 to disable the timeout
end
Controlling the remaining time
If you do not set the time out there are two ways in which custom game setup can be completed. First you can explicitly call GameRules:FinishCustomGameSetup()
or GameRules:SetCustomGameSetupRemainingTime( 0 )
from lua script on the server or Game.SetRemainingSetupTime()
from panorama ui javascript. This can only be done while in the Custom Game Setup state, if these functions are called during a different game state they will be ignored.
Lua (server)
function COverthrowGameMode:OnGameRulesStateChange()
local nNewState = GameRules:State_Get()
-- An alternate way of skiping custom game select,
-- finish (set the time to 0) when entring the state
if nNewState == DOTA_GAMERULES_STATE_CUSTOM_GAME_SETUP then
GameRules:FinishCustomGameSetup()
end
end
Panorama javascript (client)
function OnLockAndStartPressed()
{
// Set the remaining time before the game starts to four seconds
Game.SetRemainingSetupTime( 4 );
}
Game.SetRemainingSetupTime()
can only be called by a client which has host privileges. You can find out if a player has host privileges using Game.GetLocalPlayerInfo()
.
function CheckForHostPrivileges()
{
var playerInfo = Game.GetLocalPlayerInfo();
if ( !playerInfo )
return;
// Set the "player_has_host_privileges" class on the panel, this can be used
// to have some sub-panels on display or be enabled for the host player.
$.GetContextPanel().SetHasClass( "player_has_host_privileges", playerInfo.player_has_host_privileges );
}
Auto launch
The second way Custom Game Setup can be completed is by auto launch. Auto launch will set the timer to the auto launch delay time when all players are on a team. When the timer runs out the game will transition to hero selection. Auto launch is enabled by default but can be disabled (or re-enabled) using GameRules:EnableCustomGameSetupAutoLaunch()
(lua) or Game.SetAutoLaunchEnabled()
(javascript)
Lua (server)
function COverthrowGameMode:OnGameRulesStateChange()
local nNewState = GameRules:State_Get()
-- Disable auto launch when entering custom game setup, it can be
-- re-enabled at any point later while still in custom game setup
if nNewState == DOTA_GAMERULES_STATE_CUSTOM_GAME_SETUP then
GameRules:EnableCustomGameSetupAutoLaunch( false )
end
end
Panorama javascript (client)
function OnLockAndStartPressed()
{
// Disable the auto launch when lock and start is pressed, this way if cancel is pressed we won't start counting down again.
Game.SetAutoLaunchEnabled( false );
}
The default delay for auto launch is 30 seconds, but this can be configured using GameRules:SetCustomGameSetupAutoLaunchDelay
(lua) or Game.SetAutoLaunchDelay()
(javascript)
Lua (server)
function COverthrowGameMode:OnGameRulesStateChange()
local nNewState = GameRules:State_Get()
-- Change the auto launch delay from its default (30 seconds) to 15 seconds
if nNewState == DOTA_GAMERULES_STATE_CUSTOM_GAME_SETUP then
GameRules:SetCustomGameSetupAutoLaunchDelay( 15 )
end
end
Panorama javascript (client)
function OnCancelAndUnlockPressed()
{
// Re-enable the auto launch and set the delay to 15 seconds
Game.SetAutoLaunchEnabled( true );
Game.SetAutoLaunchDelay( 15 );
}
Team Assignment
Assigning players to a team
One of the primary uses of the Custom Game Setup phase is to allow players to pick or be assigned to teams. The most basic way to assign a player to a team is using the lua function PlayerResource:SetCustomTeamAssignment()
.
function COverthrowGameMode:InitGameMode()
PlayerResource:SetCustomTeamAssignment( 0, DOTA_TEAM_GOODGUYS ) -- put player 0 on Radiant team
end
Allowing a player to pick a team
To allow a player to pick their own team the panorama script function Game.PlayerJoinTeam()
can be used. This will issue a request for the player associated with the client the ui script is running on to join a specified team.
Panorama javascript (client)
function OnJoinTeamPressed()
{
// Get the team id asscociated with the team button that was pressed
var teamId = $.GetContextPanel().GetAttributeInt( "team_id", -1 );
// Request to join the team of the button that was pressed
Game.PlayerJoinTeam( teamId );
}
Since PlayerJoinTeam()
is executed on the client and sends a message to the server, it is always possible that the team may be full, even if there was space at the time the player pressed a button requesting to join the team. This is because another player may have requested the same team assignment and the other player's request may have been processed by the server first. Each time a player requests a team assignment the game event "dota_player_selected_custom_team" is broadcast, in a panorama script a listener for this game event can be registered using DOTAGame_PlayerSelectedCustomTeam
. If the assignment failed the success parameter of the event will be false.
Panorama javascript (client)
(function()
{
// Register a listener for the even which is broadcast whenever a player attempts to pick a team
$.RegisterForUnhandledEvent( "DOTAGame_PlayerSelectedCustomTeam", OnPlayerSelectedTeam );
})();
function OnPlayerSelectedTeam( nPlayerId, nTeamId, bSuccess )
{
var playerInfo = Game.GetLocalPlayerInfo();
if ( !playerInfo )
return;
// Check to see if the event is for the local player
if ( playerInfo.player_id === nPlayerId )
{
// Play a sound to indicate success or failure
if ( bSuccess )
{
Game.EmitSound( "ui_team_select_pick_team" );
}
else
{
Game.EmitSound( "ui_team_select_pick_team_failed" );
}
}
}
Another important event is DOTAGame_TeamPlayerListChanged, this event is emitted whenever the list of players on a team actually changes. A listener for this event can also be registered in a panorama ui script.
Panorama javascript (client)
(function()
{
// Register a listener for the event which is brodcast when the team assignment of a player is actually changed
$.RegisterForUnhandledEvent( "DOTAGame_TeamPlayerListChanged", OnTeamPlayerListChanged );
})();
Auto assign and shuffle
There are two helper functions which are used in the default custom game ui to change the team assignment of all players, these functions can only be used by a client which has host privileges. Game.AutoAssignPlayersToTeams()
players to teams will assign any currently assigned players to teams, trying to keep players in the same party together. Game.ShufflePlayerTeamAssignments()
will shuffle all the team assignments of all players currently assigned to a team. Game.ShufflePlayerTeamAssignments()
does not attempt to keep members of the same party together.
Panorama javascript (client)
function OnAutoAssignPressed()
{
// Assign all of the currently unassigned players to a team, trying
// to keep any players that are in a party on the same team.
Game.AutoAssignPlayersToTeams();
}
function OnShufflePlayersPressed()
{
// Shuffle the team assignments of any players which are assigned to a team,
// this will not assign any players to a team which are currently unassigned.
// This will also not attempt to keep players in a party on the same team.
Game.ShufflePlayerTeamAssignments();
}
Locking team assignment
It may be useful to lock the team selection at some point to prevent further changes to team assignment. The default custom game team selection ui does this when the lock and start button is pressed. This can be done using GameRules:LockCustomGameSetupTeamAssignment()
(lua) or Game.SetTeamSelectionLocked()
(javascript).
Lua (server)
function COverthrowGameMode:OnGameRulesStateChange()
local nNewState = GameRules:State_Get()
-- Change the auto launch delay from its default (30 seconds) to 15 seconds
if nNewState == DOTA_GAMERULES_STATE_CUSTOM_GAME_SETUP then
GameRules:LockCustomGameSetupTeamAssignment( true )
end
end
Panorama javascript (client)
function OnLockAndStartPressed()
{
// Don't allow a forced start if there are unassigned players
if ( Game.GetUnassignedPlayerIDs().length > 0 )
return;
// Lock the team selection so that no more team changes can be made
Game.SetTeamSelectionLocked( true );
}
Relevant commands and events
Lua script functions
Function | Signature | Description |
---|---|---|
GameRules:FinishCustomGameSetup | void FinishCustomGameSetup()
|
Indicate that the custom game setup phase is complete, and advance to the game. |
GameRules:SetCustomGameSetupTimeout | void SetCustomGameSetupTimeout( int seconds )
|
Set the amount of remaining time, in seconds, for custom game setup. ( int seconds /*0 = finish immediately, -1 = wait forever*/ ) |
GameRules:SetCustomGameSetupRemainingTime | void SetCustomGameSetupRemainingTime( int seconds )
|
Set the amount of remaining time, in seconds, for custom game setup. ( int seconds /*0 = finish immediately, -1 = wait forever*/ ) |
GameRules:SetCustomGameSetupAutoLaunchDelay | void SetCustomGameSetupAutoLaunchDelay( int seconds )
|
Set the amount of time to wait for auto launch. |
GameRules:EnableCustomGameSetupAutoLaunch | void EnableCustomGameSetupAutoLaunch( bool enable )
|
Enable (true) or disable (false) auto launch for custom game setup. |
GameRules:LockCustomGameSetupTeamAssignment | void LockCustomGameSetupTeamAssignment( bool enable )
|
Lock (true) or unlock (false) team assignment. If team assignment is locked players cannot change teams. |
PlayerResource:SetCustomTeamAssignment | void SetCustomTeamAssignment( int playerID, int teamAssignment )
|
Assign the player specified by id to the specified team. |
Panorama javascript functions
Function | Signature | Description |
---|---|---|
Game.PlayerJoinTeam | void PlayerJoinTeam( int nTeamID ) | Assign the local player to the specified team. |
Game.AutoAssignPlayersToTeams | void AutoAssignPlayersToTeams() | Assign the currently unassigned players to teams. |
Game.ShufflePlayerTeamAssignments | void ShufflePlayerTeamAssignments() | Shuffle the team assignments of all of the players currently assigned to a team. |
Game.SetRemainingSetupTime | void SetRemainingSetupTime( float flSeconds ) | Set the remaining seconds in team setup before the game starts. -1 to stop the countdown timer. |
Game.SetAutoLaunchDelay | void SetAutoLaunchDelay( float flSeconds ) | Set the amount of time in seconds that will be set as the remaining time when all players are assigned to a team. |
Game.SetAutoLaunchEnabled | void SetAutoLaunchEnabled( bool bEnable ) | Enable or disable automatically starting the game once all players are assigned to a team. |
Game.GetAutoLaunchEnabled | bool GetAutoLaunchEnabled() | Return true or false indicating if automatically starting the game is enabled. |
Game.SetTeamSelectionLocked | void SetTeamSelectionLocked( bool bLockTeams ) | Lock the team selection preventing players from switching teams. |
Game.GetTeamSelectionLocked | bool GetTeamSelectionLocked() const | Returns true or false to indicate if team selection is locked. |
Game events
- dota_team_player_list_changed: A player team assignment has changed
- dota_player_details_changed: Some information about a player has changed
- dota_player_selected_custom_team: The specified player attempted to change to the specified team
- player_id ( short ): Player id of the player who selected a team
- team_id( short ): Id of the team the player selected
- success( bool ): Was the player successfully assigned to the selected team
Panorama events
Game event | Panorama event |
---|---|
dota_team_player_list_changed | DOTAGame_TeamPlayerListChanged |
dota_player_details_changed | DOTAGame_PlayerDetailsChanged |
dota_player_selected_custom_team | DOTAGame_PlayerSelectedCustomTeam |