1 /*
2 ===========================================================================
3 Copyright (C) 1999 - 2005, Id Software, Inc.
4 Copyright (C) 2000 - 2013, Raven Software, Inc.
5 Copyright (C) 2001 - 2013, Activision, Inc.
6 Copyright (C) 2013 - 2015, OpenJK contributors
7 
8 This file is part of the OpenJK source code.
9 
10 OpenJK is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License version 2 as
12 published by the Free Software Foundation.
13 
14 This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
21 ===========================================================================
22 */
23 
24 // cg_info.c -- display information while data is being loading
25 
26 #include "cg_local.h"
27 
28 #define MAX_LOADING_PLAYER_ICONS	16
29 #define MAX_LOADING_ITEM_ICONS		26
30 
31 //static int			loadingPlayerIconCount;
32 //static qhandle_t	loadingPlayerIcons[MAX_LOADING_PLAYER_ICONS];
33 
34 void CG_LoadBar(void);
35 
36 /*
37 ======================
38 CG_LoadingString
39 
40 ======================
41 */
CG_LoadingString(const char * s)42 void CG_LoadingString( const char *s ) {
43 	Q_strncpyz( cg.infoScreenText, s, sizeof( cg.infoScreenText ) );
44 
45 	trap->UpdateScreen();
46 }
47 
48 /*
49 ===================
50 CG_LoadingItem
51 ===================
52 */
CG_LoadingItem(int itemNum)53 void CG_LoadingItem( int itemNum ) {
54 	gitem_t		*item;
55 	char	upperKey[1024];
56 
57 	item = &bg_itemlist[itemNum];
58 
59 	if (!item->classname || !item->classname[0])
60 	{
61 	//	CG_LoadingString( "Unknown item" );
62 		return;
63 	}
64 
65 	strcpy(upperKey, item->classname);
66 	CG_LoadingString( CG_GetStringEdString("SP_INGAME",Q_strupr(upperKey)) );
67 }
68 
69 /*
70 ===================
71 CG_LoadingClient
72 ===================
73 */
CG_LoadingClient(int clientNum)74 void CG_LoadingClient( int clientNum ) {
75 	const char		*info;
76 	char			personality[MAX_QPATH];
77 
78 	info = CG_ConfigString( CS_PLAYERS + clientNum );
79 
80 /*
81 	char			model[MAX_QPATH];
82 	char			iconName[MAX_QPATH];
83 	char			*skin;
84 	if ( loadingPlayerIconCount < MAX_LOADING_PLAYER_ICONS ) {
85 		Q_strncpyz( model, Info_ValueForKey( info, "model" ), sizeof( model ) );
86 		skin = Q_strrchr( model, '/' );
87 		if ( skin ) {
88 			*skin++ = '\0';
89 		} else {
90 			skin = "default";
91 		}
92 
93 		Com_sprintf( iconName, MAX_QPATH, "models/players/%s/icon_%s.tga", model, skin );
94 
95 		loadingPlayerIcons[loadingPlayerIconCount] = trap->R_RegisterShaderNoMip( iconName );
96 		if ( !loadingPlayerIcons[loadingPlayerIconCount] ) {
97 			Com_sprintf( iconName, MAX_QPATH, "models/players/characters/%s/icon_%s.tga", model, skin );
98 			loadingPlayerIcons[loadingPlayerIconCount] = trap->R_RegisterShaderNoMip( iconName );
99 		}
100 		if ( !loadingPlayerIcons[loadingPlayerIconCount] ) {
101 			Com_sprintf( iconName, MAX_QPATH, "models/players/%s/icon_%s.tga", DEFAULT_MODEL, "default" );
102 			loadingPlayerIcons[loadingPlayerIconCount] = trap->R_RegisterShaderNoMip( iconName );
103 		}
104 		if ( loadingPlayerIcons[loadingPlayerIconCount] ) {
105 			loadingPlayerIconCount++;
106 		}
107 	}
108 */
109 	Q_strncpyz( personality, Info_ValueForKey( info, "n" ), sizeof(personality) );
110 //	Q_CleanStr( personality );
111 
112 	/*
113 	if( cgs.gametype == GT_SINGLE_PLAYER ) {
114 		trap->S_RegisterSound( va( "sound/player/announce/%s.wav", personality ));
115 	}
116 	*/
117 
118 	CG_LoadingString( personality );
119 }
120 
121 
122 /*
123 ====================
124 CG_DrawInformation
125 
126 Draw all the status / pacifier stuff during level loading
127 ====================
128 overlays UI_DrawConnectScreen
129 */
130 #define UI_INFOFONT (UI_BIGFONT)
CG_DrawInformation(void)131 void CG_DrawInformation( void ) {
132 	const char	*s;
133 	const char	*info;
134 	const char	*sysInfo;
135 	int			y;
136 	int			value, valueNOFP;
137 	qhandle_t	levelshot;
138 	char		buf[1024];
139 	int			iPropHeight = 18;	// I know, this is total crap, but as a post release asian-hack....  -Ste
140 
141 	info = CG_ConfigString( CS_SERVERINFO );
142 	sysInfo = CG_ConfigString( CS_SYSTEMINFO );
143 
144 	s = Info_ValueForKey( info, "mapname" );
145 	levelshot = trap->R_RegisterShaderNoMip( va( "levelshots/%s", s ) );
146 	if ( !levelshot ) {
147 		levelshot = trap->R_RegisterShaderNoMip( "menu/art/unknownmap_mp" );
148 	}
149 	trap->R_SetColor( NULL );
150 	CG_DrawPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, levelshot );
151 
152 	CG_LoadBar();
153 
154 	// draw the icons of things as they are loaded
155 //	CG_DrawLoadingIcons();
156 
157 	// the first 150 rows are reserved for the client connection
158 	// screen to write into
159 	if ( cg.infoScreenText[0] ) {
160 		const char *psLoading = CG_GetStringEdString("MENUS", "LOADING_MAPNAME");
161 		CG_DrawProportionalString( 320, 128-32, va(/*"Loading... %s"*/ psLoading, cg.infoScreenText), UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
162 	} else {
163 		const char *psAwaitingSnapshot = CG_GetStringEdString("MENUS", "AWAITING_SNAPSHOT");
164 		CG_DrawProportionalString( 320, 128-32, /*"Awaiting snapshot..."*/psAwaitingSnapshot, UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
165 	}
166 
167 	// draw info string information
168 
169 	y = 180-32;
170 
171 	// don't print server lines if playing a local game
172 	trap->Cvar_VariableStringBuffer( "sv_running", buf, sizeof( buf ) );
173 	if ( !atoi( buf ) ) {
174 		// server hostname
175 		Q_strncpyz(buf, Info_ValueForKey( info, "sv_hostname" ), sizeof( buf ) );
176 		Q_CleanStr(buf);
177 		CG_DrawProportionalString( 320, y, buf, UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
178 		y += iPropHeight;
179 
180 		// pure server
181 		s = Info_ValueForKey( sysInfo, "sv_pure" );
182 		if ( s[0] == '1' ) {
183 			const char *psPure = CG_GetStringEdString("MP_INGAME", "PURE_SERVER");
184 			CG_DrawProportionalString( 320, y, psPure, UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
185 			y += iPropHeight;
186 		}
187 
188 		// server-specific message of the day
189 		s = CG_ConfigString( CS_MOTD );
190 		if ( s[0] ) {
191 			CG_DrawProportionalString( 320, y, s, UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
192 			y += iPropHeight;
193 		}
194 
195 		{	// display global MOTD at bottom (mirrors ui_main UI_DrawConnectScreen
196 			char motdString[1024];
197 			trap->Cvar_VariableStringBuffer( "cl_motdString", motdString, sizeof( motdString ) );
198 
199 			if (motdString[0])
200 			{
201 				CG_DrawProportionalString( 320, 425, motdString, UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
202 			}
203 		}
204 
205 		// some extra space after hostname and motd
206 		y += 10;
207 	}
208 
209 	// map-specific message (long map name)
210 	s = CG_ConfigString( CS_MESSAGE );
211 	if ( s[0] ) {
212 		CG_DrawProportionalString( 320, y, s, UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
213 		y += iPropHeight;
214 	}
215 
216 	// cheats warning
217 	s = Info_ValueForKey( sysInfo, "sv_cheats" );
218 	if ( s[0] == '1' ) {
219 		CG_DrawProportionalString( 320, y, CG_GetStringEdString("MP_INGAME", "CHEATSAREENABLED"), UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
220 		y += iPropHeight;
221 	}
222 
223 	// game type
224 	s = BG_GetGametypeString( cgs.gametype );
225 	CG_DrawProportionalString( 320, y, s, UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
226 	y += iPropHeight;
227 
228 	if (cgs.gametype != GT_SIEGE)
229 	{
230 		value = atoi( Info_ValueForKey( info, "timelimit" ) );
231 		if ( value ) {
232 			CG_DrawProportionalString( 320, y, va( "%s %i", CG_GetStringEdString("MP_INGAME", "TIMELIMIT"), value ), UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
233 			y += iPropHeight;
234 		}
235 
236 		if (cgs.gametype < GT_CTF ) {
237 			value = atoi( Info_ValueForKey( info, "fraglimit" ) );
238 			if ( value ) {
239 				CG_DrawProportionalString( 320, y, va( "%s %i", CG_GetStringEdString("MP_INGAME", "FRAGLIMIT"), value ), UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
240 				y += iPropHeight;
241 			}
242 
243 			if (cgs.gametype == GT_DUEL || cgs.gametype == GT_POWERDUEL)
244 			{
245 				value = atoi( Info_ValueForKey( info, "duel_fraglimit" ) );
246 				if ( value ) {
247 					CG_DrawProportionalString( 320, y, va( "%s %i", CG_GetStringEdString("MP_INGAME", "WINLIMIT"), value ), UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
248 					y += iPropHeight;
249 				}
250 			}
251 		}
252 	}
253 
254 	if (cgs.gametype >= GT_CTF) {
255 		value = atoi( Info_ValueForKey( info, "capturelimit" ) );
256 		if ( value ) {
257 			CG_DrawProportionalString( 320, y, va( "%s %i", CG_GetStringEdString("MP_INGAME", "CAPTURELIMIT"), value ), UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
258 			y += iPropHeight;
259 		}
260 	}
261 
262 	if (cgs.gametype >= GT_TEAM)
263 	{
264 		value = atoi( Info_ValueForKey( info, "g_forceBasedTeams" ) );
265 		if ( value ) {
266 			CG_DrawProportionalString( 320, y, CG_GetStringEdString("MP_INGAME", "FORCEBASEDTEAMS"), UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
267 			y += iPropHeight;
268 		}
269 	}
270 
271     if (cgs.gametype != GT_SIEGE)
272 	{
273 		valueNOFP = atoi( Info_ValueForKey( info, "g_forcePowerDisable" ) );
274 
275 		value = atoi( Info_ValueForKey( info, "g_maxForceRank" ) );
276 		if ( value && !valueNOFP && (value < NUM_FORCE_MASTERY_LEVELS) ) {
277 			char fmStr[1024];
278 
279 			trap->SE_GetStringTextString("MP_INGAME_MAXFORCERANK",fmStr, sizeof(fmStr));
280 
281 			CG_DrawProportionalString( 320, y, va( "%s %s", fmStr, CG_GetStringEdString("MP_INGAME", forceMasteryLevels[value]) ), UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
282 			y += iPropHeight;
283 		}
284 		else if (!valueNOFP)
285 		{
286 			char fmStr[1024];
287 			trap->SE_GetStringTextString("MP_INGAME_MAXFORCERANK",fmStr, sizeof(fmStr));
288 
289 			CG_DrawProportionalString( 320, y, va( "%s %s", fmStr, (char *)CG_GetStringEdString("MP_INGAME", forceMasteryLevels[7]) ), UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
290 			y += iPropHeight;
291 		}
292 
293 		if (cgs.gametype == GT_DUEL || cgs.gametype == GT_POWERDUEL)
294 		{
295 			value = atoi( Info_ValueForKey( info, "g_duelWeaponDisable" ) );
296 		}
297 		else
298 		{
299 			value = atoi( Info_ValueForKey( info, "g_weaponDisable" ) );
300 		}
301 		if ( cgs.gametype != GT_JEDIMASTER && value ) {
302 			CG_DrawProportionalString( 320, y, va( "%s", (char *)CG_GetStringEdString("MP_INGAME", "SABERONLYSET") ), UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
303 			y += iPropHeight;
304 		}
305 
306 		if ( valueNOFP ) {
307 			CG_DrawProportionalString( 320, y, va( "%s", (char *)CG_GetStringEdString("MP_INGAME", "NOFPSET") ), UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
308 			y += iPropHeight;
309 		}
310 	}
311 
312 	// Display the rules based on type
313 		y += iPropHeight;
314 	switch ( cgs.gametype ) {
315 	case GT_FFA:
316 		CG_DrawProportionalString( 320, y, va( "%s", (char *)CG_GetStringEdString("MP_INGAME", "RULES_FFA_1")), UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
317 		y += iPropHeight;
318 		break;
319 	case GT_HOLOCRON:
320 		CG_DrawProportionalString( 320, y, va( "%s", (char *)CG_GetStringEdString("MP_INGAME", "RULES_HOLO_1")), UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
321 		y += iPropHeight;
322 		CG_DrawProportionalString( 320, y, va( "%s", (char *)CG_GetStringEdString("MP_INGAME", "RULES_HOLO_2")), UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
323 		y += iPropHeight;
324 		break;
325 	case GT_JEDIMASTER:
326 		CG_DrawProportionalString( 320, y, va( "%s", (char *)CG_GetStringEdString("MP_INGAME", "RULES_JEDI_1")), UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
327 		y += iPropHeight;
328 		CG_DrawProportionalString( 320, y, va( "%s", (char *)CG_GetStringEdString("MP_INGAME", "RULES_JEDI_2")), UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
329 		y += iPropHeight;
330 		break;
331 	case GT_SINGLE_PLAYER:
332 		break;
333 	case GT_DUEL:
334 		CG_DrawProportionalString( 320, y, va( "%s", (char *)CG_GetStringEdString("MP_INGAME", "RULES_DUEL_1")), UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
335 		y += iPropHeight;
336 		CG_DrawProportionalString( 320, y, va( "%s", (char *)CG_GetStringEdString("MP_INGAME", "RULES_DUEL_2")), UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
337 		y += iPropHeight;
338 		break;
339 	case GT_POWERDUEL:
340 		CG_DrawProportionalString( 320, y, va( "%s", (char *)CG_GetStringEdString("MP_INGAME", "RULES_POWERDUEL_1")), UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
341 		y += iPropHeight;
342 		CG_DrawProportionalString( 320, y, va( "%s", (char *)CG_GetStringEdString("MP_INGAME", "RULES_POWERDUEL_2")), UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
343 		y += iPropHeight;
344 		break;
345 	case GT_TEAM:
346 		CG_DrawProportionalString( 320, y, va( "%s", (char *)CG_GetStringEdString("MP_INGAME", "RULES_TEAM_1")), UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
347 		y += iPropHeight;
348 		CG_DrawProportionalString( 320, y, va( "%s", (char *)CG_GetStringEdString("MP_INGAME", "RULES_TEAM_2")), UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
349 		y += iPropHeight;
350 		break;
351 	case GT_SIEGE:
352 		break;
353 	case GT_CTF:
354 		CG_DrawProportionalString( 320, y, va( "%s", (char *)CG_GetStringEdString("MP_INGAME", "RULES_CTF_1")), UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
355 		y += iPropHeight;
356 		CG_DrawProportionalString( 320, y, va( "%s", (char *)CG_GetStringEdString("MP_INGAME", "RULES_CTF_2")), UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
357 		y += iPropHeight;
358 		break;
359 	case GT_CTY:
360 		CG_DrawProportionalString( 320, y, va( "%s", (char *)CG_GetStringEdString("MP_INGAME", "RULES_CTY_1")), UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
361 		y += iPropHeight;
362 		CG_DrawProportionalString( 320, y, va( "%s", (char *)CG_GetStringEdString("MP_INGAME", "RULES_CTY_2")), UI_CENTER|UI_INFOFONT|UI_DROPSHADOW, colorWhite );
363 		y += iPropHeight;
364 		break;
365 	default:
366 		break;
367 	}
368 }
369 
370 /*
371 ===================
372 CG_LoadBar
373 ===================
374 */
CG_LoadBar(void)375 void CG_LoadBar(void)
376 {
377 	const int numticks = 9, tickwidth = 40, tickheight = 8;
378 	const int tickpadx = 20, tickpady = 12;
379 	const int capwidth = 8;
380 	const int barwidth = numticks*tickwidth+tickpadx*2+capwidth*2, barleft = ((640-barwidth)/2);
381 	const int barheight = tickheight + tickpady*2, bartop = 480-barheight;
382 	const int capleft = barleft+tickpadx, tickleft = capleft+capwidth, ticktop = bartop+tickpady;
383 
384 	trap->R_SetColor( colorWhite );
385 	// Draw background
386 	CG_DrawPic(barleft, bartop, barwidth, barheight, cgs.media.loadBarLEDSurround);
387 
388 	// Draw left cap (backwards)
389 	CG_DrawPic(tickleft, ticktop, -capwidth, tickheight, cgs.media.loadBarLEDCap);
390 
391 	// Draw bar
392 	CG_DrawPic(tickleft, ticktop, tickwidth*cg.loadLCARSStage, tickheight, cgs.media.loadBarLED);
393 
394 	// Draw right cap
395 	CG_DrawPic(tickleft+tickwidth*cg.loadLCARSStage, ticktop, capwidth, tickheight, cgs.media.loadBarLEDCap);
396 }
397 
398