//------------------------------------------------------------------------------------
// Bomb
//------------------------------------------------------------------------------------

void(vector org, entity inflictor, string dmsg, float barrel) ThrowScrap;
void() BombExplode =
{
	self.solid = SOLID_NOT;
	if(self.ninja)	//is an explodebox!
	{
		if(self.count)
			SpawnExplosion(self.origin, self.owner, self.count, "bigbarrel", 0);
		else
			SpawnExplosion(self.origin, self.owner, BIGBARREL_SCRAPS, "bigbarrel", 0);
	}
	else
		SpawnExplosion(self.origin, self.enemy, BOMB_SCRAPS, "bomb", 1);
	if((self.flags & FL_ITEM) && !self.ninja)
	{
		self.model = string_null;
		self.solid = SOLID_NOT;
		self.nextthink = time + 30;
		self.think = SUB_regen;
	}
	else
		remove(self);
};

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

	if((self.velocity == '0 0 0') && (other.classname == "player"))
	{
		makevectors(other.v_angle);
		self.velocity = other.velocity + '0 0 200' + v_forward * 800 * (vlen(other.velocity) / 320);
		self.flags = self.flags - (self.flags & FL_ONGROUND);
	}
	else
	{
		if ((((other.takedamage == DAMAGE_AIM) && (other.solid != SOLID_NOT)) || (other.classname == "barrow")) && (self.randomf < time))
		{
			self.solid = SOLID_NOT;
			SpawnExplosion(other.origin, self.enemy, BOMB_SCRAPS, "bomb", 1);
			if(other.classname == "barrow")
				remove(other);
			remove(self);
			return;
		}
		else if (!other.takedamage)
		{
			self.velocity = '0 0 0';
		}
	}
};

void() W_ThrowBomb =
{
	local	entity missile;

	if(!self.items & IT_SUPER_NAILGUN)
		return;
	else
	{
		self.items = self.items - (self.items & IT_SUPER_NAILGUN);
		self.weapon = W_BestWeapon();
		W_SetCurrentAmmo();
	}
	
	sound(self, CHAN_ITEM, "weapons/whoosh.wav", 1, ATTN_NORM);
	self.punchangle_x = -2;

	missile = spawn ();
	missile.enemy = self;
	missile.movetype = MOVETYPE_BOUNCE;
	missile.solid = SOLID_TRIGGER;
	missile.classname = "bomb";
	missile.count = 1;
	missile.randomf = time + 0.4;
		
// set missile speed	

	makevectors (self.v_angle);

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

	missile.touch = BombTouch;
	
// set missile duration
	missile.nextthink = time + BOMB_EXPLODETIME;
	missile.think = BombExplode;

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

void(entity center, float radius) Shake =
{
local entity head, selected;

	selected = world;
	head = findradius(center.origin, radius);
	while (head)
	{
		if (head.health > 0)
		{
			selected = head;
			if (selected != world)
			{
				selected.punchangle_x = mrand() * 5;
				if(center.jumpheight < time)
				{
					sound (selected, CHAN_AUTO, "misc/exp_big.wav", 0.3, ATTN_NORM);
					center.jumpheight = time + 4;
				}
			}
		}
		head = head.chain;
	}
};

void() ExplosionThink =
{
	if ((self.frame > 17) && (!self.count))
		self.count = TRUE;
	if((self.frame < 1) && (self.count))
	{
		remove(self);
		return;
	}

	if(self.jumptime < time)
	{
		Shake(self, 10000);
		self.jumptime = time + 0.2;
	}
	if(!self.ninja)
		T_RadiusDamage(self, self.owner, BOMB_DAMAGE_FRAMEMULTIPLIER * self.frame, world, self.deathtype, "");
	else
		T_RadiusDamage(self, self.owner, BIGBARREL_DAMAGE_FRAMEMULTIPLIER * self.frame, world, self.deathtype, "");
	if(!self.count)
		self.frame = self.frame + 1;
	else
		self.frame = self.frame - 2;
	if((self.nflytime < time) && (self.randomf > 0))
	{
		if(!self.ninja)
		{
			self.nflytime = time + (26*0.04)/BOMB_SCRAPS;
			ThrowScrap(self.origin, self.owner, "bombscrap", 1);
		}
		else if(self.ninja)
		{
			self.nflytime = time + (26*0.04)/BIGBARREL_SCRAPS;
			ThrowScrap(self.origin, self.owner, "bigbarrelscrap", 0);
		}
		self.randomf = self.randomf - 1;
	}
	self.nextthink = time + 0.04;
};

void() SmallExplosionThink =
{
	if ((self.frame > 6) && (!self.count))
		self.count = TRUE;
	if((self.frame < 1) && (self.count))
	{
		remove(self);
		return;
	}

	if(self.jumptime < time)
	{
		Shake(self, 1000);
		self.jumptime = time + 0.2;
	}
	if(!self.count)
		T_RadiusDamage(self, self.owner, BOMB_SCRAPDAMAGE_FRAMEMULTIPLIER * self.frame, world, self.deathtype, "");
	else
		T_RadiusDamage(self, self.owner, BIGBARREL_SCRAPDAMAGE_FRAMEMULTIPLIER * self.frame, world, self.deathtype, "");
	if(!self.count)
		self.frame = self.frame + 1;
	else
		self.frame = self.frame - 2;
	self.nextthink = time + 0.1;
};

void() ScrapTouch =
{
	self.velocity = '0 0 0';
	self.classname = "smallexplosion";
	if((pointcontents(self.origin) == CONTENT_WATER) || (pointcontents(self.origin) == CONTENT_SLIME))
	{
		self.think = SUB_DeathBubbles;
		self.nextthink = time;
		return;
	}
	self.movetype = MOVETYPE_NOCLIP;
	self.solid = SOLID_NOT;
	setmodel(self, "progs/sphere.mdl");
	self.flags = self.flags - (self.flags & FL_ONGROUND);
	self.avelocity_x = mrand() * 400;
	self.avelocity_y = mrand() * 400;
	self.avelocity_z = mrand() * 400;
	self.nextthink = time + 0.04;
	self.think = SmallExplosionThink;

	sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
	if(!self.count)	//is a barrel, not an exploding box
	{
		T_RadiusDamage(self, self.owner, BOMB_SCRAPRADIUS, world, self.deathtype, "");
		RadiusBurn(self.origin, BOMB_SCRAPFIRERADIUS, self.owner);
	}
	else
	{
		T_RadiusDamage(self, self.owner, BIGBARREL_SCRAPRADIUS, world, self.deathtype, "");
		RadiusBurn(self.origin, BIGBARREL_SCRAPFIRERADIUS, self.owner);
	}
};

void() ScrapThink =
{
	self.frame = self.frame + 1;
	if(self.frame > 16)
		self.frame = 6;
	self.angles = vectoangles(self.velocity);
	self.nextthink = time + 0.1;
};

void(vector org, entity inflictor, string dmsg, float barrel) ThrowScrap =
{
	local entity head, e, s;
	local vector t;
	local float f;

	head = world;
	if(barrel)
		e = findradius(org, BOMB_SCRAPAIMRADIUS);
	else
		e = findradius(org, BIGBARREL_SCRAPAIMRADIUS);
	while(e)
	{
		if(((e.classname == "player") || (e.flags & FL_MONSTER)) && (e.bombtargettime < time))
			head = e;
		e = e.chain;
	}
	s = spawn();
	s.owner = inflictor;
	s.origin = org + '0 0 32';
	s.solid = SOLID_BBOX;
	s.movetype = MOVETYPE_BOUNCE;
	s.flags = 0;
	t = '0 0 0';
	if(barrel)
		t_z = BOMB_SCRAPSPEED * 5;
	else
		t_z = BIGBARREL_SCRAPSPEED * 5;
	traceline(s.origin, s.origin + t, TRUE, world);
	if(barrel)
	{
		if(random() > BOMB_SCRAPAIMCHANCE)
			head = world;
	}
	else
	{
		if(random() > BIGBARREL_SCRAPAIMCHANCE)
			head = world;
		s.count = 1;
	}
	if(head != world)
	{
		head.bombtargettime = time + 5;
		f = vlen(head.origin - org);
		s.velocity = normalize(head.origin - org) * (f * 2);
		if(barrel)
			f = BOMB_SCRAPSPEED * 5 * trace_fraction;
		else
			f = BIGBARREL_SCRAPSPEED * 5 * trace_fraction;
		s.velocity_z = random() * f;
	}
	else
	{
		if(barrel)
		{
			s.velocity_x = mrand() * BOMB_SCRAPSPEED;
			s.velocity_y = mrand() * BOMB_SCRAPSPEED;
			f = BOMB_SCRAPSPEED * 5 * trace_fraction;
		}
		else
		{
			s.velocity_x = mrand() * BIGBARREL_SCRAPSPEED;
			s.velocity_y = mrand() * BIGBARREL_SCRAPSPEED;
			f = BIGBARREL_SCRAPSPEED * 5 * trace_fraction;
		}
		s.velocity_z = random() * f;
	}
	s.touch = ScrapTouch;
	s.think = ScrapThink;
	s.nextthink = time + 0.1;
	setmodel (s, "progs/scrap.mdl");
	setsize(s, '0 0 0', '0 0 0');
	s.frame = 6;
	s.deathtype = dmsg;
};

void() SUB_DeathBubbles;
void(vector eorigin, entity inflictor, float scraps, string dmsg, float barrel) SpawnExplosion =
{
local entity exp;

	exp = spawn();
	setorigin(exp, eorigin);
	exp.classname = "bigexplosion";
	if((pointcontents(eorigin) == CONTENT_WATER) || (pointcontents(eorigin) == CONTENT_SLIME))
	{
		if(barrel)
			setmodel(exp, "progs/fass.mdl");
		exp.think = SUB_DeathBubbles;
		exp.nextthink = time;
		return;
	}
	exp.movetype = MOVETYPE_NOCLIP;
	exp.solid = SOLID_NOT;
	exp.owner = inflictor;
	setmodel(exp, "progs/sphere.mdl");
	if (exp.flags & FL_ONGROUND)
		exp.flags = exp.flags - FL_ONGROUND;
	exp.avelocity_x = mrand() * 400;
	exp.avelocity_y = mrand() * 400;
	exp.avelocity_z = mrand() * 400;
	exp.nextthink = time + 0.04;
	exp.think = ExplosionThink;
	exp.count = FALSE;
	exp.owner = inflictor;
	exp.randomf = scraps;
	exp.deathtype = dmsg;

	WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
	WriteByte (MSG_BROADCAST, TE_EXPLOSION);
        WriteCoord (MSG_BROADCAST, eorigin_x);
        WriteCoord (MSG_BROADCAST, eorigin_y);
        WriteCoord (MSG_BROADCAST, eorigin_z);
	sound (exp, CHAN_WEAPON, "misc/exp_big.wav", 1, ATTN_NORM);
	if(barrel)
	{
		T_RadiusDamage(exp, inflictor, BOMB_RADIUS, world, dmsg, "");
		RadiusBurn(self.origin, BOMB_FIRERADIUS, inflictor);
	}
	else
	{
		T_RadiusDamage(exp, inflictor, BIGBARREL_RADIUS, world, dmsg, "");
		RadiusBurn(self.origin, BIGBARREL_FIRERADIUS, inflictor);
		exp.ninja = 1;	//mark that it is a exploding box
	}
};

