/****************************************************************************/
/*                                                                          */
/* Pick-Ups control                                                         */
/*                                                                          */
/****************************************************************************/
#include "game.h"

	extern sint16	inv_keys_objects;
	static int		pup_x,pup_y,pup_z;

/********************* PickUp Bound Boxes **********************************/

	static	sint16	PickUpBounds[12] = {					// Normal Pickup bounds
					-256,256,
					-100,100,
					-256,256,
					-10*ONE_DEGREE,10*ONE_DEGREE,
					0,0,
					0,0 };
		static	PHD_VECTOR	PickUpPosition = { 0,0,-100 };
		static	PHD_VECTOR	DetonatorPosition = { 0,0,0 };

		static	sint16	GongBounds[12] = {					
					-512,1024,
					-100,100,
					-WALL_L/2-300,-WALL_L/2+100,
					-30*ONE_DEGREE,30*ONE_DEGREE,
					0,0,
					0,0 };

		static	sint16	PickUpBoundsUW[12] = {					// UnderWater pickup bounds
					-512,512,
					-512,512,
					-512,512,
					-45*ONE_DEGREE,45*ONE_DEGREE,
					-45*ONE_DEGREE,45*ONE_DEGREE,
					-45*ONE_DEGREE,45*ONE_DEGREE };
		static	PHD_VECTOR	PickUpPositionUW = { 0,-200,-350 };


#define MAXOFF 220
		static	sint16	Switch1Bounds[12] = {
					-MAXOFF,+MAXOFF,                        // X axis Limits
					0,0,                                    // Y axis Limits
					WALL_L/2-MAXOFF,WALL_L/2,               // Z axis Limits
					-10*ONE_DEGREE,+10*ONE_DEGREE,			// X Rot Limits
					-30*ONE_DEGREE,+30*ONE_DEGREE,          // Y Rot Limits
					-10*ONE_DEGREE,+10*ONE_DEGREE };        // Z Rot Limits
		static	PHD_VECTOR	SmallSwitchPosition = {0,0,WALL_L/2-LARA_RAD-50};	// X,Y,Z relative to Switch
		static	PHD_VECTOR	PushSwitchPosition = {0,0,WALL_L/2-LARA_RAD-120};	// X,Y,Z relative to Switch
		static	PHD_VECTOR	AirlockPosition = {0,0,WALL_L/2-LARA_RAD-200};

		static	sint16	Switch2Bounds[12] = {
					-WALL_L,WALL_L,                         // X axis Limits
					-WALL_L,WALL_L,                         // Y axis Limits
					-WALL_L,WALL_L/2,       				// Z axis Limits
					-80*ONE_DEGREE,+80*ONE_DEGREE,			// X Rot Limits
					-80*ONE_DEGREE,+80*ONE_DEGREE,			// Y Rot Limits
					-80*ONE_DEGREE,+80*ONE_DEGREE };        // Z Rot Limits

		static	PHD_VECTOR	Switch2Position = {0,0,108 };	// X,Y,Z relative to Switch

#define MAXOFF_KH 	200
		static	sint16	KeyHoleBounds[12] = {
					-MAXOFF_KH,+MAXOFF_KH,                  // X axis Limits
					0,0,                                    // Y axis Limits
					WALL_L/2-MAXOFF_KH,WALL_L/2,            // Z axis Limits
					-10*ONE_DEGREE,+10*ONE_DEGREE,			// X Rot Limits
					-30*ONE_DEGREE,+30*ONE_DEGREE,			// Y Rot Limits
					-10*ONE_DEGREE,+10*ONE_DEGREE };        // Z Rot Limits

		static	PHD_VECTOR	KeyHolePosition = { 0,0,WALL_L/2-LARA_RAD-50 };

#define MAXOFF_PH 200
		static	sint16	PuzzleHoleBounds[12] = {
					-MAXOFF_PH,+MAXOFF_PH,                  // X axis Limits
					0,0,                                    // Y axis Limits
					WALL_L/2-MAXOFF_PH,WALL_L/2,            // Z axis Limits
					-10*ONE_DEGREE,+10*ONE_DEGREE,			// X Rot Limits
					-30*ONE_DEGREE,+30*ONE_DEGREE,			// Y Rot Limits
					-10*ONE_DEGREE,+10*ONE_DEGREE };        // Z Rot Limits

		static	PHD_VECTOR	PuzzleHolePosition = { 0,0,WALL_L/2-LARA_RAD-85 };  // Ideal Pos of Lara rel to PuzzleHole

/****************************************************************************
 *			Collision with PickUpable Items
 ***************************************************************************/
void	PickUpCollision( sint16 item_num, ITEM_INFO *laraitem, COLL_INFO *coll )
{
	ITEM_INFO	*item;
	sint16 x_rot, y_rot, z_rot;
#ifdef SECRET_BONUS
	int	i;
#endif

	item = &items[item_num];

	/* Gav: remember the rotations, as they are fiddled with for detection purposes */
	x_rot = item->pos.x_rot;
	y_rot = item->pos.y_rot;
	z_rot = item->pos.z_rot;

	item->pos.y_rot = laraitem->pos.y_rot;
	item->pos.z_rot = 0;
	if ( lara.water_status==LARA_ABOVEWATER || lara.water_status==LARA_WADE )
	{
		item->pos.x_rot = 0;
		if (!TestLaraPosition( PickUpBounds,item,laraitem))
		{
			item->pos.x_rot = x_rot;
			item->pos.y_rot = y_rot;
			item->pos.z_rot = z_rot;
			return;
		}

		if ( laraitem->current_anim_state==AS_PICKUP )
		{
			if ( laraitem->frame_number==PICKUP_F && item->object_number!=FLARE_ITEM )				// We are in the pickup
			{
				AddDisplayPickup( item->object_number );
				Inv_AddItem( item->object_number );
#ifdef SECRET_BONUS
				if ( item->object_number==SECRET_ITEM1 || item->object_number==SECRET_ITEM2 || item->object_number==SECRET_ITEM3)
				{
					if ((i = (savegame.secrets&1) + ((savegame.secrets&2)>>1) + ((savegame.secrets&4)>>2)) >=3)
						GF_ModifyInventory( CurrentLevel, 1 );
				}
#endif
				item->status = INVISIBLE;
				RemoveDrawnItem( item_num );
			}
			return;                                      	// required frame before deleting object
		}
		else if (laraitem->current_anim_state==AS_FLAREPICKUP)
		{
			if ( laraitem->frame_number==PICKUPF_F && item->object_number==FLARE_ITEM && lara.gun_type!=LG_FLARE ) 
			{
				lara.request_gun_type = LG_FLARE;
				lara.gun_type = LG_FLARE;      // make sure we Draw required Guns
				InitialiseNewWeapon();
				lara.gun_status = LG_SPECIAL;
				lara.flare_age = (sint32)(item->data) & 0x7fff; // the flare's flags are its age
				KillItem(item_num);
			}
			return;
		}
		else if ( input&IN_ACTION && !laraitem->gravity_status && laraitem->current_anim_state==AS_STOP &&
		 	  	lara.gun_status==LG_ARMLESS && !(lara.gun_type==LG_FLARE && item->object_number==FLARE_ITEM))
		{
			if (item->object_number==FLARE_ITEM)
			{
				laraitem->goal_anim_state = AS_FLAREPICKUP;
				do
					AnimateLara(laraitem);
				while (laraitem->current_anim_state!=AS_FLAREPICKUP);
			}
			else
			{
				AlignLaraPosition(&PickUpPosition,item,laraitem);
				laraitem->goal_anim_state = AS_PICKUP;				// We want to go into pickup
				do
					AnimateLara(laraitem);                      		// the pickup animation
				while ( laraitem->current_anim_state!=AS_PICKUP );
			}
			laraitem->goal_anim_state = AS_STOP;
			lara.gun_status=LG_HANDSBUSY;
			return;
		}
	}
	else if ( lara.water_status==LARA_UNDERWATER )				// UNDERWATER PICKUPS
	{
		item->pos.x_rot = -25*ONE_DEGREE;
		if (!TestLaraPosition(PickUpBoundsUW,item,laraitem))
		{
			item->pos.x_rot = x_rot;
			item->pos.y_rot = y_rot;
			item->pos.z_rot = z_rot;
			return;
		}

		if ( laraitem->current_anim_state==AS_PICKUP )
		{
			if ( laraitem->frame_number==PICKUP_UW_F && item->object_number!=FLARE_ITEM)			// We are in the pickup
			{
				AddDisplayPickup( item->object_number );
				Inv_AddItem( item->object_number );
#ifdef SECRET_BONUS
				if ( item->object_number==SECRET_ITEM1 || item->object_number==SECRET_ITEM2 || item->object_number==SECRET_ITEM3)
				{
					if ((i = (savegame.secrets&1) + ((savegame.secrets&2)>>1) + ((savegame.secrets&4)>>2)) >=3)
						GF_ModifyInventory( CurrentLevel, 1 );
				}
#endif
				item->status = INVISIBLE;
				RemoveDrawnItem( item_num );
			}
			return;
		}
		else if (laraitem->current_anim_state==AS_FLAREPICKUP)
		{
			if (laraitem->frame_number==PICKUPF_UW_F && item->object_number==FLARE_ITEM && lara.gun_type!=LG_FLARE)
			{
				lara.request_gun_type = LG_FLARE;
				lara.gun_type = LG_FLARE;
				InitialiseNewWeapon();
				lara.gun_status = LG_SPECIAL;
				lara.flare_age = (sint32)(item->data) & 0x7fff; // the flare's flags are its age
				draw_flare_meshes();
				KillItem(item_num);
			}
			return;
		}
		else if ( input&IN_ACTION && laraitem->current_anim_state==AS_TREAD &&
	 	  	lara.gun_status==LG_ARMLESS && !(lara.gun_type==LG_FLARE && item->object_number==FLARE_ITEM))

		{
			if ( !MoveLaraPosition( &PickUpPositionUW,item,laraitem) )
				return;
			if (item->object_number==FLARE_ITEM)
			{
				laraitem->fallspeed = 0;
				laraitem->current_anim_state = AS_FLAREPICKUP;
				laraitem->anim_number = PICKUPF_UW_A;
				laraitem->frame_number = anims[PICKUPF_UW_A].frame_base;
			}
			else
			{
				laraitem->goal_anim_state = AS_PICKUP;				// We want to go into
				do
				{
					AnimateLara(laraitem);                      		// the pickup animation
				} while ( laraitem->current_anim_state!=AS_PICKUP );
			}
			laraitem->goal_anim_state = AS_TREAD;
			return;
		}
	}

	/* If not in pickup then realign object to its original rotation */
	item->pos.x_rot = x_rot;
	item->pos.y_rot = y_rot;
	item->pos.z_rot = z_rot;
}


/******************************************************************************
 *				Collision Routine for Switches
 *****************************************************************************/
enum switch_states { SS_OFF,SS_ON,SS_LINK };

void	SwitchCollision( sint16 item_num, ITEM_INFO *laraitem, COLL_INFO *coll )
{
	ITEM_INFO	*item;

	item = &items[item_num];
	if ( !(input&IN_ACTION) || item->status!=NOT_ACTIVE || lara.gun_status!=LG_ARMLESS ||
		laraitem->gravity_status )
		return;

	if ( laraitem->current_anim_state==AS_STOP )
	{
		if ( !TestLaraPosition( Switch1Bounds, item, laraitem ) )
			return;
		laraitem->pos.y_rot = item->pos.y_rot;

		/* Jump Lara to position in front of switch (for SMALL_SWITCH and PUSH_SWITCH) */
		if (item->object_number == SMALL_SWITCH)
			AlignLaraPosition( &SmallSwitchPosition, item, laraitem );
		else if (item->object_number == PUSH_SWITCH)
			AlignLaraPosition( &PushSwitchPosition, item, laraitem );
		else if (item->object_number == AIRLOCK_SWITCH)
		{
			if (item->current_anim_state == SS_ON)
				return;
			AlignLaraPosition( &AirlockPosition, item, laraitem );
		}

		if ( item->current_anim_state==SS_ON )
		{
			/* Jump to on anim */
			if (item->object_number == SMALL_SWITCH)
				laraitem->anim_number = objects[LARA].anim_index + 195;
			else if (item->object_number == PUSH_SWITCH)
				laraitem->anim_number = objects[LARA].anim_index + 197;
			else
				laraitem->anim_number = objects[LARA].anim_index + 63;

			laraitem->current_anim_state = AS_SWITCHON;
			item->goal_anim_state = SS_OFF;
		}
		else
		{
			laraitem->current_anim_state = AS_SWITCHOFF;

			/* Jump to off anim */
			if (item->object_number == SMALL_SWITCH)
				laraitem->anim_number = objects[LARA].anim_index + 196;
			else if (item->object_number == PUSH_SWITCH)
				laraitem->anim_number = objects[LARA].anim_index + 197;
			else if (item->object_number == AIRLOCK_SWITCH)
			{
				laraitem->anim_number = objects[LARA_EXTRA].anim_index;
				laraitem->frame_number = anims[laraitem->anim_number].frame_base;
				laraitem->current_anim_state = EXTRA_BREATH;
				laraitem->goal_anim_state = EXTRA_AIRLOCK;
				AnimateItem(laraitem);
				lara.extra_anim = 1;
			}
			else
				laraitem->anim_number = objects[LARA].anim_index + 64;

			item->goal_anim_state = SS_ON;
		}

		if (!lara.extra_anim)
		{
			laraitem->frame_number = anims[laraitem->anim_number].frame_base;
			laraitem->goal_anim_state=AS_STOP;
		}
		lara.gun_status=LG_HANDSBUSY;

		item->status = ACTIVE;
		AddActiveItem( item_num );
		AnimateItem(item);
	}
}

/*******************************************************************************
 *					UnderWater switching
 ******************************************************************************/
void	SwitchCollision2( sint16 item_num, ITEM_INFO *laraitem, COLL_INFO *coll )
{
	ITEM_INFO	*item;

	item = &items[item_num];
	if ( !(input&IN_ACTION) || item->status!=NOT_ACTIVE || lara.water_status!=LARA_UNDERWATER ||
			lara.gun_status!=LG_ARMLESS)
			return;

	if ( laraitem->current_anim_state==AS_TREAD )
	{
		if ( !TestLaraPosition( Switch2Bounds, item, laraitem) )
			return;
		if ( item->current_anim_state==SS_ON || item->current_anim_state==SS_OFF )
		{
			if ( MoveLaraPosition( &Switch2Position, item, laraitem ) )
			{
				laraitem->fallspeed = 0;
				laraitem->goal_anim_state = AS_SWITCHON;			// Request for a SwitchOn animation
				do
				{
					AnimateLara( laraitem );
				} while ( laraitem->current_anim_state!=AS_SWITCHON );
				laraitem->goal_anim_state = AS_TREAD;
				lara.gun_status=LG_HANDSBUSY;
				item->status = ACTIVE;
				if ( item->current_anim_state==SS_ON )
					item->goal_anim_state = SS_OFF;
				else
					item->goal_anim_state = SS_ON;
				AddActiveItem( item_num );
				AnimateItem(item);
			}
		}
	}
}


void DetonatorCollision(sint16 item_number, ITEM_INFO *laraitem, COLL_INFO *coll)
{
	/* Special collision routine for detonator box (and gong too now) */
	ITEM_INFO *item;
	sint16 x_rot, y_rot, z_rot;

	/* If already doing this, don't bother */
	if (lara.extra_anim)
		return;

	item = &items[item_number];

	/* Remember the rotations, as they are fiddled with for detection purposes */
	x_rot = item->pos.x_rot;
	y_rot = item->pos.y_rot;
	z_rot = item->pos.z_rot;

	item->pos.y_rot = laraitem->pos.y_rot;
	item->pos.z_rot = 0;
	item->pos.x_rot = 0;

	if	(item->status != DEACTIVATED && (input&IN_ACTION) && lara.gun_status==LG_ARMLESS && 
		 !laraitem->gravity_status && laraitem->current_anim_state==AS_STOP) 
	{
		if (item->object_number == DETONATOR)
		{
			if (!TestLaraPosition(PickUpBounds,item,laraitem))
				goto normal_collision;
		}
		else
		{
			if (!TestLaraPosition(GongBounds,item,laraitem))
				goto normal_collision;
			else
			{
				item->pos.x_rot = x_rot;
				item->pos.y_rot = y_rot;
				item->pos.z_rot = z_rot;
			}
		}


		/* Pull up inventory if item not currently chosen */
		if (Inventory_Chosen == -1)
			Display_Inventory(INV_KEYS_MODE);

		/* If detonator key not chosen then don't continue */
		if (Inventory_Chosen != KEY_OPTION2)
			goto normal_collision;

		Inv_RemoveItem(KEY_OPTION2);
			
		AlignLaraPosition(&DetonatorPosition,item,laraitem);

		/* Jump to detonator animation state in LARA_EXTRA */
		laraitem->anim_number = objects[LARA_EXTRA].anim_index;
		laraitem->frame_number = anims[laraitem->anim_number].frame_base;
		laraitem->current_anim_state = EXTRA_BREATH;
		if (item->object_number == DETONATOR)
			laraitem->goal_anim_state = EXTRA_PLUNGER;
		else
		{
			laraitem->goal_anim_state = EXTRA_GONGBONG;
			laraitem->pos.y_rot += -0x8000;
		}

		/* Jump to that animation */
		AnimateItem(laraitem);
		
		/* Flag that Lara is running animations from another project */
		lara.extra_anim = 1;

		lara.gun_status = LG_HANDSBUSY;

		if (item->object_number==DETONATOR)
		{
			/* Activate detonator to get it to play its side of the anim */
			item->status = ACTIVE;
			AddActiveItem(item_number);
		}
		else
		{
			/* Create gong bonger and make it do its thing */
			item_number = CreateItem();
			if (item_number != NO_ITEM)
			{
				item = &items[item_number];
				item->object_number = GONGBONGER;
				item->pos.x_pos = laraitem->pos.x_pos;
				item->pos.y_pos = laraitem->pos.y_pos;
				item->pos.z_pos = laraitem->pos.z_pos;
				item->pos.y_rot = laraitem->pos.y_rot;
				item->pos.x_rot = laraitem->pos.z_rot = 0;
				item->room_number = laraitem->room_number;

				InitialiseItem(item_number);

				AddActiveItem(item_number);
				item->status = ACTIVE;
			}
		}

		return;
	}

normal_collision:
	item->pos.x_rot = x_rot;
	item->pos.y_rot = y_rot;
	item->pos.z_rot = z_rot;
	ObjectCollision(item_number, laraitem, coll);
}

/*****************************************************************************
 *				Lara Has Collided With A KeyHole...
 ****************************************************************************/
void	KeyHoleCollision( sint16 item_num, ITEM_INFO *laraitem, COLL_INFO *coll )
{
	ITEM_INFO	*item;
	int			correct=0;


	if ( laraitem->current_anim_state==AS_STOP )
	{
		item = &items[item_num];
		if ( (Inventory_Chosen==-1 && !(input&IN_ACTION)) ||
		 	lara.gun_status!=LG_ARMLESS ||
		 	laraitem->gravity_status )
				return;

		if ( !TestLaraPosition( KeyHoleBounds, item, laraitem ) )
			return;
		if ( item->status!=NOT_ACTIVE )
		{
			/* If keyhole used, say NO and remember position so she doesn't say it again */
			if ( laraitem->pos.x_pos!=pup_x ||
				 laraitem->pos.y_pos!=pup_y	||
				 laraitem->pos.z_pos!=pup_z )
			{
				pup_x = laraitem->pos.x_pos;
				pup_y = laraitem->pos.y_pos;
				pup_z = laraitem->pos.z_pos;
				SoundEffect( 2, &laraitem->pos, 0 );
			}
			return;
		}

		if ( Inventory_Chosen==-1 )
		{
			Display_Inventory(INV_KEYS_MODE);
			if ( Inventory_Chosen==-1 && inv_keys_objects )
				return;
			if ( Inventory_Chosen!=-1 )
				pup_y = laraitem->pos.y_pos-1;            // alter saved pos so enforces response
		}
		else
			pup_y = laraitem->pos.y_pos-1;            // alter saved pos so enforces response

		switch ( item->object_number )
		{
			case KEY_HOLE1:
				if ( Inventory_Chosen!=KEY_OPTION1 )
					break;
				Inv_RemoveItem( KEY_OPTION1 );
				correct = 1;
			break;

			case KEY_HOLE2:
				if ( Inventory_Chosen!=KEY_OPTION2 )
					break;
				Inv_RemoveItem( KEY_OPTION2 );
				correct = 1;
			break;

			case KEY_HOLE3:
				if ( Inventory_Chosen!=KEY_OPTION3 )
					break;
				Inv_RemoveItem( KEY_OPTION3 );
				correct = 1;
			break;

			case KEY_HOLE4:
				if ( Inventory_Chosen!=KEY_OPTION4 )
					break;
				Inv_RemoveItem( KEY_OPTION4 );
				correct = 1;
			break;

		}

		Inventory_Chosen = -1;				// reset inventory chosen item
		if ( !correct )
		{
			if ( laraitem->pos.x_pos!=pup_x ||
				 laraitem->pos.y_pos!=pup_y	||
				 laraitem->pos.z_pos!=pup_z )
			{
				SoundEffect( 2, &laraitem->pos, 0 );
				pup_x = laraitem->pos.x_pos;
				pup_y = laraitem->pos.y_pos;
				pup_z = laraitem->pos.z_pos;
			}
			return;
		}

		AlignLaraPosition( &KeyHolePosition, item, laraitem );
		laraitem->goal_anim_state = AS_USEKEY;
		do
			AnimateLara( laraitem );
		while ( laraitem->current_anim_state!=AS_USEKEY );

		laraitem->goal_anim_state=AS_STOP;          // make Lara go back to Stop
		lara.gun_status=LG_HANDSBUSY;               // Hands Are Busy for now..
		item->status = ACTIVE;						// Make keyHole Active...

		pup_x = laraitem->pos.x_pos;
		pup_y = laraitem->pos.y_pos;
		pup_z = laraitem->pos.z_pos;
	}
}


/*****************************************************************************
 *				Lara Has Collided With A Puzzle Receptacle
 ****************************************************************************/
void	PuzzleHoleCollision( sint16 item_num, ITEM_INFO *laraitem, COLL_INFO *coll )
{
	ITEM_INFO	*item;
	int			correct=0;


	item = &items[item_num];
	if ( laraitem->current_anim_state==AS_STOP )
	{
		if ( (Inventory_Chosen==-1 && !(input&IN_ACTION)) ||
		 	lara.gun_status!=LG_ARMLESS ||
		 	laraitem->gravity_status )
				return;

		if ( !TestLaraPosition( PuzzleHoleBounds, item, laraitem ) )
			return;
		if ( item->status!=NOT_ACTIVE )
		{
			if ( laraitem->pos.x_pos!=pup_x ||
				 laraitem->pos.y_pos!=pup_y	||
				 laraitem->pos.z_pos!=pup_z )
			{
				pup_x = laraitem->pos.x_pos;
				pup_y = laraitem->pos.y_pos;
				pup_z = laraitem->pos.z_pos;
				SoundEffect( 2, &laraitem->pos, 0 );
			}
			return;
		}
		if ( Inventory_Chosen==-1 )
		{
			Display_Inventory(INV_KEYS_MODE);
			if ( Inventory_Chosen==-1 && inv_keys_objects )
				return;
			if ( Inventory_Chosen!=-1 )
				pup_y = laraitem->pos.y_pos-1;            // alter saved pos so enforces response
		}
		else
			pup_y = laraitem->pos.y_pos-1;            // alter saved pos so enforces response
		switch ( item->object_number )
		{
			case PUZZLE_HOLE1:
				if ( Inventory_Chosen!=PUZZLE_OPTION1 )
					break;
				Inv_RemoveItem( PUZZLE_OPTION1 );
				correct = 1;
			break;

			case PUZZLE_HOLE2:
				if ( Inventory_Chosen!=PUZZLE_OPTION2 )
					break;
				Inv_RemoveItem( PUZZLE_OPTION2 );
				correct = 1;
			break;

			case PUZZLE_HOLE3:
				if ( Inventory_Chosen!=PUZZLE_OPTION3 )
					break;
				Inv_RemoveItem( PUZZLE_OPTION3 );
				correct = 1;
			break;

			case PUZZLE_HOLE4:
				if ( Inventory_Chosen!=PUZZLE_OPTION4 )
					break;
				Inv_RemoveItem( PUZZLE_OPTION4 );
				correct = 1;
			break;
		}
		Inventory_Chosen = -1;				// reset inventory chosen item
		if ( !correct )
		{
			if ( laraitem->pos.x_pos!=pup_x ||
				 laraitem->pos.y_pos!=pup_y	||
				 laraitem->pos.z_pos!=pup_z )
			{
				SoundEffect( 2, &laraitem->pos, 0 );
				pup_x = laraitem->pos.x_pos;
				pup_y = laraitem->pos.y_pos;
				pup_z = laraitem->pos.z_pos;
			}
			return;
		}
		AlignLaraPosition( &PuzzleHolePosition, item, laraitem );
		laraitem->goal_anim_state = AS_USEPUZZLE;
		do
		{
			AnimateLara( laraitem );
		} while ( laraitem->current_anim_state!=AS_USEPUZZLE );
		laraitem->goal_anim_state=AS_STOP;          // make Lara go back to Stop
		lara.gun_status=LG_HANDSBUSY;               // Hands Are Busy for now..
		item->status = ACTIVE;						// Make keyHole Active...
		pup_x = laraitem->pos.x_pos;
		pup_y = laraitem->pos.y_pos;
		pup_z = laraitem->pos.z_pos;
		return;
	}
	else if ( laraitem->current_anim_state==AS_USEPUZZLE )
	{
		if ( !TestLaraPosition( PuzzleHoleBounds, item, laraitem ) )
			return;
		if ( laraitem->frame_number==USEPUZZLE_F )
		{
			switch ( item->object_number )
			{
				case PUZZLE_HOLE1:
					item->object_number = PUZZLE_DONE1;
				break;

				case PUZZLE_HOLE2:
					item->object_number = PUZZLE_DONE2;
				break;

				case PUZZLE_HOLE3:
					item->object_number = PUZZLE_DONE3;
				break;

				case PUZZLE_HOLE4:
					item->object_number = PUZZLE_DONE4;
				break;
			}
		}
	}
}


/*****************************************************************************
 *		Switch Control Routine...
 ****************************************************************************/
void	SwitchControl( sint16 item_number )
{
	ITEM_INFO *item;

	item = &items[item_number];

	item->flags |= CODE_BITS; // needed by TriggerActive()
	if (!TriggerActive(item))
	{
		item->goal_anim_state = SS_ON;
		item->timer = 0; // needed to avoid dodgy effects next time switch pulled
	}
	AnimateItem( item );
}

/****************************************************************************
 *			Switch has reached Deactivate so do triggering
 *			 returns 0 if not switched yet
 *					 1 if switched
 *			Also remove from Active List if finished...
 ***************************************************************************/
int		SwitchTrigger( sint16 item_num, sint16 timer )
{
	ITEM_INFO	*item;

	item = &items[item_num];

	/* Airlock switches work differently */
	if (item->object_number == AIRLOCK_SWITCH)
	{
		if (item->status==DEACTIVATED)
		{
			RemoveActiveItem(item_num);
			item->status = NOT_ACTIVE;
			return 0;
		}
		else if ((item->flags & ONESHOT) || item->current_anim_state==SS_OFF)
			return 0;

		item->flags |= ONESHOT;
		return 1;
	}

	if ( item->status==DEACTIVATED )
	{
		/* Gav: switches with timers reset automatically */
		if ( item->current_anim_state==SS_OFF && timer>0 )
		{
			item->timer = timer;
			if ( timer!=1 )
				item->timer *= 30;
			item->status = ACTIVE;
		}
		else
		{
			RemoveActiveItem( item_num );
			item->status = NOT_ACTIVE;
		}
		return(1);
	}
	return(0);
}

/****************************************************************************
 *		  Key Receptacle has reached Deactivate so if Lara has finished her
 *			Animation( Flagged by HANDS NOW FREE ) then True..
 *			 returns 0 if not triggered yet
 *					 1 if Key Triggered
 *			Also remove from Active List if finished...
 ***************************************************************************/
int		KeyTrigger( sint16 item_num )
{
	ITEM_INFO	*item;

	item = &items[item_num];
//	if ( item->status==ACTIVE && lara.gun_status==LG_ARMLESS )		//SONY BUG FIX B13 - After using detonator, you immediately drew your weapons
	if ( item->status==ACTIVE && lara.gun_status!=LG_HANDSBUSY )	//					 the flip-map wouldn't happen until you put your weapons away
	{																//					 or not at all if you went into the water with your guns still out
		item->status = DEACTIVATED;									//					 This also fixes the same bug with the doors opening.
		return(1);
	}
	return(0);
}

/****************************************************************************
 *		  If an item has Been picked up then it has to be able to trigger
 *		  			an effect. However this only happens once!!
 ***************************************************************************/
int		PickupTrigger( sint16 item_num )
{
	ITEM_INFO	*item;

	item = &items[item_num];
	if ( item->status==INVISIBLE )
	{
		item->status = DEACTIVATED;
		return(1);
	}
	return(0);
}


void SecretControl(sint16 item_number)
{
	items[item_number].status = INVISIBLE;
	RemoveDrawnItem(item_number);
}