/*
*/

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;
void(vector org, vector dir) launch_spike;
float	modelindex_eyes, modelindex_player;
void() respawn;

// called by worldspawn
void() W_Precache =
{
	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_sound ("items/inv3.wav");
	precache_model ("progs/eyes.mdl");
	precache_model ("progs/player.mdl");

// Begin Pulse Cannon Precache
      precache_model ("progs/laser.mdl");
	precache_sound ("enforcer/enfire.wav");        // Laser Rifle
	precache_sound ("enforcer/enfstop.wav");       // Laser Rifle
// End Pulse Cannon Precache
	precache_model ("progs/k_spike.mdl");
	precache_sound ("hknight/attack1.wav");
};

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

/*
================
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);
		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);
	}
};




void() W_Mario =
{

	SuperDamageSound ();
	T_RadiusDamage (self, self.owner, 120, self);
	


};

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


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;
//	if (self.u_ammo != 1)
//		self.currentammo = self.ammo_shells = self.ammo_shells - 1;
	dir = aim (self, 100000);
	FireBullets (3, dir, '0.06 0.04 0');
};


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

//	if (self.currentammo == 1)
//	{
//		W_FireShotgun ();
//		return;
//	}
		
	sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM); 

	self.punchangle_x = -4;
//	if (self.u_ammo != 1)
//		self.currentammo = self.ammo_shells = self.ammo_shells - 2;
	dir = aim (self, 100000);
	FireBullets (16, dir, '0.20 0.10 0');
};


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

ROCKETS
Built in Rocket Functions
==============================================================================
*/

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] {};

void()      player_rock1;
void()      player_rock2;


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_RocketTouch =
{
	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 ();
};



/*
================
W_FireRocket
================
*/
void() W_FireRocket =
{
	local   entity missile, mpuff;
	
	self.currentammo = self.ammo_rockets = self.ammo_rockets - 2;
	
	sound (self, CHAN_WEAPON, "weapons/sgun1.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_RocketTouch;
	
// set missile duration
	missile.nextthink = time + 5;
	missile.think = SUB_Remove;

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

void() T_RocketTouch2 =
{
	local float     damg;

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

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

	damg = 25 + random()*10;
	
	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, 30, 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 ();
};

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 = 80 + random()*20;
	damg = self.life + 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, 40, 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 ();
};



/*
================
W_FireMissle
				Homing Missles v.005
				~~~~~~~~~~~~~~~~~~~~
Authors: Lynx (briggsj@lurch.ball.com)
	 Dumont (pjsmith@ix.netcom.com)       

Credits: based on Homing Missiles v.001
		by Vhold <vhold@netwizards.net> 
		http://netwizards.net/~vhold/


================
*/
void()   HomeThink;
entity() HomeFindTarget;
float(entity targ) visible;
float(entity targ) infront;

void() W_FireMissle =
{
	local   entity missile, mpuff;
      if (self.ammo_rockets < 5)
	{         
	player_rock1();
		return;
	}
	if (self.u_ammo != 1)
		self.currentammo = self.ammo_rockets = self.ammo_rockets - 5;
	
	sound (self, CHAN_WEAPON, "weapons/sgun1.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 * 450;
	missile.angles = vectoangles(missile.velocity);

	missile.life = 100;
	
	missile.touch = T_MissileTouch;
	
// set missile duration
//      missile.nextthink = time + 1;
//      missile.think = SUB_Remove;

	missile.nextthink = time + 0.25;
	missile.think = HomeThink;
	missile.enemy = world;

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

entity() HomeFindTarget = 
{
	local entity head, selected;
	local float dist;
	dist = 100000;
	selected = world;
	head = findradius(self.origin, 250);
	while(head)
	{
		if( (head.health > 1) && (head != self) && (head != self.owner) )
		{
			traceline(self.origin,head.origin,TRUE,self);
			if ( (trace_fraction >= 1) && (vlen(head.origin - self.origin) < dist) )
			{
				selected = head;
				dist = vlen(head.origin - self.origin);
			}
		}               
		head = head.chain;
	}
	if (selected != world)
	{
		sprint (self.owner,"Homing->");
		if (selected.classname == "player")
		{
			sprint (self.owner,selected.netname);
			sprint (selected,self.owner.netname);
			sprint (selected," has a bogey on you!\n");
		}
		else
		{
			sprint (self.owner,selected.classname);
		}
		sprint (self.owner,"\n");
	}
	return selected;
};

void() HomeThink =
{
	local vector dir, olddir, vtemp;
	local float turnrate;

	turnrate= 0.3;
	if ( !(self.enemy) || (self.enemy == world) || (self.enemy.health < 1) )
		self.enemy = HomeFindTarget();

	if (self.enemy != world) // Arr.. don't be taken on da World!
	{
		vtemp = self.enemy.origin + '0 0 10';
		olddir = normalize(self.velocity);
		dir = normalize(vtemp - self.origin);
		//Limits the turnrate of the rockets
		if (olddir_x - dir_x > turnrate)
			dir_x = olddir_x - turnrate;
		if (olddir_x - dir_x < -1 * turnrate)
			dir_x = olddir_x + turnrate;
		if (olddir_y - dir_y > turnrate)
			dir_y = olddir_y - turnrate;
		if (olddir_y - dir_y < -1 * turnrate)
			dir_y = olddir_y + turnrate;
		if (olddir_z - dir_z > turnrate)
			dir_z = olddir_z - turnrate;
		if (olddir_z - dir_z < -1 * turnrate)
			dir_z = olddir_z + turnrate;
		self.velocity = dir * 230;
		self.angles = vectoangles(self.velocity);
		self.life = self.life - 2;
	}

	if (self.life < 5)
		{
		self.enemy = world;
		T_MissileTouch;
		}
	self.nextthink = time + 0.1;
	self.think=HomeThink;
};

/*

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

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;
	if (self.u_ammo != 1)
		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);
};


//=============================================================================
//GRENADES
//=============================================================================

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

void() GrenadeTouch =
{
	if (other == self.owner)
		return;         // don't explode on owner
	if (other.takedamage == DAMAGE_AIM)
	{
		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 =
{
	local   entity missile, mpuff;
	if (self.u_ammo != 1)
		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 = "grenade";
		
// 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;
	
// set missile duration
	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);
};


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

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.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 * 1200;
};

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;
	if (self.u_ammo != 1)
		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;
};

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;
	if (self.u_ammo != 1)
		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 (21);
		T_Damage (other, self, self.owner, 21);
	}
	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);

};

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

Laser

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

/*
================
W_FirePulseCannon

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

void() Laser_Touch2 =
{
	local vector org;
	
	if (other == self.owner)
		return;         // don't explode on owner

	if (pointcontents(self.origin) == CONTENT_SKY)
	{
		remove(self);
		return;
	}
	
	sound (self, CHAN_WEAPON, "enforcer/enfstop.wav", 1, ATTN_STATIC);
	org = self.origin - 8*normalize(self.velocity);

	if (other.health)
	{
		SpawnBlood (org, self.velocity*0.2, 20);
		T_Damage (other, self, self.owner, 20);
	}
	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);
	}
	
	remove(self);   
};

void(vector org, vector vec) LaunchLaser2 =
{
	local   vector  vec;
		
	sound (self, CHAN_WEAPON, "enforcer/enfire.wav", 1, ATTN_NORM);
	vec = normalize(vec);
	
	newmis = spawn();
	newmis.owner = self;
	newmis.movetype = MOVETYPE_FLY;
	newmis.solid = SOLID_BBOX;
	newmis.effects = EF_DIMLIGHT;

	setmodel (newmis, "progs/laser.mdl");
	setsize (newmis, '0 0 0', '0 0 0');             

	setorigin (newmis, org);

      newmis.velocity = vec * 800;
	newmis.angles = vectoangles(newmis.velocity);

	newmis.nextthink = time + 5;
	newmis.think = SUB_Remove;
	newmis.touch = Laser_Touch2;
};




/*
============
Start Marmot's Pulse Cannon
============
*/

void()      player_pulse1;
void()      player_pulse2;


void(float ox) W_FirePulse =
{
	local vector    dir;
	local entity    old;
	
	makevectors (self.v_angle);
	
	if (self.ammo_shells < 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.punchangle_x = -2;
	
	if (self.u_ammo != 1)
		self.currentammo = self.ammo_shells = self.ammo_shells - 1;
	dir = aim (self, 100000);
	LaunchLaser2(self.origin + '0 0 16' + v_right*ox, dir);
};

/*
============
End Marmot's Pulse Cannon
============
*/


// ------------------------------------------
// Pipe Bombs
//
// Modifications by AsmodeusB (28/07/96)
//
// Bill Lefler 8/1/96 - changed keys to:
//                                  "IMPULSE 22" - fire pipe bomb
//                                  "IMPULSE 23" - detonate pipe bomps
// ------------------------------------------

//===========================================================================
// 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;
	if (self.u_ammo != 1)
		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;

//      missile.nextthink = time + 0.3;
//      missile.think = RichThink;

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

/*
==================
End Pipe Bombs
==================
*/

/*
================
Start Marmot's Happy Fun Rocket Pack
================
*/


void(float ox) W_FireRocket2 =
{
	local   entity missile;
	local entity old;

	sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
	if (self.u_ammo != 1)
		self.currentammo = self.ammo_rockets = self.ammo_rockets - 0.5;
	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, 1200);
	missile.velocity = missile.velocity * 1200;
	missile.angles = vectoangles(missile.velocity);
	
	missile.touch = T_RocketTouch2;
	
// set missile duration
	missile.nextthink = time + 5;
	missile.think = SUB_Remove;

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

};

/*
================
End Marmot's Happy Fun Rocket Pack
================
*/

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

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_SHOTGUN)
	{
//		self.currentammo = self.ammo_shells;
		self.currentammo = 0;
		self.weaponmodel = "progs/v_shot.mdl";
		self.weaponframe = 0;
		self.items = self.items;
	}
	else if (self.weapon == IT_SUPER_SHOTGUN)
	{
		self.currentammo = 0;
//		self.currentammo = self.ammo_shells;
		self.weaponmodel = "progs/v_shot2.mdl";
		self.weaponframe = 0;
		self.items = self.items;
	}
	else if (self.weapon == IT_NAILGUN)
	{
		self.currentammo = self.ammo_shells;
		self.weaponmodel = "progs/v_nail.mdl";
		self.weaponframe = 0;
		self.items = self.items | IT_SHELLS;
	}
	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.weapon == IT_PIPE_BOMBS))
	{
		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.weapon == IT_MISSILE_LAUNCHER) || (self.weapon == IT_ROCKET_OLD))
	{
		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 >= 1 && (it & IT_SUPER_NAILGUN) )
		return IT_SUPER_NAILGUN;
	else if(self.ammo_shells >= 1 && (it & IT_NAILGUN) )
		return IT_NAILGUN;
	else if(it & IT_SUPER_SHOTGUN) 
		return IT_SUPER_SHOTGUN;
//	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 >= 5 && (it & IT_MISSILE_LAUNCHER) )
		return IT_MISSILE_LAUNCHER;
	else if(self.ammo_rockets >= 2 && (it & IT_ROCKET_OLD) )
		return IT_ROCKET_OLD;
	else if(self.ammo_rockets >= 1 && (it & IT_GRENADE_LAUNCHER) )
		return IT_GRENADE_LAUNCHER;
	else if(self.ammo_rockets >= 1 $$ (it & IT_PIPE_BOMBS) )
		return IT_PIPE BOMBS;

*/

	return IT_SHOTGUN;
};

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

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

	if (self.weapon == IT_SUPER_SHOTGUN)
		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() W_Attack =
{
	local   float   r;

	if (!W_CheckNoAmmo ())
		return;

	if (self.observer == 1)
		return;

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

	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.2;

	}
	else if (self.weapon == IT_SUPER_SHOTGUN)
	{
		player_shot1 ();
		W_FireSuperShotgun ();
		self.attack_finished = time + 0.6;
	}
	else if (self.weapon == IT_NAILGUN)
	{
		player_pulse1 ();
	}
	else if (self.weapon == IT_SUPER_NAILGUN)
	{
		player_nail1 ();
	}
	else if (self.weapon == IT_GRENADE_LAUNCHER)
	{
		player_rocket1();
		W_FireGrenade();
		self.attack_finished = time + 0.5;
	}
	else if (self.weapon == IT_PIPE_BOMBS)
	{
		player_rocket1();
		W_FirePipeBomb();
		self.attack_finished = time + 0.5;
	}
	else if (self.weapon == IT_ROCKET_OLD)
	{
		player_rocket1();
		W_FireRocket();
		self.attack_finished = time + 0.8;
	}
	else if (self.weapon == IT_ROCKET_LAUNCHER)
	{
		player_rock1();
      }
      else if (self.weapon == IT_MISSILE_LAUNCHER)
	{
		player_rocket1();
		W_FireMissle();
		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_shells < 1)
			am = 1;
	}
	else if (self.impulse == 5)
	{
		fl = IT_SUPER_NAILGUN;
		if (self.ammo_nails < 1)
			am = 1;
	}
	else if (self.impulse == 6)
	{
		if (self.weapon == IT_GRENADE_LAUNCHER)
		{
			self.weapon = IT_PIPE_BOMBS;
			if (self.ammo_rockets < 1)
				am =1;
			sprint(self,"Pipe Bomb mode\n");
			return;
		}  
		sprint(self,"Grenade Launcher Mode\n");
		
		fl = IT_GRENADE_LAUNCHER;
		if (self.ammo_rockets < 1)
			am = 1;

	}
	else if (self.impulse == 7)
	{

		if (self.weapon == IT_ROCKET_LAUNCHER)
		{
			self.weapon = IT_MISSILE_LAUNCHER;
			if (self.ammo_rockets < 5)
				am =1;
			sprint(self,"Homing Missile Mode\n");
			return;
		}
		if (self.weapon == IT_MISSILE_LAUNCHER)
		{
			self.weapon = IT_ROCKET_OLD;
			if (self.ammo_rockets < 2)
				am =1;
			sprint(self,"Rocket Launcher Mode\n");
			return;
		}  
		sprint(self,"Rocket Pod Mode\n");
		
		fl = IT_ROCKET_LAUNCHER;
		if (self.ammo_rockets < 0.5)
			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 ();
};

/*
============
W_DropWeapon

============
*/
void() Drop_PulseCannon;
void() Drop_SuperShotgun;
void() Drop_SuperNailgun;
void() Drop_RocketLauncher;
void() Drop_GrenadeLauncher;
void() Drop_Thunderbolt;

void() W_DropWeapon =
{
	
	if (self.impulse == 3)
	{
		sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
		bprint (self.netname);
	      bprint (" has placed a SuperShotgun onto the level.\n");
		Drop_SuperShotgun ();
	}               
	else if (self.impulse == 4)
	{
		sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
		bprint (self.netname);
	      bprint (" has placed a Pulse Cannon onto the level.\n");
		Drop_PulseCannon ();
	}
	else if (self.impulse == 5)
	{
		sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
		bprint (self.netname);
	      bprint (" has placed a SuperNailgun onto the level.\n");
		Drop_SuperNailgun ();
	}
	else if (self.impulse == 6)
	{
		sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
		bprint (self.netname);
	      bprint (" has placed a Grenade Launcher onto the level.\n");
		Drop_GrenadeLauncher ();
	}
	else if (self.impulse == 7)
	{
		sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
		bprint (self.netname);
	      bprint (" has placed a Rocket Launcher onto the level.\n");
		Drop_RocketLauncher ();
	}
	else if (self.impulse == 8)
	{
		sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
		bprint (self.netname);
	      bprint (" has placed a Thunderbolt onto the level.\n");
		Drop_Thunderbolt ();
	}
	self.impulse = 0;
	self.drop = 0;

};


/*
============
CheatCommand
============
*/
void() CheatCommand =
{
	if (deathmatch || coop)
	{               
			return;
	}
	else
	{

	self.ammo_rockets = 200;
	self.ammo_nails = 200;
	self.ammo_shells = 200;
	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 ();
	}
};

/*
===============
CheatCommand II
===============
*/
void() CheatCommand2 =
{
	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_shells < 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_PIPE_BOMBS;
			if (self.ammo_rockets < 1)
				am = 1;
		}
		else if (self.weapon == IT_PIPE_BOMBS)
		{
			self.weapon = IT_ROCKET_LAUNCHER;
			if (self.ammo_rockets < 0.5)
				am = 1;
		}
		else if (self.weapon == IT_ROCKET_LAUNCHER)
		{
			self.weapon = IT_ROCKET_OLD;
			if (self.ammo_rockets < 2)
				am = 1;
		}
		else if (self.weapon == IT_ROCKET_OLD)
		{
			self.weapon = IT_MISSILE_LAUNCHER;
			if (self.ammo_rockets < 5)
				am = 1;
		}
		else if (self.weapon == IT_MISSILE_LAUNCHER)
		{
			self.weapon = IT_LIGHTNING;
			if (self.ammo_cells < 3)
				am = 1;
		}
	
		if ( (self.items & self.weapon) && am == 0)
		{
			W_SetCurrentAmmo ();
			return;
		}
	}

};

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

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

void() QuadCheat =
{
	if (deathmatch || coop)
	{               
			return;
	}
	else
//              return;
	{
	self.super_time = 1;
	self.super_damage_finished = time + 30;
	self.items = self.items | IT_QUAD;
//	dprint ("quad cheat\n");
	}
};


void() Setnoammo =
{
	if ((deathmatch) && (self.admin != 3))
		return;
	if (self.sysop != 3)
		return;
	if (self.u_ammo == 1)
		{
		self.u_ammo = 0;
		sprint (self,"Limited Ammo Mode Engaged\n");
		bprint (self.netname);
	      bprint (" has left unlimited ammunition mode\n");
		return;
		}
	self.u_ammo = 1;
	sprint (self,"Unlimited Ammo Mode Engaged\n");
	bprint (self.netname);
	bprint (" has entered unlimited ammunition mode\n");
};

void() Help =
{
		sprint (self, "Impulse Commands available are:\n");
		sprint (self, "\n");
		sprint (self, "impulse 23 - detonate pipe bombs\n"); 
		sprint (self, "impulse 200 - next skin\n");		
		sprint (self, "impulse 201 - previous skin\n");
		sprint (self, "impulse 210 - Toggle Mouse Mode\n");
		sprint (self, "impulse 211 - Toggle between Mouse and Moth modes\n");
		sprint (self, "\n");
		sprint (self, "6 and 7 cycle for more weapons\n");


};


/*
============
TimeOverride

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

void() TimeOverride =
{
	if (self.impulse == 1)
	{
		localcmd ("timelimit 10");
	}               
	else if (self.impulse == 2)
	{
		localcmd ("timelimit 20");
	}
	else if (self.impulse == 3)
	{
		localcmd ("timelimit 30");
	}
	else if (self.impulse == 4)
	{
		localcmd ("timelimit 40");
	}
	else if (self.impulse == 5)
	{
		localcmd ("timelimit 50");
	}
	else if (self.impulse == 6)
	{
		localcmd ("timelimit 60");
	}

	self.impulse = 0;
	self.set_timelimit = 0;
};

/*
============
FragOverride

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

void() FragOverride =
{
	if (self.impulse == 1)
	{
		localcmd ("fraglimit 10");
	}               
	else if (self.impulse == 2)
	{
		localcmd ("fraglimit 20");
	}
	else if (self.impulse == 3)
	{
		localcmd ("fraglimit 30");
	}
	else if (self.impulse == 4)
	{
		localcmd ("fraglimit 40");
	}
	else if (self.impulse == 5)
	{
		localcmd ("fraglimit 50");
	}
	else if (self.impulse == 6)
	{
		localcmd ("fraglimit 60");
	}
	else if (self.impulse == 7)
	{
		localcmd ("fraglimit 70");
	}
	else if (self.impulse == 8)
	{
		localcmd ("fraglimit 80");
	}

	self.impulse = 0;
	self.set_fraglimit = 0;
};



/*
============
W_WarpEpisode1

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

void() W_WarpEpisode1 =
{
	if (self.impulse == 1)
	{
		changelevel ("e1m1");
	}               
	else if (self.impulse == 2)
	{
		changelevel ("e1m2");
	}
	else if (self.impulse == 3)
	{
		changelevel ("e1m3");
	}
	else if (self.impulse == 4)
	{
		changelevel ("e1m4");
	}
	else if (self.impulse == 5)
	{
		changelevel ("e1m5");
	}
	else if (self.impulse == 6)
	{
		changelevel ("e1m6");
	}
	else if (self.impulse == 7)
	{
		changelevel ("e1m7");
	}
	else if (self.impulse == 8)
	{
		changelevel ("e1m8");
	}
	self.impulse = 0;
	self.s_switch = 0;
	self.s_episode = 0;
};


/*
============
W_WarpEpisode2

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

void() W_WarpEpisode2 =
{
	if (self.impulse == 1)
	{
		changelevel ("e2m1");
	}               
	else if (self.impulse == 2)
	{
		changelevel ("e2m2");
	}
	else if (self.impulse == 3)
	{
		changelevel ("e2m3");
	}
	else if (self.impulse == 4)
	{
		changelevel ("e2m4");
	}
	else if (self.impulse == 5)
	{
		changelevel ("e2m5");
	}
	else if (self.impulse == 6)
	{
		changelevel ("e2m6");
	}
	else if (self.impulse == 7)
	{
		changelevel ("e2m7");
	}
	self.impulse = 0;
	self.s_switch = 0;
	self.s_episode = 0;
};


/*
============
W_WarpEpisode3

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

void() W_WarpEpisode3 =
{
	if (self.impulse == 1)
	{
		changelevel ("e3m1");
	}               
	else if (self.impulse == 2)
	{
		changelevel ("e3m2");
	}
	else if (self.impulse == 3)
	{
		changelevel ("e3m3");
	}
	else if (self.impulse == 4)
	{
		changelevel ("e3m4");
	}
	else if (self.impulse == 5)
	{
		changelevel ("e3m5");
	}
	else if (self.impulse == 6)
	{
		changelevel ("e3m6");
	}
	else if (self.impulse == 7)
	{
		changelevel ("e3m7");
	}

	self.impulse = 0;
	self.s_switch = 0;
	self.s_episode = 0;
};


/*
============
W_WarpEpisode4

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

void() W_WarpEpisode4 =
{
	if (self.impulse == 1)
	{
		changelevel ("e4m1");
	}               
	else if (self.impulse == 2)
	{
		changelevel ("e4m2");
	}
	else if (self.impulse == 3)
	{
		changelevel ("e4m3");
	}
	else if (self.impulse == 4)
	{
		changelevel ("e4m4");
	}
	else if (self.impulse == 5)
	{
		changelevel ("e4m5");
	}
	else if (self.impulse == 6)
	{
		changelevel ("e4m6");
	}
	else if (self.impulse == 7)
	{
		changelevel ("e4m7");
	}
	else if (self.impulse == 8)
	{
		changelevel ("e4m8");
	}
	self.impulse = 0;
	self.s_switch = 0;
	self.s_episode = 0;
};


/*
============
W_WarpDeath

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

void() W_WarpDeath =
{
	if (self.impulse == 1)
	{
		changelevel ("dm1");
	}               
	else if (self.impulse == 2)
	{
		changelevel ("dm2");
	}
	else if (self.impulse == 3)
	{
		changelevel ("dm3");
	}
	else if (self.impulse == 4)
	{
		changelevel ("dm4");
	}
	else if (self.impulse == 5)
	{
		changelevel ("dm5");
	}
	else if (self.impulse == 6)
	{
		changelevel ("dm6");
	}

	self.impulse = 0;
	self.s_switch = 0;
	self.s_episode = 0;
};

void() MakeMouse =
{
	self.health = 100;
	self.takedamage = DAMAGE_NO;
	self.solid = SOLID_NOT;
	self.movetype = MOVETYPE_WALK;
	self.effects = 0;
	
	self.deadflag = DEAD_NO;
	
	setmodel (self, string_null);
	self.items = 0;
	self.currentammo = 0;
	self.weaponmodel = "";
	self.weaponframe = 0;
	self.weapon = 0;
	self.flags = self.flags | FL_ONGROUND;
};


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

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

void() ImpulseCommands =
{
	local   entity  kicker;
	local   float dumb;
	local   float stupid;

	if ((self.sysop > 2) && (self.impulse != 0))
		{
		if (self.impulse == OP_CODE_1)		
			self.impulse = 0;
		if (self.impulse == OP_CODE_2)		
			self.impulse = 0;
		if (self.impulse == OP_CODE_3)		
			self.impulse = 0;
		if (self.impulse == AD_CODE_1)		
			self.impulse = 0;
		if (self.impulse == AD_CODE_2)		
			self.impulse = 0;
		if (self.impulse == AD_CODE_3)		
			self.impulse = 0;
		}

	if ((self.admin == 1) && (self.impulse != 0))
		if (self.impulse != AD_CODE_2)		
			self.admin = 0;

	if ((self.admin == 2) && (self.impulse != 0))
		if (self.impulse != AD_CODE_3)
			self.admin = 0;


	if ((self.drop == 1) && (self.impulse > 8))
		{
		self.drop = 0;
		}
	if ((self.s_switch == 1) && (self.impulse > 6))
		{
		self.s_switch = 0;
		}
	if ((self.set_timelimit == 1) && (self.impulse > 8))
		{
		self.set_timelimit = 0;
		}
	if ((self.set_fraglimit == 1) && (self.impulse > 8))
		{
		self.set_fraglimit = 0;
		}
	if ((self.s_switch == 1)  && (self.impulse == 6))
		{
		self.impulse = 0;
		self.s_switch = 0;
		changelevel("start");
		}	
	if ((self.s_switch == 2) && (self.impulse > 8))
		{
		self.s_switch = 0;
		}
	if ((self.impulse >= 1) && (self.impulse <= 8))
		{
		if (self.drop != 1)
			{
			if (self.set_timelimit != 1)
				{
				if (self.set_fraglimit != 1)
					{
					if (self.s_switch == 1)
						{
						self.s_episode = self.impulse; 
						self.s_switch = 2;
						}
					else if (self.s_switch == 2)
						{
						if (self.s_episode == 1)
							W_WarpEpisode1 ();
						if (self.s_episode == 2)
							W_WarpEpisode2 ();
						if (self.s_episode == 3)
							W_WarpEpisode3 ();
						if (self.s_episode == 4)
							W_WarpEpisode4 ();
						if (self.s_episode == 5)
							W_WarpDeath ();
						}
					else		
						{
						W_ChangeWeapon ();
						}
					}	
				else
					{
					FragOverride ();
					}
				}
			else 
				{
				TimeOverride ();
				}
			}
		else
                        {
			W_DropWeapon ();
			}
		}
	if (self.impulse == 9)
		CheatCommand ();
	if (self.impulse == 10)
		CycleWeaponCommand ();
	if (self.impulse == 11)
		ServerflagsCommand ();
      if (self.impulse == 23)
		DetPipeBombs ();
	if (self.impulse == 120)
		{
		if (self.sysop == 3)
			{
			sprint(self,"Press the key of the weapon to deploy\n");
			self.drop = 1;
			}
		}
	if (self.impulse == 130)
		{
		if (self.sysop == 3)
			{
			sprint(self,"Enter destination level: \n");
			self.s_switch = 1;
			}
		}

	if (self.impulse == 160)
		{
		if (self.sysop == 3)
			{
			sprint(self,"New Time Limit (x10 min)\n");
			self.set_timelimit = 1;
			}
		}

	if (self.impulse == 161)
		{
		if (self.sysop == 3)
			{
			sprint(self,"New Frag Limit (x10)\n");
			self.set_fraglimit = 1;
			}
		}
// Server Admin Stuff Starts
				     
		if (self.impulse == OP_CODE_1)
		{
			self.sysop = 1;
		}
		if (self.impulse == OP_CODE_2)
		{
			if (self.sysop == 1)
			{
				self.sysop = 2;
			}
			else
			{
				self.sysop = 0;
			}
		}
		if (self.impulse == OP_CODE_3) 
		{
			if (self.sysop == 2)
			{
				self.sysop = 3;
				sprint(self,"\nSysop privileges enabled\n");
				bprint(self.netname);
				bprint(" is now a Sysop\n");
				dprint("***OPER -- ");
				dprint(self.netname);
				dprint(" is now a Sysop\n");
			}
			else 
			{
				self.sysop = 0;
			}
		}

		if (self.impulse == AD_CODE_1)
		{
			self.admin = 1;
		}
		if (self.impulse == AD_CODE_2)
		{
			if (self.admin == 1)
			{
				self.admin = 2;
			}
			else
			{
				self.admin = 0;
			}
		}
		if (self.impulse == AD_CODE_3) 
		{
			if (self.admin == 2)
			{
				self.admin = 3;
				self.sysop = 3;
				sprint(self,"\nAdmin privileges enabled\n");
				bprint(self.netname);
				bprint(" is now an Admin\n");
				dprint("***OPER -- ");
				dprint(self.netname);
				dprint(" is now an Admin\n");
			}

		}

		if ((self.impulse == 134) && (self.sysop == 3))
		{
			bprint(self.netname);
			bprint(" sets Teamplay -- is now ");
			if (cvar("teamplay") == 1)
			{
				 bprint("ON\n");
				 dumb = 2;
				 dprint ("***MODE -- ");
				 dprint (self.netname);
				 dprint (" sets teamplay mode 2\n");
			}
			else if (cvar("teamplay") == 2)
			{
				 bprint("ON\n");
				 dumb = 3;
				 dprint ("***MODE -- ");
				 dprint (self.netname);
				 dprint (" sets teamplay mode 3\n");
			}
			else if (cvar("teamplay") == 3)
			{
				 bprint("OFF\n");
				 dumb = 0;
				 dprint ("***MODE -- ");
				 dprint (self.netname);
				 dprint (" sets teamplay off\n");
			}
			else
			{
				 bprint("ON\n");
				 dumb = 1;
				 dprint ("***MODE -- ");
				 dprint (self.netname);
				 dprint (" sets teamplay mode 1\n");
			}                          
			if (dumb == 0)
				localcmd("teamplay 0\n");
			if (dumb == 1)
				localcmd("teamplay 1\n"); 
			if (dumb == 2)
				localcmd("teamplay 2\n"); 
			if (dumb == 3)
				localcmd("teamplay 3\n");  
		}

		if ((self.impulse == 133) && (self.sysop == 3))
		{
			bprint(self.netname);
			bprint(" sets DeathMatch");
			if (cvar("deathmatch") == 1)
			{
				bprint(" 2\n");
				dprint ("***MODE -- "); 
				dprint (self.netname);
				dprint (" sets Deathmatch 2\n");
				localcmd("deathmatch 2\n");
			}
			else
			{
				bprint(" 1\n");
				dprint ("***MODE -- "); 
				dprint (self.netname);
				dprint (" sets Deathmatch 1\n");
				localcmd("deathmatch 1\n"); 
			}
			bprint("Restarting level with new settings...\n");
			changelevel(mapname);
		}
				     
		if ((self.impulse == 132) && (self.sysop == 3))
		{
			bprint(self.netname);
			bprint(" sets Coop-Mode ");
			if (cvar("coop") == 1)
			{
				bprint(" off\n");
				dprint ("***MODE -- "); 
				dprint (self.netname);
				dprint (" sets Coop OFF\n");

				localcmd("coop 0\n");
				localcmd("deathmatch 1\n");
			}
			else
			{
				bprint(" on\n");
				dprint ("***MODE -- "); 
				dprint (self.netname);
				dprint (" sets Coop ON\n");
				
				localcmd("deathmatch 0\n");
				localcmd("coop 1\n");
			}
			bprint("Restarting level with new settings...\n");
			changelevel(mapname);
		}

		if ((self.impulse == 131) && (self.sysop == 3))
		{                    
			bprint(self.netname);
			bprint(" sets NoExit ");
			if (cvar("noexit") == 1)
			{
				bprint("OFF\n");
				dprint ("***MODE -- "); 
				dprint (self.netname);
				dprint (" sets NoExit OFF\n");

				localcmd("noexit 0\n");
			}
			else
			{
				bprint("ON\n");
				dprint ("***MODE -- "); 
				dprint (self.netname);
				dprint (" sets NoExit ON\n");
				localcmd("noexit 1\n");
			}
			
		}


		if ((self.impulse == 135) && (self.sysop == 3))
		{
			bprint(self.netname);
			bprint(" sets Skill -- is now ");
			if (cvar("skill") == 0)
			{
				 bprint("1\n");
				 stupid = 1;
				 dprint ("***MODE -- ");
				 dprint (self.netname);
				 dprint (" sets normal skill\n");
			}
			else if (cvar("skill") == 1)
			{
				 bprint("2\n");
				 stupid = 2;
				 dprint ("***MODE -- ");
				 dprint (self.netname);
				 dprint (" sets hard skill\n");
			}
			else if (cvar("skill") == 2)
			{
				 bprint("3\n");
				 stupid = 3;
				 dprint ("***MODE -- ");
				 dprint (self.netname);
				 dprint (" sets nightmare skill\n");
			}
			else if (cvar("skill") == 3)
			{
				 bprint("0\n");
				 stupid = 0;
				 dprint ("***MODE -- ");
				 dprint (self.netname);
				 dprint (" sets easy skill\n");
			}                          
			if (stupid == 0)
				localcmd("skill 0\n");
			if (stupid == 1)
				localcmd("skill 1\n"); 
			if (stupid == 2)
				localcmd("skill 2\n"); 
			if (stupid == 3)
				localcmd("skill 3\n");  
	  		bprint("Restarting level with new settings...\n");
			changelevel(mapname);
		}

// Give the admin all the weapons and 255 of each ammo
// Limited usefullness, included for completeness

	if ((self.impulse == 140) && (self.admin == 3))
	{
	    bprint (self.netname);
	    bprint (" has used administrative ammo/weapon cheat\n");
	    CheatCommand2 ();
	}
// Administrator God Mode, invulnerability and quad damage for getting medieval 
// on campers, snipers, and other scum who deserve it

	if ((self.impulse == 141) && (self.admin == 3) && (self.sysop == 3))
	{            
		if (self.admin_god != 1)
		{
			self.admin_god = 1;
			self.items = self.items | IT_INVULNERABILITY;
			self.takedamage    = DAMAGE_NO;
//			self.effects = -1;
			bprint (self.netname);
			bprint (" has entered administrative god mode\n");
		}
		else 
		{
			self.items = self.items - IT_INVULNERABILITY;
			self.takedamage    = DAMAGE_AIM;
//			self.effects = 0;
			bprint (self.netname);
			bprint (" has left administrative god mode\n");
			self.admin_god = 0;
		}
	}


		if ((self.impulse == 150) && (self.sysop == 3))
		{
			self.kick = 3;
			kicker = find(world, classname, "player");
			sprint(self,"Kick ");
			sprint(self,kicker.netname);
			sprint(self,"?\n");
		}

		if ((self.impulse == 151) && (self.kick == 3))
		{
			bprint(self.netname);
			bprint(" has kicked ");
			bprint(kicker.netname);
			bprint(" off the server\n");
			dprint("***KICK -- ");
			dprint(self.netname);
			dprint(" kicks ");
			dprint(kicker.netname);
			dprint(" off the server\n");
			localcmd("kick ");
			localcmd(kicker.netname);
			localcmd("\n");
			self.kick = 0;

		}

		if ((self.impulse == 152) && (self.kick == 3))
		{
			kicker = find(kicker, classname, "player");
			if (kicker != world)
			{
				sprint(self,"Kick ");
				sprint(self,kicker.netname);
				sprint(self,"?\n");
			}
			else
			{
				sprint(self,"End of player list\n");
				self.kick = 0;
			}                 
		}

// Server Admin stuff ends



	if (self.impulse == 210)
	{            
		if (self.observer != 1)
		{
			self.observer = 1;
			stuffcmd(self,"fov 120\n");
			centerprint (self,"\nMouse Mode enabled\n");
			bprint(self.netname);
			bprint(" is now a mouse\n");
			MakeMouse ();
		}
		else 
		{
			self.observer = 0;
			stuffcmd(self,"fov 90\n");
			self.movetype = MOVETYPE_FLY;
			respawn ();
		}
	}

	if ((self.impulse == 211) && (self.observer == 1))
	{
		if (self.movetype == MOVETYPE_FLY)
			{
			self.movetype = MOVETYPE_WALK;
			centerprint (self,"\nMouse Mode enabled\n");
			}
		else
			{
			self.movetype = MOVETYPE_FLY;
			centerprint (self,"\nMoth Mode enabled\n");
			}
	}

// Engage noclipping mode for Serverop stuff
	if ((self.impulse == 111) && (self.sysop == 3))
	{
		if (self.movetype == MOVETYPE_NOCLIP)
			self.movetype = MOVETYPE_WALK;
		else
			self.movetype = MOVETYPE_NOCLIP;
	}
// Engage normal walking mode for Serverop stuff
	if ((self.impulse == 110) && (self.sysop == 3))
	{
		self.movetype = MOVETYPE_WALK;
	}
// Toggle fly mode for Serverop stuff
	if ((self.impulse == 112) && (self.sysop == 3))
	{
		if (self.movetype == MOVETYPE_FLY)
			self.movetype = MOVETYPE_WALK;
		else
			self.movetype = MOVETYPE_FLY;
	}

	if ((self.impulse == 199) && (self.sysop == 3))
	{
		if (self.admin == 3)
			{
			self.sysop = 5;
			bprint (self.netname);
			bprint (" is no longer an Admin\n");
			dprint ("***MODE -- ");
			dprint (self.netname);
			dprint ("  deops himself\n");
			self.impulse = 0;
			}
		else
			{  
			self.sysop = 4;
			bprint (self.netname);
			bprint (" is no longer a ServerOp\n");
			dprint ("***MODE -- ");
			dprint (self.netname);
			dprint ("  deops himself\n");
			self.impulse = 0;
			}
	}

	if ((self.impulse == 199) && (self.sysop == 4))
	{
		self.sysop = 3;
		sprint(self,"\nSysop privileges enabled\n");
		bprint(self.netname);
		bprint(" is now a Sysop\n");
		dprint("***OPER -- ");
		dprint(self.netname);
		dprint(" is now a Sysop\n");
	}

	if ((self.impulse == 199) && (self.sysop == 5))
	{
		self.admin = 3; 
		self.sysop = 3;
		sprint(self,"\nAdmin privileges enabled\n");
		bprint(self.netname);
		bprint(" is now an Admin\n");
		dprint("***OPER -- ");
		dprint(self.netname);
		dprint(" is now an Admin\n");
	}

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


	if ((self.impulse == 200) || (self.impulse == 201))
	{
		if (self.impulse == 200)
		{
		self.skin = self.skin + 1;
		if (self.skin == 32) self.skin = 0;
		} else
		if (self.impulse == 201)
		{
		self.skin = self.skin - 1;
		if (self.skin == -1) self.skin = 30;
		}
		if (self.skin == 0) centerprint(self, "SKIN: Quake himself (1)"); else
		if (self.skin == 1) centerprint(self, "SKIN: Duke Nukem 3d (2)"); else
		if (self.skin == 2) centerprint(self, "SKIN: Mr. Toad (3)"); else
		if (self.skin == 3) centerprint(self, "SKIN: the Stormtrooper (4)"); else
		if (self.skin == 4) centerprint(self, "SKIN: Maxx (5)"); else
		if (self.skin == 5) centerprint(self, "SKIN: the Terminator (6)"); else
		if (self.skin == 6) centerprint(self, "SKIN: Judge Dredd (7)"); else
		if (self.skin == 7) centerprint(self, "SKIN: Camouflaged soldier (8)"); else
		if (self.skin == 8) centerprint(self, "SKIN: Captain Picard (9)"); else
		if (self.skin == 9) centerprint(self, "SKIN: the Wizzard (10)"); else
		if (self.skin == 10) centerprint(self,"SKIN: the Predator (11)"); else
		if (self.skin == 11) centerprint(self,"SKIN: Skeleton (12)"); else
		if (self.skin == 12) centerprint(self,"SKIN: Wan-Fu (13)"); else
		if (self.skin == 13) centerprint(self,"SKIN: Henry Rollins (14)"); else
		if (self.skin == 14) centerprint(self,"SKIN: He-Man (15)"); else
		if (self.skin == 15) centerprint(self,"SKIN: Boba Fett(16)"); else
		if (self.skin == 16) centerprint(self,"SKIN: Superman (17)"); else
		if (self.skin == 17) centerprint(self,"SKIN: NYPD Cop (18)"); else
		if (self.skin == 18) centerprint(self,"SKIN: Knight (19)"); else
		if (self.skin == 19) centerprint(self,"SKIN: Mr. Happy(20)"); else
		if (self.skin == 20) centerprint(self,"SKIN: Homer Simpson(21)"); else
		if (self.skin == 21) centerprint(self,"SKIN: Super Mario(22)"); else
		if (self.skin == 22) centerprint(self,"SKIN: clan 311 outfit(23)"); else
		if (self.skin == 23) centerprint(self,"SKIN: Ninjobo (24)"); else
		if (self.skin == 24) centerprint(self,"SKIN: Deadpool (25)"); else
		if (self.skin == 25) centerprint(self,"SKIN: Jason (26)"); else
		if (self.skin == 26) centerprint(self,"SKIN: Venom (27)"); else
		if (self.skin == 27) centerprint(self,"SKIN: Sub-Zero (28)"); else
		if (self.skin == 28) centerprint(self,"SKIN: Punisher (29)"); else
		if (self.skin == 29) centerprint(self,"SKIN: HexMarine (30)"); else
		if (self.skin == 30) centerprint(self,"SKIN: Grue (31)"); else
		if (self.skin == 31) centerprint(self,"SKIN: Kramer (32)");
	}

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

	if (self.impulse == 50)
		Help ();
	if (self.impulse == 255)
		QuadCheat ();
	if (self.impulse == 142)
		Setnoammo ();   
	self.impulse = 0;

};

/*
============
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);
		}
	}
	
	if (self.admin_god == 1)
	{
		if (self.super_sound < time)
		{
			self.super_sound = time + 1;
			sound (self, CHAN_BODY, "items/damage3.wav", 1, ATTN_NORM);
		}
	}
	return;
};


