/***********************************************************************************************************/
/*                                                                                                         */
/* Main Lara Controller                                                                                    */
/*                                                                                                         */
/***********************************************************************************************************/

/*---------------------------------------------------------------------------
 *	Import Headers
\*--------------------------------------------------------------------------*/

#ifdef PSX_VERSION
#include <sys\types.h>
#include <stdio.h>
#include "../spec_psx/typedefs.h"
#include "../spec_psx/psxinput.h"
#include "../spec_psx/specific.h"
#else
#include "../specific/standard.h"
#include "../specific/global.h"
#include "../specific/input.h"
#include "../specific/debug.h"
#endif

#include "objects.h"
#include "lara.h"
#include "laraanim.h"
#include "camera.h"
#include "control.h"
#include "input.h"
#include "sound.h"
#include "gameflow.h"
#include "invfunc.h"
#include "inventry.h"
#include "savegame.h"
#include "cinema.h"
#include "larafunc.h"
#include "laramisc.h"
#include "laraswim.h"
#include "larasurf.h"
#include "title.h"

/*---------------------------------------------------------------------------
 *	Constants
\*--------------------------------------------------------------------------*/

#define WADE_DEPTH (STEP_L)
#define SWIM_DEPTH 730

/*---------------------------------------------------------------------------
 *	Externals
\*--------------------------------------------------------------------------*/

#ifdef PSX_VERSION

extern void S_MemCpy(void *src, void *dest, int length);
extern char exit_message[];
extern int InfoFlag;

#endif

extern int outside;
extern uint16 DashTimer;

/*---------------------------------------------------------------------------
 *	Globals
\*--------------------------------------------------------------------------*/

sint16 	ExposureMeter;

/*---------------------------------------------------------------------------
 *	Locals
\*--------------------------------------------------------------------------*/

static COLL_INFO mycoll,*coll = &mycoll;

#ifdef GAMEDEBUG
char	*states[] = {
	"WALK",
	"RUN",
	"STOP",
	"F JUMP",
	"POSE",
	"FASTBACK",
	"TURN R",
	"TURN L",
	"DEATH",
	"FASTFALL",
	"HANG",
	"REACH",
	"SPLAT",
	"TREAD",
	"LAND",
	"COMPRESS",
	"BACK",
	"SWIM",
	"GLIDE",
	"NULL",
	"FAST TURN",
	"STEP RIGHT",
	"STEP LEFT",
	"ROLL2",
	"SLIDE",
	"BJUMP",
	"RJUMP",
	"LJUMP",
	"UP JUMP",
	"FALL BACK",
	"HANG LEFT",
	"HANG RIGHT",
	"SLIDE BACK",
	"SURF TREAD",
	"SURF SWIM",
	"DIVE",
	"PUSHBLOCK",
	"PULLBLOCK",
	"PPREADY",
	"PICKUP",
	"SWITCHON",
	"SWITCHOFF",
	"USE-KEY",
	"USE-PUZZLE",
	"UW_DEATH",
	"ROLL",
	"SPECIAL",
	"SURFBACK",
	"SURFLEFT",
	"SURFRIGHT",
	"USE MIDAS",
	"DIE MIDAS",
	"SWANDIVE",
	"FASTDIVE",
	"GYMNAST",
	"WATER OUT",
	"CLIMB STANCE",
	"CLIMBING",
	"CLIMB LEFT",
	"CLIMB END",
	"CLIMB RIGHT",
	"CLIMB DOWN",
	"LARATEST1",
	"LARATEST2",
	"LARATEST3",
	"WADE",
	"WATER-ROLL",
	"PICKUP",
	"TWIST",
	"KICK",
	"DEATHSLIDE",
	"DUCK",
	"DUCKROLL",
	"DASH",
	"DASHDIVE",
	"HANG2",
	"MONKEYSWING",	// 75
	"MONKEYL",
	"MONKEYR",
	"MONKEY180",
	"ALL4S",
	"CRAWL",
	"HANGTURNL",
	"HANGTURNR",
	"ALL4TURNL",
	"ALL4TURNR",
	"CRAWLBACK",
	"HANG2DUCK",
	"CRAWL2HANG",
	"LAST"
};

char	*quadrant_names[] = {
	"NORTH",
	"EAST",
	"SOUTH",
	"WEST" };

char	*gunstates[] = {
	"ARMLESS",
	"HANDSBUSY",
	"DRAW",
	"UNDRAW",
	"READY",
	"SPECIAL"
};

char	*waterstates[] = {
	"ABOVEWATER",
	"UNDERWATER",
	"SURFACE",
	"CHEAT",
	"WADE"
};

char	*guntypes[] = {
	"UNARMED",
	"PISTOLS",
	"MAGNUMS",
	"UZIS",
	"SHOTGUN",
	"M16",
	"ROCKET",
	"HARPOON",
	"FLARE"
};

char	*coll_typess[] = {
	"NONE",
	"FRONT",
	"LEFT",
	"RIGHT",
	"TOP",
	"TOPBOTTOM",
	"TOPFRONT",
	"CLAMP"
};

char	*htypes[] = {
	"WALL",
	"SMALL_SLOPE",
	"BIG_SLOPE",
	"DIAGONAL"
};
#endif

/*---------------------------------------------------------------------------
 *	Local Functions
\*--------------------------------------------------------------------------*/

/*****************************************************************************
 *			Initialise Laras Normal Meshes
 ****************************************************************************/

static void LaraInitialiseMeshes(int level_number)
{
	/* Gav: modified this to use START_INFO to make decisions */
	int i;
	START_INFO *start;

//	level_number = CurrentLevel;

	start = &savegame.start[level_number];

	/* Start by Making all Lara Meshes as Default */
//	for ( i=0;i<15;i++ )
//		lara.mesh_ptrs[i] = meshes[objects[LARA].mesh_index + i];
	for ( i=0;i<15;i++ )
		lara.mesh_ptrs[i] = meshes[objects[LARA].mesh_index + i] = meshes[objects[LARA_SKIN].mesh_index + i];

	/* Now Initialise THIGH Holsters With Guns or Not */
	switch (start->gun_type)
	{
		case LG_UNARMED:
			break;

		case LG_MAGNUMS:
			lara.mesh_ptrs[THIGH_L] = meshes[objects[MAGNUM].mesh_index + THIGH_L];
			lara.mesh_ptrs[THIGH_R] = meshes[objects[MAGNUM].mesh_index + THIGH_R];
			break;

		case LG_UZIS:
			lara.mesh_ptrs[THIGH_L] = meshes[objects[UZI].mesh_index + THIGH_L];
			lara.mesh_ptrs[THIGH_R] = meshes[objects[UZI].mesh_index + THIGH_R];
			break;

		default:
			lara.mesh_ptrs[THIGH_L] = meshes[objects[PISTOLS].mesh_index + THIGH_L];	// MESHSWAPGIBBY
			lara.mesh_ptrs[THIGH_R] = meshes[objects[PISTOLS].mesh_index + THIGH_R];
			break;
	}

	if (start->gun_type == LG_FLARE)
		lara.mesh_ptrs[HAND_L] = meshes[objects[FLARE].mesh_index + HAND_L];

	// Decide on back weapon (if any)
	switch (start->gun_type)
	{
	case LG_M16:
		lara.back_gun = M16;
		break;

	case LG_HARPOON:
		lara.back_gun = HARPOON_GUN;
		break;

	case LG_ROCKET:
		lara.back_gun = ROCKET_GUN;
		break;
	case LG_GRENADE:
		lara.back_gun = GRENADE_GUN;
		break;

	default:
		if (start->got_shotgun)
			lara.back_gun = SHOTGUN;
		else if (start->got_m16)
			lara.back_gun = M16;
		else if (start->got_rocket)
			lara.back_gun = ROCKET_GUN;
		else if (start->got_grenade)
			lara.back_gun = GRENADE_GUN;
		else if (start->got_harpoon)
			lara.back_gun = HARPOON_GUN;
	}
}

/*******************************************************************************
 *******************************************************************************
 *					Control Mode For Cheating....
 *******************************************************************************
 ******************************************************************************/

void LaraCheatGetStuff()
{
	int i;

	Inv_AddItem( M16_ITEM );
	Inv_AddItem( SHOTGUN_ITEM );
	Inv_AddItem( UZI_ITEM );
	Inv_AddItem( MAGNUM_ITEM );
	Inv_AddItem( GUN_ITEM );
	for (i=0;i<1;i++)
	{
		Inv_AddItem( FLAREBOX_ITEM );
		Inv_AddItem( MEDI_ITEM );
		Inv_AddItem( BIGMEDI_ITEM );
	}

/*	Inv_AddItem( KEY_ITEM1 );
	Inv_AddItem( KEY_ITEM2 );
	Inv_AddItem( KEY_ITEM3 );
	Inv_AddItem( KEY_ITEM4 );
	Inv_AddItem( PUZZLE_ITEM1 );
	Inv_AddItem( PUZZLE_ITEM2 );
	Inv_AddItem( PUZZLE_ITEM3 );
	Inv_AddItem( PUZZLE_ITEM4 );
	Inv_AddItem( PICKUP_ITEM1 );
	Inv_AddItem( PICKUP_ITEM2 );
*/

	lara.magnums.ammo = MAGNUM_AMMO_CLIP*50;
	lara.uzis.ammo = UZI_AMMO_CLIP*50;
	lara.shotgun.ammo = SHOTGUN_AMMO_CLIP*50;
	lara.m16.ammo = SHOTGUN_AMMO_CLIP*50;
}

#if !defined(NO_FLY_CHEAT) || defined(ALWAYS_ENABLE_DOZY_CHEAT)
sint16 cheat_hit_points;

static void LaraCheat( ITEM_INFO *item, COLL_INFO *coll )
{
	lara_item->hit_points = LARA_HITPOINTS;

	LaraUnderWater( item,coll );
	if ( input&IN_SLOW && !(input&IN_LOOK) )
	{
		lara.water_status = LARA_ABOVEWATER;			// Return to Normal Mode...
		item->frame_number = STOP_F;
		item->anim_number = STOP_A;
		item->pos.x_rot = item->pos.z_rot = 0;
		lara.torso_x_rot = lara.torso_y_rot = 0;
		lara.head_x_rot = lara.head_y_rot = 0;
		lara.gun_status = LG_ARMLESS;
		LaraInitialiseMeshes(1);
		lara.mesh_effects = 0;
		lara_item->hit_points = cheat_hit_points;
	}
}

static void LaraCheatyBits()
{
	if (!gameflow.cheat_enable && !gameflow.dozy_cheat_enabled)
		return;
	// D gets you health and weapons
	if (input & IN_D)
	{
		LaraCheatGetStuff();
		lara_item->hit_points = LARA_HITPOINTS;
	}

	// C just allows you to fly around
	if ( input&IN_C )
	{
		lara_item->pos.y_pos -= STEP_L/2;
		if ( lara.water_status!=LARA_CHEAT )
		{
			lara.water_status = LARA_CHEAT;
			lara_item->frame_number = SWIMGLIDE_F;
			lara_item->anim_number = SWIMGLIDE_A;
			lara_item->current_anim_state = AS_SWIM;
			lara_item->goal_anim_state = AS_SWIM;
			lara_item->gravity_status = 0;
			lara_item->pos.x_rot = 30*ONE_DEGREE;
			lara_item->fallspeed = 30;
			lara.air = LARA_AIR;
			lara.death_count = 0;
			lara.torso_x_rot = lara.torso_y_rot = 0;
			lara.head_x_rot = lara.head_y_rot = 0;
//##			lara.mesh_effects = 0x7fff;

			cheat_hit_points = lara_item->hit_points;
		}
	}
}
#endif

/*---------------------------------------------------------------------------
 *	Public Functions
\*--------------------------------------------------------------------------*/

void	LaraControl( sint16 item_number )
{
	int		wh,wd,hfw,room_water_state;
	ITEM_INFO	*item;

#if !defined(NO_FLY_CHEAT) || defined(ALWAYS_ENABLE_DOZY_CHEAT)
	if (gameflow.cheat_enable || gameflow.dozy_cheat_enabled)
		LaraCheatyBits();
#endif

	item = lara_item;

	lara.last_pos.x = item->pos.x_pos;
	lara.last_pos.y = item->pos.y_pos;
	lara.last_pos.z = item->pos.z_pos;

#if defined(GAMEDEBUG) && defined(PSX_VERSION)
	if (InfoFlag)
	{
		sprintf(exit_message, "%.2d %s : %d", item->current_anim_state, states[item->current_anim_state], item->anim_number);
		PrintDbug(1, 2, exit_message);
	}
#endif

/* -------- hands free fuck 'em */

	if ((lara.gun_status == LG_HANDSBUSY)
	&&  (lara_item->current_anim_state == AS_STOP)
	&&  (lara_item->goal_anim_state == AS_STOP)
	&&  (lara_item->anim_number == BREATH_A)
	&&  (lara.extra_anim == 0)
	&&  (lara_item->gravity_status == 0))
		lara.gun_status = LG_ARMLESS;

/* -------- power-up dash meter */

	if (item->current_anim_state != AS_DASH)
	{
		if (DashTimer < LARA_DASH_TIME)
			DashTimer++;
	}

	lara.IsDucked = 0;

	room_water_state = room[item->room_number].flags & (UNDERWATER|SWAMP);

#ifdef GAMEDEBUG
#ifdef PC_VERSION
//	sprintf( exit_message, "Gun: %s Req: %s State: %s",guntypes[lara.gun_type],guntypes[lara.request_gun_type],gunstates[lara.gun_status]);
//	PrintDbug(2,4, exit_message);
//	sprintf( exit_message, "WaterState: %s",waterstates[lara.water_status]);
//	PrintDbug(2,5, exit_message);
//	sprintf(exit_message, "R%d x%d y%d", lara_item->room_number, lara_item->pos.z_pos-room[lara_item->room_number].z >> WALL_SHIFT, lara_item->pos.x_pos - room[lara_item->room_number].x >> WALL_SHIFT);
//	PrintDbug(2,2,exit_message);
//	Log(exit_message);
//	Log("WaterState: %s", waterstates[lara.water_status]);
//	Log("(%d:f%d) %s G:%s (%d)", lara_item->anim_number, lara_item->frame_number-anims[lara_item->anim_number].frame_base, states[lara_item->current_anim_state], states[lara_item->goal_anim_state], lara.extra_anim);
//	Log("Speed %d f%d x%d z%d", lara_item->speed, lara_item->fallspeed, item->pos.x_pos, item->pos.z_pos);
// GF_NoFloor = 4608;
#endif
#endif

	wd = GetWaterDepth(item->pos.x_pos, item->pos.y_pos, item->pos.z_pos, item->room_number);
	wh = GetWaterHeight( item->pos.x_pos, item->pos.y_pos, item->pos.z_pos, item->room_number );

	if ( wh != NO_HEIGHT )
		hfw = item->pos.y_pos - wh;
	else
		hfw = NO_HEIGHT;
	lara.water_surface_dist = -hfw;
//Log("%s h%d d%d", waterstates[lara.water_status], hfw, wd);

	if (lara.skidoo == NO_ITEM)
		WadeSplash(item, wh, wd);

	if (lara.skidoo == NO_ITEM && !lara.extra_anim)
	{
		switch (lara.water_status)
		{
			case LARA_ABOVEWATER:
//				if (hfw==NO_HEIGHT || hfw < WADE_DEPTH)
				if (hfw==NO_HEIGHT || hfw < WADE_DEPTH || lara.skidoo != NO_ITEM)
					break;

				if (wd > SWIM_DEPTH - STEP_L && !(room_water_state & SWAMP))
				{
					if (room_water_state)
					{
	   					lara.air = LARA_AIR;
	   					lara.water_status = LARA_UNDERWATER;					// Going Into UnderWater from AboveWater
	   					item->gravity_status = 0;
	   					item->pos.y_pos += 100;
	   					UpdateLaraRoom( lara_item,0 );
						StopSoundEffect(30); // stop fastfall death scream

						if ( item->current_anim_state==AS_SWANDIVE )			// Is Lara being Cool??
	   					{
	   						item->pos.x_rot = -45*ONE_DEGREE;
	   						item->goal_anim_state = AS_DIVE;
	   						AnimateLara( item );
	   						item->fallspeed = item->fallspeed*2;
	   					}
	   					else if ( item->current_anim_state==AS_FASTDIVE )
	   					{
	   						item->pos.x_rot = -85*ONE_DEGREE;
	   						item->goal_anim_state = AS_DIVE;
	   						AnimateLara( item );
	   						item->fallspeed = item->fallspeed*2;
	   					}
	   					else
	   					{
	   						item->pos.x_rot = -45*ONE_DEGREE;
	   						item->frame_number = JUMPIN_F;
	   						item->anim_number = JUMPIN_A;
	   						item->current_anim_state = AS_DIVE;
	   						item->goal_anim_state = AS_SWIM;
	   						item->fallspeed = (item->fallspeed*3)/2;
	   					}

						lara.torso_x_rot = lara.torso_y_rot = 0;
	   					lara.head_x_rot = lara.head_y_rot = 0;
	   					Splash( lara_item );
					}
				}
				else if (hfw > WADE_DEPTH)
				{
					lara.water_status = LARA_WADE;
   			    		if (!item->gravity_status)
						item->goal_anim_state = AS_STOP;
					else if(room_water_state & SWAMP)
					{
						if (item->current_anim_state == AS_SWANDIVE || item->current_anim_state == AS_FASTDIVE)			// Is Lara swan-diving?
							item->pos.y_pos = wh+1000;

						item->goal_anim_state = AS_WADE;
						item->current_anim_state = AS_WADE;
						item->anim_number =  WADE_A;
						item->frame_number = WADE_F;
					}
				}
			break;

			case LARA_WADE:
				camera.target_elevation = -22*ONE_DEGREE;

				if (hfw < WADE_DEPTH)
				{
					// WADE to ABOVEWATER
					lara.water_status = LARA_ABOVEWATER;
					if ( item->current_anim_state==AS_WADE )
						item->goal_anim_state = AS_RUN;
				}
				else if (hfw > SWIM_DEPTH && !(room_water_state & SWAMP))
				{
					// WADE to SURFACE
  					lara.water_status = LARA_SURFACE;
  					item->pos.y_pos = item->pos.y_pos+1 - hfw;
					if (item->current_anim_state==AS_BACK)
					{
   						item->frame_number = SURFTRD2BK_F;
  						item->anim_number = SURFTRD2BK_A;
  						item->goal_anim_state = AS_SURFBACK;
  						item->current_anim_state = AS_SURFBACK;
					}
					else if ( item->current_anim_state==AS_STEPRIGHT )
					{
   						item->frame_number = SURFRIGHT_F;
  						item->anim_number = SURFRIGHT_A;
  						item->goal_anim_state = AS_SURFRIGHT;
  						item->current_anim_state = AS_SURFRIGHT;
					}
					else if ( item->current_anim_state==AS_STEPLEFT )
					{
   						item->frame_number = SURFLEFT_F;
  						item->anim_number = SURFLEFT_A;
  						item->goal_anim_state = AS_SURFLEFT;
  						item->current_anim_state = AS_SURFLEFT;
					}
					else
					{
   						item->frame_number = SURFSWIM_F;
  						item->anim_number = SURFSWIM_A;
  						item->goal_anim_state = AS_SURFSWIM;
  						item->current_anim_state = AS_SURFSWIM;
					}
					item->gravity_status = 0;
  					item->fallspeed = 0;
  					lara.dive_count = 0;
  					item->pos.x_rot = lara_item->pos.z_rot = 0;
  					lara.torso_x_rot = lara.torso_y_rot = 0;
  					lara.head_x_rot = lara.head_y_rot = 0;
  					UpdateLaraRoom( item,-LARA_HITE/2 );
				}

			break;

			case LARA_SURFACE:
				if (!room_water_state)
				{
					if (hfw > WADE_DEPTH)
					{
						lara.water_status = LARA_WADE;
						item->anim_number = BREATH_A;
						item->frame_number = BREATH_F;
						item->current_anim_state = AS_STOP;
						if (item->current_anim_state==AS_SURFBACK)
							item->goal_anim_state = AS_BACK;
						else if (item->current_anim_state==AS_SURFLEFT)
							item->goal_anim_state = AS_STEPLEFT;
						else if (item->current_anim_state==AS_SURFRIGHT)
							item->goal_anim_state = AS_STEPRIGHT;
						else
							item->goal_anim_state = AS_WADE;
						AnimateItem(item);
					}
					else
					{
						lara.water_status = LARA_ABOVEWATER;					// Directly go to AboveWater Status..
						item->frame_number = FALLDOWN_F;                   // because there is no surface!!
						item->anim_number = FALLDOWN_A;
						item->goal_anim_state = AS_FORWARDJUMP;
						item->current_anim_state = AS_FORWARDJUMP;
						item->speed = item->fallspeed/4;
						item->gravity_status = 1;
					}
					item->fallspeed = 0;
					item->pos.x_rot = lara_item->pos.z_rot = 0;        		// Dont need any rotations
					lara.torso_x_rot = lara.torso_y_rot = 0;
					lara.head_x_rot = lara.head_y_rot = 0;
				}
				break;

			case LARA_UNDERWATER:
				if (!room_water_state) // could be done on hfw<something
				{
					if (wd != NO_HEIGHT && ABS(hfw) < STEP_L)
					{
						lara.water_status = LARA_SURFACE;                  // We are now going to Surface from UnderWater
						item->pos.y_pos = item->pos.y_pos+1 - hfw;
						item->frame_number = SURFTREAD_F;
						item->anim_number = SURFTREAD_A;
						item->goal_anim_state = AS_SURFTREAD;
						item->current_anim_state = AS_SURFTREAD;
						item->fallspeed = 0;
						lara.dive_count = DIVE_COUNT+1;					   // Counter before DiveAnim invoked
						item->pos.x_rot = lara_item->pos.z_rot = 0;        // Dont need any rotations
						lara.torso_x_rot = lara.torso_y_rot = 0;
						lara.head_x_rot = lara.head_y_rot = 0;
						UpdateLaraRoom( item,-LARA_HITE/2 );
		  				SoundEffect(36, &lara_item->pos, SFX_ALWAYS);
					}
					else
					{
						lara.water_status = LARA_ABOVEWATER;               // Directly go to AboveWater status
						item->frame_number = FALLDOWN_F;                   // because there is no surface!!
						item->anim_number = FALLDOWN_A;
						item->goal_anim_state = AS_FORWARDJUMP;
						item->current_anim_state = AS_FORWARDJUMP;
						item->speed = item->fallspeed/4;
						item->gravity_status = 1;
						item->fallspeed = 0;
						item->pos.x_rot = lara_item->pos.z_rot = 0;        // Dont need any rotations
						lara.torso_x_rot = lara.torso_y_rot = 0;
						lara.head_x_rot = lara.head_y_rot = 0;
					}
				}
				break;
		}
	}


	S_SetReverbType(room[item->room_number].ReverbType);


//Log("After %s", waterstates[lara.water_status]);

	if ( item->hit_points<=0 )
	{
		item->hit_points = -1;
		if ( !lara.death_count )
			S_CDStop();
		lara.death_count++;

		// Lara blown to bits?
		if (lara_item->flags & ONESHOT)
		{
			lara.death_count++; // speed it along
			return;
		}
	}
	else if (GF_NoFloor && item->pos.y_pos >= GF_NoFloor)
	{
		item->hit_points = -1;
		lara.death_count = 9*30;
	}

/* -------- call appropriate controller */

	switch (lara.water_status)
	{
	/* ----------------------- */
		case LARA_WADE:
		case LARA_ABOVEWATER:
	/* ----------------------- */
			if ((room[item->room_number].flags & SWAMP)
			&&  (lara.water_surface_dist < -775))
			{
				if (item->hit_points >= 0)
				{
					lara.air-=6;

					if (lara.air < 0)
					{
						lara.air = -1;
						item->hit_points -= 10;
					}
				}
			}
			else if ((lara.skidoo == NO_ITEM)
				&&  (items[lara.skidoo].object_number != UPV))
					lara.air = LARA_AIR;

			LaraAboveWater(item, coll);

			if ((CurrentLevel == LV_ANTARC)
			||  (CurrentLevel == LV_MINES))
			{
				if (lara.water_status == LARA_WADE)
					ExposureMeter -= LARA_WADE_EXPOSURE;
				else
					if ((ExposureMeter += LARA_HEAT_EXPOSURE) > LARA_EXPOSURE_TIME)
						ExposureMeter = LARA_EXPOSURE_TIME;
			}

			break;
	/* ----------------------- */
		case LARA_UNDERWATER:
	/* ----------------------- */
			if (item->hit_points >= 0)
			{
				lara.air--;

				if (lara.air < 0)
				{
					lara.air = -1;
					item->hit_points -= 5;
				}
			}

			LaraUnderWater(item, coll);

			if ((CurrentLevel == LV_ANTARC)
			||  (CurrentLevel == LV_MINES))
				ExposureMeter -= LARA_SWIM_EXPOSURE;

			break;
	/* ----------------------- */
		case LARA_SURFACE:
	/* ----------------------- */
			if (item->hit_points >= 0)
			{
				lara.air+=10;

				if (lara.air > LARA_AIR)
					lara.air = LARA_AIR;
			}

			LaraSurface(item, coll);

			if ((CurrentLevel == LV_ANTARC)
			||  (CurrentLevel == LV_MINES))
				ExposureMeter -= LARA_WADE_EXPOSURE;

			break;
	/* ----------------------- */
		case LARA_CHEAT:
	/* ----------------------- */
#if !defined(NO_FLY_CHEAT) || defined(ALWAYS_ENABLE_DOZY_CHEAT)
			if (gameflow.cheat_enable || gameflow.dozy_cheat_enabled)
				LaraCheat( item,coll );
#endif
		break;
	}

	if (ExposureMeter < 0)
	{
		ExposureMeter = -1;
		item->hit_points -= 10;
	}

	/* Tot up how far Lara has moved since the last frame */
	savegame.distance_travelled += phd_sqrt(SQUARE(item->pos.x_pos - lara.last_pos.x) + SQUARE(item->pos.y_pos - lara.last_pos.y) + SQUARE(item->pos.z_pos - lara.last_pos.z));
}

/*****************************************************************************
 *		Swap All Laras Meshes with LARA_EXTRA
 ****************************************************************************/
void	LaraSwapMeshExtra( void )
{
	int		i;

	if ( objects[LARA_EXTRA].loaded )
	{
		for ( i=0;i<15;i++ )						// initialise Mesh pointers..
			lara.mesh_ptrs[i] = meshes[objects[LARA_EXTRA].mesh_index + i];
	}
}

/******************************************************************************
 *							Animate Lara
 *****************************************************************************/
void	AnimateLara( ITEM_INFO *item )
{
	int 		i;
	ANIM_STRUCT *anim;
	sint16 		*command;
	sint32 		speed;
	uint16		type, num;

	item->frame_number++;											// Inc Frame number
	anim = &anims[item->anim_number];

	/* Check for animation transitions */
	if (anim->number_changes > 0)
	{
		if (GetChange(item, anim))
		{
			anim = &anims[item->anim_number];
			item->current_anim_state = anim->current_anim_state;
		}
	}

	if (item->frame_number > anim->frame_end)						// If at end of Anim
	{
		if (anim->number_commands > 0)								// Do any Commands
		{
			command = &commands[anim->command_index];
			for (i=anim->number_commands; i>0; i--)
			{
				switch ( *(command++) )
				{
				case COMMAND_MOVE_ORIGIN:
					TranslateItem(item, (sint32)*(command), (sint32)*(command+1), (sint32)*(command+2));
					command += 3;
					break;

				case COMMAND_JUMP_VELOCITY:
					item->fallspeed = *(command++);					// Get Upward Velocity
					item->speed = *(command++);         			// Get Forward Velocity
					item->gravity_status = 1;           			// turn gravity ON
					if ( lara.calc_fallspeed )                      // If Upward velocity is  Pre-Calculated
					{
						item->fallspeed = lara.calc_fallspeed;      // then use that Value instead..
						lara.calc_fallspeed = 0;
					}
					break;

				case COMMAND_ATTACK_READY:
					if ( lara.gun_status!=LG_SPECIAL )
						lara.gun_status = LG_ARMLESS;
					break;

				case COMMAND_DEACTIVATE:
					break;

				case COMMAND_SOUND_FX:
				case COMMAND_EFFECT:
					command += 2;
					break;
				}
			}
		}

		/* Update animation information */
		item->anim_number = anim->jump_anim_num;
		item->frame_number = anim->jump_frame_num;

		anim = &anims[item->anim_number];
		item->current_anim_state = anim->current_anim_state;
	}

	/* Do any sound FX or Effect commands */
	if (anim->number_commands > 0)
	{
		command = &commands[anim->command_index];
		for (i=anim->number_commands; i>0; i--)
		{
			switch ( *(command++) )
			{
				case COMMAND_MOVE_ORIGIN:
					command += 3;
				break;

				case COMMAND_JUMP_VELOCITY:
					command += 2;
				break;

				case COMMAND_ATTACK_READY:
				case COMMAND_DEACTIVATE:
				break;

				case COMMAND_SOUND_FX:
					if ( item->frame_number==*(command) )
					{
						type = *(command+1)&0xc000;
						if ( type==SFX_LANDANDWATER ||
							(type==SFX_LANDONLY && (lara.water_surface_dist>=0 || lara.water_surface_dist==NO_HEIGHT)) ||
							(type==SFX_WATERONLY && lara.water_surface_dist<0 && lara.water_surface_dist!=NO_HEIGHT && !(room[lara_item->room_number].flags & SWAMP)) )
						{
							num = *(command+1)&0x3fff;
							SoundEffect( (int)num,&item->pos,SFX_ALWAYS );
						}
					}
					command += 2;
				break;

				case COMMAND_EFFECT:
					if (item->frame_number == *(command))
					{
						FXType = command[1] & 0xc000;
						num = *(command+1)&0x3fff;
						(*effect_routines[(int)num])( item );
					}
					command += 2;
/*
					if ( item->frame_number==*(command) )
					{
						type = *(command+1)&0xc000;
						if ( type==SFX_LANDANDWATER ||
							(type==SFX_LANDONLY && (lara.water_surface_dist>=0 || lara.water_surface_dist==NO_HEIGHT)) ||
							(type==SFX_WATERONLY && lara.water_surface_dist<0) )
						{
							num = *(command+1)&0x3fff;
							(*effect_routines[(int)num])( item );
						}
					}
					command += 2;
*/
				break;
			}
		}
	}

	if ( !item->gravity_status ) 					// Calculate absolute new velocities
	{                                               // if on the Ground...
		if (lara.water_status==LARA_WADE && (room[item->room_number].flags & SWAMP))
		{
			speed = anim->velocity>>1;
			if ( anim->acceleration )
				speed += (anim->acceleration * (item->frame_number - anim->frame_base))>>2;
			item->speed = (sint16)(speed >> 16);
		}
		else
		{
			speed = anim->velocity;
			if ( anim->acceleration )
				speed += anim->acceleration * (item->frame_number - anim->frame_base);
			item->speed = (sint16)(speed >> 16);
		}
	}
	else                                            // If gravity ON
	{                                               // do Up/down movement
		if (room[item->room_number].flags & SWAMP)
		{
			item->speed -= item->speed>>3;
			if (abs(item->speed)<8)
			{
				item->speed = 0;
				item->gravity_status = 0;
			}
			if (item->fallspeed > 128)
				item->fallspeed >>= 1;
			item->fallspeed -= item->fallspeed>>2;
			if (item->fallspeed < 4)
				item->fallspeed = 4;
			item->pos.y_pos += item->fallspeed;
		}
		else
		{
			speed = anim->velocity + anim->acceleration * (item->frame_number - anim->frame_base - 1);
			item->speed -= (sint16)(speed>>16);
			speed += anim->acceleration;
			item->speed += (sint16)(speed>>16);
			item->fallspeed += (item->fallspeed<FASTFALL_SPEED) ? GRAVITY : 1;
			item->pos.y_pos += item->fallspeed;
		}
	}
	item->pos.x_pos += (phd_sin(lara.move_angle) * item->speed) >> W2V_SHIFT;
	item->pos.z_pos += (phd_cos(lara.move_angle) * item->speed) >> W2V_SHIFT;
}


/*****************************************************************************
 *				Use Item from Inventory...
 ****************************************************************************/
void	UseItem( sint16 object_num )
{
	if ( object_num<0 || object_num>=NUMBER_OBJECTS )
		return;
	switch ( object_num )
	{
		case GUN_ITEM:
		case GUN_OPTION:
			lara.request_gun_type = LG_PISTOLS;
		break;

		case MAGNUM_ITEM:
		case MAGNUM_OPTION:
			lara.request_gun_type = LG_MAGNUMS;
		break;

		case UZI_ITEM:
		case UZI_OPTION:
			lara.request_gun_type = LG_UZIS;
		break;

		case SHOTGUN_ITEM:
		case SHOTGUN_OPTION:
			lara.request_gun_type = LG_SHOTGUN;
		break;

		case HARPOON_ITEM:
		case HARPOON_OPTION:
			lara.request_gun_type = LG_HARPOON;
		break;

		case M16_ITEM:
		case M16_OPTION:
			lara.request_gun_type = LG_M16;
		break;

		case ROCKET_GUN_ITEM:
		case ROCKET_OPTION:
			lara.request_gun_type = LG_ROCKET;
		break;

		case GRENADE_GUN_ITEM:
		case GRENADE_OPTION:
			lara.request_gun_type = LG_GRENADE;
		break;

		case FLAREBOX_ITEM:
		case FLAREBOX_OPTION:
			lara.request_gun_type = LG_FLARE;
//			Inv_RemoveItem( FLAREBOX_ITEM );
		break;

		case MEDI_ITEM:
		case MEDI_OPTION:
			if ( (lara_item->hit_points>0 && lara_item->hit_points<LARA_HITPOINTS) || lara.poisoned)
			{
				lara.poisoned = 0;
				lara_item->hit_points += LARA_HITPOINTS/2;
				if ( lara_item->hit_points>LARA_HITPOINTS )
					lara_item->hit_points = LARA_HITPOINTS;
				Inv_RemoveItem( MEDI_ITEM );
		    		SoundEffect(116, NULL, SFX_ALWAYS);
				savegame.health_used++;
			}
		break;

		case BIGMEDI_ITEM:
		case BIGMEDI_OPTION:
			if ( (lara_item->hit_points>0 && lara_item->hit_points<LARA_HITPOINTS) || lara.poisoned)
			{
				lara.poisoned = 0;
				lara_item->hit_points += LARA_HITPOINTS;
				if ( lara_item->hit_points>LARA_HITPOINTS )
					lara_item->hit_points = LARA_HITPOINTS;
				Inv_RemoveItem( BIGMEDI_ITEM );
		    		SoundEffect(116, NULL, SFX_ALWAYS);
				savegame.health_used+=2;
			}
		break;

		default:
		break;
	}
}

/******************************************************************************
 *			Control Lara Extra Used for Deaths etc etc
 *****************************************************************************/
void	ControlLaraExtra( sint16 item_num )
{
		AnimateItem(&items[item_num]);
}


/******************************************************************************
 *				initialise lara dummy routine
 *****************************************************************************/
//##	#ifdef PSX_VERSION
#if 0
	extern sint32	gym_save_x, gym_save_y, gym_save_z, gym_save_r, gym_save_yr;
#endif

void	InitialiseLaraLoad( sint16 item_num )
{
	lara.item_number = item_num;
	lara_item = &items[item_num];

//##	#ifdef PSX_VERSION
#if 0
	if (CurrentLevel==LV_GYM)
	{
		gym_save_x = lara_item->pos.x_pos;
		gym_save_y = lara_item->pos.y_pos;
		gym_save_z = lara_item->pos.z_pos;
		gym_save_yr = lara_item->pos.y_rot;
		gym_save_r = lara_item->room_number;
	}
#endif

#ifdef PC_VERSION
	Log(LT_Info,"Lara Loaded!!!");
#endif
}


/******************************************************************************
 *			Initialise Lara for this Particular Level
 *****************************************************************************/
void	InitialiseLara( int type )
{
	ITEM_INFO	*item;
	int	i;

	item = lara_item;
	item->data = (void *)&lara;
	item->collidable = 0;
	item->hit_points = LARA_HITPOINTS;

	lara.calc_fallspeed = 0;
	lara.climb_status = 0;
	lara.pose_count = 0;
	lara.hit_frame = 0;
	lara.hit_direction = -1;
	lara.air = LARA_AIR;						// Start with full Oxygen please
	lara.dive_count = 0;
	lara.death_count = 0;
	lara.current_active = 0;
	lara.spaz_effect_count = 0;
	lara.flare_age = 0;
	lara.skidoo = NO_ITEM;
	lara.weapon_item = NO_ITEM;
	lara.back_gun = 0;
	lara.flare_frame = 0;
	lara.flare_control_left = lara.flare_control_right = 0;
	lara.extra_anim = 0;
	lara.look = 1;
	lara.burn = 0;
	lara.BurnGreen = 0;
	lara.water_surface_dist = 100;
	lara.last_pos.x = item->pos.x_pos;
	lara.last_pos.y = item->pos.y_pos;
	lara.last_pos.z = item->pos.z_pos;
	lara.spaz_effect = NULL;
	lara.mesh_effects = 0;
	lara.target = NULL;
	lara.turn_rate = 0;
	lara.move_angle = 0;
	lara.head_x_rot = lara.head_y_rot = lara.head_z_rot = 0;
	lara.torso_x_rot = lara.torso_y_rot = lara.torso_z_rot = 0;
	lara.left_arm.flash_gun = lara.right_arm.flash_gun = 0;
	lara.left_arm.lock = lara.right_arm.lock = 0;
	lara.poisoned = 0;
	lara.creature = NULL;
	lara.electric = 0;

	/* Setup initial Animation status according to where she is */
	if (type==IL_NORMAL && GF_LaraStartAnim)
	{
		lara.water_status = LARA_ABOVEWATER;
		lara.gun_status = LG_HANDSBUSY;
		item->anim_number = objects[LARA_EXTRA].anim_index;
		item->frame_number = anims[item->anim_number].frame_base;
		item->current_anim_state = EXTRA_BREATH;
		item->goal_anim_state = (sint16)GF_LaraStartAnim;
		AnimateLara(item);
		lara.extra_anim = 1;

		/* Do cinematic camera */
		camera.type = CINEMATIC_CAMERA;
		cine_frame = 0;
		S_MemCpy(&cinematic_pos, &item->pos, sizeof(PHD_3DPOS));
	}
	else if (room[item->room_number].flags & UNDERWATER)
	{
		lara.water_status = LARA_UNDERWATER;
		item->fallspeed = 0;
		item->goal_anim_state = AS_TREAD;
		item->current_anim_state = AS_TREAD;
		item->anim_number = TREAD_A;
		item->frame_number = TREAD_F;

	}
	else
	{
		lara.water_status = LARA_ABOVEWATER;
		item->goal_anim_state = AS_STOP;
		item->current_anim_state = AS_STOP;
		item->anim_number = STOP_A;
		item->frame_number = STOP_F;
	}

	if (type==IL_CUTSCENE)
	{
		sint16 *temp;

		for ( i=0;i<15;i++ )
			lara.mesh_ptrs[i] = meshes[objects[LARA].mesh_index + i] = meshes[objects[LARA_SKIN].mesh_index + i];

		temp = lara.mesh_ptrs[THIGH_L];
		lara.mesh_ptrs[THIGH_L] = meshes[objects[PISTOLS].mesh_index + THIGH_L];
		meshes[objects[PISTOLS].mesh_index + THIGH_L] = temp;

		temp = lara.mesh_ptrs[THIGH_R];
		lara.mesh_ptrs[THIGH_R] = meshes[objects[PISTOLS].mesh_index + THIGH_R];
		meshes[objects[PISTOLS].mesh_index + THIGH_R] = temp;
		lara.gun_status = LG_ARMLESS;
	}
	else
		InitialiseLaraInventory(CurrentLevel);

	DashTimer = LARA_DASH_TIME;
	ExposureMeter = LARA_EXPOSURE_TIME;

#ifdef PC_VERSION
	Log(LT_Info,"Lara Initialised!!!");
#endif
}


void InitialiseLaraInventory(int level_number)
{
	int i, ammo;
	START_INFO *start;

#if defined(PSX_VERSION) && defined(GAMEDEBUG)
	printf(__FUNCTION__"\n");
#endif

	Inv_RemoveAllItems();						// Remove all old items from Inventry...

	start = &savegame.start[level_number];

	if ( GF_RemoveWeapons )
	{
		start->got_pistols = start->got_magnums = start->got_uzis = start->got_shotgun = start->got_m16 = start->got_rocket = start->got_grenade = start->got_harpoon = 0;
		start->gun_type = LG_UNARMED;
		start->gun_status = LG_ARMLESS;
		GF_RemoveWeapons = 0;
	}

	if ( GF_RemoveAmmo )
	{
		start->pistol_ammo = start->magnum_ammo = start->uzi_ammo = start->shotgun_ammo = start->harpoon_ammo = start->rocket_ammo = start->grenade_ammo = start->m16_ammo = start->harpoon_ammo = 0;
		start->num_big_medis = start->num_flares = 0;
		start->num_medis = 1;	// ## Chris did this for Compound
		GF_RemoveAmmo = 0;
	}

	Inv_AddItem( MAP_CLOSED );

	/* Initialise Pistols Now got Infinite Ammo */
	lara.pistols.ammo = 1000;
	if ( start->got_pistols )
		Inv_AddItem( GUN_ITEM );

	/* Initialise Magnums */
	if ( start->got_magnums )
	{
		Inv_AddItem( MAGNUM_ITEM );
		lara.magnums.ammo = start->magnum_ammo;
		GlobalItemReplace( MAGNUM_ITEM, MAG_AMMO_ITEM );
	}
	else
	{
		ammo = start->magnum_ammo/MAGNUM_AMMO_QTY;
		for ( i=0;i<ammo;i++ )
			Inv_AddItem( MAG_AMMO_ITEM );
		lara.magnums.ammo = 0;
	}

	/* Initialise Uzis */
	if ( start->got_uzis )
	{
		Inv_AddItem( UZI_ITEM );
		lara.uzis.ammo = start->uzi_ammo;
		GlobalItemReplace( UZI_ITEM, UZI_AMMO_ITEM );
	}
	else
	{
		ammo = start->uzi_ammo/UZI_AMMO_QTY;
		for ( i=0;i<ammo;i++ )
			Inv_AddItem( UZI_AMMO_ITEM );
		lara.uzis.ammo = 0;
	}

	/* Initialise Shotgun */
	if ( start->got_shotgun )
	{
		Inv_AddItem( SHOTGUN_ITEM );
		lara.shotgun.ammo = start->shotgun_ammo;
		GlobalItemReplace( SHOTGUN_ITEM, SG_AMMO_ITEM );
	}
	else
	{
		ammo = start->shotgun_ammo/SHOTGUN_AMMO_QTY;
		for ( i=0;i<ammo;i++ )
			Inv_AddItem( SG_AMMO_ITEM );
		lara.shotgun.ammo = 0;
	}

	/* Initialise Rocket */
	if ( start->got_rocket )
	{
		Inv_AddItem( ROCKET_GUN_ITEM );
		lara.rocket.ammo = start->rocket_ammo;
		GlobalItemReplace( ROCKET_GUN_ITEM, ROCKET_AMMO_ITEM );
	}
	else
	{
		ammo = start->rocket_ammo/ROCKET_AMMO_QTY;
		for ( i=0;i<ammo;i++ )
			Inv_AddItem( ROCKET_AMMO_ITEM );
		lara.rocket.ammo = 0;
	}

	/* Initialise Grenade */
	if ( start->got_grenade )
	{
		Inv_AddItem( GRENADE_GUN_ITEM );
		lara.grenade.ammo = start->grenade_ammo;
		GlobalItemReplace( GRENADE_GUN_ITEM, GRENADE_AMMO_ITEM );
	}
	else
	{
		ammo = start->grenade_ammo/GRENADE_AMMO_QTY;
		for ( i=0;i<ammo;i++ )
			Inv_AddItem( GRENADE_AMMO_ITEM );
		lara.grenade.ammo = 0;
	}

	/* Initialise M16 */
	if ( start->got_m16 )
	{
		Inv_AddItem( M16_ITEM );
		lara.m16.ammo = start->m16_ammo;
		GlobalItemReplace( M16_ITEM, M16_AMMO_ITEM );
	}
	else
	{
		ammo = start->m16_ammo/M16_AMMO_QTY;
		for ( i=0;i<ammo;i++ )
			Inv_AddItem( M16_AMMO_ITEM );
		lara.m16.ammo = 0;
	}

	/* Initialise Harpoon */
	if ( start->got_harpoon )
	{
		Inv_AddItem( HARPOON_ITEM );
		lara.harpoon.ammo = start->harpoon_ammo;
		GlobalItemReplace( HARPOON_ITEM, HARPOON_AMMO_ITEM );
	}
	else
	{
		lara.harpoon.ammo = 0;
		ammo = start->harpoon_ammo/HARPOON_AMMO_QTY;
		for ( i=0;i<ammo;i++ )
		{
			if (i==0)
				Inv_AddItem( HARPOON_AMMO_ITEM );
			lara.harpoon.ammo += HARPOON_AMMO_QTY;
		}
	}

	/* Initialise Flares */
	for (i=start->num_flares; i>0;i--)
		Inv_AddItem( FLARE_ITEM );

	for (i=start->num_medis; i>0; i--)
		Inv_AddItem( MEDI_ITEM );

	for (i=start->num_big_medis; i>0; i--)
		Inv_AddItem( BIGMEDI_ITEM );

	for (i=start->num_sgcrystals; i>0; i--)
		Inv_AddItem( SAVEGAME_CRYSTAL_ITEM );

/* -------- initialise icons */

	if (start->num_icon1)
		Inv_AddItem(ICON_PICKUP1_ITEM);

	if (start->num_icon2)
		Inv_AddItem(ICON_PICKUP2_ITEM);

	if (start->num_icon3)
		Inv_AddItem(ICON_PICKUP3_ITEM);

	if (start->num_icon4)
		Inv_AddItem(ICON_PICKUP4_ITEM);

	//lara.gun_status = start->gun_status;
	lara.gun_status = LG_ARMLESS;
	lara.request_gun_type = lara.gun_type = lara.last_gun_type = start->gun_type;	// Initialise Current Weapon...
#ifdef PC_VERSION
	Log(LT_Info,"Lara Gun type = %d",lara.gun_type);
#endif
	LaraInitialiseMeshes(level_number);                     	// Initialise Lara Meshes..
	InitialiseNewWeapon();
#ifdef INVINCABLE_LARA
		Inv_AddItem( HARPOON_ITEM );
		Inv_AddItem( M16_ITEM );
		Inv_AddItem( ROCKET_GUN_ITEM );
		Inv_AddItem( GRENADE_GUN_ITEM );
		Inv_AddItem( SHOTGUN_ITEM );
		Inv_AddItem( UZI_ITEM );
		Inv_AddItem( MAGNUM_ITEM );
		Inv_AddItem( GUN_ITEM );
		for (i=0;i<50;i++)
			Inv_AddItem( FLAREBOX_ITEM );
		lara.pistols.ammo = GUN_AMMO_CLIP*50;
		lara.magnums.ammo = MAGNUM_AMMO_CLIP*50;
		lara.uzis.ammo = UZI_AMMO_CLIP*50;
		lara.shotgun.ammo = SHOTGUN_AMMO_CLIP*50;
		lara.harpoon.ammo = HARPOON_AMMO_CLIP*50;
		lara.m16.ammo = M16_AMMO_CLIP*50;
		lara.rocket.ammo = ROCKET_AMMO_CLIP*50;
		lara.grenade.ammo = GRENADE_AMMO_CLIP*50;
#endif
}

/***************************************************************************
 *  Jump Tables for Lara Control depending on current anim state....
 ***************************************************************************/
void	(*lara_control_routines[])() = {
		lara_as_walk,
		lara_as_run,
		lara_as_stop,
		lara_as_forwardjump,
		lara_as_pose,
		lara_as_fastback,
		lara_as_turn_r,
		lara_as_turn_l,
		lara_as_death,
		lara_as_fastfall,
		lara_as_hang,
		lara_as_reach,
		lara_as_splat,
		lara_as_tread,
		lara_as_land,
		lara_as_compress,
		lara_as_back,
		lara_as_swim,
		lara_as_glide,
		lara_as_null,
		lara_as_fastturn,
		lara_as_stepright,
		lara_as_stepleft,
		lara_as_roll2,
		lara_as_slide,
		lara_as_backjump,
		lara_as_rightjump,
		lara_as_leftjump,
		lara_as_upjump,
		lara_as_fallback,
		lara_as_hangleft,
		lara_as_hangright,
		lara_as_slideback,
		lara_as_surftread,
		lara_as_surfswim,
		lara_as_dive,
		lara_as_pushblock,
		lara_as_pullblock,
		lara_as_ppready,
		lara_as_pickup,
		lara_as_switchon,
		lara_as_switchoff,
		lara_as_usekey,
		lara_as_usepuzzle,
		lara_as_uwdeath,
		lara_as_roll,
		lara_as_special,
		lara_as_surfback,
		lara_as_surfleft,
		lara_as_surfright,
		lara_as_usemidas,
		lara_as_diemidas,
		lara_as_swandive,
		lara_as_fastdive,
		lara_as_gymnast,
		lara_as_waterout,
		lara_as_climbstnc,
		lara_as_climbing,
		lara_as_climbleft,
		lara_as_climbend,
		lara_as_climbright,
		lara_as_climbdown,
		lara_as_laratest1,
		lara_as_laratest2,
		lara_as_laratest3,
		lara_as_wade,
		lara_as_waterroll,
		lara_as_pickupflare,
		lara_as_twist,
		lara_as_kick,
		lara_as_deathslide,
		lara_as_duck,
		lara_as_duck,	// roll
		lara_as_dash,
		lara_as_dashdive,
		lara_as_hang2,
		lara_as_monkeyswing,
		lara_as_monkeyl,
		lara_as_monkeyr,
		lara_as_monkey180,
		lara_as_all4s,
		lara_as_crawl,
		lara_as_hangturnl,
		lara_as_hangturnr,
		lara_as_all4turnl,
		lara_as_all4turnr,
		lara_as_crawlb,
		lara_void_func,
		lara_void_func
};

void (*extra_control_routines[])() = {
		extra_as_breath,
		extra_as_plunger,
		extra_as_yetikill,
		extra_as_sharkkill,
		extra_as_airlock,
		extra_as_gongbong,
		extra_as_dinokill,
		extra_as_pulldagger,
		extra_as_startanim,
		extra_as_starthouse,
		extra_as_finalanim,
		extra_as_trainkill,
		extra_as_rapidsdrown
};

void	(*lara_collision_routines[])() = {
		lara_col_walk,
		lara_col_run,
		lara_col_stop,
		lara_col_forwardjump,
		lara_col_pose,
		lara_col_fastback,
		lara_col_turn_r,
		lara_col_turn_l,
		lara_col_death,
		lara_col_fastfall,
		lara_col_hang,
		lara_col_reach,
		lara_col_splat,
		lara_col_tread,
		lara_col_land,
		lara_col_compress,
		lara_col_back,
		lara_col_swim,
		lara_col_glide,
		lara_col_null,
		lara_col_fastturn,
		lara_col_stepright,
		lara_col_stepleft,
		lara_col_roll2,
		lara_col_slide,
		lara_col_backjump,
		lara_col_rightjump,
		lara_col_leftjump,
		lara_col_upjump,
		lara_col_fallback,
		lara_col_hangleft,
		lara_col_hangright,
		lara_col_slideback,
		lara_col_surftread,
		lara_col_surfswim,
		lara_col_dive,
		lara_col_pushblock,
		lara_col_pullblock,
		lara_col_ppready,
		lara_col_pickup,
		lara_col_switchon,
		lara_col_switchoff,
		lara_col_usekey,
		lara_col_usepuzzle,
		lara_col_uwdeath,
		lara_col_roll,
		lara_col_special,
		lara_col_surfback,
		lara_col_surfleft,
		lara_col_surfright,
		lara_col_usemidas,
		lara_col_diemidas,
		lara_col_swandive,
		lara_col_fastdive,
		lara_col_gymnast,
		lara_col_waterout,
		lara_col_climbstnc,
		lara_col_climbing,
		lara_col_climbleft,
		lara_col_climbend,
		lara_col_climbright,
		lara_col_climbdown,
		lara_col_laratest1,
		lara_col_laratest2,
		lara_col_laratest3,
		lara_col_wade,
		lara_col_waterroll,
		lara_col_pickup,
		lara_col_twist,
		lara_col_kick,
		lara_col_deathslide,
		lara_col_duck,
		lara_col_duck,	// roll
		lara_col_dash,
		lara_col_dashdive,
		lara_col_hang2,
		lara_col_monkeyswing,
		lara_col_monkeyl,
		lara_col_monkeyr,
		lara_col_monkey180,
		lara_col_all4s,
		lara_col_crawl,
		lara_col_hangturnlr,
		lara_col_hangturnlr,
		lara_col_all4turnl,
		lara_col_all4turnr,
		lara_col_crawlb,
		lara_void_func,
		lara_col_crawl2hang
};

