]> icculus.org git repositories - theoddone33/hheretic.git/blob - base/in_lude.c
Menu fonts working, drawpatch fix
[theoddone33/hheretic.git] / base / in_lude.c
1 /*
2 ========================
3 =
4 = IN_lude.c
5 =
6 ========================
7 */
8
9 #include "doomdef.h"
10 #include "soundst.h"
11 #ifdef RENDER3D
12 #include "ogl_def.h"
13 #define PATCH_REF       int
14 #define WR_CacheLumpName(a,b)        W_GetNumForName(a)
15 #define ZR_ChangeTag(a,b)
16 #define WR_CacheLumpNum(a,b)        a
17 #define V_DrawPatch(x,y,p)          OGL_DrawPatch(x,y,p)
18 #define V_DrawFuzzPatch(x,y,p)      OGL_DrawFuzzPatch(x,y,p)
19 #define V_DrawAltFuzzPatch(x,y,p)   OGL_DrawAltFuzzPatch(x,y,p)
20 #define V_DrawShadowedPatch(x,y,p)  OGL_DrawShadowedPatch(x,y,p)
21 #else
22 #define ZR_ChangeTag(a,b)       Z_ChangeTag(a,b)
23 #define WR_CacheLumpName(a,b)           W_CacheLumpName(a,b)
24 #define WR_CacheLumpNum(a,b)            W_CacheLumpNum(a,b)
25 #define PATCH_REF       patch_t*
26 #endif
27
28 typedef enum
29 {
30         SINGLE,
31         COOPERATIVE,
32         DEATHMATCH
33 } gametype_t;
34
35 // Public functions
36
37 void IN_Start(void);
38 void IN_Ticker(void);
39 void IN_Drawer(void);
40
41 boolean intermission;
42
43 // Private functions
44
45 void IN_WaitStop(void);
46 void IN_Stop(void);
47 void IN_LoadPics(void);
48 void IN_UnloadPics(void);
49 void IN_CheckForSkip(void);
50 void IN_InitStats(void);
51 void IN_InitDeathmatchStats(void);
52 void IN_InitNetgameStats(void);
53 void IN_DrawOldLevel(void);
54 void IN_DrawYAH(void);
55 void IN_DrawStatBack(void);
56 void IN_DrawSingleStats(void);
57 void IN_DrawCoopStats(void);
58 void IN_DrawDMStats(void);
59 void IN_DrawNumber(int val, int x, int y, int digits);
60 void IN_DrawTime(int x, int y, int h, int m, int s);
61 void IN_DrTextB(char *text, int x, int y);
62
63 static boolean skipintermission;
64 static int interstate = 0;
65 static int intertime = -1;
66 static int oldintertime = 0;
67 static gametype_t gametype;
68
69 static int cnt;
70
71 static int time;
72 static int hours;
73 static int minutes;
74 static int seconds;
75
76 static int slaughterboy; // in DM, the player with the most kills
77
78 static int killPercent[MAXPLAYERS];
79 static int bonusPercent[MAXPLAYERS];
80 static int secretPercent[MAXPLAYERS];
81
82 static PATCH_REF patchINTERPIC;
83 static PATCH_REF patchBEENTHERE;
84 static PATCH_REF patchGOINGTHERE;
85 static PATCH_REF FontBNumbers[10];
86 #ifdef RENDER3D
87 static patch_t *FontB3DNumbers[10];
88 #endif
89 static PATCH_REF FontBNegative;
90 #ifdef RENDER3D
91 static patch_t *FontB3DNegative;
92 #endif
93 static PATCH_REF FontBSlash;
94 static PATCH_REF FontBPercent;
95
96 static int FontBLump;
97 static int FontBLumpBase;
98 static int patchFaceOkayBase;
99 static int patchFaceDeadBase;
100
101 static signed int totalFrags[MAXPLAYERS];
102 static fixed_t dSlideX[MAXPLAYERS];
103 static fixed_t dSlideY[MAXPLAYERS];
104
105 static char *KillersText[] = { "K", "I", "L", "L", "E", "R", "S" };
106
107 extern char *LevelNames[];
108
109 typedef struct
110 {
111         int x;
112         int y;
113 } yahpt_t;
114
115 static yahpt_t YAHspot[3][9] =
116 {
117         {
118                 { 172, 78 },
119                 { 86, 90 },
120                 { 73, 66 },
121                 { 159, 95 },
122                 { 148, 126 },
123                 { 132, 54 },
124                 { 131, 74 },
125                 { 208, 138 },
126                 { 52, 101 }
127         },
128         {
129                 { 218, 57 },
130                 { 137, 81 },
131                 { 155, 124 },
132                 { 171, 68 },
133                 { 250, 86 },
134                 { 136, 98 },
135                 { 203, 90 },
136                 { 220, 140 },
137                 { 279, 106 }
138         },
139         {
140                 { 86, 99 },
141                 { 124, 103 },
142                 { 154, 79 },
143                 { 202, 83 },
144                 { 178, 59 },
145                 { 142, 58 },
146                 { 219, 66 },
147                 { 247, 57 },
148                 { 107, 80 }
149         }
150 };
151
152 //========================================================================
153 //
154 // IN_Start
155 //
156 //========================================================================
157
158 extern void AM_Stop (void);
159
160 void IN_Start(void)
161 {
162         I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
163         IN_LoadPics();
164         IN_InitStats();
165         intermission = true;
166         interstate = -1;
167         skipintermission = false;
168         intertime = 0;
169         oldintertime = 0;
170         AM_Stop();
171         S_StartSong(mus_intr, true);
172 }
173
174 //========================================================================
175 //
176 // IN_WaitStop
177 //
178 //========================================================================
179
180 void IN_WaitStop(void)
181 {
182         if(!--cnt)
183         {
184                 IN_Stop();
185                 G_WorldDone();
186         }
187 }
188
189 //========================================================================
190 //
191 // IN_Stop
192 //
193 //========================================================================
194
195 void IN_Stop(void)
196 {
197         intermission = false;
198         IN_UnloadPics();
199         SB_state = -1;
200         BorderNeedRefresh = true;
201 }
202
203 //========================================================================
204 //
205 // IN_InitStats
206 //
207 //      Initializes the stats for single player mode
208 //========================================================================
209
210 void IN_InitStats(void)
211 {
212         int i;
213         int j;
214         signed int slaughterfrags;
215         int posnum;
216         int slaughtercount;
217         int playercount;
218
219
220         if(!netgame)
221         {
222                 gametype = SINGLE;
223                 time = leveltime/35;
224                 hours = time/3600;
225                 time -= hours*3600;
226                 minutes = time/60;
227                 time -= minutes*60;
228                 seconds = time;
229         }
230         else if(netgame && !deathmatch)
231         {
232                 gametype = COOPERATIVE;
233                 memset(killPercent, 0, MAXPLAYERS*sizeof(int));
234                 memset(bonusPercent, 0, MAXPLAYERS*sizeof(int));
235                 memset(secretPercent, 0, MAXPLAYERS*sizeof(int));
236                 for(i=0; i<MAXPLAYERS; i++)
237                 {
238                         if(playeringame[i])
239                         {
240                                 if(totalkills)
241                                 {
242                                         killPercent[i] = players[i].killcount*100/totalkills;
243                                 }
244                                 if(totalitems)
245                                 {
246                                         bonusPercent[i] = players[i].itemcount*100/totalitems;
247                                 }
248                                 if(totalsecret)
249                                 {
250                                         secretPercent[i] = players[i].secretcount*100/totalsecret;
251                                 }
252                         }
253                 }
254         }
255         else
256         {
257                 gametype = DEATHMATCH;
258                 slaughterboy = 0;
259                 slaughterfrags = -9999;
260                 posnum = 0;
261                 playercount = 0;
262                 slaughtercount = 0;
263                 for(i=0; i<MAXPLAYERS; i++)
264                 {
265                         totalFrags[i] = 0;
266                         if(playeringame[i])
267                         {
268                                 playercount++;
269                                 for(j=0; j<MAXPLAYERS; j++)
270                                 {
271                                         if(playeringame[j])
272                                         {
273                                                 totalFrags[i] += players[i].frags[j];
274                                         }
275                                 }
276                                 dSlideX[i] = (43*posnum*FRACUNIT)/20;
277                                 dSlideY[i] = (36*posnum*FRACUNIT)/20;
278                                 posnum++;
279                         }
280                         if(totalFrags[i] > slaughterfrags)
281                         {
282                                 slaughterboy = 1<<i;
283                                 slaughterfrags = totalFrags[i];
284                                 slaughtercount = 1;
285                         }
286                         else if(totalFrags[i] == slaughterfrags)
287                         {
288                                 slaughterboy |= 1<<i;
289                                 slaughtercount++;
290                         }
291                 }
292                 if(playercount == slaughtercount)
293                 { // don't do the slaughter stuff if everyone is equal
294                         slaughterboy = 0;
295                 }
296         }
297 }
298
299 //========================================================================
300 //
301 // IN_LoadPics
302 //
303 //========================================================================
304
305 void IN_LoadPics(void)
306 {
307         int i;
308
309         switch(gameepisode)
310         {
311                 case 1:
312                         patchINTERPIC = WR_CacheLumpName("MAPE1", PU_STATIC);
313                         break;
314                 case 2:
315                         patchINTERPIC = WR_CacheLumpName("MAPE2", PU_STATIC);
316                         break;
317                 case 3:
318                         patchINTERPIC = WR_CacheLumpName("MAPE3", PU_STATIC);
319                         break;
320                 default:
321                         break;
322         }
323         patchBEENTHERE = WR_CacheLumpName("IN_X", PU_STATIC);
324         patchGOINGTHERE = WR_CacheLumpName("IN_YAH", PU_STATIC);
325         FontBLumpBase = W_GetNumForName("FONTB16");
326         for(i=0; i<10; i++)
327         {
328                 FontBNumbers[i] = WR_CacheLumpNum(FontBLumpBase+i, PU_STATIC);
329 #ifdef RENDER3D
330                 FontB3DNumbers[i] = W_CacheLumpNum(FontBLumpBase+i, PU_STATIC);
331 #endif
332         }
333         FontBLump = W_GetNumForName("FONTB_S")+1;
334         FontBNegative = WR_CacheLumpName("FONTB13", PU_STATIC);
335 #ifdef RENDER3D
336         FontB3DNegative = W_CacheLumpName("FONTB13", PU_STATIC);
337 #endif
338
339         FontBSlash = WR_CacheLumpName("FONTB15", PU_STATIC);
340         FontBPercent = WR_CacheLumpName("FONTB05", PU_STATIC);
341         patchFaceOkayBase = W_GetNumForName("FACEA0");
342         patchFaceDeadBase = W_GetNumForName("FACEB0");
343 }
344
345 //========================================================================
346 //
347 // IN_UnloadPics
348 //
349 //========================================================================
350
351 void IN_UnloadPics(void)
352 {
353         int i;
354
355         if(patchINTERPIC)
356         {
357                 ZR_ChangeTag(patchINTERPIC, PU_CACHE);
358         }
359         ZR_ChangeTag(patchBEENTHERE, PU_CACHE);
360         ZR_ChangeTag(patchGOINGTHERE, PU_CACHE);
361         for(i=0; i<10; i++)
362         {
363                 ZR_ChangeTag(FontBNumbers[i], PU_CACHE);
364 #ifdef RENDER3D
365                 Z_ChangeTag(FontB3DNumbers[i], PU_CACHE);
366 #endif
367         }
368         ZR_ChangeTag(FontBNegative, PU_CACHE);
369 #ifdef RENDER3D
370         Z_ChangeTag (FontB3DNegative, PU_CACHE);
371 #endif
372         ZR_ChangeTag(FontBSlash, PU_CACHE);
373         ZR_ChangeTag(FontBPercent, PU_CACHE);
374 }
375
376 //========================================================================
377 //
378 // IN_Ticker
379 //
380 //========================================================================
381
382 void IN_Ticker(void)
383 {
384         if(!intermission)
385         {
386                 return;
387         }
388         if(interstate == 3)
389         {
390                 IN_WaitStop();
391                 return;
392         }
393         IN_CheckForSkip();
394         intertime++;
395         if(oldintertime < intertime)
396         {
397                 interstate++;
398                 if(gameepisode > 3 && interstate >= 1)
399                 { // Extended Wad levels:  skip directly to the next level
400                         interstate = 3;
401                 }
402                 switch(interstate)
403                 {
404                         case 0:
405                                 oldintertime = intertime+300;
406                                 if(gameepisode > 3)
407                                 {
408                                         oldintertime = intertime+1200;
409                                 }
410                                 break;
411                         case 1:
412                                 oldintertime = intertime+200;
413                                 break;
414                         case 2:
415                                 oldintertime = MAXINT;
416                                 break;
417                         case 3:
418                                 cnt = 10;
419                                 break;
420                         default:
421                                 break;
422                 }
423         }
424         if(skipintermission)
425         {
426                 if(interstate == 0 && intertime < 150)
427                 {
428                         intertime = 150;
429                         skipintermission = false;
430                         return;
431                 }
432                 else if(interstate < 2 && gameepisode < 4)
433                 {
434                         interstate = 2;
435                         skipintermission = false;
436                         S_StartSound(NULL, sfx_dorcls);
437                         return;
438                 }
439                 interstate = 3;
440                 cnt = 10;
441                 skipintermission = false;
442                 S_StartSound(NULL, sfx_dorcls);
443         }
444 }
445
446 //========================================================================
447 //
448 // IN_CheckForSkip
449 //
450 //      Check to see if any player hit a key
451 //========================================================================
452
453 void IN_CheckForSkip(void)
454 {
455         int   i;
456         player_t  *player;
457
458         for (i=0, player = players ; i<MAXPLAYERS ; i++, player++)
459         {
460                 if (playeringame[i])
461                 {
462                         if (player->cmd.buttons&BT_ATTACK)
463                         {
464                                 if (!player->attackdown)
465                                 {
466                                         skipintermission = 1;
467                                 }
468                                 player->attackdown = true;
469                         }
470                         else
471                         {
472                                 player->attackdown = false;
473                         }
474                         if (player->cmd.buttons&BT_USE)
475                         {
476                                 if (!player->usedown)
477                                 {
478                                         skipintermission = 1;
479                                 }
480                                 player->usedown = true;
481                         }
482                         else
483                         {
484                                 player->usedown = false;
485                         }
486                 }
487         }
488 }
489
490 //========================================================================
491 //
492 // IN_Drawer
493 //
494 //========================================================================
495
496 void IN_Drawer(void)
497 {
498         static int oldinterstate;
499
500         if(!intermission)
501         {
502                 return;
503         }
504         if(interstate == 3)
505         {
506                 return;
507         }
508         UpdateState |= I_FULLSCRN;
509         if(oldinterstate != 2 && interstate == 2)
510         {
511                 S_StartSound(NULL, sfx_pstop);
512         }
513         oldinterstate = interstate;
514         switch(interstate)
515         {
516                 case 0: // draw stats
517                         IN_DrawStatBack();
518                         switch(gametype)
519                         {
520                                 case SINGLE:
521                                         IN_DrawSingleStats();
522                                         break;
523                                 case COOPERATIVE:
524                                         IN_DrawCoopStats();
525                                         break;
526                                 case DEATHMATCH:
527                                         IN_DrawDMStats();
528                                         break;
529                         }
530                         break;
531                 case 1: // leaving old level
532                         if(gameepisode < 4)
533                         {
534                                 V_DrawPatch(0, 0, patchINTERPIC);
535                                 IN_DrawOldLevel();
536                         }
537                         break;
538                 case 2: // going to the next level
539                         if(gameepisode < 4)
540                         {
541                                 V_DrawPatch(0, 0, patchINTERPIC);
542                                 IN_DrawYAH();
543                         }
544                         break;
545                 case 3: // waiting before going to the next level
546                         if(gameepisode < 4)
547                         {
548                                 V_DrawPatch(0, 0, patchINTERPIC);
549                         }
550                         break;
551                 default:
552                         I_Error("IN_lude:  Intermission state out of range.\n");
553                         break;
554         }
555 }
556
557 //========================================================================
558 //
559 // IN_DrawStatBack
560 //
561 //========================================================================
562
563 void IN_DrawStatBack(void)
564 {
565 #ifndef RENDER3D
566         int x;
567         int y;
568
569         byte *src;
570         byte *dest;
571
572         src = W_CacheLumpName ("FLOOR16", PU_CACHE);
573         dest = screen;
574
575         for (y=0 ; y<SCREENHEIGHT ; y++)
576         {
577                 for (x=0 ; x<SCREENWIDTH/64 ; x++)
578                 {
579                         memcpy (dest, src+((y&63)<<6), 64);
580                         dest += 64;
581                 }
582                 if (SCREENWIDTH&63)
583                 {
584                         memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63);
585                         dest += (SCREENWIDTH&63);
586                 }
587         }
588 #else
589         OGL_SetFlat(R_FlatNumForName("FLOOR16"));
590         OGL_DrawRectTiled(0,0,SCREENWIDTH,SCREENHEIGHT,64,64);
591 #endif
592 }
593
594 //========================================================================
595 //
596 // IN_DrawOldLevel
597 //
598 //========================================================================
599
600 void IN_DrawOldLevel(void)
601 {
602         int i;
603         int x;
604
605         x = 160-MN_TextBWidth(LevelNames[(gameepisode-1)*9+prevmap-1]+7)/2;
606         IN_DrTextB(LevelNames[(gameepisode-1)*9+prevmap-1]+7, x, 3);
607         x = 160-MN_TextAWidth("FINISHED")/2;
608         MN_DrTextA("FINISHED", x, 25);
609
610         if(prevmap == 9)
611         {
612                 for(i=0; i<gamemap-1; i++)
613                 {
614                         V_DrawPatch(YAHspot[gameepisode-1][i].x, YAHspot[gameepisode-1][i].y,
615                                 patchBEENTHERE);
616                 }
617                 if(!(intertime&16))
618                 {
619                         V_DrawPatch(YAHspot[gameepisode-1][8].x, YAHspot[gameepisode-1][8].y,
620                                 patchBEENTHERE);
621                 }
622         }
623         else
624         {
625                 for(i=0; i<prevmap-1; i++)
626                 {
627                         V_DrawPatch(YAHspot[gameepisode-1][i].x, YAHspot[gameepisode-1][i].y,
628                                 patchBEENTHERE);
629                 }
630                 if(players[consoleplayer].didsecret)
631                 {
632                         V_DrawPatch(YAHspot[gameepisode-1][8].x, YAHspot[gameepisode-1][8].y,
633                                 patchBEENTHERE);
634                 }
635                 if(!(intertime&16))
636                 {
637                         V_DrawPatch(YAHspot[gameepisode-1][prevmap-1].x, YAHspot[gameepisode-1][prevmap-1].y,
638                                 patchBEENTHERE);
639                 }
640         }
641 }
642
643 //========================================================================
644 //
645 // IN_DrawYAH
646 //
647 //========================================================================
648
649 void IN_DrawYAH(void)
650 {
651         int i;
652         int x;
653
654         x = 160-MN_TextAWidth("NOW ENTERING:")/2;
655         MN_DrTextA("NOW ENTERING:", x, 10);
656         x = 160-MN_TextBWidth(LevelNames[(gameepisode-1)*9+gamemap-1]+7)/2;
657         IN_DrTextB(LevelNames[(gameepisode-1)*9+gamemap-1]+7, x, 20);
658
659         if(prevmap == 9)
660         {
661                 prevmap = gamemap-1;
662         }
663         for(i=0; i<prevmap; i++)
664         {
665                 V_DrawPatch(YAHspot[gameepisode-1][i].x, YAHspot[gameepisode-1][i].y,
666                         patchBEENTHERE);
667         }
668         if(players[consoleplayer].didsecret)
669         {
670                 V_DrawPatch(YAHspot[gameepisode-1][8].x, YAHspot[gameepisode-1][8].y,
671                         patchBEENTHERE);
672         }
673         if(!(intertime&16) || interstate == 3)
674         { // draw the destination 'X'
675                 V_DrawPatch(YAHspot[gameepisode-1][gamemap-1].x,
676                         YAHspot[gameepisode-1][gamemap-1].y, patchGOINGTHERE);
677         }
678 }
679
680 //========================================================================
681 //
682 // IN_DrawSingleStats
683 //
684 //========================================================================
685
686 void IN_DrawSingleStats(void)
687 {
688         int x;
689         static int sounds;
690
691         IN_DrTextB("KILLS", 50, 65);
692         IN_DrTextB("ITEMS", 50, 90);
693         IN_DrTextB("SECRETS", 50, 115);
694
695         x = 160-MN_TextBWidth(LevelNames[(gameepisode-1)*9+prevmap-1]+7)/2;
696         IN_DrTextB(LevelNames[(gameepisode-1)*9+prevmap-1]+7, x, 3);
697         x = 160-MN_TextAWidth("FINISHED")/2;
698         MN_DrTextA("FINISHED", x, 25);
699
700         if(intertime < 30)
701         {
702                 sounds = 0;
703                 return;
704         }
705         if(sounds < 1 && intertime >= 30)
706         {
707                 S_StartSound(NULL, sfx_dorcls);
708                 sounds++;
709         }
710         IN_DrawNumber(players[consoleplayer].killcount, 200, 65, 3);
711 #ifdef RENDER3D
712         OGL_DrawShadowedPatch(237, 65, FontBSlash);
713 #else
714         V_DrawShadowedPatch(237, 65, FontBSlash);
715 #endif
716         IN_DrawNumber(totalkills, 248, 65, 3);
717         if(intertime < 60)
718         {
719                 return;
720         }
721         if(sounds < 2 && intertime >= 60)
722         {
723                 S_StartSound(NULL, sfx_dorcls);
724                 sounds++;
725         }
726         IN_DrawNumber(players[consoleplayer].itemcount, 200, 90, 3);
727 #ifdef RENDER3D
728         OGL_DrawShadowedPatch(237, 90, FontBSlash);
729 #else
730         V_DrawShadowedPatch(237, 90, FontBSlash);
731 #endif
732         IN_DrawNumber(totalitems, 248, 90, 3);
733         if(intertime < 90)
734         {
735                 return;
736         }
737         if(sounds < 3 && intertime >= 90)
738         {
739                 S_StartSound(NULL, sfx_dorcls);
740                 sounds++;
741         }
742         IN_DrawNumber(players[consoleplayer].secretcount, 200, 115, 3);
743 #ifdef RENDER3D
744         OGL_DrawShadowedPatch(237, 115, FontBSlash);
745 #else
746         V_DrawShadowedPatch(237, 115, FontBSlash);
747 #endif
748         IN_DrawNumber(totalsecret, 248, 115, 3);
749         if(intertime < 150)
750         {
751                 return;
752         }
753         if(sounds < 4 && intertime >= 150)
754         {
755                 S_StartSound(NULL, sfx_dorcls);
756                 sounds++;
757         }
758
759         if(!ExtendedWAD || gameepisode < 4)
760         {
761                 IN_DrTextB("TIME", 85, 160);
762                 IN_DrawTime(155, 160, hours, minutes, seconds);
763         }
764         else
765         {
766                 x = 160-MN_TextAWidth("NOW ENTERING:")/2;
767                 MN_DrTextA("NOW ENTERING:", x, 160);
768                 x = 160-MN_TextBWidth(LevelNames[(gameepisode-1)*9+gamemap-1]+7)/2;
769                 IN_DrTextB(LevelNames[(gameepisode-1)*9+gamemap-1]+7, x, 170);
770                 skipintermission = false;
771         }
772 }
773
774 //========================================================================
775 //
776 // IN_DrawCoopStats
777 //
778 //========================================================================
779
780 void IN_DrawCoopStats(void)
781 {
782         int i;
783         int x;
784         int ypos;
785
786         static int sounds;
787
788         IN_DrTextB("KILLS", 95, 35);
789         IN_DrTextB("BONUS", 155, 35);
790         IN_DrTextB("SECRET", 232, 35);
791         x = 160-MN_TextBWidth(LevelNames[(gameepisode-1)*9+prevmap-1]+7)/2;
792         IN_DrTextB(LevelNames[(gameepisode-1)*9+prevmap-1]+7, x, 3);
793         x = 160-MN_TextAWidth("FINISHED")/2;
794         MN_DrTextA("FINISHED", x, 25);
795
796         ypos = 50;
797         for(i=0; i<MAXPLAYERS; i++)
798         {
799                 if(playeringame[i])
800                 {
801 #ifdef RENDER3D
802                         OGL_DrawShadowedPatch(25, ypos, patchFaceOkayBase+i);
803 #else
804                         V_DrawShadowedPatch(25, ypos, W_CacheLumpNum(patchFaceOkayBase+i, PU_CACHE));
805 #endif
806                         if(intertime < 40)
807                         {
808                                 sounds = 0;
809                                 ypos += 37;
810                                 continue;
811                         }
812                         else if(intertime >= 40 && sounds < 1)
813                         {
814                                 S_StartSound(NULL, sfx_dorcls);
815                                 sounds++;
816                         }
817                         IN_DrawNumber(killPercent[i], 85, ypos+10, 3);
818                         V_DrawShadowedPatch(121, ypos+10, FontBPercent);
819                         IN_DrawNumber(bonusPercent[i], 160, ypos+10, 3);
820                         V_DrawShadowedPatch(196, ypos+10, FontBPercent);
821                         IN_DrawNumber(secretPercent[i], 237, ypos+10, 3);
822                         V_DrawShadowedPatch(273, ypos+10, FontBPercent);
823                         ypos += 37;
824                 }
825         }
826 }
827
828 //========================================================================
829 //
830 // IN_DrawDMStats
831 //
832 //========================================================================
833
834 void IN_DrawDMStats(void)
835 {
836         int i;
837         int j;
838         int ypos;
839         int xpos;
840         int kpos;
841         //int x;        // unused variable
842
843         static int sounds;
844
845         xpos = 90;
846         ypos = 55;
847
848         IN_DrTextB("TOTAL", 265, 30);
849         MN_DrTextA("VICTIMS", 140, 8);
850         for(i=0; i<7; i++)
851         {
852                 MN_DrTextA(KillersText[i], 10, 80+9*i);
853         }
854         if(intertime < 20)
855         {
856                 for(i=0; i<MAXPLAYERS; i++)
857                 {
858                         if(playeringame[i])
859                         {
860                                 V_DrawShadowedPatch(40, ((ypos<<FRACBITS)+dSlideY[i]*intertime)
861                                         >>FRACBITS, WR_CacheLumpNum(patchFaceOkayBase+i, PU_CACHE));
862                                 V_DrawShadowedPatch(((xpos<<FRACBITS)+dSlideX[i]*intertime)
863                                         >>FRACBITS, 18, WR_CacheLumpNum(patchFaceDeadBase+i, PU_CACHE));
864                         }
865                 }
866                 sounds = 0;
867                 return;
868         }
869         if(intertime >= 20 && sounds < 1)
870         {
871                 S_StartSound(NULL, sfx_dorcls);
872                 sounds++;
873         }
874         if(intertime >= 100 && slaughterboy && sounds < 2)
875         {
876                 S_StartSound(NULL, sfx_wpnup);
877                 sounds++;
878         }
879         for(i=0; i<MAXPLAYERS; i++)
880         {
881                 if(playeringame[i])
882                 {
883                         if(intertime < 100 || i == consoleplayer)
884                         {
885                                 V_DrawShadowedPatch(40, ypos, WR_CacheLumpNum(patchFaceOkayBase+i, PU_CACHE));
886                                 V_DrawShadowedPatch(xpos, 18, WR_CacheLumpNum(patchFaceDeadBase+i, PU_CACHE));
887                         }
888                         else
889                         {
890                                 V_DrawFuzzPatch(40, ypos, WR_CacheLumpNum(patchFaceOkayBase+i, PU_CACHE));
891                                 V_DrawFuzzPatch(xpos, 18, WR_CacheLumpNum(patchFaceDeadBase+i, PU_CACHE));
892                         }
893                         kpos = 86;
894                         for(j=0; j<MAXPLAYERS; j++)
895                         {
896                                 if(playeringame[j])
897                                 {
898                                         IN_DrawNumber(players[i].frags[j], kpos, ypos+10, 3);
899                                         kpos += 43;
900                                 }
901               }
902                         if(slaughterboy&(1<<i))
903                         {
904                                 if(!(intertime&16))
905                                 {
906                                         IN_DrawNumber(totalFrags[i], 263, ypos+10, 3);
907                                 }
908                         }
909                         else
910                         {
911                                 IN_DrawNumber(totalFrags[i], 263, ypos+10, 3);
912                         }
913                         ypos += 36;
914                         xpos += 43;
915                 }
916         }
917 }
918
919 //========================================================================
920 //
921 // IN_DrawTime
922 //
923 //========================================================================
924
925 void IN_DrawTime(int x, int y, int h, int m, int s)
926 {
927         if(h)
928         {
929                 IN_DrawNumber(h, x, y, 2);
930                 IN_DrTextB(":", x+26, y);
931         }
932         x += 34;
933         if(m || h)
934         {
935                 IN_DrawNumber(m, x, y, 2);
936         }
937         x += 34;
938         if(s)
939         {
940                 IN_DrTextB(":", x-8, y);
941                 IN_DrawNumber(s, x, y, 2);
942         }
943 }
944
945 //========================================================================
946 //
947 // IN_DrawNumber
948 //
949 //========================================================================
950
951 void IN_DrawNumber(int val, int x, int y, int digits)
952 {
953         patch_t *patch;
954         int xpos;
955         int oldval;
956         int realdigits;
957         boolean neg;
958
959         oldval = val;
960         xpos = x;
961         neg = false;
962         realdigits = 1;
963
964         if(val < 0)
965         { //...this should reflect negative frags
966                 val = -val;
967                 neg = true;
968                 if(val > 99)
969                 {
970                         val = 99;
971                 }
972         }
973         if(val > 9)
974         {
975                 realdigits++;
976                 if(digits < realdigits)
977                 {
978                         realdigits = digits;
979                         val = 9;
980                 }
981         }
982         if(val > 99)
983         {
984                 realdigits++;
985                 if(digits < realdigits)
986                 {
987                         realdigits = digits;
988                         val = 99;
989                 }
990         }
991         if(val > 999)
992         {
993                 realdigits++;
994                 if(digits < realdigits)
995                 {
996                         realdigits = digits;
997                         val = 999;
998                 }
999         }
1000         if(digits == 4)
1001         {
1002 #ifdef RENDER3D
1003                 patch = FontB3DNumbers[val/1000];
1004                 OGL_DrawShadowedPatch(xpos+6-patch->width/2-12, y, FontBNumbers[val/1000]);
1005 #else
1006                 patch = FontBNumbers[val/1000];
1007                 V_DrawShadowedPatch(xpos+6-patch->width/2-12, y, patch);
1008 #endif
1009         }
1010         if(digits > 2)
1011         {
1012                 if(realdigits > 2)
1013                 {
1014 #ifdef RENDER3D
1015                         patch = FontB3DNumbers[val/100];
1016                         OGL_DrawShadowedPatch(xpos+6-patch->width/2,y,FontBNumbers[val/1000]);
1017 #else
1018                         patch = FontBNumbers[val/100];
1019                         V_DrawShadowedPatch(xpos+6-patch->width/2, y, patch);
1020 #endif
1021                 }
1022                 xpos += 12;
1023         }
1024         val = val%100;
1025         if(digits > 1)
1026         {
1027                 if(val > 9)
1028                 {
1029 #ifdef RENDER3D
1030                         patch = FontB3DNumbers[val/10];
1031                         OGL_DrawShadowedPatch(xpos+6-patch->width/2, y, FontBNumbers[val/10]);
1032 #else
1033                         patch = FontBNumbers[val/10];
1034                         V_DrawShadowedPatch(xpos+6-patch->width/2, y, patch);
1035 #endif
1036                 }
1037                 else if(digits == 2 || oldval > 99)
1038                 {
1039                         V_DrawShadowedPatch(xpos, y, FontBNumbers[0]);
1040                 }
1041                 xpos += 12;
1042         }
1043         val = val%10;
1044 #ifdef RENDER3D
1045         patch = FontB3DNumbers[val];
1046         OGL_DrawShadowedPatch(xpos+6-patch->width/2,y,FontBNumbers[val]);
1047 #else
1048         patch = FontBNumbers[val];
1049         V_DrawShadowedPatch(xpos+6-patch->width/2, y, patch);
1050 #endif
1051         if(neg)
1052         {
1053 #ifdef RENDER3D
1054                 patch = FontB3DNegative;
1055                 OGL_DrawShadowedPatch(xpos+6-patch->width/2-12*(realdigits), y, FontBNegative);
1056 #else
1057                 patch = FontBNegative;
1058                 V_DrawShadowedPatch(xpos+6-patch->width/2-12*(realdigits), y, patch);
1059 #endif
1060         }
1061 }
1062
1063 //========================================================================
1064 //
1065 // IN_DrTextB
1066 //
1067 //========================================================================
1068
1069 void IN_DrTextB(char *text, int x, int y)
1070 {
1071         char c;
1072         patch_t *p;
1073
1074         while((c = *text++) != 0)
1075         {
1076                 if(c < 33)
1077                 {
1078                         x += 8;
1079                 }
1080                 else
1081                 {
1082                         p = W_CacheLumpNum(FontBLump+c-33, PU_CACHE);
1083 #ifdef RENDER3D
1084                         OGL_DrawShadowedPatch(x,y,FontBLump+c-33);
1085 #else
1086                         V_DrawShadowedPatch(x, y, p);
1087 #endif
1088                         x += p->width-1;
1089                 }
1090         }
1091 }