/******************************************************************************

  POSIONVILLE - Episode specific code

*******************************************************************************/

#include "g_local.h"

#include "voice_punk.h"
#include "voice_bitch.h"

qboolean ProcessPVMomo (edict_t *self, edict_t *other);
qboolean ProcessPVYolanda (edict_t *self, edict_t *other);

void Resp_PVLouie_TellsMe (edict_t *self, edict_t *other, response_t response);
void misc_pv_afraid_think (edict_t *self);

// This gets called whenever a character (player or AI) is sighted by an AI character
// in the Posionville episode

qboolean EP_Poisonville_CastSight ( edict_t *self, edict_t *other, cast_memory_t *mem )
{
	if (self->name_index == NAME_MOMO && other->client)
	{
		if (mem->timestamp < (level.time - 8))
		{	// haven't seen them for a while
			other->episode_flags &= ~EP_PV_MOMO_ASKED_MONEY;
			// mem->flags &= ~MEMORY_LASTWARNING;
		}

		if ((mem->memory_type == MEMORY_TYPE_ENEMY) /*&& !other->client->pers.weapon*/)
		{	// give them a chance to make friends if they holster
			self->enemy = NULL;

			// make them a neutral instead of enemy
			AI_RemoveFromMemory( self, mem );
			AI_AddToMemory( self, mem, MEMORY_TYPE_NEUTRAL );
			mem->flags &= ~MEMORY_HOSTILE_ENEMY;
		}

		return true;
	}

	if (self->name_index == NAME_YOLANDA && other->client)
	{
		if (mem->timestamp < (level.time - 8))
		{	// haven't seen them for a while
			if (!(other->episode_flags & EP_PV_YOLANDA_TOOK_MONEY))
			other->episode_flags &= ~EP_PV_YOLANDA_ASKED_MONEY;
		}

		if ((mem->memory_type == MEMORY_TYPE_ENEMY) && !(other->client->pers.weapon))
		{	// give them a chance to make friends if they holster
			self->enemy = NULL;

			// make them a neutral instead of enemy
			AI_RemoveFromMemory( self, mem );
			AI_AddToMemory( self, mem, MEMORY_TYPE_NEUTRAL );
			mem->flags &= ~MEMORY_HOSTILE_ENEMY;
		}

		return false;
	}

	if (	(	(self->name_index == NAME_LAUREL)
			||	(self->name_index == NAME_HARDEY))
		&&	(other->client) )
	{
		if (self->enemy)
		{
			self->goal_ent = NULL;

			return false;
		}

		if (other->current_territory != self->cast_group || VectorDistance(self->s.origin, other->s.origin) > AI_NOT_HOLSTERED_RANGE_1)
		{
			// Ignore them
			return true;
		}
		else
		{
			if (VectorDistance (self->s.origin, other->s.origin) > AI_NOT_HOLSTERED_RANGE_1)
			{
				// Dont get mad yet
				return true;
			}
			else
			{
				// too close waist em
				AI_MakeEnemy( self, other, 0 );
				AI_StartAttack( self, other );
				self->goal_ent = NULL;
				return false;
			}
		}
	}

	return false;
}

// EP_Posionville_CastUse
// Called when ever a character is "used" (like when someone dies that has a ->deathtarget set)

qboolean EP_Poisonville_CastUse (edict_t *self, edict_t *other, edict_t *activator)
{
	return false;
}


// EP_Posionville_EventSpeech
// Called on speech occasions 
//
//	Return TRUE so that the normal speech routines don't say something as well

qboolean EP_Poisonville_EventSpeech (edict_t *self, edict_t *other, int saywhat)
{
	cast_memory_t	*mem;

	mem = level.global_cast_memory[ self->character_index ][ other->character_index ];
	
	switch (saywhat)
	{
	
	case say_neutral:

		if (self->name_index == NAME_LAUREL && other->name_index == NAME_YOLANDA)
		{
			Voice_Random (self, other, neutral_converse_to_female, 10);
			return true;
		}
		
		if (self->name_index == NAME_HARDEY && other->name_index == NAME_YOLANDA)
		{
			Voice_Random (self, other, neutral_converse_to_female, 10);
			return true;
		}
		
		if	((self->name_index == NAME_MOMO)
			 &&	(other->client))
		{
			return (ProcessPVMomo (self, other));
		}

		if (self->name_index == NAME_YOLANDA)
		{
			if (other->client)
			{
				// hack to save test time for yolanda
				// other->episode_flags |= EP_PV_HIRED_SAFE_BOY;
			
				if (other->episode_flags & EP_PV_HIRED_SAFE_BOY)
				{
					{
						edict_t *Laurel;
						edict_t *Hardey;

						Laurel = EP_GetCharacter (NAME_LAUREL);
						Hardey = EP_GetCharacter (NAME_HARDEY);

						if (Laurel && Hardey)
							return (ProcessPVYolanda (self, other));
						else 
							Voice_Random (self, other, &yolanda_specific[0], 5);			
					}
				}
				else
					Voice_Random (self, other, &yolanda_specific[0], 5);			
			
				return true;
			}
			else
			{
				Voice_Random (self, other, &yolanda_specific[12], 5); 
				return true;
			}
		}

		if (self->name_index == NAME_LOUIE && other->client)
		{

			if (other->episode_flags & EP_PV_SAFE_DOCS)
			{
				EP_Skidrow_Register_EPFLAG (other, EP_PV_TALKED_LOUIE);
				EP_Skidrow_Register_EPFLAG (other, EP_PV_TALKED_LOUIE2);
				EP_Skidrow_Register_EPFLAG (other, EP_PV_TALKED_LOUIE3);
				EP_Skidrow_Register_EPFLAG (other, EP_PV_TALKED_LOUIE5);
			}

			if (!(other->episode_flags & EP_PV_TALKED_LOUIE))
			{
				// hey your alive... I gotta job for you you get me the files from 
				// nicki blanco's safe and I'll let ya hire my guys
				
				Voice_Specific (self, other, pv_louie, 0);
				EP_Skidrow_Register_EPFLAG (other, EP_PV_TALKED_LOUIE);

				return true;
			}

			if (!(other->episode_flags & EP_PV_TALKED_LOUIE2))
			{
				Voice_Specific (self, other, pv_louie, 1);
				EP_Skidrow_Register_EPFLAG (other, EP_PV_TALKED_LOUIE2);

				return true;
			}
			if (!(other->episode_flags & EP_PV_TALKED_LOUIE3))
			{
				Voice_Specific (self, other, pv_louie, 3);
				EP_Skidrow_Register_EPFLAG (other, EP_PV_TALKED_LOUIE3);

				return true;
			}
			if (!(other->episode_flags & EP_PV_TALKED_LOUIE5))
			{
				Voice_Specific (self, other, pv_louie, 18);
				EP_Skidrow_Register_EPFLAG (other, EP_PV_TALKED_LOUIE5);

				return true;
			}
										 
			if (!(other->episode_flags & EP_PV_SAFE_DOCS_DELIVERED))
			{
				if ((other->client->pers.inventory[ITEM_INDEX(FindItem("Safe docs"))]) 
					&& (other->episode_flags & EP_PV_SAFE_DOCS)) 
				{
					// a deal is a deal my guys will run with you now
					Voice_Specific (self, other, pv_louie, 15);
					EP_Skidrow_Register_EPFLAG (other, EP_PV_SAFE_DOCS_DELIVERED);
					
					{
						int     index;
						gitem_t *item;

						item = FindItem ("Safe docs");
						index = ITEM_INDEX (item);
						other->client->pers.inventory[index] = 0;						
					}

					return true;
				}
				else
				{										 
					if (!(other->client->pers.episode_flags & EP_PV_SENT_TO_GET_SAFEDOCS))
					{
						Voice_Specific (self, other, pv_louie, 4);
						EP_Skidrow_Register_EPFLAG (other, EP_PV_SENT_TO_GET_SAFEDOCS);
						return true;
					}
					
					if (!(other->client->pers.episode_flags & EP_PV_LOUIE_SPEACH_1))
					{
						Voice_Specific (self, other, pv_louie, 13);
						EP_Skidrow_Register_EPFLAG (other, EP_PV_LOUIE_SPEACH_1);

						return true;
					}
					
					if (!(other->client->pers.episode_flags & EP_PV_TALKED_LOUIE4))
					{
						Voice_Specific (self, other, pv_louie, 14);
						EP_Skidrow_Register_EPFLAG (other, EP_PV_TALKED_LOUIE4);

						return true;
					}
					
					if (!(other->client->pers.episode_flags & EP_PV_LOUIE_SPEACH_2))
					{
						Voice_Specific (self, other, pv_louie, 19);
						EP_Skidrow_Register_EPFLAG (other, EP_PV_LOUIE_SPEACH_2);

						{
							cast_memory_t	*mem;

							mem = level.global_cast_memory[ self->character_index ][ other->character_index ];
							
							mem->response = Resp_PVLouie_TellsMe;
						}

						return true;
					}
					
					{
						// random speak about the wearabouts of the safe
						Voice_Random (self, other, &pv_louie[9], 5);
					}

					return true;
				}
			}

			else
			{
				if (!(other->client->pers.episode_flags & EP_PV_LOUIE_KEY))
				{
					int     index;
					gitem_t *item;

					Voice_Specific (self, other, pv_louie, 16);
					EP_Skidrow_Register_EPFLAG (other, EP_PV_LOUIE_KEY);

					item = FindItem ("Chem_Plant_Key");
					index = ITEM_INDEX (item);
					other->client->pers.inventory[ index ] = 1;
					// show icon and name on status bar
					other->client->ps.stats[STAT_PICKUP_ICON] = gi.imageindex(item->icon);
					other->client->ps.stats[STAT_PICKUP_STRING] = CS_ITEMS+index;
					other->client->pickup_msg_time = level.time + 5.5;
					
				}
				// thanks see ya again sometime
				Voice_Specific (self, other, pv_louie, 12);
			}

			return true;
		}


		return false;
		break;
	
	case say_hostile:

		
		if (self->name_index == NAME_LOUIE && other->client)
		{
			if (other->episode_flags & EP_PV_SAFE_DOCS)
			{
				EP_Skidrow_Register_EPFLAG (other, EP_PV_TALKED_LOUIE);
				EP_Skidrow_Register_EPFLAG (other, EP_PV_TALKED_LOUIE2);
				EP_Skidrow_Register_EPFLAG (other, EP_PV_TALKED_LOUIE3);
				EP_Skidrow_Register_EPFLAG (other, EP_PV_TALKED_LOUIE5);

				Voice_Random (self, other, &pv_louie[6], 3);

				mem = level.global_cast_memory [self->character_index][other->character_index];
				mem->flags &= ~MEMORY_ASSHOLE;

				return true;
			}

			if (other->client->ps.stats[STAT_HUD_SELF_TALK] == TT_POSITIVE)
			{
				mem = level.global_cast_memory [self->character_index][other->character_index];
				mem->flags &= ~MEMORY_ASSHOLE;
			
				Voice_Random (self, other, &pv_louie[9], 3);		

				return true;
			}
			else
			{
				// just do a random curse at the player
				
				Voice_Random (self, other, &pv_louie[6], 3);
				return true;
			}
		}


		if (self->name_index == NAME_MOMO && other->client)
		{
			return (ProcessPVMomo (self, other));
		}

		if (self->name_index == NAME_YOLANDA && other->client)
		{
			self->cast_info.aiflags &= ~AI_NO_TALK;

			if (other->client->ps.stats[STAT_HUD_SELF_TALK] == TT_POSITIVE)
			{
				mem = level.global_cast_memory [self->character_index][other->character_index];
				mem->flags &= ~MEMORY_ASSHOLE;
		
				Voice_Random (self, other, &yolanda_specific[0], 2);

				return true;
			}
			else
			{
				Voice_Random (self, other, &yolanda_specific[17], 8);	
			}

			self->cast_info.aiflags |= AI_NO_TALK;

			return true;
		}

		return false;
		break;
	}


	return false;
}


// EP_Posionville_ItemPickup
// Called whenever an item is picked up

void EP_Poisonville_ItemPickup ( edict_t *self, edict_t *other )
{

if (!Q_strcasecmp( self->classname, "item_safedocs" ))
{
	EP_Skidrow_Register_EPFLAG (other, EP_PV_SAFE_DOCS);
	EP_Skidrow_Register_EPFLAG (other, EP_PV_SAFEDOORISOPEN);
}

}

// EP_Posionville_Script

void EP_Poisonville_Script( edict_t *ent, char *scriptname )
{

}


//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//
// Special Posionville entities

//................................................


//==========================================================================================
//
// RESPONSES

void Resp_PVLouie_TellsMe (edict_t *self, edict_t *other, response_t response)
{
	
	if (response == resp_yes)
	{
		Voice_Player_Specific(self, TT_YES);
		{
			cast_memory_t	*mem;
			mem = level.global_cast_memory[ other->character_index ][ self->character_index ];
			mem->response = NULL;
		}
	}
	else
	{
		Voice_Player_Specific(self, TT_NO);

		self->episode_flags = self->client->pers.episode_flags &= ~EP_PV_LOUIE_SPEACH_1;
		self->episode_flags = self->client->pers.episode_flags &= ~EP_PV_LOUIE_SPEACH_2;
	}

	self->response_ent = other;
	self->last_response_time = level.time;
	self->last_response = response;
}

void Resp_PVYolanda_GotMoney ( edict_t *self, edict_t *other, response_t response )
{

	if (self->episode_flags & EP_PV_YOLANDA_TOOK_MONEY)
		return;

	if (response == resp_yes)
	{
		Voice_Player_Specific(self, TT_YES);
		
		if (!(self->episode_flags & EP_PV_YOLANDA_TOOK_MONEY))
		{
			if (self->client->pers.currentcash >= 10)
			{
				Voice_Random (self, other, player_money_yes, NUM_PLAYER_MONEY_YES);

				self->client->pers.currentcash -= 10;
				other->currentcash += 10;

				EP_Skidrow_Register_EPFLAG (self, EP_PV_YOLANDA_TOOK_MONEY);

				{
					edict_t *ent = NULL;

					ent = G_Find (ent, FOFS(classname), "misc_pv_afraid");

					Voice_Specific (other, self, yolanda_specific, 11);

					if (ent)
					{
						other->goal_ent = ent;
						ent->cast_info.aiflags |= AI_GOAL_RUN;
						ent->think = misc_pv_afraid_think;
						ent->nextthink = level.time + 2.0;
						other->cast_info.aiflags &= ~AI_TALK;
						{
							cast_memory_t	*mem;

							mem = level.global_cast_memory[ other->character_index ][ self->character_index ];

							self->last_response_time = 0;	// so we don't process this response again
							mem->response = NULL;
							self->response_ent = NULL;
						}

					}
					else
						gi.dprintf ("yolanda missing misc_pv_afraid marker\n");
				}
			}
			else
			{
				Voice_Random (self, other, player_money_no, NUM_PLAYER_MONEY_NO);

				response = resp_no;
			}
		}

	}
	else if (response == resp_no)
	{
		Voice_Specific( self, other, specific, 6 );
		Voice_Player_Specific(self, TT_NO);
	}

	self->response_ent = other;
	self->last_response_time = level.time;
	self->last_response = response;

}


qboolean ProcessPVYolanda (edict_t *self, edict_t *other)
{

	cast_memory_t	*mem;

	mem = level.global_cast_memory[ self->character_index ][ other->character_index ];

	if (other->episode_flags & EP_PV_YOLANDA_TOOK_MONEY)
	{
		Voice_Random (self, other, &yolanda_specific[0], 3);	
		return true;
	}

	if (!(other->episode_flags & EP_PV_YOLANDA_ASKED_MONEY))		
	{
		Voice_Specific (self, other, yolanda_specific, 6);
		EP_Skidrow_Register_EPFLAG (other, EP_PV_YOLANDA_ASKED_MONEY);
		mem->response = Resp_PVYolanda_GotMoney;
		return true;
	}
	/*
	else if (	(other->response_ent == self)
			 &&	(other->last_response_time > (level.time - 5)))
	{
		if (other->last_response == resp_yes)
		{	
				Voice_Specific (self, other, yolanda_specific, 25);
		}
		else	// they said no
		{
			Voice_Specific (self, other, yolanda_specific, 25);
		}

		other->last_response_time = 0;	// so we don't process this response again

		mem->response = NULL;
		other->response_ent = NULL;

		return true;
	}
	*/
	else
	{
		Voice_Random (self, other, &yolanda_specific[8], 2); 

		if (yolanda_specific[8].last_played == level.time 
			|| yolanda_specific[9].last_played == level.time )
		{	
			mem->response = Resp_PVYolanda_GotMoney;
		}
				
	}

	return true;
}


void Resp_PVMomo_GotMoney ( edict_t *self, edict_t *other, response_t response )
{
	cast_memory_t	*mem;
		
	if (self->episode_flags & EP_PV_MOMO_TOOK_MONEY)
		return;

	mem = level.global_cast_memory[ other->character_index ][ self->character_index ];

	if (response == resp_yes)
	{
		Voice_Player_Specific(self, TT_YES);
		Voice_Random (self, other, player_money_yes, NUM_PLAYER_MONEY_YES);		// yes
	}
	else if (response == resp_no)
	{
		Voice_Player_Specific (self, TT_NO);
		Voice_Random (self, other, player_money_no, NUM_PLAYER_MONEY_NO);		// no
	}

	self->response_ent = other;
	self->last_response_time = level.time;
	self->last_response = response;
}

			
// generic process for hostile or neutral momo			
qboolean ProcessPVMomo (edict_t *self, edict_t *other)			
{
	
	cast_memory_t	*mem;	

	mem = level.global_cast_memory[ self->character_index ][ other->character_index ];

	if (mem->flags & MEMORY_LASTWARNING)
	{
		Voice_Random ( self, other, &momo_specific[13], 2);		// get the fuck out of my foyer

		return true;
	}

	if (other->episode_flags & EP_PV_MOMO_TOOK_MONEY)
	{
		// Ridah, 5-8-99, we've already taken their money, so say one of the following..

		if (!(mem->flags & MEMORY_ASSHOLE))
			Voice_Random ( self, other, &momo_specific[12], 2);		// so what's it gonna be... in or out?
		else	// they've cussed us, don't act all happy to see them
			Voice_Random ( self, other, &momo_specific[13], 2);		// get the fuck out of my foyer

		return true;
	}

	if (!(other->episode_flags & EP_PV_MOMO_FIRST_TIME))
	{
		
		Voice_Specific (self, other, momo_specific, 17); // welcome.wav

		EP_Skidrow_Register_EPFLAG (other, EP_PV_MOMO_FIRST_TIME);

		return true;
	}

	// Ridah, 5-8-99, I changed this so it clears this flag in EP_CastSight() if Momo sees you after not having seen you for a while
	if (!(other->episode_flags & EP_PV_MOMO_ASKED_MONEY))
	{
		// note to Rafael: you can use "inc" for anything.. usually used to count events
		if (!mem->inc)
		{
			if (!( mem->flags & MEMORY_ASSHOLE))
			{
				Voice_Random (self, other, &momo_specific[1], 3); // 10 dollar cover charge
				mem->inc = 1;
			}
			else
			{
				Voice_Specific (self, other, momo_specific, 5);		// now it's 20 bucks!
				mem->inc = 2;
			}
		}
		else
		{
			Voice_Specific (self, other, momo_specific, 9); // your back
		}

		EP_Skidrow_Register_EPFLAG (other, EP_PV_MOMO_ASKED_MONEY);

		mem->response = Resp_Momo_GotMoney;
		return true;
	}

	// have they responded yet?
	else if (	(other->response_ent == self)
			 &&	(other->last_response_time > (level.time - 5)))
	{
				
		if (other->last_response == resp_yes)
		{	
			edict_t	*door = NULL;
			int	cost;

			if ( mem->flags	& MEMORY_ASSHOLE)
			{
				if (mem->inc < 3)
					cost = 20;
				else
					cost = 30;
			}
			else
			{
				cost = 10;
			}
				
			// have we really have money to give?
			if (other->client->pers.currentcash >= cost)
			{
				other->client->pers.currentcash -= cost;
				self->currentcash += cost;
				
				EP_Skidrow_Register_EPFLAG (other, EP_PV_MOMO_TOOK_MONEY);

				// TBD: at this point need to have momo walk away to a path corner cast

				Voice_Specific( self, other, &momo_specific[0], 10 );	// go on in


				// JOSEPH 9-MAR-99
				// in case there's more than one door
				{	// unlock the door for player
					// Find target door
					edict_t	*e;
					int		i;
					
					for (i=1, e=g_edicts+i ; i < globals.num_edicts ; i++,e++)
					{
						if ((e->targetname) && (!strcmp(e->targetname, "bardoor_pv")))
						{
							// Unlock target door
							if (e->key == -1)
							{
								e->key = 0;	
								e->targetname = NULL;							
							}
						}
					}
					
					EP_Skidrow_Register_EPFLAG (other, EP_PV_MOMO_TOOK_MONEY);
				}
				// END JOSEPH

			}
			else
			{
				// don't have money to give
				Voice_Random( self, other, &momo_specific[7], 2 );	// see me later when you got the money
			}
		}
		else	// they said no
		{
			Voice_Random( self, other, &momo_specific[13], 3 );
		}

		other->last_response_time = 0;	// so we don't process this response again

		mem->response = NULL;
		other->response_ent = NULL;

		return true;
	}

	else 
	{

		if (mem->flags & MEMORY_ASSHOLE)
		{
			if (!(mem->flags & MEMORY_UPSET))
			{
				mem->flags |= MEMORY_UPSET;

				if (mem->inc < 3)
				{
					Voice_Specific (self, other, momo_specific, 5);
				}
				else	// 30 bucks for you now!
				{
					Voice_Specific (self, other, momo_specific, 6);
				}
			}
			else
			{
				Voice_Random (self, other, &momo_specific[12], 4); 

				// This needs to be here, or Momo will never take the money when mad
				if (momo_specific[12].last_played == level.time)
				{	// we just asked them if they wanna come in, so let them respond
					mem->response = Resp_PVMomo_GotMoney;
				}

			}
		}
		else
		{
			Voice_Random (self, other, &momo_specific[12], 5); 

			if (momo_specific[12].last_played == level.time)
			{	// we just asked them if they wanna come in, so let them respond
				mem->response = Resp_PVMomo_GotMoney;
			}
		}

	}
			
	return true;
}

// 
// PROCEDURES

int	EP_PV_HiredGuysFlags (edict_t *player, edict_t *self)
{
	if ((self->name_index == NAME_FINGERS || self->name_index == NAME_BUSTER))
	{
		edict_t *Buster;
		edict_t *Fingers;
		cast_memory_t *cast_memory;

		Buster = EP_GetCharacter (NAME_BUSTER);
		Fingers = EP_GetCharacter (NAME_FINGERS);
	
		cast_memory = level.global_cast_memory[self->character_index][player->character_index];

		if (player->episode_flags & EP_PV_SAFE_DOCS_DELIVERED && cast_memory && !(cast_memory->flags & MEMORY_HIRED))
		{
			Voice_Specific (self, player, hiredguy_ask, 10);
			return (0);
		}

		if (player->episode_flags & EP_PV_TALKED_LOUIE)
		{
			if (Buster && self == Buster)
			{
				if (Fingers)
				{
					cast_memory = level.global_cast_memory[Fingers->character_index][player->character_index];

					if (cast_memory && cast_memory->flags & MEMORY_HIRED)
					{
						// gi.dprintf ("FIXME SOUND TODO: %s:sorry I only work alone\n", Buster->name);
						Voice_Specific (self, player, hiredguy_ask, 18);
						return (0);
					}
				}
			}
			else if (Fingers && self == Fingers)
			{
				if (Buster)
				{
					cast_memory = level.global_cast_memory[Buster->character_index][player->character_index];
					if (cast_memory && cast_memory->flags & MEMORY_HIRED)
					{
						// gi.dprintf ("FIXME SOUND TODO: %s:sorry I only work alone\n", Fingers->name);
						Voice_Specific (self, player, hiredguy_ask, 18);
						return (0);
					}
				}
			}
		

			{
				cast_memory_t *cast_memory;

				if (Buster && self == Buster)
				{
					cast_memory = level.global_cast_memory[self->character_index][player->character_index];
				
					if (!(cast_memory->flags & MEMORY_HIRE_FIRST_TIME))
					{
						cast_memory->flags |= MEMORY_HIRE_FIRST_TIME;
						Voice_Specific (self, player, hiredguy_ask, 14);
						return (0);
					}
					else
						return (1);
				}
				else if (Fingers && self == Fingers)
				{
					cast_memory = level.global_cast_memory[self->character_index][player->character_index];
					if (!(cast_memory->flags & MEMORY_HIRE_FIRST_TIME))
					{
						cast_memory->flags |= MEMORY_HIRE_FIRST_TIME;
						Voice_Specific (self, player, hiredguy_ask, 16);
						return (0);
					}
					else
						return (1);
				}
			}
		}
		else 
		{
			Voice_Random (self, player, &hiredguy_ask[10], 4);
			return (0);
		}
		// only the two safe crackers are allowed to join the player
		return (1);
	}
	else if (player->episode_flags & EP_PV_SAFE_DOCS_DELIVERED)
		return (1);
	else 
	{
		if (!(player->episode_flags & EP_PV_FIND_LOUIE))
			EP_Skidrow_Register_EPFLAG (player, EP_PV_FIND_LOUIE);

		if (self->gender == GENDER_MALE)
			Voice_Random (self, player, &hiredguy_ask[10], 4);
		else
			Voice_Random (self, player, &hiredgal_specific[12], 4);

		return (0);
	}
}

void EP_PV_SpecialEventDeath (edict_t *self)
{
	edict_t *player;
	edict_t *idiot;

	player = &g_edicts[1];
	
	if (self->name_index == NAME_BUSTER)
		EP_Skidrow_Register_EPFLAG (player, EP_PV_BUSTERISDEAD);

	if (self->name_index == NAME_FINGERS)
		EP_Skidrow_Register_EPFLAG (player, EP_PV_FINGERSISDEAD);

	if ( !(player->episode_flags & EP_PV_SAFEDOORISOPEN) &&
		(player->episode_flags & EP_PV_BUSTERISDEAD && player->episode_flags & EP_PV_FINGERSISDEAD))
	{
		idiot = G_Find (NULL, FOFS (targetname), "trigger_idiot");

		if (idiot)
			idiot->use (idiot, player, player);
		else
			gi.dprintf ("error you are an idiot\n");

		player->episode_flags = player->client->pers.episode_flags = 0;
	}

}

void EP_PVFlags (edict_t *self)
{
	if (self->name_index == NAME_MOMO)
	{
		self->cast_info.aiflags |= AI_IMMORTAL;
		self->s.model_parts[PART_GUN].invisible_objects = (1<<0 | 1<<1);
		self->s.model_parts[PART_GUN2].invisible_objects = (1<<0 | 1<<1);
	}
	else if ((strstr (level.mapname, "bar_")))
	{
		// make all weapons invisible while we are in a bar
		if (self->gender == GENDER_MALE || self->gender == GENDER_FEMALE)
		{
			self->s.model_parts[PART_GUN].invisible_objects = (1<<0 | 1<<1);
			self->s.model_parts[PART_GUN2].invisible_objects = (1<<0 | 1<<1);
		}
	}
}


void EP_PV_CheckMomo (edict_t *ent, cast_memory_t	*mem)
{
	if (ent->episode_flags & EP_PV_MOMO_ASKED_MONEY)
	 	mem->inc++;
				
}

qboolean EP_PV_DoKey (edict_t *self, edict_t *other)
{
	if (other->name_index == NAME_FINGERS || other->name_index == NAME_BUSTER && self->client)
		return true;
	else
		return false;
}

extern mmove_t	punk_move_walk_dokey;
extern mmove_t	punk_move_crch_dokey;

extern mmove_t  runt_move_walk_dokey;
extern mmove_t	runt_move_crch_dokey;

extern mmove_t	bitch_move_walk_dokey;

extern mmove_t	thug_move_walk_dokey;
extern mmove_t	thug_move_crch_dokey;

void EP_PV_Check_DoKey (edict_t *self, edict_t *ent)
{
	edict_t *Buster;
	edict_t *Fingers;
	edict_t *dest;
	vec3_t	vec;
	float	dist;

	Buster = EP_GetCharacter (NAME_BUSTER);
	Fingers = EP_GetCharacter (NAME_FINGERS);
	
	if (!ent)
		return;

	if (!(ent->targetname))
	{
		if (Fingers)
		{
			self->cast_info.aiflags &= ~AI_DOKEY;
			Fingers->cast_info.aiflags &= ~AI_DOKEY;
		}
		if (Buster)
		{
			self->cast_info.aiflags &= ~AI_DOKEY;
			Buster->cast_info.aiflags &= ~AI_DOKEY;
		}
	
		return;
	}

		
	// its a safe and its locked
	if (!strcmp (ent->targetname, "safe_door") && ent->key == -1)
	{
		dest = G_Find (NULL, FOFS (targetname), ent->target); // ai_safespot

		if (Buster && Buster->cast_info.aiflags & AI_DOKEY)
		{
			if (!(Buster->goal_ent) || !(Buster->enemy))
			{	
				if (visible (Buster, dest))
				{
					VectorSubtract (Buster->s.origin, dest->s.origin, vec);
					dist = VectorLength (vec);

					if (dist < 384)
					{
						Buster->goal_ent = dest; 
						self->cast_info.aiflags &= ~AI_DOKEY;
						Buster->cast_info.aiflags &= ~AI_DOKEY;
						Buster->cast_info.currentmove = &runt_move_walk_dokey;
					}
				}
			}
		}
		else if (Fingers && Fingers->cast_info.aiflags & AI_DOKEY)
		{
			if (!(Fingers->goal_ent) || !(Fingers->enemy))
			{
				if (visible (Fingers, dest))
				{
					VectorSubtract (Fingers->s.origin, dest->s.origin, vec);
					dist = VectorLength (vec);
					
					if (dist < 384)
					{
						Fingers->goal_ent = dest; 
				
						self->cast_info.aiflags &= ~AI_DOKEY;
						Fingers->cast_info.aiflags &= ~AI_DOKEY;

						Fingers->cast_info.currentmove = &thug_move_walk_dokey; // this should be called dokey

						// make the guns invisible
						Fingers->s.model_parts[PART_GUN].invisible_objects = (1<<0 | 1<<1);
						Fingers->s.model_parts[PART_GUN2].invisible_objects = (1<<0 | 1<<1);

					}
				}
			}
		}
		else 
			gi.dprintf ("there is no one to open the safe\n");
	}
	


}


void EP_PV_ReachedDoKey (edict_t *self)
{
	vec3_t	vec;
	float	dist;
	edict_t		*dest;

	VectorSubtract (self->s.origin, self->goal_ent->s.origin, vec);
	dist = VectorLength (vec);
	
	if (dist < 32)
	{
		if (self->name_index == NAME_BUSTER)
		{
			self->cast_info.currentmove = &runt_move_crch_dokey;
		}
		else if (self->name_index == NAME_FINGERS)
		{
			self->goal_ent = NULL;

			dest = G_Find (NULL, FOFS (targetname), "trigger_fingers"); 
			if (dest->use)
			{
					dest->use (dest, self, self);
			}

			self->cast_info.currentmove = &thug_move_crch_dokey;
		}
		else if (self->name_index == NAME_YOLANDA)
		{
			self->goal_ent = NULL;
			self->cast_info.currentmove = self->cast_info.move_stand;
			self->cast_info.aiflags |= AI_TALK;
			
			{
				edict_t *Laurel;
				vec3_t	vec;
				
				Laurel = EP_GetCharacter (NAME_LAUREL);

				if (Laurel)
				{
					VectorSubtract (Laurel->s.origin, self->s.origin, vec);
					VectorNormalize (vec);
					self->ideal_yaw = vectoyaw (vec);
					M_ChangeYawOld (self);
					Laurel->cast_info.aiflags |= AI_TALK;

					Voice_Specific (Laurel, self, neutral_converse_to_female, 6);
				}

			}

		}
		
	}
	/*
	else if (dist < 128)
	{
		if (self->name_index == NAME_LAUREL)
		{
			self->goal_ent = NULL;
			self->cast_info.currentmove = self->cast_info.move_stand;
			
			{
				edict_t *Yolanda;
				vec3_t	vec;
				
				Yolanda = EP_GetCharacter (NAME_YOLANDA);

				if (Yolanda)
				{
					VectorSubtract (self->s.origin, Yolanda->s.origin, vec);
					VectorNormalize (vec);
					Yolanda->ideal_yaw = vectoyaw (vec);
					M_ChangeYawOld (Yolanda);
					self->cast_info.aiflags |= AI_TALK;

					Voice_Specific (self, Yolanda, neutral_converse_to_female, 6);
				}

			}
		}
		else if (self->name_index == NAME_HARDEY)
		{
			self->goal_ent = NULL;
			self->cast_info.currentmove = self->cast_info.move_stand;
		
		}
	}
	*/

}

void EP_PV_EndDoKey (edict_t *self)
{
	edict_t		*dest;
	edict_t		*player;

	player = &g_edicts[1];

	if (self->name_index == NAME_BUSTER)
	{
		self->cast_info.currentmove = self->cast_info.move_run;

		dest = G_Find (NULL, FOFS (targetname), "trigger_buster"); 

		if (dest)
			if (dest->use)
			{
					dest->use (dest, self, self);
			}

		// spawn a grenade
		// FIXME: need to replace with dynamite
		{
			// JOSEPH 17-MAY-99
			fire_dynamite (self, self->s.origin, vec3_origin, 120, 750, 5.0, 256);
			// fire_grenade (self, self->s.origin, vec3_origin, 120, 750, 5.0, 256);
			// END JOSEPH
			// gi.dprintf ("FIXME SOUND TODO: %s: run she's gonna blow\n", self->name);
			Voice_Specific (self, player, hiredguy_ask, 15);
			EP_Skidrow_Register_EPFLAG (player, EP_PV_SAFEDOORISOPEN);
		}

	}
	else if (self->name_index == NAME_FINGERS)
	{
		self->cast_info.currentmove = self->cast_info.move_run;
		// gi.dprintf ("FIXME SOUND TODO %s: there you go easy money!\n", self->name);
		Voice_Specific (self, player, hiredguy_ask, 17);
		EP_Skidrow_Register_EPFLAG (player, EP_PV_SAFEDOORISOPEN);
		
		// he's done so show the guns
		self->s.model_parts[PART_GUN].invisible_objects = 0;
		self->s.model_parts[PART_GUN2].invisible_objects = 0;

	}	

}

qboolean EP_PV_UnlockDoorFlag (edict_t *ent)
{

	return false;

}

void EP_PV_HiredGuysRegisterFlags (edict_t *ent, edict_t *other)
{
	if (other->name_index == NAME_FINGERS || other->name_index == NAME_BUSTER)
		EP_Skidrow_Register_EPFLAG (ent, EP_PV_HIRED_SAFE_BOY);		
}

/*QUAKED misc_pv_afraid (.5 .5 1) (-16 -16 -24) (16 16 48)
used by actors to pick location where it is safer to run away from the player
*/

void misc_pv_afraid_think (edict_t *self)
{
	edict_t *Yolanda;
	edict_t *Laurel;
	edict_t *Hardey;
	vec3_t	vec;
	float	dist;

	Yolanda = EP_GetCharacter (NAME_YOLANDA);

	if (!self->count)
	{
		if (Yolanda)
		{
			self->count = 1;
			gi.sound(Yolanda, CHAN_VOICE, gi.soundindex("actors/female/yolanda/shakin.wav"), 1, ATTN_NORM, 0);
		}
	}
	else if (self->count == 3)
		return;

	if (Yolanda)
	{
		
		VectorSubtract (Yolanda->s.origin, self->s.origin, vec);
		dist = VectorLength (vec);

		// gi.dprintf ("dist: %5.3f\n", dist);

		if (dist < 128)
		{
			if (self->count == 1)
			{
				Yolanda->cast_info.currentmove = &bitch_move_walk_dokey;
				Yolanda->cast_info.aiflags &= ~AI_TALK;
			}
	
			Laurel = EP_GetCharacter (NAME_LAUREL);
			Hardey = EP_GetCharacter (NAME_HARDEY);

			if (Laurel && self->count == 1)
			{
				{
					edict_t *ent = NULL;

					ent = G_Find (ent, FOFS(classname), "misc_pv_afraid");

					if (ent)
					{
						Laurel->goal_ent = ent;
						ent->cast_info.aiflags |= AI_GOAL_RUN;
						Laurel->cast_info.aiflags &= ~AI_TALK;
					}
					
				}

				Laurel->cast_info.talk_ent = NULL;
				Laurel->cast_info.currentmove = Laurel->cast_info.move_run;
				self->count = 2;
				self->nextthink = level.time + 2.0;
			}

			else if (Hardey && self->count == 2)
			{	
				/*
				{
					edict_t *ent = NULL;

					ent = G_Find (ent, FOFS(classname), "misc_pv_afraid");

					if (ent)
					{
						// Hardey->goal_ent = ent;
						ent->cast_info.aiflags |= AI_GOAL_RUN;
						Hardey->cast_info.aiflags &= ~AI_TALK;
					}
					
				}
				*/

				if (Laurel)
					Hardey->goal_ent = Laurel;
				else
					Hardey->goal_ent = Yolanda;

				Hardey->cast_info.aiflags &= ~AI_TALK;
				Hardey->cast_info.talk_ent = NULL;
				Hardey->cast_info.currentmove = Hardey->cast_info.move_run;
				self->count = 3;
			}
		}
		else
			self->nextthink = level.time + 0.1;

	}
	

}

void SP_misc_pv_afraid (edict_t *self)
{
	//if (deathmatch->value)
	//{
	//	G_FreeEdict(self);
	//	return;
	//}

	self->movetype = MOVETYPE_NONE;
	self->solid = SOLID_NOT;
	VectorSet (self->mins, -16, -16, -24);
	VectorSet (self->maxs,  16,  16,  48);

	self->cast_info.aiflags |= AI_RUN_LIKE_HELL;
	self->count = 0;

	AI_Ent_droptofloor( self );

	gi.linkentity (self);
}


/*QUAKED ai_pv_fuseblown1 (.5 .5 1) ?
This will set the EP_PV_FUSEBLOWN flag
*/

void ai_fuseblown_touch1 (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
{	
	int     index;
	gitem_t *item;

	if (!(other->client))
		return;
	
	item = FindItem ("Fuse");
	index = ITEM_INDEX (item);

	if (other->client->pers.inventory[ index ])
	{
		self->touch = NULL;
		return;
	}	

	if (!(other->episode_flags & EP_PV_ONEFUSE))
		EP_Skidrow_Register_EPFLAG (other, EP_PV_ONEFUSE);
	
	if (!(other->episode_flags & EP_PV_FUSEISBLOWN1))
	{
		EP_Skidrow_Register_EPFLAG (other, EP_PV_FUSEISBLOWN1);
		
		if (other->episode_flags & EP_PV_ONEFUSE && other->episode_flags & EP_PV_FUSEISBLOWN2)
		{
			gi.sound(other, CHAN_VOICE, gi.soundindex("scenaric/fuse2.wav"), 1, ATTN_NORM, 0);
		}
		else
		{
			gi.sound(other, CHAN_VOICE, gi.soundindex("scenaric/fuse1.wav"), 1, ATTN_NORM, 0);
		}

		self->touch = NULL;

	}
	// FIXME
	// we need to play a wav file
	
}

void SP_pv_fuse_blown1 (edict_t *ent)
{
	//if (deathmatch->value)
	//{
	//	G_FreeEdict(ent);
	//	return;
	//}

	ent->solid = SOLID_TRIGGER;
	ent->touch = ai_fuseblown_touch1;

	ent->svflags |= SVF_NOCLIENT;

 	gi.setmodel (ent, ent->model);
	gi.linkentity (ent);

}

/*QUAKED ai_pv_fuseblown2 (.5 .5 1) ?
This will set the EP_PV_FUSEBLOWN flag
*/

void ai_fuseblown_touch2 (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
{
	int     index;
	gitem_t *item;

	if (!(other->client))
		return;

	item = FindItem ("Fuse");
	index = ITEM_INDEX (item);

	if (other->client->pers.inventory[ index ])
	{
		self->touch = NULL;
		return;
	}

	if (!(other->episode_flags & EP_PV_ONEFUSE))
		EP_Skidrow_Register_EPFLAG (other, EP_PV_ONEFUSE);
	
	if (!(other->episode_flags & EP_PV_FUSEISBLOWN2))
	{
		EP_Skidrow_Register_EPFLAG (other, EP_PV_FUSEISBLOWN2);
		
		if (other->episode_flags & EP_PV_ONEFUSE && other->episode_flags & EP_PV_FUSEISBLOWN1)
		{
			gi.sound(other, CHAN_VOICE, gi.soundindex("scenaric/fuse2.wav"), 1, ATTN_NORM, 0);
		}
		else
		{
			gi.sound(other, CHAN_VOICE, gi.soundindex("scenaric/fuse1.wav"), 1, ATTN_NORM, 0);
		}

		self->touch = NULL;

	}

	// FIXME
	// we need to play a wav file
	
}

void SP_pv_fuse_blown2 (edict_t *ent)
{
	//if (deathmatch->value)
	//{
	//	G_FreeEdict(ent);
	//	return;
	//}

	ent->solid = SOLID_TRIGGER;
	ent->touch = ai_fuseblown_touch2;

	ent->svflags |= SVF_NOCLIENT;

 	gi.setmodel (ent, ent->model);
	gi.linkentity (ent);

}


/*QUAKED ai_pv_deadlouie (.5 .5 1) ?
This will set the EP_PV_LOUIEPVB flag
*/

void ai_louiedead_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
{
	if (!(other->client))
		return;

	if (!(other->episode_flags & EP_PV_LOUIEPVB))
	{
		EP_Skidrow_Register_EPFLAG (other, EP_PV_LOUIEPVB);
		// gi.sound(other, CHAN_VOICE, gi.soundindex("scenaric/louieisdead.wav"), 1, ATTN_NORM, 0);
		self->touch = NULL;
	}
	
	// FIXME
	// we need to play a wav file
	
}

void SP_pv_deadlouie (edict_t *ent)
{
	//if (deathmatch->value)
	//{
	//	G_FreeEdict(ent);
	//	return;
	//}

	ent->solid = SOLID_TRIGGER;
	ent->touch = ai_louiedead_touch;

	ent->svflags |= SVF_NOCLIENT;

 	gi.setmodel (ent, ent->model);
	gi.linkentity (ent);

}

#include "ep_log.h"

extern int	the_log_page;

void EP_PV_Player_Log (edict_t *self, int page)
{
	int len; 
	int i;
	int	cnt = 0;
	int	select = 0;

	len = 0;

	Com_sprintf (game.helpmessage1, sizeof(game.helpmessage1), "");
	Com_sprintf (game.helpmessage2, sizeof(game.helpmessage2), "");
	
	the_log_page += page;
	
	if (the_log_page < 0)
		the_log_page = 0;
	else if (the_log_page >= NUM_PV_PLAYER_LOG)
		the_log_page = 0;

	for (i=1; i<NUM_PV_PLAYER_LOG; i++)
	{
		if (self->client->pers.episode_flags & ep_pv_player_log[i].ep_flag)
			cnt++;

		if (cnt == the_log_page)
		{
			select = i;
			break;
		}
	}	

	if (!page || !the_log_page)
	for (i=0; i<NUM_PV_PLAYER_LOG; i++)
	{
		if (ep_pv_player_log[i].new_clue == true)
		{
			select = i;
			break;
		}
	}

	if (cnt == 0)
	{
		the_log_page = 0;
		strcpy (game.helpmessage1, " ");
		
		if (ep_pv_player_log[select].new_clue)
			strcat (game.helpmessage1, "new entry");
		
		strcpy (game.helpmessage2, ep_pv_player_log[0].ep_text);
	}
	else
	{
		if (select == 0)
			the_log_page = 0;
		strcpy (game.helpmessage1, " ");
		
		if (ep_pv_player_log[select].new_clue)
			strcat (game.helpmessage1, "new entry");
		
		strcat (game.helpmessage2, ep_pv_player_log[select].ep_text);
		if (page)
			gi.sound(self, CHAN_VOICE, gi.soundindex("world/pageturn.wav"), 1, ATTN_NONE, 0);
	}


	

}

qboolean EP_PV_Flash_Newflag (edict_t *self, int ep_flag)
{
	int i;
	qboolean gotone = false;

	for (i=0; i<NUM_PV_PLAYER_LOG; i++)
	{
		if (ep_pv_player_log[i].ep_flag == ep_flag)
		{
			ep_pv_player_log[i].new_clue = true;
			gotone = true;
		}
		else
			ep_pv_player_log[i].new_clue = false;
	}

	return (gotone);
}
