]> git.lizzy.rs Git - plan9front.git/blob - sys/src/games/doom/wi_stuff.c
games/doom: fix the french problem, remove debug prints
[plan9front.git] / sys / src / games / doom / wi_stuff.c
1 // Emacs style mode select   -*- C++ -*- 
2 //-----------------------------------------------------------------------------
3 //
4 // $Id:$
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 //
8 // This source is available for distribution and/or modification
9 // only under the terms of the DOOM Source Code License as
10 // published by id Software. All rights reserved.
11 //
12 // The source is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
15 // for more details.
16 //
17 // $Log:$
18 //
19 // DESCRIPTION:
20 //      Intermission screens.
21 //
22 //-----------------------------------------------------------------------------
23
24 static const char
25 rcsid[] = "$Id: wi_stuff.c,v 1.7 1997/02/03 22:45:13 b1 Exp $";
26
27 #include "z_zone.h"
28
29 #include "m_random.h"
30 #include "m_swap.h"
31
32 #include "i_system.h"
33
34 #include "w_wad.h"
35
36 #include "g_game.h"
37
38 #include "r_local.h"
39 #include "s_sound.h"
40
41 #include "doomstat.h"
42
43 // Data.
44 #include "sounds.h"
45
46 // Needs access to LFB.
47 #include "v_video.h"
48
49 #include "wi_stuff.h"
50
51 //
52 // Data needed to add patches to full screen intermission pics.
53 // Patches are statistics messages, and animations.
54 // Loads of by-pixel layout and placement, offsets etc.
55 //
56
57
58 //
59 // Different vetween registered DOOM (1994) and
60 //  Ultimate DOOM - Final edition (retail, 1995?).
61 // This is supposedly ignored for commercial
62 //  release (aka DOOM II), which had 34 maps
63 //  in one episode. So there.
64 #define NUMEPISODES     4
65 #define NUMMAPS         9
66
67
68 // in tics
69 //U #define PAUSELEN            (TICRATE*2) 
70 //U #define SCORESTEP           100
71 //U #define ANIMPERIOD          32
72 // pixel distance from "(YOU)" to "PLAYER N"
73 //U #define STARDIST            10 
74 //U #define WK 1
75
76
77 // GLOBAL LOCATIONS
78 #define WI_TITLEY               2
79 #define WI_SPACINGY             33
80
81 // SINGPLE-PLAYER STUFF
82 #define SP_STATSX               50
83 #define SP_STATSY               50
84
85 #define SP_TIMEX                16
86 #define SP_TIMEY                (SCREENHEIGHT-32)
87
88
89 // NET GAME STUFF
90 #define NG_STATSY               50
91 #define NG_STATSX               (32 + SHORT(star->width)/2 + 32*!dofrags)
92
93 #define NG_SPACINGX             64
94
95
96 // DEATHMATCH STUFF
97 #define DM_MATRIXX              42
98 #define DM_MATRIXY              68
99
100 #define DM_SPACINGX             40
101
102 #define DM_TOTALSX              269
103
104 #define DM_KILLERSX             10
105 #define DM_KILLERSY             100
106 #define DM_VICTIMSX             5
107 #define DM_VICTIMSY             50
108
109
110
111
112 typedef enum
113 {
114     ANIM_ALWAYS,
115     ANIM_RANDOM,
116     ANIM_LEVEL
117
118 } animenum_t;
119
120 typedef struct
121 {
122     int         x;
123     int         y;
124     
125 } point_t;
126
127
128 //
129 // Animation.
130 // There is another anim_t used in p_spec.
131 //
132 typedef struct
133 {
134     animenum_t  type;
135
136     // period in tics between animations
137     int         period;
138
139     // number of animation frames
140     int         nanims;
141
142     // location of animation
143     point_t     loc;
144
145     // ALWAYS: n/a,
146     // RANDOM: period deviation (<256),
147     // LEVEL: level
148     int         data1;
149
150     // ALWAYS: n/a,
151     // RANDOM: random base period,
152     // LEVEL: n/a
153     int         data2; 
154
155     // actual graphics for frames of animations
156     patch_t*    p[3]; 
157
158     // following must be initialized to zero before use!
159
160     // next value of bcnt (used in conjunction with period)
161     int         nexttic;
162
163     // last drawn animation frame
164     int         lastdrawn;
165
166     // next frame number to animate
167     int         ctr;
168     
169     // used by RANDOM and LEVEL when animating
170     int         state;  
171
172 } anim_t;
173
174
175 static point_t lnodes[NUMEPISODES][NUMMAPS] =
176 {
177     // Episode 0 World Map
178     {
179         { 185, 164 },   // location of level 0 (CJ)
180         { 148, 143 },   // location of level 1 (CJ)
181         { 69, 122 },    // location of level 2 (CJ)
182         { 209, 102 },   // location of level 3 (CJ)
183         { 116, 89 },    // location of level 4 (CJ)
184         { 166, 55 },    // location of level 5 (CJ)
185         { 71, 56 },     // location of level 6 (CJ)
186         { 135, 29 },    // location of level 7 (CJ)
187         { 71, 24 }      // location of level 8 (CJ)
188     },
189
190     // Episode 1 World Map should go here
191     {
192         { 254, 25 },    // location of level 0 (CJ)
193         { 97, 50 },     // location of level 1 (CJ)
194         { 188, 64 },    // location of level 2 (CJ)
195         { 128, 78 },    // location of level 3 (CJ)
196         { 214, 92 },    // location of level 4 (CJ)
197         { 133, 130 },   // location of level 5 (CJ)
198         { 208, 136 },   // location of level 6 (CJ)
199         { 148, 140 },   // location of level 7 (CJ)
200         { 235, 158 }    // location of level 8 (CJ)
201     },
202
203     // Episode 2 World Map should go here
204     {
205         { 156, 168 },   // location of level 0 (CJ)
206         { 48, 154 },    // location of level 1 (CJ)
207         { 174, 95 },    // location of level 2 (CJ)
208         { 265, 75 },    // location of level 3 (CJ)
209         { 130, 48 },    // location of level 4 (CJ)
210         { 279, 23 },    // location of level 5 (CJ)
211         { 198, 48 },    // location of level 6 (CJ)
212         { 140, 25 },    // location of level 7 (CJ)
213         { 281, 136 }    // location of level 8 (CJ)
214     }
215
216 };
217
218
219 //
220 // Animation locations for episode 0 (1).
221 // Using patches saves a lot of space,
222 //  as they replace 320x200 full screen frames.
223 //
224 static anim_t epsd0animinfo[] =
225 {
226     { ANIM_ALWAYS, TICRATE/3, 3, { 224, 104 } },
227     { ANIM_ALWAYS, TICRATE/3, 3, { 184, 160 } },
228     { ANIM_ALWAYS, TICRATE/3, 3, { 112, 136 } },
229     { ANIM_ALWAYS, TICRATE/3, 3, { 72, 112 } },
230     { ANIM_ALWAYS, TICRATE/3, 3, { 88, 96 } },
231     { ANIM_ALWAYS, TICRATE/3, 3, { 64, 48 } },
232     { ANIM_ALWAYS, TICRATE/3, 3, { 192, 40 } },
233     { ANIM_ALWAYS, TICRATE/3, 3, { 136, 16 } },
234     { ANIM_ALWAYS, TICRATE/3, 3, { 80, 16 } },
235     { ANIM_ALWAYS, TICRATE/3, 3, { 64, 24 } }
236 };
237
238 static anim_t epsd1animinfo[] =
239 {
240     { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 1 },
241     { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 2 },
242     { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 3 },
243     { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 4 },
244     { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 5 },
245     { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 6 },
246     { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 7 },
247     { ANIM_LEVEL, TICRATE/3, 3, { 192, 144 }, 8 },
248     { ANIM_LEVEL, TICRATE/3, 1, { 128, 136 }, 8 }
249 };
250
251 static anim_t epsd2animinfo[] =
252 {
253     { ANIM_ALWAYS, TICRATE/3, 3, { 104, 168 } },
254     { ANIM_ALWAYS, TICRATE/3, 3, { 40, 136 } },
255     { ANIM_ALWAYS, TICRATE/3, 3, { 160, 96 } },
256     { ANIM_ALWAYS, TICRATE/3, 3, { 104, 80 } },
257     { ANIM_ALWAYS, TICRATE/3, 3, { 120, 32 } },
258     { ANIM_ALWAYS, TICRATE/4, 3, { 40, 0 } }
259 };
260
261 static int NUMANIMS[NUMEPISODES] =
262 {
263     sizeof(epsd0animinfo)/sizeof(anim_t),
264     sizeof(epsd1animinfo)/sizeof(anim_t),
265     sizeof(epsd2animinfo)/sizeof(anim_t)
266 };
267
268 static anim_t *anims[NUMEPISODES] =
269 {
270     epsd0animinfo,
271     epsd1animinfo,
272     epsd2animinfo
273 };
274
275
276 //
277 // GENERAL DATA
278 //
279
280 //
281 // Locally used stuff.
282 //
283 #define FB 0
284
285
286 // States for single-player
287 #define SP_KILLS                0
288 #define SP_ITEMS                2
289 #define SP_SECRET               4
290 #define SP_FRAGS                6 
291 #define SP_TIME                 8 
292 #define SP_PAR                  ST_TIME
293
294 #define SP_PAUSE                1
295
296 // in seconds
297 #define SHOWNEXTLOCDELAY        4
298 //#define SHOWLASTLOCDELAY      SHOWNEXTLOCDELAY
299
300
301 // used to accelerate or skip a stage
302 static int              acceleratestage;
303
304 // wbs->pnum
305 static int              me;
306
307  // specifies current state
308 static stateenum_t      state;
309
310 // contains information passed into intermission
311 static wbstartstruct_t* wbs;
312
313 static wbplayerstruct_t* plrs;  // wbs->plyr[]
314
315 // used for general timing
316 static int              cnt;  
317
318 // used for timing of background animation
319 static int              bcnt;
320
321 // signals to refresh everything for one frame
322 static int              firstrefresh; 
323
324 static int              cnt_kills[MAXPLAYERS];
325 static int              cnt_items[MAXPLAYERS];
326 static int              cnt_secret[MAXPLAYERS];
327 static int              cnt_time;
328 static int              cnt_par;
329 static int              cnt_pause;
330
331 // # of commercial levels
332 static int              NUMCMAPS; 
333
334
335 //
336 //      GRAPHICS
337 //
338
339 // background (map of levels).
340 static patch_t*         bg;
341
342 // You Are Here graphic
343 static patch_t*         yah[2]; 
344
345 // splat
346 static patch_t*         splat;
347
348 // %, : graphics
349 static patch_t*         percent;
350 static patch_t*         colon;
351
352 // 0-9 graphic
353 static patch_t*         num[10];
354
355 // minus sign
356 static patch_t*         wiminus;
357
358 // "Finished!" graphics
359 static patch_t*         finished;
360
361 // "Entering" graphic
362 static patch_t*         entering; 
363
364 // "secret"
365 static patch_t*         sp_secret;
366
367  // "Kills", "Scrt", "Items", "Frags"
368 static patch_t*         kills;
369 static patch_t*         secret;
370 static patch_t*         items;
371 static patch_t*         frags;
372
373 // Time sucks.
374 static patch_t*         Time;
375 static patch_t*         par;
376 static patch_t*         sucks;
377
378 // "killers", "victims"
379 static patch_t*         killers;
380 static patch_t*         victims; 
381
382 // "Total", your face, your dead face
383 static patch_t*         total;
384 static patch_t*         star;
385 static patch_t*         bstar;
386
387 // "red P[1..MAXPLAYERS]"
388 static patch_t*         p[MAXPLAYERS];
389
390 // "gray P[1..MAXPLAYERS]"
391 static patch_t*         bp[MAXPLAYERS];
392
393  // Name graphics of each level (centered)
394 static patch_t**        lnames;
395
396 //
397 // CODE
398 //
399
400 // slam background
401 // UNUSED static unsigned char *background=0;
402
403
404 void WI_slamBackground(void)
405 {
406     memcpy(screens[0], screens[1], SCREENWIDTH * SCREENHEIGHT);
407     V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT);
408 }
409
410 // The ticker is used to detect keys
411 //  because of timing issues in netgames.
412 boolean WI_Responder(event_t* /*ev*/)
413 {
414     return false;
415 }
416
417
418 // Draws "<Levelname> Finished!"
419 void WI_drawLF(void)
420 {
421     int y = WI_TITLEY;
422
423     // draw <LevelName> 
424     V_DrawPatch((SCREENWIDTH - SHORT(lnames[wbs->last]->width))/2,
425                 y, FB, lnames[wbs->last]);
426
427     // draw "Finished!"
428     y += (5*SHORT(lnames[wbs->last]->height))/4;
429     
430     V_DrawPatch((SCREENWIDTH - SHORT(finished->width))/2,
431                 y, FB, finished);
432 }
433
434
435
436 // Draws "Entering <LevelName>"
437 void WI_drawEL(void)
438 {
439     int y = WI_TITLEY;
440
441     // draw "Entering"
442     V_DrawPatch((SCREENWIDTH - SHORT(entering->width))/2,
443                 y, FB, entering);
444
445     // draw level
446     y += (5*SHORT(lnames[wbs->next]->height))/4;
447
448     V_DrawPatch((SCREENWIDTH - SHORT(lnames[wbs->next]->width))/2,
449                 y, FB, lnames[wbs->next]);
450
451 }
452
453 void
454 WI_drawOnLnode
455 ( int           n,
456   patch_t*      c[] )
457 {
458
459     int         i;
460     int         left;
461     int         top;
462     int         right;
463     int         bottom;
464     boolean     fits = false;
465
466     i = 0;
467     do
468     {
469         left = lnodes[wbs->epsd][n].x - SHORT(c[i]->leftoffset);
470         top = lnodes[wbs->epsd][n].y - SHORT(c[i]->topoffset);
471         right = left + SHORT(c[i]->width);
472         bottom = top + SHORT(c[i]->height);
473
474         if (left >= 0
475             && right < SCREENWIDTH
476             && top >= 0
477             && bottom < SCREENHEIGHT)
478         {
479             fits = true;
480         }
481         else
482         {
483             i++;
484         }
485     } while (!fits && i!=2);
486
487     if (fits && i<2)
488     {
489         V_DrawPatch(lnodes[wbs->epsd][n].x, lnodes[wbs->epsd][n].y,
490                     FB, c[i]);
491     }
492     else
493     {
494         // DEBUG
495         printf("Could not place patch on level %d", n+1); 
496     }
497 }
498
499
500
501 void WI_initAnimatedBack(void)
502 {
503     int         i;
504     anim_t*     a;
505
506     if (gamemode == commercial)
507         return;
508
509     if (wbs->epsd > 2)
510         return;
511
512     for (i=0;i<NUMANIMS[wbs->epsd];i++)
513     {
514         a = &anims[wbs->epsd][i];
515
516         // init variables
517         a->ctr = -1;
518
519         // specify the next time to draw it
520         if (a->type == ANIM_ALWAYS)
521             a->nexttic = bcnt + 1 + (M_Random()%a->period);
522         else if (a->type == ANIM_RANDOM)
523             a->nexttic = bcnt + 1 + a->data2+(M_Random()%a->data1);
524         else if (a->type == ANIM_LEVEL)
525             a->nexttic = bcnt + 1;
526     }
527
528 }
529
530 void WI_updateAnimatedBack(void)
531 {
532     int         i;
533     anim_t*     a;
534
535     if (gamemode == commercial)
536         return;
537
538     if (wbs->epsd > 2)
539         return;
540
541     for (i=0;i<NUMANIMS[wbs->epsd];i++)
542     {
543         a = &anims[wbs->epsd][i];
544
545         if (bcnt == a->nexttic)
546         {
547             switch (a->type)
548             {
549               case ANIM_ALWAYS:
550                 if (++a->ctr >= a->nanims) a->ctr = 0;
551                 a->nexttic = bcnt + a->period;
552                 break;
553
554               case ANIM_RANDOM:
555                 a->ctr++;
556                 if (a->ctr == a->nanims)
557                 {
558                     a->ctr = -1;
559                     a->nexttic = bcnt+a->data2+(M_Random()%a->data1);
560                 }
561                 else a->nexttic = bcnt + a->period;
562                 break;
563                 
564               case ANIM_LEVEL:
565                 // gawd-awful hack for level anims
566                 if (!(state == StatCount && i == 7)
567                     && wbs->next == a->data1)
568                 {
569                     a->ctr++;
570                     if (a->ctr == a->nanims) a->ctr--;
571                     a->nexttic = bcnt + a->period;
572                 }
573                 break;
574             }
575         }
576
577     }
578
579 }
580
581 void WI_drawAnimatedBack(void)
582 {
583     int                 i;
584     anim_t*             a;
585
586     if (commercial)
587         return;
588
589     if (wbs->epsd > 2)
590         return;
591
592     for (i=0 ; i<NUMANIMS[wbs->epsd] ; i++)
593     {
594         a = &anims[wbs->epsd][i];
595
596         if (a->ctr >= 0)
597             V_DrawPatch(a->loc.x, a->loc.y, FB, a->p[a->ctr]);
598     }
599
600 }
601
602 //
603 // Draws a number.
604 // If digits > 0, then use that many digits minimum,
605 //  otherwise only use as many as necessary.
606 // Returns new x position.
607 //
608
609 int
610 WI_drawNum
611 ( int           x,
612   int           y,
613   int           n,
614   int           digits )
615 {
616
617     int         fontwidth = SHORT(num[0]->width);
618     int         neg;
619     int         temp;
620
621     if (digits < 0)
622     {
623         if (!n)
624         {
625             // make variable-length zeros 1 digit long
626             digits = 1;
627         }
628         else
629         {
630             // figure out # of digits in #
631             digits = 0;
632             temp = n;
633
634             while (temp)
635             {
636                 temp /= 10;
637                 digits++;
638             }
639         }
640     }
641
642     neg = n < 0;
643     if (neg)
644         n = -n;
645
646     // if non-number, do not draw it
647     if (n == 1994)
648         return 0;
649
650     // draw the new number
651     while (digits--)
652     {
653         x -= fontwidth;
654         V_DrawPatch(x, y, FB, num[ n % 10 ]);
655         n /= 10;
656     }
657
658     // draw a minus sign if necessary
659     if (neg)
660         V_DrawPatch(x-=8, y, FB, wiminus);
661
662     return x;
663
664 }
665
666 void
667 WI_drawPercent
668 ( int           x,
669   int           y,
670   int           p )
671 {
672     if (p < 0)
673         return;
674
675     V_DrawPatch(x, y, FB, percent);
676     WI_drawNum(x, y, p, -1);
677 }
678
679
680
681 //
682 // Display level completion time and par,
683 //  or "sucks" message if overflow.
684 //
685 void
686 WI_drawTime
687 ( int           x,
688   int           y,
689   int           t )
690 {
691
692     int         div;
693     int         n;
694
695     if (t<0)
696         return;
697
698     if (t <= 61*59)
699     {
700         div = 1;
701
702         do
703         {
704             n = (t / div) % 60;
705             x = WI_drawNum(x, y, n, 2) - SHORT(colon->width);
706             div *= 60;
707
708             // draw
709             if (div==60 || t / div)
710                 V_DrawPatch(x, y, FB, colon);
711             
712         } while (t / div);
713     }
714     else
715     {
716         // "sucks"
717         V_DrawPatch(x - SHORT(sucks->width), y, FB, sucks); 
718     }
719 }
720
721
722 void WI_End(void)
723 {
724     void WI_unloadData(void);
725     WI_unloadData();
726 }
727
728 void WI_initNoState(void)
729 {
730     state = NoState;
731     acceleratestage = 0;
732     cnt = 10;
733 }
734
735 void WI_updateNoState(void) {
736
737     WI_updateAnimatedBack();
738
739     if (!--cnt)
740     {
741         WI_End();
742         G_WorldDone();
743     }
744
745 }
746
747 static boolean          snl_pointeron = false;
748
749
750 void WI_initShowNextLoc(void)
751 {
752     state = ShowNextLoc;
753     acceleratestage = 0;
754     cnt = SHOWNEXTLOCDELAY * TICRATE;
755
756     WI_initAnimatedBack();
757 }
758
759 void WI_updateShowNextLoc(void)
760 {
761     WI_updateAnimatedBack();
762
763     if (!--cnt || acceleratestage)
764         WI_initNoState();
765     else
766         snl_pointeron = (cnt & 31) < 20;
767 }
768
769 void WI_drawShowNextLoc(void)
770 {
771
772     int         i;
773     int         last;
774
775     WI_slamBackground();
776
777     // draw animated background
778     WI_drawAnimatedBack(); 
779
780     if ( gamemode != commercial)
781     {
782         if (wbs->epsd > 2)
783         {
784             WI_drawEL();
785             return;
786         }
787         
788         last = (wbs->last == 8) ? wbs->next - 1 : wbs->last;
789
790         // draw a splat on taken cities.
791         for (i=0 ; i<=last ; i++)
792             WI_drawOnLnode(i, &splat);
793
794         // splat the secret level?
795         if (wbs->didsecret)
796             WI_drawOnLnode(8, &splat);
797
798         // draw flashing ptr
799         if (snl_pointeron)
800             WI_drawOnLnode(wbs->next, yah); 
801     }
802
803     // draws which level you are entering..
804     if ( (gamemode != commercial)
805          || wbs->next != 30)
806         WI_drawEL();  
807
808 }
809
810 void WI_drawNoState(void)
811 {
812     snl_pointeron = true;
813     WI_drawShowNextLoc();
814 }
815
816 int WI_fragSum(int playernum)
817 {
818     int         i;
819     int         frags = 0;
820     
821     for (i=0 ; i<MAXPLAYERS ; i++)
822     {
823         if (playeringame[i]
824             && i!=playernum)
825         {
826             frags += plrs[playernum].frags[i];
827         }
828     }
829
830         
831     // JDC hack - negative frags.
832     frags -= plrs[playernum].frags[playernum];
833     // UNUSED if (frags < 0)
834     //  frags = 0;
835
836     return frags;
837 }
838
839
840
841 static int              dm_state;
842 static int              dm_frags[MAXPLAYERS][MAXPLAYERS];
843 static int              dm_totals[MAXPLAYERS];
844
845
846
847 void WI_initDeathmatchStats(void)
848 {
849
850     int         i;
851     int         j;
852
853     state = StatCount;
854     acceleratestage = 0;
855     dm_state = 1;
856
857     cnt_pause = TICRATE;
858
859     for (i=0 ; i<MAXPLAYERS ; i++)
860     {
861         if (playeringame[i])
862         {
863             for (j=0 ; j<MAXPLAYERS ; j++)
864                 if (playeringame[j])
865                     dm_frags[i][j] = 0;
866
867             dm_totals[i] = 0;
868         }
869     }
870     
871     WI_initAnimatedBack();
872 }
873
874
875
876 void WI_updateDeathmatchStats(void)
877 {
878
879     int         i;
880     int         j;
881     
882     boolean     stillticking;
883
884     WI_updateAnimatedBack();
885
886     if (acceleratestage && dm_state != 4)
887     {
888         acceleratestage = 0;
889
890         for (i=0 ; i<MAXPLAYERS ; i++)
891         {
892             if (playeringame[i])
893             {
894                 for (j=0 ; j<MAXPLAYERS ; j++)
895                     if (playeringame[j])
896                         dm_frags[i][j] = plrs[i].frags[j];
897
898                 dm_totals[i] = WI_fragSum(i);
899             }
900         }
901         
902
903         S_StartSound(0, sfx_barexp);
904         dm_state = 4;
905     }
906
907     
908     if (dm_state == 2)
909     {
910         if (!(bcnt&3))
911             S_StartSound(0, sfx_pistol);
912         
913         stillticking = false;
914
915         for (i=0 ; i<MAXPLAYERS ; i++)
916         {
917             if (playeringame[i])
918             {
919                 for (j=0 ; j<MAXPLAYERS ; j++)
920                 {
921                     if (playeringame[j]
922                         && dm_frags[i][j] != plrs[i].frags[j])
923                     {
924                         if (plrs[i].frags[j] < 0)
925                             dm_frags[i][j]--;
926                         else
927                             dm_frags[i][j]++;
928
929                         if (dm_frags[i][j] > 99)
930                             dm_frags[i][j] = 99;
931
932                         if (dm_frags[i][j] < -99)
933                             dm_frags[i][j] = -99;
934                         
935                         stillticking = true;
936                     }
937                 }
938                 dm_totals[i] = WI_fragSum(i);
939
940                 if (dm_totals[i] > 99)
941                     dm_totals[i] = 99;
942                 
943                 if (dm_totals[i] < -99)
944                     dm_totals[i] = -99;
945             }
946             
947         }
948         if (!stillticking)
949         {
950             S_StartSound(0, sfx_barexp);
951             dm_state++;
952         }
953
954     }
955     else if (dm_state == 4)
956     {
957         if (acceleratestage)
958         {
959             S_StartSound(0, sfx_slop);
960
961             if ( gamemode == commercial)
962                 WI_initNoState();
963             else
964                 WI_initShowNextLoc();
965         }
966     }
967     else if (dm_state & 1)
968     {
969         if (!--cnt_pause)
970         {
971             dm_state++;
972             cnt_pause = TICRATE;
973         }
974     }
975 }
976
977
978
979 void WI_drawDeathmatchStats(void)
980 {
981
982     int         i;
983     int         j;
984     int         x;
985     int         y;
986     int         w;
987     
988     WI_slamBackground();
989     
990     // draw animated background
991     WI_drawAnimatedBack(); 
992     WI_drawLF();
993
994     // draw stat titles (top line)
995     V_DrawPatch(DM_TOTALSX-SHORT(total->width)/2,
996                 DM_MATRIXY-WI_SPACINGY+10,
997                 FB,
998                 total);
999     
1000     V_DrawPatch(DM_KILLERSX, DM_KILLERSY, FB, killers);
1001     V_DrawPatch(DM_VICTIMSX, DM_VICTIMSY, FB, victims);
1002
1003     // draw P?
1004     x = DM_MATRIXX + DM_SPACINGX;
1005     y = DM_MATRIXY;
1006
1007     for (i=0 ; i<MAXPLAYERS ; i++)
1008     {
1009         if (playeringame[i])
1010         {
1011             V_DrawPatch(x-SHORT(p[i]->width)/2,
1012                         DM_MATRIXY - WI_SPACINGY,
1013                         FB,
1014                         p[i]);
1015             
1016             V_DrawPatch(DM_MATRIXX-SHORT(p[i]->width)/2,
1017                         y,
1018                         FB,
1019                         p[i]);
1020
1021             if (i == me)
1022             {
1023                 V_DrawPatch(x-SHORT(p[i]->width)/2,
1024                             DM_MATRIXY - WI_SPACINGY,
1025                             FB,
1026                             bstar);
1027
1028                 V_DrawPatch(DM_MATRIXX-SHORT(p[i]->width)/2,
1029                             y,
1030                             FB,
1031                             star);
1032             }
1033         }
1034         else
1035         {
1036             // V_DrawPatch(x-SHORT(bp[i]->width)/2,
1037             //   DM_MATRIXY - WI_SPACINGY, FB, bp[i]);
1038             // V_DrawPatch(DM_MATRIXX-SHORT(bp[i]->width)/2,
1039             //   y, FB, bp[i]);
1040         }
1041         x += DM_SPACINGX;
1042         y += WI_SPACINGY;
1043     }
1044
1045     // draw stats
1046     y = DM_MATRIXY+10;
1047     w = SHORT(num[0]->width);
1048
1049     for (i=0 ; i<MAXPLAYERS ; i++)
1050     {
1051         x = DM_MATRIXX + DM_SPACINGX;
1052
1053         if (playeringame[i])
1054         {
1055             for (j=0 ; j<MAXPLAYERS ; j++)
1056             {
1057                 if (playeringame[j])
1058                     WI_drawNum(x+w, y, dm_frags[i][j], 2);
1059
1060                 x += DM_SPACINGX;
1061             }
1062             WI_drawNum(DM_TOTALSX+w, y, dm_totals[i], 2);
1063         }
1064         y += WI_SPACINGY;
1065     }
1066 }
1067
1068 static int      cnt_frags[MAXPLAYERS];
1069 static int      dofrags;
1070 static int      ng_state;
1071
1072 void WI_initNetgameStats(void)
1073 {
1074
1075     int i;
1076
1077     state = StatCount;
1078     acceleratestage = 0;
1079     ng_state = 1;
1080
1081     cnt_pause = TICRATE;
1082
1083     for (i=0 ; i<MAXPLAYERS ; i++)
1084     {
1085         if (!playeringame[i])
1086             continue;
1087
1088         cnt_kills[i] = cnt_items[i] = cnt_secret[i] = cnt_frags[i] = 0;
1089
1090         dofrags += WI_fragSum(i);
1091     }
1092
1093     dofrags = !!dofrags;
1094
1095     WI_initAnimatedBack();
1096 }
1097
1098
1099
1100 void WI_updateNetgameStats(void)
1101 {
1102
1103     int         i;
1104     int         fsum;
1105     
1106     boolean     stillticking;
1107
1108     WI_updateAnimatedBack();
1109
1110     if (acceleratestage && ng_state != 10)
1111     {
1112         acceleratestage = 0;
1113
1114         for (i=0 ; i<MAXPLAYERS ; i++)
1115         {
1116             if (!playeringame[i])
1117                 continue;
1118
1119             cnt_kills[i] = (plrs[i].skills * 100) / wbs->maxkills;
1120             cnt_items[i] = (plrs[i].sitems * 100) / wbs->maxitems;
1121             cnt_secret[i] = (plrs[i].ssecret * 100) / wbs->maxsecret;
1122
1123             if (dofrags)
1124                 cnt_frags[i] = WI_fragSum(i);
1125         }
1126         S_StartSound(0, sfx_barexp);
1127         ng_state = 10;
1128     }
1129
1130     if (ng_state == 2)
1131     {
1132         if (!(bcnt&3))
1133             S_StartSound(0, sfx_pistol);
1134
1135         stillticking = false;
1136
1137         for (i=0 ; i<MAXPLAYERS ; i++)
1138         {
1139             if (!playeringame[i])
1140                 continue;
1141
1142             cnt_kills[i] += 2;
1143
1144             if (cnt_kills[i] >= (plrs[i].skills * 100) / wbs->maxkills)
1145                 cnt_kills[i] = (plrs[i].skills * 100) / wbs->maxkills;
1146             else
1147                 stillticking = true;
1148         }
1149         
1150         if (!stillticking)
1151         {
1152             S_StartSound(0, sfx_barexp);
1153             ng_state++;
1154         }
1155     }
1156     else if (ng_state == 4)
1157     {
1158         if (!(bcnt&3))
1159             S_StartSound(0, sfx_pistol);
1160
1161         stillticking = false;
1162
1163         for (i=0 ; i<MAXPLAYERS ; i++)
1164         {
1165             if (!playeringame[i])
1166                 continue;
1167
1168             cnt_items[i] += 2;
1169             if (cnt_items[i] >= (plrs[i].sitems * 100) / wbs->maxitems)
1170                 cnt_items[i] = (plrs[i].sitems * 100) / wbs->maxitems;
1171             else
1172                 stillticking = true;
1173         }
1174         if (!stillticking)
1175         {
1176             S_StartSound(0, sfx_barexp);
1177             ng_state++;
1178         }
1179     }
1180     else if (ng_state == 6)
1181     {
1182         if (!(bcnt&3))
1183             S_StartSound(0, sfx_pistol);
1184
1185         stillticking = false;
1186
1187         for (i=0 ; i<MAXPLAYERS ; i++)
1188         {
1189             if (!playeringame[i])
1190                 continue;
1191
1192             cnt_secret[i] += 2;
1193
1194             if (cnt_secret[i] >= (plrs[i].ssecret * 100) / wbs->maxsecret)
1195                 cnt_secret[i] = (plrs[i].ssecret * 100) / wbs->maxsecret;
1196             else
1197                 stillticking = true;
1198         }
1199         
1200         if (!stillticking)
1201         {
1202             S_StartSound(0, sfx_barexp);
1203             ng_state += 1 + 2*!dofrags;
1204         }
1205     }
1206     else if (ng_state == 8)
1207     {
1208         if (!(bcnt&3))
1209             S_StartSound(0, sfx_pistol);
1210
1211         stillticking = false;
1212
1213         for (i=0 ; i<MAXPLAYERS ; i++)
1214         {
1215             if (!playeringame[i])
1216                 continue;
1217
1218             cnt_frags[i] += 1;
1219
1220             if (cnt_frags[i] >= (fsum = WI_fragSum(i)))
1221                 cnt_frags[i] = fsum;
1222             else
1223                 stillticking = true;
1224         }
1225         
1226         if (!stillticking)
1227         {
1228             S_StartSound(0, sfx_pldeth);
1229             ng_state++;
1230         }
1231     }
1232     else if (ng_state == 10)
1233     {
1234         if (acceleratestage)
1235         {
1236             S_StartSound(0, sfx_sgcock);
1237             if ( gamemode == commercial )
1238                 WI_initNoState();
1239             else
1240                 WI_initShowNextLoc();
1241         }
1242     }
1243     else if (ng_state & 1)
1244     {
1245         if (!--cnt_pause)
1246         {
1247             ng_state++;
1248             cnt_pause = TICRATE;
1249         }
1250     }
1251 }
1252
1253
1254
1255 void WI_drawNetgameStats(void)
1256 {
1257     int         i;
1258     int         x;
1259     int         y;
1260     int         pwidth = SHORT(percent->width);
1261
1262     WI_slamBackground();
1263     
1264     // draw animated background
1265     WI_drawAnimatedBack(); 
1266
1267     WI_drawLF();
1268
1269     // draw stat titles (top line)
1270     V_DrawPatch(NG_STATSX+NG_SPACINGX-SHORT(kills->width),
1271                 NG_STATSY, FB, kills);
1272
1273     V_DrawPatch(NG_STATSX+2*NG_SPACINGX-SHORT(items->width),
1274                 NG_STATSY, FB, items);
1275
1276     V_DrawPatch(NG_STATSX+3*NG_SPACINGX-SHORT(secret->width),
1277                 NG_STATSY, FB, secret);
1278     
1279     if (dofrags)
1280         V_DrawPatch(NG_STATSX+4*NG_SPACINGX-SHORT(frags->width),
1281                     NG_STATSY, FB, frags);
1282
1283     // draw stats
1284     y = NG_STATSY + SHORT(kills->height);
1285
1286     for (i=0 ; i<MAXPLAYERS ; i++)
1287     {
1288         if (!playeringame[i])
1289             continue;
1290
1291         x = NG_STATSX;
1292         V_DrawPatch(x-SHORT(p[i]->width), y, FB, p[i]);
1293
1294         if (i == me)
1295             V_DrawPatch(x-SHORT(p[i]->width), y, FB, star);
1296
1297         x += NG_SPACINGX;
1298         WI_drawPercent(x-pwidth, y+10, cnt_kills[i]);   x += NG_SPACINGX;
1299         WI_drawPercent(x-pwidth, y+10, cnt_items[i]);   x += NG_SPACINGX;
1300         WI_drawPercent(x-pwidth, y+10, cnt_secret[i]);  x += NG_SPACINGX;
1301
1302         if (dofrags)
1303             WI_drawNum(x, y+10, cnt_frags[i], -1);
1304
1305         y += WI_SPACINGY;
1306     }
1307
1308 }
1309
1310 static int      sp_state;
1311
1312 void WI_initStats(void)
1313 {
1314     state = StatCount;
1315     acceleratestage = 0;
1316     sp_state = 1;
1317     cnt_kills[0] = cnt_items[0] = cnt_secret[0] = -1;
1318     cnt_time = cnt_par = -1;
1319     cnt_pause = TICRATE;
1320
1321     WI_initAnimatedBack();
1322 }
1323
1324 void WI_updateStats(void)
1325 {
1326
1327     WI_updateAnimatedBack();
1328
1329     if (acceleratestage && sp_state != 10)
1330     {
1331         acceleratestage = 0;
1332         cnt_kills[0] = (plrs[me].skills * 100) / wbs->maxkills;
1333         cnt_items[0] = (plrs[me].sitems * 100) / wbs->maxitems;
1334         cnt_secret[0] = (plrs[me].ssecret * 100) / wbs->maxsecret;
1335         cnt_time = plrs[me].stime / TICRATE;
1336         cnt_par = wbs->partime / TICRATE;
1337         S_StartSound(0, sfx_barexp);
1338         sp_state = 10;
1339     }
1340
1341     if (sp_state == 2)
1342     {
1343         cnt_kills[0] += 2;
1344
1345         if (!(bcnt&3))
1346             S_StartSound(0, sfx_pistol);
1347
1348         if (cnt_kills[0] >= (plrs[me].skills * 100) / wbs->maxkills)
1349         {
1350             cnt_kills[0] = (plrs[me].skills * 100) / wbs->maxkills;
1351             S_StartSound(0, sfx_barexp);
1352             sp_state++;
1353         }
1354     }
1355     else if (sp_state == 4)
1356     {
1357         cnt_items[0] += 2;
1358
1359         if (!(bcnt&3))
1360             S_StartSound(0, sfx_pistol);
1361
1362         if (cnt_items[0] >= (plrs[me].sitems * 100) / wbs->maxitems)
1363         {
1364             cnt_items[0] = (plrs[me].sitems * 100) / wbs->maxitems;
1365             S_StartSound(0, sfx_barexp);
1366             sp_state++;
1367         }
1368     }
1369     else if (sp_state == 6)
1370     {
1371         cnt_secret[0] += 2;
1372
1373         if (!(bcnt&3))
1374             S_StartSound(0, sfx_pistol);
1375
1376         if (cnt_secret[0] >= (plrs[me].ssecret * 100) / wbs->maxsecret)
1377         {
1378             cnt_secret[0] = (plrs[me].ssecret * 100) / wbs->maxsecret;
1379             S_StartSound(0, sfx_barexp);
1380             sp_state++;
1381         }
1382     }
1383
1384     else if (sp_state == 8)
1385     {
1386         if (!(bcnt&3))
1387             S_StartSound(0, sfx_pistol);
1388
1389         cnt_time += 3;
1390
1391         if (cnt_time >= plrs[me].stime / TICRATE)
1392             cnt_time = plrs[me].stime / TICRATE;
1393
1394         cnt_par += 3;
1395
1396         if (cnt_par >= wbs->partime / TICRATE)
1397         {
1398             cnt_par = wbs->partime / TICRATE;
1399
1400             if (cnt_time >= plrs[me].stime / TICRATE)
1401             {
1402                 S_StartSound(0, sfx_barexp);
1403                 sp_state++;
1404             }
1405         }
1406     }
1407     else if (sp_state == 10)
1408     {
1409         if (acceleratestage)
1410         {
1411             S_StartSound(0, sfx_sgcock);
1412
1413             if (gamemode == commercial)
1414                 WI_initNoState();
1415             else
1416                 WI_initShowNextLoc();
1417         }
1418     }
1419     else if (sp_state & 1)
1420     {
1421         if (!--cnt_pause)
1422         {
1423             sp_state++;
1424             cnt_pause = TICRATE;
1425         }
1426     }
1427
1428 }
1429
1430 void WI_drawStats(void)
1431 {
1432     // line height
1433     int lh;     
1434
1435     lh = (3*SHORT(num[0]->height))/2;
1436
1437     WI_slamBackground();
1438
1439     // draw animated background
1440     WI_drawAnimatedBack();
1441     
1442     WI_drawLF();
1443
1444     V_DrawPatch(SP_STATSX, SP_STATSY, FB, kills);
1445     WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY, cnt_kills[0]);
1446
1447     V_DrawPatch(SP_STATSX, SP_STATSY+lh, FB, items);
1448     WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY+lh, cnt_items[0]);
1449
1450     V_DrawPatch(SP_STATSX, SP_STATSY+2*lh, FB, sp_secret);
1451     WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY+2*lh, cnt_secret[0]);
1452
1453     V_DrawPatch(SP_TIMEX, SP_TIMEY, FB, Time);
1454     WI_drawTime(SCREENWIDTH/2 - SP_TIMEX, SP_TIMEY, cnt_time);
1455
1456     if (wbs->epsd < 3)
1457     {
1458         V_DrawPatch(SCREENWIDTH/2 + SP_TIMEX, SP_TIMEY, FB, par);
1459         WI_drawTime(SCREENWIDTH - SP_TIMEX, SP_TIMEY, cnt_par);
1460     }
1461
1462 }
1463
1464 void WI_checkForAccelerate(void)
1465 {
1466     int   i;
1467     player_t  *player;
1468
1469     // check for button presses to skip delays
1470     for (i=0, player = players ; i<MAXPLAYERS ; i++, player++)
1471     {
1472         if (playeringame[i])
1473         {
1474             if (player->cmd.buttons & BT_ATTACK)
1475             {
1476                 if (!player->attackdown)
1477                     acceleratestage = 1;
1478                 player->attackdown = true;
1479             }
1480             else
1481                 player->attackdown = false;
1482             if (player->cmd.buttons & BT_USE)
1483             {
1484                 if (!player->usedown)
1485                     acceleratestage = 1;
1486                 player->usedown = true;
1487             }
1488             else
1489                 player->usedown = false;
1490         }
1491     }
1492 }
1493
1494
1495
1496 // Updates stuff each tick
1497 void WI_Ticker(void)
1498 {
1499     // counter for general background animation
1500     bcnt++;  
1501
1502     if (bcnt == 1)
1503     {
1504         // intermission music
1505         if ( gamemode == commercial )
1506           S_ChangeMusic(mus_dm2int, true);
1507         else
1508           S_ChangeMusic(mus_inter, true); 
1509     }
1510
1511     WI_checkForAccelerate();
1512
1513     switch (state)
1514     {
1515       case StatCount:
1516         if (deathmatch) WI_updateDeathmatchStats();
1517         else if (netgame) WI_updateNetgameStats();
1518         else WI_updateStats();
1519         break;
1520         
1521       case ShowNextLoc:
1522         WI_updateShowNextLoc();
1523         break;
1524         
1525       case NoState:
1526         WI_updateNoState();
1527         break;
1528     }
1529
1530 }
1531
1532 void WI_loadData(void)
1533 {
1534     int         i;
1535     int         j;
1536     char        name[9];
1537     anim_t*     a;
1538
1539     if (gamemode == commercial)
1540         strcpy(name, "INTERPIC");
1541     else 
1542         sprintf(name, "WIMAP%d", wbs->epsd);
1543     
1544     if ( gamemode == retail )
1545     {
1546       if (wbs->epsd == 3)
1547         strcpy(name,"INTERPIC");
1548     }
1549
1550     // background
1551     bg = W_CacheLumpName(name, PU_CACHE);    
1552     V_DrawPatch(0, 0, 1, bg);
1553
1554
1555     // UNUSED unsigned char *pic = screens[1];
1556     // if (gamemode == commercial)
1557     // {
1558     // darken the background image
1559     // while (pic != screens[1] + SCREENHEIGHT*SCREENWIDTH)
1560     // {
1561     //   *pic = colormaps[256*25 + *pic];
1562     //   pic++;
1563     // }
1564     //}
1565
1566     if (gamemode == commercial)
1567     {
1568         NUMCMAPS = 32;                                                          
1569         lnames = (patch_t **) Z_Malloc(sizeof(patch_t*) * NUMCMAPS,
1570                                        PU_STATIC, 0);
1571         for (i=0 ; i<NUMCMAPS ; i++)
1572         {                                                               
1573             sprintf(name, "CWILV%2.2d", i);
1574             lnames[i] = W_CacheLumpName(name, PU_STATIC);
1575         }                                       
1576     }
1577     else
1578     {
1579         lnames = (patch_t **) Z_Malloc(sizeof(patch_t*) * NUMMAPS,
1580                                        PU_STATIC, 0);
1581         for (i=0 ; i<NUMMAPS ; i++)
1582         {
1583             sprintf(name, "WILV%d%d", wbs->epsd, i);
1584             lnames[i] = W_CacheLumpName(name, PU_STATIC);
1585         }
1586
1587         // you are here
1588         yah[0] = W_CacheLumpName("WIURH0", PU_STATIC);
1589
1590         // you are here (alt.)
1591         yah[1] = W_CacheLumpName("WIURH1", PU_STATIC);
1592
1593         // splat
1594         splat = W_CacheLumpName("WISPLAT", PU_STATIC); 
1595         
1596         if (wbs->epsd < 3)
1597         {
1598             for (j=0;j<NUMANIMS[wbs->epsd];j++)
1599             {
1600                 a = &anims[wbs->epsd][j];
1601                 for (i=0;i<a->nanims;i++)
1602                 {
1603                     // MONDO HACK!
1604                     if (wbs->epsd != 1 || j != 8) 
1605                     {
1606                         // animations
1607                         sprintf(name, "WIA%d%.2d%.2d", wbs->epsd, j, i);  
1608                         a->p[i] = W_CacheLumpName(name, PU_STATIC);
1609                     }
1610                     else
1611                     {
1612                         // HACK ALERT!
1613                         a->p[i] = anims[1][4].p[i]; 
1614                     }
1615                 }
1616             }
1617         }
1618     }
1619
1620     // More hacks on minus sign.
1621     wiminus = W_CacheLumpName("WIMINUS", PU_STATIC); 
1622
1623     for (i=0;i<10;i++)
1624     {
1625          // numbers 0-9
1626         sprintf(name, "WINUM%d", i);     
1627         num[i] = W_CacheLumpName(name, PU_STATIC);
1628     }
1629
1630     // percent sign
1631     percent = W_CacheLumpName("WIPCNT", PU_STATIC);
1632
1633     // "finished"
1634     finished = W_CacheLumpName("WIF", PU_STATIC);
1635
1636     // "entering"
1637     entering = W_CacheLumpName("WIENTER", PU_STATIC);
1638
1639     // "kills"
1640     kills = W_CacheLumpName("WIOSTK", PU_STATIC);   
1641
1642     // "scrt"
1643     secret = W_CacheLumpName("WIOSTS", PU_STATIC);
1644
1645      // "secret"
1646     sp_secret = W_CacheLumpName("WISCRT2", PU_STATIC);
1647
1648     // Yuck. 
1649     if (language == french)
1650     {
1651         // "items"
1652         if (netgame && !deathmatch)
1653             items = W_CacheLumpName("WIOBJ", PU_STATIC);    
1654         else
1655             items = W_CacheLumpName("WIOSTI", PU_STATIC);
1656     } else
1657         items = W_CacheLumpName("WIOSTI", PU_STATIC);
1658
1659     // "frgs"
1660     frags = W_CacheLumpName("WIFRGS", PU_STATIC);    
1661
1662     // ":"
1663     colon = W_CacheLumpName("WICOLON", PU_STATIC); 
1664
1665     // "time"
1666     Time = W_CacheLumpName("WITIME", PU_STATIC);   
1667
1668     // "sucks"
1669     sucks = W_CacheLumpName("WISUCKS", PU_STATIC);  
1670
1671     // "par"
1672     par = W_CacheLumpName("WIPAR", PU_STATIC);   
1673
1674     // "killers" (vertical)
1675     killers = W_CacheLumpName("WIKILRS", PU_STATIC);
1676
1677     // "victims" (horiz)
1678     victims = W_CacheLumpName("WIVCTMS", PU_STATIC);
1679
1680     // "total"
1681     total = W_CacheLumpName("WIMSTT", PU_STATIC);   
1682
1683     // your face
1684     star = W_CacheLumpName("STFST01", PU_STATIC);
1685
1686     // dead face
1687     bstar = W_CacheLumpName("STFDEAD0", PU_STATIC);    
1688
1689     for (i=0 ; i<MAXPLAYERS ; i++)
1690     {
1691         // "1,2,3,4"
1692         sprintf(name, "STPB%d", i);      
1693         p[i] = W_CacheLumpName(name, PU_STATIC);
1694
1695         // "1,2,3,4"
1696         sprintf(name, "WIBP%d", i+1);     
1697         bp[i] = W_CacheLumpName(name, PU_STATIC);
1698     }
1699
1700 }
1701
1702 void WI_unloadData(void)
1703 {
1704     int         i;
1705     int         j;
1706
1707     Z_ChangeTag(wiminus, PU_CACHE);
1708
1709     for (i=0 ; i<10 ; i++)
1710         Z_ChangeTag(num[i], PU_CACHE);
1711     
1712     if (gamemode == commercial)
1713     {
1714         for (i=0 ; i<NUMCMAPS ; i++)
1715             Z_ChangeTag(lnames[i], PU_CACHE);
1716     }
1717     else
1718     {
1719         Z_ChangeTag(yah[0], PU_CACHE);
1720         Z_ChangeTag(yah[1], PU_CACHE);
1721
1722         Z_ChangeTag(splat, PU_CACHE);
1723
1724         for (i=0 ; i<NUMMAPS ; i++)
1725             Z_ChangeTag(lnames[i], PU_CACHE);
1726         
1727         if (wbs->epsd < 3)
1728         {
1729             for (j=0;j<NUMANIMS[wbs->epsd];j++)
1730             {
1731                 if (wbs->epsd != 1 || j != 8)
1732                     for (i=0;i<anims[wbs->epsd][j].nanims;i++)
1733                         Z_ChangeTag(anims[wbs->epsd][j].p[i], PU_CACHE);
1734             }
1735         }
1736     }
1737     
1738     Z_Free(lnames);
1739
1740     Z_ChangeTag(percent, PU_CACHE);
1741     Z_ChangeTag(colon, PU_CACHE);
1742     Z_ChangeTag(finished, PU_CACHE);
1743     Z_ChangeTag(entering, PU_CACHE);
1744     Z_ChangeTag(kills, PU_CACHE);
1745     Z_ChangeTag(secret, PU_CACHE);
1746     Z_ChangeTag(sp_secret, PU_CACHE);
1747     Z_ChangeTag(items, PU_CACHE);
1748     Z_ChangeTag(frags, PU_CACHE);
1749     Z_ChangeTag(Time, PU_CACHE);
1750     Z_ChangeTag(sucks, PU_CACHE);
1751     Z_ChangeTag(par, PU_CACHE);
1752
1753     Z_ChangeTag(victims, PU_CACHE);
1754     Z_ChangeTag(killers, PU_CACHE);
1755     Z_ChangeTag(total, PU_CACHE);
1756     //  Z_ChangeTag(star, PU_CACHE);
1757     //  Z_ChangeTag(bstar, PU_CACHE);
1758     
1759     for (i=0 ; i<MAXPLAYERS ; i++)
1760         Z_ChangeTag(p[i], PU_CACHE);
1761
1762     for (i=0 ; i<MAXPLAYERS ; i++)
1763         Z_ChangeTag(bp[i], PU_CACHE);
1764 }
1765
1766 void WI_Drawer (void)
1767 {
1768     switch (state)
1769     {
1770       case StatCount:
1771         if (deathmatch)
1772             WI_drawDeathmatchStats();
1773         else if (netgame)
1774             WI_drawNetgameStats();
1775         else
1776             WI_drawStats();
1777         break;
1778         
1779       case ShowNextLoc:
1780         WI_drawShowNextLoc();
1781         break;
1782         
1783       case NoState:
1784         WI_drawNoState();
1785         break;
1786     }
1787 }
1788
1789
1790 void WI_initVariables(wbstartstruct_t* wbstartstruct)
1791 {
1792
1793     wbs = wbstartstruct;
1794
1795 #ifdef RANGECHECKING
1796     if (gamemode != commercial)
1797     {
1798       if ( gamemode == retail )
1799         RNGCHECK(wbs->epsd, 0, 3);
1800       else
1801         RNGCHECK(wbs->epsd, 0, 2);
1802     }
1803     else
1804     {
1805         RNGCHECK(wbs->last, 0, 8);
1806         RNGCHECK(wbs->next, 0, 8);
1807     }
1808     RNGCHECK(wbs->pnum, 0, MAXPLAYERS);
1809     RNGCHECK(wbs->pnum, 0, MAXPLAYERS);
1810 #endif
1811
1812     acceleratestage = 0;
1813     cnt = bcnt = 0;
1814     firstrefresh = 1;
1815     me = wbs->pnum;
1816     plrs = wbs->plyr;
1817
1818     if (!wbs->maxkills)
1819         wbs->maxkills = 1;
1820
1821     if (!wbs->maxitems)
1822         wbs->maxitems = 1;
1823
1824     if (!wbs->maxsecret)
1825         wbs->maxsecret = 1;
1826
1827     if ( gamemode != retail )
1828       if (wbs->epsd > 2)
1829         wbs->epsd -= 3;
1830 }
1831
1832 void WI_Start(wbstartstruct_t* wbstartstruct)
1833 {
1834
1835     WI_initVariables(wbstartstruct);
1836     WI_loadData();
1837
1838     if (deathmatch)
1839         WI_initDeathmatchStats();
1840     else if (netgame)
1841         WI_initNetgameStats();
1842     else
1843         WI_initStats();
1844 }