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 #include "cg_local.h"
25 #include "cg_media.h"
26 #include "../game/objectives.h"
27 #include "strip_objectives.h"
28 
29 static const int missionYpos = 79;
30 
31 const char *showLoadPowersName[] =
32 {
33 	"INGAME_HEAL2",
34 	"INGAME_JUMP2",
35 	"INGAME_SPEED2",
36 	"INGAME_PUSH2",
37 	"INGAME_PULL2",
38 	"INGAME_MINDTRICK2",
39 	"INGAME_GRIP2",
40 	"INGAME_LIGHTNING2",
41 	"INGAME_SABER_THROW2",
42 	"INGAME_SABER_OFFENSE2",
43 	"INGAME_SABER_DEFENSE2",
44 	NULL,
45 };
46 
47 // Hack to see if the graphics objectives have been printed.
48 int obj_graphics[4];
49 
50 /*
51 ====================
52 MissionPrint_Line
53 ====================
54 */
MissionPrint_Line(const int color,const int objectIndex,int & missionYcnt)55 static void MissionPrint_Line(const int color, const int objectIndex, int &missionYcnt)
56 {
57 	char *str,*strBegin;
58 	int y,pixelLen,charLen;
59 	char holdText[1024] ;
60 	char finalText[2048];
61 	qhandle_t	graphic;
62 
63 	int iYPixelsPerLine = cgi_R_Font_HeightPixels(cgs.media.qhFontMedium, 1.0f) * (cgi_Language_IsAsian() ? 1.2f : 1.0f );
64 
65 	cgi_SP_GetStringText( PACKAGE_OBJECTIVES<<8|objectIndex , finalText, sizeof(finalText) );
66 
67 	pixelLen = cgi_R_Font_StrLenPixels(finalText, cgs.media.qhFontMedium, 1.0f);
68 
69 	str = finalText;
70 
71 /*	CG_DisplayBoxedText(70,50,500,300,finalText,
72 						cgs.media.qhFontSmall,
73 						1.0f,
74 						colorTable[color]
75 						);
76 */
77 	if (pixelLen < 500)	// One shot - small enough to print entirely on one line
78 	{
79 		y =missionYpos + (iYPixelsPerLine * (missionYcnt));
80 		if (obj_graphics[0])
81 		{
82 			y += 32 + 4;
83 		}
84 		if (obj_graphics[1])
85 		{
86 			y += 32 + 4;
87 		}
88 		if (obj_graphics[2])
89 		{
90 			y += 32 + 4;
91 		}
92 		//CG_DrawProportionalString(108, y,str, CG_SMALLFONT, colorTable[color] );
93 		cgi_R_Font_DrawString (108, y, str, colorTable[color], cgs.media.qhFontMedium, -1, 1.0f);
94 		++missionYcnt;
95 	}
96 	// Text is too long, break into lines.
97 	else
98 	{
99 		char holdText2[2];
100 		pixelLen = 0;
101 		charLen = 0;
102 		holdText2[1] = '\0';
103 		strBegin = str;
104 
105 		while( *str )
106 		{
107 			holdText2[0] = *str;
108 			pixelLen += cgi_R_Font_StrLenPixels(holdText2, cgs.media.qhFontMedium, 1.0f);
109 
110 			pixelLen += 2; // For kerning
111 			++charLen;
112 
113 			if (pixelLen > 500 )
114 			{	//Reached max length of this line
115 				//step back until we find a space
116 				while ((charLen) && (*str != ' ' ))
117 				{
118 					--str;
119 					--charLen;
120 				}
121 
122 				if (*str==' ')
123 				{
124 					++str;	// To get past space
125 				}
126 
127 				Q_strncpyz( holdText, strBegin, charLen);
128 				holdText[charLen] = '\0';
129 				strBegin = str;
130 				pixelLen = 0;
131 				charLen = 1;
132 
133 				y = missionYpos + (iYPixelsPerLine * missionYcnt);
134 
135 				CG_DrawProportionalString(108, y, holdText, CG_SMALLFONT, colorTable[color] );
136 				++missionYcnt;
137 			}
138 			else if (*(str+1) == '\0')
139 			{
140 				++charLen;
141 
142 				y = missionYpos + (iYPixelsPerLine * missionYcnt);
143 
144 				Q_strncpyz( holdText, strBegin, charLen);
145 				CG_DrawProportionalString(108, y, holdText, CG_SMALLFONT, colorTable[color] );
146 				++missionYcnt;
147 				break;
148 			}
149 			++str;
150 
151 
152 		}
153 	}
154 
155 	// Special case hack
156 	if (objectIndex == DOOM_COMM_OBJ4)
157 	{
158 		y = missionYpos + (iYPixelsPerLine * missionYcnt);
159 		graphic = cgi_R_RegisterShaderNoMip("textures/system/securitycode");
160 		CG_DrawPic( 320 - (128/2), y+8, 128, 32, graphic );
161 		obj_graphics[0] = qtrue;
162 	}
163 	else if (objectIndex == KEJIM_POST_OBJ3)
164 	{
165 		y = missionYpos + (iYPixelsPerLine * missionYcnt);
166 		graphic = cgi_R_RegisterShaderNoMip("textures/system/securitycode_red");
167 		CG_DrawPic( 320 - (32/2), y+8, 32, 32, graphic );
168 		obj_graphics[1] = qtrue;
169 	}
170 	else if (objectIndex == KEJIM_POST_OBJ4)
171 	{
172 		y =missionYpos + (iYPixelsPerLine * missionYcnt);
173 		if (obj_graphics[1])
174 		{
175 			y += 32 + 4;
176 		}
177 		graphic = cgi_R_RegisterShaderNoMip("textures/system/securitycode_green");
178 		CG_DrawPic( 320 - (32/2), y+8, 32, 32, graphic );
179 		obj_graphics[2] = qtrue;
180 	}
181 	else if (objectIndex == KEJIM_POST_OBJ5)
182 	{
183 		y =missionYpos + (iYPixelsPerLine * missionYcnt);
184 		if (obj_graphics[1])
185 		{
186 			y += 32 + 4;
187 		}
188 		if (obj_graphics[2])
189 		{
190 			y += 32 + 4;
191 		}
192 		graphic = cgi_R_RegisterShaderNoMip("textures/system/securitycode_blue");
193 		CG_DrawPic( 320 - (32/2), y+8, 32, 32, graphic );
194 		obj_graphics[3] = qtrue;
195 	}
196 }
197 
198 /*
199 ====================
200 MissionInformation_Draw
201 ====================
202 */
MissionInformation_Draw(centity_t * cent)203 void MissionInformation_Draw( centity_t *cent )
204 {
205 	int		i,totalY;
206 	int iYPixelsPerLine = cgi_R_Font_HeightPixels(cgs.media.qhFontMedium, 1.0f) * (cgi_Language_IsAsian() ? 1.2f : 1.0f );
207 
208 	missionInfo_Updated = qfalse;		// This will stop the text from flashing
209 	cg.missionInfoFlashTime = 0;
210 
211 	// Frame
212 	char text[1024]={0};
213 	cgi_SP_GetStringTextString( "INGAME_OBJECTIVES", text, sizeof(text) );
214 	cgi_R_Font_DrawString (96, missionYpos-23, text, colorTable[CT_WHITE], cgs.media.qhFontMedium, -1, 1.0f);
215 
216 	int missionYcnt = 0;
217 
218 	obj_graphics[0] = obj_graphics[1] = obj_graphics[2] = obj_graphics[3] = qfalse;
219 
220 	// Print active objectives
221 	cgi_R_SetColor(colorTable[CT_BLUE3]);
222 	for (i=0;i<MAX_OBJECTIVES;++i)
223 	{
224 		if (cent->gent->client->sess.mission_objectives[i].display)
225 		{
226 			totalY = missionYpos + (iYPixelsPerLine * (missionYcnt))+(iYPixelsPerLine/2);
227 			if (obj_graphics[0])
228 			{
229 				totalY += 32 + 4;
230 			}
231 			if (obj_graphics[1])
232 			{
233 				totalY += 32 + 4;
234 			}
235 			if (obj_graphics[2])
236 			{
237 				totalY += 32 + 4;
238 			}
239 			if (obj_graphics[3])
240 			{
241 				totalY += 32 + 4;
242 			}
243 
244 			//	OBJECTIVE_STAT_PENDING
245 			CG_DrawPic( 88,   totalY,   16,  16, cgs.media.messageObjCircle);	// Circle in front
246 			if (cent->gent->client->sess.mission_objectives[i].status == OBJECTIVE_STAT_SUCCEEDED)
247 			{
248 				CG_DrawPic( 88,   totalY,   16,  16, cgs.media.messageLitOn);	// Center Dot
249 			}
250 			MissionPrint_Line(CT_BLUE3, i, missionYcnt );
251 		}
252 	}
253 
254 	if (!missionYcnt)
255 	{
256 		cgi_SP_GetStringTextString( "INGAME_OBJNONE", text, sizeof(text) );
257 //		CG_DrawProportionalString(108, missionYpos, text, CG_SMALLFONT, colorTable[CT_LTBLUE1] );
258 		cgi_R_Font_DrawString (108, missionYpos, text, colorTable[CT_LTBLUE1], cgs.media.qhFontMedium, -1, 1.0f);
259 	}
260 }
261 
262 /*
263 
264 //-------------------------------------------------------
265 static void CG_DrawForceCount( const int force, int x, float *y, const int pad,qboolean *hasForcePowers )
266 {
267 	char	s[MAX_STRING_CHARS];
268 	int		val, textColor;
269 	char	text[1024]={0};
270 
271 	gi.Cvar_VariableStringBuffer( va("playerfplvl%d", force ),s, sizeof(s) );
272 
273 	sscanf( s, "%d",&val );
274 
275 	if ((val<1) || (val> NUM_FORCE_POWERS))
276 	{
277 		return;
278 	}
279 
280 	textColor = CT_ICON_BLUE;
281 
282 	// Draw title
283 	cgi_SP_GetStringTextString( showLoadPowersName[force], text, sizeof(text) );
284 	CG_DrawProportionalString( x, *y, text, CG_BIGFONT, colorTable[textColor] );
285 
286 
287 	// Draw icons
288 	cgi_R_SetColor( colorTable[CT_WHITE]);
289 	const int iconSize = 30;
290 	if ( val >= 0 )
291 	{
292 		x -= 10;	// Back up from title a little
293 
294 		for ( int i = 0; i < val; i++ )
295 		{
296 			CG_DrawPic( x - iconSize - i * (iconSize + 10) , *y, iconSize, iconSize, force_icons[force] );
297 		}
298 	}
299 
300 	*y += pad;
301 
302 	*hasForcePowers = qtrue;
303 }
304 
305 
306 /*
307 ====================
308 CG_LoadScreen_PersonalInfo
309 ====================
310 */
311 /*
312 static void CG_LoadScreen_PersonalInfo(void)
313 {
314 	float	x, y;
315 	int		pad = 25;
316 	char	text[1024]={0};
317 	qboolean	hasForcePowers;
318 
319 	y = 65 + 30;
320 
321 	pad = 28;
322 	x = 300;
323 	hasForcePowers=qfalse;
324 
325 	CG_DrawForceCount( FP_HEAL, x, &y, pad,&hasForcePowers);
326 	CG_DrawForceCount( FP_LEVITATION, x, &y, pad,&hasForcePowers );
327 	CG_DrawForceCount( FP_SPEED, x, &y, pad,&hasForcePowers );
328 	CG_DrawForceCount( FP_PUSH, x, &y, pad,&hasForcePowers );
329 	CG_DrawForceCount( FP_PULL, x, &y, pad,&hasForcePowers );
330 	CG_DrawForceCount( FP_TELEPATHY, x, &y, pad,&hasForcePowers );
331 	CG_DrawForceCount( FP_GRIP, x, &y, pad,&hasForcePowers );
332 	CG_DrawForceCount( FP_LIGHTNING, x, &y, pad,&hasForcePowers );
333 	CG_DrawForceCount( FP_SABERTHROW, x, &y, pad,&hasForcePowers );
334 	CG_DrawForceCount( FP_SABER_OFFENSE, x, &y, pad,&hasForcePowers );
335 	CG_DrawForceCount( FP_SABER_DEFENSE, x, &y, pad,&hasForcePowers );
336 
337 	if (hasForcePowers)
338 	{
339 		cgi_SP_GetStringTextString( "INGAME_CURRENTFORCEPOWERS", text, sizeof(text) );
340 		CG_DrawProportionalString( 200, 65, text, CG_CENTER | CG_BIGFONT, colorTable[CT_WHITE] );
341 	}
342 	else
343 	{	//you are only totally empty on the very first map?
344 //		cgi_SP_GetStringTextString( "INGAME_NONE", text, sizeof(text) );
345 //		CG_DrawProportionalString( 320, y+30, text, CG_CENTER | CG_BIGFONT, colorTable[CT_ICON_BLUE] );
346 		cgi_SP_GetStringTextString( "INGAME_ALONGTIME", text, sizeof(text) );
347 		int w = cgi_R_Font_StrLenPixels(text,cgs.media.qhFontMedium, 1.5f);
348 		cgi_R_Font_DrawString((320)-(w/2), y+40, text,  colorTable[CT_ICON_BLUE], cgs.media.qhFontMedium, -1, 1.5f);
349 	}
350 
351 }
352 */
353 
CG_LoadBar(void)354 static void CG_LoadBar(void)
355 {
356 	const int numticks = 9, tickwidth = 40, tickheight = 8;
357 	const int tickpadx = 20, tickpady = 12;
358 	const int capwidth = 8;
359 	const int barwidth = numticks*tickwidth+tickpadx*2+capwidth*2, barleft = ((640-barwidth)/2);
360 	const int barheight = tickheight + tickpady*2, bartop = 480-barheight;
361 	const int capleft = barleft+tickpadx, tickleft = capleft+capwidth, ticktop = bartop+tickpady;
362 
363 	cgi_R_SetColor( colorTable[CT_WHITE]);
364 	// Draw background
365 	CG_DrawPic(barleft, bartop, barwidth, barheight, cgs.media.levelLoad);
366 
367 	// Draw left cap (backwards)
368 	CG_DrawPic(tickleft, ticktop, -capwidth, tickheight, cgs.media.loadTickCap);
369 
370 	// Draw bar
371 	CG_DrawPic(tickleft, ticktop, tickwidth*cg.loadLCARSStage, tickheight, cgs.media.loadTick);
372 
373 	// Draw right cap
374 	CG_DrawPic(tickleft+tickwidth*cg.loadLCARSStage, ticktop, capwidth, tickheight, cgs.media.loadTickCap);
375 }
376 
377 /*
378 ====================
379 CG_DrawInformation
380 
381 Draw all the status / pacifier stuff during level loading
382 overylays UI_DrawConnectText from ui_connect.cpp
383 ====================
384 */
CG_DrawInformation(void)385 void CG_DrawInformation( void ) {
386 	int			y;
387 
388 
389 	// draw the dialog background
390 	const char	*info	= CG_ConfigString( CS_SERVERINFO );
391 	const char	*s		= Info_ValueForKey( info, "mapname" );
392 	qhandle_t	levelshot;
393 
394 	if (!strcmp(s,"bespin_undercity")) // this map has no levelshot
395 		levelshot = cgi_R_RegisterShaderNoMip( "levelshots/kejim_post" );
396 	else
397 		levelshot = cgi_R_RegisterShaderNoMip( va( "levelshots/%s", s ) );
398 
399 	if (!levelshot) {
400 		levelshot = cgi_R_RegisterShaderNoMip( "menu/art/unknownmap" );
401 	}
402 
403 	extern SavedGameJustLoaded_e g_eSavedGameJustLoaded;	// hack! (hey, it's the last week of coding, ok?
404 #ifdef JK2_MODE
405 	if ( !levelshot || g_eSavedGameJustLoaded == eFULL )
406 	{
407 		// keep whatever's in the screen buffer so far (either the last ingame rendered-image (eg for maptransition)
408 		//	or the screenshot built-in to a loaded save game...
409 		//
410 		cgi_R_DrawScreenShot( 0, 0, 640, 480 );
411 	} else
412 #endif
413 	{
414 		// put up the pre-defined levelshot for this map...
415 		//
416 		cgi_R_SetColor( NULL );
417 		CG_DrawPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, levelshot );
418 	}
419 
420 	if ( g_eSavedGameJustLoaded != eFULL && !strcmp(s,"kejim_post") )//special case for first map!
421 	{
422 		char	text[1024]={0};
423 		cgi_SP_GetStringTextString( "INGAME_ALONGTIME", text, sizeof(text) );
424 
425 		int w = cgi_R_Font_StrLenPixels(text,cgs.media.qhFontMedium, 1.0f);
426 		cgi_R_Font_DrawString((320)-(w/2), 140, text,  colorTable[CT_ICON_BLUE], cgs.media.qhFontMedium, -1, 1.0f);
427 	}
428 	else
429 	if (cg_missionstatusscreen.integer )
430 	{
431 		CG_MissionCompletion();
432 	}
433 	CG_LoadBar();
434 
435 
436 	// the first 150 rows are reserved for the client connection
437 	// screen to write into
438 	if ( cg.processedSnapshotNum == 0 ) {
439 		// still loading
440 		// print the current item being loaded
441 
442 #ifndef NDEBUG
443 		cgi_R_Font_DrawString( 48, 398, va("LOADING ... %s",cg.infoScreenText),colorTable[CT_LTGOLD1], cgs.media.qhFontSmall, -1, 1.0f );
444 #endif
445 	}
446 
447 	// draw info string information
448 
449 	y = 20;
450 	// map-specific message (long map name)
451 	s = CG_ConfigString( CS_MESSAGE );
452 
453 	if ( s[0] )
454 	{
455 		if (s[0] == '@')
456 		{
457 			char text[1024]={0};
458 			cgi_SP_GetStringTextString( s+1, text, sizeof(text) );
459 			cgi_R_Font_DrawString( 15, y, va("\"%s\"",text),colorTable[CT_WHITE],cgs.media.qhFontMedium, -1, 1.0f );
460 		}
461 		else
462 		{
463 			cgi_R_Font_DrawString( 15, y, va("\"%s\"",s),colorTable[CT_WHITE],cgs.media.qhFontMedium, -1, 1.0f );
464 		}
465 		y += 20;
466 	}
467 }
468 
469