1 /*
2 ===========================================================================
3 
4 Return to Castle Wolfenstein single player GPL Source Code
5 Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
8 
9 RTCW SP Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 RTCW SP Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with RTCW SP Source Code.  If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code.  If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 #include "g_local.h"
30 
31 
32 /*
33 =======================================================================
34 
35   SESSION DATA
36 
37 Session data is the only data that stays persistant across level loads
38 and tournament restarts.
39 =======================================================================
40 */
41 
42 /*
43 ================
44 G_WriteClientSessionData
45 
46 Called on game shutdown
47 ================
48 */
G_WriteClientSessionData(gclient_t * client)49 void G_WriteClientSessionData( gclient_t *client ) {
50 	const char  *s;
51 	const char  *var;
52 
53 	s = va( "%i %i %i %i %i %i %i %i %i %i %i",       // DHM - Nerve
54 			client->sess.sessionTeam,
55 			client->sess.spectatorNum,
56 			client->sess.spectatorState,
57 			client->sess.spectatorClient,
58 			client->sess.wins,
59 			client->sess.losses,
60 			client->sess.playerType,    // DHM - Nerve
61 			client->sess.playerWeapon,  // DHM - Nerve
62 			client->sess.playerPistol,  // DHM - Nerve
63 			client->sess.playerItem,    // DHM - Nerve
64 			client->sess.playerSkin     // DHM - Nerve
65 			);
66 
67 	var = va( "session%i", (int)(client - level.clients) );
68 
69 	trap_Cvar_Set( var, s );
70 }
71 
72 /*
73 ================
74 G_ReadSessionData
75 
76 Called on a reconnect
77 ================
78 */
G_ReadSessionData(gclient_t * client)79 void G_ReadSessionData( gclient_t *client ) {
80 	char s[MAX_STRING_CHARS];
81 	const char  *var;
82 
83 	var = va( "session%i", (int)(client - level.clients) );
84 	trap_Cvar_VariableStringBuffer( var, s, sizeof( s ) );
85 
86 	sscanf( s, "%i %i %i %i %i %i %i %i %i %i %i",       // DHM - Nerve
87 			(int *)&client->sess.sessionTeam,
88 			&client->sess.spectatorNum,
89 			(int *)&client->sess.spectatorState,
90 			&client->sess.spectatorClient,
91 			&client->sess.wins,
92 			&client->sess.losses,
93 			&client->sess.playerType,       // DHM - Nerve
94 			&client->sess.playerWeapon,     // DHM - Nerve
95 			&client->sess.playerPistol,     // DHM - Nerve
96 			&client->sess.playerItem,       // DHM - Nerve
97 			&client->sess.playerSkin        // DHM - Nerve
98 			);
99 }
100 
101 
102 /*
103 ================
104 G_InitSessionData
105 
106 Called on a first-time connect
107 ================
108 */
G_InitSessionData(gclient_t * client,char * userinfo)109 void G_InitSessionData( gclient_t *client, char *userinfo ) {
110 	clientSession_t *sess;
111 	const char      *value;
112 
113 	sess = &client->sess;
114 
115 	// check for team preference, mainly for bots
116 	value = Info_ValueForKey( userinfo, "teampref" );
117 
118 	// check for human's team preference set by start server menu
119 	if ( !value[0] && g_localTeamPref.string[0] /*&& client->pers.localClient*/ ) {
120 		value = g_localTeamPref.string;
121 
122 		// clear team so it's only used once
123 		trap_Cvar_Set( "g_localTeamPref", "" );
124 	}
125 
126 	// initial team determination
127 	if ( g_gametype.integer >= GT_TEAM ) {
128 		// always spawn as spectator in team games
129 		sess->sessionTeam = TEAM_SPECTATOR;
130 		sess->spectatorState = SPECTATOR_FREE;
131 
132 		if ( value[0] || g_teamAutoJoin.integer ) {
133 			SetTeam( &g_entities[client - level.clients], value );
134  		}
135 	} else {
136 		if ( value[0] == 's' ) {
137 			// a willing spectator, not a waiting-in-line
138 			sess->sessionTeam = TEAM_SPECTATOR;
139 		} else {
140 			switch ( g_gametype.integer ) {
141 			default:
142 			case GT_FFA:
143 			case GT_SINGLE_PLAYER:
144 				if ( g_maxGameClients.integer > 0 &&
145 					 level.numNonSpectatorClients >= g_maxGameClients.integer ) {
146 					sess->sessionTeam = TEAM_SPECTATOR;
147 				} else {
148 					sess->sessionTeam = TEAM_FREE;
149 				}
150 				break;
151 			case GT_TOURNAMENT:
152 				// if the game is full, go into a waiting mode
153 				if ( level.numNonSpectatorClients >= 2 ) {
154 					sess->sessionTeam = TEAM_SPECTATOR;
155 				} else {
156 					sess->sessionTeam = TEAM_FREE;
157 				}
158 				break;
159 			}
160 		}
161 
162 		sess->spectatorState = SPECTATOR_FREE;
163 	}
164 
165 	AddTournamentQueue(client);
166 
167 	// DHM - Nerve
168 	sess->playerType = 0;
169 	sess->playerWeapon = 0;
170 	sess->playerPistol = 0;
171 	sess->playerItem = 0;
172 	sess->playerSkin = 0;
173 	// dhm - end
174 
175 	G_WriteClientSessionData( client );
176 }
177 
178 
179 /*
180 ==================
181 G_InitWorldSession
182 
183 ==================
184 */
G_InitWorldSession(void)185 void G_InitWorldSession( void ) {
186 	char s[MAX_STRING_CHARS];
187 	int gt;
188 
189 	trap_Cvar_VariableStringBuffer( "session", s, sizeof( s ) );
190 	gt = atoi( s );
191 
192 	// if the gametype changed since the last session, don't use any
193 	// client sessions
194 	if ( g_gametype.integer != gt ) {
195 		level.newSession = qtrue;
196 		G_Printf( "Gametype changed, clearing session data.\n" );
197 	}
198 }
199 
200 /*
201 ==================
202 G_WriteSessionData
203 
204 ==================
205 */
G_WriteSessionData(void)206 void G_WriteSessionData( void ) {
207 	int i;
208 
209 	trap_Cvar_Set( "session", va( "%i", g_gametype.integer ) );
210 
211 	for ( i = 0 ; i < level.maxclients ; i++ ) {
212 		if ( level.clients[i].pers.connected == CON_CONNECTED ) {
213 			G_WriteClientSessionData( &level.clients[i] );
214 		}
215 	}
216 }
217