1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 2016 EDuke32 developers and contributors
4
5 This file is part of EDuke32.
6
7 EDuke32 is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License version 2
9 as published by the Free Software Foundation.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
15 See the GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 */
21 //-------------------------------------------------------------------------
22
23 #include "duke3d.h"
24 #include "compat.h"
25 #include "screens.h"
26 #include "colmatch.h"
27 #include "input.h"
28 #include "anim.h"
29 #include "sbar.h"
30 #include "menus.h"
31 #include "osdfuncs.h"
32 #include "demo.h"
33 #include "mdsprite.h"
34
35 #ifdef __ANDROID__
36 #include "android.h"
37 #endif
38
39 #define COLOR_RED redcol
40 #define COLOR_WHITE whitecol
41
42 #define quotepulseshade (sintable[((uint32_t)totalclock<<5)&2047]>>11)
43
44 palette_t CrosshairColors = { 255, 255, 255, 0 };
45 palette_t DefaultCrosshairColors = { 0, 0, 0, 0 };
46 int32_t g_crosshairSum = -1;
47 // yxaspect and viewingrange just before the 'main' drawrooms call
48 int32_t dr_yxaspect, dr_viewingrange;
49 double g_moveActorsTime, g_moveWorldTime; // in ms, smoothed
50 int32_t g_noLogoAnim = 0;
51 int32_t g_noLogo = 0;
52
53 ////////// OFTEN-USED FEW-LINERS //////////
G_HandleEventsWhileNoInput(void)54 static void G_HandleEventsWhileNoInput(void)
55 {
56 I_ClearAllInput();
57
58 while (!I_CheckAllInput())
59 G_HandleAsync();
60
61 I_ClearAllInput();
62 }
63
G_PlaySoundWhileNoInput(int32_t soundnum)64 static int32_t G_PlaySoundWhileNoInput(int32_t soundnum)
65 {
66 S_PlaySound(soundnum);
67 I_ClearAllInput();
68 while (S_CheckSoundPlaying(-1, soundnum))
69 {
70 G_HandleAsync();
71 if (I_CheckAllInput())
72 {
73 I_ClearAllInput();
74 return 1;
75 }
76 }
77
78 return 0;
79 }
80 //////////
81
P_SetGamePalette(DukePlayer_t * player,uint32_t palid,int32_t set)82 void P_SetGamePalette(DukePlayer_t *player, uint32_t palid, int32_t set)
83 {
84 if (palid >= MAXBASEPALS)
85 palid = 0;
86
87 player->palette = palid;
88
89 if (player != g_player[screenpeek].ps)
90 return;
91
92 videoSetPalette(ud.brightness>>2, palid, set);
93 }
94
G_GetCrosshairColor(void)95 void G_GetCrosshairColor(void)
96 {
97 if (DefaultCrosshairColors.f)
98 return;
99
100 tileLoad(CROSSHAIR);
101
102 if (!waloff[CROSSHAIR])
103 return;
104
105 char const *ptr = (char const *) waloff[CROSSHAIR];
106
107 // find the brightest color in the original 8-bit tile
108 int32_t ii = tilesiz[CROSSHAIR].x * tilesiz[CROSSHAIR].y;
109 int32_t bri = 0, j = 0, i;
110
111 Bassert(ii > 0);
112
113 do
114 {
115 if (*ptr != 255)
116 {
117 i = curpalette[(int32_t) *ptr].r+curpalette[(int32_t) *ptr].g+curpalette[(int32_t) *ptr].b;
118 if (i > j) { j = i; bri = *ptr; }
119 }
120 ptr++;
121 } while (--ii);
122
123 Bmemcpy(&CrosshairColors, &curpalette[bri], sizeof(palette_t));
124 Bmemcpy(&DefaultCrosshairColors, &curpalette[bri], sizeof(palette_t));
125 DefaultCrosshairColors.f = 1; // this flag signifies that the color has been detected
126 }
127
G_SetCrosshairColor(int32_t r,int32_t g,int32_t b)128 void G_SetCrosshairColor(int32_t r, int32_t g, int32_t b)
129 {
130 if (g_crosshairSum == r+(g<<8)+(b<<16))
131 return;
132
133 tileLoad(CROSSHAIR);
134
135 if (!waloff[CROSSHAIR])
136 return;
137
138 if (!DefaultCrosshairColors.f)
139 G_GetCrosshairColor();
140
141 g_crosshairSum = r+(g<<8)+(b<<16);
142 CrosshairColors.r = r;
143 CrosshairColors.g = g;
144 CrosshairColors.b = b;
145
146 char *ptr = (char *) waloff[CROSSHAIR];
147
148 int32_t ii = tilesiz[CROSSHAIR].x * tilesiz[CROSSHAIR].y;
149
150 Bassert(ii > 0);
151
152 int32_t i = (videoGetRenderMode() == REND_CLASSIC)
153 ? paletteGetClosestColor(CrosshairColors.r, CrosshairColors.g, CrosshairColors.b)
154 : paletteGetClosestColor(255, 255, 255); // use white in GL so we can tint it to the right color
155
156 do
157 {
158 if (*ptr != 255)
159 *ptr = i;
160 ptr++;
161 } while (--ii);
162
163 paletteMakeLookupTable(CROSSHAIR_PAL, NULL, CrosshairColors.r, CrosshairColors.g, CrosshairColors.b, 1);
164
165 #ifdef USE_OPENGL
166 // XXX: this makes us also load all hightile textures tinted with the crosshair color!
167 polytint_t & crosshairtint = hictinting[CROSSHAIR_PAL];
168 crosshairtint.r = CrosshairColors.r;
169 crosshairtint.g = CrosshairColors.g;
170 crosshairtint.b = CrosshairColors.b;
171 crosshairtint.f = HICTINT_USEONART | HICTINT_GRAYSCALE;
172 #endif
173 tileInvalidate(CROSSHAIR, -1, -1);
174 }
175
176 #define SCORESHEETOFFSET -20
G_ShowScores(void)177 static void G_ShowScores(void)
178 {
179 int32_t t, i;
180
181 if (g_mostConcurrentPlayers > 1 && (g_gametypeFlags[ud.coop]&GAMETYPE_SCORESHEET))
182 {
183 gametext_center(SCORESHEETOFFSET+58+2, "Multiplayer Totals");
184 gametext_center(SCORESHEETOFFSET+58+10, g_mapInfo[G_LastMapInfoIndex()].name);
185
186 t = 0;
187 minitext(70, SCORESHEETOFFSET+80, "Name", 8, 2+8+16+ROTATESPRITE_MAX);
188 minitext(170, SCORESHEETOFFSET+80, "Frags", 8, 2+8+16+ROTATESPRITE_MAX);
189 minitext(200, SCORESHEETOFFSET+80, "Deaths", 8, 2+8+16+ROTATESPRITE_MAX);
190 minitext(235, SCORESHEETOFFSET+80, "Ping", 8, 2+8+16+ROTATESPRITE_MAX);
191
192 for (i=g_mostConcurrentPlayers-1; i>=0; i--)
193 {
194 if (!g_player[i].playerquitflag)
195 continue;
196
197 minitext(70, SCORESHEETOFFSET+90+t, g_player[i].user_name, g_player[i].ps->palookup, 2+8+16+ROTATESPRITE_MAX);
198
199 Bsprintf(tempbuf, "%-4d", g_player[i].ps->frag);
200 minitext(170, SCORESHEETOFFSET+90+t, tempbuf, 2, 2+8+16+ROTATESPRITE_MAX);
201
202 Bsprintf(tempbuf, "%-4d", g_player[i].frags[i] + g_player[i].ps->fraggedself);
203 minitext(200, SCORESHEETOFFSET+90+t, tempbuf, 2, 2+8+16+ROTATESPRITE_MAX);
204
205 //Bsprintf(tempbuf, "%-4d", g_player[i].ping);
206 //minitext(235, SCORESHEETOFFSET+90+t, tempbuf, 2, 2+8+16+ROTATESPRITE_MAX);
207
208 t += 7;
209 }
210 }
211 }
212 #undef SCORESHEETOFFSET
213
214 ////////// TINT ACCUMULATOR //////////
215
216 typedef struct {
217 int32_t r, g, b;
218 // f: 0-63 scale
219 int32_t maxf, sumf;
220 } palaccum_t;
221
222 #define PALACCUM_INITIALIZER { 0, 0, 0, 0, 0 }
223
224 /* For a picture frame F and n tints C_1, C_2, ... C_n weighted a_1, a_2,
225 * ... a_n (on a 0-1 scale), the faded frame is calculated as
226 *
227 * F_new := (1-max_i(a_i))*F + d*sum_i(a_i), where
228 *
229 * d := max_i(a_i)/sum_i(a_i).
230 *
231 * This means that
232 * 1) tint application is independent of their order.
233 * 2) going from n+1 to n tints is continuous when the leaving one has faded.
234 *
235 * But note that for more than one tint, the composite tint will in general
236 * change its hue as the ratio of the weights of the individual ones changes.
237 */
palaccum_add(palaccum_t * pa,const palette_t * pal,int32_t f)238 static void palaccum_add(palaccum_t *pa, const palette_t *pal, int32_t f)
239 {
240 f = clamp(f, 0, 63);
241 if (f == 0)
242 return;
243
244 pa->maxf = max(pa->maxf, f);
245 pa->sumf += f;
246
247 pa->r += f*clamp(pal->r, 0, 63);
248 pa->g += f*clamp(pal->g, 0, 63);
249 pa->b += f*clamp(pal->b, 0, 63);
250 }
251
G_FadePalaccum(const palaccum_t * pa)252 static void G_FadePalaccum(const palaccum_t *pa)
253 {
254 videoFadePalette(tabledivide32_noinline(pa->r, pa->sumf)<<2,
255 tabledivide32_noinline(pa->g, pa->sumf)<<2,
256 tabledivide32_noinline(pa->b, pa->sumf)<<2, pa->maxf<<2);
257 }
258
259
gtextsc(int32_t sc)260 static int32_t gtextsc(int32_t sc)
261 {
262 return scale(sc, ud.textscale, 400);
263 }
264
265 ////////// DISPLAYREST //////////
266
G_DrawCameraText(int16_t i)267 static void G_DrawCameraText(int16_t i)
268 {
269 if (!T1(i))
270 {
271 rotatesprite_win(24<<16, 33<<16, 65536L, 0, CAMCORNER, 0, 0, 2);
272 rotatesprite_win((320-26)<<16, 34<<16, 65536L, 0, CAMCORNER+1, 0, 0, 2);
273 rotatesprite_win(22<<16, 163<<16, 65536L, 512, CAMCORNER+1, 0, 0, 2+4);
274 rotatesprite_win((310-10)<<16, 163<<16, 65536L, 512, CAMCORNER+1, 0, 0, 2);
275
276 if ((int32_t) totalclock&16)
277 rotatesprite_win(46<<16, 32<<16, 65536L, 0, CAMLIGHT, 0, 0, 2);
278 }
279 else
280 {
281 int32_t flipbits = ((int32_t) totalclock<<1)&48;
282
283 for (bssize_t x=-64; x<394; x+=64)
284 for (bssize_t y=0; y<200; y+=64)
285 rotatesprite_win(x<<16, y<<16, 65536L, 0, STATIC, 0, 0, 2+flipbits);
286 }
287 }
288
G_MoveClouds(void)289 static inline void G_MoveClouds(void)
290 {
291 int32_t i;
292
293 if (totalclock <= g_cloudClock && totalclock >= (g_cloudClock-7))
294 return;
295
296 g_cloudClock = totalclock+6;
297
298 g_cloudX += sintable[(fix16_to_int(g_player[screenpeek].ps->q16ang)+512)&2047]>>9;
299 g_cloudY += sintable[fix16_to_int(g_player[screenpeek].ps->q16ang)&2047]>>9;
300
301 for (i=g_cloudCnt-1; i>=0; i--)
302 {
303 sector[g_cloudSect[i]].ceilingxpanning = g_cloudX>>6;
304 sector[g_cloudSect[i]].ceilingypanning = g_cloudY>>6;
305 }
306 }
307
G_DrawOverheadMap(int32_t cposx,int32_t cposy,int32_t czoom,int16_t cang)308 static void G_DrawOverheadMap(int32_t cposx, int32_t cposy, int32_t czoom, int16_t cang)
309 {
310 int32_t i, j, k, l, x1, y1, x2=0, y2=0, x3, y3, x4, y4, ox, oy, xoff, yoff;
311 int32_t dax, day, cosang, sinang, xspan, yspan, sprx, spry;
312 int32_t xrepeat, yrepeat, z1, z2, startwall, endwall, tilenum, daang;
313 int32_t xvect, yvect, xvect2, yvect2;
314 int16_t p;
315 char col;
316 uwalltype *wal, *wal2;
317 spritetype *spr;
318
319 int32_t tmpydim = (xdim*5)/8;
320
321 renderSetAspect(65536, divscale16(tmpydim*320, xdim*200));
322
323 xvect = sintable[(-cang)&2047] * czoom;
324 yvect = sintable[(1536-cang)&2047] * czoom;
325 xvect2 = mulscale16(xvect, yxaspect);
326 yvect2 = mulscale16(yvect, yxaspect);
327
328 renderDisableFog();
329
330 //Draw red lines
331 for (i=numsectors-1; i>=0; i--)
332 {
333 if (!(show2dsector[i>>3]&(1<<(i&7)))) continue;
334
335 startwall = sector[i].wallptr;
336 endwall = sector[i].wallptr + sector[i].wallnum;
337
338 z1 = sector[i].ceilingz;
339 z2 = sector[i].floorz;
340
341 for (j=startwall, wal=(uwalltype *)&wall[startwall]; j<endwall; j++, wal++)
342 {
343 k = wal->nextwall;
344 if (k < 0) continue;
345
346 if (sector[wal->nextsector].ceilingz == z1)
347 if (sector[wal->nextsector].floorz == z2)
348 if (((wal->cstat|wall[wal->nextwall].cstat)&(16+32)) == 0) continue;
349
350 col = editorcolors[1]; //red
351 if ((wal->cstat|wall[wal->nextwall].cstat)&1) col = editorcolors[5]; //magenta
352
353 if (!(show2dsector[wal->nextsector>>3]&(1<<(wal->nextsector&7))))
354 col = editorcolors[7];
355 else continue;
356
357 ox = wal->x-cposx;
358 oy = wal->y-cposy;
359 x1 = dmulscale16(ox, xvect, -oy, yvect)+(xdim<<11);
360 y1 = dmulscale16(oy, xvect2, ox, yvect2)+(ydim<<11);
361
362 wal2 = (uwalltype *)&wall[wal->point2];
363 ox = wal2->x-cposx;
364 oy = wal2->y-cposy;
365 x2 = dmulscale16(ox, xvect, -oy, yvect)+(xdim<<11);
366 y2 = dmulscale16(oy, xvect2, ox, yvect2)+(ydim<<11);
367
368 renderDrawLine(x1, y1, x2, y2, col);
369 }
370 }
371
372 renderEnableFog();
373
374 //Draw sprites
375 k = g_player[screenpeek].ps->i;
376 for (i=numsectors-1; i>=0; i--)
377 {
378 if (!(show2dsector[i>>3]&(1<<(i&7)))) continue;
379 for (j=headspritesect[i]; j>=0; j=nextspritesect[j])
380 {
381 spr = &sprite[j];
382
383 if (j == k || (spr->cstat&0x8000) || spr->cstat == 257 || spr->xrepeat == 0) continue;
384
385 col = editorcolors[6]; //cyan
386 if (spr->cstat&1) col = editorcolors[5]; //magenta
387
388 sprx = spr->x;
389 spry = spr->y;
390
391 if ((spr->cstat&257) != 0) switch (spr->cstat&48)
392 {
393 case 0:
394 // break;
395
396 ox = sprx-cposx;
397 oy = spry-cposy;
398 x1 = dmulscale16(ox, xvect, -oy, yvect);
399 y1 = dmulscale16(oy, xvect2, ox, yvect2);
400
401 ox = (sintable[(spr->ang+512)&2047]>>7);
402 oy = (sintable[(spr->ang)&2047]>>7);
403 x2 = dmulscale16(ox, xvect, -oy, yvect);
404 y2 = dmulscale16(oy, xvect, ox, yvect);
405
406 x3 = mulscale16(x2, yxaspect);
407 y3 = mulscale16(y2, yxaspect);
408
409 renderDrawLine(x1-x2+(xdim<<11), y1-y3+(ydim<<11),
410 x1+x2+(xdim<<11), y1+y3+(ydim<<11), col);
411 renderDrawLine(x1-y2+(xdim<<11), y1+x3+(ydim<<11),
412 x1+x2+(xdim<<11), y1+y3+(ydim<<11), col);
413 renderDrawLine(x1+y2+(xdim<<11), y1-x3+(ydim<<11),
414 x1+x2+(xdim<<11), y1+y3+(ydim<<11), col);
415 break;
416
417 case 16:
418 if (spr->picnum == LASERLINE)
419 {
420 x1 = sprx;
421 y1 = spry;
422 tilenum = spr->picnum;
423 xoff = picanm[tilenum].xofs + spr->xoffset;
424 if ((spr->cstat&4) > 0) xoff = -xoff;
425 k = spr->ang;
426 l = spr->xrepeat;
427 dax = sintable[k&2047]*l;
428 day = sintable[(k+1536)&2047]*l;
429 l = tilesiz[tilenum].x;
430 k = (l>>1)+xoff;
431 x1 -= mulscale16(dax, k);
432 x2 = x1+mulscale16(dax, l);
433 y1 -= mulscale16(day, k);
434 y2 = y1+mulscale16(day, l);
435
436 ox = x1-cposx;
437 oy = y1-cposy;
438 x1 = dmulscale16(ox, xvect, -oy, yvect);
439 y1 = dmulscale16(oy, xvect2, ox, yvect2);
440
441 ox = x2-cposx;
442 oy = y2-cposy;
443 x2 = dmulscale16(ox, xvect, -oy, yvect);
444 y2 = dmulscale16(oy, xvect2, ox, yvect2);
445
446 renderDrawLine(x1+(xdim<<11), y1+(ydim<<11),
447 x2+(xdim<<11), y2+(ydim<<11), col);
448 }
449
450 break;
451
452 case 32:
453 tilenum = spr->picnum;
454 xoff = picanm[tilenum].xofs + spr->xoffset;
455 yoff = picanm[tilenum].yofs + spr->yoffset;
456 if ((spr->cstat&4) > 0) xoff = -xoff;
457 if ((spr->cstat&8) > 0) yoff = -yoff;
458
459 k = spr->ang;
460 cosang = sintable[(k+512)&2047];
461 sinang = sintable[k&2047];
462 xspan = tilesiz[tilenum].x;
463 xrepeat = spr->xrepeat;
464 yspan = tilesiz[tilenum].y;
465 yrepeat = spr->yrepeat;
466
467 dax = ((xspan>>1)+xoff)*xrepeat;
468 day = ((yspan>>1)+yoff)*yrepeat;
469 x1 = sprx + dmulscale16(sinang, dax, cosang, day);
470 y1 = spry + dmulscale16(sinang, day, -cosang, dax);
471 l = xspan*xrepeat;
472 x2 = x1 - mulscale16(sinang, l);
473 y2 = y1 + mulscale16(cosang, l);
474 l = yspan*yrepeat;
475 k = -mulscale16(cosang, l);
476 x3 = x2+k;
477 x4 = x1+k;
478 k = -mulscale16(sinang, l);
479 y3 = y2+k;
480 y4 = y1+k;
481
482 ox = x1-cposx;
483 oy = y1-cposy;
484 x1 = dmulscale16(ox, xvect, -oy, yvect);
485 y1 = dmulscale16(oy, xvect2, ox, yvect2);
486
487 ox = x2-cposx;
488 oy = y2-cposy;
489 x2 = dmulscale16(ox, xvect, -oy, yvect);
490 y2 = dmulscale16(oy, xvect2, ox, yvect2);
491
492 ox = x3-cposx;
493 oy = y3-cposy;
494 x3 = dmulscale16(ox, xvect, -oy, yvect);
495 y3 = dmulscale16(oy, xvect2, ox, yvect2);
496
497 ox = x4-cposx;
498 oy = y4-cposy;
499 x4 = dmulscale16(ox, xvect, -oy, yvect);
500 y4 = dmulscale16(oy, xvect2, ox, yvect2);
501
502 renderDrawLine(x1+(xdim<<11), y1+(ydim<<11),
503 x2+(xdim<<11), y2+(ydim<<11), col);
504
505 renderDrawLine(x2+(xdim<<11), y2+(ydim<<11),
506 x3+(xdim<<11), y3+(ydim<<11), col);
507
508 renderDrawLine(x3+(xdim<<11), y3+(ydim<<11),
509 x4+(xdim<<11), y4+(ydim<<11), col);
510
511 renderDrawLine(x4+(xdim<<11), y4+(ydim<<11),
512 x1+(xdim<<11), y1+(ydim<<11), col);
513
514 break;
515 }
516 }
517 }
518
519 renderDisableFog();
520
521 //Draw white lines
522 for (i=numsectors-1; i>=0; i--)
523 {
524 if (!(show2dsector[i>>3]&(1<<(i&7)))) continue;
525
526 startwall = sector[i].wallptr;
527 endwall = sector[i].wallptr + sector[i].wallnum;
528
529 k = -1;
530 for (j=startwall, wal=(uwalltype *)&wall[startwall]; j<endwall; j++, wal++)
531 {
532 if (wal->nextwall >= 0) continue;
533
534 if (tilesiz[wal->picnum].x == 0) continue;
535 if (tilesiz[wal->picnum].y == 0) continue;
536
537 if (j == k)
538 {
539 x1 = x2;
540 y1 = y2;
541 }
542 else
543 {
544 ox = wal->x-cposx;
545 oy = wal->y-cposy;
546 x1 = dmulscale16(ox, xvect, -oy, yvect)+(xdim<<11);
547 y1 = dmulscale16(oy, xvect2, ox, yvect2)+(ydim<<11);
548 }
549
550 k = wal->point2;
551 wal2 = (uwalltype *)&wall[k];
552 ox = wal2->x-cposx;
553 oy = wal2->y-cposy;
554 x2 = dmulscale16(ox, xvect, -oy, yvect)+(xdim<<11);
555 y2 = dmulscale16(oy, xvect2, ox, yvect2)+(ydim<<11);
556
557 renderDrawLine(x1, y1, x2, y2, editorcolors[7]);
558 }
559 }
560
561 renderEnableFog();
562
563 videoSetCorrectedAspect();
564
565 for (TRAVERSE_CONNECT(p))
566 {
567 if (ud.scrollmode && p == screenpeek) continue;
568
569 DukePlayer_t const * const pPlayer = g_player[p].ps;
570 uspritetype const * const pSprite = (uspritetype const *)&sprite[pPlayer->i];
571
572 ox = pSprite->x - cposx;
573 oy = pSprite->y - cposy;
574 daang = (pSprite->ang - cang) & 2047;
575 if (p == screenpeek)
576 {
577 ox = 0;
578 oy = 0;
579 daang = 0;
580 }
581 x1 = mulscale16(ox, xvect) - mulscale16(oy, yvect);
582 y1 = mulscale16(oy, xvect2) + mulscale16(ox, yvect2);
583
584 if (p == screenpeek || GTFLAGS(GAMETYPE_OTHERPLAYERSINMAP))
585 {
586 if (REALITY)
587 {
588 if (pSprite->xvel > 16 && pPlayer->on_ground)
589 i = 1440-((((4-((int32_t) totalclock>>4)))&3)*5);
590 else
591 i = APLAYER;
592 }
593 else
594 {
595 if (pSprite->xvel > 16 && pPlayer->on_ground)
596 i = APLAYERTOP+(((int32_t) totalclock>>4)&3);
597 else
598 i = APLAYERTOP;
599 }
600
601 if (i < 0)
602 continue;
603
604 j = klabs(pPlayer->truefz - pPlayer->pos.z) >> 8;
605 j = mulscale16(czoom * (pSprite->yrepeat + j), yxaspect);
606
607 if (j < 22000) j = 22000;
608 else if (j > (65536<<1)) j = (65536<<1);
609
610 if (REALITY)
611 j >>= 1;
612
613 rotatesprite_win((x1<<4)+(xdim<<15), (y1<<4)+(ydim<<15), j, daang, i, pSprite->shade,
614 P_GetOverheadPal(pPlayer), 0);
615 }
616 }
617 }
618
619 #define printcoordsline(fmt, ...) do { \
620 Bsprintf(tempbuf, fmt, ## __VA_ARGS__); \
621 printext256(20, y+=9, COLOR_WHITE, -1, tempbuf, 0); \
622 } while (0)
623
624 #ifdef DEBUGGINGAIDS
625 sprstat_t g_spriteStat;
626 #endif
627
G_PrintCoords(int32_t snum)628 static void G_PrintCoords(int32_t snum)
629 {
630 const int32_t x = 250;
631 int32_t y = 16;
632
633 const DukePlayer_t *ps = g_player[snum].ps;
634 const int32_t sectnum = ps->cursectnum;
635
636 if ((g_gametypeFlags[ud.coop] & GAMETYPE_FRAGBAR))
637 {
638 if (ud.multimode > 4)
639 y = 32;
640 else if (g_netServer || ud.multimode > 1)
641 y = 24;
642 }
643 Bsprintf(tempbuf, "XYZ= (%d, %d, %d)", ps->pos.x, ps->pos.y, ps->pos.z);
644 printext256(x, y, COLOR_WHITE, -1, tempbuf, 0);
645 char ang[16], horiz[16], horizoff[16];
646 fix16_to_str(ps->q16ang, ang, 2);
647 fix16_to_str(ps->q16horiz, horiz, 2);
648 fix16_to_str(ps->q16horizoff, horizoff, 2);
649 Bsprintf(tempbuf, "A/H/HO= %s, %s, %s", ang, horiz, horizoff);
650 printext256(x, y+9, COLOR_WHITE, -1, tempbuf, 0);
651 Bsprintf(tempbuf, "VEL= (%d, %d, %d) + (%d, %d, 0)",
652 ps->vel.x>>14, ps->vel.y>>14, ps->vel.z, ps->fric.x>>5, ps->fric.y>>5);
653 printext256(x, y+18, COLOR_WHITE, -1, tempbuf, 0);
654 Bsprintf(tempbuf, "OG= %d SBRIDGE=%d SBS=%d", ps->on_ground, ps->spritebridge, ps->sbs);
655 printext256(x, y+27, COLOR_WHITE, -1, tempbuf, 0);
656 if (sectnum >= 0)
657 Bsprintf(tempbuf, "SECT= %d (LO=%d EX=%d)", sectnum,
658 TrackerCast(sector[sectnum].lotag), TrackerCast(sector[sectnum].extra));
659 else
660 Bsprintf(tempbuf, "SECT= %d", sectnum);
661 printext256(x, y+36, COLOR_WHITE, -1, tempbuf, 0);
662 // Bsprintf(tempbuf,"SEED= %d",randomseed);
663 // printext256(x,y+45,COLOR_WHITE,-1,tempbuf,0);
664 y -= 9;
665
666 y += 7;
667 Bsprintf(tempbuf, "THOLD= %d", ps->transporter_hold);
668 printext256(x, y+54, COLOR_WHITE, -1, tempbuf, 0);
669 Bsprintf(tempbuf, "GAMETIC= %u, TOTALCLOCK=%d", g_moveThingsCount, totalclock);
670 printext256(x, y+63, COLOR_WHITE, -1, tempbuf, 0);
671 #ifdef DEBUGGINGAIDS
672 Bsprintf(tempbuf, "NUMSPRITES= %d", Numsprites);
673 printext256(x, y+72, COLOR_WHITE, -1, tempbuf, 0);
674 if (g_moveThingsCount > g_spriteStat.lastgtic + REALGAMETICSPERSEC)
675 {
676 g_spriteStat.lastgtic = g_moveThingsCount;
677 g_spriteStat.lastnumins = g_spriteStat.numins;
678 g_spriteStat.numins = 0;
679 }
680 Bsprintf(tempbuf, "INSERTIONS/s= %u", g_spriteStat.lastnumins);
681 printext256(x, y+81, COLOR_WHITE, -1, tempbuf, 0);
682 Bsprintf(tempbuf, "ONSCREEN= %d", g_spriteStat.numonscreen);
683 printext256(x, y+90, COLOR_WHITE, -1, tempbuf, 0);
684 y += 3*9;
685 #endif
686 y += 7;
687 Bsprintf(tempbuf, "VR=%.03f YX=%.03f", (double) dr_viewingrange/65536.0, (double) dr_yxaspect/65536.0);
688 printext256(x, y+72, COLOR_WHITE, -1, tempbuf, 0);
689 Bsprintf(tempbuf, "MOVEACTORS [ms]= %.3e", g_moveActorsTime);
690 printext256(x, y+81, COLOR_WHITE, -1, tempbuf, 0);
691 Bsprintf(tempbuf, "MOVEWORLD [ms]= %.3e", g_moveWorldTime);
692 printext256(x, y+90, COLOR_WHITE, -1, tempbuf, 0);
693
694 #ifdef USE_OPENGL
695 if (ud.coords == 2)
696 {
697 y=16;
698
699 printcoordsline("rendmode = %d", videoGetRenderMode());
700 printcoordsline("r_ambientlight = %.03f", r_ambientlight);
701
702 if (rendmode >= 3)
703 {
704 if (rendmode==3)
705 printcoordsline("r_usenewshading = %d", r_usenewshading);
706 # ifdef POLYMER
707 else
708 printcoordsline("r_pr_artmapping = %d", pr_artmapping);
709 #endif
710 }
711 }
712 #endif
713 }
714
G_ShowCacheLocks(void)715 static void G_ShowCacheLocks(void)
716 {
717 if (offscreenrendering)
718 return;
719
720 int k = 0;
721
722 #if !defined DEBUG_ALLOCACHE_AS_MALLOC
723 auto indexes = g_cache.getIndex();
724
725 for (int i=g_cache.numBlocks()-1; i>=0; i--)
726 {
727 if ((*indexes[i].lock) != CACHE1D_LOCKED && (*indexes[i].lock) != 1)
728 {
729 if (k >= ydim-12)
730 break;
731
732 Bsprintf(tempbuf, "Locked- %d: Leng:%d, Lock:%d", i, indexes[i].leng, *indexes[i].lock);
733 printext256(0L, k, COLOR_WHITE, -1, tempbuf, 1);
734 k += 6;
735 }
736 }
737 #endif
738
739 if (k < ydim-12)
740 k += 6;
741
742 for (int i=10; i>=0; i--)
743 {
744 if (rts_lumplockbyte[i] >= CACHE1D_LOCKED)
745 {
746 if (k >= ydim-12)
747 break;
748
749 Bsprintf(tempbuf, "RTS Locked %d:", i);
750 printext256(0, k, COLOR_WHITE, -1, tempbuf, 1);
751 k += 6;
752 }
753 }
754
755 if (k >= ydim-12 && k<ydim-6)
756 printext256(0, k, COLOR_WHITE, -1, "(MORE . . .)", 1);
757
758 // sounds
759 if (xdim < 640)
760 return;
761
762 k = 0;
763
764 for (int i=0; i<=g_highestSoundIdx; i++)
765 {
766 if (g_sounds[i].num > 0)
767 {
768 for (int j = 0, n = g_sounds[i].num; j < n; j++)
769 {
770 if (k >= ydim-12)
771 return;
772
773 Bsprintf(tempbuf, "snd %d_%d: voice %d, ow %d", i, j, g_sounds[i].voices[j].id, g_sounds[i].voices[j].owner);
774 printext256(160, k, COLOR_WHITE, -1, tempbuf, 1);
775
776 k += 6;
777 }
778 }
779 }
780 }
781
782 #define LOW_FPS 30
783 #define SLOW_FRAME_TIME 33
784
785 #if defined GEKKO
786 # define FPS_YOFFSET 16
787 #else
788 # define FPS_YOFFSET 0
789 #endif
790
791 #define FPS_COLOR(x) ((x) ? COLOR_RED : COLOR_WHITE)
792
G_PrintFPS(void)793 static void G_PrintFPS(void)
794 {
795 static int32_t frameCount;
796 static double cumulativeFrameDelay;
797 static double lastFrameTime;
798 static float lastFPS, minFPS = FLT_MAX, maxFPS;
799 static double minGameUpdate = DBL_MAX, maxGameUpdate;
800
801 double frameTime = timerGetHiTicks();
802 double frameDelay = frameTime - lastFrameTime;
803 cumulativeFrameDelay += frameDelay;
804
805 if (frameDelay >= 0)
806 {
807 int32_t x = (xdim <= 640);
808
809 if (ud.showfps)
810 {
811 int32_t chars = Bsprintf(tempbuf, "%.1f ms, %5.1f fps", frameDelay, lastFPS);
812
813 printext256(windowxy2.x-(chars<<(3-x))+1, windowxy1.y+2+FPS_YOFFSET, 0, -1, tempbuf, x);
814 printext256(windowxy2.x-(chars<<(3-x)), windowxy1.y+1+FPS_YOFFSET,
815 FPS_COLOR(lastFPS < LOW_FPS), -1, tempbuf, x);
816
817 if (ud.showfps > 1)
818 {
819 chars = Bsprintf(tempbuf, "max: %5.1f fps", maxFPS);
820
821 printext256(windowxy2.x-(chars<<(3-x))+1, windowxy1.y+10+2+FPS_YOFFSET, 0, -1, tempbuf, x);
822 printext256(windowxy2.x-(chars<<(3-x)), windowxy1.y+10+FPS_YOFFSET,
823 FPS_COLOR(maxFPS < LOW_FPS), -1, tempbuf, x);
824
825 chars = Bsprintf(tempbuf, "min: %5.1f fps", minFPS);
826
827 printext256(windowxy2.x-(chars<<(3-x))+1, windowxy1.y+20+2+FPS_YOFFSET, 0, -1, tempbuf, x);
828 printext256(windowxy2.x-(chars<<(3-x)), windowxy1.y+20+FPS_YOFFSET,
829 FPS_COLOR(minFPS < LOW_FPS), -1, tempbuf, x);
830 }
831 if (ud.showfps > 2)
832 {
833 if (g_gameUpdateTime > maxGameUpdate) maxGameUpdate = g_gameUpdateTime;
834 if (g_gameUpdateTime < minGameUpdate) minGameUpdate = g_gameUpdateTime;
835
836 chars = Bsprintf(tempbuf, "Game Update: %2.2f ms + draw: %2.2f ms", g_gameUpdateTime, g_gameUpdateAndDrawTime);
837
838 printext256(windowxy2.x-(chars<<(3-x))+1, windowxy1.y+30+2+FPS_YOFFSET, 0, -1, tempbuf, x);
839 printext256(windowxy2.x-(chars<<(3-x)), windowxy1.y+30+FPS_YOFFSET,
840 FPS_COLOR(g_gameUpdateAndDrawTime >= SLOW_FRAME_TIME), -1, tempbuf, x);
841
842 chars = Bsprintf(tempbuf, "GU min/max/avg: %5.2f/%5.2f/%5.2f ms", minGameUpdate, maxGameUpdate, g_gameUpdateAvgTime);
843
844 printext256(windowxy2.x-(chars<<(3-x))+1, windowxy1.y+40+2+FPS_YOFFSET, 0, -1, tempbuf, x);
845 printext256(windowxy2.x-(chars<<(3-x)), windowxy1.y+40+FPS_YOFFSET,
846 FPS_COLOR(maxGameUpdate >= SLOW_FRAME_TIME), -1, tempbuf, x);
847
848 chars = Bsprintf(tempbuf, "G_MoveActors(): %.3e ms", g_moveActorsTime);
849
850 printext256(windowxy2.x-(chars<<(3-x))+1, windowxy1.y+50+2+FPS_YOFFSET, 0, -1, tempbuf, x);
851 printext256(windowxy2.x-(chars<<(3-x)), windowxy1.y+50+FPS_YOFFSET,
852 COLOR_WHITE, -1, tempbuf, x);
853
854 chars = Bsprintf(tempbuf, "G_MoveWorld(): %.3e ms", g_moveWorldTime);
855
856 printext256(windowxy2.x-(chars<<(3-x))+1, windowxy1.y+60+2+FPS_YOFFSET, 0, -1, tempbuf, x);
857 printext256(windowxy2.x-(chars<<(3-x)), windowxy1.y+60+FPS_YOFFSET,
858 COLOR_WHITE, -1, tempbuf, x);
859 }
860
861 // lag meter
862 if (g_netClientPeer)
863 {
864 chars = Bsprintf(tempbuf, "%d +- %d ms", (g_netClientPeer->lastRoundTripTime + g_netClientPeer->roundTripTime)/2,
865 (g_netClientPeer->lastRoundTripTimeVariance + g_netClientPeer->roundTripTimeVariance)/2);
866
867 printext256(windowxy2.x-(chars<<(3-x))+1, windowxy1.y+30+2+FPS_YOFFSET, 0, -1, tempbuf, x);
868 printext256(windowxy2.x-(chars<<(3-x)), windowxy1.y+30+1+FPS_YOFFSET, FPS_COLOR(g_netClientPeer->lastRoundTripTime > 200), -1, tempbuf, x);
869 }
870 }
871
872 if (cumulativeFrameDelay >= 1000.0)
873 {
874 lastFPS = 1000.f * frameCount / cumulativeFrameDelay;
875 g_frameRate = Blrintf(lastFPS);
876 frameCount = 0;
877 cumulativeFrameDelay = 0.0;
878
879 if (ud.showfps > 1)
880 {
881 if (lastFPS > maxFPS) maxFPS = lastFPS;
882 if (lastFPS < minFPS) minFPS = lastFPS;
883
884 static int secondCounter;
885
886 if (++secondCounter >= ud.frameperiod)
887 {
888 maxFPS = (lastFPS + maxFPS) * .5f;
889 minFPS = (lastFPS + minFPS) * .5f;
890 maxGameUpdate = (g_gameUpdateTime + maxGameUpdate) * 0.5;
891 minGameUpdate = (g_gameUpdateTime + minGameUpdate) * 0.5;
892 secondCounter = 0;
893 }
894 }
895 }
896 frameCount++;
897 }
898 lastFrameTime = frameTime;
899 }
900
901 #undef FPS_COLOR
902
G_DisplayRest(int32_t smoothratio)903 void G_DisplayRest(int32_t smoothratio)
904 {
905 int32_t i, j;
906 palaccum_t tint = PALACCUM_INITIALIZER;
907
908 DukePlayer_t *const pp = g_player[screenpeek].ps;
909 #ifdef SPLITSCREEN_MOD_HACKS
910 DukePlayer_t *const pp2 = g_fakeMultiMode==2 ? g_player[1].ps : NULL;
911 #endif
912 int32_t cposx, cposy, cang;
913
914 #ifdef USE_OPENGL
915 // this takes care of fullscreen tint for OpenGL
916 if (videoGetRenderMode() >= REND_POLYMOST)
917 {
918 polytint_t & fstint = hictinting[MAXPALOOKUPS-1];
919
920 if (pp->palette == WATERPAL)
921 {
922 fstint.r = 224;
923 fstint.g = 192;
924 fstint.b = 255;
925 fstint.f = 0;
926 }
927 else if (pp->palette == SLIMEPAL)
928 {
929 fstint.r = 208;
930 fstint.g = 255;
931 fstint.b = 192;
932 fstint.f = 0;
933 }
934 else
935 {
936 fstint.r = 255;
937 fstint.g = 255;
938 fstint.b = 255;
939 fstint.f = 0;
940 }
941 }
942 #endif // USE_OPENGL
943
944 if (!REALITY)
945 palaccum_add(&tint, &pp->pals, pp->pals.f);
946 #ifdef SPLITSCREEN_MOD_HACKS
947 if (pp2)
948 palaccum_add(&tint, &pp2->pals, pp2->pals.f);
949 #endif
950 if (!RR)
951 {
952 static const palette_t loogiepal = { 0, 63, 0, 0 };
953
954 palaccum_add(&tint, &loogiepal, pp->loogcnt>>1);
955 #ifdef SPLITSCREEN_MOD_HACKS
956 if (pp2)
957 palaccum_add(&tint, &loogiepal, pp2->loogcnt>>1);
958 #endif
959 }
960
961 if (g_restorePalette)
962 {
963 // reset a normal palette
964 static uint32_t omovethingscnt;
965
966 if (g_restorePalette < 2 || omovethingscnt+1 == g_moveThingsCount)
967 {
968 int32_t pal = pp->palette;
969 #ifdef SPLITSCREEN_MOD_HACKS
970 const int32_t opal = pal;
971
972 if (pp2) // splitscreen HACK: BASEPAL trumps all, then it's arbitrary.
973 pal = min(pal, pp2->palette);
974 #endif
975
976 // g_restorePalette < 0: reset tinting, too (e.g. when loading new game)
977 P_SetGamePalette(pp, pal, 2 + (g_restorePalette>0)*16);
978
979 #ifdef SPLITSCREEN_MOD_HACKS
980 if (pp2) // keep first player's pal as its member!
981 pp->palette = opal;
982 #endif
983
984 g_restorePalette = 0;
985 }
986 else
987 {
988 // delay setting the palette by one game tic
989 omovethingscnt = g_moveThingsCount;
990 }
991 }
992
993 if (ud.show_help)
994 {
995 switch (ud.show_help)
996 {
997 case 1:
998 rotatesprite_fs(160<<16, 100<<16, 65536L, 0, TEXTSTORY, 0, 0, 10+64);
999 break;
1000 case 2:
1001 rotatesprite_fs(160<<16, 100<<16, 65536L, 0, F1HELP, 0, 0, 10+64);
1002 break;
1003 case 3:
1004 if (RRRA)
1005 rotatesprite_fs(160<<16, 100<<16, 65536L, 0, RRTILE1636, 0, 0, 10+64);
1006 break;
1007 }
1008
1009 if (I_ReturnTrigger())
1010 {
1011 I_ReturnTriggerClear();
1012 ud.show_help = 0;
1013 if ((!g_netServer && ud.multimode < 2) && ud.recstat != 2)
1014 {
1015 ready2send = 1;
1016 totalclock = ototalclock;
1017 }
1018 G_UpdateScreenArea();
1019 }
1020
1021 return;
1022 }
1023
1024 i = pp->cursectnum;
1025 if (i > -1)
1026 {
1027 const walltype *wal = &wall[sector[i].wallptr];
1028
1029 show2dsector[i>>3] |= (1<<(i&7));
1030 for (j=sector[i].wallnum; j>0; j--, wal++)
1031 {
1032 i = wal->nextsector;
1033 if (i < 0) continue;
1034 if (wal->cstat&0x0071) continue;
1035 if (wall[wal->nextwall].cstat&0x0071) continue;
1036 if (sector[i].lotag == 32767) continue;
1037 if (sector[i].ceilingz >= sector[i].floorz) continue;
1038 show2dsector[i>>3] |= (1<<(i&7));
1039 }
1040 }
1041
1042 if (ud.camerasprite == -1)
1043 {
1044 if (ud.overhead_on != 2)
1045 {
1046 if (!RR && pp->newowner >= 0)
1047 G_DrawCameraText(pp->newowner);
1048 else
1049 {
1050 P_DisplayWeapon();
1051 #ifdef SPLITSCREEN_MOD_HACKS
1052 if (pp2) // HACK
1053 {
1054 const int32_t oscreenpeek = screenpeek;
1055 screenpeek = 1;
1056 P_DisplayWeapon();
1057 screenpeek = oscreenpeek;
1058 }
1059 #endif
1060
1061 if (pp->over_shoulder_on == 0)
1062 {
1063 if (REALITY)
1064 RT_P_DisplayScuba();
1065 else
1066 P_DisplayScuba();
1067 }
1068 #ifdef SPLITSCREEN_MOD_HACKS
1069 if (pp2 && pp2->over_shoulder_on == 0) // HACK
1070 {
1071 const int32_t oscreenpeek = screenpeek;
1072 screenpeek = 1;
1073 P_DisplayScuba();
1074 screenpeek = oscreenpeek;
1075 }
1076 #endif
1077 }
1078 if (!RR)
1079 G_MoveClouds();
1080 }
1081
1082 if (DEER)
1083 sub_57B38(pp->opos.x, pp->opos.y, 20, 1536);
1084
1085 if (ud.overhead_on > 0)
1086 {
1087 // smoothratio = min(max(smoothratio,0),65536);
1088 smoothratio = calc_smoothratio(totalclock, ototalclock);
1089 G_DoInterpolations(smoothratio);
1090
1091 if (ud.scrollmode == 0)
1092 {
1093 if (pp->newowner == -1 && !ud.pause_on)
1094 {
1095 if (screenpeek == myconnectindex && numplayers > 1)
1096 {
1097 cposx = omypos.x + mulscale16(mypos.x-omypos.x, smoothratio);
1098 cposy = omypos.y + mulscale16(mypos.y-omypos.y, smoothratio);
1099 cang = fix16_to_int(omyang) + mulscale16((fix16_to_int(myang+F16(1024)-omyang)&2047)-1024, smoothratio);
1100 }
1101 else
1102 {
1103 cposx = pp->opos.x + mulscale16(pp->pos.x-pp->opos.x, smoothratio);
1104 cposy = pp->opos.y + mulscale16(pp->pos.y-pp->opos.y, smoothratio);
1105 cang = fix16_to_int(pp->oq16ang) + mulscale16((fix16_to_int(pp->q16ang+F16(1024)-pp->oq16ang)&2047)-1024, smoothratio);
1106 }
1107 }
1108 else
1109 {
1110 cposx = pp->opos.x;
1111 cposy = pp->opos.y;
1112 cang = fix16_to_int(pp->oq16ang);
1113 }
1114 }
1115 else
1116 {
1117 #ifdef __ANDROID__
1118 CONTROL_Android_ScrollMap(&ud.fola, &ud.folx, &ud.foly, &pp->zoom);
1119 #else
1120 if (!ud.pause_on)
1121 {
1122 ud.fola += ud.folavel>>3;
1123 ud.folx += (ud.folfvel*sintable[(512+2048-ud.fola)&2047])>>14;
1124 ud.foly += (ud.folfvel*sintable[(512+1024-512-ud.fola)&2047])>>14;
1125 }
1126 #endif
1127 cposx = ud.folx;
1128 cposy = ud.foly;
1129 cang = ud.fola;
1130 }
1131
1132 if (ud.overhead_on == 2)
1133 {
1134 videoClearViewableArea(0L);
1135 renderDrawMapView(cposx, cposy, pp->zoom, cang);
1136 }
1137 G_DrawOverheadMap(cposx, cposy, pp->zoom, cang);
1138
1139 G_RestoreInterpolations();
1140
1141 if (ud.overhead_on == 2)
1142 {
1143 const int32_t a = RR ? 0 : ((ud.screen_size > 0) ? 147 : 179);
1144 if (RR && g_lastLevel)
1145 minitext(5, a+6, "CLOSE ENCOUNTERS", 0, 2+8+16+256);
1146 else
1147 {
1148 if (!REALITY && !G_HaveUserMap())
1149 minitext(5, a+6, g_volumeNames[ud.volume_number], 0, 2+8+16+256);
1150 minitext(5, a+6+6, g_mapInfo[ud.volume_number*MAXLEVELS + ud.level_number].name, 0, 2+8+16+256);
1151 }
1152 }
1153 }
1154 }
1155
1156 if (!REALITY && pp->invdisptime > 0) G_DrawInventory(pp);
1157
1158 G_DrawStatusBar(screenpeek);
1159
1160 #ifdef SPLITSCREEN_MOD_HACKS
1161 // HACK
1162 if (g_fakeMultiMode==2)
1163 {
1164 G_DrawStatusBar(1);
1165 G_PrintGameQuotes(1);
1166 }
1167 #endif
1168
1169 G_PrintGameQuotes(screenpeek);
1170
1171 if (ud.show_level_text && hud_showmapname && g_levelTextTime > 1)
1172 {
1173 int32_t o = 10|16;
1174
1175 if (g_levelTextTime < 3)
1176 o |= 1|32;
1177 else if (g_levelTextTime < 5)
1178 o |= 1;
1179
1180 if (g_mapInfo[(ud.volume_number*MAXLEVELS) + ud.level_number].name != NULL)
1181 {
1182 char const * const fn = currentboardfilename[0] != 0 &&
1183 ud.volume_number == 0 && ud.level_number == 7
1184 ? currentboardfilename
1185 : g_mapInfo[(ud.volume_number*MAXLEVELS) + ud.level_number].name;
1186
1187 if (REALITY)
1188 {
1189 RT_DisablePolymost(0);
1190 RT_RotateSpriteSetColor(255, 128, 128, clamp(g_levelTextTime * 8, 0, 256));
1191 menutext_(160<<16, (90+16+8)<<16, 0, fn, 0, TEXT_XCENTER|TEXT_N64NOPAL);
1192 RT_EnablePolymost();
1193 }
1194 else
1195 menutext_(160<<16, (90+16+8)<<16, -g_levelTextTime+22/*quotepulseshade*/, fn, o, TEXT_XCENTER);
1196 }
1197 }
1198
1199 if (I_EscapeTrigger() && ud.overhead_on == 0
1200 && ud.show_help == 0
1201 && g_player[myconnectindex].ps->newowner == -1)
1202 {
1203 if ((g_player[myconnectindex].ps->gm&MODE_MENU) == MODE_MENU && g_currentMenu <= MENU_MAIN_INGAME)
1204 {
1205 I_EscapeTriggerClear();
1206 S_PlaySound(REALITY ? 0xaa : EXITMENUSOUND);
1207 Menu_Change(MENU_CLOSE);
1208 if (!ud.pause_on)
1209 S_PauseSounds(false);
1210 }
1211 else if ((g_player[myconnectindex].ps->gm&MODE_MENU) != MODE_MENU &&
1212 g_player[myconnectindex].ps->newowner == -1 &&
1213 (g_player[myconnectindex].ps->gm&MODE_TYPE) != MODE_TYPE)
1214 {
1215 I_EscapeTriggerClear();
1216 S_PauseSounds(true);
1217
1218 Menu_Open(myconnectindex);
1219
1220 if ((!g_netServer && ud.multimode < 2) && ud.recstat != 2) ready2send = 0;
1221
1222 if (g_player[myconnectindex].ps->gm&MODE_GAME) Menu_Change(MENU_MAIN_INGAME);
1223 else Menu_Change(MENU_MAIN);
1224 screenpeek = myconnectindex;
1225
1226 S_MenuSound();
1227 }
1228 }
1229
1230 if (!DEER && g_player[myconnectindex].ps->newowner == -1 && ud.overhead_on == 0 && ud.crosshair && ud.camerasprite == -1)
1231 {
1232 int32_t a = CROSSHAIR;
1233 if ((unsigned) a < MAXTILES)
1234 {
1235 vec2_t crosshairpos = { (160<<16) - (g_player[myconnectindex].ps->look_ang<<15), 100<<16 };
1236 uint8_t crosshair_pal = CROSSHAIR_PAL;
1237 uint32_t crosshair_o = 1|2;
1238 uint32_t crosshair_scale = divscale16(ud.crosshairscale, 100);
1239 if (RR)
1240 crosshair_scale >>= 1;
1241
1242 rotatesprite_win(crosshairpos.x, crosshairpos.y, crosshair_scale, 0, a, 0, crosshair_pal, crosshair_o);
1243 }
1244 }
1245
1246 #ifdef GEKKO
1247 // like the mouse cursor, the pointer doesn't use the crosshair enabled / scale options
1248 if (g_player[myconnectindex].ps->newowner == -1 && ud.overhead_on == 0 && ud.camerasprite == -1 &&
1249 (g_player[myconnectindex].ps->gm&MODE_MENU) == 0 && mouseReadAbs((vec2_t *)&ud.returnvar[0], &g_mouseAbs))
1250 {
1251 int32_t a = VM_OnEventWithReturn(EVENT_DISPLAYPOINTER, g_player[screenpeek].ps->i, screenpeek, CROSSHAIR);
1252 if ((unsigned) a < MAXTILES)
1253 {
1254 vec2_t pointerpos = { tabledivide32(ud.returnvar[0], upscalefactor), tabledivide32(ud.returnvar[1], upscalefactor) };
1255 uint8_t pointer_pal = CROSSHAIR_PAL;
1256 uint32_t pointer_o = 1|2;
1257 uint32_t pointer_scale = 65536;
1258
1259 auto const oyxaspect = yxaspect;
1260
1261 rotatesprite_win(pointerpos.x, pointerpos.y, pointer_scale, 0, a, 0, pointer_pal, pointer_o);
1262 }
1263 }
1264 #endif
1265 #if 0
1266 if (g_gametypeFlags[ud.coop] & GAMETYPE_TDM)
1267 {
1268 for (i=0; i<ud.multimode; i++)
1269 {
1270 if (g_player[i].ps->team == g_player[myconnectindex].ps->team)
1271 {
1272 j = min(max((G_GetAngleDelta(getangle(g_player[i].ps->pos.x-g_player[myconnectindex].ps->pos.x,
1273 g_player[i].ps->pos.y-g_player[myconnectindex].ps->pos.y), g_player[myconnectindex].ps->ang))>>1, -160), 160);
1274 rotatesprite_win((160-j)<<16, 100L<<16, 65536L, 0, DUKEICON, 0, 0, 2+1);
1275 }
1276 }
1277 }
1278 #endif
1279
1280 if (ud.pause_on==1 && (g_player[myconnectindex].ps->gm&MODE_MENU) == 0)
1281 menutext_center(100, "Game Paused");
1282
1283 if (ud.coords)
1284 G_PrintCoords(screenpeek);
1285
1286 #ifdef YAX_DEBUG
1287 M32_drawdebug();
1288 #endif
1289
1290 #ifdef USE_OPENGL
1291 mdpause = (ud.pause_on || (ud.recstat==2 && (g_demo_paused && g_demo_goalCnt==0)) || (g_player[myconnectindex].ps->gm&MODE_MENU && numplayers < 2));
1292 #endif
1293
1294 G_PrintFPS();
1295
1296 // JBF 20040124: display level stats in screen corner
1297 if (ud.overhead_on != 2 && ud.levelstats)
1298 {
1299 DukePlayer_t const * const myps = g_player[myconnectindex].ps;
1300 int const sbarshift = RR ? 15 : 16;
1301 int const ystep = RR ? (10<<16) : (7<<16);
1302
1303 i = 198<<16;
1304
1305 if (ud.screen_size == 4)
1306 {
1307 if (ud.althud == 0 || ud.hudontop == 0)
1308 i -= sbarsc(ud.althud ? ((tilesiz[BIGALPHANUM].y<<sbarshift)+(8<<16)) : (REALITY ? 30 : tilesiz[INVENTORYBOX].y)<<sbarshift);
1309 }
1310 else if (RR && ud.screen_size == 12)
1311 {
1312 i -= sbarsc((tilesiz[BOTTOMSTATUSBAR].y+tilesiz[WEAPONBAR].y)<<sbarshift);
1313 }
1314 else if (ud.screen_size > 2)
1315 i -= sbarsc(tilesiz[BOTTOMSTATUSBAR].y<<sbarshift);
1316
1317 int32_t const xbetween = (tilesiz[MF_Bluefont.tilenum + 'A' - '!'].x<<16) + MF_Bluefont.between.x;
1318
1319 int32_t textflags = TEXT_XOFFSETZERO | TEXT_GAMETEXTNUMHACK;
1320
1321 if (REALITY)
1322 {
1323 RT_DisablePolymost(0);
1324 RT_RotateSpriteSetColor(255, 80, 0, 256);
1325 textflags |= TEXT_N64NOPAL;
1326 }
1327
1328 Bsprintf(tempbuf, "T:^15%d:%02d.%02d",
1329 (myps->player_par/(REALGAMETICSPERSEC*60)),
1330 (myps->player_par/REALGAMETICSPERSEC)%60,
1331 ((myps->player_par%REALGAMETICSPERSEC)*33)/10
1332 );
1333 G_ScreenText(MF_Bluefont.tilenum, 2<<16, i-gtextsc(ystep*(REALITY ? 4 : 3)), gtextsc(MF_Bluefont.zoom), 0, 0, tempbuf, 0, 10, 2|8|16|256|ROTATESPRITE_FULL16, 0, MF_Bluefont.emptychar.x, MF_Bluefont.emptychar.y, xbetween, MF_Bluefont.between.y, MF_Bluefont.textflags|textflags, 0, 0, xdim-1, ydim-1);
1334
1335 if ((!RR && ud.player_skill > 3) || ((g_netServer || ud.multimode > 1) && !GTFLAGS(GAMETYPE_PLAYERSFRIENDLY)))
1336 Bsprintf(tempbuf, "K:^15%d", (ud.multimode>1 &&!GTFLAGS(GAMETYPE_PLAYERSFRIENDLY)) ?
1337 myps->frag-myps->fraggedself : myps->actors_killed);
1338 else
1339 {
1340 if (myps->actors_killed >= myps->max_actors_killed)
1341 Bsprintf(tempbuf, "K:%d/%d", myps->actors_killed, myps->actors_killed);
1342 else
1343 Bsprintf(tempbuf, "K:^15%d/%d", myps->actors_killed, myps->max_actors_killed);
1344 }
1345 G_ScreenText(MF_Bluefont.tilenum, 2<<16, i-gtextsc(ystep*(REALITY ? 3 : 2)), gtextsc(MF_Bluefont.zoom), 0, 0, tempbuf, 0, 10, 2|8|16|256|ROTATESPRITE_FULL16, 0, MF_Bluefont.emptychar.x, MF_Bluefont.emptychar.y, xbetween, MF_Bluefont.between.y, MF_Bluefont.textflags|textflags, 0, 0, xdim-1, ydim-1);
1346
1347 if (myps->secret_rooms == myps->max_secret_rooms)
1348 Bsprintf(tempbuf, "S:%d/%d", myps->secret_rooms, myps->max_secret_rooms);
1349 else Bsprintf(tempbuf, "S:^15%d/%d", myps->secret_rooms, myps->max_secret_rooms);
1350 G_ScreenText(MF_Bluefont.tilenum, 2<<16, i-gtextsc(ystep), gtextsc(MF_Bluefont.zoom), 0, 0, tempbuf, 0, 10, 2|8|16|256|ROTATESPRITE_FULL16, 0, MF_Bluefont.emptychar.x, MF_Bluefont.emptychar.y, xbetween, MF_Bluefont.between.y, MF_Bluefont.textflags|textflags, 0, 0, xdim-1, ydim-1);
1351
1352
1353 if (REALITY)
1354 {
1355 Bsprintf(tempbuf, "B:%d/%d",
1356 myps->dn64_36e, myps->dn64_36d
1357 );
1358 G_ScreenText(MF_Bluefont.tilenum, 2<<16, i-gtextsc(ystep*2), gtextsc(MF_Bluefont.zoom), 0, 0, tempbuf, 0, 10, 2|8|16|256|ROTATESPRITE_FULL16, 0, MF_Bluefont.emptychar.x, MF_Bluefont.emptychar.y, xbetween, MF_Bluefont.between.y, MF_Bluefont.textflags|textflags, 0, 0, xdim-1, ydim-1);
1359
1360 RT_EnablePolymost();
1361 }
1362 }
1363
1364 if (g_player[myconnectindex].gotvote == 0 && voting != -1 && voting != myconnectindex)
1365 {
1366 Bsprintf(tempbuf, "%s^00 has called a vote for map", g_player[voting].user_name);
1367 gametext_center(40, tempbuf);
1368 Bsprintf(tempbuf, "%s (E%dL%d)", g_mapInfo[vote_episode*MAXLEVELS + vote_map].name, vote_episode+1, vote_map+1);
1369 gametext_center(48, tempbuf);
1370 gametext_center(70, "Press F1 to Accept, F2 to Decline");
1371 }
1372
1373 if (BUTTON(gamefunc_Show_DukeMatch_Scores))
1374 G_ShowScores();
1375
1376 if (g_Debug)
1377 G_ShowCacheLocks();
1378
1379 Net_DisplaySyncMsg();
1380
1381 #ifndef EDUKE32_TOUCH_DEVICES
1382 if (VOLUMEONE)
1383 {
1384 if (ud.show_help == 0 && g_showShareware > 0 && (g_player[myconnectindex].ps->gm&MODE_MENU) == 0)
1385 rotatesprite_fs((320-50)<<16, 9<<16, 65536L, 0, BETAVERSION, 0, 0, 2+8+16+128);
1386 }
1387 #endif
1388
1389 if (!Demo_IsProfiling())
1390 {
1391 if (g_player[myconnectindex].ps->gm&MODE_TYPE)
1392 Net_SendMessage();
1393 else
1394 M_DisplayMenus();
1395 }
1396
1397 {
1398 static int32_t applied = 0;
1399
1400 if (tint.maxf)
1401 {
1402 G_FadePalaccum(&tint);
1403 applied = 1;
1404 }
1405 else if (applied)
1406 {
1407 // be sure to always un-apply a tint.
1408 videoFadePalette(0, 0, 0, 0);
1409 applied = 0;
1410 }
1411 }
1412 }
1413
G_FadePalette(int32_t r,int32_t g,int32_t b,int32_t e)1414 void G_FadePalette(int32_t r, int32_t g, int32_t b, int32_t e)
1415 {
1416 if (ud.screenfade == 0)
1417 return;
1418 videoFadePalette(r, g, b, e);
1419 videoNextPage();
1420
1421 int32_t tc = (int32_t) totalclock;
1422 while (totalclock < tc + 4)
1423 G_HandleAsync();
1424 }
1425
1426 // START and END limits are always inclusive!
1427 // STEP must evenly divide END-START, i.e. abs(end-start)%step == 0
fadepal(int32_t r,int32_t g,int32_t b,int32_t start,int32_t end,int32_t step)1428 void fadepal(int32_t r, int32_t g, int32_t b, int32_t start, int32_t end, int32_t step)
1429 {
1430 if (ud.screenfade == 0)
1431 return;
1432 if (videoGetRenderMode() >= REND_POLYMOST)
1433 {
1434 G_FadePalette(r, g, b, end);
1435 return;
1436 }
1437
1438 // (end-start)/step + 1 iterations
1439 do
1440 {
1441 if (KB_KeyPressed(sc_Space))
1442 {
1443 KB_ClearKeyDown(sc_Space);
1444 videoFadePalette(r, g, b, end); // have to set to end fade value if we break!
1445 return;
1446 }
1447
1448 G_FadePalette(r, g, b, start);
1449
1450 start += step;
1451 } while (start != end+step);
1452 }
1453
1454 // START and END limits are always inclusive!
fadepaltile(int32_t r,int32_t g,int32_t b,int32_t start,int32_t end,int32_t step,int32_t tile)1455 static void fadepaltile(int32_t r, int32_t g, int32_t b, int32_t start, int32_t end, int32_t step, int32_t tile)
1456 {
1457 if (ud.screenfade == 0)
1458 return;
1459 // STEP must evenly divide END-START
1460 Bassert(klabs(end-start)%step == 0);
1461
1462 videoClearScreen(0);
1463
1464 // (end-start)/step + 1 iterations
1465 do
1466 {
1467 #ifdef __ANDROID__ //Needed for N7 2013 to stop corruption while fading video
1468 videoClearViewableArea(0);
1469 #endif
1470 if (KB_KeyPressed(sc_Space))
1471 {
1472 KB_ClearKeyDown(sc_Space);
1473 videoFadePalette(r, g, b, end); // have to set to end fade value if we break!
1474 return;
1475 }
1476 rotatesprite_fs(160<<16, 100<<16, 65536L, 0, tile, 0, 0, 2+8+64+BGSTRETCH);
1477 G_FadePalette(r, g, b, start);
1478
1479 start += step;
1480 } while (start != end+step);
1481 }
1482
1483 #ifdef __ANDROID__
1484 int inExtraScreens = 0;
1485 #endif
1486
G_DisplayExtraScreens(void)1487 void G_DisplayExtraScreens(void)
1488 {
1489 S_StopMusic();
1490 FX_StopAllSounds();
1491 if (RR)
1492 return;
1493
1494 if (!VOLUMEALL)
1495 {
1496 #ifdef __ANDROID__
1497 inExtraScreens = 1;
1498 #endif
1499 videoSetViewableArea(0, 0, xdim-1, ydim-1);
1500 renderFlushPerms();
1501 //g_player[myconnectindex].ps->palette = palette;
1502 P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 1); // JBF 20040308
1503 fadepal(0, 0, 0, 0, 252, 28);
1504 I_ClearAllInput();
1505 rotatesprite_fs(160<<16, 100<<16, 65536L, 0, 3291, 0, 0, 2+8+64+BGSTRETCH);
1506 fadepaltile(0, 0, 0, 252, 0, -28, 3291);
1507 while (!I_CheckAllInput())
1508 G_HandleAsync();
1509
1510 fadepaltile(0, 0, 0, 0, 252, 28, 3291);
1511 I_ClearAllInput();
1512 rotatesprite_fs(160<<16, 100<<16, 65536L, 0, 3290, 0, 0, 2+8+64+BGSTRETCH);
1513 fadepaltile(0, 0, 0, 252, 0, -28, 3290);
1514 while (!I_CheckAllInput())
1515 G_HandleAsync();
1516
1517 #ifdef __ANDROID__
1518 inExtraScreens = 0;
1519 #endif
1520 }
1521
1522 if (0)
1523 {
1524 #ifdef __ANDROID__
1525 inExtraScreens = 1;
1526 #endif
1527 videoSetViewableArea(0, 0, xdim-1, ydim-1);
1528 renderFlushPerms();
1529 //g_player[myconnectindex].ps->palette = palette;
1530 P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 1); // JBF 20040308
1531 fadepal(0, 0, 0, 0, 252, 28);
1532 I_ClearAllInput();
1533 totalclock = 0;
1534 rotatesprite_fs(160<<16, 100<<16, 65536L, 0, TENSCREEN, 0, 0, 2+8+64+BGSTRETCH);
1535 fadepaltile(0, 0, 0, 252, 0, -28, TENSCREEN);
1536 while (!I_CheckAllInput() && totalclock < 2400)
1537 G_HandleAsync();
1538
1539 fadepaltile(0, 0, 0, 0, 252, 28, TENSCREEN);
1540 I_ClearAllInput();
1541 #ifdef __ANDROID__
1542 inExtraScreens = 0;
1543 #endif
1544 }
1545 }
1546
G_DisplayLogo(void)1547 void G_DisplayLogo(void)
1548 {
1549 int32_t soundanm = 0;
1550 //int32_t logoflags = G_GetLogoFlags();
1551
1552 ready2send = 0;
1553
1554 I_ClearAllInput();
1555
1556 videoSetViewableArea(0, 0, xdim-1, ydim-1);
1557 videoClearScreen(0L);
1558 G_FadePalette(0, 0, 0, 252);
1559
1560 renderFlushPerms();
1561 videoNextPage();
1562
1563 G_UpdateAppTitle();
1564
1565 S_StopMusic();
1566 FX_StopAllSounds(); // JBF 20031228
1567 S_ClearSoundLocks(); // JBF 20031228
1568 if (DEER)
1569 {
1570 if (!g_noLogo /* && (!g_netServer && ud.multimode < 2) */)
1571 {
1572 if (!I_CheckAllInput() && g_noLogoAnim == 0)
1573 {
1574 videoClearScreen(0);
1575
1576 P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8 + 2 + 1); // JBF 20040308
1577 fadepal(0, 0, 0, 0, 252, 28);
1578 renderFlushPerms();
1579 rotatesprite_fs(160 << 16, 100 << 16, 65536L, 0, 7106, 0, 0, 2 + 8 + 64 + BGSTRETCH);
1580 videoNextPage();
1581 fadepaltile(0, 0, 0, 252, 0, -4, 7106);
1582 totalclock = 0;
1583
1584 while (totalclock < (120 * 3) && !I_CheckAllInput())
1585 {
1586 if (engineFPSLimit())
1587 {
1588 videoClearScreen(0);
1589 rotatesprite_fs(160 << 16, 100 << 16, 65536L, 0, 7106, 0, 0, 2 + 8 + 64 + BGSTRETCH);
1590 G_HandleAsync();
1591
1592 if (g_restorePalette)
1593 {
1594 P_SetGamePalette(g_player[myconnectindex].ps, g_player[myconnectindex].ps->palette, 0);
1595 g_restorePalette = 0;
1596 }
1597 videoNextPage();
1598 }
1599 }
1600
1601 fadepaltile(0, 0, 0, 0, 252, 4, 7106);
1602 }
1603
1604 videoClearScreen(0L);
1605 videoNextPage();
1606
1607 I_ClearAllInput();
1608
1609 videoClearScreen(0L);
1610 videoNextPage();
1611
1612 videoClearScreen(0);
1613
1614 //g_player[myconnectindex].ps->palette = drealms;
1615 //G_FadePalette(0,0,0,252);
1616
1617 if (!I_CheckAllInput() && g_noLogoAnim == 0)
1618 {
1619 videoClearScreen(0);
1620
1621 P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8 + 2 + 1); // JBF 20040308
1622 fadepal(0, 0, 0, 0, 252, 28);
1623 renderFlushPerms();
1624 rotatesprite_fs(160 << 16, 100 << 16, 65536L, 0, 7107, 0, 0, 2 + 8 + 64 + BGSTRETCH);
1625 videoNextPage();
1626 fadepaltile(0, 0, 0, 252, 0, -4, 7107);
1627 totalclock = 0;
1628
1629 while (totalclock < (120 * 3) && !I_CheckAllInput())
1630 {
1631 if (engineFPSLimit())
1632 {
1633 videoClearScreen(0);
1634 rotatesprite_fs(160 << 16, 100 << 16, 65536L, 0, 7107, 0, 0, 2 + 8 + 64 + BGSTRETCH);
1635 G_HandleAsync();
1636
1637 if (g_restorePalette)
1638 {
1639 P_SetGamePalette(g_player[myconnectindex].ps, g_player[myconnectindex].ps->palette, 0);
1640 g_restorePalette = 0;
1641 }
1642 videoNextPage();
1643 }
1644 }
1645
1646 fadepaltile(0, 0, 0, 0, 252, 4, 7107);
1647 }
1648
1649 I_ClearAllInput();
1650 }
1651
1652 renderFlushPerms();
1653 videoClearScreen(0L);
1654 videoNextPage();
1655
1656 //g_player[myconnectindex].ps->palette = palette;
1657 P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 0); // JBF 20040308
1658
1659 //G_FadePalette(0,0,0,0);
1660 videoClearScreen(0L);
1661
1662 g_noLogo = 1; // Play intro only once
1663 return;
1664 }
1665 if (RRRA)
1666 return;
1667 if (RR)
1668 {
1669 if (!I_CheckAllInput() && g_noLogoAnim == 0)
1670 {
1671 Net_GetPackets();
1672 Anim_Play("rr_intro.anm");
1673 G_FadePalette(0, 0, 0, 252);
1674 I_ClearAllInput();
1675 }
1676
1677 videoClearScreen(0L);
1678 videoNextPage();
1679 FX_StopAllSounds();
1680 S_ClearSoundLocks();
1681
1682 if (!I_CheckAllInput() && g_noLogoAnim == 0)
1683 {
1684 Net_GetPackets();
1685 Anim_Play("redneck.anm");
1686 G_FadePalette(0, 0, 0, 252);
1687 I_ClearAllInput();
1688 }
1689
1690 videoClearScreen(0L);
1691 videoNextPage();
1692 FX_StopAllSounds();
1693 S_ClearSoundLocks();
1694
1695 if (!I_CheckAllInput() && g_noLogoAnim == 0)
1696 {
1697 Net_GetPackets();
1698 Anim_Play("xatlogo.anm");
1699 G_FadePalette(0, 0, 0, 252);
1700 I_ClearAllInput();
1701 }
1702
1703 videoClearScreen(0L);
1704 videoNextPage();
1705 FX_StopAllSounds();
1706 S_ClearSoundLocks();
1707
1708 //g_player[myconnectindex].ps->palette = palette;
1709 P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 0); // JBF 20040308
1710 S_PlaySound(NITEVISION_ONOFF);
1711
1712 //G_FadePalette(0,0,0,0);
1713 videoClearScreen(0L);
1714 return;
1715 }
1716 if (REALITY)
1717 {
1718 G_FadePalette(0, 0, 0, 0);
1719 totalclock = 0;
1720
1721 while ((int)totalclock < (4 * (16 + 120 + 16)) && !I_CheckAllInput())
1722 {
1723 if (engineFPSLimit())
1724 {
1725 int alpha = 0;
1726 if (totalclock < (4 * 16))
1727 alpha = clamp((int)totalclock * 4, 0, 256);
1728 else if (totalclock < (4 * (16 + 120)))
1729 alpha = 256;
1730 else
1731 alpha = clamp(256 - ((int)totalclock - (4 * (16 + 120))) * 4, 0, 256);
1732
1733
1734 videoClearScreen(0);
1735
1736 RT_DisablePolymost(0);
1737 RT_RotateSpriteSetColor(255, 255, 255, alpha);
1738
1739 RT_RotateSprite(160, 60, 100, 100, 0xe09, 0);
1740 RT_RotateSprite(100, 160, 100, 100, 0xe5d, 0);
1741 RT_RotateSprite(220, 160, 100, 100, 0xe5e, 0);
1742 RT_EnablePolymost();
1743
1744 G_HandleAsync();
1745 videoNextPage();
1746 }
1747 }
1748
1749 I_ClearAllInput();
1750
1751 S_PlaySpecialMusicOrNothing(MUS_INTRO);
1752
1753 renderFlushPerms();
1754 videoClearScreen(0L);
1755 videoNextPage();
1756
1757 //g_player[myconnectindex].ps->palette = palette;
1758 P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 0); // JBF 20040308
1759
1760 //G_FadePalette(0,0,0,0);
1761 videoClearScreen(0L);
1762 return;
1763 }
1764 if (!g_noLogo /* && (!g_netServer && ud.multimode < 2) */)
1765 {
1766 #ifndef EDUKE32_TOUCH_DEVICES
1767 if (VOLUMEALL)
1768 #endif
1769 {
1770 if (!I_CheckAllInput() && g_noLogoAnim == 0)
1771 {
1772 Net_GetPackets();
1773 Anim_Play("logo.anm");
1774 G_FadePalette(0, 0, 0, 252);
1775 I_ClearAllInput();
1776 }
1777
1778 videoClearScreen(0L);
1779 videoNextPage();
1780 FX_StopAllSounds();
1781 S_ClearSoundLocks();
1782 }
1783
1784 S_PlaySpecialMusicOrNothing(MUS_INTRO);
1785
1786 //g_player[myconnectindex].ps->palette = drealms;
1787 //G_FadePalette(0,0,0,252);
1788
1789 if (!I_CheckAllInput() && g_noLogoAnim == 0)
1790 {
1791 int32_t i;
1792 Net_GetPackets();
1793
1794 i = kopen4loadfrommod("3dr.ivf", 0);
1795
1796 if (i == -1)
1797 i = kopen4loadfrommod("3dr.anm", 0);
1798
1799 if (i != -1)
1800 {
1801 kclose(i);
1802 Anim_Play("3dr.anm");
1803 G_FadePalette(0, 0, 0, 252);
1804 I_ClearAllInput();
1805 }
1806 else
1807 {
1808 videoClearScreen(0);
1809
1810 P_SetGamePalette(g_player[myconnectindex].ps, DREALMSPAL, 8 + 2 + 1); // JBF 20040308
1811 fadepal(0, 0, 0, 0, 252, 28);
1812 renderFlushPerms();
1813 rotatesprite_fs(160 << 16, 100 << 16, 65536L, 0, DREALMS, 0, 0, 2 + 8 + 64 + BGSTRETCH);
1814 videoNextPage();
1815 fadepaltile(0, 0, 0, 252, 0, -28, DREALMS);
1816 totalclock = 0;
1817
1818 while (totalclock < (120 * 7) && !I_CheckAllInput())
1819 {
1820 if (engineFPSLimit())
1821 {
1822 videoClearScreen(0);
1823 rotatesprite_fs(160 << 16, 100 << 16, 65536L, 0, DREALMS, 0, 0, 2 + 8 + 64 + BGSTRETCH);
1824 G_HandleAsync();
1825
1826 if (g_restorePalette)
1827 {
1828 P_SetGamePalette(g_player[myconnectindex].ps, g_player[myconnectindex].ps->palette, 0);
1829 g_restorePalette = 0;
1830 }
1831 videoNextPage();
1832 }
1833 }
1834
1835 fadepaltile(0, 0, 0, 0, 252, 28, DREALMS);
1836 }
1837 }
1838
1839 videoClearScreen(0L);
1840 videoNextPage();
1841
1842 I_ClearAllInput();
1843
1844 videoClearScreen(0L);
1845 videoNextPage();
1846
1847 videoClearScreen(0);
1848
1849 //g_player[myconnectindex].ps->palette = titlepal;
1850 P_SetGamePalette(g_player[myconnectindex].ps, TITLEPAL, 8+2+1); // JBF 20040308
1851 renderFlushPerms();
1852 rotatesprite_fs(160<<16, 100<<16, 65536L, 0, BETASCREEN, 0, 0, 2+8+64+BGSTRETCH);
1853 KB_FlushKeyboardQueue();
1854 fadepaltile(0, 0, 0, 252, 0, -28, BETASCREEN);
1855 totalclock = 0;
1856
1857 while (
1858 #ifndef EDUKE32_SIMPLE_MENU
1859 totalclock < (860+120) &&
1860 #endif
1861 !I_CheckAllInput())
1862 {
1863 if (engineFPSLimit())
1864 {
1865 videoClearScreen(0);
1866 rotatesprite_fs(160<<16, 100<<16, 65536L, 0, BETASCREEN, 0, 0, 2+8+64+BGSTRETCH);
1867
1868 if (totalclock > 120 && totalclock < (120+60))
1869 {
1870 if (soundanm == 0)
1871 {
1872 soundanm++;
1873 S_PlaySound(PIPEBOMB_EXPLODE);
1874 }
1875 rotatesprite_fs(160<<16, 104<<16, ((int32_t) totalclock-120)<<10, 0, DUKENUKEM, 0, 0, 2+8);
1876 }
1877 else if (totalclock >= (120+60))
1878 rotatesprite_fs(160<<16, (104)<<16, 60<<10, 0, DUKENUKEM, 0, 0, 2+8);
1879
1880 if (totalclock > 220 && totalclock < (220+30))
1881 {
1882 if (soundanm == 1)
1883 {
1884 soundanm++;
1885 S_PlaySound(PIPEBOMB_EXPLODE);
1886 }
1887
1888 rotatesprite_fs(160<<16, (104)<<16, 60<<10, 0, DUKENUKEM, 0, 0, 2+8);
1889 rotatesprite_fs(160<<16, (129)<<16, ((int32_t) totalclock - 220)<<11, 0, THREEDEE, 0, 0, 2+8);
1890 }
1891 else if (totalclock >= (220+30))
1892 rotatesprite_fs(160<<16, (129)<<16, 30<<11, 0, THREEDEE, 0, 0, 2+8);
1893
1894 if (PLUTOPAK)
1895 {
1896 // JBF 20030804
1897 if (totalclock >= 280 && totalclock < 395)
1898 {
1899 rotatesprite_fs(160<<16, (151)<<16, (410-(int32_t) totalclock)<<12, 0, PLUTOPAKSPRITE+1, (sintable[((int32_t) totalclock<<4)&2047]>>11), 0, 2+8);
1900 if (soundanm == 2)
1901 {
1902 soundanm++;
1903 S_PlaySound(FLY_BY);
1904 }
1905 }
1906 else if (totalclock >= 395)
1907 {
1908 if (soundanm == 3)
1909 {
1910 soundanm++;
1911 S_PlaySound(PIPEBOMB_EXPLODE);
1912 }
1913 rotatesprite_fs(160<<16, (151)<<16, 30<<11, 0, PLUTOPAKSPRITE+1, (sintable[((int32_t) totalclock<<4)&2047]>>11), 0, 2+8);
1914 }
1915 }
1916
1917 if (g_restorePalette)
1918 {
1919 P_SetGamePalette(g_player[myconnectindex].ps, g_player[myconnectindex].ps->palette, 0);
1920 g_restorePalette = 0;
1921 }
1922
1923 videoNextPage();
1924 }
1925
1926 G_HandleAsync();
1927 }
1928
1929 I_ClearAllInput();
1930 }
1931
1932 renderFlushPerms();
1933 videoClearScreen(0L);
1934 videoNextPage();
1935
1936 //g_player[myconnectindex].ps->palette = palette;
1937 P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 0); // JBF 20040308
1938 S_PlaySound(NITEVISION_ONOFF);
1939
1940 //G_FadePalette(0,0,0,0);
1941 videoClearScreen(0L);
1942 }
1943
G_DoOrderScreen(void)1944 void G_DoOrderScreen(void)
1945 {
1946 int32_t i;
1947
1948 videoSetViewableArea(0, 0, xdim-1, ydim-1);
1949
1950 P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 1); // JBF 20040308
1951
1952 for (i=0; i<4; i++)
1953 {
1954 fadepal(0, 0, 0, 0, 252, 28);
1955 I_ClearAllInput();
1956 rotatesprite_fs(160<<16, 100<<16, 65536L, 0, ORDERING+i, 0, 0, 2+8+64+BGSTRETCH);
1957 fadepal(0, 0, 0, 252, 0, -28);
1958 while (!I_CheckAllInput())
1959 G_HandleAsync();
1960 }
1961
1962 I_ClearAllInput();
1963 }
1964
1965
G_BonusCutscenes(void)1966 static void G_BonusCutscenes(void)
1967 {
1968 if (RRRA)
1969 return;
1970 if (!(numplayers < 2 && ud.eog && ud.from_bonus == 0))
1971 return;
1972
1973 if (RR)
1974 {
1975 switch (ud.volume_number)
1976 {
1977 case 0:
1978 videoClearScreen(0L);
1979 videoNextPage();
1980 if (ud.lockout == 0)
1981 {
1982 Anim_Play("turdmov.anm");
1983 I_ClearAllInput();
1984 videoClearScreen(0L);
1985 videoNextPage();
1986 }
1987 ud.level_number = 0;
1988 ud.volume_number = 1;
1989 ud.eog = 0;
1990 fadepal(0, 0, 0, 0, 252, 4);
1991 I_ClearAllInput();
1992 P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8+2+1);
1993 rotatesprite_fs(0, 0, 65536L, 0, TENSCREEN, 0, 0, 2+8+16+64+128+BGSTRETCH);
1994 videoNextPage();
1995 fadepal(0, 0, 0, 252, 0, -4);
1996 I_ClearAllInput();
1997 G_HandleEventsWhileNoInput();
1998 fadepal(0, 0, 0, 0, 252, 4);
1999 FX_StopAllSounds();
2000 S_ClearSoundLocks();
2001 break;
2002 case 1:
2003 videoClearScreen(0L);
2004 videoNextPage();
2005 if (ud.lockout == 0)
2006 {
2007 Anim_Play("rr_outro.anm");
2008 I_ClearAllInput();
2009 videoClearScreen(0L);
2010 videoNextPage();
2011 }
2012 g_lastLevel = 0;
2013 g_vixenLevel = 1;
2014 ud.level_number = 0;
2015 ud.volume_number = 0;
2016 fadepal(0, 0, 0, 0, 252, 4);
2017 videoSetViewableArea(0, 0, xdim-1, ydim-1);
2018 I_ClearAllInput();
2019 P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8 + 2 + 1);
2020 rotatesprite_fs(0, 0, 65536L, 0, TENSCREEN, 0, 0, 2 + 8 + 16 + 64 + 128 + BGSTRETCH);
2021 videoNextPage();
2022 fadepal(0, 0, 0, 252, 0, -4);
2023 I_ClearAllInput();
2024 G_HandleEventsWhileNoInput();
2025 fadepal(0, 0, 0, 0, 252, 4);
2026 FX_StopAllSounds();
2027 S_ClearSoundLocks();
2028 break;
2029 }
2030 return;
2031 }
2032
2033 switch (ud.volume_number)
2034 {
2035 case 0:
2036 if (ud.lockout == 0)
2037 {
2038 int32_t bonuscnt=0;
2039 int32_t const bossmove [] =
2040 {
2041 0, 120, VICTORY1+3, 86, 59,
2042 220, 260, VICTORY1+4, 86, 59,
2043 260, 290, VICTORY1+5, 86, 59,
2044 290, 320, VICTORY1+6, 86, 59,
2045 320, 350, VICTORY1+7, 86, 59,
2046 350, 380, VICTORY1+8, 86, 59,
2047 350, 380, VICTORY1+8, 86, 59 // duplicate row to alleviate overflow in the for loop below "boss"
2048 };
2049
2050 P_SetGamePalette(g_player[myconnectindex].ps, ENDINGPAL, 8+2+1); // JBF 20040308
2051 videoClearScreen(0L);
2052 rotatesprite_fs(0, 50<<16, 65536L, 0, VICTORY1, 0, 0, 2+8+16+64+128+BGSTRETCH);
2053 videoNextPage();
2054 fadepal(0, 0, 0, 252, 0, -4);
2055
2056 I_ClearAllInput();
2057 totalclock = 0;
2058
2059 while (1)
2060 {
2061 if (engineFPSLimit())
2062 {
2063 videoClearScreen(0L);
2064 rotatesprite_fs(0, 50<<16, 65536L, 0, VICTORY1, 0, 0, 2+8+16+64+128+BGSTRETCH);
2065
2066 // boss
2067 if (totalclock > 390 && totalclock < 780)
2068 for (bssize_t t=0; t<35; t+=5) if (bossmove[t+2] && (totalclock%390) > bossmove[t] && (totalclock%390) <= bossmove[t+1])
2069 {
2070 if (t==10 && bonuscnt == 1)
2071 {
2072 S_PlaySound(SHOTGUN_FIRE);
2073 S_PlaySound(SQUISHED);
2074 bonuscnt++;
2075 }
2076 rotatesprite_fs(bossmove[t+3]<<16, bossmove[t+4]<<16, 65536L, 0, bossmove[t+2], 0, 0, 2+8+16+64+128+BGSTRETCH);
2077 }
2078
2079 // Breathe
2080 if (totalclock < 450 || totalclock >= 750)
2081 {
2082 int32_t const breathe [] =
2083 {
2084 0, 30, VICTORY1+1, 176, 59,
2085 30, 60, VICTORY1+2, 176, 59,
2086 60, 90, VICTORY1+1, 176, 59,
2087 90, 120, 0, 176, 59
2088 };
2089
2090 if (totalclock >= 750)
2091 {
2092 rotatesprite_fs(86<<16, 59<<16, 65536L, 0, VICTORY1+8, 0, 0, 2+8+16+64+128+BGSTRETCH);
2093 if (totalclock >= 750 && bonuscnt == 2)
2094 {
2095 S_PlaySound(DUKETALKTOBOSS);
2096 bonuscnt++;
2097 }
2098
2099 }
2100 for (bssize_t t=0; t<20; t+=5)
2101 if (breathe[t+2] && (totalclock%120) > breathe[t] && (totalclock%120) <= breathe[t+1])
2102 {
2103 if (t==5 && bonuscnt == 0)
2104 {
2105 S_PlaySound(BOSSTALKTODUKE);
2106 bonuscnt++;
2107 }
2108 rotatesprite_fs(breathe[t+3]<<16, breathe[t+4]<<16, 65536L, 0, breathe[t+2], 0, 0, 2+8+16+64+128+BGSTRETCH);
2109 }
2110 }
2111
2112 videoNextPage();
2113 }
2114
2115 G_HandleAsync();
2116
2117 if (I_CheckAllInput()) break;
2118 }
2119
2120 fadepal(0, 0, 0, 0, 252, 4);
2121 }
2122
2123 I_ClearAllInput();
2124 P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8+2+1); // JBF 20040308
2125
2126 rotatesprite_fs(160<<16, 100<<16, 65536L, 0, 3292, 0, 0, 2+8+64+BGSTRETCH);
2127 fadepal(0, 0, 0, 252, 0, -4);
2128 G_HandleEventsWhileNoInput();
2129 fadepal(0, 0, 0, 0, 252, 4);
2130
2131 S_StopMusic();
2132 FX_StopAllSounds();
2133 S_ClearSoundLocks();
2134 break;
2135
2136 case 1:
2137 videoSetViewableArea(0, 0, xdim-1, ydim-1);
2138
2139 S_StopMusic();
2140 videoClearScreen(0L);
2141 videoNextPage();
2142
2143 if (ud.lockout == 0)
2144 {
2145 fadepal(0, 0, 0, 252, 0, -4);
2146 Anim_Play("cineov2.anm");
2147 I_ClearAllInput();
2148 videoClearScreen(0L);
2149 videoNextPage();
2150
2151 S_PlaySound(PIPEBOMB_EXPLODE);
2152 fadepal(0, 0, 0, 0, 252, 4);
2153 }
2154
2155 I_ClearAllInput();
2156 P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8+2+1); // JBF 20040308
2157 rotatesprite_fs(160<<16, 100<<16, 65536L, 0, 3293, 0, 0, 2+8+64+BGSTRETCH);
2158 fadepal(0, 0, 0, 252, 0, -4);
2159 G_HandleEventsWhileNoInput();
2160 fadepal(0, 0, 0, 0, 252, 4);
2161
2162 break;
2163
2164 case 3:
2165 videoSetViewableArea(0, 0, xdim-1, ydim-1);
2166
2167 S_StopMusic();
2168 videoClearScreen(0L);
2169 videoNextPage();
2170
2171 if (ud.lockout == 0)
2172 {
2173 fadepal(0, 0, 0, 252, 0, -4);
2174
2175 I_ClearAllInput();
2176 int t = Anim_Play("vol4e1.anm");
2177 videoClearScreen(0L);
2178 videoNextPage();
2179 if (t)
2180 goto end_vol4e;
2181
2182 t = Anim_Play("vol4e2.anm");
2183 videoClearScreen(0L);
2184 videoNextPage();
2185 if (t)
2186 goto end_vol4e;
2187
2188 Anim_Play("vol4e3.anm");
2189 videoClearScreen(0L);
2190 videoNextPage();
2191 }
2192
2193 end_vol4e:
2194 FX_StopAllSounds();
2195 S_ClearSoundLocks();
2196 S_PlaySound(ENDSEQVOL3SND4);
2197 I_ClearAllInput();
2198
2199 G_FadePalette(0, 0, 0, 0);
2200 P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8+2+1); // JBF 20040308
2201 // G_FadePalette(0,0,0,252);
2202 videoClearScreen(0L);
2203 menutext_center(60, "Thanks to all our");
2204 menutext_center(60+16, "fans for giving");
2205 menutext_center(60+16+16, "us big heads.");
2206 menutext_center(70+16+16+16, "Look for a Duke Nukem 3D");
2207 menutext_center(70+16+16+16+16, "sequel soon.");
2208 videoNextPage();
2209
2210 fadepal(0, 0, 0, 252, 0, -12);
2211 videoNextPage();
2212 I_ClearAllInput();
2213 G_HandleEventsWhileNoInput();
2214 fadepal(0, 0, 0, 0, 252, 12);
2215
2216 videoClearScreen(0L);
2217 videoNextPage();
2218
2219 Anim_Play("DUKETEAM.ANM");
2220
2221 I_ClearAllInput();
2222 G_HandleEventsWhileNoInput();
2223
2224 videoClearScreen(0L);
2225 videoNextPage();
2226 G_FadePalette(0, 0, 0, 252);
2227
2228 FX_StopAllSounds();
2229 S_ClearSoundLocks();
2230 I_ClearAllInput();
2231
2232 break;
2233
2234 case 2:
2235 S_StopMusic();
2236 videoClearScreen(0L);
2237 videoNextPage();
2238 if (ud.lockout == 0)
2239 {
2240 fadepal(0, 0, 0, 252, 0, -4);
2241 Anim_Play("cineov3.anm");
2242 I_ClearAllInput();
2243 ototalclock = totalclock+200;
2244 while (totalclock < ototalclock)
2245 G_HandleAsync();
2246 videoClearScreen(0L);
2247 videoNextPage();
2248
2249 FX_StopAllSounds();
2250 S_ClearSoundLocks();
2251 }
2252
2253 Anim_Play("RADLOGO.ANM");
2254
2255 if (ud.lockout == 0 && !I_CheckAllInput())
2256 {
2257 if (G_PlaySoundWhileNoInput(ENDSEQVOL3SND5)) goto ENDANM;
2258 if (G_PlaySoundWhileNoInput(ENDSEQVOL3SND6)) goto ENDANM;
2259 if (G_PlaySoundWhileNoInput(ENDSEQVOL3SND7)) goto ENDANM;
2260 if (G_PlaySoundWhileNoInput(ENDSEQVOL3SND8)) goto ENDANM;
2261 if (G_PlaySoundWhileNoInput(ENDSEQVOL3SND9)) goto ENDANM;
2262 }
2263
2264 I_ClearAllInput();
2265
2266 totalclock = 0;
2267 if (PLUTOPAK)
2268 {
2269 while (totalclock < 120 && !I_CheckAllInput())
2270 G_HandleAsync();
2271
2272 I_ClearAllInput();
2273 }
2274 else
2275 {
2276 G_HandleEventsWhileNoInput();
2277 }
2278
2279 ENDANM:
2280 if (!PLUTOPAK)
2281 {
2282 FX_StopAllSounds();
2283 S_ClearSoundLocks();
2284 S_PlaySound(ENDSEQVOL3SND4);
2285
2286 videoClearScreen(0L);
2287 videoNextPage();
2288
2289 Anim_Play("DUKETEAM.ANM");
2290
2291 I_ClearAllInput();
2292 G_HandleEventsWhileNoInput();
2293
2294 videoClearScreen(0L);
2295 videoNextPage();
2296 G_FadePalette(0, 0, 0, 252);
2297 }
2298
2299 I_ClearAllInput();
2300 FX_StopAllSounds();
2301 S_ClearSoundLocks();
2302
2303 videoClearScreen(0L);
2304
2305 break;
2306 }
2307 }
2308
G_DisplayMPResultsScreen(void)2309 static void G_DisplayMPResultsScreen(void)
2310 {
2311 int32_t i, y, t = 0;
2312
2313 rotatesprite_fs(160<<16, 100<<16, 65536L, 0, MENUSCREEN, 16, 0, 2+8+64+BGSTRETCH);
2314 rotatesprite_fs(160<<16, 34<<16, RR ? 23592L : 65536L, 0, INGAMEDUKETHREEDEE, 0, 0, 10);
2315 if (!RR && PLUTOPAK) // JBF 20030804
2316 rotatesprite_fs((260)<<16, 36<<16, 65536L, 0, PLUTOPAKSPRITE+2, 0, 0, 2+8);
2317 gametext_center(58+(RR ? 0 : 2), "Multiplayer Totals");
2318 gametext_center(58+10, g_mapInfo[G_LastMapInfoIndex()].name);
2319
2320 gametext_center_shade(RR ? 175 : 165, "Press any key or button to continue", quotepulseshade);
2321
2322 minitext(38, 80, "Name", 8, 2+8+16+128);
2323 minitext(269, 80, "Kills", 8, 2+8+16+128);
2324 for (i=0; i<g_mostConcurrentPlayers; i++)
2325 {
2326 Bsprintf(tempbuf, "%-4d", i+1);
2327 minitext(92+(i*23), 80, tempbuf, RR ? 0 : 3, 2+8+16+128);
2328 }
2329
2330 for (i=0; i<g_mostConcurrentPlayers; i++)
2331 {
2332 int32_t xfragtotal = 0;
2333 Bsprintf(tempbuf, "%d", i+1);
2334
2335 minitext(30, 90+t, tempbuf, 0, 2+8+16+128);
2336 minitext(38, 90+t, g_player[i].user_name, g_player[i].ps->palookup, 2+8+16+128);
2337
2338 for (y=0; y<g_mostConcurrentPlayers; y++)
2339 {
2340 if (i == y)
2341 {
2342 Bsprintf(tempbuf, "%-4d", g_player[y].ps->fraggedself);
2343 minitext(92+(y*23), 90+t, tempbuf, RR ? 0 : 2, 2+8+16+128);
2344 xfragtotal -= g_player[y].ps->fraggedself;
2345 }
2346 else
2347 {
2348 Bsprintf(tempbuf, "%-4d", g_player[i].frags[y]);
2349 minitext(92+(y*23), 90+t, tempbuf, 0, 2+8+16+128);
2350 xfragtotal += g_player[i].frags[y];
2351 }
2352 }
2353
2354 Bsprintf(tempbuf, "%-4d", xfragtotal);
2355 minitext(101+(8*23), 90+t, tempbuf, RR ? 0 : 2, 2+8+16+128);
2356
2357 t += 7;
2358 }
2359
2360 for (y=0; y<g_mostConcurrentPlayers; y++)
2361 {
2362 int32_t yfragtotal = 0;
2363 for (i=0; i<g_mostConcurrentPlayers; i++)
2364 {
2365 if (i == y)
2366 yfragtotal += g_player[i].ps->fraggedself;
2367 else
2368 yfragtotal += g_player[i].frags[y];
2369 }
2370 Bsprintf(tempbuf, "%-4d", yfragtotal);
2371 minitext(92+(y*23), 96+(8*7), tempbuf, RR ? 0 : 2, 2+8+16+128);
2372 }
2373
2374 minitext(45, 96+(8*7), "Deaths", RR ? 0 : 8, 2+8+16+128);
2375 }
2376
G_PrintTime_ClockPad(void)2377 static int32_t G_PrintTime_ClockPad(void)
2378 {
2379 int32_t clockpad = 2;
2380 int32_t ii, ij;
2381
2382 for (ii=g_player[myconnectindex].ps->player_par/(REALGAMETICSPERSEC*60), ij=1; ii>9; ii/=10, ij++) { }
2383 clockpad = max(clockpad, ij);
2384 if (!(ud.volume_number == 0 && ud.last_level-1 == 7 && boardfilename[0]))
2385 {
2386 for (ii=g_mapInfo[G_LastMapInfoIndex()].partime/(REALGAMETICSPERSEC*60), ij=1; ii>9; ii/=10, ij++) { }
2387 clockpad = max(clockpad, ij);
2388 if (g_mapInfo[G_LastMapInfoIndex()].designertime)
2389 {
2390 for (ii=g_mapInfo[G_LastMapInfoIndex()].designertime/(REALGAMETICSPERSEC*60), ij=1; ii>9; ii/=10, ij++) { }
2391 clockpad = max(clockpad, ij);
2392 }
2393 }
2394 if (ud.playerbest > 0) for (ii=ud.playerbest/(REALGAMETICSPERSEC*60), ij=1; ii>9; ii/=10, ij++) { }
2395 clockpad = max(clockpad, ij);
2396
2397 return clockpad;
2398 }
2399
G_PrintTime2(int32_t time)2400 static const char* G_PrintTime2(int32_t time)
2401 {
2402 Bsprintf(tempbuf, RR ? "%0*d : %02d" : "%0*d:%02d", G_PrintTime_ClockPad(), time/(REALGAMETICSPERSEC*60), (time/REALGAMETICSPERSEC)%60);
2403 return tempbuf;
2404 }
G_PrintTime3(int32_t time)2405 static const char* G_PrintTime3(int32_t time)
2406 {
2407 Bsprintf(tempbuf, RR ? "%0*d : %02d . %02d" : "%0*d:%02d.%02d", G_PrintTime_ClockPad(), time/(REALGAMETICSPERSEC*60), (time/REALGAMETICSPERSEC)%60, ((time%REALGAMETICSPERSEC)*33)/10);
2408 return tempbuf;
2409 }
2410
G_PrintYourTime(void)2411 const char* G_PrintYourTime(void)
2412 {
2413 return G_PrintTime3(g_player[myconnectindex].ps->player_par);
2414 }
G_PrintParTime(void)2415 const char* G_PrintParTime(void)
2416 {
2417 if (ud.last_level < 1)
2418 return "<invalid>";
2419 return G_PrintTime2(g_mapInfo[G_LastMapInfoIndex()].partime);
2420 }
G_PrintDesignerTime(void)2421 const char* G_PrintDesignerTime(void)
2422 {
2423 if (ud.last_level < 1)
2424 return "<invalid>";
2425 return G_PrintTime2(g_mapInfo[G_LastMapInfoIndex()].designertime);
2426 }
G_PrintBestTime(void)2427 const char* G_PrintBestTime(void)
2428 {
2429 return G_PrintTime3(ud.playerbest);
2430 }
2431
G_BonusScreen(int32_t bonusonly)2432 void G_BonusScreen(int32_t bonusonly)
2433 {
2434 int32_t gfx_offset;
2435 int32_t bonuscnt;
2436 int32_t clockpad = 2;
2437 const char *lastmapname;
2438
2439 if (REALITY)
2440 {
2441 RT_Bonus();
2442 return;
2443 }
2444
2445 //if (g_networkMode == NET_DEDICATED_SERVER)
2446 // return;
2447
2448 G_UpdateAppTitle();
2449
2450 if (ud.volume_number == 0 && ud.last_level == 8 && boardfilename[0])
2451 {
2452 lastmapname = Bstrrchr(boardfilename, '\\');
2453 if (!lastmapname) lastmapname = Bstrrchr(boardfilename, '/');
2454 if (!lastmapname) lastmapname = boardfilename;
2455 }
2456 else
2457 {
2458 lastmapname = g_mapInfo[G_LastMapInfoIndex()].name;
2459 if (!lastmapname) // this isn't right but it's better than no name at all
2460 lastmapname = g_mapInfo[G_LastMapInfoIndex()].name;
2461 }
2462
2463 if (RR)
2464 {
2465 if ((g_lastLevel && ud.volume_number == 2) || g_vixenLevel)
2466 lastmapname = "CLOSE ENCOUNTERS";
2467 else if (g_turdLevel)
2468 lastmapname = "SMELTING PLANT";
2469 }
2470
2471
2472 fadepal(0, 0, 0, 0, 252, RR ? 4 : 28);
2473 videoSetViewableArea(0, 0, xdim-1, ydim-1);
2474 videoClearScreen(0L);
2475 videoNextPage();
2476 renderFlushPerms();
2477
2478 FX_StopAllSounds();
2479 S_ClearSoundLocks();
2480 FX_SetReverb(0L);
2481 CONTROL_BindsEnabled = 1; // so you can use your screenshot bind on the score screens
2482
2483 if (!bonusonly)
2484 G_BonusCutscenes();
2485
2486 P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8+2+1); // JBF 20040308
2487 G_FadePalette(0, 0, 0, 252); // JBF 20031228
2488 KB_FlushKeyboardQueue();
2489 totalclock = 0;
2490 bonuscnt = 0;
2491
2492 S_StopMusic();
2493 FX_StopAllSounds();
2494 S_ClearSoundLocks();
2495
2496 if (g_mostConcurrentPlayers > 1 && (g_gametypeFlags[ud.coop]&GAMETYPE_SCORESHEET))
2497 {
2498 videoClearScreen(0);
2499 G_DisplayMPResultsScreen();
2500
2501 if (ud.config.MusicToggle)
2502 S_PlaySound(BONUSMUSIC);
2503
2504 videoNextPage();
2505 I_ClearAllInput();
2506 fadepal(0, 0, 0, 252, 0, RR ? -4 : -28);
2507 totalclock = 0;
2508
2509 while (totalclock < TICRATE*10)
2510 {
2511 G_HandleAsync();
2512 MUSIC_Update();
2513
2514 if (engineFPSLimit())
2515 {
2516 videoClearScreen(0);
2517 G_DisplayMPResultsScreen();
2518 videoNextPage();
2519 }
2520
2521 if (I_CheckAllInput())
2522 {
2523 I_ClearAllInput();
2524 break;
2525 }
2526 }
2527
2528 fadepal(0, 0, 0, 0, 252, RR ? 4 : 28);
2529 }
2530
2531 if (bonusonly || (g_netServer || ud.multimode > 1)) return;
2532
2533 if (!RR)
2534 {
2535 gfx_offset = (ud.volume_number==1) ? 5 : 0;
2536 gfx_offset += BONUSSCREEN;
2537 rotatesprite_fs(160<<16, 100<<16, 65536L, 0, gfx_offset, 0, 0, 2+8+64+128+BGSTRETCH);
2538
2539 if (lastmapname)
2540 menutext_center(20-6, lastmapname);
2541 menutext_center(36-6, "Completed");
2542
2543 gametext_center_shade(192, "Press any key or button to continue", quotepulseshade);
2544
2545 if (ud.config.MusicToggle)
2546 S_PlaySound(BONUSMUSIC);
2547 }
2548 else
2549 {
2550 gfx_offset = (ud.volume_number==0) ? RRTILE403 : RRTILE409;
2551 gfx_offset += ud.level_number-1;
2552
2553 if (g_lastLevel || g_vixenLevel)
2554 gfx_offset = RRTILE409+7;
2555
2556 if (boardfilename[0])
2557 gfx_offset = RRTILE403;
2558
2559 rotatesprite_fs(160<<16, 100<<16, 65536L, 0, gfx_offset, 0, 0, 2+8+64+128+BGSTRETCH);
2560 if (lastmapname)
2561 menutext(80,16, lastmapname);
2562
2563 menutext(15, 192, "Press any key to continue");
2564 }
2565
2566 videoNextPage();
2567 I_ClearAllInput();
2568 fadepal(0, 0, 0, 252, 0, -4);
2569 bonuscnt = 0;
2570 totalclock = 0;
2571
2572 do
2573 {
2574 int32_t yy = 0, zz;
2575
2576 G_HandleAsync();
2577 MUSIC_Update();
2578
2579 if (engineFPSLimit())
2580 {
2581 if (g_player[myconnectindex].ps->gm&MODE_EOL)
2582 {
2583 videoClearScreen(0);
2584 rotatesprite_fs(160<<16, 100<<16, 65536L, 0, gfx_offset, 0, 0, 2+8+64+128+BGSTRETCH);
2585
2586 if (totalclock >= 1000000000 && totalclock < 1000000320)
2587 {
2588 switch (((int32_t) totalclock>>4)%15)
2589 {
2590 case 0:
2591 if (bonuscnt == 6)
2592 {
2593 bonuscnt++;
2594 S_PlaySound(RR ? 425 : SHOTGUN_COCK);
2595 switch (rand()&3)
2596 {
2597 case 0:
2598 S_PlaySound(BONUS_SPEECH1);
2599 break;
2600 case 1:
2601 S_PlaySound(BONUS_SPEECH2);
2602 break;
2603 case 2:
2604 S_PlaySound(BONUS_SPEECH3);
2605 break;
2606 case 3:
2607 S_PlaySound(BONUS_SPEECH4);
2608 break;
2609 }
2610 }
2611 fallthrough__;
2612 case 1:
2613 case 4:
2614 case 5:
2615 if (!RR)
2616 rotatesprite_fs(199<<16, 31<<16, 65536L, 0, 3+gfx_offset, 0, 0, 2+8+16+64+128+BGSTRETCH);
2617 break;
2618 case 2:
2619 case 3:
2620 if (!RR)
2621 rotatesprite_fs(199<<16, 31<<16, 65536L, 0, 4+gfx_offset, 0, 0, 2+8+16+64+128+BGSTRETCH);
2622 break;
2623 }
2624 }
2625 else if (totalclock > (10240+120L)) break;
2626 else
2627 {
2628 switch (((int32_t) totalclock>>5)&3)
2629 {
2630 case 1:
2631 case 3:
2632 if (!RR)
2633 rotatesprite_fs(199<<16, 31<<16, 65536L, 0, 1+gfx_offset, 0, 0, 2+8+16+64+128+BGSTRETCH);
2634 break;
2635 case 2:
2636 if (!RR)
2637 rotatesprite_fs(199<<16, 31<<16, 65536L, 0, 2+gfx_offset, 0, 0, 2+8+16+64+128+BGSTRETCH);
2638 break;
2639 }
2640 }
2641
2642 if (!RR)
2643 {
2644 if (lastmapname)
2645 menutext_center(20-6, lastmapname);
2646 menutext_center(36-6, "Completed");
2647
2648 gametext_center_shade(192, "Press any key or button to continue", quotepulseshade);
2649 }
2650 else
2651 {
2652 if (lastmapname)
2653 menutext(80, 16, lastmapname);
2654
2655 menutext(15, 192, "Press any key to continue");
2656 }
2657
2658 const int yystep = RR ? 16 : 10;
2659 if (totalclock > (60*3))
2660 {
2661 yy = zz = RR ? 48 : 59;
2662
2663 if (!RR)
2664 gametext(10, yy+9, "Your Time:");
2665 else
2666 menutext(30, yy, "Yer Time:");
2667
2668 yy+= yystep;
2669 if (!(ud.volume_number == 0 && ud.last_level-1 == 7 && boardfilename[0]))
2670 {
2671 if (g_mapInfo[G_LastMapInfoIndex()].partime)
2672 {
2673 if (!RR)
2674 gametext(10, yy+9, "Par Time:");
2675 else
2676 menutext(30, yy, "Par Time:");
2677 yy+=yystep;
2678 }
2679 if (g_mapInfo[G_LastMapInfoIndex()].designertime)
2680 {
2681 // EDuke 2.0 / NAM source suggests "Green Beret's Time:"
2682 if (DUKE)
2683 gametext(10, yy+9, "3D Realms' Time:");
2684 else if (RR)
2685 menutext(30, yy, "Xatrix Time:");
2686 yy+=yystep;
2687 }
2688
2689 }
2690 if (ud.playerbest > 0)
2691 {
2692 if (!RR)
2693 gametext(10, yy+9, (g_player[myconnectindex].ps->player_par > 0 && g_player[myconnectindex].ps->player_par < ud.playerbest) ? "Prev Best Time:" : "Your Best Time:");
2694 else
2695 menutext(30, yy, (g_player[myconnectindex].ps->player_par > 0 && g_player[myconnectindex].ps->player_par < ud.playerbest) ? "Prev Best:" : "Yer Best:");
2696 yy += yystep;
2697 }
2698
2699 if (bonuscnt == 0)
2700 bonuscnt++;
2701
2702 yy = zz;
2703 if (totalclock >(60*4))
2704 {
2705 if (bonuscnt == 1)
2706 {
2707 bonuscnt++;
2708 S_PlaySound(RR ? 404 : PIPEBOMB_EXPLODE);
2709 }
2710
2711 if (g_player[myconnectindex].ps->player_par > 0)
2712 {
2713 G_PrintYourTime();
2714 if (!RR)
2715 {
2716 gametext_number((320>>2)+71, yy+9, tempbuf);
2717 if (g_player[myconnectindex].ps->player_par < ud.playerbest)
2718 gametext((320>>2)+89+(clockpad*24), yy+9, "New record!");
2719 }
2720 else
2721 {
2722 menutext(191, yy, tempbuf);
2723 //if (g_player[myconnectindex].ps->player_par < ud.playerbest)
2724 // menutext(191 + 30 + (clockpad*24), yy, "New record!");
2725 }
2726 }
2727 else if (!RR)
2728 gametext_pal((320>>2)+71, yy+9, "Cheated!", 2);
2729 else
2730 menutext(191, yy, "Cheated!");
2731 yy+=yystep;
2732
2733 if (!(ud.volume_number == 0 && ud.last_level-1 == 7 && boardfilename[0]))
2734 {
2735 if (g_mapInfo[G_LastMapInfoIndex()].partime)
2736 {
2737 G_PrintParTime();
2738 if (!RR)
2739 gametext_number((320>>2)+71, yy+9, tempbuf);
2740 else
2741 menutext(191, yy, tempbuf);
2742 yy+=yystep;
2743 }
2744 if (g_mapInfo[G_LastMapInfoIndex()].designertime)
2745 {
2746 G_PrintDesignerTime();
2747 if (DUKE)
2748 gametext_number((320>>2)+71, yy+9, tempbuf);
2749 else if (RR)
2750 menutext(191, yy, tempbuf);
2751 yy+=yystep;
2752 }
2753 }
2754
2755 if (ud.playerbest > 0)
2756 {
2757 G_PrintBestTime();
2758 if (!RR)
2759 gametext_number((320>>2)+71, yy+9, tempbuf);
2760 else
2761 menutext(191, yy, tempbuf);
2762 yy+=yystep;
2763 }
2764 }
2765 }
2766
2767 zz = yy += RR ? 16 : 5;
2768 if (totalclock > (60*6))
2769 {
2770 if (!RR)
2771 gametext(10, yy+9, "Enemies Killed:");
2772 else
2773 menutext(30, yy, "Varmints Killed:");
2774 yy += yystep;
2775 if (!RR)
2776 gametext(10, yy+9, "Enemies Left:");
2777 else
2778 menutext(30, yy, "Varmints Left:");
2779 yy += yystep;
2780
2781 if (bonuscnt == 2)
2782 {
2783 bonuscnt++;
2784 if (!RR)
2785 S_PlaySound(FLY_BY);
2786 }
2787
2788 yy = zz;
2789
2790 if (totalclock > (60*7))
2791 {
2792 if (bonuscnt == 3)
2793 {
2794 bonuscnt++;
2795 S_PlaySound(RR ? 422 : PIPEBOMB_EXPLODE);
2796 }
2797 Bsprintf(tempbuf, "%-3d", g_player[myconnectindex].ps->actors_killed);
2798 if (!RR)
2799 gametext_number((320>>2)+70, yy+9, tempbuf);
2800 else
2801 menutext(231,yy,tempbuf);
2802 yy += yystep;
2803 if (ud.player_skill > 3 && !RR)
2804 {
2805 if (!RR)
2806 gametext((320>>2)+70, yy+9, "N/A");
2807 else
2808 menutext(231,yy, "N/A");
2809 yy += yystep;
2810 }
2811 else
2812 {
2813 if ((g_player[myconnectindex].ps->max_actors_killed-g_player[myconnectindex].ps->actors_killed) < 0)
2814 Bsprintf(tempbuf, "%-3d", 0);
2815 else Bsprintf(tempbuf, "%-3d", g_player[myconnectindex].ps->max_actors_killed-g_player[myconnectindex].ps->actors_killed);
2816 if (!RR)
2817 gametext_number((320>>2)+70, yy+9, tempbuf);
2818 else
2819 menutext(231, yy, tempbuf);
2820 yy += yystep;
2821 }
2822 }
2823 }
2824
2825 zz = yy += RR ? 0 : 5;
2826 if (totalclock > (60*9))
2827 {
2828 if (!RR)
2829 gametext(10, yy+9, "Secrets Found:");
2830 else
2831 menutext(30, yy, "Secrets Found:");
2832 yy += yystep;
2833 if (!RR)
2834 gametext(10, yy+9, "Secrets Missed:");
2835 else
2836 menutext(30, yy, "Secrets Missed:");
2837 yy += yystep;
2838 if (bonuscnt == 4) bonuscnt++;
2839
2840 yy = zz;
2841 if (totalclock > (60*10))
2842 {
2843 if (bonuscnt == 5)
2844 {
2845 bonuscnt++;
2846 S_PlaySound(RR ? 404 : PIPEBOMB_EXPLODE);
2847 }
2848 Bsprintf(tempbuf, "%-3d", g_player[myconnectindex].ps->secret_rooms);
2849 if (!RR)
2850 gametext_number((320>>2)+70, yy+9, tempbuf);
2851 else
2852 menutext(231, yy, tempbuf);
2853 yy += yystep;
2854 #if 0
2855 // Always overwritten.
2856 if (g_player[myconnectindex].ps->secret_rooms > 0)
2857 Bsprintf(tempbuf, "%-3d%%", (100*g_player[myconnectindex].ps->secret_rooms/g_player[myconnectindex].ps->max_secret_rooms));
2858 #endif
2859 Bsprintf(tempbuf, "%-3d", g_player[myconnectindex].ps->max_secret_rooms-g_player[myconnectindex].ps->secret_rooms);
2860 if (!RR)
2861 gametext_number((320>>2)+70, yy+9, tempbuf);
2862 else
2863 menutext(231, yy, tempbuf);
2864 yy += yystep;
2865 }
2866 }
2867
2868 if (totalclock > 10240 && totalclock < 10240+10240)
2869 totalclock = 1024;
2870
2871 if (I_CheckAllInput() && totalclock >(60*2)) // JBF 20030809
2872 {
2873 I_ClearAllInput();
2874 if (totalclock < (60*13))
2875 {
2876 KB_FlushKeyboardQueue();
2877 totalclock = (60*13);
2878 }
2879 else if (totalclock < 1000000000)
2880 totalclock = 1000000000;
2881 }
2882 }
2883 else
2884 break;
2885
2886 videoNextPage();
2887 }
2888 } while (1);
2889 if (g_turdLevel)
2890 g_turdLevel = 0;
2891 if (g_vixenLevel)
2892 g_vixenLevel = 0;
2893 }
2894
G_PlayMapAnim(void)2895 void G_PlayMapAnim(void)
2896 {
2897 const char *animFile;
2898 if (ud.volume_number == 0)
2899 {
2900 switch (ud.level_number)
2901 {
2902 case 1:
2903 animFile = "lvl1.anm";
2904 break;
2905 case 2:
2906 animFile = "lvl2.anm";
2907 break;
2908 case 3:
2909 animFile = "lvl3.anm";
2910 break;
2911 case 4:
2912 animFile = "lvl4.anm";
2913 break;
2914 case 5:
2915 animFile = "lvl5.anm";
2916 break;
2917 case 6:
2918 animFile = "lvl6.anm";
2919 break;
2920 default:
2921 animFile = "lvl7.anm";
2922 break;
2923 }
2924 }
2925 else
2926 {
2927 switch (ud.level_number)
2928 {
2929 case 1:
2930 animFile = "lvl8.anm";
2931 break;
2932 case 2:
2933 animFile = "lvl9.anm";
2934 break;
2935 case 3:
2936 animFile = "lvl10.anm";
2937 break;
2938 case 4:
2939 animFile = "lvl11.anm";
2940 break;
2941 case 5:
2942 animFile = "lvl12.anm";
2943 break;
2944 case 6:
2945 animFile = "lvl13.anm";
2946 break;
2947 default:
2948 animFile = NULL;
2949 break;
2950 }
2951 }
2952
2953 if (animFile == NULL)
2954 return;
2955
2956 Anim_Play(animFile);
2957 }
2958
G_ShowMapFrame(void)2959 void G_ShowMapFrame(void)
2960 {
2961 int frame = -1;
2962
2963 if (ud.volume_number == 0)
2964 {
2965 switch (ud.level_number)
2966 {
2967 case 1:
2968 frame = 0;
2969 break;
2970 case 2:
2971 frame = 1;
2972 break;
2973 case 3:
2974 frame = 2;
2975 break;
2976 case 4:
2977 frame = 3;
2978 break;
2979 case 5:
2980 frame = 4;
2981 break;
2982 case 6:
2983 frame = 5;
2984 break;
2985 default:
2986 frame = 6;
2987 break;
2988 }
2989 }
2990 else
2991 {
2992 switch (ud.level_number)
2993 {
2994 case 1:
2995 frame = 7;
2996 break;
2997 case 2:
2998 frame = 8;
2999 break;
3000 case 3:
3001 frame = 9;
3002 break;
3003 case 4:
3004 frame = 10;
3005 break;
3006 case 5:
3007 frame = 11;
3008 break;
3009 case 6:
3010 frame = 12;
3011 break;
3012 default:
3013 frame = -1;
3014 break;
3015 }
3016 }
3017 rotatesprite_fs(160<<16,100<<16,65536L,0,RRTILE8624+frame,0,0,10+64+128);
3018 }
3019
G_BonusScreenRRRA(int32_t bonusonly)3020 void G_BonusScreenRRRA(int32_t bonusonly)
3021 {
3022 int32_t gfx_offset;
3023 int32_t bonuscnt;
3024 int32_t showMap = 0;
3025 const char *lastmapname;
3026
3027 //if (g_networkMode == NET_DEDICATED_SERVER)
3028 // return;
3029
3030 G_UpdateAppTitle();
3031
3032 if (ud.volume_number == 0 && ud.last_level == 8 && boardfilename[0])
3033 {
3034 lastmapname = Bstrrchr(boardfilename, '\\');
3035 if (!lastmapname) lastmapname = Bstrrchr(boardfilename, '/');
3036 if (!lastmapname) lastmapname = boardfilename;
3037 }
3038 else
3039 {
3040 lastmapname = g_mapInfo[G_LastMapInfoIndex()].name;
3041 if (!lastmapname) // this isn't right but it's better than no name at all
3042 lastmapname = g_mapInfo[G_LastMapInfoIndex()].name;
3043 }
3044
3045 if ((g_lastLevel && ud.volume_number == 2) || g_vixenLevel)
3046 lastmapname = "CLOSE ENCOUNTERS";
3047 else if (g_turdLevel)
3048 lastmapname = "SMELTING PLANT";
3049
3050
3051 fadepal(0, 0, 0, 0, 252, 4);
3052 videoSetViewableArea(0, 0, xdim-1, ydim-1);
3053 videoClearScreen(0L);
3054 videoNextPage();
3055 renderFlushPerms();
3056
3057 FX_StopAllSounds();
3058 S_ClearSoundLocks();
3059 FX_SetReverb(0L);
3060 CONTROL_BindsEnabled = 1; // so you can use your screenshot bind on the score screens
3061
3062 if (boardfilename[0] == 0 && numplayers < 2)
3063 {
3064 if ((ud.eog == 0 || ud.volume_number != 1) && ud.volume_number <= 1)
3065 {
3066 showMap = 1;
3067 MUSIC_StopSong();
3068 KB_FlushKeyboardQueue();
3069
3070 P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8+2+1);
3071 G_ShowMapFrame();
3072 fadepal(0, 0, 0, 252, 0, -4);
3073 P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8+2+1);
3074 }
3075 }
3076
3077 if (!bonusonly)
3078 G_BonusCutscenes();
3079
3080 P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8+2+1); // JBF 20040308
3081 //G_FadePalette(0, 0, 0, 252); // JBF 20031228
3082 KB_FlushKeyboardQueue();
3083 totalclock = 0;
3084 bonuscnt = 0;
3085
3086 S_StopMusic();
3087 FX_StopAllSounds();
3088 S_ClearSoundLocks();
3089
3090 if (g_mostConcurrentPlayers > 1 && (g_gametypeFlags[ud.coop]&GAMETYPE_SCORESHEET))
3091 {
3092 videoClearScreen(0);
3093 G_DisplayMPResultsScreen();
3094
3095 if (ud.config.MusicToggle)
3096 S_PlaySound(BONUSMUSIC);
3097
3098 videoNextPage();
3099 I_ClearAllInput();
3100 fadepal(0, 0, 0, 252, 0, -4);
3101 totalclock = 0;
3102
3103 while (totalclock < TICRATE*10)
3104 {
3105 G_HandleAsync();
3106 MUSIC_Update();
3107
3108 if (engineFPSLimit())
3109 {
3110 videoClearScreen(0);
3111 G_DisplayMPResultsScreen();
3112 videoNextPage();
3113 }
3114
3115 if (I_CheckAllInput())
3116 {
3117 I_ClearAllInput();
3118 break;
3119 }
3120 }
3121
3122 fadepal(0, 0, 0, 0, 252, 4);
3123 }
3124
3125 if (bonusonly || (g_netServer || ud.multimode > 1)) return;
3126
3127 gfx_offset = (ud.volume_number==0) ? RRTILE403 : RRTILE409;
3128 gfx_offset += ud.level_number-1;
3129
3130 if (g_lastLevel || g_vixenLevel)
3131 gfx_offset = RRTILE409+7;
3132
3133 if (boardfilename[0])
3134 gfx_offset = RRTILE403;
3135
3136 if (!showMap)
3137 rotatesprite_fs(160<<16, 100<<16, 65536L, 0, gfx_offset, 0, 0, 2+8+64+128+BGSTRETCH);
3138 if (lastmapname)
3139 menutext(80,16, lastmapname);
3140
3141 menutext(15, 192, "Press any key to continue");
3142
3143 I_ClearAllInput();
3144 if (!showMap)
3145 {
3146 videoNextPage();
3147 fadepal(0, 0, 0, 252, 0, -4);
3148 }
3149 bonuscnt = 0;
3150 totalclock = 0;
3151
3152 do
3153 {
3154 int32_t yy = 0, zz;
3155
3156 G_HandleAsync();
3157 MUSIC_Update();
3158
3159 if (engineFPSLimit())
3160 {
3161 if (g_player[myconnectindex].ps->gm&MODE_EOL)
3162 {
3163 videoClearScreen(0);
3164 if (showMap)
3165 G_ShowMapFrame();
3166 else
3167 rotatesprite_fs(160<<16, 100<<16, 65536L, 0, gfx_offset, 0, 0, 2+8+64+128+BGSTRETCH);
3168
3169 if (showMap)
3170 {
3171 if (bonuscnt == 7)
3172 {
3173 bonuscnt++;
3174 MUSIC_StopSong();
3175 G_PlayMapAnim();
3176 break;
3177 }
3178 }
3179
3180 if (totalclock >= 1000000000 && totalclock < 1000000320)
3181 {
3182 switch (((int32_t) totalclock>>4)%15)
3183 {
3184 case 0:
3185 if (bonuscnt == 6)
3186 {
3187 bonuscnt++;
3188 S_PlaySound(425);
3189 switch (rand()&3)
3190 {
3191 case 0:
3192 S_PlaySound(BONUS_SPEECH1);
3193 break;
3194 case 1:
3195 S_PlaySound(BONUS_SPEECH2);
3196 break;
3197 case 2:
3198 S_PlaySound(BONUS_SPEECH3);
3199 break;
3200 case 3:
3201 S_PlaySound(BONUS_SPEECH4);
3202 break;
3203 }
3204 }
3205 fallthrough__;
3206 case 1:
3207 case 4:
3208 case 5:
3209 break;
3210 case 2:
3211 case 3:
3212 break;
3213 }
3214 }
3215 else if (totalclock > (10240+120L)) break;
3216 else
3217 {
3218 switch (((int32_t) totalclock>>5)&3)
3219 {
3220 case 1:
3221 case 3:
3222 break;
3223 case 2:
3224 break;
3225 }
3226 }
3227
3228 if (lastmapname)
3229 menutext(80, 16, lastmapname);
3230
3231 menutext(15, 192, "Press any key to continue");
3232
3233 const int yystep = 16;
3234 if (totalclock > (60*3))
3235 {
3236 yy = zz = 48;
3237
3238 menutext(30, yy, "Yer Time:");
3239
3240 yy+= yystep;
3241 if (!(ud.volume_number == 0 && ud.last_level-1 == 7 && boardfilename[0]))
3242 {
3243 if (g_mapInfo[G_LastMapInfoIndex()].partime)
3244 {
3245 menutext(30, yy, "Par Time:");
3246 yy+=yystep;
3247 }
3248 if (g_mapInfo[G_LastMapInfoIndex()].designertime)
3249 {
3250 menutext(30, yy, "Xatrix Time:");
3251 yy+=yystep;
3252 }
3253
3254 }
3255 if (ud.playerbest > 0)
3256 {
3257 menutext(30, yy, (g_player[myconnectindex].ps->player_par > 0 && g_player[myconnectindex].ps->player_par < ud.playerbest) ? "Prev Best:" : "Yer Best:");
3258 yy += yystep;
3259 }
3260
3261 if (bonuscnt == 0)
3262 bonuscnt++;
3263
3264 yy = zz;
3265 if (totalclock >(60*4))
3266 {
3267 if (bonuscnt == 1)
3268 {
3269 bonuscnt++;
3270 S_PlaySound(404);
3271 }
3272
3273 if (g_player[myconnectindex].ps->player_par > 0)
3274 {
3275 G_PrintYourTime();
3276 menutext(191, yy, tempbuf);
3277 //if (g_player[myconnectindex].ps->player_par < ud.playerbest)
3278 // menutext(191 + 30 + (clockpad*24), yy, "New record!");
3279 }
3280 else
3281 menutext(191, yy, "Cheated!");
3282 yy+=yystep;
3283
3284 if (!(ud.volume_number == 0 && ud.last_level-1 == 7 && boardfilename[0]))
3285 {
3286 if (g_mapInfo[G_LastMapInfoIndex()].partime)
3287 {
3288 G_PrintParTime();
3289 menutext(191, yy, tempbuf);
3290 yy+=yystep;
3291 }
3292 if (g_mapInfo[G_LastMapInfoIndex()].designertime)
3293 {
3294 G_PrintDesignerTime();
3295 menutext(191, yy, tempbuf);
3296 yy+=yystep;
3297 }
3298 }
3299
3300 if (ud.playerbest > 0)
3301 {
3302 G_PrintBestTime();
3303 menutext(191, yy, tempbuf);
3304 yy+=yystep;
3305 }
3306 }
3307 }
3308
3309 zz = yy += 16;
3310 if (totalclock > (60*6))
3311 {
3312 menutext(30, yy, "Varmints Killed:");
3313 yy += yystep;
3314 menutext(30, yy, "Varmints Left:");
3315 yy += yystep;
3316
3317 if (bonuscnt == 2)
3318 bonuscnt++;
3319
3320 yy = zz;
3321
3322 if (totalclock > (60*7))
3323 {
3324 if (bonuscnt == 3)
3325 {
3326 bonuscnt++;
3327 S_PlaySound(422);
3328 }
3329 Bsprintf(tempbuf, "%-3d", g_player[myconnectindex].ps->actors_killed);
3330 menutext(231,yy,tempbuf);
3331 yy += yystep;
3332 //if (ud.player_skill > 3)
3333 //{
3334 // menutext(231,yy, "N/A");
3335 // yy += yystep;
3336 //}
3337 //else
3338 {
3339 if ((g_player[myconnectindex].ps->max_actors_killed-g_player[myconnectindex].ps->actors_killed) < 0)
3340 Bsprintf(tempbuf, "%-3d", 0);
3341 else Bsprintf(tempbuf, "%-3d", g_player[myconnectindex].ps->max_actors_killed-g_player[myconnectindex].ps->actors_killed);
3342 menutext(231, yy, tempbuf);
3343 yy += yystep;
3344 }
3345 }
3346 }
3347
3348 zz = yy += 0;
3349 if (totalclock > (60*9))
3350 {
3351 menutext(30, yy, "Secrets Found:");
3352 yy += yystep;
3353 menutext(30, yy, "Secrets Missed:");
3354 yy += yystep;
3355 if (bonuscnt == 4) bonuscnt++;
3356
3357 yy = zz;
3358 if (totalclock > (60*10))
3359 {
3360 if (bonuscnt == 5)
3361 {
3362 bonuscnt++;
3363 S_PlaySound(404);
3364 }
3365 Bsprintf(tempbuf, "%-3d", g_player[myconnectindex].ps->secret_rooms);
3366 menutext(231, yy, tempbuf);
3367 yy += yystep;
3368 #if 0
3369 // Always overwritten.
3370 if (g_player[myconnectindex].ps->secret_rooms > 0)
3371 Bsprintf(tempbuf, "%-3d%%", (100*g_player[myconnectindex].ps->secret_rooms/g_player[myconnectindex].ps->max_secret_rooms));
3372 #endif
3373 Bsprintf(tempbuf, "%-3d", g_player[myconnectindex].ps->max_secret_rooms-g_player[myconnectindex].ps->secret_rooms);
3374 menutext(231, yy, tempbuf);
3375 yy += yystep;
3376 }
3377 }
3378
3379 if (totalclock > 10240 && totalclock < 10240+10240)
3380 totalclock = 1024;
3381
3382 if (I_CheckAllInput() && totalclock >(60*2)) // JBF 20030809
3383 {
3384 I_ClearAllInput();
3385
3386 if (totalclock < (60*13))
3387 {
3388 KB_FlushKeyboardQueue();
3389 totalclock = (60*13);
3390 }
3391 else if (totalclock < 1000000000)
3392 totalclock = 1000000000;
3393 }
3394 }
3395 else
3396 break;
3397 videoNextPage();
3398 }
3399 } while (1);
3400 if (ud.eog)
3401 {
3402 fadepal(0, 0, 0, 0, 252, 4);
3403 videoClearScreen(0L);
3404 videoNextPage();
3405 S_PlaySound(35);
3406 G_FadePalette(0, 0, 0, 0);
3407 P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8+2+1);
3408 while (1)
3409 {
3410 switch (((int32_t) totalclock >> 4) & 1)
3411 {
3412 case 0:
3413 rotatesprite(0,0,65536,0,RRTILE8677,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
3414 videoNextPage();
3415 G_FadePalette(0, 0, 0, 0);
3416 P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8+2+1);
3417 Net_GetPackets();
3418 break;
3419 case 1:
3420 rotatesprite(0,0,65536,0,RRTILE8677+1,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
3421 videoNextPage();
3422 G_FadePalette(0, 0, 0, 0);
3423 P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8+2+1);
3424 Net_GetPackets();
3425 break;
3426 }
3427 S_Cleanup();
3428 if (!S_CheckSoundPlaying(-1,35)) break;
3429 if (I_CheckAllInput())
3430 {
3431 I_ClearAllInput();
3432 S_StopSound(35);
3433 break;
3434 }
3435 }
3436 }
3437 if (g_RAendEpisode)
3438 {
3439 g_RAendEpisode = 0;
3440 ud.m_volume_number = ud.volume_number = 1;
3441 ud.m_level_number = ud.level_number = 0;
3442 ud.eog = 0;
3443 }
3444 if (g_turdLevel)
3445 g_turdLevel = 0;
3446 if (g_vixenLevel)
3447 g_vixenLevel = 0;
3448 }
3449
3450