Dota 2 Workshop Tools/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
Category:Dota 2 Workshop Tools