DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

wi_stuff.cpp (35681B)


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