/*
    weapons.qc

*** KeyMix 1.2 ***

This is a combination of code from Jiend, Multiskins, and gibbin3,
with a little changing of the impulses from me.  You can set impulse
200-218 in your autoexec.cfg to start as that skin, but for some reason
if you go to a new level, you have to re-do it.  I recommend binding a
key to that impulse.  Also, I recommend binding the [ and ] keys to
impulses 198 and 199 respectively.  These allow you to change skins at
will.  I will be adding various things to these as more new things come
out, and I actually develop some of my own stuff...  :)

I enabled the electro-axe from the J-fiend code, but left the proximity
mines off. They kinda suck for deathmatch, and if you fire too many of
them you start getting packet overflow errors, and your sound cuts out.

In addition I marked some lines of code that if you rem out will
enable the various cheats in deathmatch.  However, since the server
controls it, that means that EVERYONE can use the cheats. It's pointless
for deathmatch, as that takes all the fun out of the game, but it's nice
to know for debugging.

Changes for v1.1

- After getting my ass kicked a couple times as the demon (25 to -2, by
my roommate, Kalima) I decided the demon needed to be just a WEE BIT
tougher.  Basically all I can say now is you'd better kill it before it
gets anywhere near you.  And I changed the Pentagram so that it also acts
like a megahealth box.  The main problem with the demon is that it doesn't
have a long-range weapon, so against 3 guys with rockets, well, it needed
to be tougher.  An interesting side note is that if the level ends with
someone as the demon, everyone who's not a demon will see his arms and legs
sticking out from that vantage camera angle.  Kinda funky.

For some reason, the text that goes with MultiSkin is cycling over and over
and not leaving the screen.  That gets really annoying, so I disabled it.
Have to figure out what the prob. is and fix it for v1.2.

-KeyTrap
gaunt@cdsnet.net

********************  Text from JFiend *************************

    Mods:
        OFF Electro-Axe
        OFF Cluster-Bouncy-Proximity Grenades (Now with quick deployment!)

    Detail:
        * Electro-Axe -- The axe will now do 50 damage (instead of 20) when
        an enemy is hit and you have cells.  5 cells will be used.  If you
        have no cells, you'll do the normal amount of damage.  Also added a
        nice *SMACK* sound (borrowed from the zombies) for when the axe hits
        flesh.
        * Cluster-Bouncy-Proximity Grenades  -- Grenades are now bouncy
        proximity mines.  A grenade will lay on the floor and hop at
        intervals.  If a target is detected within range, the grenade will
        hop towards the target and explode.  Grenades won't detect targets
        while they're in the air.  When the grenade launcher is fired, if you
        have less than five ammo you will fire a single grenade which
        will behave as described above.  If you have 5 or more ammo, you'll
        fire a cluster bomb which will explode and release five proximity
        grenades.

        JFiend Mods by
                John Spickes jspickes@eng.umd.edu {JDS}
                Josh Spickes spickesj@wam.umd.edu
                Allen Seger

********************  Text from Kicking2 *************************

 Modifications by AsmodeusB
 (28/07/96)
   - Made W_SetCurrentAmmo() check if it's a player. (just a good idea)
   - Added impulse 61 (6.1) to fire a pipebomb (grenade)
     and impulse 62 which detonates all your pipebombs
   - impulse 120 lets the player kick whatever is touching him (PlayerTouch())


*/

void (entity targ, entity inflictor, entity attacker, float damage) T_Damage;
void () player_run;
void(entity bomb, entity attacker, float rad, entity ignore) T_RadiusDamage;
void(vector org, vector vel, float damage) SpawnBlood;
void() SuperDamageSound;

float Kick_em = 0;		// ==1, when touched, kicks that player/monster

// called by worldspawn
void() W_Precache =
{
        precache_sound ("zombie/z_miss.wav");   // axe splat        
	precache_sound ("weapons/r_exp3.wav");	// new rocket explosion
        precache_sound ("weapons/rocket1i.wav");// spike gun
	precache_sound ("weapons/sgun1.wav");
	precache_sound ("weapons/guncock.wav");	// player shotgun
	precache_sound ("weapons/ric1.wav");	// ricochet (used in c code)
	precache_sound ("weapons/ric2.wav");	// ricochet (used in c code)
	precache_sound ("weapons/ric3.wav");	// ricochet (used in c code)
	precache_sound ("weapons/spike2.wav");	// super spikes
	precache_sound ("weapons/tink1.wav");	// spikes tink (used in c code)
	precache_sound ("weapons/grenade.wav");	// grenade launcher
        precache_sound ("weapons/bounce.wav");  // grenade bounce
	precache_sound ("weapons/shotgn2.wav");	// super shotgun
        precache_model2 ("progs/fish.mdl");     // fish rocket!
        precache_model2 ("progs/laser.mdl");    // laser for SuperLaserGun
        precache_sound ("shambler/smack.wav");  // for electro-axe (I think)
	precache_sound ("player/udeath.wav");
        precache_sound ("enforcer/enfire.wav"); // sound for SuperLasergun
        precache_sound ("enforcer/enfstop.wav");// sound for SuperLasergun
        precache_sound ("items/damage2.wav");   // some sound I was getting an error message on.

};

float() crandom =
{
	return 2*(random() - 0.5);
};

float() jrandom =
{
   if (random() > 0.5)
      return random();
   else
      return random()*-1;
};

/*
================
W_FireAxe
================
*/
void() W_FireAxe =
{
	local	vector	source;
	local	vector	org;

        source = self.origin + '0 0 16';
	traceline (source, source + v_forward*64, FALSE, self);
	if (trace_fraction == 1.0)
		return;
	
	org = trace_endpos - v_forward*4;

	if (trace_ent.takedamage)
	{
		trace_ent.axhitme = 1;
		SpawnBlood (org, '0 0 0', 20);
                // {JDS} Play the *SMACK* sound
                sound (self, CHAN_WEAPON, "zombie/z_miss.wav", 1, ATTN_NORM);
//      {JDS}  SWITCH!
//        Add this block to enable Electro-Axe
                if (self.ammo_cells > 5)
                {
                        // If you have cells, do bonus damage and use some cells.
                        self.currentammo = self.ammo_cells = self.ammo_cells - 5;
                        T_Damage (trace_ent, self, self, 50);
                }
                else
                {

                        T_Damage (trace_ent, self, self, 20);
                }

	}
	else
	{	// hit wall
		sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
		WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
		WriteByte (MSG_BROADCAST, TE_GUNSHOT);
		WriteCoord (MSG_BROADCAST, org_x);
		WriteCoord (MSG_BROADCAST, org_y);
		WriteCoord (MSG_BROADCAST, org_z);
	}
};


//============================================================================


vector() wall_velocity =
{
	local vector	vel;
	
	vel = normalize (self.velocity);
	vel = normalize(vel + v_up*(random()- 0.5) + v_right*(random()- 0.5));
	vel = vel + 2*trace_plane_normal;
	vel = vel * 200;
	
	return vel;
};


/*
================
SpawnMeatSpray
================
*/
void(vector org, vector vel) SpawnMeatSpray =
{
	local	entity missile, mpuff;
	local	vector	org;

	missile = spawn ();
	missile.owner = self;
	missile.movetype = MOVETYPE_BOUNCE;
	missile.solid = SOLID_NOT;

	makevectors (self.angles);

	missile.velocity = vel;
	missile.velocity_z = missile.velocity_z + 250 + 50*random();

	missile.avelocity = '3000 1000 2000';
	
// set missile duration
	missile.nextthink = time + 1;
	missile.think = SUB_Remove;

	setmodel (missile, "progs/zom_gib.mdl");
	setsize (missile, '0 0 0', '0 0 0');		
	setorigin (missile, org);
};

/*
================
SpawnBlood
================
*/
void(vector org, vector vel, float damage) SpawnBlood =
{
	particle (org, vel*0.1, 73, damage*2);
};

/*
================
spawn_touchblood
================
*/
void(float damage) spawn_touchblood =
{
	local vector	vel;

	vel = wall_velocity () * 0.2;
	SpawnBlood (self.origin + vel*0.01, vel, damage);
};


/*
================
SpawnChunk
================
*/
void(vector org, vector vel) SpawnChunk =
{
	particle (org, vel*0.02, 0, 10);
};

/*
==============================================================================

MULTI-DAMAGE

Collects multiple small damages into a single damage

==============================================================================
*/

entity	multi_ent;
float	multi_damage;

void() ClearMultiDamage =
{
	multi_ent = world;
	multi_damage = 0;
};

void() ApplyMultiDamage =
{
	if (!multi_ent)
		return;
	T_Damage (multi_ent, self, self, multi_damage);
};

void(entity hit, float damage) AddMultiDamage =
{
	if (!hit)
		return;
	
	if (hit != multi_ent)
	{
		ApplyMultiDamage ();
		multi_damage = damage;
		multi_ent = hit;
	}
	else
		multi_damage = multi_damage + damage;
};

/*
==============================================================================

BULLETS

==============================================================================
*/

/*
================
TraceAttack
================
*/
void(float damage, vector dir) TraceAttack =
{
	local	vector	vel, org;
	
	vel = normalize(dir + v_up*crandom() + v_right*crandom());
	vel = vel + 2*trace_plane_normal;
	vel = vel * 200;

	org = trace_endpos - dir*4;

	if (trace_ent.takedamage)
	{
		SpawnBlood (org, vel*0.2, damage);
		AddMultiDamage (trace_ent, damage);
	}
	else
	{
		WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
		WriteByte (MSG_BROADCAST, TE_GUNSHOT);
		WriteCoord (MSG_BROADCAST, org_x);
		WriteCoord (MSG_BROADCAST, org_y);
		WriteCoord (MSG_BROADCAST, org_z);
	}
};

/*
================
FireBullets

Used by shotgun, super shotgun, and enemy soldier firing
Go to the trouble of combining multiple pellets into a single damage call.
================
*/
void(float shotcount, vector dir, vector spread) FireBullets =
{
	local	vector direction;
	local	vector	src;
	
	makevectors(self.v_angle);

	src = self.origin + v_forward*10;
	src_z = self.absmin_z + self.size_z * 0.7;

	ClearMultiDamage ();
	while (shotcount > 0)
	{
		direction = dir + crandom()*spread_x*v_right + crandom()*spread_y*v_up;

		traceline (src, src + direction*2048, FALSE, self);
		if (trace_fraction != 1.0)
			TraceAttack (4, direction);

		shotcount = shotcount - 1;
	}
	ApplyMultiDamage ();
};

/*
================
W_FireShotgun
================
*/
void() W_FireShotgun =
{
	local vector dir;

	sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);	

	self.punchangle_x = -2;
	
	self.currentammo = self.ammo_shells = self.ammo_shells - 1;
	dir = aim (self, 100000);
	FireBullets (6, dir, '0.04 0.04 0');
};


/*
================
W_FireSuperShotgun
================
*/
void() W_FireSuperShotgun =
{
	local vector dir;

        if (self.currentammo < 6)  // Only fires normal shotgun if less than 
        {                          // 6 shells.    -KT
		W_FireShotgun ();
		return;
	}
		
	sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);	

	self.punchangle_x = -4;
	
        self.currentammo = self.ammo_shells = self.ammo_shells - 6;
	dir = aim (self, 100000);
        FireBullets (14, dir, '0.14 0.08 0');
};


/*
==============================================================================

ROCKETS

==============================================================================
*/

void()	s_explode1	=	[0,		s_explode2] {};
void()	s_explode2	=	[1,		s_explode3] {};
void()	s_explode3	=	[2,		s_explode4] {};
void()	s_explode4	=	[3,		s_explode5] {};
void()	s_explode5	=	[4,		s_explode6] {};
void()	s_explode6	=	[5,		SUB_Remove] {};

// Variable for keeping track of which rocket launcher you're using
float rockettoggle = 0;

void() BecomeExplosion =
{
	self.movetype = MOVETYPE_NONE;
	self.velocity = '0 0 0';
	self.touch = SUB_Null;
	setmodel (self, "progs/s_explod.spr");
	self.solid = SOLID_NOT;
	s_explode1 ();
};

void() T_MissileTouch =
{
	local float	damg;

	if (other == self.owner)
		return;		// don't explode on owner

	if (pointcontents(self.origin) == CONTENT_SKY)
	{
		remove(self);
		return;
	}

	damg = 100 + random()*20;
	
	if (other.health)
	{
		if (other.classname == "monster_shambler")
			damg = damg * 0.5;	// mostly immune
		T_Damage (other, self, self.owner, damg );
	}

	// don't do radius damage to the other, because all the damage
	// was done in the impact
	T_RadiusDamage (self, self.owner, 120, other);

//	sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
	self.origin = self.origin - 8*normalize(self.velocity);

	WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
	WriteByte (MSG_BROADCAST, TE_EXPLOSION);
	WriteCoord (MSG_BROADCAST, self.origin_x);
	WriteCoord (MSG_BROADCAST, self.origin_y);
	WriteCoord (MSG_BROADCAST, self.origin_z);

	BecomeExplosion ();
};


/*
================
NewMissile
(This is the code for the erratic pattern of the drunk missiles)
-KT
================
*/
void() NewHome;

void() NewHome =
{
	local vector	dir, vtemp;
        local entity    client;

// ************************************
// switch the next two lines of code
// to enable the homing drunk missiles.
// ************************************

//        client = checkclient ();
        client = self.owner;

// ************************************

        self.nextthink = time + 0.2;

        if (client == self.owner ||  random() < 0.33) {
          self.velocity_x = self.velocity_x + 100 * jrandom();
          self.velocity_y = self.velocity_y + 100 * jrandom();
          self.velocity_z = self.velocity_z + 100 * jrandom();
          //self.velocity = 500 + (500 * random());
          return;
        }

        if (self.health < 1)
          remove(self);
        else
          self.health = self.health - 0.4;

        vtemp = client.origin + '0 0 10';
        dir = normalize(vtemp - self.origin);
        self.velocity = dir * 550;
        
        self.think = NewHome; 
};


/*
================
W_FireRocket
================
*/
void() W_FireRocket =
{

// If you have less than 3 rockets, you can't fire drunk missiles.
if ((rockettoggle == 0) || (self.ammo_rockets < 3))
        {
                local   entity missile, mpuff;
	
                self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;

        // *************************************************
        // switch these two statements to disable fish sound
        // *************************************************

        //        sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
                sound (self, CHAN_WEAPON, "shambler/smack.wav", 1, ATTN_NORM);

        // *************************************************

                self.punchangle_x = -2;

                missile = spawn ();
                missile.owner = self;
                missile.movetype = MOVETYPE_FLYMISSILE;
                missile.solid = SOLID_BBOX;
		
        // set missile speed 

                makevectors (self.v_angle);
                missile.velocity = aim(self, 1000);
                missile.velocity = missile.velocity * 1000;
                missile.angles = vectoangles(missile.velocity);
	
                missile.touch = T_MissileTouch;
	
        // set missile duration
                missile.nextthink = time + 5;
                missile.think = SUB_Remove;

        // ***************************************************
        // switch these two statements to disable fish missile
        // ***************************************************

        //        setmodel (missile, "progs/missile.mdl");
                setmodel (missile, "progs/fish.mdl");

        // ***************************************************

                setsize (missile, '0 0 0', '0 0 0');
                setorigin (missile, self.origin + v_forward*8 + '0 0 16');
        }

//   This is the code that lets you fire the drunk missiles
//   If the toggle is on
// -KT

if ((rockettoggle == 1) && (self.ammo_rockets >= 3))
        {
                local   entity  missile;
                local   entity  missile2;
                local   entity  missile3;

                local   vector  dir;
                local   float   dist;
	
                self.currentammo = self.ammo_rockets = self.ammo_rockets - 3;
                sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
                self.punchangle_x = -2;

                // first rocket

                missile = spawn ();
                missile.owner = self;
                missile.solid = SOLID_BBOX;
                missile.movetype = MOVETYPE_FLYMISSILE;                  
	
                makevectors (self.v_angle);
                missile.velocity = aim(self, 1000);
                missile.velocity = missile.velocity * 1000;
                missile.angles = vectoangles(missile.velocity);                

                missile.nextthink = time + 0.2;

                missile.think = NewHome;
                missile.touch = T_MissileTouch;
                missile.health = 10;

                setmodel (missile, "progs/missile.mdl");
                setsize (missile, '0 0 0', '0 0 0');             
                setorigin (missile, self.origin + v_forward*8 + '0 0 16');
                missile.avelocity = '300 300 300';       

                // second rocket

                missile2 = spawn ();
                missile2.owner = self;
                missile2.solid = SOLID_BBOX;
                missile2.movetype = MOVETYPE_FLYMISSILE;                         
	
                makevectors (self.v_angle);
                missile2.velocity = aim(self, 750);
                missile2.velocity = missile2.velocity * 750;

                missile2.angles = vectoangles(missile2.velocity);                

                missile2.nextthink = time + 0.2;

                missile2.think = NewHome;
                missile2.touch = T_MissileTouch;
                missile2.health = 10;

                setmodel (missile2, "progs/missile.mdl");
                setsize (missile2, '0 0 0', '0 0 0');            
                setorigin (missile2, self.origin + '-20 0 16');
                missile2.avelocity = '300 300 300';      

                // third rocket

                missile3 = spawn ();
                missile3.owner = self;
                missile3.solid = SOLID_BBOX;
                missile3.movetype = MOVETYPE_FLYMISSILE;                         
	
                makevectors (self.v_angle);
                missile3.velocity = aim(self, 750);
                missile3.velocity = missile3.velocity * 750;

                missile3.angles = vectoangles(missile3.velocity);                

                missile3.nextthink = time + 0.2;

                missile3.think = NewHome;
                missile3.touch = T_MissileTouch;
                missile3.health = 10;

                setmodel (missile3, "progs/missile.mdl");
                setsize (missile3, '0 0 0', '0 0 0');            
                setorigin (missile3, self.origin + '20 0 16');
                missile3.avelocity = '300 300 300';      
        }
};

/*
===============================================================================

LIGHTNING

===============================================================================
*/

/*
=================
LightningDamage
=================
*/
void(vector p1, vector p2, entity from, float damage) LightningDamage =
{
	local entity		e1, e2;
	local vector		f;
	
	f = p2 - p1;
	normalize (f);
	f_x = 0 - f_y;
	f_y = f_x;
	f_z = 0;
	f = f*16;

	e1 = e2 = world;

	traceline (p1, p2, FALSE, self);
	if (trace_ent.takedamage)
	{
		particle (trace_endpos, '0 0 100', 225, damage*4);
		T_Damage (trace_ent, from, from, damage);
		if (self.classname == "player")
		{
			if (other.classname == "player")
				trace_ent.velocity_z = trace_ent.velocity_z + 400;
		}
	}
	e1 = trace_ent;

	traceline (p1 + f, p2 + f, FALSE, self);
	if (trace_ent != e1 && trace_ent.takedamage)
	{
		particle (trace_endpos, '0 0 100', 225, damage*4);
		T_Damage (trace_ent, from, from, damage);
	}
	e2 = trace_ent;

	traceline (p1 - f, p2 - f, FALSE, self);
	if (trace_ent != e1 && trace_ent != e2 && trace_ent.takedamage)
	{
		particle (trace_endpos, '0 0 100', 225, damage*4);
		T_Damage (trace_ent, from, from, damage);
	}
};


void() W_FireLightning =
{
	local	vector		org;

	if (self.ammo_cells < 1)
	{
		self.weapon = W_BestWeapon ();
		W_SetCurrentAmmo ();
		return;
	}

// explode if under water
	if (self.waterlevel > 1)
	{
		T_RadiusDamage (self, self, 35*self.ammo_cells, world);
		self.ammo_cells = 0;
		W_SetCurrentAmmo ();
		return;
	}

	if (self.t_width < time)
	{
		sound (self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM);
		self.t_width = time + 0.6;
	}
	self.punchangle_x = -2;

	self.currentammo = self.ammo_cells = self.ammo_cells - 1;

	org = self.origin + '0 0 16';
	
	traceline (org, org + v_forward*600, TRUE, self);

	WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
	WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
	WriteEntity (MSG_BROADCAST, self);
	WriteCoord (MSG_BROADCAST, org_x);
	WriteCoord (MSG_BROADCAST, org_y);
	WriteCoord (MSG_BROADCAST, org_z);
	WriteCoord (MSG_BROADCAST, trace_endpos_x);
	WriteCoord (MSG_BROADCAST, trace_endpos_y);
	WriteCoord (MSG_BROADCAST, trace_endpos_z);

	LightningDamage (self.origin, trace_endpos + v_forward*4, self, 30);
};


//=============================================================================


void() GrenadeExplode =
{
	T_RadiusDamage (self, self.owner, 120, world);

	WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
	WriteByte (MSG_BROADCAST, TE_EXPLOSION);
	WriteCoord (MSG_BROADCAST, self.origin_x);
	WriteCoord (MSG_BROADCAST, self.origin_y);
	WriteCoord (MSG_BROADCAST, self.origin_z);

	BecomeExplosion ();
};

/*
=============
GrenadeThink

{JDS}
For Proximity grenades, look for nearby targets and hop around.
=============
*/

void() GrenadeThink =
{
        local entity head;
        local vector dir;
        if(self.flags & FL_ONGROUND) {
        // Don't detect targets if I'm not on the ground
                head = findradius(self.origin, 200);
                while(head) {
                        if (head.takedamage) {
                                if (self.avelocity == '0 0 0')
                                        self.avelocity = '300 300 300';
                                self.origin_z = self.origin_z + 1;
                                dir = normalize(head.origin - self.origin);
                                self.velocity = dir*200 + '0 0 500';
                                if (self.flags & FL_ONGROUND)
                                        self.flags = self.flags - FL_ONGROUND;

                                self.nextthink = time + random()*1.5;
                                self.think = GrenadeExplode;
                                return;
                        }
                        head = head.chain;
                }
        }
        self.nextthink = time + 0.5;
        self.think = GrenadeThink;
        if(self.wait < time)
        {
                // Time to jump.
                self.wait = time + 15 + 15*random();
        if (self.avelocity == '0 0 0')
                self.avelocity = '300 300 300';
	self.origin_z = self.origin_z + 1;
        self.velocity_x=(random()*400 - 200);
        self.velocity_y=(random()*400 - 200);
        self.velocity_z = 500;
        if (self.flags & FL_ONGROUND)
                self.flags = self.flags - FL_ONGROUND;

         }
};

void() GrenadeTouch =
{
	if (other == self.owner)
		return;		// don't explode on owner
	if (other.takedamage == DAMAGE_AIM)
	{
                // {JDS}  Comment the next line if you don't want grenades
                //        to explode on enemies.  Recommended for CBP Grenades.
                GrenadeExplode();
		return;
	}
	sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);	// bounce sound
	if (self.velocity == '0 0 0')
		self.avelocity = '0 0 0';
};

/*
================
GrenadeDeploy

{JDS} CBP Grenade code
Explode and spray out five new proximity grenades.
================
*/
void() GrenadeDeploy =
{
        local float gnum = 0;
        local entity missile;

        while(gnum < 5) {
                missile = spawn ();
                missile.owner = self.owner;
                missile.movetype = MOVETYPE_BOUNCE;
                missile.solid = SOLID_BBOX;
                missile.classname = "grenade";
                missile.wait = time + 15 + 15*random();
                missile.think = GrenadeThink;
                missile.nextthink = time + 0.5;
                missile.velocity_z = 500;
                missile.velocity_x = 400*random() - 200;
                missile.velocity_y = 400*random() - 200;
                gnum = gnum + 1;
                missile.avelocity = '300 300 300';
                missile.angles = vectoangles(missile.velocity);
                missile.touch = GrenadeTouch;
                setmodel (missile, "progs/grenade.mdl");
                setsize (missile, '0 0 0', '0 0 0');     
                setorigin (missile, self.origin);
        }
        self.think = GrenadeExplode;
        self.nextthink = time + 0.1;
};

/*
 ------------------------------------------
 Pipe Bombs  (by Asmodeus)
 ------------------------------------------
*/

/*
 * Blow up the toys.  There is a range of 1000 units (pixels?), so you can't
 * go wandering off.
 */
 
void() DetPipeBombs =
{
        local entity    head;

        head = findradius (self.origin, 1000);
        while(head)
        {
                if((head.classname == "pipebomb") && (head.owner == self))
                        head.nextthink = time;
                head = head.chain;
        }
};

/*
 * What happens if it touches something
 */
 
void() PipeBombTouch =
{
	if (other == self.owner)
		return;		// don't explode on owner
	sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);	// bounce sound
	if (self.velocity == '0 0 0')
		self.avelocity = '0 0 0';
};

/*
 * Fires a pipe bomb.  Can be detonated at any time.  Doesn't need a special
 * weapon selected.
 */

void() W_FirePipeBomb =
{
	local	entity missile, mpuff;
	
	if(self.ammo_rockets < 1)	// have to have ammo
	  return;
	self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
	
        sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);

//	self.punchangle_x = -2;

	missile = spawn ();
	missile.owner = self;
	missile.movetype = MOVETYPE_BOUNCE;
	missile.solid = SOLID_BBOX;
	missile.classname = "pipebomb";
		
// set missile speed	

	makevectors (self.v_angle);

	if (self.v_angle_x)
		missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
	else
	{
		missile.velocity = aim(self, 10000);
		missile.velocity = missile.velocity * 600;
		missile.velocity_z = 200;
	}

	missile.avelocity = '300 300 300';

	missile.angles = vectoangles(missile.velocity);
	
	missile.touch = PipeBombTouch;
	missile.think = GrenadeExplode;
	
	setmodel (missile, "progs/grenade.mdl");
	setsize (missile, '0 0 0', '0 0 0');		
	setorigin (missile, self.origin);
};


// Variable for keeping track of which grenade launcher you're using
float grenadetoggle = 0;

/*
================
W_FireGrenade
================
*/
void() W_FireGrenade =
{
if (grenadetoggle == 0)
        {
                local   entity missile, mpuff;
	
                sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);

                self.punchangle_x = -2;

                missile = spawn ();
                missile.owner = self;
                missile.movetype = MOVETYPE_BOUNCE;
                missile.solid = SOLID_BBOX;
                missile.classname = "grenade";
                missile.wait = time + 15 + 15*random();
		
        // set missile speed 

                makevectors (self.v_angle);

                if (self.v_angle_x)
                        missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
                else
                {
                        missile.velocity = aim(self, 10000);
                        missile.velocity = missile.velocity * 600;
                        missile.velocity_z = 200;
                }

                missile.avelocity = '300 300 300';

                missile.angles = vectoangles(missile.velocity);
	
                missile.touch = GrenadeTouch;

                self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
                missile.nextthink = time + 2.5;
                missile.think = GrenadeExplode;

                setmodel (missile, "progs/grenade.mdl");
                setsize (missile, '0 0 0', '0 0 0');     
                setorigin (missile, self.origin);
        }

// toggle to pipebomb launcher
if (grenadetoggle == 1) W_FirePipeBomb();

if (grenadetoggle == 2)
        {
                local   entity missile, mpuff;
	
                sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);

                self.punchangle_x = -2;

                missile = spawn ();
                missile.owner = self;
                missile.movetype = MOVETYPE_BOUNCE;
                missile.solid = SOLID_BBOX;
                missile.classname = "grenade";
                missile.wait = time + 15 + 15*random();
		
        // set missile speed 

                makevectors (self.v_angle);

                if (self.v_angle_x)
                        missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
                else
                {
                        missile.velocity = aim(self, 10000);
                        missile.velocity = missile.velocity * 600;
                        missile.velocity_z = 200;
                }

                missile.avelocity = '300 300 300';

                missile.angles = vectoangles(missile.velocity);
	
                missile.touch = GrenadeTouch;

                if (self.ammo_rockets > 4) {
                        self.currentammo = self.ammo_rockets = self.ammo_rockets - 5;
                        missile.nextthink = time + 2+(random()*3);
                        missile.think = GrenadeDeploy;
                }
                else
                {
                        self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
                        missile.nextthink = time + 2.5;
                        missile.think = GrenadeThink;
                        missile.nextthink = time + 2+(random()*2);
                }

                setmodel (missile, "progs/grenade.mdl");
                setsize (missile, '0 0 0', '0 0 0');     
                setorigin (missile, self.origin);
        }


};


//=============================================================================

void() spike_touch;
void() superspike_touch;
void() superlaser_touch;

// Variable to keep track of which nailgun you're using...  -KT
float supnailtoggle = 0;


/*
===============
launch_spike

Used for both the player and the ogre
===============
*/
void(vector org, vector dir) launch_spike =
{
	newmis = spawn ();
	newmis.owner = self;
	newmis.movetype = MOVETYPE_FLYMISSILE;
	newmis.solid = SOLID_BBOX;

	newmis.angles = vectoangles(dir);
	
	newmis.touch = spike_touch;
	newmis.classname = "spike";
	newmis.think = SUB_Remove;
	newmis.nextthink = time + 6;
	setmodel (newmis, "progs/spike.mdl");
	setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);		
	setorigin (newmis, org);

	newmis.velocity = dir * 1000;
};

void() W_FireSuperSpikes =
{
	local vector	dir;
	local entity	old;
	
	sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
	self.attack_finished = time + 0.2;
	self.currentammo = self.ammo_nails = self.ammo_nails - 2;
	dir = aim (self, 1000);
	launch_spike (self.origin + '0 0 16', dir);
        newmis.touch = superspike_touch;
	setmodel (newmis, "progs/s_spike.mdl");
	setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);		
	self.punchangle_x = -2;
};

// Code for firing lasers from SuperNailGun.
// Created entirely (for a change) by KeyTrap.

void() W_FireSuperLasers =
{
	local vector	dir;
	local entity	old;
	
        sound (self, CHAN_WEAPON, "enforcer/enfire.wav", 1, ATTN_NORM);
	self.attack_finished = time + 0.2;
        self.currentammo = self.ammo_cells = self.ammo_cells - 3;
	dir = aim (self, 1000);
	launch_spike (self.origin + '0 0 16', dir);
        newmis.touch = superlaser_touch;
        setmodel (newmis, "progs/laser.mdl");
	setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);		
	self.punchangle_x = -2;
};


void(float ox) W_FireSpikes =
{
	local vector	dir;
	local entity	old;
	
	makevectors (self.v_angle);
	
        if ((self.ammo_nails >= 2 || self.ammo_cells >= 3)
        && self.weapon == IT_SUPER_NAILGUN)
	{
        // Automatically switch to the other mode if ammo runs out. -KT
                if ((supnailtoggle == 0) && (self.ammo_nails < 2))
                    {
                        supnailtoggle = 1;
                        self.currentammo = self.ammo_cells;
                    }
                if ((supnailtoggle == 1) && (self.ammo_cells < 3))
                    {
                        supnailtoggle = 0;
                        self.currentammo = self.ammo_nails;
                    }
                if (supnailtoggle == 0) W_FireSuperSpikes();
                if (supnailtoggle == 1) W_FireSuperLasers();
		return;
	}

        if ((self.ammo_nails < 2) && (self.ammo_cells < 3) 
        && self.weapon == IT_SUPER_NAILGUN)
        {
		self.weapon = W_BestWeapon ();
		W_SetCurrentAmmo ();
		return;
	}

        if ((self.ammo_nails < 1) && (self.weapon == IT_NAILGUN))
        {
		self.weapon = W_BestWeapon ();
		W_SetCurrentAmmo ();
		return;
	}

	sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
	self.attack_finished = time + 0.2;
	self.currentammo = self.ammo_nails = self.ammo_nails - 1;
	dir = aim (self, 1000);
	launch_spike (self.origin + '0 0 16' + v_right*ox, dir);

	self.punchangle_x = -2;
};



.float hit_z;
void() spike_touch =
{
local float rand;
	if (other == self.owner)
		return;

	if (other.solid == SOLID_TRIGGER)
		return;	// trigger field, do nothing

	if (pointcontents(self.origin) == CONTENT_SKY)
	{
		remove(self);
		return;
	}
	
// hit something that bleeds
	if (other.takedamage)
	{
		spawn_touchblood (9);
		T_Damage (other, self, self.owner, 9);
	}
	else
	{
		WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
		
		if (self.classname == "wizspike")
			WriteByte (MSG_BROADCAST, TE_WIZSPIKE);
		else if (self.classname == "knightspike")
			WriteByte (MSG_BROADCAST, TE_KNIGHTSPIKE);
		else
			WriteByte (MSG_BROADCAST, TE_SPIKE);
		WriteCoord (MSG_BROADCAST, self.origin_x);
		WriteCoord (MSG_BROADCAST, self.origin_y);
		WriteCoord (MSG_BROADCAST, self.origin_z);
	}

	remove(self);

};

void() superspike_touch =
{
local float rand;
	if (other == self.owner)
		return;

	if (other.solid == SOLID_TRIGGER)
		return;	// trigger field, do nothing

	if (pointcontents(self.origin) == CONTENT_SKY)
	{
		remove(self);
		return;
	}
	
// hit something that bleeds
	if (other.takedamage)
	{
		spawn_touchblood (18);
		T_Damage (other, self, self.owner, 18);
	}
	else
	{
		WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
		WriteByte (MSG_BROADCAST, TE_SUPERSPIKE);
		WriteCoord (MSG_BROADCAST, self.origin_x);
		WriteCoord (MSG_BROADCAST, self.origin_y);
		WriteCoord (MSG_BROADCAST, self.origin_z);
	}

	remove(self);
};

void() superlaser_touch =
{
local float rand;

        sound (self, CHAN_WEAPON, "enforcer/enfstop.wav", 1, ATTN_NORM);


	if (other == self.owner)
		return;

	if (other.solid == SOLID_TRIGGER)
		return;	// trigger field, do nothing

	if (pointcontents(self.origin) == CONTENT_SKY)
	{
		remove(self);
		return;
	}
	
// hit something that bleeds
	if (other.takedamage)
	{
		spawn_touchblood (18);
                T_Damage (other, self, self.owner, 25);
	}
	else
	{
		WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
		WriteByte (MSG_BROADCAST, TE_SUPERSPIKE);
		WriteCoord (MSG_BROADCAST, self.origin_x);
		WriteCoord (MSG_BROADCAST, self.origin_y);
		WriteCoord (MSG_BROADCAST, self.origin_z);
	}

	remove(self);
};


/*
===============================================================================

PLAYER WEAPON USE

===============================================================================
*/

void() W_SetCurrentAmmo =
{
	player_run ();		// get out of any weapon firing states

	self.items = self.items - ( self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS) );

        if (self.invincible_time)
        {
		self.currentammo = 0;
                self.weaponmodel = "";
		self.weaponframe = 0;
        }                
        else if (self.weapon == IT_AXE)
	{
		self.currentammo = 0;
		self.weaponmodel = "progs/v_axe.mdl";
		self.weaponframe = 0;
	}
	else if (self.weapon == IT_SHOTGUN)
	{
		self.currentammo = self.ammo_shells;
		self.weaponmodel = "progs/v_shot.mdl";
		self.weaponframe = 0;
		self.items = self.items | IT_SHELLS;
	}
	else if (self.weapon == IT_SUPER_SHOTGUN)
	{
		self.currentammo = self.ammo_shells;
		self.weaponmodel = "progs/v_shot2.mdl";
		self.weaponframe = 0;
		self.items = self.items | IT_SHELLS;
	}
	else if (self.weapon == IT_NAILGUN)
	{
		self.currentammo = self.ammo_nails;
		self.weaponmodel = "progs/v_nail.mdl";
		self.weaponframe = 0;
		self.items = self.items | IT_NAILS;
	}
	else if (self.weapon == IT_SUPER_NAILGUN)
	{
                if ((supnailtoggle == 0) && (self.ammo_nails < 2))
                    {
                        supnailtoggle = 1;
                        self.currentammo = self.ammo_cells;
                    }
                if ((supnailtoggle == 1) && (self.ammo_cells < 3))
                    {
                        supnailtoggle = 0;
                        self.currentammo = self.ammo_nails;
                    }
		self.weaponmodel = "progs/v_nail2.mdl";
		self.weaponframe = 0;
		self.items = self.items | IT_NAILS;
	}
	else if (self.weapon == IT_GRENADE_LAUNCHER)
	{
		self.currentammo = self.ammo_rockets;
		self.weaponmodel = "progs/v_rock.mdl";
		self.weaponframe = 0;
		self.items = self.items | IT_ROCKETS;
	}
	else if (self.weapon == IT_ROCKET_LAUNCHER)
	{
		self.currentammo = self.ammo_rockets;
		self.weaponmodel = "progs/v_rock2.mdl";
		self.weaponframe = 0;
		self.items = self.items | IT_ROCKETS;
	}
	else if (self.weapon == IT_LIGHTNING)
	{
		self.currentammo = self.ammo_cells;
		self.weaponmodel = "progs/v_light.mdl";
		self.weaponframe = 0;
		self.items = self.items | IT_CELLS;
	}
	else
	{
		self.currentammo = 0;
		self.weaponmodel = "";
		self.weaponframe = 0;
	}
};

float() W_BestWeapon =
{
	local	float	it;
	
	it = self.items;

	if(self.ammo_cells >= 1 && (it & IT_LIGHTNING) )
		return IT_LIGHTNING;
        else if(((self.ammo_nails >= 2) || (self.ammo_cells >=3))
        && (it & IT_SUPER_NAILGUN))
		return IT_SUPER_NAILGUN;
	else if(self.ammo_shells >= 2 && (it & IT_SUPER_SHOTGUN) )
		return IT_SUPER_SHOTGUN;
	else if(self.ammo_nails >= 1 && (it & IT_NAILGUN) )
		return IT_NAILGUN;
	else if(self.ammo_shells >= 1 && (it & IT_SHOTGUN) )
		return IT_SHOTGUN;
		
/*
	if(self.ammo_rockets >= 1 && (it & IT_ROCKET_LAUNCHER) )
		return IT_ROCKET_LAUNCHER;
	else if(self.ammo_rockets >= 1 && (it & IT_GRENADE_LAUNCHER) )
		return IT_GRENADE_LAUNCHER;

*/

	return IT_AXE;
};

float() W_CheckNoAmmo =
{
	if (self.currentammo > 0)
		return TRUE;

        if (self.invincible_time)
                return TRUE;

	if (self.weapon == IT_AXE)
		return TRUE;
	
	self.weapon = W_BestWeapon ();

	W_SetCurrentAmmo ();
	
// drop the weapon down
	return FALSE;
};

/*
============
W_Attack

An attack impulse can be triggered now
============
*/
void()	player_axe1;
void()	player_axeb1;
void()	player_axec1;
void()	player_axed1;
void()	player_shot1;
void()	player_nail1;
void()	player_light1;
void()	player_rocket1;
void()  player_dattack;

void() W_Attack =
{
	local	float	r;

	if (!W_CheckNoAmmo ())
		return;

	makevectors	(self.v_angle);			// calculate forward angle for velocity
	self.show_hostile = time + 1;	// wake monsters up

        if (self.invincible_time)
        {
                self.attack_finished = time + 1;
                player_dattack();
        }
        else if (self.weapon == IT_AXE)
	{
		sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
		r = random();
		if (r < 0.25)
			player_axe1 ();
		else if (r<0.5)
			player_axeb1 ();
		else if (r<0.75)
			player_axec1 ();
		else
			player_axed1 ();
		self.attack_finished = time + 0.5;
	}
	else if (self.weapon == IT_SHOTGUN)
	{
		player_shot1 ();
		W_FireShotgun ();
		self.attack_finished = time + 0.5;
	}
	else if (self.weapon == IT_SUPER_SHOTGUN)
	{
		player_shot1 ();
		W_FireSuperShotgun ();
		self.attack_finished = time + 0.7;
	}
	else if (self.weapon == IT_NAILGUN)
	{
		player_nail1 ();
	}
	else if (self.weapon == IT_SUPER_NAILGUN)
	{
                if ((supnailtoggle == 0) && (self.ammo_nails < 2))
                    {
                        supnailtoggle = 1;
                        self.currentammo = self.ammo_cells;
                    }
                if ((supnailtoggle == 1) && (self.ammo_cells < 3))
                    {
                        supnailtoggle = 0;
                        self.currentammo = self.ammo_nails;
                    }

		player_nail1 ();
	}
	else if (self.weapon == IT_GRENADE_LAUNCHER)
	{
		player_rocket1();
		W_FireGrenade();
		self.attack_finished = time + 0.6;
	}
	else if (self.weapon == IT_ROCKET_LAUNCHER)
	{
		player_rocket1();
		W_FireRocket();
		self.attack_finished = time + 0.8;
	}
	else if (self.weapon == IT_LIGHTNING)
	{
		player_light1();
		self.attack_finished = time + 0.1;
		sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
	}
};

/*
============
W_ChangeWeapon

============
*/
void() W_ChangeWeapon =
{
	local	float	it, am, fl;
	
	it = self.items;
	am = 0;
	
	if (self.impulse == 1)
	{
		fl = IT_AXE;
	}
	else if (self.impulse == 2)
	{
		fl = IT_SHOTGUN;
		if (self.ammo_shells < 1)
			am = 1;
	}
	else if (self.impulse == 3)
	{
		fl = IT_SUPER_SHOTGUN;
		if (self.ammo_shells < 2)
			am = 1;
	}		
	else if (self.impulse == 4)
	{
		fl = IT_NAILGUN;
                if (self.ammo_nails < 1)
			am = 1;
	}

	else if (self.impulse == 5)
	{
		fl = IT_SUPER_NAILGUN;
                if ((supnailtoggle == 0) && (self.ammo_nails < 2))
                    {
                        supnailtoggle = 1;
                        self.currentammo = self.ammo_cells;
                    }
                if ((supnailtoggle == 1) && (self.ammo_cells < 3))
                    {
                        supnailtoggle = 0;
                        self.currentammo = self.ammo_nails;
                    }


                if ((self.ammo_nails < 2) && (self.ammo_cells < 3))
			am = 1;
	}
	else if (self.impulse == 6)
	{
		fl = IT_GRENADE_LAUNCHER;
		if (self.ammo_rockets < 1)
			am = 1;
	}
	else if (self.impulse == 7)
	{
		fl = IT_ROCKET_LAUNCHER;
		if (self.ammo_rockets < 1)
			am = 1;
	}
	else if (self.impulse == 8)
	{
		fl = IT_LIGHTNING;
		if (self.ammo_cells < 1)
			am = 1;
	}

	self.impulse = 0;
	
	if (!(self.items & fl))
	{	// don't have the weapon or the ammo
                sprint (self, "no weapon.\n");
		return;
	}
	
	if (am)
	{	// don't have the ammo
		sprint (self, "not enough ammo.\n");
		return;
	}

//
// set weapon, set ammo
//
	self.weapon = fl;		
	W_SetCurrentAmmo ();
};

/*
============
Cheat Command    (This is the impulse 9 cheat)
============
*/
void() CheatCommand =
{

//  *********************************************************
//   Rem this if you want to enable cheats in deathmatch
//   (Impulse 9)
//  *********************************************************

        if (deathmatch || coop)
                return;

//  *********************************************************

	self.ammo_rockets = 100;
	self.ammo_nails = 200;
	self.ammo_shells = 100;
	self.items = self.items | 
		IT_AXE |
		IT_SHOTGUN |
		IT_SUPER_SHOTGUN |
		IT_NAILGUN |
		IT_SUPER_NAILGUN |
		IT_GRENADE_LAUNCHER |
		IT_ROCKET_LAUNCHER |
		IT_KEY1 | IT_KEY2;

	self.ammo_cells = 200;
	self.items = self.items | IT_LIGHTNING;

	self.weapon = IT_ROCKET_LAUNCHER;
	self.impulse = 0;
	W_SetCurrentAmmo ();
};

/*
============
CycleWeaponCommand

Go to the next weapon with ammo
============
*/
void() CycleWeaponCommand =
{
	local	float	it, am;
	
	it = self.items;
	self.impulse = 0;
	
	while (1)
	{
		am = 0;

		if (self.weapon == IT_LIGHTNING)
		{
			self.weapon = IT_AXE;
		}
		else if (self.weapon == IT_AXE)
		{
			self.weapon = IT_SHOTGUN;
			if (self.ammo_shells < 1)
				am = 1;
		}
		else if (self.weapon == IT_SHOTGUN)
		{
			self.weapon = IT_SUPER_SHOTGUN;
			if (self.ammo_shells < 2)
				am = 1;
		}		
		else if (self.weapon == IT_SUPER_SHOTGUN)
		{
			self.weapon = IT_NAILGUN;
			if (self.ammo_nails < 1)
				am = 1;
		}
		else if (self.weapon == IT_NAILGUN)
		{
			self.weapon = IT_SUPER_NAILGUN;
                if ((supnailtoggle == 0) && (self.ammo_nails < 2))
                    {
                        supnailtoggle = 1;
                        self.currentammo = self.ammo_cells;
                    }
                if ((supnailtoggle == 1) && (self.ammo_cells < 3))
                    {
                        supnailtoggle = 0;
                        self.currentammo = self.ammo_nails;
                    }


                        if ((self.ammo_nails < 2) && (self.ammo_cells < 3))
				am = 1;
		}
		else if (self.weapon == IT_SUPER_NAILGUN)
		{
			self.weapon = IT_GRENADE_LAUNCHER;
			if (self.ammo_rockets < 1)
				am = 1;
		}
		else if (self.weapon == IT_GRENADE_LAUNCHER)
		{
			self.weapon = IT_ROCKET_LAUNCHER;
			if (self.ammo_rockets < 1)
				am = 1;
		}
		else if (self.weapon == IT_ROCKET_LAUNCHER)
		{
			self.weapon = IT_LIGHTNING;
			if (self.ammo_cells < 1)
				am = 1;
		}
	
		if ( (self.items & self.weapon) && am == 0)
		{
			W_SetCurrentAmmo ();
			return;
		}
	}

};

/*
============
ServerflagsCommand

Just for development
============
*/
void() ServerflagsCommand =
{
	serverflags = serverflags * 2 + 1;
};

void() QuadCheat =
{
//  *********************************************************
//   Rem this if you want to enable Quad Cheat in deathmatch
//   (Impulse 255)
//  *********************************************************

        if (deathmatch || coop)
		return;

//  *********************************************************


	self.super_time = 1;
	self.super_damage_finished = time + 30;
	self.items = self.items | IT_QUAD;
	dprint ("quad cheat\n");
};

void() FiendCheat =
{
//  *********************************************************
//   Rem this if you want to enable Fiend Cheat in deathmatch
//   (Impulse 254)
//  *********************************************************

        if (deathmatch || coop)
                return;

//  *********************************************************

        if (self.health < 100) self.health = 100;
        self.invincible_time = 1;
        self.invincible_finished = time + 120;
        self.weaponmodel = "";
        self.view_ofs = '0 0 4';
        self.items = self.items | IT_INVULNERABILITY;
        dprint ("You fiend!\n");
};

/*
============
ImpulseCommands

============
*/
void() ImpulseCommands =
{
	if (self.impulse >= 1 && self.impulse <= 8)
		W_ChangeWeapon ();

	if (self.impulse == 9)
		CheatCommand ();
	if (self.impulse == 10)
		CycleWeaponCommand ();
	if (self.impulse == 11)
		ServerflagsCommand ();

	if(self.impulse == 62)
	  DetPipeBombs();

        if (self.impulse == 63)
        {
            if (self.weapon == IT_SUPER_NAILGUN)
              {
                        supnailtoggle = (supnailtoggle + 1);
                        if (supnailtoggle > 1) {supnailtoggle = 0;}
                       // sprint (self, "SuperNailGun Toggle\n");
                    if (supnailtoggle == 0) sprint (self, "SuperNailGun\n");
                    if (supnailtoggle == 1)
                    {
                        if (self.ammo_cells >= 3)
                            sprint (self, "SuperLaserGun\n");
                        else
                            sprint (self, "SuperLaserGun (You need cells though)\n");
                     }
               }

             if (self.weapon == IT_GRENADE_LAUNCHER)
               {
                        grenadetoggle = (grenadetoggle + 1);
                        if (grenadetoggle > 2) {grenadetoggle = 0;}
                       // sprint (self, "Grenade Toggle\n");
                    if (grenadetoggle == 0) sprint (self, "Normal Grenades\n");
                    if (grenadetoggle == 1) sprint (self, "Pipe Bombs\n");
                    if (grenadetoggle == 2) sprint (self, "Proximity Mines\n");
                }

              if (self.weapon == IT_ROCKET_LAUNCHER)
                {
                        rockettoggle = (rockettoggle + 1);
                        if (rockettoggle > 1) {rockettoggle = 0;}
                       // sprint (self, "Rocket Toggle\n");
                    if (rockettoggle == 0) sprint (self, "Normal Rockets\n");
                    if (rockettoggle == 1) sprint (self, "Drunk Missiles\n");
                 }
        }

        if(self.impulse == 120)
	  Kick_em = 1;
	else
	  Kick_em = 0;

// *************************************************************************
// **								          **
// ** M U L T I S K I N  1.1  (start)                                     **
// **									  **
// *************************************************************************


        if ((self.impulse >= 198) && (self.impulse <= 231))
	{

// *************   KeyTrap's Modifications Begin ***************

                if (self.impulse == 199)
		{
		self.skin = self.skin + 1;
                if (self.skin == 32) self.skin = 0;
		} else
                if (self.impulse == 198)
		{
		self.skin = self.skin - 1;
                if (self.skin == -1) self.skin = 31;
		}
                if (self.impulse == 200) self.skin = 0;
                if (self.impulse == 201) self.skin = 1;
                if (self.impulse == 202) self.skin = 2;
                if (self.impulse == 203) self.skin = 3;
                if (self.impulse == 204) self.skin = 4;
                if (self.impulse == 205) self.skin = 5;
                if (self.impulse == 206) self.skin = 6;
                if (self.impulse == 207) self.skin = 7;
                if (self.impulse == 208) self.skin = 8;
                if (self.impulse == 209) self.skin = 9;
                if (self.impulse == 210) self.skin = 10;
                if (self.impulse == 211) self.skin = 11;
                if (self.impulse == 212) self.skin = 12;
                if (self.impulse == 213) self.skin = 13;
                if (self.impulse == 214) self.skin = 14;
                if (self.impulse == 215) self.skin = 15;
                if (self.impulse == 216) self.skin = 16;
                if (self.impulse == 217) self.skin = 17;
                if (self.impulse == 218) self.skin = 18;
                if (self.impulse == 219) self.skin = 19;
                if (self.impulse == 220) self.skin = 20;
                if (self.impulse == 221) self.skin = 21;
                if (self.impulse == 222) self.skin = 22;
                if (self.impulse == 223) self.skin = 23;
                if (self.impulse == 224) self.skin = 24;
                if (self.impulse == 225) self.skin = 25;
                if (self.impulse == 226) self.skin = 26;
                if (self.impulse == 227) self.skin = 27;
                if (self.impulse == 228) self.skin = 28;
                if (self.impulse == 229) self.skin = 29;
                if (self.impulse == 230) self.skin = 30;
                if (self.impulse == 231) self.skin = 31;

// *************   KeyTrap's Modifications End ***************

                if (self.skin == 0) sprint(self, "SKIN: Quake himself (1)\n"); else
                if (self.skin == 1) sprint(self, "SKIN: Duke Nukem 3d (2)\n"); else
                if (self.skin == 2) sprint(self, "SKIN: Mr. Toad (3)\n"); else
                if (self.skin == 3) sprint(self, "SKIN: the Stormtrooper (4)\n"); else
                if (self.skin == 4) sprint(self, "SKIN: Max (5)\n"); else
                if (self.skin == 5) sprint(self, "SKIN: the Terminator (6)\n"); else
                if (self.skin == 6) sprint(self, "SKIN: Judge Dredd (7)\n"); else
                if (self.skin == 7) sprint(self, "SKIN: Camouflaged soldier (8)\n"); else
                if (self.skin == 8) sprint(self, "SKIN: Captain Picard (9)\n"); else
                if (self.skin == 9) sprint(self, "SKIN: the Wizzard (10)\n"); else
                if (self.skin == 10) sprint(self,"SKIN: the Predator (11)\n"); else
                if (self.skin == 11) sprint(self,"SKIN: Skeleton (12)\n"); else
                if (self.skin == 12) sprint(self,"SKIN: Wan-Fu (13)\n"); else
                if (self.skin == 13) sprint(self,"SKIN: Henry Rollins (14)\n"); else
                if (self.skin == 14) sprint(self,"SKIN: He-Man (15)\n"); else
                if (self.skin == 15) sprint(self,"SKIN: Boba (16)\n"); else
                if (self.skin == 16) sprint(self,"SKIN: Superman (17)\n"); else
                if (self.skin == 17) sprint(self,"SKIN: NYPD Cop (18)\n"); else
                if (self.skin == 18) sprint(self,"SKIN: Red/Yellow women dude (19)\n");
                if (self.skin == 19) sprint(self,"SKIN: Happy dude in a suit (20)\n");
                if (self.skin == 20) sprint(self,"SKIN: Homer Simpson (21)\n");
                if (self.skin == 21) sprint(self,"SKIN: Mario (22)\n");
                if (self.skin == 22) sprint(self,"SKIN: Soldier 311 (23)\n");
                if (self.skin == 23) sprint(self,"SKIN: Ninjobo (24)\n");
                if (self.skin == 24) sprint(self,"SKIN: Deadpool (25)\n");
                if (self.skin == 25) sprint(self,"SKIN: Jason! (26)\n");
                if (self.skin == 26) sprint(self,"SKIN: Venom (27)\n");
                if (self.skin == 27) sprint(self,"SKIN: Sub-Zero (28)\n");
                if (self.skin == 28) sprint(self,"SKIN: Punisher (29)\n");
                if (self.skin == 29) sprint(self,"SKIN: HexMarine (30)\n");
                if (self.skin == 30) sprint(self,"SKIN: Grue (31)\n");
                if (self.skin == 31) sprint(self,"SKIN: Kramer (32)\n");
      	}

// *************************************************************************
// **								          **
// ** M U L T I S K I N  1.1  (end)                                       **
// **									  **
// *************************************************************************


        if (self.impulse == 254)
                FiendCheat ();

	if (self.impulse == 255)
		QuadCheat ();
		
	self.impulse = 0;
};

void() PlayerTouch =
{
if(other.takedamage != DAMAGE_AIM)
   return;
 if(!Kick_em)
   return;
   
 // boot them in the rear!
 bprint(self.netname);
 bprint(" gives ");
 if(other.classname == "player")
   bprint(other.netname);
 else
   bprint(other.classname);
 bprint(" the boot.\n");
 other.velocity_x = other.velocity_x + self.velocity_x;
 other.velocity_y = other.velocity_y + self.velocity_y;

 other.velocity_z = other.velocity_z + 50;	// add lift
 
 if(other.flags & FL_ONGROUND)
   other.flags = other.flags - FL_ONGROUND;
};

/*
============
W_WeaponFrame

Called every frame so impulse events can be handled as well as possible
============
*/
void() W_WeaponFrame =
{
	if (time < self.attack_finished)
		return;

	ImpulseCommands ();
	
// check for attack
	if (self.button0)
	{
		SuperDamageSound ();
		W_Attack ();
	}
};

/*
========
SuperDamageSound

Plays sound if needed
========
*/
void() SuperDamageSound =
{
	if (self.super_damage_finished > time)
	{
		if (self.super_sound < time)
		{
			self.super_sound = time + 1;
			sound (self, CHAN_BODY, "items/damage3.wav", 1, ATTN_NORM);
		}
	}
	return;
};


