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