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

VOMITUS 

================================================================================

This is an undead janitor / medic / tank class that:

Eats corpses to create zombies and make bouncing gib ammo for itself
Can sometimes (skill depedant) swallow incoming grenades, spitting them back 
at first opportunity.
Will temporarily die like a zombie if severely injured.
Can be flagged as sleeping.

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

$cd id1/models/vomitus
$origin 0 0 24
$base base
$skin skin

/*Frame Groups
1-8		Stand
9-24	Walk
25-29	Paina
30-34	Painb  --------WTF lost frames
49-51	Attack
52-66	Death (deflate)
67-75	Devour (Melee)
76-81	Munch
*/

$frame stand1 stand2 stand3 stand4 stand5 stand6 stand7 stand8 stand9

$frame walk1 walk2 walk3 walk4 walk5 walk6 walk7 walk8 walk9 walk10
$frame walk11 walk12 walk13 walk14 walk15 walk16

$frame paina1 paina2 paina3 paina4

$frame painb1 painb2 painb3 painb4

$frame attack1 attack2 attack3 attack4 attack5 attack6
$frame attack7 attack8 attack9 attack10 attack11 attack12 attack13

$frame painc1 painc2 painc3

$frame death1 death2 death3 death4 death5 death6 death7 death8
$frame death9 death10 death11 death12 death13 death14 death15 death16  death17

$frame devour1 devour2 devour3 devour4 devour5 devour6 devour7 devour8
$frame devour9

$frame munch1 munch2 munch3 munch4 munch5 munch6

/*============================================================================
	Prototypes
============================================================================*/

void()	Vomitus_Puke;
void()	Vomitus_Puke_Sound;
void()	Vomitus_Devour;
void()	VomitusChew;
float()	WhatsForLunch;

/*============================================================================
	Animations
============================================================================*/

//ijed Sleeping vomitus
void()	vomitus_deflated1	=[	$death15,	vomitus_deflated2	] { 
self.solid = SOLID_NOT; 
self.sleeping = TRUE;
};
void()	vomitus_deflated2	=[	$death15,	vomitus_deflated1	] {};

//ijed Deflating Vomitus - going to sleeping / dead pose
void()	vomitus_deflate1	=[	$death1,	vomitus_deflate2	] {self.solid = SOLID_NOT; Gyro_Object_ClearPhysics(self);};
void()	vomitus_deflate2	=[	$death2,	vomitus_deflate3	] {};
void()	vomitus_deflate3	=[	$death3,	vomitus_deflate4	] {};
void()	vomitus_deflate4	=[	$death4,	vomitus_deflate5	] {};
void()	vomitus_deflate5	=[	$death5,	vomitus_deflate6	] {};
void()	vomitus_deflate6	=[	$death6,	vomitus_deflate7	] {};
void()	vomitus_deflate7	=[	$death7,	vomitus_deflate8	] {};
void()	vomitus_deflate8	=[	$death8,	vomitus_deflate9	] {};
void()	vomitus_deflate9	=[	$death9,	vomitus_deflate10	] {};
void()	vomitus_deflate10	=[	$death10,	vomitus_deflate11	] {};
void()	vomitus_deflate11	=[	$death11,	vomitus_deflate12	] {};
void()	vomitus_deflate12	=[	$death12,	vomitus_deflate13	] {};
void()	vomitus_deflate13	=[	$death13,	vomitus_deflate14	] {};
void()	vomitus_deflate14	=[	$death14,	vomitus_inflate1	] {};

void()	vomitus_stand1	=[	$stand1,	vomitus_stand2	] {ai_stand();};
void()	vomitus_stand2	=[	$stand2,	vomitus_stand3	] {ai_stand();};
void()	vomitus_stand3	=[	$stand3,	vomitus_stand4	] {ai_stand();};
void()	vomitus_stand4	=[	$stand4,	vomitus_stand5	] {ai_stand();};
void()	vomitus_stand5	=[	$stand5,	vomitus_stand6	] {ai_stand();};
void()	vomitus_stand6	=[	$stand6,	vomitus_stand7	] {ai_stand();};
void()	vomitus_stand7	=[	$stand7,	vomitus_stand8	] {ai_stand();};
void()	vomitus_stand8	=[	$stand8,	vomitus_stand9	] {ai_stand();};
void()	vomitus_stand9	=[	$stand9,	vomitus_stand1	]
{
	if (WhatsForLunch())	//There's something to eat, go get it
		return;
		
	ai_stand();
};

void()	vomitus_walk1	=[	$walk1 ,	vomitus_walk2	] {
if (random() < 0.2)
	sound (self, CHAN_VOICE, "vomitus/idle1.wav", 1, ATTN_IDLE); 
ai_walk(2);};
void()	vomitus_walk2	=[	$walk2 ,	vomitus_walk3	] {ai_walk(4);};
void()	vomitus_walk3	=[	$walk3 ,	vomitus_walk4	] {ai_walk(4);};
void()	vomitus_walk4	=[	$walk4 ,	vomitus_walk5	] {ai_walk(3);};
void()	vomitus_walk5	=[	$walk5 ,	vomitus_walk6	] {ai_walk(1);};
void()	vomitus_walk6	=[	$walk6 ,	vomitus_walk7	] {ai_walk(2);};
void()	vomitus_walk7	=[	$walk7 ,	vomitus_walk8	] {ai_walk(2);};
void()	vomitus_walk8	=[	$walk8 ,	vomitus_walk9	] {ai_walk(1);};
void()	vomitus_walk9	=[	$walk9 ,	vomitus_walk10	] {ai_walk(2);};
void()	vomitus_walk10	=[	$walk10,	vomitus_walk11	] {ai_walk(4);};
void()	vomitus_walk11	=[	$walk11,	vomitus_walk12	] {ai_walk(4);};
void()	vomitus_walk12	=[	$walk12,	vomitus_walk13	] {ai_walk(1);};
void()	vomitus_walk13	=[	$walk13,	vomitus_walk14	] {ai_walk(2);};
void()	vomitus_walk14	=[	$walk14,	vomitus_walk15	] {ai_walk(3);};
void()	vomitus_walk15	=[	$walk15,	vomitus_walk16	] {ai_walk(4);};
void()	vomitus_walk16	=[	$walk16,	vomitus_walk1	]
{
	ai_walk(2);
	
	if (WhatsForLunch ())	//There's something to eat, go get it
		return;
};

void()	vomitus_run1	=[	$walk1 ,	vomitus_run2	] {ai_run(2);self.solid = SOLID_SLIDEBOX;};
void()	vomitus_run2	=[	$walk2 ,	vomitus_run3	] {ai_run(4);};
void()	vomitus_run3	=[	$walk3 ,	vomitus_run4	] {ai_run(4);};
void()	vomitus_run4	=[	$walk4 ,	vomitus_run5	] {ai_run(3);};
void()	vomitus_run5	=[	$walk5 ,	vomitus_run6	] {ai_run(1);};
void()	vomitus_run6	=[	$walk6 ,	vomitus_run7	] {ai_run(2);};
void()	vomitus_run7	=[	$walk7 ,	vomitus_run8	] {ai_run(2);};
void()	vomitus_run8	=[	$walk8 ,	vomitus_run9	] {ai_run(1);};
void()	vomitus_run9	=[	$walk9 ,	vomitus_run10	] {ai_run(2);};
void()	vomitus_run10	=[	$walk10,	vomitus_run11	] {ai_run(4);};
void()	vomitus_run11	=[	$walk11,	vomitus_run12	] {ai_run(4);};
void()	vomitus_run12	=[	$walk12,	vomitus_run13	] {ai_run(1);};
void()	vomitus_run13	=[	$walk13,	vomitus_run14	] {ai_run(2);};
void()	vomitus_run14	=[	$walk14,	vomitus_run15	] {ai_run(3);};
void()	vomitus_run15	=[	$walk15,	vomitus_run16	] {ai_run(4);};
void()	vomitus_run16	=[	$walk16,	vomitus_run1	]
{
	ai_run(2);
	
	if (!self.enemy.health	)	// constantly look for the closest morsel
	if (WhatsForLunch ()	)	// there's something closer to eat, go get it
		return;
};

//ijed Vomitus waking up after being wounded
void()	vomitus_inflate1	=[	$death15 ,	vomitus_inflate2	] {
self.nextthink = self.nextthink + random()*30;	//ijed Randomised inert time, longer for Vomitii
self.solid = SOLID_NOT;
self.sleeping = TRUE;
}; 
void()	vomitus_inflate2	=[	$death14 ,	vomitus_inflate3	] {
	if (self.h2olevel == 0)
		sound (self, CHAN_VOICE, "vomitus/idle1.wav", 1, ATTN_IDLE);
		
	self.solid = SOLID_SLIDEBOX;
	
	self.th_stand = vomitus_stand1;		// Supa, don't let the vomitus deflate after losing a target - have it gather gibs instead
	
	if (!walkmove (0, 0))
	{
		self.think = vomitus_inflate1;
		return;
	}
};
void()	vomitus_inflate3	=[	$death13 ,	vomitus_inflate4	] {self.solid = SOLID_SLIDEBOX; Gyro_Object_Activate (self, 80000);};  //ijed Turns its physics back on
void()	vomitus_inflate4	=[	$death12 ,	vomitus_inflate5	] {};
void()	vomitus_inflate5	=[	$death11 ,	vomitus_inflate6	] {};
void()	vomitus_inflate6	=[	$death10 ,	vomitus_inflate7	] {};
void()	vomitus_inflate7	=[	$death9 ,	vomitus_inflate8	] {};
void()	vomitus_inflate8	=[	$death8 ,	vomitus_inflate9	] {};
void()	vomitus_inflate9	=[	$death7 ,	vomitus_inflate10	] {};
void()	vomitus_inflate10	=[	$death6 ,	vomitus_inflate11	] {};
void()	vomitus_inflate11	=[	$death5 ,	vomitus_inflate12	] {};
void()	vomitus_inflate12	=[	$death4 ,	vomitus_inflate13	] {};
void()	vomitus_inflate13	=[	$death3 ,	vomitus_inflate14	] {};
void()	vomitus_inflate14	=[	$death2 ,	vomitus_inflate15	] {};
void()	vomitus_inflate15	=[	$death1 ,	vomitus_run1		] {};

//ijed Vomitus waking up from the start asleep flag
void()	vomitus_ainflate1	=[	$death15 ,	vomitus_ainflate2	]
{
	self.solid = SOLID_NOT;
	self.sleeping = FALSE;
}; 
void()	vomitus_ainflate2	=[	$death14 ,	vomitus_ainflate3	]
{
	if (self.h2olevel == 0)
		sound (self, CHAN_VOICE, "vomitus/idle1.wav", 1, ATTN_IDLE);
		
	self.solid = SOLID_SLIDEBOX;
	
	self.th_stand = vomitus_stand1;		// Supa, don't let the vomitus deflate after losing a target - have it gather gibs instead
	
	if (!walkmove (0, 0))
	{
		self.think = vomitus_inflate1;
		return;
	}
};
void()	vomitus_ainflate3	=[	$death13 ,	vomitus_ainflate4	] {self.solid = SOLID_SLIDEBOX; Gyro_Object_Activate (self, 80000);};
void()	vomitus_ainflate4	=[	$death12 ,	vomitus_ainflate5	] {};
void()	vomitus_ainflate5	=[	$death11 ,	vomitus_ainflate6	] {};
void()	vomitus_ainflate6	=[	$death10 ,	vomitus_ainflate7	] {};
void()	vomitus_ainflate7	=[	$death9 ,	vomitus_ainflate8	] {};
void()	vomitus_ainflate8	=[	$death8 ,	vomitus_ainflate9	] {};
void()	vomitus_ainflate9	=[	$death7 ,	vomitus_ainflate10	] {};
void()	vomitus_ainflate10	=[	$death6 ,	vomitus_ainflate11	] {};
void()	vomitus_ainflate11	=[	$death5 ,	vomitus_ainflate12	] {};
void()	vomitus_ainflate12	=[	$death4 ,	vomitus_ainflate13	] {};
void()	vomitus_ainflate13	=[	$death3 ,	vomitus_ainflate14	] {};
void()	vomitus_ainflate14	=[	$death2 ,	vomitus_ainflate15	] {};
void()	vomitus_ainflate15	=[	$death1 ,	vomitus_run1		] {};

void()	vomitus_attack1		=[	$attack1,	vomitus_attack2	] {ai_face(); Vomitus_Puke_Sound();};
void()	vomitus_attack2		=[	$attack2,	vomitus_attack3	] {ai_face();};
void()	vomitus_attack3		=[	$attack3,	vomitus_attack4	] {ai_face();};
void()	vomitus_attack4		=[	$attack4,	vomitus_attack5	] {ai_face();};
void()	vomitus_attack5		=[	$attack5,	vomitus_attack6	] {ai_face();};
void()	vomitus_attack6		=[	$attack6,	vomitus_attack7	] {ai_face();};
void()	vomitus_attack7		=[	$attack7,	vomitus_attack8	] {ai_face();};
void()	vomitus_attack8		=[	$attack8,	vomitus_attack9	] {ai_face();};
void()	vomitus_attack9		=[	$attack9,	vomitus_attack10	] {ai_face();};
void()	vomitus_attack10	=[	$attack10,	vomitus_attack11	] {ai_face();};
void()	vomitus_attack11	=[	$attack11,	vomitus_attack12	] {ai_face(); Vomitus_Puke();};
void()	vomitus_attack12	=[	$attack12,	vomitus_attack13	] {ai_face();};
void()	vomitus_attack13	=[	$attack13,	vomitus_run1	] {ai_face();};

void()	vomitus_devour1	=[	$devour1,	vomitus_devour2	]	{ai_charge(3);};
void()	vomitus_devour2	=[	$devour2,	vomitus_devour3	]	{ai_charge(3);};
void()	vomitus_devour3	=[	$devour3,	vomitus_devour4	]	{ai_charge(3);};
void()	vomitus_devour4	=[	$devour4,	vomitus_devour5	]	{ai_charge(3);};
void()	vomitus_devour5	=[	$devour5,	vomitus_devour6	]	{ai_charge(3); Vomitus_Devour();};
void()	vomitus_devour6	=[	$devour6,	vomitus_devour7	]	{ai_charge(3);};
void()	vomitus_devour7	=[	$devour7,	vomitus_devour8	]	{ai_charge(3);};
void()	vomitus_devour8	=[	$devour8,	vomitus_devour9	]	{ai_charge(3);};
void()	vomitus_devour9	=[	$devour9,	vomitus_run1	]	{ai_charge(3);};

/*The Vomitus is chewing on undigested meat (cells) turning it into gib ammo (shells) and zombie 
pieces (nails).  It takes 4 zombie pieces to make a zombie, which is spat out immediately. If on
less than 2/3 health while chewing then it recovers health.  */
void()	vomitus_digest1	=[	$munch1,	vomitus_digest2	]	{};
void()	vomitus_digest2	=[	$munch2,	vomitus_digest3	]	{};
void()	vomitus_digest3	=[	$munch3,	vomitus_digest4	]	{};
void()	vomitus_digest4	=[	$munch4,	vomitus_digest5	]	{};
void()	vomitus_digest5	=[	$munch5,	vomitus_digest6	]	{};
void()	vomitus_digest6	=[	$munch6,	vomitus_digest1	]	{VomitusChew();};

void() Vomitus_SpawnZombie =	// Supa, doots out a sleeping zombie which will get up as soon as the Vomitus gyres over yonder
{
	local entity	zombi,
					store;
					
	// play a gib effect + sound
	//ThrowGib ("progs/vomitus_gib.mdl", -150);	// actuuuuually never mind the gibs; not unless you want to start a chain reaction :x
	//ThrowGib ("progs/vomitus_gib.mdl", -150);
	sound (self, CHAN_VOICE, "vomitus/revive1.wav", 1, ATTN_NORM);
	
	// gb, add the new zombie to total monster count
	total_monsters = total_monsters + 1;
	
	// and tell the engine
	WriteByte (MSG_ALL, SVC_UPDATESTAT);
	WriteByte (MSG_ALL, STAT_TOTALMONSTERS);
	WriteLong (MSG_ALL, total_monsters);

	self.should_roam = TRUE;	// get off of any zombies
						
	// spawn a sleeping zombie
	zombi = spawn();

	zombi.solid		= SOLID_SLIDEBOX;
	zombi.movetype	= MOVETYPE_STEP;

	setmodel	(zombi, "progs/zombie.mdl"			);
	setsize		(zombi, '-16 -16 -24', '16 16 40'	);
	setorigin	(zombi, self.origin + '0 0 2'		);
	
	zombi.health = 61;

	zombi.classname		= "monster_zombie";	
	zombi.th_stand		= alt_zombie_stand1;
	zombi.th_walk		= zombie_walk1;
	zombi.th_run		= zombie_run1;
	zombi.th_pain		= zombie_pain;
	zombi.th_die		= zombie_die;
	zombi.th_missile	= zombie_missile;
	zombi.th_submerged	= SUB_Null;
	
	Gyro_Object_Activate (zombi, 55000);
	
	zombi.flags = zombi.flags | FL_MONSTER;
	zombi.takedamage = DAMAGE_AIM;
	
	zombi.should_roam = TRUE;	// get out of the way of any other spawned zombies

	zombi.ideal_yaw	= zombi.angles * '0 1 0';
	zombi.yaw_speed	= 20;
	zombi.view_ofs	= '0 0 25';
	zombi.use		= monster_use;
	zombi.pausetime = 99999999;
	
	store = self;
	self = zombi;
	zombie_paine10();	// lay down
	self = store;
};
		
void() VomitusChew =
{
	if (self.ammo_cells > 0)	//we have at least 1 piece of meat
	{
		self.ammo_cells		= self.ammo_cells	- 1;	// Convert a cell (raw meat)
		self.ammo_shells	= self.ammo_shells	+ 1;	// To a gib ammo
		self.ammo_nails		= self.ammo_nails	+ 1;	// and potential zombie piece
		
		if (self.health < 250)	//I'm injured, so eating heals me
			self.health = self.health + 10;
		
		if (self.ammo_nails >= 4)	//4 digested required to make a zombie
		{	
			Vomitus_SpawnZombie();	// Supa
			self.ammo_nails = self.ammo_nails - 4;	// they've been used up now
		}
	}
	else
	{
		//No meat left, stop digesting and get back to work
		if (self.movetarget)	self.th_walk ();
		else					self.th_stand ();
		return;
	}
};

void()	vomitus_paina1	=[	$paina1,	vomitus_paina2	] {};
void()	vomitus_paina2	=[	$paina2,	vomitus_paina3	] {};
void()	vomitus_paina3	=[	$paina3,	vomitus_paina4	] {};
void()	vomitus_paina4	=[	$paina4,	vomitus_run1	] {};

void()	vomitus_painb1	=[	$painb1,	vomitus_painb2	] {};
void()	vomitus_painb2	=[	$painb2,	vomitus_painb3	] {};
void()	vomitus_painb3	=[	$painb3,	vomitus_painb4	] {};
void()	vomitus_painb4	=[	$painb4,	vomitus_run1	] {};

void()	vomitus_painc1	=[	$painc1,	vomitus_painc2	] {};
void()	vomitus_painc2	=[	$painc2,	vomitus_painc3	] {};
void()	vomitus_painc3	=[	$painc3,	vomitus_run1	] {};

/*============================================================================
	Attacks
============================================================================*/

void() Vomitus_Puke_Sound =
{
	local float r;
	r = random ();
	
	if (r < 0.6)
		sound (self, CHAN_WEAPON, "vomitus/attack1.wav", 1, ATTN_NORM);
	else
		sound (self, CHAN_WEAPON, "vomitus/attack2.wav", 1, ATTN_NORM);
};

void()	Vomitus_Puke =
{
	/*The vomitus pukes a load of stuff at the player, more at higher skills.  One side
	effect of this is that on lower skills the Vomitus is more conservative, saving its
	special ammo.  On higher skills it will waste ammo more, chucking everything at the 
	target*/

	local float MultiShot;
	
	MultiShot	=	(skill + 2);	//Gob 2-5 things at the player depending on the skill
	while (MultiShot > 0)	//basically spams the player with whatever has been eaten
		{					//either gibs or grenades - these can be given to the thing via a 'sanctioned hack' from the mapper
			M_FireGrenade('0 0 0');	//attack library decides what to throw
			MultiShot = MultiShot - 1;	//reduce qty of things by one and repeat
		}		//end vomit attack
};

void()	Vomitus_Devour	=	
{
	local vector	delta,
					enemyorg;
					
	local float 	ldmg,
					enemyhealth,
					yummy;

	if (!self.enemy)
		return;

	if		(self.enemy.classname == "gib"			)	yummy = TRUE;
	else if (self.enemy.health <= 0					&&
			 (self.enemy.flags & FL_MONSTER)		)	yummy = TRUE;	
				  
	if (!yummy							)	// can't eat it?
	if (!CanDamage (self.enemy, self)	)	// can't damage it?
		return;								// meh

	//High damage melee attack 
	ai_charge(15);
	
	// Supa, take breakables into account
	/*if (self.enemy.solid == SOLID_BSP)	enemyorg = (self.enemy.absmin + self.enemy.absmax) * 0.5;
	else								enemyorg = self.enemy.origin;
	delta = enemyorg - self.origin;*/
	
    if (!InMeleeRange (100))    // Needed for fat dragons.
        return;
		
	if (!yummy)	// Supa, don't attempt to damage food; that's just silly
	{
		// Supa, check if we did damage by recording enemy health and checking it after T_Dam

		enemyhealth = self.enemy.health;
		
		T_Damage (self.enemy, self, self, 50, DTH_VOM_DEVOUR, FALSE, 1.5);
	}
	
	if (self.enemy.health < enemyhealth	||	// Did I bite them?
		yummy							)	// or am I just having a snack?
	{
		if (self.enemy.health < 1)	//sucessfully devoured victim
		{	//figure out how much chewing is needed
			if		(self.enemy.classname == "monster_shambler"	)	self.ammo_cells = self.ammo_cells + 9;	//very big creature
			else if (self.enemy.classname == "monster_shalrath"	||
					 self.enemy.classname == "monster_demon1"	|| 
					 self.enemy.classname == "monster_ogre"		)	self.ammo_cells = self.ammo_cells + 7;	//big creature
			else if (self.enemy.classname == "monster_fish"		|| 
					 self.enemy.classname == "monster_dog"		)	self.ammo_cells = self.ammo_cells + 3;	//tiny creature
			else													self.ammo_cells = self.ammo_cells + 5;	//humanoid or unknown size
			
			if (self.enemy.classname != "player")
			{
				self.enemy.think = SUB_Remove;
				self.enemy.nextthink = time;// + 0.1;	//non-player devoured enemy removes itself next frame
				
				self.enemy = world;
			}	//FIXME move the enemy to the vomitus' position before removing it and make the anim swallow them whole
		}
		else	//They haven't been devoured, but I've taken a bite
			self.ammo_cells = self.ammo_cells + 2;
			
		vomitus_digest1();	//I've got food in my mouth, so will chew it
	}
};

/*============================================================================
	Find Food Sequence
============================================================================*/

// Supa 20110220 rewrote from scratch
float() WhatsForLunch =
{
	local float		dist,
					cdist,	// distance of closest nommable found
					yummy;
	
	local entity	head,
					eatme;
	
	cdist	= 701;
	head	= nextent(world);

	while (head != world)
	{
		// look for gibs or corpses, eat the closest one
		yummy = FALSE;	// okay, wtf, let's try to remember to clear everything important at the beginning of every iteration of a loop next time -_-
		
		if		(head.classname == "gib"				)	yummy = TRUE;
		else if (head.health <= 0						&&
				 (head.flags & FL_MONSTER)				)	yummy = TRUE;

		if (yummy								)
//		if (visible(head)						)
		if (head.classname != "monster_zombie"	)
		{
			dist = vlen(head.origin - self.origin);
			
			if (dist < cdist)
			{
				cdist = dist;	// mark new closest distance
				eatme = head;
			}
		}

		head = nextent(head);
	}
	
	if (eatme)
	{
		 self.enemy	= eatme;
	 
		 FoundTarget();	// a special case in ai_run will handle the rest
		 
		 return TRUE;
	}
	else return FALSE;
};

/*
float() WhatsForLunch =
	{
		local entity   lunch;		//This is what we want to eat
		local entity   eat;			//This is what we'll do if we find lunch
		local float    dist;	//Check within this radius
		local float    result;		//This is the response to the question - what's for lunch?

		dist = 2000;
		eat = world;
		lunch = nextent(world);

		while (lunch!=world)
		{
			//if (lunch.classname == "gib")	//It's just a gib, vacuum it
			//{	
				//lunch.think = SUB_Remove; //FIXME Make the gib move to the Vomitus' position
				//lunch.nextthink = time + 0.1;
				//self.ammo_shells = self.ammo_shells + 1;
			//}
			//else 
			if ((lunch.health < 1) && (lunch.flags & (FL_MONSTER|FL_CLIENT)))	//Lunch is a corpse or head
			{
				result = fabs(lunch.origin_z - self.origin_z);
				if ((visible(lunch)) && (result<80) && (lunch.eating == FALSE) && (visible_distance<dist))
				{
					dist = visible_distance;
					eat = lunch;
				}
			}
			lunch = nextent(lunch);
		}
		 
		 
		if ((eat != world) && (dist < (700*random())))
         {
	//         dprint("starting to eat ");
	//         dprint(eat.classname);
	//         dprint("\n");
			 self.oldenemy = self.enemy;
			 self.eating = TRUE;
			 self.enemy = eat;
			 self.search_time = time + 4.0;
			 FoundTarget();
			 return TRUE;
         }
   result = FindTarget();
   self.search_time = time + 2.0;
   return result;
   };
*/
   
/*============================================================================
	Pain and Death Sequence
============================================================================*/

void(entity attacker, float damage)	vomitus_pain =
{
	local float	r;
	r = random();
	
	if (self.axhitme == TRUE)  //ijed Ripped from zaxe, Supa ack!
	{
		self.axhitme = FALSE;
		self.cnt = self.cnt + 1;
		
		if (random () < 0.3)
			ThrowGib ("progs/gib1.mdl", self.health);
			
		if (self.cnt > 12)	//Much tougher to melee gib than a zombie
			T_Damage (self, attacker, attacker, 180, DTH_CHAINSAW, FALSE, 1);  //ijed Frags the vomitus if it takes 5 chainsaw hits in a row
	}
	else
	{	
		if (self.health <= (skill*5))  //ijed Vomitus checks weather or not to deflate and go to sleep, skill and health dependant
		{
			// gb, submerged? 
			if (self.h2olevel >= 3)
			{
				DeathBubbles (3);
				sound (self, CHAN_VOICE, "player/drown1.wav", 1, ATTN_NORM);	// FIXME
			}
			else
			{
				sound (self, CHAN_VOICE, "vomitus/die.wav", 1, ATTN_IDLE);
			}

			self.solid = SOLID_NOT;
			vomitus_deflate1();
			return;
		}	
		else
		{
			if (damage < (7 + (r*10)))	//barely a scratch
				return;
			
			if (self.pain_finished > time)
				return;

			if (self.axhitme == -1)	// check if we were pierced by a SNG nail
			{
				self.axhitme = FALSE;
				return;
			}

			if (r < 0.25)
			{
				// gb, submerged? 
				if (self.h2olevel >= 3)
				{
					DeathBubbles (3);
					sound (self, CHAN_VOICE, "player/drown1.wav", 1, ATTN_NORM);	// FIXME
				}
				else
				{
					sound (self, CHAN_VOICE, "vomitus/paina.wav", 1, ATTN_NORM);
				}

				vomitus_paina1 ();
				self.pain_finished = time + 1;
			}
			else if (r < 0.5)
			{
				// gb, submerged? 
				if (self.h2olevel >= 3)
				{
					DeathBubbles (3);
					sound (self, CHAN_VOICE, "player/drown1.wav", 1, ATTN_NORM);	// FIXME
				}
				else
				{
					sound (self, CHAN_VOICE, "vomitus/painb.wav", 1, ATTN_NORM);
				}

				vomitus_painb1 ();
				self.pain_finished = time + 1;
			}
			else
			{
				// gb, submerged? 
				if (self.h2olevel >= 3)
				{
					DeathBubbles (3);
					sound (self, CHAN_VOICE, "player/drown1.wav", 1, ATTN_NORM);	// FIXME
				}
				else
				{
					sound (self, CHAN_VOICE, "vomitus/painc.wav", 1, ATTN_NORM);
				}

				vomitus_painc1 ();
				self.pain_finished = time + 2;
			}
		}
	}
};

void() vomitus_die =  
/*On death the vomitus converts everything it's eaten to gibs which form part of
it's instagib death, with some blood thrown in there as well in case it hasn't
eaten anything.  Any grenades eaten are dropped all at once, live and capable of
killing stuff.  Other vomitii in the vicinity will happily gather up the mess. */

{
	sound (self, CHAN_VOICE, "player/udeath.wav", 1, ATTN_NORM);
	//particle (self.origin, '0 0 0', 73, 200);
	local float Splatter; //how many pieces to throw
	Splatter = (self.ammo_shells + self.ammo_cells + self.ammo_rockets + 6);	//All the stuff I carry
	
	while (Splatter > 0)
		{
			if (self.ammo_rockets > 0)	//drop live grenade
			{
				M_FireGrenade('0 0 0');	//Attack library knows that it's dead
				self.ammo_rockets = self.ammo_rockets - 1;
			}
			else if (self.ammo_shells > 0)	//drop gib
			{
				ThrowGib ("progs/vomitus_gib.mdl", self.health);
				self.ammo_shells = self.ammo_shells - 1;
			}
			else if (self.ammo_cells > 0)	//drop gib
			{
				ThrowGib ("progs/vomitus_gib.mdl", self.health);
				self.ammo_shells = self.ammo_cells - 1;
			}
			else	//just drop blood
			{
				ThrowGib ("progs/bloodtrail.mdl", self.health);
			}	
			Splatter = Splatter - 1;
		}

	setmodel (self, "");
	CorpseThink();
	self.solid = SOLID_NOT;
	self.nextthink = -1;
	return;
};

/*============================================================================
	Start Up 
============================================================================*/

void() vomitus_decide =  // inflate if deflated
{
	if (self.sleeping == TRUE)
		vomitus_ainflate1();
	else
		vomitus_run1();
};

void() vomitus_start =  // is inflated or not on start
{
	if (self.spawnflags & SPAWN_SLEEPING)
	{
		Gyro_Object_ClearPhysics(self);  //ijed Turns off Gyro whilst it's 'dead'
		self.sleeping = TRUE;
		vomitus_deflated1 ();
	}
	else
	{
		vomitus_stand1 ();
	}
};

void() monster_vomitus_go =
{
	self.solid = SOLID_SLIDEBOX;
	self.movetype = MOVETYPE_STEP;

	setmodel (self, "progs/vomitus.mdl");

	setsize (self, '-48 -48 -24', '48 48 40');
	
	self.health = MonsterHealth(300);

	self.th_stand = vomitus_start;
	self.th_walk = vomitus_walk1;
	self.th_run = vomitus_decide;
	self.th_pain = vomitus_pain;
	self.th_die = vomitus_die;
	self.th_missile = vomitus_attack1;
	self.th_melee = vomitus_devour1;
	self.th_submerged = SUB_Null;

	Gyro_Object_Activate (self, 80000);

	//Give it a handful of gibs on startup, skill dependant as always
	self.ammo_shells = (self.ammo_shells + (random()*10 + skill));
	
	walkmonster_start();
};

/*QUAKED monster_vomitus (1 0 0) (-32 -32 -24) (32 32 40) Ambush
*/
void() monster_vomitus =
{
	if (deathmatch)
	{
		remove(self);
		return;
	}
	precache_model ("progs/vomitus.mdl");
	precache_model ("progs/vomitus_gib.mdl");	
	precache_model ("progs/bloodtrail.mdl");	

	precache_sound2 ("vomitus/die.wav");
	precache_sound2 ("vomitus/idle1.wav");
	precache_sound2 ("vomitus/paina.wav");
	precache_sound2 ("vomitus/painb.wav");
	precache_sound2 ("vomitus/painc.wav");
	precache_sound2 ("vomitus/attack1.wav");
	precache_sound2 ("vomitus/attack2.wav");
	precache_sound2 ("zombie/z_miss.wav"); 
	precache_sound2 ("zombie/z_hit.wav");
	
	// gb, slimy regurgitation sound
	precache_sound2 ("vomitus/revive1.wav");

	//Zombie Precache
	zombie_cache();
	
	self.go = monster_vomitus_go;
	if(!CheckGroup()) self.go();
};
