aboutsummaryrefslogtreecommitdiff
path: root/Northstar.CustomServers/mod/scripts/vscripts/lobby/_private_lobby.gnut
blob: 388f4794c765dd34ad4c221fee4b3108e202cf67 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
// TODO: could probably add some checks for whether player setting stuff is player 0 to check for host, might fail in dedicated tho

global function PrivateLobby_Init

struct {
	int startState
	string map = "mp_forwardbase_kodai"
	string mode = "aitdm"
} file 

void function PrivateLobby_Init()
{
	print( "PrivateLobby_Init()" )
	
	file.map = GetConVarString( "ns_private_match_last_map" )
	file.mode = GetConVarString( "ns_private_match_last_mode" )
	
	thread SetupPrivateMatchUIVarsWhenReady()
	
	AddClientCommandCallback( "PrivateMatchLaunch", ClientCommandCallback_PrivateMatchLaunch )
	AddClientCommandCallback( "PrivateMatchSetMode", ClientCommandCallback_PrivateMatchSetMode )
	AddClientCommandCallback( "SetCustomMap", ClientCommandCallback_SetCustomMap )
	AddClientCommandCallback( "PrivateMatchSwitchTeams", ClientCommandCallback_PrivateMatchSwitchTeams )
	AddClientCommandCallback( "PrivateMatchToggleSpectate", ClientCommandCallback_PrivateMatchToggleSpectate )
	
	AddClientCommandCallback( "PrivateMatchSetPlaylistVarOverride", ClientCommandCallback_PrivateMatchSetPlaylistVarOverride )
	AddClientCommandCallback( "ResetMatchSettingsToDefault", ClientCommandCallback_ResetMatchSettingsToDefault )
}

void function SetupPrivateMatchUIVarsWhenReady()
{
	// have to wait until end of first frame for SetUIVar to work
	WaitEndFrame()
	SetUIVar( level, "privatematch_map", GetPrivateMatchMapIndex( file.map ) )
	SetUIVar( level, "privatematch_mode", GetPrivateMatchModeIndex( file.mode ) )
}

bool function ClientCommandCallback_PrivateMatchLaunch( entity player, array<string> args )
{
	if ( GetConVarBool( "ns_private_match_only_host_can_start" ) )
		if ( !NSIsPlayerIndexLocalPlayer( player.GetPlayerIndex() ) )
			return true

	if ( file.startState == ePrivateMatchStartState.STARTING ) 
	{
		// cancel start if we're already mid-countdown
		file.startState = ePrivateMatchStartState.READY
		SetUIVar( level, "privatematch_starting", ePrivateMatchStartState.READY )
		SetUIVar( level, "gameStartTime", null )
	}
	else
	{
		// start match
		file.startState = ePrivateMatchStartState.STARTING
		thread StartMatch()
	}
	
	return true
}

bool function ClientCommandCallback_PrivateMatchSetMode( entity player, array<string> args )
{
	if ( file.startState == ePrivateMatchStartState.STARTING )
		return true

	if ( args.len() != 1 )
		return true
	
	if ( GetConVarInt( "ns_private_match_only_host_can_change_settings" ) == 2 )
		if ( !NSIsPlayerIndexLocalPlayer( player.GetPlayerIndex() ) )
			return true
	
	// todo: need to verify this value
	file.mode = args[0]
	//GameRules_SetGameMode( args[0] ) // can't do this here due to out of sync errors with new clients
	
	RefreshPlayerTeams()

	SetUIVar( level, "privatematch_mode", GetPrivateMatchModeIndex( args[0] ) ) 
	return true
}

bool function ClientCommandCallback_SetCustomMap( entity player, array<string> args )
{
	if ( file.startState == ePrivateMatchStartState.STARTING )
		return true
		
	if ( args.len() != 1 )
		return true
	
	if ( GetConVarInt( "ns_private_match_only_host_can_change_settings" ) == 2 )
		if ( !NSIsPlayerIndexLocalPlayer( player.GetPlayerIndex() ) )
			return true
	
	// todo: need to verify this value
	file.map = args[0]
	
	// todo: this should NOT be necessary, private matches should use an api to register maps in the future rather than hardcoded ids
	// should be removed whenever possible really
	SetUIVar( level, "privatematch_map", GetPrivateMatchMapIndex( args[0] ) )
	return true
}

bool function ClientCommandCallback_PrivateMatchSwitchTeams( entity player, array<string> args )
{
	if ( file.startState == ePrivateMatchStartState.STARTING || GetGamemodeVarOrUseValue( file.mode, "max_teams", "2" ).tointeger() != 2 )
		return true
		
	// currently only support 2 teams in private matches
	SetTeam( player, player.GetTeam() == 2 ? 3 : 2 )
	return true
}

bool function ClientCommandCallback_PrivateMatchToggleSpectate( entity player, array<string> args )
{
	// not currently working, gotta figure it out at some point
	return true
}

void function StartMatch()
{	
	// set starting uivar
	SetUIVar( level, "privatematch_starting", ePrivateMatchStartState.STARTING )
	
	// start countdown
	SetUIVar( level, "gameStartTime", Time() + GetConVarFloat( "ns_private_match_countdown_length" ) ) 
	float countdownEndTime = Time() + GetConVarFloat( "ns_private_match_countdown_length" )
	
	// can't use start here because we need to check stuff
	while ( Time() < countdownEndTime )
	{
		// stop if the countdown's been cancelled
		if ( file.startState != ePrivateMatchStartState.STARTING )
			return
	
		WaitFrame()
	}
		
	// do this before setting playlist
	if ( GetConVarBool( "ns_private_match_override_maxplayers" ) )
		SetPlaylistVarOverride( "max_players", GetCurrentPlaylistVarString( "max_players", "16" ) )
		
	try
	{
		// todo: not every gamemode uses the same playlist as their name! need some code to resolve these manually
		// would be nice if the gamemode api got some tweaks to allow for registering private match gamemodes maybe
		SetCurrentPlaylist( file.mode )
	}
	catch ( exception ) 
	{
		// temp
		if ( file.mode == "speedball" )
			SetCurrentPlaylist( "lf" )
	
		print( "couldn't find playlist for gamemode " + file.mode )
	}
	
	RefreshPlayerTeams()
	
	SetConVarString( "ns_private_match_last_map", file.map )
	SetConVarString( "ns_private_match_last_mode", file.mode )
	//SetConVarBool( "ns_should_return_to_lobby", true ) // potentially temp?
	
	string mode = file.mode
	if ( !( mode in GAMETYPE_TEXT ) )
		mode = GetPlaylistGamemodeByIndex( file.mode, 0 )
	
	GameRules_ChangeMap( file.map, mode )
}

void function RefreshPlayerTeams()
{
	int maxTeams = GetGamemodeVarOrUseValue( file.mode, "max_teams", "2" ).tointeger()
	int maxPlayers = GetGamemodeVarOrUseValue( file.mode, "max_players", "12" ).tointeger()

	// special case for situations where we wrongly assume ffa teams because there's 2 teams/2 players
	if ( maxPlayers == maxTeams && maxTeams > 2 )
	{
		array<entity> players = GetPlayerArray()
		for ( int i = 0; i < players.len(); i++ )
			SetTeam( players[ i ], i + 7 ) // 7 is the lowest ffa team
	}
	else
	{
		bool lastSetMilitia = false
		foreach ( entity player in GetPlayerArray() )
		{
			if ( player.GetTeam() == TEAM_MILITIA || player.GetTeam() == TEAM_IMC )
				continue
				
			if ( lastSetMilitia ) // ensure roughly evenish distribution
				SetTeam( player, TEAM_IMC )
			else
				SetTeam( player, TEAM_MILITIA )
				
			lastSetMilitia = !lastSetMilitia
		}
	}
}

bool function ClientCommandCallback_PrivateMatchSetPlaylistVarOverride( entity player, array<string> args )
{
	if ( args.len() < 2 )
		return true
		
	if ( GetConVarInt( "ns_private_match_only_host_can_change_settings" ) >= 1 )
		if ( !NSIsPlayerIndexLocalPlayer( player.GetPlayerIndex() ) )
			return true
		
	bool found = false
	foreach ( string category in GetPrivateMatchSettingCategories() )
	{
		foreach ( CustomMatchSettingContainer setting in GetPrivateMatchCustomSettingsForCategory( category ) )
		{
			if ( args[ 0 ] == setting.playlistVar )
			{
				found = true
				break
			}
		}
	}
		
	if ( found )
		SetPlaylistVarOverride( args[0], args[1] )
	
	return true
}

bool function ClientCommandCallback_ResetMatchSettingsToDefault( entity player, array<string> args )
{
	if ( GetConVarInt( "ns_private_match_only_host_can_change_settings" ) >= 1 )
		if ( !NSIsPlayerIndexLocalPlayer( player.GetPlayerIndex() ) )
			return true

	ClearPlaylistVarOverrides()
	return true
}