DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

st_stuff.cpp (30640B)


      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 
     32 
     33 #include <stdio.h>
     34 
     35 #include "i_system.h"
     36 #include "i_video.h"
     37 #include "z_zone.h"
     38 #include "m_random.h"
     39 #include "w_wad.h"
     40 
     41 #include "doomdef.h"
     42 
     43 #include "g_game.h"
     44 
     45 #include "st_stuff.h"
     46 #include "st_lib.h"
     47 #include "r_local.h"
     48 
     49 #include "p_local.h"
     50 #include "p_inter.h"
     51 
     52 #include "am_map.h"
     53 #include "m_cheat.h"
     54 
     55 #include "s_sound.h"
     56 
     57 // Needs access to LFB.
     58 #include "v_video.h"
     59 
     60 // State.
     61 #include "doomstat.h"
     62 
     63 // Data.
     64 #include "dstrings.h"
     65 #include "sounds.h"
     66 
     67 //
     68 // STATUS BAR DATA
     69 //
     70 
     71 
     72 // Palette indices.
     73 // For damage/bonus red-/gold-shifts
     74 // Radiation suit, green shift.
     75 
     76 // N/256*100% probability
     77 //  that the normal face state will change
     78 
     79 // For Responder
     80 
     81 // Location of status bar
     82 
     83 
     84 // Should be set to patch width
     85 //  for tall numbers later on
     86 
     87 // Number of status ::g->faces.
     88 
     89 
     90 
     91 
     92 
     93 
     94 
     95 
     96 
     97 // Location and size of statistics,
     98 //  justified according to widget type.
     99 // Problem is, within which space? STbar? Screen?
    100 // Note: this could be read in by a lump.
    101 //       Problem is, is the stuff rendered
    102 //       into a buffer,
    103 //       or into the frame buffer?
    104 
    105 // AMMO number pos.
    106 
    107 // HEALTH number pos.
    108 
    109 // Weapon pos.
    110 
    111 // Frags pos.
    112 
    113 // ARMOR number pos.
    114 
    115 // Key icon positions.
    116 
    117 // Ammunition counter.
    118 
    119 // Indicate maximum ammunition.
    120 // Only needed because backpack exists.
    121 
    122 // pistol
    123 
    124 // shotgun
    125 
    126 // chain gun
    127 
    128 // missile launcher
    129 
    130 // plasma gun
    131 
    132 // bfg
    133 
    134 // WPNS title
    135 
    136 // DETH title
    137 
    138 //Incoming messages window location
    139 //UNUSED
    140 // #define ST_MSGTEXTX	   (::g->viewwindowx)
    141 // #define ST_MSGTEXTY	   (::g->viewwindowy+::g->viewheight-18)
    142 // Dimensions given in characters.
    143 // Or shall I say, in lines?
    144 
    145 
    146 // Width, in characters again.
    147 // Height, in ::g->lines. 
    148 
    149 
    150 
    151 
    152 
    153 // main player in game
    154 
    155 // ST_Start() has just been called
    156 
    157 // used to execute ST_Init() only once
    158 
    159 // lump number for PLAYPAL
    160 
    161 // used for timing
    162 
    163 // used for making messages go away
    164 
    165 // used when in chat 
    166 
    167 // States for the intermission
    168 
    169 
    170 // whether in automap or first-person
    171 
    172 // whether left-side main status bar is active
    173 
    174 // whether status bar chat is active
    175 
    176 // value of ::g->st_chat before message popped up
    177 
    178 // whether chat window has the cursor on
    179 
    180 // !::g->deathmatch
    181 
    182 // !::g->deathmatch && ::g->st_statusbaron
    183 
    184 // !::g->deathmatch
    185 
    186 // main bar left
    187 
    188 // 0-9, tall numbers
    189 
    190 // tall % sign
    191 
    192 // 0-9, short, yellow (,different!) numbers
    193 
    194 // 3 key-cards, 3 skulls
    195 
    196 // face status patches
    197 
    198 // face background
    199 
    200 // main bar right
    201 
    202 // weapon ownership patches
    203 
    204 // ready-weapon widget
    205 
    206 // in ::g->deathmatch only, summary of frags stats
    207 
    208 // health widget
    209 
    210 // ::g->arms background
    211 
    212 
    213 // weapon ownership widgets
    214 
    215 // face status widget
    216 
    217 // keycard widgets
    218 
    219 // armor widget
    220 
    221 // ammo widgets
    222 
    223 // max ammo widgets
    224 
    225 
    226 
    227 // number of frags so far in ::g->deathmatch
    228 
    229 // used to use appopriately pained face
    230 
    231 // used for evil grin
    232 
    233 // count until face changes
    234 
    235 // current face index, used by ::g->w_faces
    236 
    237 // holds key-type for each key box on bar
    238 
    239 // a random number per tick
    240 
    241 
    242 
    243 // Massive bunches of cheat shit
    244 //  to keep it from being easy to figure them out.
    245 // Yeah, right...
    246 const unsigned char	cheat_mus_seq[] =
    247 {
    248 	0xb2, 0x26, 0xb6, 0xae, 0xea, 1, 0, 0, 0xff
    249 };
    250 
    251 const unsigned char	cheat_choppers_seq[] =
    252 {
    253 	0xb2, 0x26, 0xe2, 0x32, 0xf6, 0x2a, 0x2a, 0xa6, 0x6a, 0xea, 0xff // id...
    254 };
    255 
    256 const unsigned char	cheat_god_seq[] =
    257 {
    258 	0xb2, 0x26, 0x26, 0xaa, 0x26, 0xff  // iddqd
    259 };
    260 
    261 const unsigned char	cheat_ammo_seq[] =
    262 {
    263 	0xb2, 0x26, 0xf2, 0x66, 0xa2, 0xff	// idkfa
    264 };
    265 
    266 const unsigned char	cheat_ammonokey_seq[] =
    267 {
    268 	0xb2, 0x26, 0x66, 0xa2, 0xff	// idfa
    269 };
    270 
    271 
    272 // Smashing Pumpkins Into Samml Piles Of Putried Debris. 
    273 const unsigned char	cheat_noclip_seq[] =
    274 {
    275 	0xb2, 0x26, 0xea, 0x2a, 0xb2,	// idspispopd
    276 		0xea, 0x2a, 0xf6, 0x2a, 0x26, 0xff
    277 };
    278 
    279 //
    280 const unsigned char	cheat_commercial_noclip_seq[] =
    281 {
    282 	0xb2, 0x26, 0xe2, 0x36, 0xb2, 0x2a, 0xff	// idclip
    283 }; 
    284 
    285 
    286 
    287 const unsigned char	cheat_powerup_seq[7][10] =
    288 {
    289 	{ 0xb2, 0x26, 0x62, 0xa6, 0x32, 0xf6, 0x36, 0x26, 0x6e, 0xff }, 	// beholdv
    290 	{ 0xb2, 0x26, 0x62, 0xa6, 0x32, 0xf6, 0x36, 0x26, 0xea, 0xff }, 	// beholds
    291 	{ 0xb2, 0x26, 0x62, 0xa6, 0x32, 0xf6, 0x36, 0x26, 0xb2, 0xff }, 	// beholdi
    292 	{ 0xb2, 0x26, 0x62, 0xa6, 0x32, 0xf6, 0x36, 0x26, 0x6a, 0xff }, 	// beholdr
    293 	{ 0xb2, 0x26, 0x62, 0xa6, 0x32, 0xf6, 0x36, 0x26, 0xa2, 0xff }, 	// beholda
    294 	{ 0xb2, 0x26, 0x62, 0xa6, 0x32, 0xf6, 0x36, 0x26, 0x36, 0xff }, 	// beholdl
    295 	{ 0xb2, 0x26, 0x62, 0xa6, 0x32, 0xf6, 0x36, 0x26, 0xff }		// behold
    296 };
    297 
    298 
    299 const unsigned char	cheat_clev_seq[] =
    300 {
    301 	0xb2, 0x26,  0xe2, 0x36, 0xa6, 0x6e, 1, 0, 0, 0xff	// idclev
    302 };
    303 
    304 
    305 // my position cheat
    306 const unsigned char	cheat_mypos_seq[] =
    307 {
    308 	0xb2, 0x26, 0xb6, 0xba, 0x2a, 0xf6, 0xea, 0xff	// idmypos
    309 }; 
    310 
    311 
    312 // Now what?
    313 cheatseq_t	cheat_mus = cheatseq_t( cheat_mus_seq, 0 );
    314 cheatseq_t	cheat_god = cheatseq_t( cheat_god_seq, 0 );
    315 cheatseq_t	cheat_ammo = cheatseq_t( cheat_ammo_seq, 0 );
    316 cheatseq_t	cheat_ammonokey = cheatseq_t( cheat_ammonokey_seq, 0 );
    317 cheatseq_t	cheat_noclip = cheatseq_t( cheat_noclip_seq, 0 );
    318 cheatseq_t	cheat_commercial_noclip = cheatseq_t( cheat_commercial_noclip_seq, 0 );
    319 
    320 // ALAN
    321 
    322 // DISABLED cheatseq_t( cheat_powerup_seq[0], 0 ), cheatseq_t( cheat_powerup_seq[1], 0 ),
    323 // cheatseq_t( cheat_powerup_seq[2], 0 ),
    324 // DISABLED cheatseq_t( cheat_powerup_seq[3], 0 ), 
    325 // cheatseq_t( cheat_powerup_seq[4], 0 ),cheatseq_t( cheat_powerup_seq[5], 0 ),cheatseq_t( cheat_powerup_seq[6], 0 ) };
    326 
    327 cheatseq_t	cheat_choppers = cheatseq_t( cheat_choppers_seq, 0 );
    328 cheatseq_t	cheat_clev = cheatseq_t( cheat_clev_seq, 0 );
    329 cheatseq_t	cheat_mypos = cheatseq_t( cheat_mypos_seq, 0 );
    330 
    331 
    332 // 
    333 const extern char*	mapnames[];
    334 
    335 
    336 //
    337 // STATUS BAR CODE
    338 //
    339 void ST_Stop(void);
    340 
    341 void ST_refreshBackground(void)
    342 {
    343 
    344 	if (::g->st_statusbaron)
    345 	{
    346 		V_DrawPatch(ST_X, 0, BG, ::g->sbar);
    347 
    348 		if (::g->netgame)
    349 			V_DrawPatch(ST_FX, 0, BG, ::g->faceback);
    350 
    351 		V_CopyRect(ST_X, 0, BG, ST_WIDTH, ST_HEIGHT, ST_X, ST_Y, FG);
    352 	}
    353 
    354 }
    355 
    356 
    357 // Respond to keyboard input ::g->events,
    358 //  intercept cheats.
    359 qboolean
    360 ST_Responder (event_t* ev)
    361 {
    362 	int		i;
    363 
    364 	// Filter automap on/off.
    365 	if (ev->type == ev_keyup
    366 		&& ((ev->data1 & 0xffff0000) == AM_MSGHEADER))
    367 	{
    368 		switch(ev->data1)
    369 		{
    370 		case AM_MSGENTERED:
    371 			::g->st_gamestate = AutomapState;
    372 			::g->st_firsttime = true;
    373 			break;
    374 
    375 		case AM_MSGEXITED:
    376 			//	I_PrintfE( "AM exited\n");
    377 			::g->st_gamestate = FirstPersonState;
    378 			break;
    379 		}
    380 	}
    381 
    382 	// if a user keypress...
    383 	else if (ev->type == ev_keydown)
    384 	{
    385 		if (!::g->netgame)
    386 		{
    387 			// b. - enabled for more debug fun.
    388 			// if (::g->gameskill != sk_nightmare) {
    389 
    390 			// 'dqd' cheat for toggleable god mode
    391 			if (cht_CheckCheat(&cheat_god, ev->data1))
    392 			{
    393 				::g->plyr->cheats ^= CF_GODMODE;
    394 				if (::g->plyr->cheats & CF_GODMODE)
    395 				{
    396 					if (::g->plyr->mo)
    397 						::g->plyr->mo->health = 100;
    398 
    399 					::g->plyr->health = 100;
    400 					::g->plyr->message = STSTR_DQDON;
    401 				}
    402 				else 
    403 					::g->plyr->message = STSTR_DQDOFF;
    404 			}
    405 			// 'fa' cheat for killer fucking arsenal
    406 			else if (cht_CheckCheat(&cheat_ammonokey, ev->data1))
    407 			{
    408 				::g->plyr->armorpoints = 200;
    409 				::g->plyr->armortype = 2;
    410 
    411 				for (i=0;i<NUMWEAPONS;i++)
    412 					::g->plyr->weaponowned[i] = true;
    413 
    414 				for (i=0;i<NUMAMMO;i++)
    415 					::g->plyr->ammo[i] = ::g->plyr->maxammo[i];
    416 
    417 				::g->plyr->message = STSTR_FAADDED;
    418 			}
    419 			// 'kfa' cheat for key full ammo
    420 			else if (cht_CheckCheat(&cheat_ammo, ev->data1))
    421 			{
    422 				::g->plyr->armorpoints = 200;
    423 				::g->plyr->armortype = 2;
    424 
    425 				for (i=0;i<NUMWEAPONS;i++)
    426 					::g->plyr->weaponowned[i] = true;
    427 
    428 				for (i=0;i<NUMAMMO;i++)
    429 					::g->plyr->ammo[i] = ::g->plyr->maxammo[i];
    430 
    431 				for (i=0;i<NUMCARDS;i++)
    432 					::g->plyr->cards[i] = true;
    433 
    434 				::g->plyr->message = STSTR_KFAADDED;
    435 			}
    436 			// 'mus' cheat for changing music
    437 			else if (cht_CheckCheat(&cheat_mus, ev->data1))
    438 			{
    439 
    440 				char	buf[3];
    441 				int		musnum;
    442 
    443 				::g->plyr->message = STSTR_MUS;
    444 				cht_GetParam(&cheat_mus, buf);
    445 
    446 				if (::g->gamemode == commercial)
    447 				{
    448 					musnum = mus_runnin + (buf[0]-'0')*10 + buf[1]-'0' - 1;
    449 
    450 					if (((buf[0]-'0')*10 + buf[1]-'0') > 35)
    451 						::g->plyr->message = STSTR_NOMUS;
    452 					else
    453 						S_ChangeMusic(musnum, 1);
    454 				}
    455 				else
    456 				{
    457 					musnum = mus_e1m1 + (buf[0]-'1')*9 + (buf[1]-'1');
    458 
    459 					if (((buf[0]-'1')*9 + buf[1]-'1') > 31)
    460 						::g->plyr->message = STSTR_NOMUS;
    461 					else
    462 						S_ChangeMusic(musnum, 1);
    463 				}
    464 			}
    465 			// Simplified, accepting both "noclip" and "idspispopd".
    466 			// no clipping mode cheat
    467 			else if ( cht_CheckCheat(&cheat_noclip, ev->data1) 
    468 				|| cht_CheckCheat(&cheat_commercial_noclip,ev->data1) )
    469 			{	
    470 				::g->plyr->cheats ^= CF_NOCLIP;
    471 
    472 				if (::g->plyr->cheats & CF_NOCLIP)
    473 					::g->plyr->message = STSTR_NCON;
    474 				else
    475 					::g->plyr->message = STSTR_NCOFF;
    476 			}
    477 			// 'behold?' power-up cheats
    478 			for (i=0;i<6;i++)
    479 			{
    480 				if (cht_CheckCheat(&::g->cheat_powerup[i], ev->data1))
    481 				{
    482 					if (!::g->plyr->powers[i])
    483 						P_GivePower( ::g->plyr, i);
    484 					else if (i!=pw_strength)
    485 						::g->plyr->powers[i] = 1;
    486 					else
    487 						::g->plyr->powers[i] = 0;
    488 
    489 					::g->plyr->message = STSTR_BEHOLDX;
    490 				}
    491 			}
    492 
    493 			// 'behold' power-up menu
    494 			if (cht_CheckCheat(&::g->cheat_powerup[6], ev->data1))
    495 			{
    496 				::g->plyr->message = STSTR_BEHOLD;
    497 			}
    498 			// 'choppers' invulnerability & chainsaw
    499 			else if (cht_CheckCheat(&cheat_choppers, ev->data1))
    500 			{
    501 				::g->plyr->weaponowned[wp_chainsaw] = true;
    502 				::g->plyr->powers[pw_invulnerability] = true;
    503 				::g->plyr->message = STSTR_CHOPPERS;
    504 			}
    505 			// 'mypos' for player position
    506 			else if (cht_CheckCheat(&cheat_mypos, ev->data1))
    507 			{
    508 				static char	buf[ST_MSGWIDTH];
    509 				sprintf(buf, "ang=0x%x;x,y=(0x%x,0x%x)",
    510 					::g->players[::g->consoleplayer].mo->angle,
    511 					::g->players[::g->consoleplayer].mo->x,
    512 					::g->players[::g->consoleplayer].mo->y);
    513 				::g->plyr->message = buf;
    514 			}
    515 		}
    516 
    517 		// 'clev' change-level cheat
    518 // ALAN NETWORKING
    519 		if (false) // cht_CheckCheat(&cheat_clev, ev->data1))
    520 		{
    521 			char		buf[3];
    522 			int		epsd;
    523 			int		map;
    524 
    525 			cht_GetParam(&cheat_clev, buf);
    526 
    527 			if (::g->gamemode == commercial)
    528 			{
    529 				epsd = 0;
    530 				map = (buf[0] - '0')*10 + buf[1] - '0';
    531 			}
    532 			else
    533 			{
    534 				epsd = buf[0] - '0';
    535 				map = buf[1] - '0';
    536 			}
    537 
    538 			// Catch invalid maps.
    539 			if (epsd < 1)
    540 				return false;
    541 
    542 			if (map < 1)
    543 				return false;
    544 
    545 			// Ohmygod - this is not going to work.
    546 			if ((::g->gamemode == retail)
    547 				&& ((epsd > 4) || (map > 9)))
    548 				return false;
    549 
    550 			if ((::g->gamemode == registered)
    551 				&& ((epsd > 3) || (map > 9)))
    552 				return false;
    553 
    554 			if ((::g->gamemode == shareware)
    555 				&& ((epsd > 1) || (map > 9)))
    556 				return false;
    557 
    558 			if ((::g->gamemode == commercial)
    559 				&& (( epsd > 1) || (map > 34)))
    560 				return false;
    561 
    562 			// So be it.
    563 			::g->plyr->message = STSTR_CLEV;
    564 			G_DeferedInitNew(::g->gameskill, epsd, map);
    565 		}    
    566 	}
    567 	return false;
    568 }
    569 
    570 
    571 
    572 int ST_calcPainOffset(void)
    573 {
    574 	int		health;
    575 
    576 	health = ::g->plyr->health > 100 ? 100 : ::g->plyr->health;
    577 
    578 	if (health != ::g->oldhealth)
    579 	{
    580 		::g->lastcalc = ST_FACESTRIDE * (((100 - health) * ST_NUMPAINFACES) / 101);
    581 		::g->oldhealth = health;
    582 	}
    583 	return ::g->lastcalc;
    584 }
    585 
    586 
    587 //
    588 // This is a not-very-pretty routine which handles
    589 //  the face states and their timing.
    590 // the precedence of expressions is:
    591 //  dead > evil grin > turned head > straight ahead
    592 //
    593 void ST_updateFaceWidget(void)
    594 {
    595 	int		i;
    596 	angle_t	badguyangle;
    597 	angle_t	diffang;
    598 	qboolean	doevilgrin;
    599 
    600 	if (::g->priority < 10)
    601 	{
    602 		// dead
    603 		if (!::g->plyr->health)
    604 		{
    605 			::g->priority = 9;
    606 			::g->st_faceindex = ST_DEADFACE;
    607 			::g->st_facecount = 1;
    608 		}
    609 	}
    610 
    611 	if (::g->priority < 9)
    612 	{
    613 		if (::g->plyr->bonuscount)
    614 		{
    615 			// picking up bonus
    616 			doevilgrin = false;
    617 
    618 			for (i=0;i<NUMWEAPONS;i++)
    619 			{
    620 				if (::g->oldweaponsowned[i] != ::g->plyr->weaponowned[i])
    621 				{
    622 					doevilgrin = true;
    623 					::g->oldweaponsowned[i] = ::g->plyr->weaponowned[i];
    624 				}
    625 			}
    626 			if (doevilgrin) 
    627 			{
    628 				// evil grin if just picked up weapon
    629 				::g->priority = 8;
    630 				::g->st_facecount = ST_EVILGRINCOUNT;
    631 				::g->st_faceindex = ST_calcPainOffset() + ST_EVILGRINOFFSET;
    632 			}
    633 		}
    634 
    635 	}
    636 
    637 	if (::g->priority < 8)
    638 	{
    639 		if (::g->plyr->damagecount
    640 			&& ::g->plyr->attacker
    641 			&& ::g->plyr->attacker != ::g->plyr->mo)
    642 		{
    643 			// being attacked
    644 			::g->priority = 7;
    645 
    646 			if (::g->plyr->health - ::g->st_oldhealth > ST_MUCHPAIN)
    647 			{
    648 				::g->st_facecount = ST_TURNCOUNT;
    649 				::g->st_faceindex = ST_calcPainOffset() + ST_OUCHOFFSET;
    650 			}
    651 			else
    652 			{
    653 				badguyangle = R_PointToAngle2(::g->plyr->mo->x,
    654 					::g->plyr->mo->y,
    655 					::g->plyr->attacker->x,
    656 					::g->plyr->attacker->y);
    657 
    658 				if (badguyangle > ::g->plyr->mo->angle)
    659 				{
    660 					// whether right or left
    661 					diffang = badguyangle - ::g->plyr->mo->angle;
    662 					i = diffang > ANG180; 
    663 				}
    664 				else
    665 				{
    666 					// whether left or right
    667 					diffang = ::g->plyr->mo->angle - badguyangle;
    668 					i = diffang <= ANG180; 
    669 				} // confusing, aint it?
    670 
    671 
    672 				::g->st_facecount = ST_TURNCOUNT;
    673 				::g->st_faceindex = ST_calcPainOffset();
    674 
    675 				if (diffang < ANG45)
    676 				{
    677 					// head-on    
    678 					::g->st_faceindex += ST_RAMPAGEOFFSET;
    679 				}
    680 				else if (i)
    681 				{
    682 					// turn face right
    683 					::g->st_faceindex += ST_TURNOFFSET;
    684 				}
    685 				else
    686 				{
    687 					// turn face left
    688 					::g->st_faceindex += ST_TURNOFFSET+1;
    689 				}
    690 			}
    691 		}
    692 	}
    693 
    694 	if (::g->priority < 7)
    695 	{
    696 		// getting hurt because of your own damn stupidity
    697 		if (::g->plyr->damagecount)
    698 		{
    699 			if (::g->plyr->health - ::g->st_oldhealth > ST_MUCHPAIN)
    700 			{
    701 				::g->priority = 7;
    702 				::g->st_facecount = ST_TURNCOUNT;
    703 				::g->st_faceindex = ST_calcPainOffset() + ST_OUCHOFFSET;
    704 			}
    705 			else
    706 			{
    707 				::g->priority = 6;
    708 				::g->st_facecount = ST_TURNCOUNT;
    709 				::g->st_faceindex = ST_calcPainOffset() + ST_RAMPAGEOFFSET;
    710 			}
    711 
    712 		}
    713 
    714 	}
    715 
    716 	if (::g->priority < 6)
    717 	{
    718 		// rapid firing
    719 		if (::g->plyr->attackdown)
    720 		{
    721 			if (::g->lastattackdown==-1)
    722 				::g->lastattackdown = ST_RAMPAGEDELAY;
    723 			else if (!--::g->lastattackdown)
    724 			{
    725 				::g->priority = 5;
    726 				::g->st_faceindex = ST_calcPainOffset() + ST_RAMPAGEOFFSET;
    727 				::g->st_facecount = 1;
    728 				::g->lastattackdown = 1;
    729 			}
    730 		}
    731 		else
    732 			::g->lastattackdown = -1;
    733 
    734 	}
    735 
    736 	if (::g->priority < 5)
    737 	{
    738 		// invulnerability
    739 		if ((::g->plyr->cheats & CF_GODMODE)
    740 			|| ::g->plyr->powers[pw_invulnerability])
    741 		{
    742 			::g->priority = 4;
    743 
    744 			::g->st_faceindex = ST_GODFACE;
    745 			::g->st_facecount = 1;
    746 
    747 		}
    748 
    749 	}
    750 
    751 	// look left or look right if the facecount has timed out
    752 	if (!::g->st_facecount)
    753 	{
    754 		::g->st_faceindex = ST_calcPainOffset() + (::g->st_randomnumber % 3);
    755 		::g->st_facecount = ST_STRAIGHTFACECOUNT;
    756 		::g->priority = 0;
    757 	}
    758 
    759 	::g->st_facecount--;
    760 
    761 }
    762 
    763 void ST_updateWidgets(void)
    764 {
    765 	int		i;
    766 
    767 	// must redirect the pointer if the ready weapon has changed.
    768 	//  if (::g->w_ready.data != ::g->plyr->readyweapon)
    769 	//  {
    770 	if (weaponinfo[::g->plyr->readyweapon].ammo == am_noammo)
    771 		::g->w_ready.num = &::g->largeammo;
    772 	else
    773 		::g->w_ready.num = &::g->plyr->ammo[weaponinfo[::g->plyr->readyweapon].ammo];
    774 	//{
    775 	// static int tic=0;
    776 	// static int dir=-1;
    777 	// if (!(tic&15))
    778 	//   ::g->plyr->ammo[weaponinfo[::g->plyr->readyweapon].ammo]+=dir;
    779 	// if (::g->plyr->ammo[weaponinfo[::g->plyr->readyweapon].ammo] == -100)
    780 	//   dir = 1;
    781 	// tic++;
    782 	// }
    783 	::g->w_ready.data = ::g->plyr->readyweapon;
    784 
    785 	// if (*::g->w_ready.on)
    786 	//  STlib_updateNum(&::g->w_ready, true);
    787 	// refresh weapon change
    788 	//  }
    789 
    790 	// update keycard multiple widgets
    791 	for (i=0;i<3;i++)
    792 	{
    793 		::g->keyboxes[i] = ::g->plyr->cards[i] ? i : -1;
    794 
    795 		if (::g->plyr->cards[i+3])
    796 			::g->keyboxes[i] = i+3;
    797 	}
    798 
    799 	// refresh everything if this is him coming back to life
    800 	ST_updateFaceWidget();
    801 
    802 	// used by the ::g->w_armsbg widget
    803 	::g->st_notdeathmatch = !::g->deathmatch;
    804 
    805 	// used by ::g->w_arms[] widgets
    806 	::g->st_armson = ::g->st_statusbaron && !::g->deathmatch; 
    807 
    808 	// used by ::g->w_frags widget
    809 	::g->st_fragson = ::g->deathmatch && ::g->st_statusbaron; 
    810 	::g->st_fragscount = 0;
    811 
    812 	for (i=0 ; i<MAXPLAYERS ; i++)
    813 	{
    814 		if (i != ::g->consoleplayer)
    815 			::g->st_fragscount += ::g->plyr->frags[i];
    816 		else
    817 			::g->st_fragscount -= ::g->plyr->frags[i];
    818 	}
    819 
    820 	// get rid of chat window if up because of message
    821 	if (!--::g->st_msgcounter)
    822 		::g->st_chat = ::g->st_oldchat;
    823 
    824 }
    825 
    826 void ST_Ticker (void)
    827 {
    828 
    829 	::g->st_clock++;
    830 	::g->st_randomnumber = M_Random();
    831 	ST_updateWidgets();
    832 	::g->st_oldhealth = ::g->plyr->health;
    833 
    834 }
    835 
    836 
    837 void ST_doPaletteStuff(void)
    838 {
    839 
    840 	int		palette;
    841 	byte*	pal;
    842 	int		cnt;
    843 	int		bzc;
    844 
    845 	cnt = ::g->plyr->damagecount;
    846 
    847 	if (::g->plyr->powers[pw_strength])
    848 	{
    849 		// slowly fade the berzerk out
    850 		bzc = 12 - (::g->plyr->powers[pw_strength]>>6);
    851 
    852 		if (bzc > cnt)
    853 			cnt = bzc;
    854 	}
    855 
    856 	if (cnt)
    857 	{
    858 		palette = (cnt+7)>>3;
    859 
    860 		if (palette >= NUMREDPALS)
    861 			palette = NUMREDPALS-1;
    862 
    863 		palette += STARTREDPALS;
    864 	}
    865 
    866 	else if (::g->plyr->bonuscount)
    867 	{
    868 		palette = (::g->plyr->bonuscount+7)>>3;
    869 
    870 		if (palette >= NUMBONUSPALS)
    871 			palette = NUMBONUSPALS-1;
    872 
    873 		palette += STARTBONUSPALS;
    874 	}
    875 
    876 	else if ( ::g->plyr->powers[pw_ironfeet] > 4*32
    877 		|| ::g->plyr->powers[pw_ironfeet]&8)
    878 		palette = RADIATIONPAL;
    879 	else
    880 		palette = 0;
    881 
    882 	if (palette != ::g->st_palette)
    883 	{
    884 		::g->st_palette = palette;
    885 		pal = (byte *) W_CacheLumpNum (::g->lu_palette, PU_CACHE_SHARED)+palette*768;
    886 		I_SetPalette (pal);
    887 	}
    888 
    889 }
    890 
    891 void ST_drawWidgets(qboolean refresh)
    892 {
    893 	int		i;
    894 
    895 	::g->st_notdeathmatch = !::g->deathmatch;
    896 
    897 	// used by ::g->w_arms[] widgets
    898 	::g->st_armson = ::g->st_statusbaron && !::g->deathmatch;
    899 
    900 	// used by ::g->w_frags widget
    901 	::g->st_fragson = ::g->deathmatch && ::g->st_statusbaron; 
    902 
    903 	STlib_updateNum(&::g->w_ready, refresh);
    904 
    905 	for (i=0;i<4;i++)
    906 	{
    907 		STlib_updateNum(&::g->w_ammo[i], refresh);
    908 		STlib_updateNum(&::g->w_maxammo[i], refresh);
    909 	}
    910 
    911 	STlib_updatePercent(&::g->w_health, refresh);
    912 	STlib_updatePercent(&::g->w_armor, refresh);
    913 
    914 	STlib_updateBinIcon(&::g->w_armsbg, refresh);
    915 
    916 	for (i=0;i<6;i++)
    917 		STlib_updateMultIcon(&::g->w_arms[i], refresh);
    918 
    919 	STlib_updateMultIcon(&::g->w_faces, refresh);
    920 
    921 	for (i=0;i<3;i++)
    922 		STlib_updateMultIcon(&::g->w_keyboxes[i], refresh);
    923 
    924 	STlib_updateNum(&::g->w_frags, refresh);
    925 
    926 }
    927 
    928 void ST_doRefresh(void)
    929 {
    930 	::g->st_firsttime = false;
    931 
    932 	// draw status bar background to off-screen buff
    933 	ST_refreshBackground();
    934 
    935 	// and refresh all widgets
    936 	ST_drawWidgets(true);
    937 }
    938 
    939 void ST_diffDraw(void)
    940 {
    941 	// update all widgets
    942 	ST_drawWidgets(false);
    943 }
    944 
    945 void ST_Drawer (qboolean fullscreen, qboolean refresh)
    946 {
    947 	::g->st_statusbaron = (!fullscreen) || ::g->automapactive;
    948 	::g->st_firsttime = ::g->st_firsttime || refresh;
    949 
    950 	// Do red-/gold-shifts from damage/items
    951 	ST_doPaletteStuff();
    952 
    953 	// If just after ST_Start(), refresh all
    954 	if (::g->st_firsttime) ST_doRefresh();
    955 	// Otherwise, update as little as possible
    956 	else ST_diffDraw();
    957 }
    958 
    959 void ST_loadGraphics(void)
    960 {
    961 	static bool ST_HasBeenCalled = false;
    962 
    963 //	if (ST_HasBeenCalled == true)
    964 //		return;
    965 	ST_HasBeenCalled = true;
    966 	
    967 	int		i;
    968 	int		j;
    969 	int		facenum;
    970 
    971 	char	namebuf[9];
    972 
    973 	// Load the numbers, tall and short
    974 	for (i=0;i<10;i++)
    975 	{
    976 		sprintf(namebuf, "STTNUM%d", i);
    977 		::g->tallnum[i] = (patch_t *) W_CacheLumpName(namebuf, PU_STATIC_SHARED);
    978 
    979 		sprintf(namebuf, "STYSNUM%d", i);
    980 		::g->shortnum[i] = (patch_t *) W_CacheLumpName(namebuf, PU_STATIC_SHARED);
    981 	}
    982 
    983 	// Load percent key.
    984 	//Note: why not load STMINUS here, too?
    985 	::g->tallpercent = (patch_t *) W_CacheLumpName("STTPRCNT", PU_STATIC_SHARED);
    986 
    987 	// key cards
    988 	for (i=0;i<NUMCARDS;i++)
    989 	{
    990 		sprintf(namebuf, "STKEYS%d", i);
    991 		::g->keys[i] = (patch_t *) W_CacheLumpName(namebuf, PU_STATIC_SHARED);
    992 	}
    993 
    994 	// ::g->arms background
    995 	::g->armsbg = (patch_t *) W_CacheLumpName("STARMS", PU_STATIC_SHARED);
    996 
    997 	// ::g->arms ownership widgets
    998 	for (i=0;i<6;i++)
    999 	{
   1000 		sprintf(namebuf, "STGNUM%d", i+2);
   1001 
   1002 		// gray #
   1003 		::g->arms[i][0] = (patch_t *) W_CacheLumpName(namebuf, PU_STATIC_SHARED);
   1004 
   1005 		// yellow #
   1006 		::g->arms[i][1] = ::g->shortnum[i+2]; 
   1007 	}
   1008 
   1009 	// face backgrounds for different color ::g->players
   1010 	sprintf(namebuf, "STFB%d", ::g->consoleplayer);
   1011 	::g->faceback = (patch_t *) W_CacheLumpName(namebuf, PU_STATIC_SHARED);
   1012 
   1013 	// status bar background bits
   1014 	::g->sbar = (patch_t *) W_CacheLumpName("STBAR", PU_STATIC_SHARED);
   1015 
   1016 	// face states
   1017 	facenum = 0;
   1018 	for (i=0;i<ST_NUMPAINFACES;i++)
   1019 	{
   1020 		for (j=0;j<ST_NUMSTRAIGHTFACES;j++)
   1021 		{
   1022 			sprintf(namebuf, "STFST%d%d", i, j);
   1023 			::g->faces[facenum++] = (patch_t*)W_CacheLumpName(namebuf, PU_STATIC_SHARED);
   1024 		}
   1025 		sprintf(namebuf, "STFTR%d0", i);	// turn right
   1026 		::g->faces[facenum++] = (patch_t*)W_CacheLumpName(namebuf, PU_STATIC_SHARED);
   1027 		sprintf(namebuf, "STFTL%d0", i);	// turn left
   1028 		::g->faces[facenum++] = (patch_t*)W_CacheLumpName(namebuf, PU_STATIC_SHARED);
   1029 		sprintf(namebuf, "STFOUCH%d", i);	// ouch!
   1030 		::g->faces[facenum++] = (patch_t*)W_CacheLumpName(namebuf, PU_STATIC_SHARED);
   1031 		sprintf(namebuf, "STFEVL%d", i);	// evil grin ;)
   1032 		::g->faces[facenum++] = (patch_t*)W_CacheLumpName(namebuf, PU_STATIC_SHARED);
   1033 		sprintf(namebuf, "STFKILL%d", i);	// pissed off
   1034 		::g->faces[facenum++] = (patch_t*)W_CacheLumpName(namebuf, PU_STATIC_SHARED);
   1035 	}
   1036 	::g->faces[facenum++] = (patch_t*)W_CacheLumpName("STFGOD0", PU_STATIC_SHARED);
   1037 	::g->faces[facenum++] = (patch_t*)W_CacheLumpName("STFDEAD0", PU_STATIC_SHARED);
   1038 
   1039 }
   1040 
   1041 void ST_loadData(void)
   1042 {
   1043 	::g->lu_palette = W_GetNumForName ("PLAYPAL");
   1044 	ST_loadGraphics();
   1045 }
   1046 
   1047 void ST_unloadGraphics(void)
   1048 {
   1049 	// These things are always reloaded... so just don't bother to clean them up!
   1050 }
   1051 
   1052 void ST_unloadData(void)
   1053 {
   1054 	ST_unloadGraphics();
   1055 }
   1056 
   1057 void ST_initData(void)
   1058 {
   1059 
   1060 	int		i;
   1061 
   1062 	::g->st_firsttime = true;
   1063 	::g->plyr = &::g->players[::g->consoleplayer];
   1064 
   1065 	::g->st_clock = 0;
   1066 	::g->st_chatstate = StartChatState;
   1067 	::g->st_gamestate = FirstPersonState;
   1068 
   1069 	::g->st_statusbaron = true;
   1070 	::g->st_oldchat = ::g->st_chat = false;
   1071 	::g->st_cursoron = false;
   1072 
   1073 	::g->st_faceindex = 0;
   1074 	::g->st_palette = -1;
   1075 
   1076 	::g->st_oldhealth = -1;
   1077 
   1078 	for (i=0;i<NUMWEAPONS;i++)
   1079 		::g->oldweaponsowned[i] = ::g->plyr->weaponowned[i];
   1080 
   1081 	for (i=0;i<3;i++)
   1082 		::g->keyboxes[i] = -1;
   1083 
   1084 	STlib_init();
   1085 
   1086 }
   1087 
   1088 
   1089 
   1090 void ST_createWidgets(void)
   1091 {
   1092 
   1093 	int i;
   1094 
   1095 	// ready weapon ammo
   1096 	STlib_initNum(&::g->w_ready,
   1097 		ST_AMMOX,
   1098 		ST_AMMOY,
   1099 		::g->tallnum,
   1100 		&::g->plyr->ammo[weaponinfo[::g->plyr->readyweapon].ammo],
   1101 		&::g->st_statusbaron,
   1102 		ST_AMMOWIDTH );
   1103 
   1104 	// the last weapon type
   1105 	::g->w_ready.data = ::g->plyr->readyweapon; 
   1106 
   1107 	// health percentage
   1108 	STlib_initPercent(&::g->w_health,
   1109 		ST_HEALTHX,
   1110 		ST_HEALTHY,
   1111 		::g->tallnum,
   1112 		&::g->plyr->health,
   1113 		&::g->st_statusbaron,
   1114 		::g->tallpercent);
   1115 
   1116 	// ::g->arms background
   1117 	STlib_initBinIcon(&::g->w_armsbg,
   1118 		ST_ARMSBGX,
   1119 		ST_ARMSBGY,
   1120 		::g->armsbg,
   1121 		&::g->st_notdeathmatch,
   1122 		&::g->st_statusbaron);
   1123 
   1124 	// weapons owned
   1125 	for(i=0;i<6;i++)
   1126 	{
   1127 		STlib_initMultIcon(&::g->w_arms[i],
   1128 			ST_ARMSX+(i%3)*ST_ARMSXSPACE,
   1129 			ST_ARMSY+(i/3)*ST_ARMSYSPACE,
   1130 			::g->arms[i], (int *) &::g->plyr->weaponowned[i+1],
   1131 			&::g->st_armson);
   1132 	}
   1133 
   1134 	// frags sum
   1135 	STlib_initNum(&::g->w_frags,
   1136 		ST_FRAGSX,
   1137 		ST_FRAGSY,
   1138 		::g->tallnum,
   1139 		&::g->st_fragscount,
   1140 		&::g->st_fragson,
   1141 		ST_FRAGSWIDTH);
   1142 
   1143 	// ::g->faces
   1144 	STlib_initMultIcon(&::g->w_faces,
   1145 		ST_FACESX,
   1146 		ST_FACESY,
   1147 		::g->faces,
   1148 		&::g->st_faceindex,
   1149 		&::g->st_statusbaron);
   1150 
   1151 	// armor percentage - should be colored later
   1152 	STlib_initPercent(&::g->w_armor,
   1153 		ST_ARMORX,
   1154 		ST_ARMORY,
   1155 		::g->tallnum,
   1156 		&::g->plyr->armorpoints,
   1157 		&::g->st_statusbaron, ::g->tallpercent);
   1158 
   1159 	// ::g->keyboxes 0-2
   1160 	STlib_initMultIcon(&::g->w_keyboxes[0],
   1161 		ST_KEY0X,
   1162 		ST_KEY0Y,
   1163 		::g->keys,
   1164 		&::g->keyboxes[0],
   1165 		&::g->st_statusbaron);
   1166 
   1167 	STlib_initMultIcon(&::g->w_keyboxes[1],
   1168 		ST_KEY1X,
   1169 		ST_KEY1Y,
   1170 		::g->keys,
   1171 		&::g->keyboxes[1],
   1172 		&::g->st_statusbaron);
   1173 
   1174 	STlib_initMultIcon(&::g->w_keyboxes[2],
   1175 		ST_KEY2X,
   1176 		ST_KEY2Y,
   1177 		::g->keys,
   1178 		&::g->keyboxes[2],
   1179 		&::g->st_statusbaron);
   1180 
   1181 	// ammo count (all four kinds)
   1182 	STlib_initNum(&::g->w_ammo[0],
   1183 		ST_AMMO0X,
   1184 		ST_AMMO0Y,
   1185 		::g->shortnum,
   1186 		&::g->plyr->ammo[0],
   1187 		&::g->st_statusbaron,
   1188 		ST_AMMO0WIDTH);
   1189 
   1190 	STlib_initNum(&::g->w_ammo[1],
   1191 		ST_AMMO1X,
   1192 		ST_AMMO1Y,
   1193 		::g->shortnum,
   1194 		&::g->plyr->ammo[1],
   1195 		&::g->st_statusbaron,
   1196 		ST_AMMO1WIDTH);
   1197 
   1198 	STlib_initNum(&::g->w_ammo[2],
   1199 		ST_AMMO2X,
   1200 		ST_AMMO2Y,
   1201 		::g->shortnum,
   1202 		&::g->plyr->ammo[2],
   1203 		&::g->st_statusbaron,
   1204 		ST_AMMO2WIDTH);
   1205 
   1206 	STlib_initNum(&::g->w_ammo[3],
   1207 		ST_AMMO3X,
   1208 		ST_AMMO3Y,
   1209 		::g->shortnum,
   1210 		&::g->plyr->ammo[3],
   1211 		&::g->st_statusbaron,
   1212 		ST_AMMO3WIDTH);
   1213 
   1214 	// max ammo count (all four kinds)
   1215 	STlib_initNum(&::g->w_maxammo[0],
   1216 		ST_MAXAMMO0X,
   1217 		ST_MAXAMMO0Y,
   1218 		::g->shortnum,
   1219 		&::g->plyr->maxammo[0],
   1220 		&::g->st_statusbaron,
   1221 		ST_MAXAMMO0WIDTH);
   1222 
   1223 	STlib_initNum(&::g->w_maxammo[1],
   1224 		ST_MAXAMMO1X,
   1225 		ST_MAXAMMO1Y,
   1226 		::g->shortnum,
   1227 		&::g->plyr->maxammo[1],
   1228 		&::g->st_statusbaron,
   1229 		ST_MAXAMMO1WIDTH);
   1230 
   1231 	STlib_initNum(&::g->w_maxammo[2],
   1232 		ST_MAXAMMO2X,
   1233 		ST_MAXAMMO2Y,
   1234 		::g->shortnum,
   1235 		&::g->plyr->maxammo[2],
   1236 		&::g->st_statusbaron,
   1237 		ST_MAXAMMO2WIDTH);
   1238 
   1239 	STlib_initNum(&::g->w_maxammo[3],
   1240 		ST_MAXAMMO3X,
   1241 		ST_MAXAMMO3Y,
   1242 		::g->shortnum,
   1243 		&::g->plyr->maxammo[3],
   1244 		&::g->st_statusbaron,
   1245 		ST_MAXAMMO3WIDTH);
   1246 
   1247 }
   1248 
   1249 
   1250 
   1251 void ST_Start (void)
   1252 {
   1253 
   1254 	if (!::g->st_stopped)
   1255 		ST_Stop();
   1256 
   1257 	ST_initData();
   1258 	ST_createWidgets();
   1259 	::g->st_stopped = false;
   1260 
   1261 }
   1262 
   1263 void ST_Stop (void)
   1264 {
   1265 	if (::g->st_stopped)
   1266 		return;
   1267 
   1268 	I_SetPalette ((byte*)W_CacheLumpNum ((int)::g->lu_palette, PU_CACHE_SHARED));
   1269 
   1270 	::g->st_stopped = true;
   1271 }
   1272 
   1273 void ST_Init (void)
   1274 {
   1275 	::g->veryfirsttime = 0;
   1276 	ST_loadData();
   1277 	::g->screens[4] = (byte *) DoomLib::Z_Malloc( SCREENWIDTH * SCREENHEIGHT /*ST_WIDTH*ST_HEIGHT*/, PU_STATIC, 0);
   1278 	memset( ::g->screens[4], 0, SCREENWIDTH * SCREENHEIGHT );
   1279 }
   1280 
   1281 
   1282 CONSOLE_COMMAND_SHIP( idqd, "cheat for toggleable god mode", 0 ) {
   1283 	int oldPlayer = DoomLib::GetPlayer();
   1284 	DoomLib::SetPlayer( 0 );
   1285 	if ( ::g == NULL ) {
   1286 		return;
   1287 	}
   1288 
   1289 	if (::g->gamestate != GS_LEVEL) {
   1290 		return;
   1291 	}
   1292 
   1293 	::g->plyr->cheats ^= CF_GODMODE;
   1294 	if (::g->plyr->cheats & CF_GODMODE)
   1295 	{
   1296 		if (::g->plyr->mo)
   1297 			::g->plyr->mo->health = 100;
   1298 
   1299 		::g->plyr->health = 100;
   1300 		::g->plyr->message = STSTR_DQDON;
   1301 	}
   1302 	else 
   1303 		::g->plyr->message = STSTR_DQDOFF;
   1304 
   1305 	DoomLib::SetPlayer( oldPlayer );
   1306 }
   1307 
   1308 CONSOLE_COMMAND_SHIP( idfa, "cheat for killer fucking arsenal", 0 ) {
   1309 	int oldPlayer = DoomLib::GetPlayer();
   1310 	DoomLib::SetPlayer( 0 );
   1311 	if ( ::g == NULL ) {
   1312 		return;
   1313 	}
   1314 
   1315 	if (::g->gamestate != GS_LEVEL) {
   1316 		return;
   1317 	}
   1318 
   1319 	int i = 0;
   1320 	::g->plyr->armorpoints = 200;
   1321 	::g->plyr->armortype = 2;
   1322 
   1323 	for (i=0;i<NUMWEAPONS;i++)
   1324 		::g->plyr->weaponowned[i] = true;
   1325 
   1326 	for (i=0;i<NUMAMMO;i++)
   1327 		::g->plyr->ammo[i] = ::g->plyr->maxammo[i];
   1328 
   1329 	::g->plyr->message = STSTR_FAADDED;
   1330 
   1331 	DoomLib::SetPlayer( oldPlayer );
   1332 }
   1333 
   1334 CONSOLE_COMMAND_SHIP( idkfa, "cheat for key full ammo", 0 ) {
   1335 	int oldPlayer = DoomLib::GetPlayer();
   1336 	DoomLib::SetPlayer( 0 );
   1337 	if ( ::g == NULL ) {
   1338 		return;
   1339 	}
   1340 
   1341 	if (::g->gamestate != GS_LEVEL) {
   1342 		return;
   1343 	}
   1344 
   1345 	int i = 0;
   1346 	::g->plyr->armorpoints = 200;
   1347 	::g->plyr->armortype = 2;
   1348 
   1349 	for (i=0;i<NUMWEAPONS;i++)
   1350 		::g->plyr->weaponowned[i] = true;
   1351 
   1352 	for (i=0;i<NUMAMMO;i++)
   1353 		::g->plyr->ammo[i] = ::g->plyr->maxammo[i];
   1354 
   1355 	for (i=0;i<NUMCARDS;i++)
   1356 		::g->plyr->cards[i] = true;
   1357 
   1358 	::g->plyr->message = STSTR_KFAADDED;
   1359 
   1360 	DoomLib::SetPlayer( oldPlayer );
   1361 }
   1362 
   1363 
   1364 CONSOLE_COMMAND_SHIP( idclip, "cheat for no clip", 0 ) {
   1365 	int oldPlayer = DoomLib::GetPlayer();
   1366 	DoomLib::SetPlayer( 0 );
   1367 	if ( ::g == NULL ) {
   1368 		return;
   1369 	}
   1370 
   1371 	if (::g->gamestate != GS_LEVEL) {
   1372 		return;
   1373 	}
   1374 
   1375 	::g->plyr->cheats ^= CF_NOCLIP;
   1376 
   1377 	if (::g->plyr->cheats & CF_NOCLIP)
   1378 		::g->plyr->message = STSTR_NCON;
   1379 	else
   1380 		::g->plyr->message = STSTR_NCOFF;
   1381 
   1382 	DoomLib::SetPlayer( oldPlayer );
   1383 }
   1384 CONSOLE_COMMAND_SHIP( idmypos, "for player position", 0 ) {
   1385 	int oldPlayer = DoomLib::GetPlayer();
   1386 	DoomLib::SetPlayer( 0 );
   1387 	if ( ::g == NULL ) {
   1388 		return;
   1389 	}
   1390 
   1391 	if (::g->gamestate != GS_LEVEL) {
   1392 		return;
   1393 	}
   1394 
   1395 	static char	buf[ST_MSGWIDTH];
   1396 	sprintf(buf, "ang=0x%x;x,y=(0x%x,0x%x)",
   1397 		::g->players[::g->consoleplayer].mo->angle,
   1398 		::g->players[::g->consoleplayer].mo->x,
   1399 		::g->players[::g->consoleplayer].mo->y);
   1400 	::g->plyr->message = buf;
   1401 
   1402 	DoomLib::SetPlayer( oldPlayer );
   1403 }
   1404 
   1405 CONSOLE_COMMAND_SHIP( idclev, "warp to next level", 0 ) {
   1406 	int oldPlayer = DoomLib::GetPlayer();
   1407 	DoomLib::SetPlayer( 0 );
   1408 	if ( ::g == NULL ) {
   1409 		return;
   1410 	}
   1411 
   1412 	if (::g->gamestate != GS_LEVEL) {
   1413 		return;
   1414 	}
   1415 
   1416 	int		epsd;
   1417 	int		map;
   1418 
   1419 	if (::g->gamemode == commercial)
   1420 	{
   1421 		
   1422 		if( args.Argc() > 1 ) {
   1423 			epsd = 1;
   1424 			map = atoi( args.Argv( 1 ) );
   1425 		} else {
   1426 			idLib::Printf( "idclev takes map as first argument \n"  );
   1427 			return;
   1428 		}
   1429 
   1430 		if( map > 32 ) {
   1431 			map = 1;
   1432 		}
   1433 	}
   1434 	else
   1435 	{
   1436 		if( args.Argc() > 2 ) {
   1437 			epsd = atoi( args.Argv( 1 ) );
   1438 			map = atoi( args.Argv( 2 ) );
   1439 		} else {
   1440 			idLib::Printf( "idclev takes episode and map as first two arguments \n"  );
   1441 			return;
   1442 		}
   1443 	}
   1444 
   1445 	// Catch invalid maps.
   1446 	if (epsd < 1)
   1447 		return;
   1448 
   1449 	if (map < 1)
   1450 		return;
   1451 
   1452 	// Ohmygod - this is not going to work.
   1453 	if ((::g->gamemode == retail)
   1454 		&& ((epsd > 4) || (map > 9)))
   1455 		return;
   1456 
   1457 	if ((::g->gamemode == registered)
   1458 		&& ((epsd > 3) || (map > 9)))
   1459 		return;
   1460 
   1461 	if ((::g->gamemode == shareware)
   1462 		&& ((epsd > 1) || (map > 9)))
   1463 		return;
   1464 
   1465 	if ((::g->gamemode == commercial)
   1466 		&& (( epsd > 1) || (map > 34)))
   1467 		return;
   1468 
   1469 	// So be it.
   1470 	::g->plyr->message = STSTR_CLEV;
   1471 	G_DeferedInitNew(::g->gameskill, epsd, map);
   1472 
   1473 	DoomLib::SetPlayer( oldPlayer );
   1474 }