Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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