Home | History | Annotate | Download | only in progs
      1 void() W_SetCurrentAmmo;
      2 /* ALL LIGHTS SHOULD BE 0 1 0 IN COLOR ALL OTHER ITEMS SHOULD
      3 BE .8 .3 .4 IN COLOR */
      4 
      5 
      6 void() SUB_regen =
      7 {
      8 	self.model = self.mdl;          // restore original model
      9 	self.solid = SOLID_TRIGGER;     // allow it to be touched again
     10 	sound (self, CHAN_VOICE, "items/itembk2.wav", 1, ATTN_NORM);    // play respawn sound
     11 	setorigin (self, self.origin);
     12 };
     13 
     14 
     15 
     16 /*QUAKED noclass (0 0 0) (-8 -8 -8) (8 8 8)
     17 prints a warning message when spawned
     18 */
     19 void() noclass =
     20 {
     21 	dprint ("noclass spawned at");
     22 	dprint (vtos(self.origin));
     23 	dprint ("\n");
     24 	remove (self);
     25 };
     26 
     27 void() q_touch;
     28 
     29 void() q_touch =
     30 {
     31 local entity    stemp;
     32 local float     best;
     33 local string    s;
     34 
     35 	if (other.classname != "player")
     36 		return;
     37 	if (other.health <= 0)
     38 		return;
     39 
     40 	self.mdl = self.model;
     41 
     42 	sound (other, CHAN_VOICE, self.noise, 1, ATTN_NORM);
     43 	stuffcmd (other, "bf\n");
     44 	self.solid = SOLID_NOT;
     45 	other.items = other.items | IT_QUAD;
     46 	self.model = string_null;
     47 		if (deathmatch == 4)
     48 		{
     49 			other.armortype = 0;
     50 			other.armorvalue = 0 * 0.01;
     51 			other.ammo_cells = 0;
     52 		}
     53 
     54 // do the apropriate action
     55 	other.super_time = 1;
     56 	other.super_damage_finished = self.cnt;
     57 
     58 	s=ftos(rint(other.super_damage_finished - time));
     59 
     60 	bprint (PRINT_LOW, other.netname);
     61 	if (deathmatch == 4)
     62 		bprint (PRINT_LOW, " recovered an OctaPower with ");
     63 	else 
     64 		bprint (PRINT_LOW, " recovered a Quad with ");
     65 	bprint (PRINT_LOW, s);
     66 	bprint (PRINT_LOW, " seconds remaining!\n");
     67 
     68 	activator = other;
     69 	SUB_UseTargets();                               // fire all targets / killtargets
     70 };
     71 
     72 
     73 void(float timeleft) DropQuad =
     74 {
     75 	local entity    item;
     76 
     77 	item = spawn();
     78 	item.origin = self.origin;
     79 	
     80 	item.velocity_z = 300;
     81 	item.velocity_x = -100 + (random() * 200);
     82 	item.velocity_y = -100 + (random() * 200);
     83 	
     84 	item.flags = FL_ITEM;
     85 	item.solid = SOLID_TRIGGER;
     86 	item.movetype = MOVETYPE_TOSS;
     87 	item.noise = "items/damage.wav";
     88 	setmodel (item, "progs/quaddama.mdl");
     89 	setsize (item, '-16 -16 -24', '16 16 32');
     90 	item.cnt = time + timeleft;
     91 	item.touch = q_touch;
     92 	item.nextthink = time + timeleft;    // remove it with the time left on it
     93 	item.think = SUB_Remove;
     94 };
     95 
     96 
     97 void() r_touch;
     98 
     99 void() r_touch =
    100 {
    101 local entity    stemp;
    102 local float     best;
    103 local string    s;
    104 
    105 	if (other.classname != "player")
    106 		return;
    107 	if (other.health <= 0)
    108 		return;
    109 
    110 	self.mdl = self.model;
    111 
    112 	sound (other, CHAN_VOICE, self.noise, 1, ATTN_NORM);
    113 	stuffcmd (other, "bf\n");
    114 	self.solid = SOLID_NOT;
    115 	other.items = other.items | IT_INVISIBILITY;
    116 	self.model = string_null;
    117 
    118 // do the apropriate action
    119 	other.invisible_time = 1;
    120 	other.invisible_finished = self.cnt;
    121 	s=ftos(rint(other.invisible_finished - time));
    122 	bprint (PRINT_LOW, other.netname);
    123 	bprint (PRINT_LOW, " recovered a Ring with ");
    124 	bprint (PRINT_LOW, s);
    125 	bprint (PRINT_LOW, " seconds remaining!\n");
    126       
    127 
    128 	activator = other;
    129 	SUB_UseTargets();                               // fire all targets / killtargets
    130 };
    131 
    132 
    133 void(float timeleft) DropRing =
    134 {
    135 	local entity    item;
    136 
    137 	item = spawn();
    138 	item.origin = self.origin;
    139 	
    140 	item.velocity_z = 300;
    141 	item.velocity_x = -100 + (random() * 200);
    142 	item.velocity_y = -100 + (random() * 200);
    143 	
    144 	item.flags = FL_ITEM;
    145 	item.solid = SOLID_TRIGGER;
    146 	item.movetype = MOVETYPE_TOSS;
    147 	item.noise = "items/inv1.wav";
    148 	setmodel (item, "progs/invisibl.mdl");
    149 	setsize (item, '-16 -16 -24', '16 16 32');
    150 	item.cnt = time + timeleft;
    151 	item.touch = r_touch;
    152 	item.nextthink = time + timeleft;    // remove after 30 seconds
    153 	item.think = SUB_Remove;
    154 };
    155 
    156 /*
    157 ============
    158 PlaceItem
    159 
    160 plants the object on the floor
    161 ============
    162 */
    163 void() PlaceItem =
    164 {
    165 	local float     oldz;
    166 
    167 	self.mdl = self.model;          // so it can be restored on respawn
    168 	self.flags = FL_ITEM;           // make extra wide
    169 	self.solid = SOLID_TRIGGER;
    170 	self.movetype = MOVETYPE_TOSS;  
    171 	self.velocity = '0 0 0';
    172 	self.origin_z = self.origin_z + 6;
    173 	oldz = self.origin_z;
    174 	if (!droptofloor())
    175 	{
    176 		dprint ("Bonus item fell out of level at ");
    177 		dprint (vtos(self.origin));
    178 		dprint ("\n");
    179 		remove(self);
    180 		return;
    181 	}
    182 };
    183 
    184 /*
    185 ============
    186 StartItem
    187 
    188 Sets the clipping size and plants the object on the floor
    189 ============
    190 */
    191 void() StartItem =
    192 {
    193 	self.nextthink = time + 0.2;    // items start after other solids
    194 	self.think = PlaceItem;
    195 };
    196 
    197 /*
    198 =========================================================================
    199 
    200 HEALTH BOX
    201 
    202 =========================================================================
    203 */
    204 //
    205 // T_Heal: add health to an entity, limiting health to max_health
    206 // "ignore" will ignore max_health limit
    207 //
    208 float (entity e, float healamount, float ignore) T_Heal =
    209 {
    210 	if (e.health <= 0)
    211 		return 0;
    212 	if ((!ignore) && (e.health >= other.max_health))
    213 		return 0;
    214 	healamount = ceil(healamount);
    215 
    216 	e.health = e.health + healamount;
    217 	if ((!ignore) && (e.health >= other.max_health))
    218 		e.health = other.max_health;
    219 		
    220 	if (e.health > 250)
    221 		e.health = 250;
    222 	return 1;
    223 };
    224 
    225 /*QUAKED item_health (.3 .3 1) (0 0 0) (32 32 32) rotten megahealth
    226 Health box. Normally gives 25 points.
    227 Rotten box heals 5-10 points,
    228 megahealth will add 100 health, then 
    229 rot you down to your maximum health limit, 
    230 one point per second.
    231 */
    232 
    233 float   H_ROTTEN = 1;
    234 float   H_MEGA = 2;
    235 .float  healamount, healtype;
    236 void() health_touch;
    237 void() item_megahealth_rot;
    238 
    239 void() item_health =
    240 {       
    241 	self.touch = health_touch;
    242 
    243 	if (self.spawnflags & H_ROTTEN)
    244 	{
    245 		precache_model("maps/b_bh10.bsp");
    246 
    247 		precache_sound("items/r_item1.wav");
    248 		setmodel(self, "maps/b_bh10.bsp");
    249 		self.noise = "items/r_item1.wav";
    250 		self.healamount = 15;
    251 		self.healtype = 0;
    252 	}
    253 	else
    254 	if (self.spawnflags & H_MEGA)
    255 	{
    256 		precache_model("maps/b_bh100.bsp");
    257 		precache_sound("items/r_item2.wav");
    258 		setmodel(self, "maps/b_bh100.bsp");
    259 		self.noise = "items/r_item2.wav";
    260 		self.healamount = 100;
    261 		self.healtype = 2;
    262 	}
    263 	else
    264 	{
    265 		precache_model("maps/b_bh25.bsp");
    266 		precache_sound("items/health1.wav");
    267 		setmodel(self, "maps/b_bh25.bsp");
    268 		self.noise = "items/health1.wav";
    269 		self.healamount = 25;
    270 		self.healtype = 1;
    271 	}
    272 	setsize (self, '0 0 0', '32 32 56');
    273 	StartItem ();
    274 };
    275 
    276 
    277 void() health_touch =
    278 {
    279 	local   float amount;
    280 	local   string  s;
    281 	
    282 	if (deathmatch == 4)
    283 		if (other.invincible_time > 0)
    284 			return;
    285 
    286 	if (other.classname != "player")
    287 		return;
    288 	
    289 	if (self.healtype == 2) // Megahealth?  Ignore max_health...
    290 	{
    291 		if (other.health >= 250)
    292 			return;
    293 		if (!T_Heal(other, self.healamount, 1))
    294 			return;
    295 	}
    296 	else
    297 	{
    298 		if (!T_Heal(other, self.healamount, 0))
    299 			return;
    300 	}
    301 	
    302 	sprint(other, PRINT_LOW, "You receive ");
    303 	s = ftos(self.healamount);
    304 	sprint(other, PRINT_LOW, s);
    305 	sprint(other, PRINT_LOW, " health\n");
    306 	
    307 // health touch sound
    308 	sound(other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
    309 
    310 	stuffcmd (other, "bf\n");
    311 	
    312 	self.model = string_null;
    313 	self.solid = SOLID_NOT;
    314 
    315 	// Megahealth = rot down the player's super health
    316 	if (self.healtype == 2)
    317 	{
    318 		other.items = other.items | IT_SUPERHEALTH;
    319 		if (deathmatch != 4)
    320 		{
    321 			self.nextthink = time + 5;
    322 			self.think = item_megahealth_rot;
    323 		}
    324 		self.owner = other;
    325 	}
    326 	else
    327 	{
    328 		if (deathmatch != 2)            // deathmatch 2 is the silly old rules
    329 		{
    330 			self.nextthink = time + 20;
    331 			self.think = SUB_regen;
    332 		}
    333 	}
    334 	
    335 	activator = other;
    336 	SUB_UseTargets();                               // fire all targets / killtargets
    337 };      
    338 
    339 void() item_megahealth_rot =
    340 {
    341 	other = self.owner;
    342 	
    343 	if (other.health > other.max_health)
    344 	{
    345 		other.health = other.health - 1;
    346 		self.nextthink = time + 1;
    347 		return;
    348 	}
    349 
    350 // it is possible for a player to die and respawn between rots, so don't
    351 // just blindly subtract the flag off
    352 	other.items = other.items - (other.items & IT_SUPERHEALTH);
    353 	
    354 	if (deathmatch != 2)    // deathmatch 2 is silly old rules
    355 	{
    356 		self.nextthink = time + 20;
    357 		self.think = SUB_regen;
    358 	}
    359 };
    360 
    361 /*
    362 ===============================================================================
    363 
    364 ARMOR
    365 
    366 ===============================================================================
    367 */
    368 
    369 void() armor_touch;
    370 
    371 void() armor_touch =
    372 {
    373 	local   float   type, value, bit;
    374 	
    375 	if (other.health <= 0)
    376 		return;
    377 	if (other.classname != "player")
    378 		return;
    379 
    380 	if (deathmatch == 4)
    381 		if (other.invincible_time > 0)
    382 			return;
    383 
    384 	if (self.classname == "item_armor1")
    385 	{
    386 		type = 0.3;
    387 		value = 100;
    388 		bit = IT_ARMOR1;
    389 	}
    390 	if (self.classname == "item_armor2")
    391 	{
    392 		type = 0.6;
    393 		value = 150;
    394 		bit = IT_ARMOR2;
    395 	}
    396 	if (self.classname == "item_armorInv")
    397 	{
    398 		type = 0.8;
    399 		value = 200;
    400 		bit = IT_ARMOR3;
    401 	}
    402 	if (other.armortype*other.armorvalue >= type*value)
    403 		return;
    404 		
    405 	other.armortype = type;
    406 	other.armorvalue = value;
    407 	other.items = other.items - (other.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3)) + bit;
    408 
    409 	self.solid = SOLID_NOT;
    410 	self.model = string_null;
    411 	if (deathmatch != 2)
    412 		self.nextthink = time + 20;
    413 	self.think = SUB_regen;
    414 
    415 	sprint(other, PRINT_LOW, "You got armor\n");
    416 // armor touch sound
    417 	sound(other, CHAN_ITEM, "items/armor1.wav", 1, ATTN_NORM);
    418 	stuffcmd (other, "bf\n");
    419 	
    420 	activator = other;
    421 	SUB_UseTargets();                               // fire all targets / killtargets
    422 };
    423 
    424 
    425 /*QUAKED item_armor1 (0 .5 .8) (-16 -16 0) (16 16 32)
    426 */
    427 
    428 void() item_armor1 =
    429 {
    430 	self.touch = armor_touch;
    431 	precache_model ("progs/armor.mdl");
    432 	setmodel (self, "progs/armor.mdl");
    433 	self.skin = 0;
    434 	setsize (self, '-16 -16 0', '16 16 56');
    435 	StartItem ();
    436 };
    437 
    438 /*QUAKED item_armor2 (0 .5 .8) (-16 -16 0) (16 16 32)
    439 */
    440 
    441 void() item_armor2 =
    442 {
    443 	self.touch = armor_touch;
    444 	precache_model ("progs/armor.mdl");
    445 	setmodel (self, "progs/armor.mdl");
    446 	self.skin = 1;
    447 	setsize (self, '-16 -16 0', '16 16 56');
    448 	StartItem ();
    449 };
    450 
    451 /*QUAKED item_armorInv (0 .5 .8) (-16 -16 0) (16 16 32)
    452 */
    453 
    454 void() item_armorInv =
    455 {
    456 	self.touch = armor_touch;
    457 	precache_model ("progs/armor.mdl");
    458 	setmodel (self, "progs/armor.mdl");
    459 	self.skin = 2;
    460 	setsize (self, '-16 -16 0', '16 16 56');
    461 	StartItem ();
    462 };
    463 
    464 /*
    465 ===============================================================================
    466 
    467 WEAPONS
    468 
    469 ===============================================================================
    470 */
    471 
    472 void() bound_other_ammo =
    473 {
    474 	if (other.ammo_shells > 100)
    475 		other.ammo_shells = 100;
    476 	if (other.ammo_nails > 200)
    477 		other.ammo_nails = 200;
    478 	if (other.ammo_rockets > 100)
    479 		other.ammo_rockets = 100;               
    480 	if (other.ammo_cells > 100)
    481 		other.ammo_cells = 100;         
    482 };
    483 
    484 
    485 float(float w) RankForWeapon =
    486 {
    487 	if (w == IT_LIGHTNING)
    488 		return 1;
    489 	if (w == IT_ROCKET_LAUNCHER)
    490 		return 2;
    491 	if (w == IT_SUPER_NAILGUN)
    492 		return 3;
    493 	if (w == IT_GRENADE_LAUNCHER)
    494 		return 4;
    495 	if (w == IT_SUPER_SHOTGUN)
    496 		return 5;
    497 	if (w == IT_NAILGUN)
    498 		return 6;
    499 	return 7;
    500 };
    501 
    502 float (float w) WeaponCode =
    503 {
    504 	if (w == IT_SUPER_SHOTGUN)
    505 		return 3;
    506 	if (w == IT_NAILGUN)
    507 		return 4;
    508 	if (w == IT_SUPER_NAILGUN)
    509 		return 5;
    510 	if (w == IT_GRENADE_LAUNCHER)
    511 		return 6;
    512 	if (w == IT_ROCKET_LAUNCHER)
    513 		return 7;
    514 	if (w == IT_LIGHTNING)
    515 		return 8;
    516 	return 1;
    517 };
    518 
    519 /*
    520 =============
    521 Deathmatch_Weapon
    522 
    523 Deathmatch weapon change rules for picking up a weapon
    524 
    525 .float          ammo_shells, ammo_nails, ammo_rockets, ammo_cells;
    526 =============
    527 */
    528 void(float old, float new) Deathmatch_Weapon =
    529 {
    530 	local float or, nr;
    531 
    532 // change self.weapon if desired
    533 	or = RankForWeapon (self.weapon);
    534 	nr = RankForWeapon (new);
    535 	if ( nr < or )
    536 		self.weapon = new;
    537 };
    538 
    539 /*
    540 =============
    541 weapon_touch
    542 =============
    543 */
    544 float() W_BestWeapon;
    545 
    546 void() weapon_touch =
    547 {
    548 	local   float   hadammo, best, new, old;
    549 	local   entity  stemp;
    550 	local   float   leave;
    551 
    552 	// For client weapon_switch
    553 	local   float   w_switch;
    554 
    555 	if (!(other.flags & FL_CLIENT))
    556 		return;
    557 
    558 	if ((stof(infokey(other,"w_switch"))) == 0)
    559 		w_switch = 8;
    560 	else
    561 		w_switch = stof(infokey(other,"w_switch"));
    562 	
    563 // if the player was using his best weapon, change up to the new one if better          
    564 	stemp = self;
    565 	self = other;
    566 	best = W_BestWeapon();
    567 	self = stemp;
    568 
    569 	if (deathmatch == 2 || deathmatch == 3 || deathmatch == 5)
    570 		leave = 1;
    571 	else
    572 		leave = 0;
    573 	
    574 	if (self.classname == "weapon_nailgun")
    575 	{
    576 		if (leave && (other.items & IT_NAILGUN) )
    577 			return;
    578 		hadammo = other.ammo_nails;                     
    579 		new = IT_NAILGUN;
    580 		other.ammo_nails = other.ammo_nails + 30;
    581 	}
    582 	else if (self.classname == "weapon_supernailgun")
    583 	{
    584 		if (leave && (other.items & IT_SUPER_NAILGUN) )
    585 			return;
    586 		hadammo = other.ammo_rockets;                   
    587 		new = IT_SUPER_NAILGUN;
    588 		other.ammo_nails = other.ammo_nails + 30;
    589 	}
    590 	else if (self.classname == "weapon_supershotgun")
    591 	{
    592 		if (leave && (other.items & IT_SUPER_SHOTGUN) )
    593 			return;
    594 		hadammo = other.ammo_rockets;                   
    595 		new = IT_SUPER_SHOTGUN;
    596 		other.ammo_shells = other.ammo_shells + 5;
    597 	}
    598 	else if (self.classname == "weapon_rocketlauncher")
    599 	{
    600 		if (leave && (other.items & IT_ROCKET_LAUNCHER) )
    601 			return;
    602 		hadammo = other.ammo_rockets;                   
    603 		new = IT_ROCKET_LAUNCHER;
    604 		other.ammo_rockets = other.ammo_rockets + 5;
    605 	}
    606 	else if (self.classname == "weapon_grenadelauncher")
    607 	{
    608 		if (leave && (other.items & IT_GRENADE_LAUNCHER) )
    609 			return;
    610 		hadammo = other.ammo_rockets;                   
    611 		new = IT_GRENADE_LAUNCHER;
    612 		other.ammo_rockets = other.ammo_rockets + 5;
    613 	}
    614 	else if (self.classname == "weapon_lightning")
    615 	{
    616 		if (leave && (other.items & IT_LIGHTNING))
    617 			return;
    618 		hadammo = other.ammo_rockets;                   
    619 		new = IT_LIGHTNING;
    620 		other.ammo_cells = other.ammo_cells + 15;
    621 	}
    622 	else
    623 		objerror ("weapon_touch: unknown classname");
    624 
    625 	sprint (other, PRINT_LOW, "You got the ");
    626 	sprint (other, PRINT_LOW, self.netname);
    627 	sprint (other, PRINT_LOW, "\n");
    628 // weapon touch sound
    629 	sound (other, CHAN_ITEM, "weapons/pkup.wav", 1, ATTN_NORM);
    630 	stuffcmd (other, "bf\n");
    631 
    632 	bound_other_ammo ();
    633 
    634 // change to the weapon
    635 	old = other.items;
    636 	other.items = other.items | new;
    637 	
    638 	stemp = self;
    639 	self = other;
    640 
    641 	if ( WeaponCode(new) <= w_switch )
    642 	{
    643 		if (self.flags & FL_INWATER)
    644 		{
    645 			if (new != IT_LIGHTNING)
    646 			{
    647 				Deathmatch_Weapon (old, new);
    648 			}
    649 		}
    650 		else
    651 		{                
    652 			Deathmatch_Weapon (old, new);
    653 		}
    654 	}
    655 
    656 	W_SetCurrentAmmo();
    657 
    658 	self = stemp;
    659 
    660 	if (leave)
    661 		return;
    662 
    663 	if (deathmatch!=3 || deathmatch !=5)
    664 	{
    665 	// remove it in single player, or setup for respawning in deathmatch
    666 		self.model = string_null;
    667 		self.solid = SOLID_NOT;
    668 		if (deathmatch != 2)
    669 			self.nextthink = time + 30;
    670 		self.think = SUB_regen;
    671 	}
    672 	activator = other;
    673 	SUB_UseTargets();                               // fire all targets / killtargets
    674 };
    675 
    676 
    677 /*QUAKED weapon_supershotgun (0 .5 .8) (-16 -16 0) (16 16 32)
    678 */
    679 
    680 void() weapon_supershotgun =
    681 {
    682 if (deathmatch <= 3)
    683 {
    684 	precache_model ("progs/g_shot.mdl");
    685 	setmodel (self, "progs/g_shot.mdl");
    686 	self.weapon = IT_SUPER_SHOTGUN;
    687 	self.netname = "Double-barrelled Shotgun";
    688 	self.touch = weapon_touch;
    689 	setsize (self, '-16 -16 0', '16 16 56');
    690 	StartItem ();
    691 }
    692 };
    693 
    694 /*QUAKED weapon_nailgun (0 .5 .8) (-16 -16 0) (16 16 32)
    695 */
    696 
    697 void() weapon_nailgun =
    698 {
    699 if (deathmatch <= 3)
    700 {
    701 	precache_model ("progs/g_nail.mdl");
    702 	setmodel (self, "progs/g_nail.mdl");
    703 	self.weapon = IT_NAILGUN;
    704 	self.netname = "nailgun";
    705 	self.touch = weapon_touch;
    706 	setsize (self, '-16 -16 0', '16 16 56');
    707 	StartItem ();
    708 }
    709 };
    710 
    711 /*QUAKED weapon_supernailgun (0 .5 .8) (-16 -16 0) (16 16 32)
    712 */
    713 
    714 void() weapon_supernailgun =
    715 {
    716 if (deathmatch <= 3)
    717 {
    718 	precache_model ("progs/g_nail2.mdl");
    719 	setmodel (self, "progs/g_nail2.mdl");
    720 	self.weapon = IT_SUPER_NAILGUN;
    721 	self.netname = "Super Nailgun";
    722 	self.touch = weapon_touch;
    723 	setsize (self, '-16 -16 0', '16 16 56');
    724 	StartItem ();
    725 }
    726 };
    727 
    728 /*QUAKED weapon_grenadelauncher (0 .5 .8) (-16 -16 0) (16 16 32)
    729 */
    730 
    731 void() weapon_grenadelauncher =
    732 {
    733 if (deathmatch <= 3)
    734 {
    735 	precache_model ("progs/g_rock.mdl");
    736 	setmodel (self, "progs/g_rock.mdl");
    737 	self.weapon = 3;
    738 	self.netname = "Grenade Launcher";
    739 	self.touch = weapon_touch;
    740 	setsize (self, '-16 -16 0', '16 16 56');
    741 	StartItem ();
    742 }
    743 };
    744 
    745 /*QUAKED weapon_rocketlauncher (0 .5 .8) (-16 -16 0) (16 16 32)
    746 */
    747 
    748 void() weapon_rocketlauncher =
    749 {
    750 if (deathmatch <= 3)
    751 {
    752 	precache_model ("progs/g_rock2.mdl");
    753 	setmodel (self, "progs/g_rock2.mdl");
    754 	self.weapon = 3;
    755 	self.netname = "Rocket Launcher";
    756 	self.touch = weapon_touch;
    757 	setsize (self, '-16 -16 0', '16 16 56');
    758 	StartItem ();
    759 }
    760 };
    761 
    762 
    763 /*QUAKED weapon_lightning (0 .5 .8) (-16 -16 0) (16 16 32)
    764 */
    765 
    766 void() weapon_lightning =
    767 {
    768 if (deathmatch <= 3)
    769 {
    770 	precache_model ("progs/g_light.mdl");
    771 	setmodel (self, "progs/g_light.mdl");
    772 	self.weapon = 3;
    773 	self.netname = "Thunderbolt";
    774 	self.touch = weapon_touch;
    775 	setsize (self, '-16 -16 0', '16 16 56');
    776 	StartItem ();
    777 }
    778 };
    779 
    780 
    781 /*
    782 ===============================================================================
    783 
    784 AMMO
    785 
    786 ===============================================================================
    787 */
    788 
    789 void() ammo_touch =
    790 {
    791 local entity    stemp;
    792 local float             best;
    793 
    794 	if (other.classname != "player")
    795 		return;
    796 	if (other.health <= 0)
    797 		return;
    798 
    799 // if the player was using his best weapon, change up to the new one if better          
    800 	stemp = self;
    801 	self = other;
    802 	best = W_BestWeapon();
    803 	self = stemp;
    804 
    805 
    806 // shotgun
    807 	if (self.weapon == 1)
    808 	{
    809 		if (other.ammo_shells >= 100)
    810 			return;
    811 		other.ammo_shells = other.ammo_shells + self.aflag;
    812 	}
    813 
    814 // spikes
    815 	if (self.weapon == 2)
    816 	{
    817 		if (other.ammo_nails >= 200)
    818 			return;
    819 		other.ammo_nails = other.ammo_nails + self.aflag;
    820 	}
    821 
    822 //      rockets
    823 	if (self.weapon == 3)
    824 	{
    825 		if (other.ammo_rockets >= 100)
    826 			return;
    827 		other.ammo_rockets = other.ammo_rockets + self.aflag;
    828 	}
    829 
    830 //      cells
    831 	if (self.weapon == 4)
    832 	{
    833 		if (other.ammo_cells >= 100)
    834 			return;
    835 		other.ammo_cells = other.ammo_cells + self.aflag;
    836 	}
    837 
    838 	bound_other_ammo ();
    839 	
    840 	sprint (other, PRINT_LOW, "You got the ");
    841 	sprint (other, PRINT_LOW, self.netname);
    842 	sprint (other, PRINT_LOW, "\n");
    843 // ammo touch sound
    844 	sound (other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
    845 	stuffcmd (other, "bf\n");
    846 
    847 // change to a better weapon if appropriate
    848 
    849 	if ( other.weapon == best )
    850 	{
    851 		stemp = self;
    852 		self = other;
    853 		self.weapon = W_BestWeapon();
    854 		W_SetCurrentAmmo ();
    855 		self = stemp;
    856 	}
    857 
    858 // if changed current ammo, update it
    859 	stemp = self;
    860 	self = other;
    861 	W_SetCurrentAmmo();
    862 	self = stemp;
    863 
    864 // remove it in single player, or setup for respawning in deathmatch
    865 	self.model = string_null;
    866 	self.solid = SOLID_NOT;
    867 	if (deathmatch != 2)
    868 		self.nextthink = time + 30;
    869 
    870 // Xian -- If playing in DM 3.0 mode, halve the time ammo respawns        
    871 
    872 	if (deathmatch == 3 || deathmatch == 5)        
    873 		self.nextthink = time + 15;
    874 
    875 	self.think = SUB_regen;
    876 
    877 	activator = other;
    878 	SUB_UseTargets();                               // fire all targets / killtargets
    879 };
    880 
    881 
    882 
    883 
    884 float WEAPON_BIG2 = 1;
    885 
    886 /*QUAKED item_shells (0 .5 .8) (0 0 0) (32 32 32) big
    887 */
    888 
    889 void() item_shells =
    890 {
    891 	if (deathmatch == 4)
    892 		return;
    893 
    894 	self.touch = ammo_touch;
    895 
    896 	if (self.spawnflags & WEAPON_BIG2)
    897 	{
    898 		precache_model ("maps/b_shell1.bsp");
    899 		setmodel (self, "maps/b_shell1.bsp");
    900 		self.aflag = 40;
    901 	}
    902 	else
    903 	{
    904 		precache_model ("maps/b_shell0.bsp");
    905 		setmodel (self, "maps/b_shell0.bsp");
    906 		self.aflag = 20;
    907 	}
    908 	self.weapon = 1;
    909 	self.netname = "shells";
    910 	setsize (self, '0 0 0', '32 32 56');
    911 	StartItem ();
    912 };
    913 
    914 /*QUAKED item_spikes (0 .5 .8) (0 0 0) (32 32 32) big
    915 */
    916 
    917 void() item_spikes =
    918 {
    919 	if (deathmatch == 4)
    920 		return;
    921 
    922 	self.touch = ammo_touch;
    923 
    924 	if (self.spawnflags & WEAPON_BIG2)
    925 	{
    926 		precache_model ("maps/b_nail1.bsp");
    927 		setmodel (self, "maps/b_nail1.bsp");
    928 		self.aflag = 50;
    929 	}
    930 	else
    931 	{
    932 		precache_model ("maps/b_nail0.bsp");
    933 		setmodel (self, "maps/b_nail0.bsp");
    934 		self.aflag = 25;
    935 	}
    936 	self.weapon = 2;
    937 	self.netname = "nails";
    938 	setsize (self, '0 0 0', '32 32 56');
    939 	StartItem ();
    940 
    941 };
    942 
    943 /*QUAKED item_rockets (0 .5 .8) (0 0 0) (32 32 32) big
    944 */
    945 
    946 void() item_rockets =
    947 {
    948 	if (deathmatch == 4)
    949 		return;
    950 
    951 	self.touch = ammo_touch;
    952 
    953 	if (self.spawnflags & WEAPON_BIG2)
    954 	{
    955 		precache_model ("maps/b_rock1.bsp");
    956 		setmodel (self, "maps/b_rock1.bsp");
    957 		self.aflag = 10;
    958 	}
    959 	else
    960 	{
    961 		precache_model ("maps/b_rock0.bsp");
    962 		setmodel (self, "maps/b_rock0.bsp");
    963 		self.aflag = 5;
    964 	}
    965 	self.weapon = 3;
    966 	self.netname = "rockets";
    967 	setsize (self, '0 0 0', '32 32 56');
    968 	StartItem ();
    969 
    970 };
    971 
    972 
    973 /*QUAKED item_cells (0 .5 .8) (0 0 0) (32 32 32) big
    974 */
    975 
    976 void() item_cells =
    977 {
    978 	if (deathmatch == 4)
    979 		return;
    980 
    981 	self.touch = ammo_touch;
    982 
    983 	if (self.spawnflags & WEAPON_BIG2)
    984 	{
    985 		precache_model ("maps/b_batt1.bsp");
    986 		setmodel (self, "maps/b_batt1.bsp");
    987 		self.aflag = 12;
    988 	}
    989 	else
    990 	{
    991 		precache_model ("maps/b_batt0.bsp");
    992 		setmodel (self, "maps/b_batt0.bsp");
    993 		self.aflag = 6;
    994 	}
    995 	self.weapon = 4;
    996 	self.netname = "cells";
    997 	setsize (self, '0 0 0', '32 32 56');
    998 	StartItem ();
    999 
   1000 };
   1001 
   1002 
   1003 /*QUAKED item_weapon (0 .5 .8) (0 0 0) (32 32 32) shotgun rocket spikes big
   1004 DO NOT USE THIS!!!! IT WILL BE REMOVED!
   1005 */
   1006 
   1007 float WEAPON_SHOTGUN = 1;
   1008 float WEAPON_ROCKET = 2;
   1009 float WEAPON_SPIKES = 4;
   1010 float WEAPON_BIG = 8;
   1011 void() item_weapon =
   1012 {
   1013 	self.touch = ammo_touch;
   1014 
   1015 	if (self.spawnflags & WEAPON_SHOTGUN)
   1016 	{
   1017 		if (self.spawnflags & WEAPON_BIG)
   1018 		{
   1019 			precache_model ("maps/b_shell1.bsp");
   1020 			setmodel (self, "maps/b_shell1.bsp");
   1021 			self.aflag = 40;
   1022 		}
   1023 		else
   1024 		{
   1025 			precache_model ("maps/b_shell0.bsp");
   1026 			setmodel (self, "maps/b_shell0.bsp");
   1027 			self.aflag = 20;
   1028 		}
   1029 		self.weapon = 1;
   1030 		self.netname = "shells";
   1031 	}
   1032 
   1033 	if (self.spawnflags & WEAPON_SPIKES)
   1034 	{
   1035 		if (self.spawnflags & WEAPON_BIG)
   1036 		{
   1037 			precache_model ("maps/b_nail1.bsp");
   1038 			setmodel (self, "maps/b_nail1.bsp");
   1039 			self.aflag = 40;
   1040 		}
   1041 		else
   1042 		{
   1043 			precache_model ("maps/b_nail0.bsp");
   1044 			setmodel (self, "maps/b_nail0.bsp");
   1045 			self.aflag = 20;
   1046 		}
   1047 		self.weapon = 2;
   1048 		self.netname = "spikes";
   1049 	}
   1050 
   1051 	if (self.spawnflags & WEAPON_ROCKET)
   1052 	{
   1053 		if (self.spawnflags & WEAPON_BIG)
   1054 		{
   1055 			precache_model ("maps/b_rock1.bsp");
   1056 			setmodel (self, "maps/b_rock1.bsp");
   1057 			self.aflag = 10;
   1058 		}
   1059 		else
   1060 		{
   1061 			precache_model ("maps/b_rock0.bsp");
   1062 			setmodel (self, "maps/b_rock0.bsp");
   1063 			self.aflag = 5;
   1064 		}
   1065 		self.weapon = 3;
   1066 		self.netname = "rockets";
   1067 	}
   1068 	
   1069 	setsize (self, '0 0 0', '32 32 56');
   1070 	StartItem ();
   1071 };
   1072 
   1073 
   1074 /*
   1075 ===============================================================================
   1076 
   1077 KEYS
   1078 
   1079 ===============================================================================
   1080 */
   1081 
   1082 void() key_touch =
   1083 {
   1084 local entity    stemp;
   1085 local float             best;
   1086 
   1087 	if (other.classname != "player")
   1088 		return;
   1089 	if (other.health <= 0)
   1090 		return;
   1091 	if (other.items & self.items)
   1092 		return;
   1093 
   1094 	sprint (other, PRINT_LOW, "You got the ");
   1095 	sprint (other, PRINT_LOW, self.netname);
   1096 	sprint (other,PRINT_LOW, "\n");
   1097 
   1098 	sound (other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
   1099 	stuffcmd (other, "bf\n");
   1100 	other.items = other.items | self.items;
   1101 
   1102 	self.solid = SOLID_NOT;
   1103 	self.model = string_null;
   1104 
   1105 	activator = other;
   1106 	SUB_UseTargets();                               // fire all targets / killtargets
   1107 };
   1108 
   1109 
   1110 void() key_setsounds =
   1111 {
   1112 	if (world.worldtype == 0)
   1113 	{
   1114 		precache_sound ("misc/medkey.wav");
   1115 		self.noise = "misc/medkey.wav";
   1116 	}
   1117 	if (world.worldtype == 1)
   1118 	{
   1119 		precache_sound ("misc/runekey.wav");
   1120 		self.noise = "misc/runekey.wav";
   1121 	}
   1122 	if (world.worldtype == 2)
   1123 	{
   1124 		precache_sound2 ("misc/basekey.wav");
   1125 		self.noise = "misc/basekey.wav";
   1126 	}
   1127 };
   1128 
   1129 /*QUAKED item_key1 (0 .5 .8) (-16 -16 -24) (16 16 32)
   1130 SILVER key
   1131 In order for keys to work
   1132 you MUST set your maps
   1133 worldtype to one of the
   1134 following:
   1135 0: medieval
   1136 1: metal
   1137 2: base
   1138 */
   1139 
   1140 void() item_key1 =
   1141 {
   1142 	if (world.worldtype == 0)
   1143 	{
   1144 		precache_model ("progs/w_s_key.mdl");
   1145 		setmodel (self, "progs/w_s_key.mdl");
   1146 		self.netname = "silver key";
   1147 	}
   1148 	else if (world.worldtype == 1)
   1149 	{
   1150 		precache_model ("progs/m_s_key.mdl");
   1151 		setmodel (self, "progs/m_s_key.mdl");
   1152 		self.netname = "silver runekey";
   1153 	}
   1154 	else if (world.worldtype == 2)
   1155 	{
   1156 		precache_model2 ("progs/b_s_key.mdl");
   1157 		setmodel (self, "progs/b_s_key.mdl");
   1158 		self.netname = "silver keycard";
   1159 	}
   1160 	key_setsounds();
   1161 	self.touch = key_touch;
   1162 	self.items = IT_KEY1;
   1163 	setsize (self, '-16 -16 -24', '16 16 32');
   1164 	StartItem ();
   1165 };
   1166 
   1167 /*QUAKED item_key2 (0 .5 .8) (-16 -16 -24) (16 16 32)
   1168 GOLD key
   1169 In order for keys to work
   1170 you MUST set your maps
   1171 worldtype to one of the
   1172 following:
   1173 0: medieval
   1174 1: metal
   1175 2: base
   1176 */
   1177 
   1178 void() item_key2 =
   1179 {
   1180 	if (world.worldtype == 0)
   1181 	{
   1182 		precache_model ("progs/w_g_key.mdl");
   1183 		setmodel (self, "progs/w_g_key.mdl");
   1184 		self.netname = "gold key";
   1185 	}
   1186 	if (world.worldtype == 1)
   1187 	{
   1188 		precache_model ("progs/m_g_key.mdl");
   1189 		setmodel (self, "progs/m_g_key.mdl");
   1190 		self.netname = "gold runekey";
   1191 	}
   1192 	if (world.worldtype == 2)
   1193 	{
   1194 		precache_model2 ("progs/b_g_key.mdl");
   1195 		setmodel (self, "progs/b_g_key.mdl");
   1196 		self.netname = "gold keycard";
   1197 	}
   1198 	key_setsounds();
   1199 	self.touch = key_touch;
   1200 	self.items = IT_KEY2;
   1201 	setsize (self, '-16 -16 -24', '16 16 32');
   1202 	StartItem ();
   1203 };
   1204 
   1205 
   1206 
   1207 /*
   1208 ===============================================================================
   1209 
   1210 END OF LEVEL RUNES
   1211 
   1212 ===============================================================================
   1213 */
   1214 
   1215 void() sigil_touch =
   1216 {
   1217 local entity    stemp;
   1218 local float             best;
   1219 
   1220 	if (other.classname != "player")
   1221 		return;
   1222 	if (other.health <= 0)
   1223 		return;
   1224 
   1225 	centerprint (other, "You got the rune!");
   1226 
   1227 	sound (other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
   1228 	stuffcmd (other, "bf\n");
   1229 	self.solid = SOLID_NOT;
   1230 	self.model = string_null;
   1231 	serverflags = serverflags | (self.spawnflags & 15);
   1232 	self.classname = "";            // so rune doors won't find it
   1233 	
   1234 	activator = other;
   1235 	SUB_UseTargets();                               // fire all targets / killtargets
   1236 };
   1237 
   1238 
   1239 /*QUAKED item_sigil (0 .5 .8) (-16 -16 -24) (16 16 32) E1 E2 E3 E4
   1240 End of level sigil, pick up to end episode and return to jrstart.
   1241 */
   1242 
   1243 void() item_sigil =
   1244 {
   1245 	if (!self.spawnflags)
   1246 		objerror ("no spawnflags");
   1247 
   1248 	precache_sound ("misc/runekey.wav");
   1249 	self.noise = "misc/runekey.wav";
   1250 
   1251 	if (self.spawnflags & 1)
   1252 	{
   1253 		precache_model ("progs/end1.mdl");
   1254 		setmodel (self, "progs/end1.mdl");
   1255 	}
   1256 	if (self.spawnflags & 2)
   1257 	{
   1258 		precache_model2 ("progs/end2.mdl");
   1259 		setmodel (self, "progs/end2.mdl");
   1260 	}
   1261 	if (self.spawnflags & 4)
   1262 	{
   1263 		precache_model2 ("progs/end3.mdl");
   1264 		setmodel (self, "progs/end3.mdl");
   1265 	}
   1266 	if (self.spawnflags & 8)
   1267 	{
   1268 		precache_model2 ("progs/end4.mdl");
   1269 		setmodel (self, "progs/end4.mdl");
   1270 	}
   1271 	
   1272 	self.touch = sigil_touch;
   1273 	setsize (self, '-16 -16 -24', '16 16 32');
   1274 	StartItem ();
   1275 };
   1276 
   1277 /*
   1278 ===============================================================================
   1279 
   1280 POWERUPS
   1281 
   1282 ===============================================================================
   1283 */
   1284 
   1285 void() powerup_touch;
   1286 
   1287 
   1288 void() powerup_touch =
   1289 {
   1290 local entity    stemp;
   1291 local float             best;
   1292 
   1293 	if (other.classname != "player")
   1294 		return;
   1295 	if (other.health <= 0)
   1296 		return;
   1297 
   1298 	sprint (other, PRINT_LOW, "You got the ");
   1299 	sprint (other,PRINT_LOW,  self.netname);
   1300 	sprint (other,PRINT_LOW, "\n");
   1301 
   1302 	self.mdl = self.model;
   1303 	
   1304 	if ((self.classname == "item_artifact_invulnerability") ||
   1305 		(self.classname == "item_artifact_invisibility"))
   1306 		self.nextthink = time + 60*5;
   1307 	else
   1308 		self.nextthink = time + 60;
   1309 	
   1310 	self.think = SUB_regen;
   1311 
   1312 	sound (other, CHAN_VOICE, self.noise, 1, ATTN_NORM);
   1313 	stuffcmd (other, "bf\n");
   1314 	self.solid = SOLID_NOT;
   1315 	other.items = other.items | self.items;
   1316 	self.model = string_null;
   1317 
   1318 // do the apropriate action
   1319 	if (self.classname == "item_artifact_envirosuit")
   1320 	{
   1321 		other.rad_time = 1;
   1322 		other.radsuit_finished = time + 30;
   1323 	}
   1324 	
   1325 	if (self.classname == "item_artifact_invulnerability")
   1326 	{
   1327 		other.invincible_time = 1;
   1328 		other.invincible_finished = time + 30;
   1329 	}
   1330 	
   1331 	if (self.classname == "item_artifact_invisibility")
   1332 	{
   1333 		other.invisible_time = 1;
   1334 		other.invisible_finished = time + 30;
   1335 	}
   1336 
   1337 	if (self.classname == "item_artifact_super_damage")
   1338 	{
   1339 		if (deathmatch == 4)
   1340 		{
   1341 			other.armortype = 0;
   1342 			other.armorvalue = 0 * 0.01;
   1343 			other.ammo_cells = 0;
   1344 		}
   1345 		other.super_time = 1;
   1346 		other.super_damage_finished = time + 30;
   1347 	}       
   1348 
   1349 	activator = other;
   1350 	SUB_UseTargets();                               // fire all targets / killtargets
   1351 };
   1352 
   1353 
   1354 
   1355 /*QUAKED item_artifact_invulnerability (0 .5 .8) (-16 -16 -24) (16 16 32)
   1356 Player is invulnerable for 30 seconds
   1357 */
   1358 void() item_artifact_invulnerability =
   1359 {
   1360 	self.touch = powerup_touch;
   1361 
   1362 	precache_model ("progs/invulner.mdl");
   1363 	precache_sound ("items/protect.wav");
   1364 	precache_sound ("items/protect2.wav");
   1365 	precache_sound ("items/protect3.wav");
   1366 	self.noise = "items/protect.wav";
   1367 	setmodel (self, "progs/invulner.mdl");
   1368 	self.netname = "Pentagram of Protection";
   1369 	self.effects = self.effects | EF_RED;
   1370 	self.items = IT_INVULNERABILITY;
   1371 	setsize (self, '-16 -16 -24', '16 16 32');
   1372 	StartItem ();
   1373 };
   1374 
   1375 /*QUAKED item_artifact_envirosuit (0 .5 .8) (-16 -16 -24) (16 16 32)
   1376 Player takes no damage from water or slime for 30 seconds
   1377 */
   1378 void() item_artifact_envirosuit =
   1379 {
   1380 	self.touch = powerup_touch;
   1381 
   1382 	precache_model ("progs/suit.mdl");
   1383 	precache_sound ("items/suit.wav");
   1384 	precache_sound ("items/suit2.wav");
   1385 	self.noise = "items/suit.wav";
   1386 	setmodel (self, "progs/suit.mdl");
   1387 	self.netname = "Biosuit";
   1388 	self.items = IT_SUIT;
   1389 	setsize (self, '-16 -16 -24', '16 16 32');
   1390 	StartItem ();
   1391 };
   1392 
   1393 
   1394 /*QUAKED item_artifact_invisibility (0 .5 .8) (-16 -16 -24) (16 16 32)
   1395 Player is invisible for 30 seconds
   1396 */
   1397 void() item_artifact_invisibility =
   1398 {
   1399 	self.touch = powerup_touch;
   1400 
   1401 	precache_model ("progs/invisibl.mdl");
   1402 	precache_sound ("items/inv1.wav");
   1403 	precache_sound ("items/inv2.wav");
   1404 	precache_sound ("items/inv3.wav");
   1405 	self.noise = "items/inv1.wav";
   1406 	setmodel (self, "progs/invisibl.mdl");
   1407 	self.netname = "Ring of Shadows";
   1408 	self.items = IT_INVISIBILITY;
   1409 	setsize (self, '-16 -16 -24', '16 16 32');
   1410 	StartItem ();
   1411 };
   1412 
   1413 
   1414 /*QUAKED item_artifact_super_damage (0 .5 .8) (-16 -16 -24) (16 16 32)
   1415 The next attack from the player will do 4x damage
   1416 */
   1417 void() item_artifact_super_damage =
   1418 {
   1419 	self.touch = powerup_touch;
   1420 
   1421 	precache_model ("progs/quaddama.mdl");
   1422 	precache_sound ("items/damage.wav");
   1423 	precache_sound ("items/damage2.wav");
   1424 	precache_sound ("items/damage3.wav");
   1425 	self.noise = "items/damage.wav";
   1426 	setmodel (self, "progs/quaddama.mdl");
   1427 	if (deathmatch == 4)
   1428 		self.netname = "OctaPower";	
   1429 	else
   1430 		self.netname = "Quad Damage";
   1431 	self.items = IT_QUAD;
   1432 	self.effects = self.effects | EF_BLUE;
   1433 	setsize (self, '-16 -16 -24', '16 16 32');
   1434 	StartItem ();
   1435 };
   1436 
   1437 
   1438 
   1439 /*
   1440 ===============================================================================
   1441 
   1442 PLAYER BACKPACKS
   1443 
   1444 ===============================================================================
   1445 */
   1446 
   1447 void() BackpackTouch =
   1448 {
   1449 	local string    s;
   1450 	local   float   best, old, new;
   1451 	local           entity  stemp;
   1452 	local   float   acount;
   1453 	local   float   b_switch;
   1454 
   1455 	if (deathmatch == 4)
   1456 		if (other.invincible_time > 0)
   1457 			return;
   1458 
   1459 	if ((stof(infokey(other,"b_switch"))) == 0)
   1460 		b_switch = 8;
   1461 	else
   1462 		b_switch = stof(infokey(other,"b_switch"));
   1463 	
   1464 
   1465 	if (other.classname != "player")
   1466 		return;
   1467 	if (other.health <= 0)
   1468 		return;
   1469 		
   1470 	acount = 0;
   1471 	sprint (other, PRINT_LOW, "You get ");
   1472  
   1473 	if (deathmatch == 4)
   1474 	{       
   1475 		other.health = other.health + 10;
   1476 		sprint (other, PRINT_LOW, "10 additional health\n");
   1477 		if ((other.health > 250) && (other.health < 300))
   1478 			sound (other, CHAN_ITEM, "items/protect3.wav", 1, ATTN_NORM);
   1479 		else
   1480 			sound (other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
   1481 		stuffcmd (other, "bf\n");
   1482 		remove(self);
   1483 
   1484 		if (other.health >299)
   1485 		{               
   1486 			if (other.invincible_time != 1)
   1487 			{                       
   1488 				other.invincible_time = 1;
   1489 				other.invincible_finished = time + 30;
   1490 				other.items = other.items | IT_INVULNERABILITY;
   1491 				
   1492 				other.super_time = 1;
   1493 				other.super_damage_finished = time + 30;
   1494 				other.items = other.items | IT_QUAD;
   1495 
   1496 				other.ammo_cells = 0;		
   1497 		
   1498 	
   1499 				sound (other, CHAN_VOICE, "boss1/sight1.wav", 1, ATTN_NORM);
   1500 				stuffcmd (other, "bf\n");               
   1501 				bprint (PRINT_HIGH, other.netname);
   1502 				bprint (PRINT_HIGH, " attains bonus powers!!!\n");
   1503 			}
   1504 		}
   1505 		self = other;
   1506 		return;
   1507 	}
   1508 	if (self.items)
   1509 		if ((other.items & self.items) == 0)
   1510 		{
   1511 			acount = 1;
   1512 			sprint (other, PRINT_LOW, "the ");
   1513 			sprint (other, PRINT_LOW, self.netname);
   1514 		}
   1515  
   1516 // if the player was using his best weapon, change up to the new one if better          
   1517 	stemp = self;
   1518 	self = other;
   1519 	best = W_BestWeapon();
   1520 	self = stemp;
   1521 
   1522 // change weapons
   1523 	other.ammo_shells = other.ammo_shells + self.ammo_shells;
   1524 	other.ammo_nails = other.ammo_nails + self.ammo_nails;
   1525 	other.ammo_rockets = other.ammo_rockets + self.ammo_rockets;
   1526 	other.ammo_cells = other.ammo_cells + self.ammo_cells;
   1527 
   1528 	new = self.items;
   1529 	if (!new)
   1530 		new = other.weapon;
   1531 	old = other.items;
   1532 	other.items = other.items | self.items;
   1533 	
   1534 	bound_other_ammo ();
   1535 
   1536 	if (self.ammo_shells)
   1537 	{
   1538 		if (acount)
   1539 			sprint(other, PRINT_LOW, ", ");
   1540 		acount = 1;
   1541 		s = ftos(self.ammo_shells);
   1542 		sprint (other, PRINT_LOW, s);
   1543 		sprint (other, PRINT_LOW, " shells");
   1544 	}
   1545 	if (self.ammo_nails)
   1546 	{
   1547 		if (acount)
   1548 			sprint(other, PRINT_LOW, ", ");
   1549 		acount = 1;
   1550 		s = ftos(self.ammo_nails);
   1551 		sprint (other, PRINT_LOW, s);
   1552 		sprint (other, PRINT_LOW, " nails");
   1553 	}
   1554 	if (self.ammo_rockets)
   1555 	{
   1556 		if (acount)
   1557 			sprint(other, PRINT_LOW, ", ");
   1558 		acount = 1;
   1559 		s = ftos(self.ammo_rockets);
   1560 		sprint (other, PRINT_LOW, s);
   1561 		sprint (other, PRINT_LOW, " rockets");
   1562 	}
   1563 	if (self.ammo_cells)
   1564 	{
   1565 		if (acount)
   1566 			sprint(other, PRINT_LOW, ", ");
   1567 		acount = 1;
   1568 		s = ftos(self.ammo_cells);
   1569 		sprint (other, PRINT_LOW, s);
   1570 		sprint (other,PRINT_LOW, " cells");
   1571 	}
   1572 	
   1573 	if ( (deathmatch==3 || deathmatch == 5) & ( (WeaponCode(new)==6) || (WeaponCode(new)==7) ) & (other.ammo_rockets < 5) )
   1574 		other.ammo_rockets = 5;
   1575 
   1576 	sprint (other, PRINT_LOW, "\n");
   1577 // backpack touch sound
   1578 	sound (other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
   1579 	stuffcmd (other, "bf\n");
   1580 
   1581 	remove(self);
   1582 	self = other;
   1583 	
   1584 // change to the weapon
   1585 	
   1586 	
   1587 	if ( WeaponCode(new) <= b_switch )
   1588 	{
   1589 		if (self.flags & FL_INWATER)
   1590 		{
   1591 			if (new != IT_LIGHTNING)
   1592 			{
   1593 				Deathmatch_Weapon (old, new);
   1594 			}
   1595 		}
   1596 		else
   1597 		{                
   1598 			Deathmatch_Weapon (old, new);
   1599 		}
   1600 	}
   1601 
   1602 	W_SetCurrentAmmo ();
   1603 };
   1604 
   1605 /*
   1606 ===============
   1607 DropBackpack
   1608 ===============
   1609 */
   1610 void() DropBackpack =
   1611 {
   1612 	local entity    item;
   1613 
   1614 	if (!(self.ammo_shells + self.ammo_nails + self.ammo_rockets + self.ammo_cells))
   1615 		return; // nothing in it
   1616 
   1617 	item = spawn();
   1618 	item.origin = self.origin - '0 0 24';
   1619 	
   1620 	item.items = self.weapon;
   1621 	if (item.items == IT_AXE)
   1622 		item.netname = "Axe";
   1623 	else if (item.items == IT_SHOTGUN)
   1624 		item.netname = "Shotgun";
   1625 	else if (item.items == IT_SUPER_SHOTGUN)
   1626 		item.netname = "Double-barrelled Shotgun";
   1627 	else if (item.items == IT_NAILGUN)
   1628 		item.netname = "Nailgun";
   1629 	else if (item.items == IT_SUPER_NAILGUN)
   1630 		item.netname = "Super Nailgun";
   1631 	else if (item.items == IT_GRENADE_LAUNCHER)
   1632 		item.netname = "Grenade Launcher";
   1633 	else if (item.items == IT_ROCKET_LAUNCHER)
   1634 		item.netname = "Rocket Launcher";
   1635 	else if (item.items == IT_LIGHTNING)
   1636 		item.netname = "Thunderbolt";
   1637 	else
   1638 		item.netname = "";
   1639 
   1640 	item.ammo_shells = self.ammo_shells;
   1641 	item.ammo_nails = self.ammo_nails;
   1642 	item.ammo_rockets = self.ammo_rockets;
   1643 	item.ammo_cells = self.ammo_cells;
   1644 
   1645 	item.velocity_z = 300;
   1646 	item.velocity_x = -100 + (random() * 200);
   1647 	item.velocity_y = -100 + (random() * 200);
   1648 	
   1649 	item.flags = FL_ITEM;
   1650 	item.solid = SOLID_TRIGGER;
   1651 	item.movetype = MOVETYPE_TOSS;
   1652 	setmodel (item, "progs/backpack.mdl");
   1653 	setsize (item, '-16 -16 0', '16 16 56');
   1654 	item.touch = BackpackTouch;
   1655 	
   1656 	item.nextthink = time + 120;    // remove after 2 minutes
   1657 	item.think = SUB_Remove;
   1658 };
   1659 
   1660 
   1661