
//*******************************************************************
// module: 	spikes.qc 
// author: 	Charlie Zimmerman
// email: 	czimmerm@cyberenet.net
// description: Throws a number of random peices of
//		metal in random directions.
//*******************************************************************

//************
// EXTERNALS
//************
float() crandom;
void (entity targ, entity inflictor, entity attacker, float damage) T_Damage;
void (vector org) billow;

//*************
// PROTOTYPES
//*************
void() shrat_touch;
void() dspike_touch;

//*******************************************************************
//* throw_a_shrat - throws one peice of metal out
//*******************************************************************
void(vector org,entity own) throw_a_shrat =
{
	// spawn a spike owned by the passed in owner
	newmis = spawn ();
	newmis.classname = "spike";
	newmis.owner = own;

	// make it solid and make it bounce
	newmis.movetype = MOVETYPE_BOUNCE;
	newmis.solid = SOLID_BBOX;

	// starting angle 
	newmis.angles = '0 0 0';
	
	// function to call when it hits something
	newmis.touch = shrat_touch;

	// next time to wake up on own and do something.
	// May wake on own due to touch prior to this.
	if (random() > 0.9) {
		newmis.nextthink = time + random()*90;
	}
	else {
		newmis.nextthink = time + random()*9;
	}
	// what to do on own wake up
	newmis.think = SUB_Remove;

	// set size, origin, and model
	setmodel (newmis, "progs/spike.mdl");
	setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);		
	setorigin (newmis, org);

	// Start it spinning with random angular velocity
 	newmis.avelocity =v_forward*crandom()*600 +
			  v_right*crandom()*600 +
			  v_up*crandom()*600; 

	// Give it random velocity 
	newmis.velocity = v_forward*crandom()*1000 +
			  v_right*crandom()*1000 +
			  v_up*crandom()*1000; 
};

//*******************************************************************
//* throw_shrat - throws number peices of metal out
//*******************************************************************
void(vector org,entity own,float number) throw_shrat =
{
	local float i;

	i = 0;
	while (i < number) {
		throw_a_shrat(org,own);
		i = i + 1;
	}

};

//*********************************************************************
//* shrat_touch - called when metal hits something
//*********************************************************************
void() shrat_touch =
{
	local float dam;

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

	// vanish if in sky
	if (pointcontents(self.origin) == CONTENT_SKY)
	{
		remove(self);
		return;
	}
	
	// hit something that bleeds
	if (other.takedamage)
	{
		// random damage
		dam = random()*25;
		spawn_touchblood (dam);
		T_Damage (other, self, self.owner, dam);
		remove(self);
	}
	else
	{
		// hit nothing - anounce for richochet
		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);
	}
};

//*******************************************************************
//* throw_spike - throws spike in general direction passed in
//*******************************************************************
void(vector org,entity own,vector dir) throw_spike =
{

	// throw a spike owned by the owner passed in
	newmis = spawn ();
	newmis.classname = "spike";
	newmis.owner = own;

	// make it solid and make it bounce
	newmis.movetype = MOVETYPE_BOUNCE;
	newmis.solid = SOLID_BBOX;

	// starting angles
	newmis.angles = '0 0 0';
	
	// function to call when it hits something
	newmis.touch = dspike_touch;

	// next time to wake up on own and do something.
	// May wake on own due to touch prior to this.
	if (random() > 0.9) {
		newmis.nextthink = time + random()*90;
	}
	else {
		newmis.nextthink = time + random()*9;
	}
	// what to do on own wake up
	newmis.think = SUB_Remove;

	// set size, origin, and model
	setmodel (newmis, "progs/spike.mdl");
	setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);		
	setorigin (newmis, org);

	// Start it spinning with random angular velocity
 	newmis.avelocity =v_forward*crandom()*600 +
			  v_right*crandom()*600 +
			  v_up*crandom()*600; 

	// Give it random velocity sorta in direction passed in
	// This syntax kills me :)
	newmis.velocity = dir*0.75 + 
			v_forward*crandom()*200 +
			v_right*crandom()*200 +
			v_up*crandom()*200;
};

//*******************************************************************
//* fall_spike - drops a spike 
//*******************************************************************
void() fall_spike =
{
	// change a stopped spike to a falling one
	self.movetype = MOVETYPE_BOUNCE;
	newmis.solid = SOLID_BBOX;
	newmis.touch = dspike_touch;

	// plan remove at next wake up
	self.think = SUB_Remove;
	self.nextthink = time + 2;

	// make it flip when falling
	self.avelocity =v_forward*crandom()*600 +
		  v_right*crandom()*600 +
		  v_up*crandom()*600; 
};

//*******************************************************************
//* stick_spike - sticks a spike where it stops 
//*******************************************************************
void(vector org,vector dir) stick_spike =
{
	local vector facing,neworg;

	// spawn a spike owned by the world
	newmis = spawn ();
	newmis.classname = "spike";
	newmis.owner = world;

	// make it not solid and stop it
	newmis.movetype = MOVETYPE_NONE;
	newmis.solid = SOLID_NOT;

	// set angle of rest based on direction it came in from
	newmis.angles = vectoangles(dir);

	// back out spike a little to show more of it
	facing = (-8)*normalize(dir);
	neworg = org + facing;
	
	// next time to wake up on own and do something.
	if (random() > 0.9) {
		newmis.nextthink = time + random()*60;
	}
	else {
		newmis.nextthink = time + random()*9;
	}
	// make spike fall at wake up time
	newmis.think = fall_spike;

	setmodel (newmis, "progs/spike.mdl");
	setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);		
	setorigin (newmis, neworg);

	// no velocities
	newmis.avelocity = '0 0 0';
	newmis.velocity = '0 0 0';
};

//*********************************************************************
//* dspike_touch - deflected spike touches
//*********************************************************************
void() dspike_touch =
{
local float rand;

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

	// vanish if it hits sky
	if (pointcontents(self.origin) == CONTENT_SKY)
	{
		remove(self);
		return;
	}
	
	// hit something that bleeds
	if (other.takedamage)
	{
		spawn_touchblood (4);
		T_Damage (other, self, self.owner, 4);
		remove(self);
	}
	else
	{
		// Hello!  I'm here!
		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);
	}
};



