Home | History | Annotate | Download | only in progs
      1 
      2 // prototypes
      3 void () W_WeaponFrame;
      4 void() W_SetCurrentAmmo;
      5 void() player_pain;
      6 void() player_stand1;
      7 void (vector org) spawn_tfog;
      8 void (vector org, entity death_owner) spawn_tdeath;
      9 
     10 float   modelindex_eyes, modelindex_player;
     11 
     12 /*
     13 =============================================================================
     14 
     15 				LEVEL CHANGING / INTERMISSION
     16 
     17 =============================================================================
     18 */
     19 
     20 string nextmap;
     21 
     22 float   intermission_running;
     23 float   intermission_exittime;
     24 
     25 /*QUAKED info_intermission (1 0.5 0.5) (-16 -16 -16) (16 16 16)
     26 This is the camera point for the intermission.
     27 Use mangle instead of angle, so you can set pitch or roll as well as yaw.  'pitch roll yaw'
     28 */
     29 void() info_intermission =
     30 {
     31 	self.angles = self.mangle;      // so C can get at it
     32 };
     33 
     34 
     35 
     36 void() SetChangeParms =
     37 {
     38 	if (self.health <= 0)
     39 	{
     40 		SetNewParms ();
     41 		return;
     42 	}
     43  
     44 // remove items
     45 	self.items = self.items - (self.items & 
     46 	(IT_KEY1 | IT_KEY2 | IT_INVISIBILITY | IT_INVULNERABILITY | IT_SUIT | IT_QUAD) );
     47 	
     48 // cap super health
     49 	if (self.health > 100)
     50 		self.health = 100;
     51 	if (self.health < 50)
     52 		self.health = 50;
     53 	parm1 = self.items;
     54 	parm2 = self.health;
     55 	parm3 = self.armorvalue;
     56 	if (self.ammo_shells < 25)
     57 		parm4 = 25;
     58 	else
     59 		parm4 = self.ammo_shells;
     60 	parm5 = self.ammo_nails;
     61 	parm6 = self.ammo_rockets;
     62 	parm7 = self.ammo_cells;
     63 	parm8 = self.weapon;
     64 	parm9 = self.armortype * 100;
     65 };
     66 
     67 void() SetNewParms =
     68 {
     69 	parm1 = IT_SHOTGUN | IT_AXE;
     70 	parm2 = 100;
     71 	parm3 = 0;
     72 	parm4 = 25;
     73 	parm5 = 0;
     74 	parm6 = 0;
     75 	parm7 = 0;
     76 	parm8 = 1;
     77 	parm9 = 0;
     78 };
     79 
     80 void() DecodeLevelParms =
     81 {
     82 	if (serverflags)
     83 	{
     84 		if (world.model == "maps/start.bsp")
     85 			SetNewParms ();         // take away all stuff on starting new episode
     86 	}
     87 	
     88 	self.items = parm1;
     89 	self.health = parm2;
     90 	self.armorvalue = parm3;
     91 	self.ammo_shells = parm4;
     92 	self.ammo_nails = parm5;
     93 	self.ammo_rockets = parm6;
     94 	self.ammo_cells = parm7;
     95 	self.weapon = parm8;
     96 	self.armortype = parm9 * 0.01;
     97 };
     98 
     99 /*
    100 ============
    101 FindIntermission
    102 
    103 Returns the entity to view from
    104 ============
    105 */
    106 entity() FindIntermission =
    107 {
    108 	local   entity spot;
    109 	local   float cyc;
    110 
    111 // look for info_intermission first
    112 	spot = find (world, classname, "info_intermission");
    113 	if (spot)
    114 	{       // pick a random one
    115 		cyc = random() * 4;
    116 		while (cyc > 1)
    117 		{
    118 			spot = find (spot, classname, "info_intermission");
    119 			if (!spot)
    120 				spot = find (spot, classname, "info_intermission");
    121 			cyc = cyc - 1;
    122 		}
    123 		return spot;
    124 	}
    125 
    126 // then look for the start position
    127 	spot = find (world, classname, "info_player_start");
    128 	if (spot)
    129 		return spot;
    130 	
    131 	objerror ("FindIntermission: no spot");
    132 };
    133 
    134 
    135 void() GotoNextMap =
    136 {
    137 	local string newmap;
    138 
    139 //ZOID: 12-13-96, samelevel is overloaded, only 1 works for same level
    140 
    141 	if (cvar("samelevel") == 1)     // if samelevel is set, stay on same level
    142 		changelevel (mapname);
    143 	else {
    144 		// configurable map lists, see if the current map exists as a
    145 		// serverinfo/localinfo var
    146 		newmap = infokey(world, mapname);
    147 		if (newmap != "")
    148 			changelevel (newmap);
    149 		else
    150 			changelevel (nextmap);
    151 	}
    152 };
    153 
    154 
    155 
    156 /*
    157 ============
    158 IntermissionThink
    159 
    160 When the player presses attack or jump, change to the next level
    161 ============
    162 */
    163 void() IntermissionThink =
    164 {
    165 	if (time < intermission_exittime)
    166 		return;
    167 
    168 	if (!self.button0 && !self.button1 && !self.button2)
    169 		return;
    170 	
    171 	GotoNextMap ();
    172 };
    173 
    174 /*
    175 ============
    176 execute_changelevel
    177 
    178 The global "nextmap" has been set previously.
    179 Take the players to the intermission spot
    180 ============
    181 */
    182 void() execute_changelevel =
    183 {
    184 	local entity    pos;
    185 
    186 	intermission_running = 1;
    187 	
    188 // enforce a wait time before allowing changelevel
    189 	intermission_exittime = time + 5;
    190 
    191 	pos = FindIntermission ();
    192 
    193 // play intermission music
    194 	WriteByte (MSG_ALL, SVC_CDTRACK);
    195 	WriteByte (MSG_ALL, 3);
    196 
    197 	WriteByte (MSG_ALL, SVC_INTERMISSION);
    198 	WriteCoord (MSG_ALL, pos.origin_x);
    199 	WriteCoord (MSG_ALL, pos.origin_y);
    200 	WriteCoord (MSG_ALL, pos.origin_z);
    201 	WriteAngle (MSG_ALL, pos.mangle_x);
    202 	WriteAngle (MSG_ALL, pos.mangle_y);
    203 	WriteAngle (MSG_ALL, pos.mangle_z);
    204 	
    205 	other = find (world, classname, "player");
    206 	while (other != world)
    207 	{
    208 		other.takedamage = DAMAGE_NO;
    209 		other.solid = SOLID_NOT;
    210 		other.movetype = MOVETYPE_NONE;
    211 		other.modelindex = 0;
    212 		other = find (other, classname, "player");
    213 	}       
    214 
    215 };
    216 
    217 
    218 void() changelevel_touch =
    219 {
    220 	local entity    pos;
    221 
    222 	if (other.classname != "player")
    223 		return;
    224 
    225 // if "noexit" is set, blow up the player trying to leave
    226 //ZOID, 12-13-96, noexit isn't supported in QW.  Overload samelevel
    227 //      if ((cvar("noexit") == 1) || ((cvar("noexit") == 2) && (mapname != "start")))
    228 	if ((cvar("samelevel") == 2) || ((cvar("samelevel") == 3) && (mapname != "start")))
    229 	{
    230 		T_Damage (other, self, self, 50000);
    231 		return;
    232 	}
    233 
    234 	bprint (PRINT_HIGH, other.netname);
    235 	bprint (PRINT_HIGH," exited the level\n");
    236 	
    237 	nextmap = self.map;
    238 
    239 	SUB_UseTargets ();
    240 
    241 	self.touch = SUB_Null;
    242 
    243 // we can't move people right now, because touch functions are called
    244 // in the middle of C movement code, so set a think time to do it
    245 	self.think = execute_changelevel;
    246 	self.nextthink = time + 0.1;
    247 };
    248 
    249 /*QUAKED trigger_changelevel (0.5 0.5 0.5) ? NO_INTERMISSION
    250 When the player touches this, he gets sent to the map listed in the "map" variable.  Unless the NO_INTERMISSION flag is set, the view will go to the info_intermission spot and display stats.
    251 */
    252 void() trigger_changelevel =
    253 {
    254 	if (!self.map)
    255 		objerror ("chagnelevel trigger doesn't have map");
    256 	
    257 	InitTrigger ();
    258 	self.touch = changelevel_touch;
    259 };
    260 
    261 
    262 /*
    263 =============================================================================
    264 
    265 				PLAYER GAME EDGE FUNCTIONS
    266 
    267 =============================================================================
    268 */
    269 
    270 void() set_suicide_frame;
    271 
    272 // called by ClientKill and DeadThink
    273 void() respawn =
    274 {
    275 	// make a copy of the dead body for appearances sake
    276 	CopyToBodyQue (self);
    277 	// set default spawn parms
    278 	SetNewParms ();
    279 	// respawn              
    280 	PutClientInServer ();
    281 };
    282 
    283 
    284 /*
    285 ============
    286 ClientKill
    287 
    288 Player entered the suicide command
    289 ============
    290 */
    291 void() ClientKill =
    292 {
    293 	bprint (PRINT_MEDIUM, self.netname);
    294 	bprint (PRINT_MEDIUM, " suicides\n");
    295 	set_suicide_frame ();
    296 	self.modelindex = modelindex_player;
    297 	logfrag (self, self);
    298 	self.frags = self.frags - 2;    // extra penalty
    299 	respawn ();
    300 };
    301 
    302 float(vector v) CheckSpawnPoint =
    303 {
    304 	return FALSE;
    305 };
    306 
    307 /*
    308 ============
    309 SelectSpawnPoint
    310 
    311 Returns the entity to spawn at
    312 ============
    313 */
    314 entity() SelectSpawnPoint =
    315 {
    316 	local   entity spot, newspot, thing;
    317 	local   float   numspots, totalspots;
    318 	local   float   rnum, pcount;
    319 	local   float   rs;
    320 	local entity spots;
    321 
    322 	numspots = 0;
    323 	totalspots = 0;
    324 
    325 // testinfo_player_start is only found in regioned levels
    326 	spot = find (world, classname, "testplayerstart");
    327 	if (spot)
    328 		return spot;
    329 		
    330 // choose a info_player_deathmatch point
    331 
    332 // ok, find all spots that don't have players nearby
    333 
    334 	spots = world;
    335 	spot = find (world, classname, "info_player_deathmatch");       
    336 	while (spot)
    337 	{
    338 		totalspots = totalspots + 1;
    339 
    340 		thing=findradius(spot.origin, 84);
    341 		pcount=0;               
    342 		while (thing)
    343 		{
    344 			if (thing.classname == "player")
    345 				pcount=pcount + 1;                      
    346 			thing=thing.chain;      
    347 		}
    348 		if (pcount == 0) {
    349 			spot.goalentity = spots;
    350 			spots = spot;
    351 			numspots = numspots + 1;
    352 		}
    353 
    354 		// Get the next spot in the chain
    355 		spot = find (spot, classname, "info_player_deathmatch");                
    356 	}
    357 	totalspots=totalspots - 1;
    358 	if (!numspots) {
    359 		// ack, they are all full, just pick one at random
    360 //		bprint (PRINT_HIGH, "Ackk! All spots are full. Selecting random spawn spot\n");
    361 		totalspots = rint((random() * totalspots));
    362 		spot = find (world, classname, "info_player_deathmatch");       
    363 		while (totalspots > 0) {
    364 			totalspots = totalspots - 1;
    365 			spot = find (spot, classname, "info_player_deathmatch");
    366 		}
    367 		return spot;
    368 	}
    369 		
    370 // We now have the number of spots available on the map in numspots
    371 
    372 	// Generate a random number between 1 and numspots
    373 
    374 	numspots = numspots - 1;
    375 	
    376 	numspots = rint((random() * numspots ) );
    377 
    378 	spot = spots;
    379 	while (numspots > 0) {
    380 		spot = spot.goalentity;
    381 		numspots = numspots - 1;
    382 	}
    383 	return spot;
    384 
    385 };
    386 void() DecodeLevelParms;
    387 void() PlayerDie;
    388 
    389 /*
    390 ===========
    391 ValidateUser
    392 
    393 
    394 ============
    395 */
    396 float(entity e) ValidateUser =
    397 {
    398 /*
    399 	local string    s;
    400 	local string    userclan;
    401 	local float     rank, rankmin, rankmax;
    402 
    403 //
    404 // if the server has set "clan1" and "clan2", then it
    405 // is a clan match that will allow only those two clans in
    406 //
    407 	s = serverinfo("clan1");
    408 	if (s)
    409 	{
    410 		userclan = masterinfo(e,"clan");
    411 		if (s == userclan)
    412 			return true;
    413 		s = serverinfo("clan2");
    414 		if (s == userclan)
    415 			return true;
    416 		return false;
    417 	}
    418 
    419 //
    420 // if the server has set "rankmin" and/or "rankmax" then
    421 // the users rank must be between those two values
    422 //
    423 	s = masterinfo (e, "rank");
    424 	rank = stof (s);
    425 
    426 	s = serverinfo("rankmin");
    427 	if (s)
    428 	{
    429 		rankmin = stof (s);
    430 		if (rank < rankmin)
    431 			return false;
    432 	}
    433 	s = serverinfo("rankmax");
    434 	if (s)
    435 	{
    436 		rankmax = stof (s);
    437 		if (rankmax < rank)
    438 			return false;
    439 	}
    440 
    441 	return true;
    442 */
    443 };
    444 
    445 
    446 /*
    447 ===========
    448 PutClientInServer
    449 
    450 called each time a player enters a new level
    451 ============
    452 */
    453 void() PutClientInServer =
    454 {
    455 	local   entity spot;
    456 	local 	string	s;
    457 
    458 	self.classname = "player";
    459 	self.health = 100;
    460 	self.takedamage = DAMAGE_AIM;
    461 	self.solid = SOLID_SLIDEBOX;
    462 	self.movetype = MOVETYPE_WALK;
    463 	self.show_hostile = 0;
    464 	self.max_health = 100;
    465 	self.flags = FL_CLIENT;
    466 	self.air_finished = time + 12;
    467 	self.dmg = 2;                   // initial water damage
    468 	self.super_damage_finished = 0;
    469 	self.radsuit_finished = 0;
    470 	self.invisible_finished = 0;
    471 	self.invincible_finished = 0;
    472 	self.effects = 0;
    473 	self.invincible_time = 0;
    474 
    475 	DecodeLevelParms ();
    476 	
    477 	W_SetCurrentAmmo ();
    478 
    479 	self.attack_finished = time;
    480 	self.th_pain = player_pain;
    481 	self.th_die = PlayerDie;
    482 	
    483 	self.deadflag = DEAD_NO;
    484 // paustime is set by teleporters to keep the player from moving a while
    485 	self.pausetime = 0;
    486 	
    487 	spot = SelectSpawnPoint ();
    488 
    489 	self.origin = spot.origin + '0 0 1';
    490 	self.angles = spot.angles;
    491 	self.fixangle = TRUE;           // turn this way immediately
    492 
    493 // oh, this is a hack!
    494 	setmodel (self, "progs/eyes.mdl");
    495 	modelindex_eyes = self.modelindex;
    496 
    497 	setmodel (self, "progs/player.mdl");
    498 	modelindex_player = self.modelindex;
    499 
    500 	setsize (self, VEC_HULL_MIN, VEC_HULL_MAX);
    501 	
    502 	self.view_ofs = '0 0 22';
    503 
    504 // Mod - Xian (May.20.97)
    505 // Bug where player would have velocity from their last kill
    506 
    507 	self.velocity = '0 0 0';
    508 
    509 	player_stand1 ();
    510 	
    511 	makevectors(self.angles);
    512 	spawn_tfog (self.origin + v_forward*20);
    513 
    514 	spawn_tdeath (self.origin, self);
    515 
    516 	// Set Rocket Jump Modifiers
    517 	if (stof(infokey(world, "rj")) != 0)
    518 	{                
    519 		rj = stof(infokey(world, "rj"));
    520 	}
    521 
    522 	if (deathmatch == 4)
    523 	{
    524 		self.ammo_shells = 0;
    525 		if (stof(infokey(world, "axe")) == 0)
    526 		{
    527 			self.ammo_nails = 255;
    528 			self.ammo_shells = 255;
    529 			self.ammo_rockets = 255;
    530 			self.ammo_cells = 255;
    531 			self.items = self.items | IT_NAILGUN;
    532 			self.items = self.items | IT_SUPER_NAILGUN;
    533 			self.items = self.items | IT_SUPER_SHOTGUN;
    534 			self.items = self.items | IT_ROCKET_LAUNCHER;
    535 //		self.items = self.items | IT_GRENADE_LAUNCHER;
    536 			self.items = self.items | IT_LIGHTNING;
    537 		}
    538 		self.items = self.items - (self.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3)) + IT_ARMOR3;
    539 		self.armorvalue = 200;
    540 		self.armortype = 0.8;
    541 		self.health = 250;
    542 		self.items = self.items | IT_INVULNERABILITY;
    543 		self.invincible_time = 1;
    544 		self.invincible_finished = time + 3;
    545 	}
    546 
    547 	if (deathmatch == 5)
    548 	{
    549 		self.ammo_nails = 80;
    550 		self.ammo_shells = 30;
    551 		self.ammo_rockets = 10;
    552 		self.ammo_cells = 30;
    553 		self.items = self.items | IT_NAILGUN;
    554 		self.items = self.items | IT_SUPER_NAILGUN;
    555 		self.items = self.items | IT_SUPER_SHOTGUN;
    556 		self.items = self.items | IT_ROCKET_LAUNCHER;
    557 		self.items = self.items | IT_GRENADE_LAUNCHER;
    558 		self.items = self.items | IT_LIGHTNING;
    559 		self.items = self.items - (self.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3)) + IT_ARMOR3;
    560 		self.armorvalue = 200;
    561 		self.armortype = 0.8;
    562 		self.health = 200;
    563 		self.items = self.items | IT_INVULNERABILITY;
    564 		self.invincible_time = 1;
    565 		self.invincible_finished = time + 3;
    566 	}
    567 
    568 
    569 };
    570 
    571 
    572 /*
    573 =============================================================================
    574 
    575 				QUAKED FUNCTIONS
    576 
    577 =============================================================================
    578 */
    579 
    580 
    581 /*QUAKED info_player_start (1 0 0) (-16 -16 -24) (16 16 24)
    582 The normal starting point for a level.
    583 */
    584 void() info_player_start =
    585 {
    586 };
    587 
    588 
    589 /*QUAKED info_player_start2 (1 0 0) (-16 -16 -24) (16 16 24)
    590 Only used on start map for the return point from an episode.
    591 */
    592 void() info_player_start2 =
    593 {
    594 };
    595 
    596 /*QUAKED info_player_deathmatch (1 0 1) (-16 -16 -24) (16 16 24)
    597 potential spawning position for deathmatch games
    598 */
    599 void() info_player_deathmatch =
    600 {
    601 };
    602 
    603 /*QUAKED info_player_coop (1 0 1) (-16 -16 -24) (16 16 24)
    604 potential spawning position for coop games
    605 */
    606 void() info_player_coop =
    607 {
    608 };
    609 
    610 /*
    611 ===============================================================================
    612 
    613 RULES
    614 
    615 ===============================================================================
    616 */
    617 
    618 /*
    619 go to the next level for deathmatch
    620 */
    621 void() NextLevel =
    622 {
    623 	local entity o;
    624 	local string newmap;
    625 
    626 	if (nextmap != "")
    627 		return; // already done
    628 
    629 	if (mapname == "start")
    630 	{
    631 		if (!cvar("registered"))
    632 		{
    633 			mapname = "e1m1";
    634 		}
    635 		else if (!(serverflags & 1))
    636 		{
    637 			mapname = "e1m1";
    638 			serverflags = serverflags | 1;
    639 		}
    640 		else if (!(serverflags & 2))
    641 		{
    642 			mapname = "e2m1";
    643 			serverflags = serverflags | 2;
    644 		}
    645 		else if (!(serverflags & 4))
    646 		{
    647 			mapname = "e3m1";
    648 			serverflags = serverflags | 4;
    649 		}
    650 		else if (!(serverflags & 8))
    651 		{
    652 			mapname = "e4m1";
    653 			serverflags = serverflags - 7;
    654 		}
    655  
    656 		o = spawn();
    657 		o.map = mapname;
    658 	}
    659 	else
    660 	{
    661 		// find a trigger changelevel
    662 		o = find(world, classname, "trigger_changelevel");
    663 		if (!o || mapname == "start")
    664 		{       // go back to same map if no trigger_changelevel
    665 			o = spawn();
    666 			o.map = mapname;
    667 		}
    668 	}
    669 
    670 	nextmap = o.map;
    671 
    672 	if (o.nextthink < time)
    673 	{
    674 		o.think = execute_changelevel;
    675 		o.nextthink = time + 0.1;
    676 	}
    677 };
    678 
    679 /*
    680 ============
    681 CheckRules
    682 
    683 Exit deathmatch games upon conditions
    684 ============
    685 */
    686 void() CheckRules =
    687 {       
    688 	if (timelimit && time >= timelimit)
    689 		NextLevel ();
    690 	
    691 	if (fraglimit && self.frags >= fraglimit)
    692 		NextLevel ();
    693 };
    694 
    695 //============================================================================
    696 
    697 void() PlayerDeathThink =
    698 {
    699 	local entity    old_self;
    700 	local float             forward;
    701 
    702 	if ((self.flags & FL_ONGROUND))
    703 	{
    704 		forward = vlen (self.velocity);
    705 		forward = forward - 20;
    706 		if (forward <= 0)
    707 			self.velocity = '0 0 0';
    708 		else    
    709 			self.velocity = forward * normalize(self.velocity);
    710 	}
    711 
    712 // wait for all buttons released
    713 	if (self.deadflag == DEAD_DEAD)
    714 	{
    715 		if (self.button2 || self.button1 || self.button0)
    716 			return;
    717 		self.deadflag = DEAD_RESPAWNABLE;
    718 		return;
    719 	}
    720 
    721 // wait for any button down
    722 	if (!self.button2 && !self.button1 && !self.button0)
    723 		return;
    724 
    725 	self.button0 = 0;
    726 	self.button1 = 0;
    727 	self.button2 = 0;
    728 	respawn();
    729 };
    730 
    731 
    732 void() PlayerJump =
    733 {
    734 	local vector start, end;
    735 
    736 	if (self.flags & FL_WATERJUMP)
    737 		return;
    738 	
    739 	if (self.waterlevel >= 2)
    740 	{
    741 // play swiming sound
    742 		if (self.swim_flag < time)
    743 		{
    744 			self.swim_flag = time + 1;
    745 			if (random() < 0.5)
    746 				sound (self, CHAN_BODY, "misc/water1.wav", 1, ATTN_NORM);
    747 			else
    748 				sound (self, CHAN_BODY, "misc/water2.wav", 1, ATTN_NORM);
    749 		}
    750 
    751 		return;
    752 	}
    753 
    754 	if (!(self.flags & FL_ONGROUND))
    755 		return;
    756 
    757 	if ( !(self.flags & FL_JUMPRELEASED) )
    758 		return;         // don't pogo stick
    759 
    760 	self.flags = self.flags - (self.flags & FL_JUMPRELEASED);       
    761 	self.button2 = 0;
    762 
    763 // player jumping sound
    764 	sound (self, CHAN_BODY, "player/plyrjmp8.wav", 1, ATTN_NORM);
    765 };
    766 
    767 
    768 /*
    769 ===========
    770 WaterMove
    771 
    772 ============
    773 */
    774 .float  dmgtime;
    775 
    776 void() WaterMove =
    777 {
    778 //dprint (ftos(self.waterlevel));
    779 	if (self.movetype == MOVETYPE_NOCLIP)
    780 		return;
    781 	if (self.health < 0)
    782 		return;
    783 
    784 	if (self.waterlevel != 3)
    785 	{
    786 		if (self.air_finished < time)
    787 			sound (self, CHAN_VOICE, "player/gasp2.wav", 1, ATTN_NORM);
    788 		else if (self.air_finished < time + 9)
    789 			sound (self, CHAN_VOICE, "player/gasp1.wav", 1, ATTN_NORM);
    790 		self.air_finished = time + 12;
    791 		self.dmg = 2;
    792 	}
    793 	else if (self.air_finished < time)
    794 	{       // drown!
    795 		if (self.pain_finished < time)
    796 		{
    797 			self.dmg = self.dmg + 2;
    798 			if (self.dmg > 15)
    799 				self.dmg = 10;
    800 			T_Damage (self, world, world, self.dmg);
    801 			self.pain_finished = time + 1;
    802 		}
    803 	}
    804 	
    805 	if (!self.waterlevel)
    806 	{
    807 		if (self.flags & FL_INWATER)
    808 		{       
    809 			// play leave water sound
    810 			sound (self, CHAN_BODY, "misc/outwater.wav", 1, ATTN_NORM);
    811 			self.flags = self.flags - FL_INWATER;
    812 		}
    813 		return;
    814 	}
    815 
    816 	if (self.watertype == CONTENT_LAVA)
    817 	{       // do damage
    818 		if (self.dmgtime < time)
    819 		{
    820 			if (self.radsuit_finished > time)
    821 				self.dmgtime = time + 1;
    822 			else
    823 				self.dmgtime = time + 0.2;
    824 
    825 			T_Damage (self, world, world, 10*self.waterlevel);
    826 		}
    827 	}
    828 	else if (self.watertype == CONTENT_SLIME)
    829 	{       // do damage
    830 		if (self.dmgtime < time && self.radsuit_finished < time)
    831 		{
    832 			self.dmgtime = time + 1;
    833 			T_Damage (self, world, world, 4*self.waterlevel);
    834 		}
    835 	}
    836 	
    837 	if ( !(self.flags & FL_INWATER) )
    838 	{       
    839 
    840 // player enter water sound
    841 
    842 		if (self.watertype == CONTENT_LAVA)
    843 			sound (self, CHAN_BODY, "player/inlava.wav", 1, ATTN_NORM);
    844 		if (self.watertype == CONTENT_WATER)
    845 			sound (self, CHAN_BODY, "player/inh2o.wav", 1, ATTN_NORM);
    846 		if (self.watertype == CONTENT_SLIME)
    847 			sound (self, CHAN_BODY, "player/slimbrn2.wav", 1, ATTN_NORM);
    848 
    849 		self.flags = self.flags + FL_INWATER;
    850 		self.dmgtime = 0;
    851 	}       
    852 };
    853 
    854 void() CheckWaterJump =
    855 {
    856 	local vector start, end;
    857 
    858 // check for a jump-out-of-water
    859 	makevectors (self.angles);
    860 	start = self.origin;
    861 	start_z = start_z + 8; 
    862 	v_forward_z = 0;
    863 	normalize(v_forward);
    864 	end = start + v_forward*24;
    865 	traceline (start, end, TRUE, self);
    866 	if (trace_fraction < 1)
    867 	{       // solid at waist
    868 		start_z = start_z + self.maxs_z - 8;
    869 		end = start + v_forward*24;
    870 		self.movedir = trace_plane_normal * -50;
    871 		traceline (start, end, TRUE, self);
    872 		if (trace_fraction == 1)
    873 		{       // open at eye level
    874 			self.flags = self.flags | FL_WATERJUMP;
    875 			self.velocity_z = 225;
    876 			self.flags = self.flags - (self.flags & FL_JUMPRELEASED);
    877 			self.teleport_time = time + 2;  // safety net
    878 			return;
    879 		}
    880 	}
    881 };
    882 
    883 /*
    884 ================
    885 PlayerPreThink
    886 
    887 Called every frame before physics are run
    888 ================
    889 */
    890 void() PlayerPreThink =
    891 {
    892 	local   float   mspeed, aspeed;
    893 	local   float   r;
    894 
    895 	if (intermission_running)
    896 	{
    897 		IntermissionThink ();   // otherwise a button could be missed between
    898 		return;                                 // the think tics
    899 	}
    900 
    901 	if (self.view_ofs == '0 0 0')
    902 		return;         // intermission or finale
    903 
    904 	makevectors (self.v_angle);             // is this still used
    905 
    906         self.deathtype = "";
    907 
    908 	CheckRules ();
    909 	WaterMove ();
    910 /*
    911 	if (self.waterlevel == 2)
    912 		CheckWaterJump ();
    913 */
    914 
    915 	if (self.deadflag >= DEAD_DEAD)
    916 	{
    917 		PlayerDeathThink ();
    918 		return;
    919 	}
    920 	
    921 	if (self.deadflag == DEAD_DYING)
    922 		return; // dying, so do nothing
    923 
    924 	if (self.button2)
    925 	{
    926 		PlayerJump ();
    927 	}
    928 	else
    929 		self.flags = self.flags | FL_JUMPRELEASED;
    930 
    931 // teleporters can force a non-moving pause time        
    932 	if (time < self.pausetime)
    933 		self.velocity = '0 0 0';
    934 
    935 	if(time > self.attack_finished && self.currentammo == 0 && self.weapon != IT_AXE)
    936 	{
    937 		self.weapon = W_BestWeapon ();
    938 		W_SetCurrentAmmo ();
    939 	}
    940 };
    941 	
    942 /*
    943 ================
    944 CheckPowerups
    945 
    946 Check for turning off powerups
    947 ================
    948 */
    949 void() CheckPowerups =
    950 {
    951 	if (self.health <= 0)
    952 		return;
    953 
    954 // invisibility
    955 	if (self.invisible_finished)
    956 	{
    957 // sound and screen flash when items starts to run out
    958 		if (self.invisible_sound < time)
    959 		{
    960 			sound (self, CHAN_AUTO, "items/inv3.wav", 0.5, ATTN_IDLE);
    961 			self.invisible_sound = time + ((random() * 3) + 1);
    962 		}
    963 
    964 
    965 		if (self.invisible_finished < time + 3)
    966 		{
    967 			if (self.invisible_time == 1)
    968 			{
    969 				sprint (self, PRINT_HIGH, "Ring of Shadows magic is fading\n");
    970 				stuffcmd (self, "bf\n");
    971 				sound (self, CHAN_AUTO, "items/inv2.wav", 1, ATTN_NORM);
    972 				self.invisible_time = time + 1;
    973 			}
    974 			
    975 			if (self.invisible_time < time)
    976 			{
    977 				self.invisible_time = time + 1;
    978 				stuffcmd (self, "bf\n");
    979 			}
    980 		}
    981 
    982 		if (self.invisible_finished < time)
    983 		{       // just stopped
    984 			self.items = self.items - IT_INVISIBILITY;
    985 			self.invisible_finished = 0;
    986 			self.invisible_time = 0;
    987 		}
    988 		
    989 	// use the eyes
    990 		self.frame = 0;
    991 		self.modelindex = modelindex_eyes;
    992 	}
    993 	else
    994 		self.modelindex = modelindex_player;    // don't use eyes
    995 
    996 // invincibility
    997 	if (self.invincible_finished)
    998 	{
    999 // sound and screen flash when items starts to run out
   1000 		if (self.invincible_finished < time + 3)
   1001 		{
   1002 			if (self.invincible_time == 1)
   1003 			{
   1004 				sprint (self, PRINT_HIGH, "Protection is almost burned out\n");
   1005 				stuffcmd (self, "bf\n");
   1006 				sound (self, CHAN_AUTO, "items/protect2.wav", 1, ATTN_NORM);
   1007 				self.invincible_time = time + 1;
   1008 			}
   1009 			
   1010 			if (self.invincible_time < time)
   1011 			{
   1012 				self.invincible_time = time + 1;
   1013 				stuffcmd (self, "bf\n");
   1014 			}
   1015 		}
   1016 		
   1017 		if (self.invincible_finished < time)
   1018 		{       // just stopped
   1019 			self.items = self.items - IT_INVULNERABILITY;
   1020 			self.invincible_time = 0;
   1021 			self.invincible_finished = 0;
   1022 		}
   1023 		if (self.invincible_finished > time)
   1024 		{
   1025 			self.effects = self.effects | EF_DIMLIGHT;
   1026 			self.effects = self.effects | EF_RED;
   1027 		}
   1028 		else
   1029 		{
   1030 			self.effects = self.effects - (self.effects & EF_DIMLIGHT);
   1031 			self.effects = self.effects - (self.effects & EF_RED);
   1032 		}
   1033 	}
   1034 
   1035 // super damage
   1036 	if (self.super_damage_finished)
   1037 	{
   1038 
   1039 // sound and screen flash when items starts to run out
   1040 
   1041 		if (self.super_damage_finished < time + 3)
   1042 		{
   1043 			if (self.super_time == 1)
   1044 			{
   1045 				if (deathmatch == 4)
   1046 					sprint (self, PRINT_HIGH, "OctaPower is wearing off\n");
   1047 				else
   1048 					sprint (self, PRINT_HIGH, "Quad Damage is wearing off\n");
   1049 				stuffcmd (self, "bf\n");
   1050 				sound (self, CHAN_AUTO, "items/damage2.wav", 1, ATTN_NORM);
   1051 				self.super_time = time + 1;
   1052 			}         
   1053 			
   1054 			if (self.super_time < time)
   1055 			{
   1056 				self.super_time = time + 1;
   1057 				stuffcmd (self, "bf\n");
   1058 			}
   1059 		}
   1060 
   1061 		if (self.super_damage_finished < time)
   1062 		{       // just stopped
   1063 			self.items = self.items - IT_QUAD;
   1064 			if (deathmatch == 4)
   1065 			{
   1066 				self.ammo_cells = 255;
   1067 				self.armorvalue = 1;
   1068 				self.armortype = 0.8;
   1069 				self.health = 100;
   1070 			}
   1071 			self.super_damage_finished = 0;
   1072 			self.super_time = 0;
   1073 		}
   1074 		if (self.super_damage_finished > time)
   1075 		{
   1076 			self.effects = self.effects | EF_DIMLIGHT;
   1077 			self.effects = self.effects | EF_BLUE;
   1078 		}
   1079 		else
   1080 		{
   1081 			self.effects = self.effects - (self.effects & EF_DIMLIGHT);
   1082 			self.effects = self.effects - (self.effects & EF_BLUE);
   1083 		}
   1084 	}       
   1085 
   1086 // suit 
   1087 	if (self.radsuit_finished)
   1088 	{
   1089 		self.air_finished = time + 12;          // don't drown
   1090 
   1091 // sound and screen flash when items starts to run out
   1092 		if (self.radsuit_finished < time + 3)
   1093 		{
   1094 			if (self.rad_time == 1)
   1095 			{
   1096 				sprint (self, PRINT_HIGH, "Air supply in Biosuit expiring\n");
   1097 				stuffcmd (self, "bf\n");
   1098 				sound (self, CHAN_AUTO, "items/suit2.wav", 1, ATTN_NORM);
   1099 				self.rad_time = time + 1;
   1100 			}
   1101 			
   1102 			if (self.rad_time < time)
   1103 			{
   1104 				self.rad_time = time + 1;
   1105 				stuffcmd (self, "bf\n");
   1106 			}
   1107 		}
   1108 
   1109 		if (self.radsuit_finished < time)
   1110 		{       // just stopped
   1111 			self.items = self.items - IT_SUIT;
   1112 			self.rad_time = 0;
   1113 			self.radsuit_finished = 0;
   1114 		}
   1115 	}       
   1116 
   1117 };
   1118 
   1119 
   1120 /*
   1121 ================
   1122 PlayerPostThink
   1123 
   1124 Called every frame after physics are run
   1125 ================
   1126 */
   1127 void() PlayerPostThink =
   1128 {
   1129 	local   float   mspeed, aspeed;
   1130 	local   float   r;
   1131 
   1132 //dprint ("post think\n");
   1133 	if (self.view_ofs == '0 0 0')
   1134 		return;         // intermission or finale
   1135 	if (self.deadflag)
   1136 		return;
   1137 
   1138 // check to see if player landed and play landing sound 
   1139 	if ((self.jump_flag < -300) && (self.flags & FL_ONGROUND) )
   1140 	{
   1141 		if (self.watertype == CONTENT_WATER)
   1142 			sound (self, CHAN_BODY, "player/h2ojump.wav", 1, ATTN_NORM);
   1143 		else if (self.jump_flag < -650)
   1144 		{
   1145 			self.deathtype = "falling";
   1146 			T_Damage (self, world, world, 5); 
   1147 			sound (self, CHAN_VOICE, "player/land2.wav", 1, ATTN_NORM);
   1148 		}
   1149 		else
   1150 			sound (self, CHAN_VOICE, "player/land.wav", 1, ATTN_NORM);
   1151 	}
   1152 
   1153 	self.jump_flag = self.velocity_z;
   1154 
   1155 	CheckPowerups ();
   1156 
   1157 	W_WeaponFrame ();
   1158 
   1159 };
   1160 
   1161 
   1162 /*
   1163 ===========
   1164 ClientConnect
   1165 
   1166 called when a player connects to a server
   1167 ============
   1168 */
   1169 void() ClientConnect =
   1170 {
   1171 	bprint (PRINT_HIGH, self.netname);
   1172 	bprint (PRINT_HIGH, " entered the game\n");
   1173 	
   1174 // a client connecting during an intermission can cause problems
   1175 	if (intermission_running)
   1176 		GotoNextMap ();
   1177 };
   1178 
   1179 
   1180 /*
   1181 ===========
   1182 ClientDisconnect
   1183 
   1184 called when a player disconnects from a server
   1185 ============
   1186 */
   1187 void() ClientDisconnect =
   1188 {
   1189 	// let everyone else know
   1190 	bprint (PRINT_HIGH, self.netname);
   1191 		bprint (PRINT_HIGH, " left the game with ");
   1192 		bprint (PRINT_HIGH, ftos(self.frags));
   1193 		bprint (PRINT_HIGH, " frags\n");
   1194 	sound (self, CHAN_BODY, "player/tornoff2.wav", 1, ATTN_NONE);
   1195 	set_suicide_frame ();
   1196 };
   1197 
   1198 /*
   1199 ===========
   1200 ClientObituary
   1201 
   1202 called when a player dies
   1203 ============
   1204 */
   1205 
   1206 void(entity targ, entity attacker) ClientObituary =
   1207 {
   1208 	local   float rnum;
   1209 	local   string deathstring, deathstring2;
   1210 	local   string s;
   1211 	local   string  attackerteam, targteam;
   1212 
   1213 	rnum = random();
   1214 	//ZOID 12-13-96: self.team doesn't work in QW.  Use keys
   1215 	attackerteam = infokey(attacker, "team");
   1216 	targteam = infokey(targ, "team");
   1217 
   1218 	if (targ.classname == "player")
   1219 	{
   1220 
   1221 		if (deathmatch > 3)	
   1222 		{
   1223 			if (targ.deathtype == "selfwater")
   1224 			{
   1225 				bprint (PRINT_MEDIUM, targ.netname);
   1226 				bprint (PRINT_MEDIUM," electrocutes himself.\n ");
   1227 				targ.frags = targ.frags - 1;
   1228 				return;
   1229 			}
   1230 		}
   1231 
   1232 		if (attacker.classname == "teledeath")
   1233 		{
   1234 			bprint (PRINT_MEDIUM,targ.netname);
   1235 			bprint (PRINT_MEDIUM," was telefragged by ");
   1236 			bprint (PRINT_MEDIUM,attacker.owner.netname);
   1237 			bprint (PRINT_MEDIUM,"\n");
   1238 			logfrag (attacker.owner, targ);
   1239 
   1240 			attacker.owner.frags = attacker.owner.frags + 1;
   1241 			return;
   1242 		}
   1243 
   1244 		if (attacker.classname == "teledeath2")
   1245 		{
   1246 			bprint (PRINT_MEDIUM,"Satan's power deflects ");
   1247 			bprint (PRINT_MEDIUM,targ.netname);
   1248 			bprint (PRINT_MEDIUM,"'s telefrag\n");
   1249 
   1250 			targ.frags = targ.frags - 1;
   1251 			logfrag (targ, targ);
   1252 			return;
   1253 		}
   1254 
   1255 		// double 666 telefrag (can happen often in deathmatch 4)
   1256 		if (attacker.classname == "teledeath3") 
   1257 		{
   1258 			bprint (PRINT_MEDIUM,targ.netname);
   1259 			bprint (PRINT_MEDIUM," was telefragged by ");
   1260 			bprint (PRINT_MEDIUM,attacker.owner.netname);
   1261 			bprint (PRINT_MEDIUM, "'s Satan's power\n");
   1262 			targ.frags = targ.frags - 1;
   1263 			logfrag (targ, targ);
   1264 			return;
   1265 		}
   1266 	
   1267 
   1268 		if (targ.deathtype == "squish")
   1269 		{
   1270 			if (teamplay && targteam == attackerteam && attackerteam != "" && targ != attacker)
   1271 			{
   1272 				logfrag (attacker, attacker);
   1273 				attacker.frags = attacker.frags - 1; 
   1274 				bprint (PRINT_MEDIUM,attacker.netname);
   1275 				bprint (PRINT_MEDIUM," squished a teammate\n");
   1276 				return;
   1277 			}
   1278 			else if (attacker.classname == "player" && attacker != targ)
   1279 			{
   1280 				bprint (PRINT_MEDIUM, attacker.netname);
   1281 				bprint (PRINT_MEDIUM," squishes ");
   1282 				bprint (PRINT_MEDIUM,targ.netname);
   1283 				bprint (PRINT_MEDIUM,"\n");
   1284 				logfrag (attacker, targ);
   1285 				attacker.frags = attacker.frags + 1;
   1286 				return;
   1287 			}
   1288 			else
   1289 			{
   1290 				logfrag (targ, targ);
   1291 				targ.frags = targ.frags - 1;            // killed self
   1292 				bprint (PRINT_MEDIUM,targ.netname);
   1293 				bprint (PRINT_MEDIUM," was squished\n");
   1294 				return;
   1295 			}
   1296 		}
   1297 
   1298 		if (attacker.classname == "player")
   1299 		{
   1300 			if (targ == attacker)
   1301 			{
   1302 				// killed self
   1303 				logfrag (attacker, attacker);
   1304 				attacker.frags = attacker.frags - 1;
   1305 				bprint (PRINT_MEDIUM,targ.netname);
   1306 				if (targ.deathtype == "grenade")
   1307 					bprint (PRINT_MEDIUM," tries to put the pin back in\n");
   1308 				else if (targ.deathtype == "rocket")
   1309 					bprint (PRINT_MEDIUM," becomes bored with life\n");
   1310 				else if (targ.weapon == 64 && targ.waterlevel > 1)
   1311 				{
   1312 					if (targ.watertype == CONTENT_SLIME)
   1313 						bprint (PRINT_MEDIUM," discharges into the slime\n");
   1314 					else if (targ.watertype == CONTENT_LAVA)
   1315 						bprint (PRINT_MEDIUM," discharges into the lava\n");
   1316 					else
   1317 						bprint (PRINT_MEDIUM," discharges into the water.\n");
   1318 				}
   1319 				else
   1320 					bprint (PRINT_MEDIUM," becomes bored with life\n");
   1321 				return;
   1322 			}
   1323 			else if ( (teamplay == 2) && (targteam == attackerteam) &&
   1324 				(attackerteam != "") )
   1325 			{
   1326 				if (rnum < 0.25)
   1327 					deathstring = " mows down a teammate\n";
   1328 				else if (rnum < 0.50)
   1329 					deathstring = " checks his glasses\n";
   1330 				else if (rnum < 0.75)
   1331 					deathstring = " gets a frag for the other team\n";
   1332 				else
   1333 					deathstring = " loses another friend\n";
   1334 				bprint (PRINT_MEDIUM, attacker.netname);
   1335 				bprint (PRINT_MEDIUM, deathstring);
   1336 				attacker.frags = attacker.frags - 1;
   1337 				//ZOID 12-13-96:  killing a teammate logs as suicide
   1338 				logfrag (attacker, attacker);
   1339 				return;
   1340 			}
   1341 			else
   1342 			{
   1343 				logfrag (attacker, targ);
   1344 				attacker.frags = attacker.frags + 1;
   1345 
   1346 				rnum = attacker.weapon;
   1347 				if (targ.deathtype == "nail")
   1348 				{
   1349 					deathstring = " was nailed by ";
   1350 					deathstring2 = "\n";
   1351 				}
   1352 				else if (targ.deathtype == "supernail")
   1353 				{
   1354 					deathstring = " was punctured by ";
   1355 					deathstring2 = "\n";
   1356 				}
   1357 				else if (targ.deathtype == "grenade")
   1358 				{
   1359 					deathstring = " eats ";
   1360 					deathstring2 = "'s pineapple\n";
   1361 					if (targ.health < -40)
   1362 					{
   1363 						deathstring = " was gibbed by ";
   1364 						deathstring2 = "'s grenade\n";
   1365 					}
   1366 				}
   1367 				else if (targ.deathtype == "rocket")
   1368 				{
   1369 					if (attacker.super_damage_finished > 0 && targ.health < -40)
   1370 					{
   1371 						rnum = random();
   1372 						if (rnum < 0.3)
   1373 							deathstring = " was brutalized by ";
   1374 						else if (rnum < 0.6)
   1375 							deathstring = " was smeared by ";
   1376 						else
   1377 						{
   1378 							bprint (PRINT_MEDIUM, attacker.netname);
   1379 							bprint (PRINT_MEDIUM, " rips ");
   1380 							bprint (PRINT_MEDIUM, targ.netname);
   1381 							bprint (PRINT_MEDIUM, " a new one\n");
   1382 							return;
   1383 						}
   1384 						deathstring2 = "'s quad rocket\n";
   1385 					}
   1386 					else
   1387 					{
   1388 						deathstring = " rides ";
   1389 						deathstring2 = "'s rocket\n";
   1390 						if (targ.health < -40)
   1391 						{
   1392 							deathstring = " was gibbed by ";
   1393 							deathstring2 = "'s rocket\n" ;
   1394 						}
   1395 					}
   1396 				}
   1397 				else if (rnum == IT_AXE)
   1398 				{
   1399 					deathstring = " was ax-murdered by ";
   1400 					deathstring2 = "\n";
   1401 				}
   1402 				else if (rnum == IT_SHOTGUN)
   1403 				{
   1404 					deathstring = " chewed on ";
   1405 					deathstring2 = "'s boomstick\n";
   1406 				}
   1407 				else if (rnum == IT_SUPER_SHOTGUN)
   1408 				{
   1409 					deathstring = " ate 2 loads of ";
   1410 					deathstring2 = "'s buckshot\n";
   1411 				}
   1412 				else if (rnum == IT_LIGHTNING)
   1413 				{
   1414 					deathstring = " accepts ";
   1415 					if (attacker.waterlevel > 1)
   1416 						deathstring2 = "'s discharge\n";
   1417 					else
   1418 						deathstring2 = "'s shaft\n";
   1419 				}
   1420 				bprint (PRINT_MEDIUM,targ.netname);
   1421 				bprint (PRINT_MEDIUM,deathstring);
   1422 				bprint (PRINT_MEDIUM,attacker.netname);
   1423 				bprint (PRINT_MEDIUM,deathstring2);
   1424 			}
   1425 			return;
   1426 		}
   1427 		else
   1428 		{
   1429 			logfrag (targ, targ);
   1430 			targ.frags = targ.frags - 1;            // killed self
   1431 			rnum = targ.watertype;
   1432 
   1433 			bprint (PRINT_MEDIUM,targ.netname);
   1434 			if (rnum == -3)
   1435 			{
   1436 				if (random() < 0.5)
   1437 					bprint (PRINT_MEDIUM," sleeps with the fishes\n");
   1438 				else
   1439 					bprint (PRINT_MEDIUM," sucks it down\n");
   1440 				return;
   1441 			}
   1442 			else if (rnum == -4)
   1443 			{
   1444 				if (random() < 0.5)
   1445 					bprint (PRINT_MEDIUM," gulped a load of slime\n");
   1446 				else
   1447 					bprint (PRINT_MEDIUM," can't exist on slime alone\n");
   1448 				return;
   1449 			}
   1450 			else if (rnum == -5)
   1451 			{
   1452 				if (targ.health < -15)
   1453 				{
   1454 					bprint (PRINT_MEDIUM," burst into flames\n");
   1455 					return;
   1456 				}
   1457 				if (random() < 0.5)
   1458 					bprint (PRINT_MEDIUM," turned into hot slag\n");
   1459 				else
   1460 					bprint (PRINT_MEDIUM," visits the Volcano God\n");
   1461 				return;
   1462 			}
   1463 
   1464 			if (attacker.classname == "explo_box")
   1465 			{
   1466 				bprint (PRINT_MEDIUM," blew up\n");
   1467 				return;
   1468 			}
   1469 			if (targ.deathtype == "falling")
   1470 			{
   1471 				bprint (PRINT_MEDIUM," fell to his death\n");
   1472 				return;
   1473 			}
   1474 			if (targ.deathtype == "nail" || targ.deathtype == "supernail")
   1475 			{
   1476 				bprint (PRINT_MEDIUM," was spiked\n");
   1477 				return;
   1478 			}
   1479 			if (targ.deathtype == "laser")
   1480 			{
   1481 				bprint (PRINT_MEDIUM," was zapped\n");
   1482 				return;
   1483 			}
   1484 			if (attacker.classname == "fireball")
   1485 			{
   1486 				bprint (PRINT_MEDIUM," ate a lavaball\n");
   1487 				return;
   1488 			}
   1489 			if (attacker.classname == "trigger_changelevel")
   1490 			{
   1491 				bprint (PRINT_MEDIUM," tried to leave\n");
   1492 				return;
   1493 			}
   1494 
   1495 			bprint (PRINT_MEDIUM," died\n");
   1496 		}
   1497 	}
   1498 };
   1499