/*
*/
void () player_chain1; // prototype from player.qc
void () player_chain3; // prototype from player.qc

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, float damage) SpawnBlood;
void() SuperDamageSound;
void() HasteSound;
void() PreviousWeaponCommand;

void() healthtoss;
.float packs;

entity(entity spot) TelefragSelectSpawnPoint;
.float	grappling;
entity	whereigo;


// called by worldspawn
void() W_Precache =
{
        precache_sound ("hknight/hit.wav");  // flamethrower
	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

        //grapple sounds (wedge)
//        precache_sound ("weapons/chain1.wav");
//        precache_sound ("weapons/chain2.wav");
//        precache_sound ("weapons/chain3.wav");
        precache_sound ("weapons/bounce2.wav");
        precache_sound ("blob/land1.wav");

// AIRG_MAIN_START
  // prechache the AirFist fire sounds.
	precache_sound ("weapons/agfire.wav");	// Air gun fire
	precache_sound ("weapons/agfail.wav");	// Air gun failed fire
	precache_sound ("weapons/agwater.wav");	// Air gun under water shot
  precache_sound ("weapons/agwfail.wav"); // Air gun fail water shot
// AIRG_MAIN_END

	// ZOID:
	// normally the weapon models are precached in the individual item
	// creation routines.  But since we've added impulse 21 we can drop
	// weapons at any time.  Must precache all weapon models.
	precache_model ("progs/g_shot.mdl");
//	precache_model ("progs/g_nail.mdl");
	precache_model ("progs/g_nail2.mdl");
	precache_model ("progs/g_rock.mdl");
	precache_model ("progs/g_rock2.mdl");
//	precache_model ("progs/g_light.mdl");
};

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

// Handles major cloaking activities
void() TWCloak =
{
		if (self.floyd == 1)
		{
			sound (self, CHAN_ITEM, "tw/twcloak2.wav", 1, ATTN_NORM);
			self.floyd = 2;
		}
		setmodel (self, "progs/player.mdl");

		self.bippy = time + 5;
		self.gene = time + 7;
		self.jimmy = 2;
};

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

	makevectors (self.v_angle);
	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, 20);
		T_Damage (trace_ent, self, self, 20);
	}
	else
	{	// hit wall
        sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);

		WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
		WriteByte (MSG_MULTICAST, TE_GUNSHOT);
		WriteByte (MSG_MULTICAST, 3);
		WriteCoord (MSG_MULTICAST, org_x);
		WriteCoord (MSG_MULTICAST, org_y);
		WriteCoord (MSG_MULTICAST, org_z);
		multicast (org, MULTICAST_PVS);
	}
};


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


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;
	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, float damage) SpawnBlood =
{
	WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
	WriteByte (MSG_MULTICAST, TE_BLOOD);
	WriteByte (MSG_MULTICAST, 1);
	WriteCoord (MSG_MULTICAST, org_x);
	WriteCoord (MSG_MULTICAST, org_y);
	WriteCoord (MSG_MULTICAST, org_z);
	multicast (org, MULTICAST_PVS);
};

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

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


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

MULTI-DAMAGE

Collects multiple small damages into a single damage

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

entity	multi_ent;
float	multi_damage;

vector	blood_org;
float	blood_count;

vector	puff_org;
float	puff_count;

void() ClearMultiDamage =
{
	multi_ent = world;
	multi_damage = 0;
	blood_count = 0;
	puff_count = 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;
};

void() Multi_Finish =
{
	if (puff_count)
	{
		WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
		WriteByte (MSG_MULTICAST, TE_GUNSHOT);
		WriteByte (MSG_MULTICAST, puff_count);
		WriteCoord (MSG_MULTICAST, puff_org_x);
		WriteCoord (MSG_MULTICAST, puff_org_y);
		WriteCoord (MSG_MULTICAST, puff_org_z);
		multicast (puff_org, MULTICAST_PVS);
	}

	if (blood_count)
	{
		WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
		WriteByte (MSG_MULTICAST, TE_BLOOD);
		WriteByte (MSG_MULTICAST, blood_count);
		WriteCoord (MSG_MULTICAST, blood_org_x);
		WriteCoord (MSG_MULTICAST, blood_org_y);
		WriteCoord (MSG_MULTICAST, blood_org_z);
		multicast (puff_org, MULTICAST_PVS);
	}
};

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

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)
	{
		blood_count = blood_count + 1;
		blood_org = org;
		AddMultiDamage (trace_ent, damage);
	}
	else
	{
 		puff_count = puff_count + 1;
	}
};

/*
================
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 ();
 
 	traceline (src, src + dir*2048, FALSE, self);
 	puff_org = trace_endpos - dir*4;
 
	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 ();
	Multi_Finish ();
};

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

	sound (self, CHAN_WEAPON, "tw/tw_shot.wav", 1, ATTN_NORM);	

	msg_entity = self;
	WriteByte (MSG_ONE, SVC_SMALLKICK);
	
	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 == 1)
	{
		W_FireShotgun ();
		return;
	}
		
	sound (self ,CHAN_WEAPON, "tw/tw_shot2.wav", 1, ATTN_NORM);	

	msg_entity = self;
	WriteByte (MSG_ONE, SVC_BIGKICK);
	
	self.currentammo = self.ammo_shells = self.ammo_shells - 2;
	dir = aim (self, 100000);
	FireBullets (14, dir, '0.19 0.08 0');
};

/*
==========================
ThunderWalker Sniper Code
an adaption of id's shotgun
code
==========================
*/
void(vector dir) FireSniper =
{

	local	vector	src;
	local	float	snipdamg;
	
	makevectors(self.v_angle);

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

	ClearMultiDamage ();
 
 	traceline (src, src + dir*2048, FALSE, self);
 	puff_org = trace_endpos - dir*4;

	snipdamg = 244 + random()*17;
 
		traceline (src, src + dir*2048, FALSE, self);
		if (trace_fraction != 1.0)
			TraceAttack (snipdamg, dir);

	ApplyMultiDamage ();
	Multi_Finish ();
};

void() W_FireSniper =
{
	local vector dir;

	sound (self, CHAN_WEAPON, "tw/tfsniper.wav", 1, ATTN_NORM);	

	msg_entity = self;
	WriteByte (MSG_ONE, SVC_SMALLKICK);
	
	self.currentammo = self.sniper_ammo = self.sniper_ammo - 1;
	dir = aim (self, 100000);
	FireSniper (dir);
};

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

ROCKETS

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

void() T_MissileTouch =
{
	local float	damg;

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

	if (self.cnt)
		return;

	self.cnt = 1;
	if (pointcontents(self.origin) == CONTENT_SKY)
	{
		remove(self);
		return;
	}
 //ThunderWalker: Damage lowered to make game more fun
	damg = 80 + random()*16;
	
	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_MULTICAST, SVC_TEMPENTITY);
	WriteByte (MSG_MULTICAST, TE_EXPLOSION);
	WriteCoord (MSG_MULTICAST, self.origin_x);
	WriteCoord (MSG_MULTICAST, self.origin_y);
	WriteCoord (MSG_MULTICAST, self.origin_z);
	multicast (self.origin, MULTICAST_PHS);

	remove(self);
};



/*
================
W_FireRocket
================
*/
void() W_FireRocket =
{
	self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
// ThunderWalker: used cool rocket sound	
	sound (self, CHAN_WEAPON, "tw/twrkt.wav", 1, ATTN_NORM);
	

	msg_entity = self;
	WriteByte (MSG_ONE, SVC_SMALLKICK);

	newmis = spawn ();
	newmis.owner = self;
	newmis.movetype = MOVETYPE_FLYMISSILE;
	newmis.solid = SOLID_BBOX;
	newmis.classname = "missile";
	newmis.cnt = 0;
		
// set newmis speed	

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

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


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


void() GrenadeExplode =
{
	// ThunderWalker:  Needed to do damage for direct hits with people who have protection rune
	if (other.twrune & ITEM_RUNE6_FLAG)
		T_Damage (other, self, self.owner, 95); 
	
	T_RadiusDamage (self, self.owner, 95, world);

	WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
	WriteByte (MSG_MULTICAST, TE_EXPLOSION);
	WriteCoord (MSG_MULTICAST, self.origin_x);
	WriteCoord (MSG_MULTICAST, self.origin_y);
	WriteCoord (MSG_MULTICAST, self.origin_z);
	multicast (self.origin, MULTICAST_PHS);

	remove (self);
};

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

	if (self.cnt)
		return;

	if (other.takedamage == DAMAGE_AIM)
	{
		self.cnt = 1;
		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';
};

/*
================
W_FireGrenade
================
*/
void() W_FireGrenade =
{	
	self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
	
// ThunderWalker:  cool grenade launch sound	
	sound (self, CHAN_WEAPON, "tw/twgrenad.wav", 1, ATTN_NORM);

	msg_entity = self;
	WriteByte (MSG_ONE, SVC_SMALLKICK);

	newmis = spawn ();
	newmis.owner = self;
	newmis.movetype = MOVETYPE_BOUNCE;
	newmis.solid = SOLID_BBOX;
	newmis.classname = "grenade";
	newmis.cnt = 0;
		
// set newmis speed	

	makevectors (self.v_angle);

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

	newmis.avelocity = '300 300 300';

	newmis.angles = vectoangles(newmis.velocity);
	
	newmis.touch = GrenadeTouch;
	
// set newmis duration
	newmis.nextthink = time + 2.5;
	newmis.think = GrenadeExplode;

	if (teamplay & TW_FLOUNDERVISION_FLAG)
		setmodel (newmis, "progs/fish.mdl");
	else
		setmodel (newmis, "progs/grenade.mdl");
	setsize (newmis, '0 0 0', '0 0 0');		
	setorigin (newmis, self.origin);
};

void() flare_touch;
void() flare_bright;
void() flare_dim;


/*
=========================================================================
Flares Code Begins Here.
=========================================================================
*/

/*
================================
launch_flare

rework of id's launch_spike code
================================
*/

.float flaretime;

void(vector org, vector dir) launch_flare =
{


	if (self.flares == 0)
	{
	centerprint (self, "You are out of flares!!!\n\n\n\n\n");
	return;
	}
        TWCloak();

	self.flares = self.flares - 1;
	
	if (self.flares == 2)	
		sprint (self, PRINT_HIGH, "2 flares left!\n");
	if (self.flares == 1)
		sprint (self, PRINT_HIGH, "1 flare left!\n");
	if (self.flares == 0)
		sprint (self, PRINT_HIGH, "Out of flares!\n");
	
	msg_entity = self;
//	WriteByte (MSG_ONE, SVC_SMALLKICK);

	newmis = spawn ();
	newmis.owner = self;
	newmis.movetype = MOVETYPE_FLYMISSILE;
	newmis.solid = SOLID_BBOX;
	newmis.classname = "flare";
		
// set newmis speed	

	makevectors (self.v_angle);
	newmis.velocity = aim(self, 1000);
	newmis.velocity = newmis.velocity * 1750;
	newmis.angles = vectoangles(newmis.velocity);
	
	newmis.touch = flare_touch;
	newmis.think = flare_bright;
	newmis.nextthink = time + 3;
	
// set newmis duration
//	newmis.nextthink = time + 5;
//	newmis.think = SUB_Remove;

        setmodel (newmis, "progs/flare.mdl");
	setsize (newmis, '0 0 0', '0 0 0');		
	setorigin (newmis, self.origin + '0 0 16');

        newmis.effects = EF_DIMLIGHT;

};

/*
============================
flare_touch

rework of id's spike_touch()
============================
*/
void() flare_touch =
{
local float rand;
	if (other == self.owner)
		return;

        if (other.classname == "door" || other.classname == "plat")
                {
                remove(self);
                return;
                }

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

	if (pointcontents(self.origin) == CONTENT_SKY)
	{
		remove(self);
		return;
	}
	
// has the flare hit something that bleeds?
	if (other.takedamage)
	{
                // If so, spawn some blood
		spawn_touchblood (9);
                // also do one point of damage    
		T_Damage (other, self, self.owner, 1);

/*
Don't remove the flare unless it is still flying. Otherwise, monsters or
other players can come up and 'pull' your flare out of the wall
*/
	      if (self.velocity != '0 0 0')
			remove(self);
	}
	else
	{
        // Write information to the network
		WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
		WriteByte (MSG_BROADCAST, TE_SPIKE);
		WriteCoord (MSG_BROADCAST, self.origin_x);
		WriteCoord (MSG_BROADCAST, self.origin_y);
		WriteCoord (MSG_BROADCAST, self.origin_z);
	}

//Stop the flare, but do not remove it.
	self.movetype = MOVETYPE_NONE;
// Fix it so that flare only partially embeds itself (thanks, Luke)
        self.origin = self.origin - self.velocity * 0.005;
     	self.velocity = '0 0 0';
	self.touch = SUB_Null;
};


/*
==============================
flare_bright()

This function makes the flare
emit brighter light
==============================
*/

void() flare_bright =
{
	local vector    vel;
// Make the flare get BRIGHT by setting .effects bit       
        self.effects = EF_BRIGHTLIGHT;
// Give it 10 seconds at maximum intensity
        self.nextthink = time + 10;
// After 10 seconds, call flare_dim
	self.think = flare_dim;
// Play a sound for flare ignition
	sound (self, CHAN_WEAPON, "tw/flareup.wav", 1, ATTN_NORM);
	
// Set up some red and yellow sparks
	vel = '0 0 150';
//	particle (self.origin+vel*0.01,vel,111,150);
//       vel = '0 0 120';
//	particle (self.origin+vel*0.01,vel,73,200);



/*
==============================
flare_dim()

This function makes the flare
go dim again
==============================
*/
};

void() flare_dim =
{
// Make the flare get dim by setting .effects bit        
        self.effects = EF_DIMLIGHT;
// Give it 15 seconds before burnout
	self.nextthink = time + 5;
// After 15 seconds remove the flare from the game
	self.think = SUB_Remove;
};





/*
===================================================================
End of Flare Code  -    Steve Bond 8/1/96 adapted for TW by Marc Rittierodt 4/97
===================================================================
*/
/*
========================
ThundeWalker Laser Code
adaption of id rocket
code
========================
*/
void() LaserTouch =
{
	if (other == self.owner)
		return;		// don't explode on owner

	if (self.cnt)
		return;

	self.cnt = 1;
	if (pointcontents(self.origin) == CONTENT_SKY)
	{
		remove(self);
		return;
	}
	if (other.health)
		T_Damage (other, self, self.owner, 58 );

remove(self);

};

void() W_FireLaser =
{

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

sound (self, CHAN_WEAPON, "tw/twlaz04.wav", 1, ATTN_NORM);

newmis = spawn();
newmis.owner = self;
newmis.movetype = MOVETYPE_FLYMISSILE;
newmis.solid = SOLID_BBOX;
newmis.classname = "laser";
newmis.cnt = 0;

makevectors (self.v_angle);
newmis.velocity = aim(self, 1000);
newmis.velocity = newmis.velocity * 1900;
newmis.angles = vectoangles(newmis.velocity);

newmis.touch = LaserTouch;
newmis.nextthink = time + 3;
newmis.think = SUB_Remove;
if (self.super_time < time)
{
if (self.steam == TEAM_COLOR2)
	setmodel (newmis, "progs/twbolt-b.mdl");
else
	setmodel (newmis, "progs/twbolt1.mdl");
}
else if (self.super_time > time)
	setmodel (newmis, "progs/whtlaser.mdl");
setsize (newmis, '0 0 0', '0 0 0');		
setorigin (newmis, self.origin + v_forward*8 + '0 0 16');

};

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

void() spike_touch;
void() superspike_touch;


/*
===============
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.cnt = 0;

	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;
//ThunderWalker: One nail, makes nails last longer on map
	self.currentammo = self.ammo_nails = self.ammo_nails - 1;
	dir = aim (self, 1000);
	launch_spike (self.origin + '0 0 16', dir);
	newmis.touch = superspike_touch;
	newmis.classname = "spike";
	setmodel (newmis, "progs/s_spike.mdl");
	setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);		
	msg_entity = self;
	WriteByte (MSG_ONE, SVC_SMALLKICK);
};

void(float ox) W_FireSpikes =
{
	local vector	dir;
	local entity	old;
	
	makevectors (self.v_angle);
	
	if (self.ammo_nails >= 2 && self.weapon == IT_SUPER_NAILGUN)
	{
		W_FireSuperSpikes ();
		return;
	}

	if (self.ammo_nails < 1)
	{
		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);

	msg_entity = self;
	WriteByte (MSG_ONE, SVC_SMALLKICK);
};



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

	if (self.cnt)
		return;

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

	self.cnt = 1;

	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_MULTICAST, SVC_TEMPENTITY);
  		if (self.classname == "wizspike")
			WriteByte (MSG_MULTICAST, TE_WIZSPIKE);
  		else if (self.classname == "knightspike")
			WriteByte (MSG_MULTICAST, TE_KNIGHTSPIKE);
  		else
			WriteByte (MSG_MULTICAST, TE_SPIKE);
		WriteCoord (MSG_MULTICAST, self.origin_x);
		WriteCoord (MSG_MULTICAST, self.origin_y);
		WriteCoord (MSG_MULTICAST, self.origin_z);
		multicast (self.origin, MULTICAST_PHS);
	}

	remove(self);

};

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

	if (self.cnt)
		return;

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

	self.cnt = 1;

	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_MULTICAST, SVC_TEMPENTITY);
		WriteByte (MSG_MULTICAST, TE_SUPERSPIKE);
		WriteCoord (MSG_MULTICAST, self.origin_x);
		WriteCoord (MSG_MULTICAST, self.origin_y);
		WriteCoord (MSG_MULTICAST, self.origin_z);
		multicast (self.origin, MULTICAST_PHS);
	}

	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.weapon == IT_AXE)
	{
		self.currentammo = 0;
		self.weaponmodel = "progs/v_axe.mdl";
		self.weaponframe = 0;
	}
        else if (self.weapon == IT_GRAPPLE)
	{
		self.currentammo = 0;
		self.weaponmodel = "progs/twharpgn.mdl";
		self.weaponframe = 0;
	}
	else if (self.weapon == IT_SHOTGUN)
	{
		self.currentammo = self.ammo_shells;
		self.weaponmodel = "progs/twvshota.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/twvshot2.mdl";
		self.weaponframe = 0;
		self.items = self.items | IT_SHELLS;
	}
	else if (self.weapon == IT_NAILGUN)
	{
		self.currentammo = self.ammo_cells;
		self.weaponmodel = "progs/twlaserh.mdl";
		self.weaponframe = 0;
		self.items = self.items | IT_CELLS;
	}
	else if (self.weapon == IT_SUPER_NAILGUN)
	{
		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.sniper_ammo;
		self.weaponmodel = "progs/v_sniper.mdl";
		self.weaponframe = 0;
	// AIRG_WEAPON_START
	}
  else if(self.weapon == IT_AIRGUN)
  {
		self.currentammo = 0;

// AIRG_MAIN_START
		self.weaponmodel = "progs/v_airgun.mdl";
// AIRG_MAIN_END

		self.weaponframe = 0;

// AIRG_WEAPON_END
	}
	else
	{
		self.currentammo = 0;
		self.weaponmodel = "";
		self.weaponframe = 0;
	}
};

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

/*	
if (self.waterlevel <= 1 && self.ammo_cells >= 1 && (it & IT_LIGHTNING) )
		return IT_LIGHTNING; 
*/
 	if(self.ammo_nails >= 1 && (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_cells >= 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;

*/
// AIRG_WEAPON_START
	if (AIRG_SHOWINWEAPONLIST == TRUE && it & IT_AIRGUN )
			return IT_AIRGUN;
// AIRG_WEAPON_END

	return IT_AXE;
};

float() W_CheckNoAmmo =
{
	if (self.currentammo > 0)
		return TRUE;
// AIRG_WEAPON_START
  // AirFist does not use any ammo.
	if (self.weapon == IT_AIRGUN)
		return TRUE;
// AIRG_WEAPON_END

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

	if (self.weapon == IT_GRAPPLE)
		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_snipe1;
void()	player_rocket1;



void() W_Attack =
{
	local	float	r;

	if (!W_CheckNoAmmo ())
		return;

// ThunderWalker:  Like in Star Trek, you cannot fire while cloaked
if (self.twrune & ITEM_RUNE8_FLAG)
		TWCloak();

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

	if (self.weapon == IT_GRAPPLE) {
		if (self.hook_out)
			player_chain3 ();
		else
			player_chain1 ();
		self.grapple_time = time + 0.1;

	}

	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 ();
		// RUNE: rune of hell magic
		if (self.player_flag & ITEM_RUNE3_FLAG) {
			self.attack_finished = time + 0.3;
			HasteSound();
		} else
			self.attack_finished = time + 0.5;
	}
	else if (self.weapon == IT_SHOTGUN)
	{
		player_shot1 ();
		W_FireShotgun ();
		// RUNE: rune of hell magic
		if (self.player_flag & ITEM_RUNE3_FLAG) {
// ThunderWalker: made faster, made mean
			self.attack_finished = time + 0.1;
			HasteSound();
		} else
			self.attack_finished = time + 0.3;
	}
	else if (self.weapon == IT_SUPER_SHOTGUN)
	{
		player_shot1 ();
		W_FireSuperShotgun ();
		// RUNE: rune of hell magic
		if (self.player_flag & ITEM_RUNE3_FLAG) {
			self.attack_finished = time + 0.25;
			HasteSound();
		} else
			self.attack_finished = time + 0.45;
	}
	else if (self.weapon == IT_NAILGUN)
	{
		        player_shot1();
                W_FireLaser();
                if (self.player_flag & ITEM_RUNE3_FLAG)
                        {
                        self.attack_finished = time + 0.2;
                        HasteSound();
                        }
                else
                self.attack_finished = time + 0.35;
	}
	else if (self.weapon == IT_SUPER_NAILGUN)
	{
		player_nail1 ();
	}
	else if (self.weapon == IT_GRENADE_LAUNCHER)
	{
		player_rocket1();
		W_FireGrenade();
		// RUNE: rune of hell magic
 		if (self.player_flag & ITEM_RUNE3_FLAG) {
 			self.attack_finished = time + 0.3;
 			HasteSound();
 		} else
			self.attack_finished = time + 0.6;
	}
	else if (self.weapon == IT_ROCKET_LAUNCHER)
	{
		player_rocket1();
		W_FireRocket();
		// RUNE: rune of hell magic
 		if (self.player_flag & ITEM_RUNE3_FLAG) {
 			self.attack_finished = time + 0.4;
 			HasteSound();
 		} else
			self.attack_finished = time + 0.8;
	}
	else if (self.weapon == IT_LIGHTNING)
	{
// ThunderWalker:  due to long reload time a message was added to let the player know when the sniper was ready to shoot again plus there is no reload time after last shot
        player_snipe1();


                W_FireSniper();
                if ((self.player_flag & ITEM_RUNE3_FLAG) && self.sniper_ammo != 0)
				{
				self.attack_finished = time + 3.25;
//				self.reload = time + 3.25;
				HasteSound();
				}
			else if (self.sniper_ammo != 0)
				{
				self.attack_finished = time + 6.5;
//				self.reload = time + 6.5;
				}
			else 
				
				self.attack_finished = time + 0.8;
				

				if (self.sniper_ammo == 4)
					centerprint(self, "Reloading\n4 Shots remaining!\n\n\n\n\n\n\n");
				else if (self.sniper_ammo == 3)
					centerprint(self, "Reloading\n3 Shots remaining!\n\n\n\n\n\n\n");
				else if (self.sniper_ammo == 2)
					centerprint(self, "Reloading\n2 Shots remaining!\n\n\n\n\n\n\n");
				else if (self.sniper_ammo == 1)
					centerprint(self, "Reloading Last Shot!!\n\n\n\n\n\n\n");
				else if (self.sniper_ammo == 0)
					centerprint(self, "Out of Sniper Ammo!");
// AIRG_WEAPON_START
	}
  else if(self.weapon == IT_AIRGUN)
  {
    // Fire the AirFist weapon
		launch_horn();
// AIRG_WEAPON_END
			}
	
};

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

============
*/
void() W_ChangeWeapon =
{
	local	float	it, am, fl;

	it = self.items;
	am = 0;
	
	if (self.impulse == 1 && self.weapon) {
		if (self.weapon == IT_AXE) {
			fl = IT_GRAPPLE;

			if (self.hook_out)
				Reset_Grapple(self.hook);
		} else if (self.weapon != IT_AXE)
			fl = IT_AXE;
	} else if (self.impulse == 22) {
		fl = IT_GRAPPLE;
		sprint (self, PRINT_HIGH , "Grappling Hook Selected\n");
		if (self.hook_out)
			sound (self, CHAN_WEAPON, "weapons/bounce2.wav", 1, ATTN_NORM);

		self.hook_out = FALSE;
		self.on_hook = FALSE;
	} else if (self.impulse == 31) {
		fl = IT_AXE;
	} else if (self.impulse == 2 || self.impulse == 32) {
		fl = IT_SHOTGUN;
		if (self.ammo_shells < 1)
			am = 1;
	} else if (self.impulse == 3 || self.impulse == 33) {
		fl = IT_SUPER_SHOTGUN;
		if (self.ammo_shells < 2)
			am = 1;
	} else if (self.impulse == 4 || self.impulse == 34) {
		fl = IT_NAILGUN;
		if (self.ammo_cells < 1)
			am = 1;
	} else if (self.impulse == 5) {
		fl = IT_SUPER_NAILGUN;
		if (self.ammo_nails < 1)
			am = 1;
	} else if (self.impulse == 35) {
		fl = IT_SUPER_NAILGUN;
		if (self.ammo_nails < 2)
			am = 1;
	} else if (self.impulse == 6 || self.impulse == 36) {
		fl = IT_GRENADE_LAUNCHER;
		if (self.ammo_rockets < 1)
			am = 1;
	} else if (self.impulse == 7 || self.impulse == 37) {
		fl = IT_ROCKET_LAUNCHER;
		if (self.ammo_rockets < 1)
			am = 1;
	} else if (self.impulse == 8 || self.impulse == 38) {
		fl = IT_LIGHTNING;
		if (self.sniper_ammo < 1)
			am = 1;
	}
// AIRG_WEAPON_START
  else if(self.impulse == AIRG_IMPULSEVALUE)
  {
	  fl = IT_AIRGUN;
  }

	// if already have the weapon or if you don't have the weapon, try the
  // double tap impulse.
  if((self.weapon == fl || !(self.items & fl) || am == 1) && AIRG_DOUBLETAPIMPULSE == self.impulse)
  {
	  fl = IT_AIRGUN;
    am = 0;
  }
// AIRG_WEAPON_END

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

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

};

/*
============
CheatCommand
============
*/
void() CheatCommand =
{
//	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 = 60;
	self.items = self.items | IT_LIGHTNING;

// AIRG_WEAPON_START
	self.items = self.items | IT_AIRGUN;
// AIRG_WEAPON_END

	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;
	
//McBain: save current weapon
	self.previous_weapon = self.weapon;

	while (1)
	{
		am = 0;

		if (self.weapon == IT_LIGHTNING) {
			self.weapon = IT_GRAPPLE;
		} else if (self.weapon == IT_GRAPPLE) {
			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)
		// AIRG_WEAPON_START
	  {
    	if(AIRG_SHOWINWEAPONLIST == TRUE) {

				self.weapon = IT_AIRGUN;

      } else {
				self.weapon = IT_SUPER_SHOTGUN;
				if (self.ammo_shells < 2)
					am = 1;
      }
		}
  	else if(self.weapon == IT_AIRGUN)
// AIRG_WEAPON_END		
		{
			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_cells < 1)
				am = 1;
		} else if (self.weapon == IT_NAILGUN) {
			self.weapon = IT_SUPER_NAILGUN;
			if (self.ammo_nails < 1)
				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.sniper_ammo < 1)
				am = 1;
		}
	
		if ( (it & self.weapon) && am == 0)
		{
			W_SetCurrentAmmo ();
			return;
		}
	}

};

/*
============
CycleWeaponReverseCommand

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

//McBain: save current weapon
	self.previous_weapon = self.weapon;

	while (1)
	{
		am = 0;

		if (self.weapon == IT_LIGHTNING)
		{
			self.weapon = IT_ROCKET_LAUNCHER;
			if (self.ammo_rockets < 1)
				am = 1;
		}
		else if (self.weapon == IT_ROCKET_LAUNCHER)
		{
			self.weapon = IT_GRENADE_LAUNCHER;
			if (self.ammo_rockets < 1)
				am = 1;
		}
		else if (self.weapon == IT_GRENADE_LAUNCHER)
		{
			self.weapon = IT_SUPER_NAILGUN;
			if (self.ammo_nails < 1)
				am = 1;
		}
		else if (self.weapon == IT_SUPER_NAILGUN)
		{
			self.weapon = IT_NAILGUN;
			if (self.ammo_cells < 1)
				am = 1;
		}
		else if (self.weapon == IT_NAILGUN)
		{
			self.weapon = IT_SUPER_SHOTGUN;
			if (self.ammo_shells < 2)
				am = 1;
		}		
		else if (self.weapon == IT_SUPER_SHOTGUN)
		// AIRG_WEAPON_START
	  {
    	if(AIRG_SHOWINWEAPONLIST == TRUE) {
				self.weapon = IT_AIRGUN;

      } else {
        self.weapon = IT_SHOTGUN;
        if (self.ammo_shells < 1)
          am = 1;
      }
		}
  	else if(self.weapon == IT_AIRGUN)
// AIRG_WEAPON_END
		{
			self.weapon = IT_SHOTGUN;
			if (self.ammo_shells < 1)
				am = 1;
		}
		else if (self.weapon == IT_SHOTGUN) {
			self.weapon = IT_AXE;
		} else if (self.weapon == IT_AXE) {
			self.weapon = IT_GRAPPLE;
		} else if (self.weapon == IT_GRAPPLE) {
			self.weapon = IT_LIGHTNING;
			if (self.sniper_ammo < 1)
				am = 1;
		}
	
		if ( (it & self.weapon) && am == 0)
		{
			W_SetCurrentAmmo ();
			return;
		}
	}

};


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

Just for development
============
*/
void() ServerflagsCommand =
{
	serverflags = serverflags * 2 + 1;
// ZOID:  Bug fix
	serverflags = (serverflags & 15);
};

//ZOID:  Uhm, where am I?
void() PrintLocation =
{
	local string p;

	p = vtos(self.origin);

	sprint(self, PRINT_HIGH, "You are at ");
	sprint(self, PRINT_HIGH, p);
	sprint(self, PRINT_HIGH, "\n");
};

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

============
*/
//ZOID: Note, changed it all to an if/else construct.  No need to check
//remaining impulses if we have one already.  Much cleaner and a tad
//more efficient.  Using a non-existant impulse is still the worst case. :(
void() ImpulseCommands =
{
	if ((self.impulse >= 1 && self.impulse <= 8) || self.impulse == 22 ||
		(self.impulse >= 31 && self.impulse <= 40) ||
 		self.impulse == 50)
  		W_ChangeWeapon ();

// AIRG_WEAPON_START
	if (self.impulse == AIRG_IMPULSEVALUE)
		W_ChangeWeapon ();
// AIRG_WEAPON_END
  
	else if (self.impulse == 9)
  		CheatCommand ();

	else if (self.impulse == 10)
  		CycleWeaponCommand ();

	else if (self.impulse == 11)
  		ServerflagsCommand ();
 
	else if (self.impulse == 12)
		CycleWeaponReverseCommand ();

//McBain: I picked 69 -- seems appropriate!  I hope 69 hasn't been used in
// other add-ons.  This is my first attempt at Quake C, and I hope I haven't
// violated any Quake C ettiquette.  :(
	else if (self.impulse == 69)
		PreviousWeaponCommand ();

	else if (self.impulse == 99)
		PrintLocation();

// ThunderWalker: flare launching
	else if (self.impulse == 160 && time > self.flaretime)
	{
		launch_flare ();
		self.flaretime = time + 0.8;
	}
// thunderWalker: boom
	else if (self.impulse == 170)
	{
 	if (self.times == 0 && !(gamestart))
		{
		if (self.invincible_finished > time)
		{
			sound (self, CHAN_AUTO, "doors/basetry.wav", 1, ATTN_NORM); 	 
			centerprint(self, "Not while 666\nThat would be silly!");
		}
		else 
			{
			sound (self, CHAN_BODY, "tw/suicide2.wav", 1, ATTN_NORM);
			self.boom = time + 3;
			}
		}
		else 
			{
			sound (self, CHAN_AUTO, "doors/basetry.wav", 1, ATTN_NORM); 	 
			centerprint (self, "You cannot Kamakazi...yet!");
			}
	}

// ThunderWalker: What rune do I have?
	else if (self.impulse == 180)
		whatrune();

// ThunderWalker: destroy rune
	else if (self.impulse == 181)
		menolike();

// ThunderWalker: Health pack toss
	else if (self.impulse == 192 && (self.packs))
		healthtoss();

// ThunderWalker: Teleporter.  Idea by Ozzzy
	else if ((self.impulse == 200) && self.transtime == 0)
		{
		if (!gamestart)
		{
		if (self.yessir)                       
			{
			centerprint(self, "Can't teleport with flag!");  
                        sound (self, CHAN_AUTO, "doors/basetry.wav", 1, ATTN_NORM);       
			}
		else if (self.acme != 1)
			{
                        sound (self, CHAN_AUTO, "doors/basetry.wav", 1, ATTN_NORM);       
                        centerprint(self, "One teleport per life!");
			}
        else
            {
            sound (self, CHAN_AUTO, "tw/twtele.wav", 1, ATTN_NORM);       
            self.attack_finished = time + 3;
            self.transtime = time + 2.85;
            }
		}
		}

// *TEAMPLAY*
// If we're allowed to drop items, enable impulse 20 and 21
	else if ((teamplay & TEAM_DROP_ITEMS) && self.impulse == 20)
                TossBackpack ();

	else if ((teamplay & TEAM_DROP_ITEMS) && self.impulse == 21)
		TossWeapon ();

// *TEAMPLAY*
// Impulse 25 prints info about the current teamplay settings.
	else if (self.impulse == 25)
		TeamPrintSettings ();

// *Capture The Flag - Status report by Wonko
// Impulse 23 prints the current status of your flag and the
// enemy flag (summarizes the endless messages)
	else if (self.impulse == 23)
		TeamFlagStatusReport();

	else if (self.impulse == 141)
		identify_player();

	else if (self.impulse == 70) {
		if (self.statstate < 0) {
			self.statstate = 0;
			sprint(self, PRINT_HIGH, "Status bar on (impulse 71 to 81 to set size)\n");
		} else {
			self.statstate = -1;
			sprint(self, PRINT_HIGH, "Status bar off.\n");
		}

	} else if (self.impulse >= 71 && self.impulse <= 81) {
		self.statstate = self.impulse - 71;
		sprint(self, PRINT_HIGH, "Status bar set\n");
	}


  	self.impulse = 0;
};

//McBain: Here's the beef...
/*
============
PreviousWeaponCommand
============
*/
void() PreviousWeaponCommand =
{
	local	float	fl, am;
	
	self.impulse = 0;
	am = 0;

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

	// this might not be the best method, but I'll be able to play sooner
	if (self.weapon == IT_SHOTGUN || self.weapon == IT_SUPER_SHOTGUN) {
		if (self.ammo_shells < 1)
			am = 1;
	}
	else if (self.weapon == IT_NAILGUN)
	{
		if (self.ammo_cells < 1)
			am = 1;
	}
	else if (self.weapon == IT_SUPER_NAILGUN) {
		if (self.ammo_nails < 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_LIGHTNING) {
		if (self.sniper_ammo < 1)
			am = 1;
	}
	// ignore AXE -- no ammo needed

	if (am)
		self.weapon = W_BestWeapon ();

	W_SetCurrentAmmo ();
};

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

Called every frame so impulse events can be handled as well as possible
============
*/
void() W_WeaponFrame =
{
//ThunderWalker:  Allows for grappling during snipe
if (self.grapple_time > time)
	return;

// ThunderWalker: However if hook is already out yer in trouble
if (self.impulse == 22)
{
	if (self.weapon == IT_LIGHTNING && self.hook_out == FALSE)
		ImpulseCommands ();
}

if ((self.weapon == IT_GRAPPLE) && (self.button0))
	{
		SuperDamageSound ();
		W_Attack ();
	}

	if (time < self.attack_finished)
		return;

//	if (time > self.reload && time < self.reload + 1)
if ((self.weapon == IT_LIGHTNING) && (time > self.attack_finished) && (time < self.attack_finished +1))
	centerprint (self, "Sniper Rifle is Ready!\n\n\n\n\n\n\n\n\n\n");

// ThunderWalker: Handles whether you should be visible or not with cloaking rune

	if (self.twrune & ITEM_RUNE8_FLAG)
	{
		if (time > self.bippy)
		{
			if (time < self.gene)
			{			
				stuffcmd (self, "bf\n");
			}
			if (self.jimmy == 2)
			{
				sound (self, CHAN_ITEM, "tw/twcloak.wav", 1, ATTN_NORM);
				self.jimmy = 1;
			}

			setmodel (self, "progs/eyes.mdl");		
			self.floyd = 1;
		}
	}
// ThunderWalker: Teleport mojo
if (self.transtime < time && self.transtime != 0) 
{
if (self.yessir)
{
	centerprint(self, "Nice Try, Bucko");
	self.transtime = 0;
}
else
{
/*
	whereigo = find(whereigo, classname, "info_player_deathmatch");
		if (whereigo == world)
			whereigo = find (whereigo, classname, "info_player_deathmatch");

	whereigo = TelefragSelectSpawnPoint(whereigo);
*/
	whereigo = SelectTeleSpot();

	spawn_tfog(self.origin);
	spawn_tfog(whereigo.origin);

	spawn_tdeath(whereigo.origin, self);

self.origin = whereigo.origin;
self.transtime = 0;
self.acme = 2;
}
}	



//ZOID: Only call ImpulseCommands() if needed!  This saves a good chunk
//of cpu.  'profile' in console listed ImpulseCommands() as #1 user of
//cpu (instructions), adding this one line caused it to not even be in
//the top ten.
	if (self.impulse)
		ImpulseCommands ();
	
// check for attack
	if (self.button0)
	{
		SuperDamageSound ();
		W_Attack ();
	}
};

/*
========
Resistancesound

Plays sound if needed
========
*/
void(entity who) ResistanceSound =
{
// RUNE play resistance sound if player has Earth Magic
	if (who.player_flag & ITEM_RUNE1_FLAG) {
		if (who.invincible_sound < time) {
			who.invincible_sound = time + 1;
			sound(who, CHAN_BODY, "rune/rune1.wav", 1, ATTN_NORM);
		}
	}
};
/*
========
SuperDamageSound

Plays sound if needed
========
*/
void() SuperDamageSound =
{
// ThunderWalker: Laser shouldn't make sound since black magic does not work with it
if (self.weapon == IT_NAILGUN)
	return;

// RUNE play super damage sound if player has Black Magic, too
	if ((self.player_flag & ITEM_RUNE2_FLAG) && 
		(self.super_damage_finished > time)) {
		if (self.super_sound < time) {
			self.super_sound = time + 1;
			sound (self, CHAN_BODY, "rune/rune22.wav", 1, ATTN_NORM);
		}
	}

	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);
		}
	}

        if ((self.player_flag & ITEM_RUNE2_FLAG) && self.weapon != IT_NAILGUN) {
		if (self.super_sound < time) {
			self.super_sound = time + 1;
			sound (self, CHAN_BODY, "rune/rune2.wav", 1, ATTN_NORM);
		}
	}
};

/*
========
RegenerationSound

Plays sound if needed
adapted to allow for
TW Living armor    
========
*/
void() RegenerationSound =
{
// RUNE play healing sound if player has Elder Magic
	if ((self.player_flag & ITEM_RUNE4_FLAG) || (self.twrune & ITEM_RUNE5_FLAG))
	{
		if (self.regeneration_sound < time) {
			self.regeneration_sound = time + 1;
			if (self.twrune & ITEM_RUNE5_FLAG)
			sound (self, CHAN_BODY, "weapons/tink1.wav", 1, ATTN_NORM);	// tink works best for this
		else
			sound(self, CHAN_BODY, "tw/twregen2.wav", 1, ATTN_NORM);
		}
	}
};

/*
========
HasteSound

Plays sound if needed
========
*/
void() HasteSound =
{
// RUNE play haste (Chthon's roar) sound if player has Hell Magic
	if (self.player_flag & ITEM_RUNE3_FLAG) {
		if (self.haste_sound < time) {
			self.haste_sound = time + 1;
			sound(self, CHAN_BODY, "rune/rune3.wav", 1, ATTN_NORM);
		}
	}
};
