aboutsummaryrefslogtreecommitdiff
path: root/Northstar.CustomServers/mod/scripts/vscripts/lobby/_private_lobby.gnut
blob: c410869e5e99574370bbd7ddd9cfa9a87649f894 (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
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
// 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
	
	PlayerChangedTheGame( player , " changed the game state." , args )

	if ( file.startState == ePrivateMatchStartState.STARTING ) 
	{
		PlayerChangedTheGame( player , " canceled the game countdown." , args )

		// cancel start if we're already mid-countdown
		file.startState = ePrivateMatchStartState.READY
		SetUIVar( level, "privatematch_starting", ePrivateMatchStartState.READY )
		SetUIVar( level, "gameStartTime", null )
	}
	else
	{
		PlayerChangedTheGame( player , " started the game countdown." , args )

		// 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
	
	PlayerChangedTheGame( player , " changed the mode to " , args )

	// 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
	
	PlayerChangedTheGame( player , " changed the map to " , args )

	// 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 )
{
	if ( file.startState == ePrivateMatchStartState.STARTING || !GetConVarBool( "ns_allow_spectators" ) )
		return true
	
	player.SetPersistentVar( "privateMatchState", player.GetPersistentVarAsInt( "privateMatchState" ) == 0 ? 1 : 0 )
	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
	
	PlayerChangedTheGame( player , " override the setting " , args )

	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
	
	PlayerChangedTheGame( player , " reset to default" , args )

	ClearPlaylistVarOverrides()
	return true
}

void function PlayerChangedTheGame( entity player , string step , array<string> args ){
	if( step.find( "mode" ) || step.find( "map" )){
		print( player.GetPlayerName() + step + args[ 0 ] + ".---" + "UID:" +player.GetUID() )
	}
	else if(step.find("setting")){
		print( player.GetPlayerName() + step + args[ 0 ] + " to "+ args[ 1 ] + ".---" + "UID:" +player.GetUID() )
	}
	else{
		print( player.GetPlayerName() + step + ".---" + "UID:" + player.GetUID())
	}
}