float IM_HOMER = 74;
float WP_HOMER = 4;

void() W_FireHomer;
void() HomerThink;
void() HomerTouch;
void() HomerExplode;
void() T_MissileTouch;

void() W_FireHomer =
{
	local entity missile;
	
	missile=spawn();
	missile.owner=self;
	missile.movetype=MOVETYPE_FLYMISSILE;
	missile.solid=SOLID_BBOX;
	makevectors(self.v_angle);
	missile.velocity=aim(self,500);
	missile.velocity=missile.velocity*500;
	missile.angles=vectoangles(missile.velocity);
	self.punchangle_x= -2;
	self.ammo_rockets=self.ammo_rockets - 5;
	self.currentammo=floor(self.ammo_rockets/5);
	sound(self,CHAN_WEAPON,"weapons/sgun1.wav",1,ATTN_NORM);
	missile.touch=HomerTouch;
	missile.nextthink=time+0.5;
	missile.think=HomerThink;
	missile.targrange=1000;
	missile.blasttimer=time+10;
	missile.takedamage=DAMAGE_AIM;
	missile.health=1;
	setmodel(missile,"progs/missile.mdl");
	setsize(missile,'0 0 0','0 0 0');
	setorigin(missile,self.origin+v_forward*8+'0 0 16');
};

void() HomerThink =
{
	local entity head,curr,next;
	local vector targspot;
	local float tmp;
	if (!self.enemy)	// FindEnemy
	{	
		head=findradius(self.origin, 1000);
		curr=head;
		next=curr.chain;
		tmp=0;
		while (tmp==0)	// find 1st visible && infront target
		{
			if (curr==self)
			{
				curr=curr.chain;
				remove(head);
				head=curr;
			}
			if (!visible(curr))
			{
				curr=curr.chain;
				remove(head);
				head=curr;
			}
			else if (!infront(curr)) //visible
			{
				curr=curr.chain;
				remove(head);
				head=curr;
			}
			else
				tmp = 1;
		}
		next=curr.chain;
		targspot=curr.origin+curr.view_ofs;
		tmp=vlen(self.origin-targspot); // check 1st one
		if (tmp<self.targrange)
		{
			self.targrange=tmp;
			self.enemy=curr;
		}
		if (!head)
		{
			self.enemy=world;
			next=head;
		}
		while (next)
		{
			if (!visible(next))	// not visible
			{
				if (next.chain)
				{
					curr.chain=next.chain;
					remove(next);
					next=curr.chain;
				}
				else
					next=next.chain;
				
			}
			else if (next==self)
			{
				if (next.chain)
				{
					curr.chain=next.chain;
					remove(next);
					next=curr.chain;
				}
				else
					next=next.chain;
			}
			else if (next==self.owner)
			{
				if (next.chain)
				{
					curr.chain=next.chain;
					remove(next);
					next=curr.chain;
				}
				else
					next=next.chain;
			}
			else if (!infront(next))	// not in front of rocket
			{
				if (next.chain)
				{
					curr.chain=next.chain;
					remove(next);	
					next=curr.chain;
				}
				else
					next=next.chain;
			}
			else if (!next.takedamage)	// cant be hurt
			{
				if (next.chain)
				{
					curr.chain=next.chain;
					remove(next);
					next=curr.chain;
				}
				else
					next=next.chain;
			}
			else if (next.health<1)	//	dead
			{
				if (next.chain)
				{
					curr.chain=next.chain;
					remove(next);
					next=curr.chain;
				}
				else
					next=next.chain;
			}
			else
			{
				targspot=next.origin+next.view_ofs;
				tmp=vlen(self.origin-targspot);
				if (tmp<self.targrange)
				{
					self.targrange=tmp;
					self.enemy=next;
					curr=next;
					next=curr.chain;
				}
			}
		} // ok, self.enemy is closest visible entity infront of rocket that can
			// be hurt and is still alive
	}
	self.ideal_yaw=vectoyaw(self.origin-self.enemy.origin);
	self.yaw_speed=20;
	ChangeYaw();
	makevectors(self.angles);
	self.velocity=v_forward*500;
	sprint(self.owner,"Missile Found target: ");
	sprint(self.owner,self.enemy.netname);
	if (self.enemy.classname=="player")
	{	
		sprint(self.enemy,"Warning, You are the current target of ");
		sprint(self.enemy,self.owner.netname);
		sprint(self.enemy,"'s Missile.\nHave a nice day\n");
	}
	if (self.targrange<1000)
		self.pingtime=time+0.6;
	if (self.targrange<500)
		self.pingtime=time+0.3;
	if (self.targrange<250)
		self.pingtime=time+0.2;
	if (self.targrange<150)
		self.pingtime=time+0.1;
	if (time<=self.pingtime)
		sound(self,CHAN_WEAPON,"weapons/bounce.wav",1,ATTN_NORM);
	if (time<=self.blasttimer)
		HomerExplode();
	self.nextthink=time+0.1;
	self.think=HomerThink;
};

void() HomerTouch =
{
	if (other==self.owner)
		return;
	if (pointcontents(self.origin) == CONTENT_SKY)
	{
		remove(self);
		return;
	}
	HomerExplode();
};

void() HomerDie =
{
	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() HomerExplode =
{
	T_RadiusDamage (self, self.owner, 60, 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 ();
};
/*
================
HomeFindTarget by Vhold
returns the closest entity to itself that is killable, not a team member on 
self's team, ect ect....
================
*/
entity() HomeFindTarget =
{
        local entity head, selected;
        local float dist;
        dist = 100000;
        selected = world;
        head = findradius(self.origin, 100000);
        while(head)
        {
          if( (head.health > 1) && (head != self) && (head != self.owner) && !( (teamplay == 1) && (head.team > 0)&&(head.team == self.owner.team) ) && (head.classname != "door") && (head.classname != "misc_explobox") && !(head.items & IT_INVISIBILITY) )
	         {

                        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)   // All of this is stuff you can comment out
        {
                sprint (self.owner,"Homing->");
                if (selected.classname == "player")
                {
                        sprint (self.owner,selected.netname);
                        sprint (selected,"Warning: You have been targeted by ");
                        sprint (selected,self.owner.netname);
                        sprint (selected,"'s missile!\n");
                }
                else
                        sprint (self.owner,selected.classname);
                sprint (self.owner,"\n");
								sound(self.owner,CHAN_BODY,"weapons/bounce.wav",1,ATTN_NONE);
								sound(selected,CHAN_BODY,"weapons/bounce.wav",1,ATTN_NONE);
        }


        return selected;
};
/* 
===============
HomeThink by Vhold
The Think function for the Homing Missile
===============
*/
void() HomeThink =
{
        local vector needdir, currdir;
	local float needspeed, maxspeed, acceleration;
	local vector temp;

	traceline(self.origin,self.enemy.origin,TRUE,self);

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

        if (self.enemy != world) // Arr.. don't be taken on da World!
        {
		temp = normalize(self.velocity) * 100;
		traceline(self.origin,self.origin+temp,TRUE,self);
		if(trace_fraction < 1)
		{
			maxspeed = 200;
			acceleration = 300;
		}
		else
		{
			maxspeed = 400;
			acceleration = 150;
		}
                needdir = normalize((self.enemy.origin + '0 0 10') - self.origin);
                currdir = normalize(self.velocity);
                self.angles = vectoangles(needdir);

                needspeed = vlen(needdir - currdir) * acceleration;

                self.movedir = needdir * needspeed;
                self.velocity = self.velocity + self.movedir;

                if ( vlen(self.velocity) > maxspeed )
                        self.velocity = normalize(self.velocity) * maxspeed;
		self.nextthink = time + 0.1;
		self.targrange = vlen(self.origin-self.enemy.origin);
		if (self.targrange < 100000)
			self.pingtime=time+0.5;
		if (self.targrange < 25000)
			self.pingtime=time+0.4;
		if (self.targrange < 5000)
			self.pingtime=time+0.3;
		if (self.targrange < 2500)
			self.pingtime=time+0.2;
		if (self.targrange < 1000)
			self.pingtime=time+0.1;
  }
	else
	{
	        self.nextthink = time + 0.5;
   				self.pingtime=time+100;
  }     
	self.think=HomeThink;
	if (self.pingtime<time)
		sound(self.enemy,CHAN_BODY,"weapons/bounce.wav",1,ATTN_NONE);
		sound(self.owner,CHAN_BODY,"weapons/bounce.wav",1,ATTN_NONE);		
//	if (self.blasttimer<=time)
//		GrenadeExplode();
};

/*
==============
FireHomingMissile
Fires a Vhold brand homing missile
==============
*/
void() FireHomingMissile =
{
	local	entity missile, mpuff;
		
	self.ammo_rockets = self.ammo_rockets - 5;
	self.currentammo = floor(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;
	missile.classname = "arocket";
	missile.health = 1;
		
// set missile speed	

	makevectors (self.v_angle);
	missile.velocity = aim(self, 1000);
	missile.velocity = missile.velocity * 400;
	missile.angles = vectoangles(missile.velocity);
	missile.takedamage=DAMAGE_AIM;
	missile.health=1;
	missile.touch = HomerTouch;
	missile.th_die=HomerDie;
	
// set missile duration
	missile.nextthink = time + 0.5;
	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');
};