/***********************************************************************************************************/
/*                                                                                                         */
/* General Lara Control                                                                                    */
/*                                                                                                         */
/***********************************************************************************************************/

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

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

#include "objects.h"
#include "lara.h"
#include "laraanim.h"
#include "camera.h"
#include "control.h"
#include "input.h"
#include "sound.h"
#include "invfunc.h"
#include "inventry.h"
#include "laramisc.h"
#include "larafunc.h"
#include "effect2.h"
#include "sphere.h"
#include "skidoo.h"
#include "quadbike.h"
#include "minecart.h"
#include "kayak.h"
#include "sub.h"
#include "biggun.h"

extern uchar 	LaraOnPad;		// For House level.

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

#define CAM_A_HANG 	0
#define CAM_E_HANG 	-60*ONE_DEGREE

#define HANG_ANGLE  (35*ONE_DEGREE)

#define DAMAGE_START  140
#define DAMAGE_LENGTH 14

#define MAX_HEAD_ROTATION	(44*ONE_DEGREE)		// Look Around Limits
#define MAX_HEAD_TILT		(30*ONE_DEGREE)
#define MIN_HEAD_TILT		(-35*ONE_DEGREE)
#define HEAD_TURN			(2*ONE_DEGREE)

#define SLOPE_DIF 60	// Maximum slope that can be vaulted etc..

#define BAD_JUMP_CEILING	((STEP_L*3)/4)		// 3/4  of a Step

#define LARA_DEF_ADD_EDGE	(5*ONE_DEGREE)

#define SWAMP_GRAVITY		2

#define VAULT_ANGLE	(30*ONE_DEGREE)

/* -------- duck/crawl defines */

#define LARA_DUCK_HEIGHT		400
#define LARA_DUCK_DEFLECT	(2*ONE_DEGREE)
#define LARA_CRAWLB_RAD		250

/* -------- dash defines */

#define LARA_DASH_LEAN_RATE	((ONE_DEGREE/2) + LARA_LEAN_UNDO)
#define LARA_DASH_LEAN_MAX	((ONE_DEGREE*15) + LARA_LEAN_UNDO)
#define LARA_DASH_TURN_RATE	((ONE_DEGREE/4) + LARA_TURN_UNDO)
#define LARA_DASH_TURN_MAX	((ONE_DEGREE*2) + LARA_TURN_UNDO)

/* -------- monkey-swing defines */

#define LARA_MONKEY_TURN_RATE	((ONE_DEGREE/4) + LARA_TURN_UNDO)
#define LARA_MONKEY_TURN_MAX	((ONE_DEGREE*2) + LARA_TURN_UNDO)


#ifdef PC_VERSION
//#define PC_JOYSTICK
#endif

#define DEATH_SPEED 100
#define DEATH_ACC   5

enum death_anims {
	DEATH_EMPTY,
	DEATH_GRAB,
	DEATH_HANG
};

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

//extern void S_StartSyncedAudio(int nTrack);

extern char *clmb_txt[];
extern int LaraTestClimbPos(ITEM_INFO *, int, int, int, int, int *);

extern int level_complete;

#ifdef PSX_VERSION
extern sint32 LaraLookX;
extern sint32 LaraLookY;
#endif

extern char exit_message[];

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

LARA_INFO lara;
ITEM_INFO *lara_item;

int health_bar_timer=0;

uint16 DashTimer;

/* -------- Lara's absolute joint position table */

char GotJointPos[15];
char IsJointUnderwater[15];

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

static sint16 DeathSlideBounds[12] = {-256,256,-100,100,WALL_L/2-256,WALL_L/2, 0,0,-25*ONE_DEGREE,25*ONE_DEGREE,0,0};
static PHD_VECTOR DeathSlidePosition = {0,0,WALL_L/2-141};

/*---------------------------------------------------------------------------
 * Macros
\*--------------------------------------------------------------------------*/

#define FASTFALL_FRICTION	item->speed = (item->speed*95)/100

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

int LaraLandedBad(ITEM_INFO *item, COLL_INFO *coll);
int LaraHitCeiling(ITEM_INFO *item, COLL_INFO *coll);
int GetStaticObjects( ITEM_INFO *item, PHD_ANGLE ang, sint32 hite, sint32 radius, sint32 dist );
sint16 LaraFloorFront(ITEM_INFO *item, PHD_ANGLE ang, sint32 dist);
sint16 LaraCeilingFront(ITEM_INFO *item, PHD_ANGLE ang, sint32 dist);
int LaraFallen(ITEM_INFO *item, COLL_INFO *coll);
int LaraTestEdgeCatch( ITEM_INFO *item, COLL_INFO *coll, sint32 *edge );
int LaraDeflectEdge( ITEM_INFO *item, COLL_INFO *coll );


/****************************************************************************
* LaraDeflectEdgeDuck
*
* SYNOPSIS
*	int LaraDeflectEdgeDuck(ITEM_INFO *item, COLL_INFO *coll)
*
* PURPOSE
*	Determines whether Lara has collided with a wall
*
* INPUTS
*	item		= ptr to item structure
*	coll		= ptr to collision structure
*
* RETURNS
*	1 if Lara has hit a wall head-on
*/
static int LaraDeflectEdgeDuck(ITEM_INFO *item, COLL_INFO *coll)
{
	if ((coll->coll_type == COLL_FRONT)
	||  (coll->coll_type == COLL_TOPFRONT))
	{
		ShiftItem(item, coll);
		item->speed = 0;
		item->gravity_status = 0;
		return 1;
	}

	else if (coll->coll_type == COLL_LEFT)
	{
		ShiftItem(item, coll);
		item->pos.y_rot += LARA_DUCK_DEFLECT;
	}

	else if (coll->coll_type == COLL_RIGHT)
	{
		ShiftItem(item, coll);
		item->pos.y_rot -= LARA_DUCK_DEFLECT;
	}

//	else if (coll->coll_type)
//		printf("%d\n", coll->coll_type);

	return 0;
}

/*****************************************************************************
 *			Calculate Floor Heights etc for Bounding Box...
 ****************************************************************************/
static void GetLaraCollisionInfo( ITEM_INFO *item, COLL_INFO *coll )
{
	coll->facing = lara.move_angle;
	GetCollisionInfo( coll, item->pos.x_pos,item->pos.y_pos,item->pos.z_pos, item->room_number,LARA_HITE );
}

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

/******************************************************************************
 *	Test If Lara Is Standing On a Tilted Block
 *	returns if slide has been initiated
 *****************************************************************************/
int TestLaraSlide( ITEM_INFO *item, COLL_INFO *coll )
{
	static	PHD_ANGLE 	old_ang=1;
	PHD_ANGLE			adif,ang;

	/* No Slide if slope is Small */
	if ( (ABS(coll->tilt_x))<=2 && (ABS(coll->tilt_z))<=2 )
		return(0);

	ang = 0;
	if ( coll->tilt_x>2 )                       		// get angle of Slope if any
		ang = -16384;
	else if ( coll->tilt_x<-2 )
		ang = 16384;
	if ( coll->tilt_z>2 && coll->tilt_z>(ABS(coll->tilt_x)) )
		ang = -32768;
	else if ( coll->tilt_z<-2 && -coll->tilt_z>(ABS(coll->tilt_x)) )
		ang = 0;

	adif = ang - item->pos.y_rot;
	ShiftItem( item,coll );
	if ( adif>=-16384 && adif<=16384 )
	{
		if ( item->current_anim_state!=AS_SLIDE || old_ang!=ang )
		{
			item->anim_number = SLIDE_A;				// Slide Forwards Animation
			item->frame_number = SLIDE_F;
			item->goal_anim_state = AS_SLIDE;			// Jump straight to Slide
			item->current_anim_state = AS_SLIDE;    	// status
			item->pos.y_rot = ang;
			lara.move_angle = ang;
			old_ang = ang;
		}
	}
	else
	{
		if ( item->current_anim_state!=AS_SLIDEBACK || old_ang!=ang )
		{
			item->anim_number = SLIDEBACK_A;			// Slide Backwards Animation
			item->frame_number = SLIDEBACK_F;
			item->goal_anim_state = AS_SLIDEBACK;		// Jump straight to slide backwards
			item->current_anim_state = AS_SLIDEBACK;    // status
			item->pos.y_rot = ang - 32768;
			lara.move_angle = ang;
			old_ang = ang;
		}
	}
	return(1);
}

int LaraTestClimbStance( ITEM_INFO *item, COLL_INFO *coll )
{
	// returns 0 if bad, 1 if good
	int result_r, result_l, shift_r, shift_l;

	// test both left and right sides; test at 700 to allow Lara to go to climb stance of hanging on slope
	result_r = LaraTestClimbPos(item, coll->radius, coll->radius+CLIMB_WIDTHR, -700, (STEP_L*2), &shift_r);
	if (result_r != 1)
		return 0;

	result_l = LaraTestClimbPos(item, coll->radius, -(coll->radius+CLIMB_WIDTHL), -700, (STEP_L*2), &shift_l);
	if (result_l != 1)
		return 0;

	if (shift_r)
	{
		if (shift_l)
		{
			// 2 shifts! if oppose, then bad pos, else use biggest shift
			if ((shift_l < 0) ^ (shift_r < 0))
				return 0;
			if (shift_r < 0 && shift_l < shift_r)
				shift_r = shift_l;
			else if (shift_r > 0 && shift_l > shift_r)
				shift_r = shift_l;
		}

		item->pos.y_pos += shift_r;
	}
	else if (shift_l)
		item->pos.y_pos += shift_l;

	return 1;
}

/*******************************************************************************
 *		Test For And Initiate A VAULT animation if need be..
 *				Returns TRUE if Vault started
 ******************************************************************************/
int TestLaraVault( ITEM_INFO *item, COLL_INFO *coll)
{
	if ((!(input & IN_ACTION))
	||  (lara.gun_status != LG_ARMLESS))
		return 0;

	if (coll->coll_type == COLL_FRONT)
	{
		int hdif, slope;
		PHD_ANGLE	angle;

		angle = item->pos.y_rot;

		if ( angle>=0-VAULT_ANGLE && angle<=0+VAULT_ANGLE)                         // North Wall
			angle = 0;
		else if ( angle>=16384-VAULT_ANGLE && angle<=16384+VAULT_ANGLE ) 		   // East Wall
			angle = 16384;
		else if ( angle>=32767-VAULT_ANGLE || angle<=-32767+VAULT_ANGLE ) 		   // South Wall
			angle = -32768;
		else if ( angle>=-16384-VAULT_ANGLE && angle<=-16384+VAULT_ANGLE )         // West Wall
			angle = -16384;

		if ( angle&0x3fff )
			return(0);

		hdif =  coll->front_floor;		  					  	// Get Average Height In front of Lara
//##		slope = ( ABS(coll->left_floor-coll->right_floor) >= SLOPE_DIF );
		slope = ( ABS(coll->left_floor2-coll->right_floor2) >= SLOPE_DIF );

	/* -------- initiate half-block vault */

		if ((hdif >= (-STEP_L*2 - STEP_L/2))
		&&  (hdif <= (-STEP_L*2 + STEP_L/2)))
		{
		// Exit Now if no space to vault into

			if ((slope)
			||  (coll->front_floor-coll->front_ceiling < 0)
//##			||  (coll->left_floor-coll->left_ceiling < 0)
//##			||  (coll->right_floor-coll->right_ceiling < 0))
			||  (coll->left_floor2-coll->left_ceiling2 < 0)
			||  (coll->right_floor2-coll->right_ceiling2 < 0))
				return(0);

		// If in swamp room and below surface of swamp, don't allow vaults.

			if ((room[item->room_number].flags & SWAMP)
			&&  (lara.water_surface_dist < -768))
				return(0);

			item->anim_number = VAULT12_A;
			item->frame_number = VAULT12_F;
			item->current_anim_state = AS_NULL;
			item->goal_anim_state = AS_STOP;
			item->pos.y_pos += STEP_L*2 + hdif;
			lara.gun_status = LG_HANDSBUSY;
		}

	/* -------- initiate three-quarter block vault */

		else if ((hdif >= (-STEP_L*3 - STEP_L/2))
			&&  (hdif <= (-STEP_L*3 + STEP_L/2)))
		{
		// Exit Now if no space to vault into

			if ((slope)
			||  (coll->front_floor-coll->front_ceiling < 0)
//##			||  (coll->left_floor-coll->left_ceiling < 0)
//##			||  (coll->right_floor-coll->right_ceiling < 0))
			||  (coll->left_floor2-coll->left_ceiling2 < 0)
			||  (coll->right_floor2-coll->right_ceiling2 < 0))
				return(0);

		// If in swamp room and below surface of swamp, don't allow vaults.

			if ((room[item->room_number].flags & SWAMP)
			&&  (lara.water_surface_dist < -768))
				return(0);

			item->anim_number = VAULT34_A;
			item->frame_number = VAULT34_F;
			item->current_anim_state = AS_NULL;
			item->goal_anim_state = AS_STOP;
			item->pos.y_pos += STEP_L*3 + hdif;
			lara.gun_status = LG_HANDSBUSY;
		}

	/* -------- jump up to grab walls within reach */

		else if ((!slope)
			&&  (hdif >= (-STEP_L*7 - STEP_L/2))
			&&  (hdif <= (-STEP_L*4 + STEP_L/2)))
		{
			if (room[item->room_number].flags & SWAMP)
				return(0);

			item->anim_number = STOP_A;		// Start Jump Up animation
			item->frame_number = STOP_F;
			item->goal_anim_state = AS_UPJUMP;
			item->current_anim_state = AS_STOP;
			lara.calc_fallspeed = -(sint16)(phd_sqrt( (int)(-2*GRAVITY*(hdif+800)) ) + 3);
			AnimateLara( item );
		}

	// Jump up onto tall climbable wall; won't do this for tall ceiling walls lowered below platform we're on (v.rare)
		else if ((lara.climb_status)
			&&  (hdif <= (-STEP_L*8 + STEP_L/2))
			&&  (lara.water_status != LARA_WADE)
//##			&&  (coll->left_floor <= (-STEP_L*8 + STEP_L/2))
//##			&&  (coll->right_floor <= -STEP_L*8)
			&&  (coll->left_floor2 <= (-STEP_L*8 + STEP_L/2))
			&&  (coll->right_floor2 <= -STEP_L*8)
			&&  (coll->mid_ceiling <= (-STEP_L*8 + STEP_L/2 + LARA_HITE)))
			{
				item->anim_number = STOP_A;
				item->frame_number = STOP_F;
				item->goal_anim_state = AS_UPJUMP;
				item->current_anim_state = AS_STOP;
				lara.calc_fallspeed = -116; // from that sqrt equation above
				AnimateLara( item );
			}

		else if ((lara.climb_status)
			&& ((hdif < -STEP_L*4)						// Is wall's height > a full block
			||  (coll->front_ceiling >= LARA_HITE-STEP_L))
			&&  (coll->mid_ceiling <= -STEP_L*5 + LARA_HITE))	// or a ceilingwall, lower than Lara
			{
				ShiftItem(item,coll);

				if (LaraTestClimbStance(item, coll))
				{
					item->anim_number = STOP_A;							// Start climb anim
					item->frame_number = STOP_F;
					item->goal_anim_state = AS_CLIMBSTNC;
					item->current_anim_state = AS_STOP;
					AnimateLara(item);
					item->pos.y_rot = angle;                                // line up angles
					lara.gun_status = LG_HANDSBUSY;
					return(1);
				}
				return(0);
			}
		else
			return(0);

		item->pos.y_rot = angle;                                // line up angles
		ShiftItem( item,coll );                                 // shift away from wall
		return(1);
	}
//## Oh, arse
#if 0
	else if (lara.CanMonkeySwing)
	{
		item->anim_number = STOP_A;		// Start Jump Up animation
		item->frame_number = STOP_F;
		item->goal_anim_state = AS_UPJUMP;
		item->current_anim_state = AS_NULL;
		lara.calc_fallspeed = -116;
		AnimateLara(item);
		return 1;
	}
#endif

	else
		return 0;
}

/*****************************************************************************
 *			Can Lara Hang at Current Position
 *				Returns 1 if lara still hanging
 ****************************************************************************/
static int TestWall(ITEM_INFO *item, sint32 front, sint32 right, sint32 down)
{
	int			x,y,z;
	int			h,c;
	FLOOR_INFO	*floor;
	sint16		room_num;
	PHD_ANGLE	angle;

	x = item->pos.x_pos;
	y = item->pos.y_pos + down;
	z = item->pos.z_pos;
	room_num = item->room_number;

	angle = (uint16)(item->pos.y_rot+0x2000)/0x4000;
	switch ( angle )
	{
		case NORTH:
			x-=right;
		break;

		case WEST:
			z+=right;
		break;

		case SOUTH:
			x+=right;
		break;

		case EAST:
			z-=right;
		break;
	}

	floor = GetFloor( x,y,z, &room_num );

	switch ( angle )
	{
		case NORTH:
			z+=front;
		break;

		case WEST:
			x-=front;
		break;

		case SOUTH:
			z-=front;
		break;

		case EAST:
			x+=front;
		break;
	}

	floor = GetFloor( x,y,z, &room_num );

	h = GetHeight( floor,x,y,z );
	c = GetCeiling( floor,x,y,z );
	if ( h!=NO_HEIGHT )
	{
		if ( (h-y)>0 && (c-y)<0 )
		{
			return(0); // No wall there
		}
		return(2);
	}
	return(1);			// Wall there!
}

/*
 * Lara has run/walked etc into something and needs to be in stop state.
 * However, if she started the control phase in this state, then should
 * continue old anim
 *
 */
static void LaraCollideStop(ITEM_INFO *item, COLL_INFO *coll)
{
	switch (coll->old_anim_state)
	{
		case AS_STOP:
		case AS_TURN_L:
		case AS_TURN_R:
		case AS_FASTTURN:
			item->current_anim_state = coll->old_anim_state;
			item->anim_number = coll->old_anim_number;
			item->frame_number = coll->old_frame_number;

			if ( input&IN_LEFT )
				item->goal_anim_state = AS_TURN_L;
			else if ( input&IN_RIGHT )
				item->goal_anim_state = AS_TURN_R;
			else
				item->goal_anim_state = AS_STOP;
			AnimateLara(item);
			break;

		default:
			item->anim_number = STOP_A;
			item->frame_number = STOP_F;
	}
}

/******************************************************************************
 *				Routine for Multiway Sliding...
 *****************************************************************************/
void	lara_slide_slope( ITEM_INFO *item, COLL_INFO *coll )
{
	coll->bad_pos = NO_BAD_POS;
	coll->bad_neg = -512;								// Allow player to Pop out of Bad-Holes
	coll->bad_ceiling = 0;
	GetLaraCollisionInfo( item, coll );
	if ( LaraHitCeiling( item,coll ) )
		return;
	LaraDeflectEdge( item,coll );

	if ( coll->mid_floor > 200 )						// Floor Has Fallen Away From
	{                                                   // Under Us...
		if ( item->current_anim_state==AS_SLIDE )
		{
			item->anim_number = FALLDOWN_A;					// So Initiate A Fall
			item->frame_number = FALLDOWN_F;
			item->current_anim_state = AS_FORWARDJUMP;
			item->goal_anim_state = AS_FORWARDJUMP;
		}
		else
		{
			item->anim_number = FALLBACK_A;					// So Initiate A Fall
			item->frame_number = FALLBACK_F;
			item->current_anim_state = AS_FALLBACK;
			item->goal_anim_state = AS_FALLBACK;
		}

		StopSoundEffect(3); 	// stop slide sound
		item->fallspeed = 0;
		item->gravity_status = 1;
		return;
	}
	TestLaraSlide( item,coll );
	item->pos.y_pos += coll->mid_floor;                 	// Enforce to floor height..

	if ( (ABS(coll->tilt_x))<=2 && (ABS(coll->tilt_z))<=2 ) // then Return to Stop Position
	{
		item->goal_anim_state = AS_STOP;
		StopSoundEffect(3); 	// stop slide sound
	}
}

/*****************************************************************************
 *		Test if Lara Has Hit A Wall in the Middle of A Jump..
 *					so Deflect or Stop..
 *			Also handles Hitting Ceiling
 ****************************************************************************/
void	LaraDeflectEdgeJump( ITEM_INFO *item, COLL_INFO *coll )
{
	ShiftItem( item,coll );
	switch ( coll->coll_type )
	{
		case COLL_FRONT:
		case COLL_TOPFRONT:
			// Ignore front collision if dropping from climb stance
			if (lara.climb_status && item->speed==2)
				return;

			/* Choose anim to jump to based on severity of collision */
			if (coll->mid_floor > 512)
			{
				item->goal_anim_state = AS_FASTFALL;      	// Make Player Stop Immediately
				item->current_anim_state = AS_FASTFALL;   	// and Skip directly into fastfall
				item->frame_number = FASTSPLAT_F;
				item->anim_number = FASTSPLAT_A;
			}
			else if (coll->mid_floor <= 128)
			{
				item->goal_anim_state = AS_LAND;
				item->current_anim_state = AS_LAND;
				item->frame_number = LAND_F;
				item->anim_number = LAND_A;
			}
			item->speed /= 4;
			lara.move_angle += -0x8000;
			if ( item->fallspeed<=0 )
				item->fallspeed = 1;
		break;

		case COLL_LEFT:
			item->pos.y_rot += LARA_DEF_ADD_EDGE;
		break;

		case COLL_RIGHT:
			item->pos.y_rot -= LARA_DEF_ADD_EDGE;
		break;

		case COLL_TOP:
			if ( item->fallspeed<=0 )					// If hit ceiling whilst going upwards
				item->fallspeed = 1;                    // then start falling
		break;

		case COLL_CLAMP:								// If hit ceiling and floor then Use old Position
			item->pos.z_pos -= (phd_cos(coll->facing)*100)>>W2V_SHIFT;		// shift away from the clamp
			item->pos.x_pos -= (phd_sin(coll->facing)*100)>>W2V_SHIFT;       // position
			item->speed = 0;
			coll->mid_floor = 0;
			if ( item->fallspeed<=0 )                   // make jump velocity positive
				item->fallspeed = 16;                    // so we can land
		break;
	}
}

/*****************************************************************************
 *		Test if Lara Has Hit A Wall in the Middle of A Jump..
 *					so Slide or Stop..
 *			Also handles Hitting Ceiling
 ****************************************************************************/
void	LaraSlideEdgeJump( ITEM_INFO *item, COLL_INFO *coll )
{
	ShiftItem( item,coll );
	switch ( coll->coll_type )
	{
		case COLL_LEFT:
			item->pos.y_rot += LARA_DEF_ADD_EDGE;
		break;

		case COLL_RIGHT:
			item->pos.y_rot -= LARA_DEF_ADD_EDGE;
		break;

		case COLL_TOP:
		case COLL_TOPFRONT:
			if ( item->fallspeed<=0 )					// If hit ceiling whilst going upwards
				item->fallspeed = 1;                    // then start falling
		break;

		case COLL_CLAMP:								// If hit ceiling and floor
			item->pos.z_pos -= (phd_cos(coll->facing)*100)>>W2V_SHIFT;		// shift away from the clamp
			item->pos.x_pos -= (phd_sin(coll->facing)*100)>>W2V_SHIFT;       // position
			item->speed = 0;
			coll->mid_floor = 0;
			if ( item->fallspeed<=0 )                   // make jump velocity positive
				item->fallspeed = 16;                    // so we can land
		break;

		default:
		break;
	}
}

int LaraTestHangOnClimbWall(ITEM_INFO *item, COLL_INFO *coll)
{
	// check if valid hang position; return 0 if not
	int shift, result;
	sint16 *bounds;

	// easy checks first
	if (!lara.climb_status || item->fallspeed<0)
		return 0;

	switch ((uint16)(item->pos.y_rot+0x2000)/0x4000)
	{
		case NORTH:
		case SOUTH:
			item->pos.z_pos += coll->shift.z;
			break;
		case EAST:
		case WEST:
			item->pos.x_pos += coll->shift.x;
			break;
	}

	// test middle/left/right
	bounds = GetBoundsAccurate( item );

	if (!LaraTestClimbPos(item, coll->radius, coll->radius, bounds[2], bounds[3]-bounds[2], &shift)
	||  !LaraTestClimbPos(item, coll->radius, -coll->radius, bounds[2], bounds[3]-bounds[2], &shift))
		return 0;

	result = LaraTestClimbPos(item, coll->radius, 0, bounds[2], bounds[3]-bounds[2], &shift);

	if (!result)
		return 0;

	else if (result==1) // saying climb OK, but not really valid test (so ignore y shift)
		return 1;

	item->pos.y_pos += shift;

	return 1;
}


void	LaraHangTest(ITEM_INFO *item, COLL_INFO *coll)
{
	PHD_ANGLE	angle;
	sint16 		*bounds;
	int			flag=0;
	int			hdif;
	PHD_VECTOR	pos;

	coll->bad_pos = NO_BAD_POS;
	coll->bad_neg = NO_BAD_NEG;
	coll->bad_ceiling = 0;
	GetLaraCollisionInfo( item, coll );

	if ( coll->front_floor < 200 )
		flag=1;

	item->gravity_status = item->fallspeed = 0;		// gravity off
	lara.move_angle = item->pos.y_rot;

	angle = (uint16)(item->pos.y_rot+0x2000)/0x4000;

/* -------- move Lara towards where she is hanging */

	switch (angle)
	{
		case NORTH:
			item->pos.z_pos+=4;
			break;

		case WEST:
			item->pos.x_pos-=4;
			break;

		case SOUTH:
			item->pos.z_pos-=4;
			break;

		case EAST:
			item->pos.x_pos+=4;
			break;
	}

	coll->bad_pos = NO_BAD_POS;
	coll->bad_neg = -STEPUP_HEIGHT;
	coll->bad_ceiling = 0;
	GetLaraCollisionInfo( item, coll );

/* -------- hang on climbable wall */

	if (lara.climb_status)
	{
		if ((!(input & IN_ACTION))
		||  (item->hit_points <= 0))
		{
#if 0	// ## TWATS & CUNTS

		// move to hip pos, else nasty snap when go drop from some anims
			pos.x = pos.y = pos.z = 0;
			GetJointAbsPosition(item, &pos, 0);

		// only sideways; not away from wall or no regrab possible
			if ((angle == NORTH)
			||  (angle == SOUTH))
				item->pos.x_pos = pos.x;
			else
				item->pos.z_pos = pos.z;
#endif
			item->goal_anim_state = AS_FORWARDJUMP;				// Jump straight to falldown
			item->current_anim_state = AS_FORWARDJUMP;           // UpJump status if user releases
			item->anim_number = FALLDOWN_A;                 // Action button
			item->frame_number = FALLDOWN_F;
			item->pos.y_pos += 256;
			item->gravity_status = 1;
			item->speed = 2;
			item->fallspeed = 1;
			lara.gun_status = LG_ARMLESS;
			return;
		}

		if (!LaraTestHangOnClimbWall(item, coll)) // this does coll->shift
		{
			item->pos.x_pos = coll->old.x;
			item->pos.y_pos = coll->old.y;
			item->pos.z_pos = coll->old.z;
			item->goal_anim_state = AS_HANG;
			item->current_anim_state = AS_HANG;
			item->frame_number = HANG_F;
			item->anim_number = HANG_A;
			return;
		}

		if ((item->anim_number == HANG_A)
		&&  (item->frame_number == HANG_F))
		{
			if (LaraTestClimbStance(item, coll))
				item->goal_anim_state = AS_CLIMBSTNC;
		}

		return;
	}

// NON CLIMBABLE WALL
	if ((!(input&IN_ACTION))			// If user Dies Or releases Action
	||  (item->hit_points <= 0)
	||  (coll->front_floor > 0))
	{
		item->goal_anim_state = AS_UPJUMP;				// Jump straight to falldown
		item->current_anim_state = AS_UPJUMP;           // UpJump status if user releases
		item->anim_number = STOPHANG_A;                 // Action button
		item->frame_number = STOPHANG_F;
		bounds = GetBoundsAccurate( item );
//		item->pos.y_pos += coll->front_floor - bounds[2] + 2;
		item->pos.y_pos += bounds[3];
		item->pos.x_pos += coll->shift.x;
		item->pos.z_pos += coll->shift.z;
		item->gravity_status = 1;
		item->speed = 2;
		item->fallspeed = 1;
		lara.gun_status = LG_ARMLESS;
		return;
	}

	bounds = GetBoundsAccurate( item );
	hdif = coll->front_floor - bounds[2];

//	if ( (ABS(coll->left_floor-coll->right_floor))>=SLOPE_DIF ||
	if ( (ABS(coll->left_floor2-coll->right_floor2))>=SLOPE_DIF ||
	     coll->mid_ceiling>=0 || coll->coll_type!=COLL_FRONT || flag || coll->hit_static ||
		  hdif<-SLOPE_DIF || hdif>SLOPE_DIF ) // last 2 checks are for if gone from climbable to unclimbable wall
	{
		item->pos.x_pos = coll->old.x;
		item->pos.y_pos = coll->old.y;
		item->pos.z_pos = coll->old.z;
		if ( item->current_anim_state==AS_HANGLEFT || item->current_anim_state==AS_HANGRIGHT )
		{
			item->goal_anim_state = AS_HANG;
			item->current_anim_state = AS_HANG;
			item->frame_number = HANG_F;
			item->anim_number = HANG_A;
		}
		return;
	}

	switch ( angle )
	{
		case NORTH:
		case SOUTH:
			item->pos.z_pos += coll->shift.z;
		break;

		case WEST:
		case EAST:
			item->pos.x_pos += coll->shift.x;
		break;
	}

	item->pos.y_pos += hdif;
}



/******************************************************************************
 *		Test if Lara Can swing inwards when Doing Hang Reach
 *****************************************************************************/
static int TestHangSwingIn( ITEM_INFO *item, PHD_ANGLE angle )
{
	int			x,y,z;
	int			h,c;
	FLOOR_INFO	*floor;
	sint16		room_num;

	x = item->pos.x_pos;
	y = item->pos.y_pos;
	z = item->pos.z_pos;
	room_num = item->room_number;

	switch (angle)
	{
		case 0:
			z += 256;
			break;
		case 16384:
			x += 256;
			break;
		case -16384:
			x -= 256;
			break;
		case -32768:
			z -= 256;
			break;
	}

	floor = GetFloor(x, y, z, &room_num);

	h = GetHeight(floor, x, y, z);
	c = GetCeiling(floor, x, y, z);

	if (h != NO_HEIGHT)
	{
		if (((h-y) > 0)
		&&  ((c-y) < -400)
		&&  ((y-819-c) > -72))
			return(1);
	}
	return(0);
}

/******************************************************************************
 *		Test For Ability to Hang when doing Forward Jump Also
 *****************************************************************************/
int LaraTestHangJump(ITEM_INFO *item, COLL_INFO *coll)
{
	int				edge_catch;
	PHD_ANGLE		angle;
	sint16 			*bounds;
	sint32			edge;

	// Is a wall there? Pressing 'action? No weapons?
	if ((!(input & IN_ACTION))
	||  (lara.gun_status != LG_ARMLESS)
//	||  (coll->coll_type != COLL_FRONT)
	||  (coll->hit_static))
		return 0;

/* -------- initialise monkey swing */

	if ((lara.CanMonkeySwing)
	&&  (coll->coll_type == COLL_TOP))
	{
		lara.head_x_rot = lara.head_y_rot = 0;
		lara.torso_x_rot = lara.torso_y_rot = 0;
		item->goal_anim_state = AS_HANG2;
		item->current_anim_state = AS_HANG2;
		item->anim_number = GRABLEDGEIN_A;
		item->frame_number = GRABLEDGEIN_F;
		item->gravity_status = 0;
		item->speed = 0;
		item->fallspeed = 0;
		lara.gun_status = LG_HANDSBUSY;
		return 1;
	}

	// is there room above and below lara.
	if ((coll->mid_ceiling > -STEPUP_HEIGHT)
	||  (coll->mid_floor < 200)
	||  (coll->coll_type != COLL_FRONT))
		return(0);

	// Check if Hands are in Correct place
	if (!(edge_catch = LaraTestEdgeCatch(item, coll, &edge)))
		return(0);

	if ((edge_catch < 0)
	&&  (!LaraTestHangOnClimbWall(item, coll)))
		return(0);

/* -------- determine wall angle */

	angle = item->pos.y_rot;

	if ( angle>=0-HANG_ANGLE && angle<=0+HANG_ANGLE)                     // North Wall
		angle = 0;
	else if ( angle>=16384-HANG_ANGLE && angle<=16384+HANG_ANGLE ) 		 // East Wall
		angle = 16384;
	else if ( angle>=32767-HANG_ANGLE || angle<=-32767+HANG_ANGLE ) 	 // South Wall
		angle = -32768;
	else if ( angle>=-16384-HANG_ANGLE && angle<=-16384+HANG_ANGLE )     // West Wall
		angle = -16384;

	if ( angle&0x3fff )
		return(0);

/* -------- determine animation */

	if (TestHangSwingIn(item, angle))
	{
		lara.head_x_rot = lara.head_y_rot = 0;
		lara.torso_x_rot = lara.torso_y_rot = 0;
	 	item->anim_number = GRABLEDGEIN_A;
		item->frame_number = GRABLEDGEIN_F;
  		item->current_anim_state = AS_HANG2;
		item->goal_anim_state = AS_HANG2;
	}
	else
	{
	 	item->anim_number = GRABLEDGE_A;
		item->frame_number = GRABLEDGE_F;
  		item->current_anim_state = AS_HANG;
		item->goal_anim_state = AS_HANG;
	}

	bounds = GetBoundsAccurate( item );

	if (edge_catch>0)
	{
		item->pos.y_pos += coll->front_floor-bounds[2]; // catch edge
		item->pos.x_pos += coll->shift.x;
		item->pos.z_pos += coll->shift.z;
	}
	else
		item->pos.y_pos = edge - bounds[2];
		//item->pos.y_pos = ((item->pos.y_pos + bounds[2]) & ~(STEP_L-1)) - bounds[2]; // catch 1/4
	item->pos.y_rot = angle;
	item->gravity_status = 1;
	item->speed = 2;
	item->fallspeed = 1;
	lara.gun_status = LG_HANDSBUSY;
	return(1);
}

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 +					Lara control Routines Are Here
 +			these Request Different Anim States according to input..
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

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

/****************************************************************************
* LaraAboveWater
*
* SYNOPSIS
*	void LaraAboveWater(ITEM_INFO *item, COLL_INFO *coll)
*
* PURPOSE
*	Standard Lara controller
*
* INPUTS
*	item		=
*	coll		=
*
* RETURN
*	Nothing
*/
void	LaraAboveWater(ITEM_INFO *item, COLL_INFO *coll)
{
/* -------- initialise collision defaults */

	coll->old.x = item->pos.x_pos;
	coll->old.y = item->pos.y_pos;
	coll->old.z = item->pos.z_pos;
	coll->old_anim_state = item->current_anim_state;
	coll->old_anim_number = item->anim_number;
	coll->old_frame_number = item->frame_number;
	coll->radius = LARA_RAD;
	coll->trigger = NULL;
	coll->lava_is_pit = 0;
	coll->slopes_are_walls = 0;
	coll->slopes_are_pits = 0;
	coll->enable_spaz = 1;
	coll->enable_baddie_push = 1;

/* -------- process look */

	if ((input & IN_LOOK)
	&&  (!lara.extra_anim)
	&&  (lara.look))
		LookLeftRight();
	else
		ResetLook();

	lara.look = 1;

/* -------- process skidoo/boat */

	if (lara.skidoo != NO_ITEM)
	{
		if (items[lara.skidoo].object_number == KAYAK) // may be a boat, not a skidoo!
		{
			if (KayakControl())
				return;
		}

		else if (items[lara.skidoo].object_number == QUADBIKE)
		{
			if (QuadBikeControl())
				return;
		}

		else if (items[lara.skidoo].object_number == UPV)
		{
			if (SubControl())
				return;
		}

		else if (items[lara.skidoo].object_number == BIGGUN)
		{
			if (BigGunControl(coll))
				return;
		}

		else if (items[lara.skidoo].object_number == MINECART)
		{
			if (MineCartControl())
				return;
		}

		else
		{
			LaraGun();
			return; // boat control is done in BoatControl
		}
	}

/* -------- update animation */

	if (lara.extra_anim)
		(*extra_control_routines[item->current_anim_state])(item, coll);
	else
		(*lara_control_routines[item->current_anim_state])(item, coll);		// Get Input regardless of Collisions etc..

	if ( item->pos.z_rot>=-LARA_LEAN_UNDO && item->pos.z_rot<=LARA_LEAN_UNDO )	// Undo Any Leaning
		item->pos.z_rot = 0;                                                    // on corners
	else if ( item->pos.z_rot<-LARA_LEAN_UNDO )
		item->pos.z_rot += LARA_LEAN_UNDO;
	else
		item->pos.z_rot -= LARA_LEAN_UNDO;

	if ( lara.turn_rate>=-LARA_TURN_UNDO && lara.turn_rate<=LARA_TURN_UNDO )	// Undo Turning Rate
		lara.turn_rate = 0;														// Uses fairly Quick rate
	else if ( lara.turn_rate<-LARA_TURN_UNDO )                                  // else get feeling of
		lara.turn_rate += LARA_TURN_UNDO;                                       // Unresponsiveness and Lag
	else
		lara.turn_rate -= LARA_TURN_UNDO;
	item->pos.y_rot += lara.turn_rate;                              			// Add On Turning Rate

	AnimateLara(item);															// Move Lara and animate...

	if (!lara.extra_anim)
	{
		LaraBaddieCollision( item,coll );											// Do any Baddie collisions...
		if (lara.skidoo == NO_ITEM) // 13/8/97: get out if Lara has found vehicle (in case normal collision overrides)
			(*lara_collision_routines[item->current_anim_state])( item,coll );			// Now Handle Any Collision Issues..
	}

	UpdateLaraRoom(item, -LARA_HITE/2);

	LaraGun();

	LaraOnPad = 0;
	TestTriggers(coll->trigger, 0);	// Gibbytesttriggers
	if (!LaraOnPad)
		lara_item->item_flags[1] = 0;	// Reset lara on pad flag.
}

/****************************************************************************
 *
 *	Duck
 *
\****************************************************************************/

void	lara_as_duck(ITEM_INFO *item, COLL_INFO *coll)
{
	coll->enable_spaz = 1;
	coll->enable_baddie_push = 1;

	lara.IsDucked = 1;

	if (item->hit_points <=0 )
	{
		item->goal_anim_state = AS_ALL4S;
		return;
	}

	if (TestLaraSlide(item, coll))
		return;

	if (input & IN_LOOK)
		LookUpDown();

	if ((input & (IN_FORWARD|IN_BACK))
	&&  (lara.gun_status == LG_ARMLESS)
	&&  (item->frame_number > (DUCKBREATHE_F+10)))
	{
		lara.torso_x_rot = lara.torso_y_rot = 0;
		item->goal_anim_state = AS_ALL4S;
		return;
	}
}

void	lara_col_duck(ITEM_INFO *item, COLL_INFO *coll)
{
	item->gravity_status = item->fallspeed = 0;
	coll->facing = lara.move_angle = item->pos.y_rot;
	coll->radius = LARA_RAD*2;
	coll->bad_pos = STEPUP_HEIGHT;
	coll->bad_neg = -STEPUP_HEIGHT;
	coll->bad_ceiling = 0;
	coll->slopes_are_walls = 1;

	GetCollisionInfo(coll,
				  item->pos.x_pos,
				  item->pos.y_pos,
				  item->pos.z_pos,
				  item->room_number,
				  LARA_DUCK_HEIGHT);

	if (LaraFallen(item, coll))
	{
		lara.gun_status = LG_ARMLESS;
		return;
	}

	if (coll->mid_ceiling >= -(LARA_HITE-LARA_DUCK_HEIGHT))
		lara.keep_ducked = 1;
	else
		lara.keep_ducked = 0;

	ShiftItem(item, coll);
	item->pos.y_pos += coll->mid_floor;

	if (((!(input & IN_DUCK))
	||   (lara.water_status == LARA_WADE))
	&&   (!lara.keep_ducked)
	&&   (item->anim_number == DUCKBREATHE_A))
//	&&   (item->frame_number > (DUCKBREATHE_F+10)))
	{
		item->goal_anim_state = AS_STOP;
		return;
	}
}

/* -------- crawl */

void	lara_as_all4s(ITEM_INFO *item, COLL_INFO *coll)
{
	if (item->hit_points <= 0)
	{
		item->goal_anim_state = AS_DEATH;
		return;
	}

	if (input & IN_LOOK)
		LookUpDown();

	lara.torso_x_rot = lara.torso_y_rot = 0;

	coll->enable_spaz = 0;
	coll->enable_baddie_push = 1;

	if (item->anim_number == 258)			// duck-to-crawl link
		lara.gun_status = LG_HANDSBUSY;

	if (TestLaraSlide(item, coll))
		return;

	camera.target_elevation = -23*ONE_DEGREE;

}

void	lara_col_all4s(ITEM_INFO *item, COLL_INFO *coll)
{
	item->gravity_status = item->fallspeed = 0;

	if (item->goal_anim_state == AS_CRAWL2HANG)
		return;

	coll->facing = lara.move_angle = item->pos.y_rot;
	coll->radius = LARA_RAD*2;
	coll->bad_pos = STEP_L-1;
	coll->bad_neg = -(STEP_L-1);
	coll->bad_ceiling = LARA_DUCK_HEIGHT;
	coll->slopes_are_walls = 1;
	coll->slopes_are_pits = 1;

	GetCollisionInfo(coll, item->pos.x_pos, item->pos.y_pos, item->pos.z_pos, item->room_number, LARA_DUCK_HEIGHT);

	if (LaraFallen(item, coll))
	{
		lara.gun_status = LG_ARMLESS;
		return;
	}

	if (coll->mid_ceiling >= -(LARA_HITE-LARA_DUCK_HEIGHT))
		lara.keep_ducked = 1;
	else
		lara.keep_ducked = 0;

	ShiftItem(item, coll);
	item->pos.y_pos += coll->mid_floor;

	if (((!(input & IN_DUCK)) && (lara.keep_ducked == 0))
	||   (input & IN_DRAW))
		item->goal_anim_state = AS_DUCK;

	else if ((item->anim_number == ALL4S_A)
		||  (item->anim_number == ALL4S2_A))
		{
			if (input & IN_FORWARD)
			{
				sint16 height;

				height = LaraFloorFront(item, item->pos.y_rot, 256);

				if ((height < (STEP_L-1))
				&&  (height > -(STEP_L-1))
				&&  (height_type != BIG_SLOPE))
					item->goal_anim_state = AS_CRAWL;
			}

			else if (input & IN_BACK)
			{
				sint16 height;

//				coll->facing = item->pos.y_rot - 0x8000;
//				coll->bad_pos = 128;
//				coll->bad_neg = -128;
//				coll->bad_ceiling = LARA_DUCK_HEIGHT;
//				GetCollisionInfo(coll, item->pos.x_pos, item->pos.y_pos, item->pos.z_pos, item->room_number, LARA_DUCK_HEIGHT);

//				printf("%d\n", coll->front_floor);

//				if (coll->coll_type != COLL_FRONT)
//					item->goal_anim_state = AS_CRAWLBACK;


				height = LaraCeilingFront(item, item->pos.y_rot, -300);
				if (height == NO_HEIGHT || height > 256)
					return;

				height = LaraFloorFront(item, item->pos.y_rot, -300);

				if ((height < (STEP_L-1))
				&&  (height > -(STEP_L-1))
				&&  (height_type != BIG_SLOPE))
					item->goal_anim_state = AS_CRAWLBACK;

				else if ((input & IN_ACTION)
					&&  (height > 768))
					{
						if (GetStaticObjects(item,item->pos.y_rot+0x8000,512,50,300) == 0)
						{
							PHD_ANGLE angle;

							angle = (uint16)(item->pos.y_rot+0x2000)/0x4000;

							switch ( angle )
							{
								case NORTH:
									item->pos.z_pos = (item->pos.z_pos & ~1023) + 225;
									item->pos.y_rot = 0;
									break;

								case SOUTH:
									item->pos.z_pos = (item->pos.z_pos | 1023) - 225;
									item->pos.y_rot = 0x8000;
									break;

								case EAST:
									item->pos.x_pos = (item->pos.x_pos & ~1023) + 225;
									item->pos.y_rot = 0x4000;
									break;

								case WEST:
									item->pos.x_pos = (item->pos.x_pos | 1023) - 225;
									item->pos.y_rot = 0xc000;
									break;
							}
				    			item->goal_anim_state = AS_CRAWL2HANG;
						}
					}
			}

			else if (input & IN_LEFT)
			{
				item->current_anim_state = AS_ALL4TURNL;
				item->goal_anim_state = AS_ALL4TURNL;
				item->anim_number = ALL4TURNL_A;
				item->frame_number = ALL4TURNL_F;
			}

			else if (input & IN_RIGHT)
			{
				item->current_anim_state = AS_ALL4TURNR;
				item->goal_anim_state = AS_ALL4TURNR;
				item->anim_number = ALL4TURNR_A;
				item->frame_number = ALL4TURNR_F;
			}
		}
}

void	lara_as_crawl(ITEM_INFO *item, COLL_INFO *coll)
{
	if (item->hit_points <=0)
	{
		item->goal_anim_state = AS_ALL4S;
		return;
	}

	if (input & IN_LOOK)
		LookUpDown();

	lara.torso_x_rot = lara.torso_y_rot = 0;
	coll->enable_spaz = 0;
	coll->enable_baddie_push = 1;
	camera.target_elevation = -23*ONE_DEGREE;

	if (TestLaraSlide(item, coll))
		return;

	if ((!(input & IN_FORWARD))
	||  ((!(input & IN_DUCK)) && (!lara.keep_ducked)))
		item->goal_anim_state = AS_ALL4S;

	else if (input & IN_LEFT)
	{
		lara.turn_rate -= LARA_TURN_RATE;

		if (lara.turn_rate < -LARA_JUMP_TURN)
			lara.turn_rate = -LARA_JUMP_TURN;
	}
	else if (input & IN_RIGHT)
	{
		lara.turn_rate += LARA_TURN_RATE;

		if (lara.turn_rate > LARA_JUMP_TURN)
			lara.turn_rate = LARA_JUMP_TURN;
	}
}

void	lara_col_crawl(ITEM_INFO *item, COLL_INFO *coll)
{
	item->gravity_status = item->fallspeed = 0;
	lara.move_angle = item->pos.y_rot;
	coll->radius = LARA_RAD*2;
	coll->bad_pos = STEP_L-1;
	coll->bad_neg = -(STEP_L-1);
	coll->bad_ceiling = LARA_DUCK_HEIGHT;
	coll->slopes_are_walls = 1;
	coll->slopes_are_pits = 1;

	coll->facing = lara.move_angle;
	GetCollisionInfo(coll,
				  item->pos.x_pos,
				  item->pos.y_pos,
				  item->pos.z_pos,
				  item->room_number,
				  LARA_DUCK_HEIGHT);

	if (LaraDeflectEdgeDuck(item, coll))
	{
		item->current_anim_state = AS_ALL4S;
		item->goal_anim_state = AS_ALL4S;

		if (item->anim_number != ALL4S_A)
		{
			item->anim_number = ALL4S_A;
			item->frame_number = ALL4S_F;
		}
		return;
	}

	if (LaraFallen(item, coll))
	{
		lara.gun_status = LG_ARMLESS;
		return;
	}

	ShiftItem(item, coll);
	item->pos.y_pos += coll->mid_floor;
}

void lara_as_all4turnl(ITEM_INFO *item, COLL_INFO *coll)
{
	if (item->hit_points <= 0)
	{
		item->goal_anim_state = AS_ALL4S;
		return;
	}

	coll->enable_spaz = 0;
	coll->enable_baddie_push = 1;
	lara.torso_x_rot = lara.torso_y_rot = 0;
	camera.target_elevation = -23*ONE_DEGREE;

	if (TestLaraSlide(item, coll))
		return;

	item->pos.y_rot -= (ONE_DEGREE + (ONE_DEGREE/2));

	if (!(input & IN_LEFT))
		item->goal_anim_state = AS_ALL4S;
}

void lara_col_all4turnl(ITEM_INFO *item, COLL_INFO *coll)
{
	GetCollisionInfo(coll,
				  item->pos.x_pos,
				  item->pos.y_pos,
				  item->pos.z_pos,
				  item->room_number,
				  LARA_DUCK_HEIGHT);
}

void lara_as_all4turnr(ITEM_INFO *item, COLL_INFO *coll)
{
	if (item->hit_points <= 0)
	{
		item->goal_anim_state = AS_ALL4S;
		return;
	}

	coll->enable_spaz = 0;
	coll->enable_baddie_push = 1;
	lara.torso_x_rot = lara.torso_y_rot = 0;
	camera.target_elevation = -23*ONE_DEGREE;

	if (TestLaraSlide(item, coll))
		return;

	item->pos.y_rot += (ONE_DEGREE + (ONE_DEGREE/2));

	if (!(input & IN_RIGHT))
		item->goal_anim_state = AS_ALL4S;
}

void lara_col_all4turnr(ITEM_INFO *item, COLL_INFO *coll)
{
	GetCollisionInfo(coll,
				  item->pos.x_pos,
				  item->pos.y_pos,
				  item->pos.z_pos,
				  item->room_number,
				  LARA_DUCK_HEIGHT);
}

void	lara_as_crawlb(ITEM_INFO *item, COLL_INFO *coll)
{
	if (item->hit_points <=0)
	{
		item->goal_anim_state = AS_ALL4S;
		return;
	}

	if (input & IN_LOOK)
		LookUpDown();

	coll->enable_spaz = 0;
	coll->enable_baddie_push = 1;
	lara.torso_x_rot = lara.torso_y_rot = 0;
	camera.target_elevation = -23*ONE_DEGREE;

	if (TestLaraSlide(item, coll))
		return;

	if (!(input & IN_BACK))
		item->goal_anim_state = AS_ALL4S;

	else if (input & IN_RIGHT)
	{
		lara.turn_rate -= LARA_TURN_RATE;

		if (lara.turn_rate < -LARA_JUMP_TURN)
			lara.turn_rate = -LARA_JUMP_TURN;
	}
	else if (input & IN_LEFT)
	{
		lara.turn_rate += LARA_TURN_RATE;

		if (lara.turn_rate > LARA_JUMP_TURN)
			lara.turn_rate = LARA_JUMP_TURN;
	}
}

void	lara_col_crawlb(ITEM_INFO *item, COLL_INFO *coll)
{
	item->gravity_status = item->fallspeed = 0;

	coll->radius = LARA_CRAWLB_RAD;
	coll->bad_pos = STEP_L-1;
	coll->bad_neg = -(STEP_L-1);
	coll->bad_ceiling = LARA_DUCK_HEIGHT;
	coll->slopes_are_walls = 1;
	coll->slopes_are_pits = 1;
	coll->facing = lara.move_angle = item->pos.y_rot-32768;

	GetCollisionInfo(coll,
				  item->pos.x_pos,
				  item->pos.y_pos,
				  item->pos.z_pos,
				  item->room_number,
				  LARA_DUCK_HEIGHT);

	if (LaraDeflectEdgeDuck(item, coll))
	{
		item->current_anim_state = AS_ALL4S;
		item->goal_anim_state = AS_ALL4S;

		if (item->anim_number != ALL4S_A)
		{
			item->anim_number = ALL4S_A;
			item->frame_number = ALL4S_F;
		}
		return;
	}

	if (LaraFallen(item, coll))
	{
		lara.gun_status = LG_ARMLESS;
		return;
	}

	ShiftItem(item, coll);
	item->pos.y_pos += coll->mid_floor;

	lara.move_angle = item->pos.y_rot;
}



void	lara_col_crawl2hang(ITEM_INFO *item, COLL_INFO *coll)
{
	if (item->anim_number == 302)
	{
		int				edge_catch;
		PHD_ANGLE		angle;
		sint16 			*bounds;
		sint32			edge;

	/* -------- these lines force the slag to catch edges */
		item->fallspeed = 512;
		item->pos.y_pos |= (STEP_L-1);

		coll->bad_pos = NO_BAD_POS;
		coll->bad_neg = -STEPUP_HEIGHT;
		coll->bad_ceiling = BAD_JUMP_CEILING;
		coll->facing = lara.move_angle = item->pos.y_rot;

		GetCollisionInfo(
			coll,
			item->pos.x_pos,
			item->pos.y_pos,
			item->pos.z_pos,
			item->room_number,
			870);	// ## why is this not defined ?

	// Check if Hands are in Correct place

		if (!(edge_catch = LaraTestEdgeCatch(item, coll, &edge)))
			return;

		if ((edge_catch < 0)
		&&  (!LaraTestHangOnClimbWall(item, coll)))
			return;

	/* -------- determine wall angle */

		angle = item->pos.y_rot;

		if ( angle>=0-HANG_ANGLE && angle<=0+HANG_ANGLE)                     // North Wall
			angle = 0;
		else if ( angle>=16384-HANG_ANGLE && angle<=16384+HANG_ANGLE ) 		 // East Wall
			angle = 16384;
		else if ( angle>=32767-HANG_ANGLE || angle<=-32767+HANG_ANGLE ) 	 // South Wall
			angle = -32768;
		else if ( angle>=-16384-HANG_ANGLE && angle<=-16384+HANG_ANGLE )     // West Wall
			angle = -16384;

		if ( angle&0x3fff )
			return;

	/* -------- determine animation */

		if (TestHangSwingIn(item, angle))
		{
			lara.head_x_rot = lara.head_y_rot = 0;
			lara.torso_x_rot = lara.torso_y_rot = 0;
	 		item->anim_number = GRABLEDGEIN_A;
			item->frame_number = GRABLEDGEIN_F;
  			item->current_anim_state = AS_HANG2;
			item->goal_anim_state = AS_HANG2;
		}
		else
		{
	 		item->anim_number = GRABLEDGE_A;
			item->frame_number = GRABLEDGE_F;
  			item->current_anim_state = AS_HANG;
			item->goal_anim_state = AS_HANG;
		}

		bounds = GetBoundsAccurate( item );

		if (edge_catch>0)
		{
			item->pos.y_pos += coll->front_floor-bounds[2]; // catch edge
			item->pos.x_pos += coll->shift.x;
			item->pos.z_pos += coll->shift.z;
		}
		else
			item->pos.y_pos = edge - bounds[2];
			//item->pos.y_pos = ((item->pos.y_pos + bounds[2]) & ~(STEP_L-1)) - bounds[2]; // catch 1/4
		item->pos.y_rot = angle;
		item->gravity_status = 1;
		item->speed = 2;
		item->fallspeed = 1;
		lara.gun_status = LG_HANDSBUSY;
	}
}


/****************************************************************************
 *
 *	Dash
 *
\****************************************************************************/

void	lara_as_dash(ITEM_INFO *item, COLL_INFO *coll)
{
	if (item->hit_points <= 0)		// Time To Die!!!
	{
//		item->goal_anim_state = AS_DEATH;
		item->goal_anim_state = AS_RUN;
		return;
	}

	if ((!DashTimer)
	||  (!(input & IN_DASH))
	||  (lara.water_status == LARA_WADE))
	{
		item->goal_anim_state = AS_RUN;
		return;
	}
	DashTimer--;

	if ((input & IN_DUCK)
	&&  (lara.water_status != LARA_WADE))
	{
		item->goal_anim_state = AS_STOP;
		return;
	}


#ifdef ANALOG_CONTROL
	if (input & IN_LOOK)
		LookUpDown();
#endif

#ifdef PC_JOYSTICK
	lara.turn_rate = LARA_FAST_TURN * joy_x >> 4;
#endif

	if (input & IN_LEFT)
	{
#ifndef PC_JOYSTICK
		lara.turn_rate -= LARA_DASH_TURN_RATE;
		if ( lara.turn_rate < -LARA_DASH_TURN_MAX)
			lara.turn_rate = -LARA_DASH_TURN_MAX;
#endif
		item->pos.z_rot -= LARA_DASH_LEAN_RATE;
		if ( item->pos.z_rot < -LARA_DASH_LEAN_MAX )
			item->pos.z_rot = -LARA_DASH_LEAN_MAX;
	}
	else if (input & IN_RIGHT)
	{
#ifndef PC_JOYSTICK
		lara.turn_rate += LARA_DASH_TURN_RATE;
		if ( lara.turn_rate > LARA_DASH_TURN_MAX)
			lara.turn_rate = LARA_DASH_TURN_MAX;
#endif
		item->pos.z_rot += LARA_DASH_LEAN_RATE;
		if ( item->pos.z_rot > LARA_DASH_LEAN_MAX )
			item->pos.z_rot = LARA_DASH_LEAN_MAX;
	}

	if ((input & IN_JUMP)
	&&  (!item->gravity_status))
		item->goal_anim_state = AS_DASHDIVE;

	else if (input & IN_FORWARD)
	{
		if (input & IN_SLOW)
			item->goal_anim_state = AS_WALK;
		else
			item->goal_anim_state = AS_DASH;
	}
	else if (!(input & (IN_LEFT|IN_RIGHT)))
		item->goal_anim_state = AS_STOP;
}

void	lara_col_dash( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.move_angle = item->pos.y_rot;
	coll->bad_pos = NO_BAD_POS;
	coll->bad_neg = -STEPUP_HEIGHT;
	coll->bad_ceiling = 0;
	coll->slopes_are_walls = 1;

	GetLaraCollisionInfo( item, coll );

	if (LaraHitCeiling(item, coll))
		return;

	if (TestLaraVault(item, coll))
		return;

	if (LaraDeflectEdge(item, coll))		// Make Lara Stop because hit wall
	{                                       // straight on..
		item->pos.z_rot = 0;

		if (TestWall(item, 256, 0, -640))	// Test for wall at shoulder height
		{															  		// certain height in front
			item->current_anim_state = AS_SPLAT;
			item->anim_number = HITWALLLEFT_A;
			item->frame_number = HITWALLLEFT_F;
			return;

#if 0
			if ( item->frame_number>=0 && item->frame_number<=9 )
			{
				item->anim_number = HITWALLLEFT_A;
				item->frame_number = HITWALLLEFT_F;
				return;
			}
			if ( item->frame_number>=10 && item->frame_number<=21 )
			{
				item->anim_number = HITWALLRIGHT_A;
				item->frame_number = HITWALLRIGHT_F;
				return;
			}
#endif
		}

		LaraCollideStop(item, coll);
	}

	if (LaraFallen(item, coll))
		return;

	if ( coll->mid_floor >= -STEPUP_HEIGHT && coll->mid_floor < -STEP_L/2 )		// We need to step up
	{
		if ( item->frame_number>=3 && item->frame_number<=14 )
		{
			item->anim_number = RUNSTEPUP_LEFT_A; 			// So kick off Left or
			item->frame_number = RUNSTEPUP_LEFT_F;          // Right foot Animation
		}
		else
		{
			item->anim_number = RUNSTEPUP_RIGHT_A;
			item->frame_number = RUNSTEPUP_RIGHT_F;
		}
	}
	if ( TestLaraSlide(item,coll ) )
		return;
	if ( coll->mid_floor >= 50 ) 							// Weve RUN off a Smallish Step
	{                                                   	// so Let lara fall down
		item->pos.y_pos += 50;
		return;
	}
	item->pos.y_pos += coll->mid_floor;							// Otherwise Position Is OK..
}

/****************************************************************************
 *
 *	Dive From Dash
 *
\****************************************************************************/

void	lara_as_dashdive(ITEM_INFO *item, COLL_INFO *coll)
{
	if ((item->goal_anim_state != AS_DEATH)
	&&  (item->goal_anim_state != AS_STOP)
	&&  (item->goal_anim_state != AS_RUN))
	{
		if (item->fallspeed > LARA_FASTFALL_SPEED)	// Fastfall has highest Priority
			item->goal_anim_state = AS_FASTFALL;	// for State changes
	}
}

void	lara_col_dashdive(ITEM_INFO *item, COLL_INFO *coll )
{
	if (item->speed >= 0)
		lara.move_angle = item->pos.y_rot;
	else
		lara.move_angle = item->pos.y_rot-0x8000;

	coll->bad_pos = NO_BAD_POS;
	coll->bad_neg = -STEP_L;
	coll->slopes_are_walls = 1;
	coll->bad_ceiling = BAD_JUMP_CEILING;

	GetLaraCollisionInfo( item, coll );

	LaraDeflectEdgeJump( item,coll );

	if (LaraFallen(item, coll))
		return;

	if (item->speed < 0)
		lara.move_angle = item->pos.y_rot;

/* -------- landed */

	if ((coll->mid_floor <= 0)
	&&  (item->fallspeed > 0))
	{                                                   // and have landed..
#ifndef INVINCABLE_LARA
		if (LaraLandedBad(item,coll))
			item->goal_anim_state = AS_DEATH;			// If Died cos fallen too far
		else
#endif
		{
			if (lara.water_status == LARA_WADE)
				item->goal_anim_state = AS_STOP;
			else
			{
				if ( input&IN_FORWARD && !(input&IN_SLOW) )
					item->goal_anim_state = AS_RUN;    		// We are now landing
				else                                   		// into a run or stop
					item->goal_anim_state = AS_STOP;
			}
		}
		item->fallspeed = 0;
		item->pos.y_pos += coll->mid_floor;
		item->gravity_status = 0;
		item->speed = 0;
		AnimateLara(item);								// Move Lara and animate...
	}

	ShiftItem(item, coll);
	item->pos.y_pos += coll->mid_floor;
}

/****************************************************************************
 *
 *	Monkey Swing
 *
\****************************************************************************/

#define HANG_HEIGHT 600

static void MonkeySwingFall(ITEM_INFO *item)
{
	item->goal_anim_state = AS_UPJUMP;
	item->current_anim_state = AS_UPJUMP;
	item->anim_number = STOPHANG_A;
	item->frame_number = STOPHANG_F;
	item->gravity_status = 1;
	item->speed = 2;
	item->fallspeed = 1;
	item->pos.y_pos += 256;
	lara.gun_status = LG_ARMLESS;
}

static void MonkeySwingSnap(ITEM_INFO *item, COLL_INFO *coll)
{
	sint16 room_num;
	FLOOR_INFO *floor;

	room_num = item->room_number;
	floor = GetFloor(item->pos.x_pos, item->pos.y_pos, item->pos.z_pos, &room_num);
	item->pos.y_pos = GetCeiling(floor, item->pos.x_pos, item->pos.y_pos, item->pos.z_pos) + (768-64);
}

static sint16 GetDirOctant(sint32 rot)
{
	if ((abs(rot) < 8192) || (abs(rot) > 24576))
		return 0;
	else
		return 1;
}

static sint16 TestMonkeyLeft(ITEM_INFO *item, COLL_INFO *coll)
{
	coll->bad_pos = NO_BAD_POS;
	coll->bad_neg = NO_BAD_NEG;
	coll->bad_ceiling = 0;
	coll->facing = lara.move_angle = item->pos.y_rot-16384;
	coll->radius = LARA_RAD;
	coll->slopes_are_walls = 0;
	GetCollisionInfo(coll, item->pos.x_pos, item->pos.y_pos, item->pos.z_pos, item->room_number, HANG_HEIGHT);

	if (abs(coll->mid_ceiling - coll->front_ceiling) > 50)
		return 0;

	if (coll->coll_type)
	{
		sint16 oct;

		oct = GetDirOctant(item->pos.y_rot);

		if (((oct == 0) && (coll->coll_type == COLL_FRONT))
		||  ((oct == 0) && (coll->coll_type == COLL_LEFT))
		||  ((oct == 1) && (coll->coll_type == COLL_RIGHT))
		||  ((oct == 1) && (coll->coll_type == COLL_LEFT)))
			return 0;
	}
	return 1;
}

static sint16 TestMonkeyRight(ITEM_INFO *item, COLL_INFO *coll)
{
	coll->bad_pos = NO_BAD_POS;
	coll->bad_neg = -STEPUP_HEIGHT;
	coll->bad_ceiling = 0;
	coll->facing = lara.move_angle = item->pos.y_rot+16384;
	coll->radius = LARA_RAD;
	coll->slopes_are_walls = 0;
	GetCollisionInfo(coll, item->pos.x_pos, item->pos.y_pos, item->pos.z_pos, item->room_number, HANG_HEIGHT);

	if (abs(coll->mid_ceiling - coll->front_ceiling) > 50)
		return 0;

	if (coll->coll_type)
	{
		sint16 oct;

		oct = GetDirOctant(item->pos.y_rot);

		if (((oct == 0) && (coll->coll_type == COLL_FRONT))
		||  ((oct == 1) && (coll->coll_type == COLL_FRONT))
		||  ((oct == 1) && (coll->coll_type == COLL_RIGHT))
		||  ((oct == 1) && (coll->coll_type == COLL_LEFT)))
			return 0;
	}
	return 1;
}

void	lara_as_hang2(ITEM_INFO *item, COLL_INFO *coll)
{
	if (item->hit_points <= 0)		// Time To Die!!!
	{
		item->goal_anim_state = AS_STOP;
		return;
	}

	coll->enable_spaz = 0;
	coll->enable_baddie_push = 0;

	lara.torso_x_rot = lara.torso_y_rot = 0;

	if (lara.CanMonkeySwing)
	{
		if ((!(input & IN_ACTION))
		||  (item->hit_points <= 0))
			return MonkeySwingFall(item);

		camera.target_angle = CAM_A_HANG;
		camera.target_elevation = CAM_E_HANG;
	}
	else
	{
		if (input & IN_LOOK)
			LookUpDown();
	}
}

void	lara_col_hang2(ITEM_INFO *item, COLL_INFO *coll)
{
	if (lara.CanMonkeySwing)
	{
		coll->bad_pos = NO_BAD_POS;
		coll->bad_neg = NO_BAD_NEG;
//		coll->bad_neg = -STEPUP_HEIGHT;
		coll->bad_ceiling = 0;
		coll->facing = lara.move_angle = item->pos.y_rot;
		coll->radius = LARA_RAD;
//		coll->radius = LARA_RAD*2;
		coll->slopes_are_walls = 0;
		GetCollisionInfo(coll, item->pos.x_pos, item->pos.y_pos, item->pos.z_pos, item->room_number, HANG_HEIGHT);

		if ((input & IN_FORWARD)
		&&  (coll->coll_type != COLL_FRONT)
		&&  (abs(coll->mid_ceiling - coll->front_ceiling) < 50))
			item->goal_anim_state = AS_MONKEYSWING;

		else if ((input & IN_STEPL)
			&&  (TestMonkeyLeft(item, coll)))
	  			item->goal_anim_state = AS_MONKEYL;

		else if ((input & IN_STEPR)
			&&  (TestMonkeyRight(item, coll)))
				item->goal_anim_state = AS_MONKEYR;

		else if (input & IN_LEFT)
			item->goal_anim_state = AS_HANGTURNL;

		else if (input & IN_RIGHT)
			item->goal_anim_state = AS_HANGTURNR;

		MonkeySwingSnap(item, coll);
	}
	else
	{
		LaraHangTest(item, coll);

		if (item->goal_anim_state == AS_HANG2)
		{
			if (input & IN_FORWARD)
			{
				if ((coll->front_floor > -850)
				&&  (coll->front_floor < -650)
				&&  (coll->front_floor - coll->front_ceiling >= 0)
//##				&&  (coll->left_floor - coll->left_ceiling >= 0)
//##				&&  (coll->right_floor - coll->right_ceiling >= 0)
				&&  (coll->left_floor2 - coll->left_ceiling2 >= 0)
				&&  (coll->right_floor2 - coll->right_ceiling2 >= 0)
				&&  (!coll->hit_static))
				{
					if (input & IN_SLOW)
						item->goal_anim_state = AS_GYMNAST;
					else
						item->goal_anim_state = AS_NULL;

					return;
				}
#if 0
				else if ((lara.climb_status)
					&&  (item->anim_number == HANG_A)
					&&  (item->frame_number == HANG_F)
					&&  (coll->mid_ceiling <= -256))
					{
						item->goal_anim_state = AS_HANG;
						item->current_anim_state = AS_HANG;
						item->anim_number = HANGUP_A;
						item->frame_number = HANGUP_F;

						return;
					}
#endif
			}

			if ((input & (IN_DUCK|IN_FORWARD))
			&&  (coll->front_floor > -850)
			&&  (coll->front_floor < -650)
			&&  (coll->front_floor-coll->front_ceiling >= -STEP_L)
//##			&&  (coll->left_floor-coll->left_ceiling >= -STEP_L)
//##			&&  (coll->right_floor-coll->right_ceiling >= -STEP_L)
			&&  (coll->left_floor2-coll->left_ceiling2 >= -STEP_L)
			&&  (coll->right_floor2-coll->right_ceiling2 >= -STEP_L)
			&&  (!coll->hit_static))
			{
		    		item->goal_anim_state = AS_HANG2DUCK;
		    		item->required_anim_state = AS_DUCK;
			}
#if 0
			else if ((input & IN_BACK)
				&&  (lara.climb_status)
				&&  (item->anim_number == HANG_A)
				&&  (item->frame_number == HANG_F))
				{
					item->goal_anim_state = AS_HANG;
					item->current_anim_state = AS_HANG;
					item->anim_number = HANGDOWN_A;
					item->frame_number = HANGDOWN_F;
				}
#endif
			else if (input&IN_LEFT || input&IN_STEPL)
				item->goal_anim_state = AS_HANGLEFT;

			else if (input&IN_RIGHT || input&IN_STEPR)
				item->goal_anim_state = AS_HANGRIGHT;
		}
	}
}

void	lara_as_hang2duck(ITEM_INFO *item, COLL_INFO *coll)
{

}

/* -------- swing forwards */

void	lara_as_monkeyswing(ITEM_INFO *item, COLL_INFO *coll)
{
	if (item->hit_points <= 0)		// Time To Die!!!
	{
		item->goal_anim_state = AS_HANG2;
		return;
	}

	coll->enable_spaz = 0;
	coll->enable_baddie_push = 0;

	lara.torso_x_rot = lara.torso_y_rot = 0;

	if (input & IN_FORWARD)
		item->goal_anim_state = AS_MONKEYSWING;
	else
		item->goal_anim_state = AS_HANG2;

	if (input & IN_LEFT)
	{
		lara.turn_rate -= LARA_TURN_RATE;

		if (lara.turn_rate < -LARA_JUMP_TURN)
			lara.turn_rate = -LARA_JUMP_TURN;
	}
	else if (input & IN_RIGHT)
	{
		lara.turn_rate += LARA_TURN_RATE;

		if (lara.turn_rate > LARA_JUMP_TURN)
			lara.turn_rate = LARA_JUMP_TURN;
	}
}

void	lara_col_monkeyswing(ITEM_INFO *item, COLL_INFO *coll)
{
	if ((!(input & IN_ACTION))
	||  (!(lara.CanMonkeySwing)))
		return MonkeySwingFall(item);

	coll->bad_pos = NO_BAD_POS;
	coll->bad_neg = NO_BAD_NEG;
	coll->bad_ceiling = 0;
	coll->facing = lara.move_angle = item->pos.y_rot;
	coll->radius = LARA_RAD;
	coll->slopes_are_walls = 0;
	GetCollisionInfo(coll, item->pos.x_pos, item->pos.y_pos, item->pos.z_pos, item->room_number, HANG_HEIGHT);

	if ((coll->coll_type == COLL_FRONT)
	||  (abs(coll->mid_ceiling - coll->front_ceiling) > 50))
	{
		item->current_anim_state = AS_HANG2;
		item->goal_anim_state = AS_HANG2;
		item->anim_number = MONKEYHANG_A;
		item->frame_number = MONKEYHANG_F;
		return;
	}

	camera.target_elevation = 10*ONE_DEGREE;

	MonkeySwingSnap(item, coll);
}

/* -------- swing left */

void	lara_as_monkeyl(ITEM_INFO *item, COLL_INFO *coll)
{
	if (item->hit_points <= 0)		// Time To Die!!!
	{
		item->goal_anim_state = AS_HANG2;
		return;
	}

	coll->enable_spaz = 0;
	coll->enable_baddie_push = 0;

	lara.torso_x_rot = lara.torso_y_rot = 0;

	if (input & IN_STEPL)
		item->goal_anim_state = AS_MONKEYL;
	else
		item->goal_anim_state = AS_HANG2;

	camera.target_elevation = 10*ONE_DEGREE;
}

void	lara_col_monkeyl(ITEM_INFO *item, COLL_INFO *coll)
{
	if ((!(input & IN_ACTION))
	||  (!(lara.CanMonkeySwing)))
		return MonkeySwingFall(item);

	if (!TestMonkeyLeft(item, coll))
	{
		item->current_anim_state = AS_HANG2;
		item->goal_anim_state = AS_HANG2;
		item->anim_number = MONKEYHANG_A;
		item->frame_number = MONKEYHANG_F;
	}
	else
		MonkeySwingSnap(item, coll);
}

/* -------- swing right */

void	lara_as_monkeyr(ITEM_INFO *item, COLL_INFO *coll)
{
	if (item->hit_points <= 0)		// Time To Die!!!
	{
		item->goal_anim_state = AS_HANG2;
		return;
	}

	lara.torso_x_rot = lara.torso_y_rot = 0;
	coll->enable_spaz = 0;
	coll->enable_baddie_push = 0;

	if (input & IN_STEPR)
		item->goal_anim_state = AS_MONKEYR;
	else
		item->goal_anim_state = AS_HANG2;

	camera.target_elevation = 10*ONE_DEGREE;
}

void	lara_col_monkeyr(ITEM_INFO *item, COLL_INFO *coll)
{
	if ((!(input & IN_ACTION))
	||  (!(lara.CanMonkeySwing)))
		return MonkeySwingFall(item);

	if (!TestMonkeyRight(item, coll))
	{
		item->current_anim_state = AS_HANG2;
		item->goal_anim_state = AS_HANG2;
		item->anim_number = MONKEYHANG_A;
		item->frame_number = MONKEYHANG_F;
		return;
	}
	else
		MonkeySwingSnap(item, coll);
}

void lara_as_hangturnl(ITEM_INFO *item, COLL_INFO *coll)
{
	if (item->hit_points <= 0)		// Time To Die!!!
	{
		item->goal_anim_state = AS_HANG2;
		return;
	}

	camera.target_elevation = 10*ONE_DEGREE;
	lara.torso_x_rot = lara.torso_y_rot = 0;

	item->pos.y_rot -= (ONE_DEGREE + (ONE_DEGREE/2));

	if (!(input & IN_LEFT))
		item->goal_anim_state = AS_HANG2;
}

void lara_col_hangturnlr(ITEM_INFO *item, COLL_INFO *coll)
{
	if ((!(input & IN_ACTION))
	||  (!lara.CanMonkeySwing))
		return MonkeySwingFall(item);

	coll->bad_pos = NO_BAD_POS;
	coll->bad_neg = -STEPUP_HEIGHT;
	coll->bad_ceiling = 0;
	coll->facing = lara.move_angle = item->pos.y_rot;
	coll->radius = LARA_RAD;
	coll->slopes_are_walls = 1;
	GetCollisionInfo(coll, item->pos.x_pos, item->pos.y_pos, item->pos.z_pos, item->room_number, HANG_HEIGHT);

	MonkeySwingSnap(item, coll);
}

void lara_as_hangturnr(ITEM_INFO *item, COLL_INFO *coll)
{
	if (item->hit_points <= 0)		// Time To Die!!!
	{
		item->goal_anim_state = AS_HANG2;
		return;
	}

	lara.torso_x_rot = lara.torso_y_rot = 0;
	camera.target_elevation = 10*ONE_DEGREE;

	item->pos.y_rot += (ONE_DEGREE + (ONE_DEGREE/2));

	if (!(input & IN_RIGHT))
		item->goal_anim_state = AS_HANG2;
}

void	lara_as_monkey180(ITEM_INFO *item, COLL_INFO *coll)
{
	coll->enable_spaz = 0;
	coll->enable_baddie_push = 0;

	item->goal_anim_state = AS_HANG2;
}

void	lara_col_monkey180(ITEM_INFO *item, COLL_INFO *coll)
{
	lara_col_monkeyswing(item, coll);
}

/****************************************************************************
 *
 *	Stationary - fixed by Chris - thrice!
 *
\****************************************************************************/

void	lara_as_stop( ITEM_INFO *item, COLL_INFO *coll )
{
	sint16 fheight = NO_HEIGHT;
	sint16 rheight = NO_HEIGHT;

#ifdef ANALOG_CONTROL
	static char wait=0;
#endif

	if (item->hit_points <= 0)
	{
		item->goal_anim_state = AS_DEATH;
		return;
	}

	if ((item->anim_number != 226)	// dash skid anims
	&&  (item->anim_number != 228))
		StopSoundEffect(3); 	// stop slide sound

	if ((input & IN_ROLL)
	&&  (lara.water_status != LARA_WADE))
	{
		item->anim_number = ROLL_A;
		item->frame_number = ROLL_F;
		item->current_anim_state = AS_ROLL;
		item->goal_anim_state = AS_STOP;
		return;
	}

	if ((input & IN_DUCK)
	&&  (lara.water_status != LARA_WADE)
	&&  (item->current_anim_state == AS_STOP)
	&& ((lara.gun_status == LG_ARMLESS)
	||  (lara.gun_type == LG_UNARMED)
	||  (lara.gun_type == LG_PISTOLS)
	||  (lara.gun_type == LG_MAGNUMS)
	||  (lara.gun_type == LG_UZIS)
	||  (lara.gun_type == LG_FLARE)))
	{
		item->goal_anim_state = AS_DUCK;
		return;
	}

	item->goal_anim_state = AS_STOP;

	/* If using Look Key enable Lara to Look around */
	if (input & IN_LOOK)
		LookUpDown();

#ifdef ANALOG_CONTROL
	if (input & (IN_FORWARD|IN_BACK|IN_LEFT|IN_RIGHT|IN_STEPL|IN_STEPR))
	{
		if (input & IN_SLOW)
		{
			if (wait < 2)
			{
				wait++;
				return;
			}
		}
	}
	else
		wait = 0;
#endif

	if (input & IN_FORWARD)
		fheight = LaraFloorFront(item, item->pos.y_rot, LARA_RAD+4);

	else if (input & IN_BACK)
		rheight = LaraFloorFront(item, item->pos.y_rot+32768, LARA_RAD+4);

	if (room[item->room_number].flags & SWAMP)
	{
		if (input & IN_LEFT)
			item->goal_anim_state = AS_TURN_L;

		else if (input & IN_RIGHT)
			item->goal_anim_state = AS_TURN_R;
	}
	else
	{
		if (input & IN_STEPL)
		{
			sint16 height,ceiling;

			height = LaraFloorFront(item, item->pos.y_rot-16384, LARA_RAD+48);
			ceiling = LaraCeilingFront(item, item->pos.y_rot-16384, LARA_RAD+48);

			if ((height < 128)
			&&  (height > -128)
			&&  (height_type != BIG_SLOPE)
			&&  (ceiling <= 0))
	 			item->goal_anim_state = AS_STEPLEFT;
		}
		else if (input & IN_STEPR)
		{
			sint16 height,ceiling;

			height = LaraFloorFront(item, item->pos.y_rot+16384, LARA_RAD+48);
			ceiling = LaraCeilingFront(item, item->pos.y_rot+16384, LARA_RAD+48);

			if ((height < 128)
			&&  (height > -128)
			&&  (height_type != BIG_SLOPE)
			&&  (ceiling <= 0))
				item->goal_anim_state = AS_STEPRIGHT;
		}

		else if (input & IN_LEFT)                           	// Do Turning...
			item->goal_anim_state = AS_TURN_L;

		else if (input & IN_RIGHT)
			item->goal_anim_state = AS_TURN_R;
	}

/* -------- wading */

	if (lara.water_status == LARA_WADE)
	{
		if ((input & IN_JUMP)
		&&  (!(room[item->room_number].flags & SWAMP)))
			item->goal_anim_state = AS_COMPRESS;

		if (input & IN_FORWARD)
		{
			int wade = 0;

			if (room[item->room_number].flags & SWAMP)
			{
				if (fheight > -(STEPUP_HEIGHT-1))
				{
					lara_as_wade(item, coll);
					wade = 1;
				}
			}

			else
			{
				if ((fheight < (STEPUP_HEIGHT-1))
				&&  (fheight > -(STEPUP_HEIGHT-1)))
				{
					lara_as_wade(item, coll);
					wade = 1;
				}
			}

			if (!wade)
			{
				lara.move_angle = item->pos.y_rot;
				coll->bad_pos = NO_BAD_POS;
				coll->bad_neg = -STEPUP_HEIGHT;
				coll->bad_ceiling = 0;
				coll->slopes_are_walls = 1;
				coll->radius = LARA_RAD+2;
				GetLaraCollisionInfo(item, coll);

				if (TestLaraVault(item, coll))
					return;

				coll->radius = LARA_RAD;
			}
		}
		else if (input & IN_BACK)
		{
			if ((rheight < (STEPUP_HEIGHT-1))
			&&  (rheight > -(STEPUP_HEIGHT-1)))
				lara_as_back(item, coll);
		}
	}

/* -------- on land */

	else
	{
		if (input & IN_JUMP)
			item->goal_anim_state = AS_COMPRESS;

		else if (input & IN_FORWARD)
		{
			sint16 room;
			FLOOR_INFO *floor;
			sint32 x, y, z, height,ceiling;

			height = LaraFloorFront(item, item->pos.y_rot, LARA_RAD+4);
			ceiling = LaraCeilingFront(item, item->pos.y_rot, LARA_RAD+4);

			if ((height_type == BIG_SLOPE) && (height < 0))
			{
				item->goal_anim_state = AS_STOP;
				return;
			}

//			x = item->pos.x_pos + ((phd_sin(item->pos.y_rot) * (LARA_RAD*2)) >> W2V_SHIFT);
//			y = item->pos.y_pos - LARA_HITE;
//			z = item->pos.z_pos + ((phd_cos(item->pos.y_rot) * (LARA_RAD*2)) >> W2V_SHIFT);
//			room = item->room_number;

//			floor=GetFloor(x, y, z, &room);  				// Get ceiling directly in front
//			height = GetCeiling(floor, x, y, z);

//##			if (height == NO_HEIGHT)
//##				return;

//##			if ((height -= item->pos.y_pos) > -LARA_HITE)
//			if (height != NO_HEIGHT && (height - item->pos.y_pos) > -LARA_HITE)

			if (ceiling > 0)
			{
				item->goal_anim_state = AS_STOP;
				return;
			}

			if (input & IN_SLOW)
				lara_as_walk(item, coll);
			else
				lara_as_run(item, coll);
		}

		else if (input & IN_BACK)
		{
			if (input & IN_SLOW)
			{
				if ((rheight < (STEPUP_HEIGHT-1))
				&&  (rheight > -(STEPUP_HEIGHT-1))
				&&  (height_type != BIG_SLOPE))
					lara_as_back(item, coll);
			}
			else
			{
				if (rheight > -(STEPUP_HEIGHT-1))
					item->goal_anim_state = AS_FASTBACK;
			}
		}
	}
}

void	lara_col_stop(ITEM_INFO *item, COLL_INFO *coll)
{
	item->gravity_status = item->fallspeed = 0;	// No Gravity Effects
	lara.move_angle = item->pos.y_rot;
	coll->bad_pos = STEPUP_HEIGHT;
	coll->bad_neg = -STEPUP_HEIGHT;
	coll->bad_ceiling = 0;
	coll->slopes_are_pits = 1;
	coll->slopes_are_walls = 1;
	GetLaraCollisionInfo(item, coll);

	if (LaraHitCeiling(item, coll))
		return;

	if (LaraFallen(item, coll))
		return;

	if (TestLaraSlide(item, coll))
		return;

	ShiftItem(item, coll);

// Enforce to floor height.. if not a swamp room.
	if (!(room[item->room_number].flags & SWAMP)
	||  (coll->mid_floor < 0))
		item->pos.y_pos += coll->mid_floor;

	else if ((room[item->room_number].flags & SWAMP)
		&&  (coll->mid_floor))
		item->pos.y_pos += SWAMP_GRAVITY;
}

/****************************************************************************
 *
 *	Upwards Jump
 *
\****************************************************************************/

static int LaraTestHangJumpUp(ITEM_INFO *item, COLL_INFO *coll)
{
	sint32 edge;
	int edge_catch;
	sint16 *bounds;
	PHD_ANGLE angle;

	if ((!(input & IN_ACTION))
	||  (lara.gun_status != LG_ARMLESS)
	||  (coll->hit_static))
		return 0;

/* -------- initialise monkey swing */

	if ((lara.CanMonkeySwing)
	&&  (coll->coll_type == COLL_TOP))
	{
		item->goal_anim_state = AS_HANG2;
		item->current_anim_state = AS_HANG2;
		item->anim_number = UPJUMPGRAB_A;
		item->frame_number = UPJUMPGRAB_F;
		item->gravity_status = 0;
		item->speed = 0;
		item->fallspeed = 0;
		lara.gun_status = LG_HANDSBUSY;
		MonkeySwingSnap(item, coll);
		return 1;
	}

/* -------- catch on edge of block or climbable wall ? */

	if ((coll->coll_type != COLL_FRONT)
	||  (coll->mid_ceiling > -STEPUP_HEIGHT))
		return 0;

	if (!(edge_catch = LaraTestEdgeCatch(item, coll, &edge)))
		return 0;

	if ((edge_catch < 0)
	&&  (!LaraTestHangOnClimbWall(item, coll)))
		return 0;

/* -------- initialise catch */

	angle = item->pos.y_rot;

	if ( angle>=0-HANG_ANGLE && angle<=0+HANG_ANGLE)                     // North Wall
		angle = 0;
	else if ( angle>=16384-HANG_ANGLE && angle<=16384+HANG_ANGLE ) 		 // East Wall
		angle = 16384;
	else if ( angle>=32767-HANG_ANGLE || angle<=-32767+HANG_ANGLE ) 	 // South Wall
		angle = -32768;
	else if ( angle>=-16384-HANG_ANGLE && angle<=-16384+HANG_ANGLE )     // West Wall
		angle = -16384;
	if ( angle&0x3fff )
		return(0);

	if (TestHangSwingIn(item,angle))
	{
	 	item->anim_number = UPJUMPGRAB_A;
		item->frame_number = UPJUMPGRAB_F;
		item->goal_anim_state = AS_HANG2;
		item->current_anim_state = AS_HANG2;
//##		item->goal_anim_state = AS_HANG;									// Jump straight to Hang
//##		item->current_anim_state = AS_HANG;                                 // status
//##		item->anim_number = STARTHANG_A;
//##		item->frame_number = STARTHANG_F;
	}
	else
	{
		item->goal_anim_state = AS_HANG;									// Jump straight to Hang
		item->current_anim_state = AS_HANG;                                 // status
		item->anim_number = STARTHANG_A;
		item->frame_number = STARTHANG_F;
	}

	bounds = GetBoundsAccurate( item );
	if (edge_catch>0)
		item->pos.y_pos += coll->front_floor - bounds[2]; // catch edge
	else
		item->pos.y_pos = edge - bounds[2];
	item->pos.x_pos += coll->shift.x;
	item->pos.z_pos += coll->shift.z;
	item->pos.y_rot = angle;
	item->gravity_status = 0;
	item->speed = 0;
	item->fallspeed = 0;
	lara.gun_status = LG_HANDSBUSY;
	lara.torso_x_rot = lara.torso_y_rot = 0;
	return 1;
}

void	lara_as_upjump(ITEM_INFO *item, COLL_INFO *coll)
{
	if (item->fallspeed > LARA_FASTFALL_SPEED)
		item->goal_anim_state = AS_FASTFALL;
}

void	lara_col_upjump(ITEM_INFO *item, COLL_INFO *coll)
{
	if (item->hit_points <= 0)
	{
		item->goal_anim_state = AS_STOP;
		return;
	}

	lara.move_angle = item->pos.y_rot;
	coll->bad_pos = NO_BAD_POS;
	coll->bad_neg = -STEPUP_HEIGHT;
	coll->bad_ceiling = BAD_JUMP_CEILING;
	coll->facing = (item->speed < 0) ? lara.move_angle-32768 : lara.move_angle;
	coll->hit_ceiling = 0;

	GetCollisionInfo(coll,
				  item->pos.x_pos,
				  item->pos.y_pos,
				  item->pos.z_pos,
				  item->room_number,
				  870);	// ## why is this not defined ?

	if (LaraTestHangJumpUp(item, coll))
		return;

//	LaraSlideEdgeJump( item,coll );	//SONY BUG FIX A30
	ShiftItem( item,coll );			//STOPS LARA GOING INTO BLACKNESS IN CLAMPED CORNERS EG.'EMPRTOMB' START
	if (coll->coll_type==COLL_CLAMP || coll->coll_type==COLL_TOP || coll->coll_type==COLL_TOPFRONT || coll->hit_ceiling)
//##		item->goal_anim_state = AS_STOP;
		item->fallspeed = 1;
	// Gav
	if (coll->coll_type)
		item->speed = (item->speed>0)? 2 : -2;
	else if (item->fallspeed < -70)
	{
		if (input & IN_FORWARD && item->speed < 5)
			item->speed++;
		else if (input & IN_BACK && item->speed > -5)
			item->speed-=2; //needs more for back jump to get onto 3/4 block
	}
	// End
	if ( item->fallspeed > 0 )								// We are now falling
	{
		if ( coll->mid_floor <= 0 )
		{                                                   // IF Landed
#ifndef INVINCABLE_LARA
  			if ( LaraLandedBad(item,coll) )					// So either Die
				item->goal_anim_state = AS_DEATH;
			else
#endif
				item->goal_anim_state = AS_STOP;			// Or Stop
			item->fallspeed = 0;
			item->pos.y_pos += coll->mid_floor;
			item->gravity_status = 0;
		}
	}
}

//--------------------------- FORWARDJUMP --------------------------------------

void	lara_as_forwardjump( ITEM_INFO *item, COLL_INFO *coll )
{
	if ((item->goal_anim_state == AS_SWANDIVE)
	||  (item->goal_anim_state == AS_REACH))
		item->goal_anim_state = AS_FORWARDJUMP;

	if ((item->goal_anim_state != AS_DEATH)
	&&  (item->goal_anim_state != AS_STOP)
	&&  (item->goal_anim_state != AS_RUN))
	{
		if ( (input&IN_ACTION) && lara.gun_status==LG_ARMLESS)
			item->goal_anim_state = AS_REACH;

		if ((input&IN_ROLL) || (input&IN_BACK))
			item->goal_anim_state = AS_TWIST;

		if ( (input&IN_SLOW) && lara.gun_status==LG_ARMLESS)
			item->goal_anim_state = AS_SWANDIVE;

		if (item->fallspeed > LARA_FASTFALL_SPEED)		// Fastfall has highest Priority
			item->goal_anim_state = AS_FASTFALL;        // for State changes
	}

	if ( input&IN_LEFT )							// TURN While Jumping..
	{
		lara.turn_rate -= LARA_TURN_RATE;
		if ( lara.turn_rate < -LARA_JUMP_TURN )
			lara.turn_rate = -LARA_JUMP_TURN;
	}
	else if ( input&IN_RIGHT )
	{
		lara.turn_rate += LARA_TURN_RATE;
		if ( lara.turn_rate > LARA_JUMP_TURN )
			lara.turn_rate = LARA_JUMP_TURN;
	}
}

/******************************************************************************
 ******************************************************************************
 *					Lara control Routines Are Here
 *			these Request Different Anim States according to input..
 ******************************************************************************
 *****************************************************************************/

//-------------------------------------- WALK ---------------------------------

void	lara_as_walk( ITEM_INFO *item, COLL_INFO *coll )
{
	if ( item->hit_points<=0 ) 					// Time To Die!!!
	{
		item->goal_anim_state = AS_STOP;
		return;
	}

#ifdef ANALOG_CONTROL
	if (input & IN_LOOK)
		LookUpDown();
#endif

#ifdef PC_JOYSTICK
	lara.turn_rate = LARA_FAST_TURN * joy_x >> 4;
#endif
	if ( input&IN_LEFT )
	{
#ifndef PC_JOYSTICK
		lara.turn_rate -= LARA_TURN_RATE;
#endif
		if ( lara.turn_rate < -LARA_SLOW_TURN )
			lara.turn_rate = -LARA_SLOW_TURN;
	}
	else if ( input&IN_RIGHT )
	{
#ifndef PC_JOYSTICK
		lara.turn_rate += LARA_TURN_RATE;
#endif
		if ( lara.turn_rate > LARA_SLOW_TURN )
			lara.turn_rate = LARA_SLOW_TURN;
	}
	if ( input & IN_FORWARD )
	{
		if (lara.water_status==LARA_WADE)
		{
			item->goal_anim_state = AS_WADE;
		}
		else
		{
			if (!( input&IN_SLOW ))
				item->goal_anim_state = AS_RUN;
			else
				item->goal_anim_state = AS_WALK;
		}
	}
	else
		item->goal_anim_state = AS_STOP;
}


//---------------------------------------  RUN  -------------------------------

void	lara_as_run( ITEM_INFO *item, COLL_INFO *coll )
{
	static int jump_ok = 1;

	if ( item->hit_points<=0 ) 					// Time To Die!!!
	{
		item->goal_anim_state = AS_DEATH;
		return;
	}

	if (input & IN_ROLL)
	{
		item->anim_number =  ROLL_A;
		item->frame_number = ROLL_F;
		item->current_anim_state = AS_ROLL;
		item->goal_anim_state = AS_STOP;
		return;
	}

	if ((input & IN_DASH) && (DashTimer == LARA_DASH_TIME))
	{
		item->goal_anim_state = AS_DASH;
		return;
	}

	if ((input & IN_DUCK)
	&&  (lara.water_status != LARA_WADE))
	{
		item->goal_anim_state = AS_STOP;
		return;
	}

#ifdef ANALOG_CONTROL
	if (input & IN_LOOK)
		LookUpDown();
#endif

#ifdef PC_JOYSTICK
	lara.turn_rate = LARA_FAST_TURN * joy_x >> 4;
#endif

	if ( input&IN_LEFT )
	{
#ifndef PC_JOYSTICK
		lara.turn_rate -= LARA_TURN_RATE;
		if ( lara.turn_rate < -LARA_FAST_TURN )
			lara.turn_rate = -LARA_FAST_TURN;
#endif
		item->pos.z_rot -= LARA_LEAN_RATE;
		if ( item->pos.z_rot< - LARA_LEAN_MAX )
			item->pos.z_rot = -LARA_LEAN_MAX;
	}
	else if ( input&IN_RIGHT )
	{
#ifndef PC_JOYSTICK
		lara.turn_rate += LARA_TURN_RATE;
		if ( lara.turn_rate > LARA_FAST_TURN )
			lara.turn_rate = LARA_FAST_TURN;
#endif
		item->pos.z_rot += LARA_LEAN_RATE;
		if ( item->pos.z_rot > LARA_LEAN_MAX )
			item->pos.z_rot = LARA_LEAN_MAX;
	}

	/* Gav: jump lock during stop2run anim (anim 6) */
   if (item->anim_number == 6)
		jump_ok = 0;
	else if (item->anim_number == 0)
	{
		// If proper run anim, wait till frame 4 before removing jump lock
		if (item->frame_number == 4)
			jump_ok = 1;
	}
	else // if any other anim, reset jump lock (if it is engaged; could happen if player stopped during stop2run anim)
		jump_ok = 1;

	if ( input&IN_JUMP && jump_ok && !item->gravity_status )
		item->goal_anim_state = AS_FORWARDJUMP;
	else if (input & IN_FORWARD )
	{
		if (lara.water_status==LARA_WADE)
		{
			item->goal_anim_state = AS_WADE;
		}
		else
		{
			if ( input&IN_SLOW )
				item->goal_anim_state = AS_WALK;
			else
				item->goal_anim_state = AS_RUN;
		}
	}
	else
		item->goal_anim_state = AS_STOP;
}

//------------------------------- POSE ----------------------------------------

void	lara_as_pose( ITEM_INFO *item, COLL_INFO *coll )
{
}

//------------------------------- FASTBACK ------------------------------------

void	lara_as_fastback( ITEM_INFO *item, COLL_INFO *coll )
{
	item->goal_anim_state = AS_STOP;
	if ( input&IN_LEFT )
	{
		lara.turn_rate -= LARA_TURN_RATE;
		if ( lara.turn_rate < -LARA_MED_TURN )
			lara.turn_rate = -LARA_MED_TURN;
	}
	else if ( input&IN_RIGHT )
	{
		lara.turn_rate += LARA_TURN_RATE;
		if ( lara.turn_rate > LARA_MED_TURN )
			lara.turn_rate = LARA_MED_TURN;
	}
}

//-------------------------------- TURN R -------------------------------------

void	lara_as_turn_r( ITEM_INFO *item, COLL_INFO *coll )
{
	if (item->hit_points <=0)
	{
		item->goal_anim_state = AS_STOP;
		return;
	}

#ifdef PC_JOYSTICK
	lara.turn_rate = joy_x * LARA_FAST_TURN >> 4;
#else
	lara.turn_rate += LARA_TURN_RATE;
#endif

	if ((lara.gun_status == LG_READY)
	&&  (lara.water_status != LARA_WADE))
		item->goal_anim_state = AS_FASTTURN;

	else if (lara.turn_rate > LARA_SLOW_TURN)
	{
		if ((!(input & IN_SLOW))
		&&  (lara.water_status != LARA_WADE))
			item->goal_anim_state = AS_FASTTURN;
		else
			lara.turn_rate = LARA_SLOW_TURN;
	}

	if (input & IN_FORWARD)
	{
		if (lara.water_status == LARA_WADE)
			item->goal_anim_state = AS_WADE;
		else
		{
			if (input & IN_SLOW)
				item->goal_anim_state = AS_WALK;
			else
				item->goal_anim_state = AS_RUN;
		}
	}

	else if (!(input&IN_RIGHT))
		item->goal_anim_state = AS_STOP;
}

//-------------------------------- TURN L -------------------------------------

void	lara_as_turn_l( ITEM_INFO *item, COLL_INFO *coll )
{
	if (item->hit_points <= 0)
	{
		item->goal_anim_state = AS_STOP;
		return;
	}

#ifdef PC_JOYSTICK
	lara.turn_rate = joy_x * LARA_FAST_TURN >> 4;
#else
	lara.turn_rate -= LARA_TURN_RATE;
#endif

	if ((lara.gun_status == LG_READY)
	&&  (lara.water_status != LARA_WADE))
		item->goal_anim_state = AS_FASTTURN;

	else if (lara.turn_rate < -LARA_SLOW_TURN)
	{
		if ((!(input & IN_SLOW))
		&&  (lara.water_status != LARA_WADE))
			item->goal_anim_state = AS_FASTTURN;
		else
			lara.turn_rate = -LARA_SLOW_TURN;
	}

	if (input & IN_FORWARD)
	{
		if (lara.water_status == LARA_WADE)
			item->goal_anim_state = AS_WADE;
		else
		{
			if (input & IN_SLOW)
				item->goal_anim_state = AS_WALK;
			else
				item->goal_anim_state = AS_RUN;
		}
	}

	else if (!(input & IN_LEFT))
		item->goal_anim_state = AS_STOP;
}

//------------------------------ DEATH ----------------------------------------
void	lara_as_death( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.look = 0;
	coll->enable_spaz = 0;
	coll->enable_baddie_push = 0;
//	camera.target_angle = 60*ONE_DEGREE;
//	camera.target_elevation = -45*ONE_DEGREE;
}

//---------------------------- FASTFALL ---------------------------------------

void	lara_as_fastfall( ITEM_INFO *item, COLL_INFO *coll )
{
	FASTFALL_FRICTION;
	if ( item->fallspeed==DAMAGE_START+DAMAGE_LENGTH )		//Kick off FALL_TO_DEATH sound effect
		SoundEffect( 30, &item->pos, 0 );
}

//----------------------------- HANG ------------------------------------------

void	lara_void_func( ITEM_INFO *item, COLL_INFO *coll )
{
}

void	lara_as_hang( ITEM_INFO *item, COLL_INFO *coll )
{
	if (item->hit_points <= 0)
	{
		item->goal_anim_state = AS_STOP;
		return;
	}

	if (input & IN_LOOK)
		LookUpDown();

	coll->enable_spaz = 0;
	coll->enable_baddie_push = 0;
	camera.target_angle = CAM_A_HANG;
	camera.target_elevation = CAM_E_HANG;

	if (input & (IN_LEFT|IN_STEPL))
		item->goal_anim_state = AS_HANGLEFT;

	else if (input & (IN_RIGHT|IN_STEPR))
		item->goal_anim_state = AS_HANGRIGHT;
}

//----------------------------- REACH -----------------------------------------
void	lara_as_reach( ITEM_INFO *item, COLL_INFO *coll )
{
	camera.target_angle = 85*ONE_DEGREE;
	if (item->fallspeed > LARA_FASTFALL_SPEED)
		item->goal_anim_state = AS_FASTFALL;
}

//----------------------------- SPLAT -----------------------------------------

void	lara_as_splat( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.look = 0;
}


//----------------------------------- LAND ------------------------------------

void	lara_as_land( ITEM_INFO *item, COLL_INFO *coll )
{
}

//-------------------------------- COMPRESS -----------------------------------

void	lara_as_compress(ITEM_INFO *item, COLL_INFO *coll)
{
	if (lara.water_status != LARA_WADE)
	{
		if ((input & IN_FORWARD)
		&&  (LaraFloorFront(item,item->pos.y_rot, 256) >= -STEPUP_HEIGHT))
		{
			item->goal_anim_state = AS_FORWARDJUMP;
			lara.move_angle = item->pos.y_rot;
		}
		else
		if ((input & IN_LEFT)
		&&  (LaraFloorFront(item, (sint16)(item->pos.y_rot-16384), 256) >= -STEPUP_HEIGHT))
		{
			item->goal_anim_state = AS_LEFTJUMP;
			lara.move_angle = item->pos.y_rot-16384;
		}
		else
		if ((input & IN_RIGHT)
		&&  (LaraFloorFront(item, (sint16)(item->pos.y_rot+16384), 256) >= -STEPUP_HEIGHT))
		{
			item->goal_anim_state = AS_RIGHTJUMP;
			lara.move_angle = item->pos.y_rot+16384;
		}
		else
		if ((input & IN_BACK)
		&&  (LaraFloorFront(item, (sint16)(item->pos.y_rot-32768), 256) >= -STEPUP_HEIGHT))
		{
			item->goal_anim_state = AS_BACKJUMP;
			lara.move_angle = item->pos.y_rot-32768;
		}
	}

	if (item->fallspeed > LARA_FASTFALL_SPEED)
		item->goal_anim_state = AS_FASTFALL;
}

//------------------------------------- BACK ----------------------------------

void	lara_as_back( ITEM_INFO *item, COLL_INFO *coll )
{
	if (item->hit_points <= 0)
	{
		item->goal_anim_state = AS_STOP;
		return;
	}

	if ( !(input&IN_BACK) || (!(input&IN_SLOW) && lara.water_status!=LARA_WADE) )		// if release SLOW or BACK
		item->goal_anim_state = AS_STOP;            // go back to STOP
	else
		item->goal_anim_state = AS_BACK;

	if ( input&IN_LEFT )
	{
		lara.turn_rate -= LARA_TURN_RATE;
		if ( lara.turn_rate < -LARA_SLOW_TURN )
			lara.turn_rate = -LARA_SLOW_TURN;
	}
	else if ( input&IN_RIGHT )
	{
		lara.turn_rate += LARA_TURN_RATE;
		if ( lara.turn_rate > LARA_SLOW_TURN )
			lara.turn_rate = LARA_SLOW_TURN;
	}
}

//----------------------------------- NULL ------------------------------------
void	lara_as_null( ITEM_INFO *item, COLL_INFO *coll )
{
	coll->enable_spaz = 0;      			// No spazing or pushing
	coll->enable_baddie_push = 0;
}

//---------------------------------- FAST_TURN ------------------------------

void	lara_as_fastturn( ITEM_INFO *item, COLL_INFO *coll )
{
	if ( item->hit_points<=0 )						// Time To Die !!!
	{
		item->goal_anim_state = AS_STOP;
		return;
	}
#ifdef PC_JOYSTICK
	lara.turn_rate = LARA_FAST_TURN * joy_x >> 4;
#endif
	if ( lara.turn_rate<0 )
	{
#ifndef PC_JOYSTICK
		lara.turn_rate = -LARA_FAST_TURN;
#endif
		if ( !(input&IN_LEFT) )
			item->goal_anim_state = AS_STOP;
	}
	else
	{
#ifndef PC_JOYSTICK
		lara.turn_rate = LARA_FAST_TURN;
#endif
		if ( !(input&IN_RIGHT) )
			item->goal_anim_state = AS_STOP;
	}
}

//----------------------------------- STEP_RIGHT ---------------------------

void	lara_as_stepright( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.look = 0;
	if ( item->hit_points<=0 )						// Time To Die !!!
	{
		item->goal_anim_state = AS_STOP;
		return;
	}
	if ( !(input&IN_STEPR) )
		item->goal_anim_state = AS_STOP;			// Go Back To A Stop straight away..

	if ( input&IN_LEFT )
	{
		lara.turn_rate -= LARA_TURN_RATE;
		if ( lara.turn_rate < -LARA_SLOW_TURN )
			lara.turn_rate = -LARA_SLOW_TURN;
	}
	else if ( input&IN_RIGHT )
	{
		lara.turn_rate += LARA_TURN_RATE;
		if ( lara.turn_rate > LARA_SLOW_TURN )
			lara.turn_rate = LARA_SLOW_TURN;
	}
}

//----------------------------------- STEP_LEFT ----------------------------

void	lara_as_stepleft( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.look = 0;
	if ( item->hit_points<=0 )						// Time To Die !!!
	{
		item->goal_anim_state = AS_STOP;
		return;
	}
	if ( !(input&IN_STEPL) )
		item->goal_anim_state = AS_STOP;			// Go Back To A Stop straight away..
	if ( input&IN_LEFT )
	{
		lara.turn_rate -= LARA_TURN_RATE;
		if ( lara.turn_rate < -LARA_SLOW_TURN )
			lara.turn_rate = -LARA_SLOW_TURN;
	}
	else if ( input&IN_RIGHT )
	{
		lara.turn_rate += LARA_TURN_RATE;
		if ( lara.turn_rate > LARA_SLOW_TURN )
			lara.turn_rate = LARA_SLOW_TURN;
	}
}

//----------------------------------- SLIDE ----------------------------

void	lara_as_slide( ITEM_INFO *item, COLL_INFO *coll )
{
	camera.flags = NO_CHUNKY;
	camera.target_elevation = -45 * ONE_DEGREE;
	if ( (input&IN_JUMP) && !(input&IN_BACK))
		item->goal_anim_state = AS_FORWARDJUMP;
}

//----------------------------------- BACKJUMP ----------------------------

void	lara_as_backjump( ITEM_INFO *item, COLL_INFO *coll )
{
	camera.target_angle = ONE_DEGREE * 135;
	if (item->fallspeed > LARA_FASTFALL_SPEED)
		item->goal_anim_state = AS_FASTFALL;
	else if (item->goal_anim_state == AS_RUN) // twist from forward jump; may have set goal as RUN, but need STOP in backjump
		item->goal_anim_state = AS_STOP;
	else if ((input&IN_FORWARD || input&IN_ROLL) && item->goal_anim_state!=AS_STOP)
		item->goal_anim_state = AS_TWIST;
}

//----------------------------------- RIGHTJUMP ----------------------------

void	lara_as_rightjump( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.look = 0;
	if (item->fallspeed > LARA_FASTFALL_SPEED)
		item->goal_anim_state = AS_FASTFALL;
	else if (input&IN_LEFT && item->goal_anim_state!=AS_STOP)
		item->goal_anim_state = AS_TWIST;
}

//----------------------------------- LEFTJUMP ----------------------------

void	lara_as_leftjump( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.look = 0;
	if (item->fallspeed > LARA_FASTFALL_SPEED)
		item->goal_anim_state = AS_FASTFALL;
	else if (input&IN_RIGHT && item->goal_anim_state!=AS_STOP)
		item->goal_anim_state = AS_TWIST;
}

//-------------------------------- FALLBACK ----------------------------

void	lara_as_fallback( ITEM_INFO *item, COLL_INFO *coll )
{
	if (item->fallspeed > LARA_FASTFALL_SPEED)
		item->goal_anim_state = AS_FASTFALL;

	if ((input & IN_ACTION)
	&&  (lara.gun_status == LG_ARMLESS))
		item->goal_anim_state = AS_REACH;
}


//-------------------------------- HANGLEFT ----------------------------
void	lara_as_hangleft( ITEM_INFO *item, COLL_INFO *coll )
{
	coll->enable_spaz = 0;
	coll->enable_baddie_push = 0;
	camera.target_angle = CAM_A_HANG;
	camera.target_elevation = CAM_E_HANG;
	if ( !(input&IN_LEFT) && !(input&IN_STEPL) )
		item->goal_anim_state = AS_HANG;
}


//-------------------------------- HANGRIGHT ----------------------------
void	lara_as_hangright( ITEM_INFO *item, COLL_INFO *coll )
{
	coll->enable_spaz = 0;
	coll->enable_baddie_push = 0;
	camera.target_angle = CAM_A_HANG;
	camera.target_elevation = CAM_E_HANG;
	if ( !(input&IN_RIGHT) && !(input&IN_STEPR) )
		item->goal_anim_state = AS_HANG;
}
//-------------------------------- SLIDEBACK ----------------------------
void	lara_as_slideback( ITEM_INFO *item, COLL_INFO *coll )
{
	if ((input&IN_JUMP) && !(input&IN_FORWARD))
		item->goal_anim_state = AS_BACKJUMP;
}

//------------------------------- PUSHBLOCK -----------------------------
void	lara_as_pushblock( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.look = 0;
	coll->enable_spaz = 0;
	coll->enable_baddie_push = 0;
	camera.flags = FOLLOW_CENTRE;
	camera.target_angle = 35*ONE_DEGREE;
	camera.target_elevation = -25*ONE_DEGREE;
}

//------------------------------- PULLBLOCK -----------------------------
void	lara_as_pullblock( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.look = 0;
	coll->enable_spaz = 0;
	coll->enable_baddie_push = 0;
	camera.flags = FOLLOW_CENTRE;
	camera.target_angle = 35*ONE_DEGREE;
	camera.target_elevation = -25*ONE_DEGREE;
}

//------------------------------- PPREADY -------------------------------
void	lara_as_ppready( ITEM_INFO *item, COLL_INFO *coll )
{
	coll->enable_spaz = 0;
	coll->enable_baddie_push = 0;
	camera.target_angle = 75*ONE_DEGREE;
	if ( !(input&IN_ACTION) )				// if user releases ACTION
		item->goal_anim_state = AS_STOP;    // go back to stop
}

//------------------------------- PICKUP -------------------------------
void	lara_as_pickup( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.look = 0;
	coll->enable_spaz = 0;
	coll->enable_baddie_push = 0;
	camera.target_angle = -130*ONE_DEGREE;
	camera.target_elevation = -15*ONE_DEGREE;
	camera.target_distance = WALL_L;
}

//------------------------------- PICKUP FLARE --------------------------
void	lara_as_pickupflare( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.look = 0;
	coll->enable_spaz = 0;
	coll->enable_baddie_push = 0;
	camera.target_angle = +130*ONE_DEGREE;
	camera.target_elevation = -15*ONE_DEGREE;
	camera.target_distance = WALL_L;

	/* In case flare goes out before end of anim, free up hands automatically! */
	if (item->frame_number == anims[item->anim_number].frame_end-1)
		lara.gun_status = LG_ARMLESS;
}

//------------------------------- SWITCHON -------------------------------
void	lara_as_switchon( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.look = 0;
	coll->enable_spaz = 0;
	coll->enable_baddie_push = 0;
	camera.target_angle = 80*ONE_DEGREE;
	camera.target_elevation = -25*ONE_DEGREE;
	camera.target_distance = WALL_L;
	camera.speed = 6;
}

//------------------------------- SWITCHOFF ------------------------------
void	lara_as_switchoff( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.look = 0;
	coll->enable_spaz = 0;
	coll->enable_baddie_push = 0;
	camera.target_angle = 80*ONE_DEGREE;
	camera.target_elevation = -25*ONE_DEGREE;
	camera.target_distance = WALL_L;
	camera.speed = 6;
}

//------------------------------- USEKEY ---------------------------------
void	lara_as_usekey( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.look = 0;
	coll->enable_spaz = 0;
	coll->enable_baddie_push = 0;
	camera.target_angle = -80*ONE_DEGREE;
	camera.target_elevation = -25*ONE_DEGREE;
	camera.target_distance = WALL_L;
}

//------------------------------- USEPUZZLE ------------------------------
void	lara_as_usepuzzle( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.look = 0;
	coll->enable_spaz = 0;
	coll->enable_baddie_push = 0;
	camera.target_angle = -80*ONE_DEGREE;
	camera.target_elevation = -25*ONE_DEGREE;
	camera.target_distance = WALL_L;
}

//------------------------------- ROLL -----------------------------------
void	lara_as_roll( ITEM_INFO *item, COLL_INFO *coll )
{
}

//----------------------------------- ROLL2 ----------------------------
void	lara_as_roll2( ITEM_INFO *item, COLL_INFO *coll )
{
}

//-------------------------- SPECIAL DEATH --------------------------------
void	lara_as_special( ITEM_INFO *item, COLL_INFO *coll )
{
	camera.flags = FOLLOW_CENTRE;                   // Dino death etc...
	camera.target_angle = 170*ONE_DEGREE;
	camera.target_elevation = -25*ONE_DEGREE;
}

//-------------------------- USE MIDAS --------------------------------
void	lara_as_usemidas( ITEM_INFO *item, COLL_INFO *coll )
{

}

//-------------------------- DIE MIDAS --------------------------------
void	lara_as_diemidas( ITEM_INFO *item, COLL_INFO *coll )
{

}

//-------------------------- SWAN DIVE --------------------------------
void	lara_as_swandive( ITEM_INFO *item, COLL_INFO *coll )
{
	coll->enable_spaz = 0;
	coll->enable_baddie_push = 1;
	if (item->fallspeed > LARA_FASTFALL_SPEED && item->goal_anim_state!=AS_DIVE)
		item->goal_anim_state = AS_FASTDIVE;
}

//-------------------------- FAST DIVE --------------------------------
void	lara_as_fastdive( ITEM_INFO *item, COLL_INFO *coll )
{
	if ((input&IN_ROLL) && item->goal_anim_state == AS_FASTDIVE)
		item->goal_anim_state = AS_TWIST;
	coll->enable_spaz = 0;
	coll->enable_baddie_push = 1;
	FASTFALL_FRICTION;
}

//-------------------------- GYMNASTICS --------------------------------
void	lara_as_gymnast( ITEM_INFO *item, COLL_INFO *coll )
{
	coll->enable_spaz = 0;      			// No spazing or pushing
	coll->enable_baddie_push = 0;
//	camera.flags = FOLLOW_CENTRE;
//	camera.target_angle = 35*ONE_DEGREE;
//	camera.target_elevation = -25*ONE_DEGREE;
//	camera.target_distance = WALL_L;
}

//-------------------------------WATER-OUT ------------------------------------
void	lara_as_waterout( ITEM_INFO *item, COLL_INFO *coll )
{
	coll->enable_spaz = 0;      			// same as null but no bum-zoom
	coll->enable_baddie_push = 0;
	camera.flags = FOLLOW_CENTRE;
}

void	lara_as_laratest1( ITEM_INFO *item, COLL_INFO *coll )
{
}

void	lara_as_laratest2( ITEM_INFO *item, COLL_INFO *coll )
{
}

void	lara_as_laratest3( ITEM_INFO *item, COLL_INFO *coll )
{
}

void	lara_as_wade( ITEM_INFO *item, COLL_INFO *coll )
{
	if ( item->hit_points<=0 ) 					// Time To Die!!!
	{
		item->goal_anim_state = AS_STOP;
		return;
	}

	camera.target_elevation = -22*ONE_DEGREE;

	if (room[item->room_number].flags & SWAMP)	// Swamp room ? - then turn slower.
	{
		if ( input&IN_LEFT )
		{
			lara.turn_rate -= LARA_TURN_RATE;
			if ( lara.turn_rate < -LARA_FAST_TURN>>1 )
				lara.turn_rate = -LARA_FAST_TURN>>1;
			item->pos.z_rot -= LARA_LEAN_RATE;
			if ( item->pos.z_rot< - LARA_LEAN_MAX>>1 )
				item->pos.z_rot = -LARA_LEAN_MAX>>1;
		}
		else if ( input&IN_RIGHT )
		{
			lara.turn_rate += LARA_TURN_RATE;
			if ( lara.turn_rate > LARA_FAST_TURN>>1 )
				lara.turn_rate = LARA_FAST_TURN>>1;
			item->pos.z_rot += LARA_LEAN_RATE;
			if ( item->pos.z_rot > LARA_LEAN_MAX>>1 )
				item->pos.z_rot = LARA_LEAN_MAX>>1;
		}

		if (input & IN_FORWARD )
			item->goal_anim_state = AS_WADE;
		else
			item->goal_anim_state = AS_STOP;
	}
	else
	{
		if ( input&IN_LEFT )
		{
			lara.turn_rate -= LARA_TURN_RATE;
			if ( lara.turn_rate < -LARA_FAST_TURN )
				lara.turn_rate = -LARA_FAST_TURN;
			item->pos.z_rot -= LARA_LEAN_RATE;
			if ( item->pos.z_rot< - LARA_LEAN_MAX )
				item->pos.z_rot = -LARA_LEAN_MAX;
		}
		else if ( input&IN_RIGHT )
		{
			lara.turn_rate += LARA_TURN_RATE;
			if ( lara.turn_rate > LARA_FAST_TURN )
				lara.turn_rate = LARA_FAST_TURN;
			item->pos.z_rot += LARA_LEAN_RATE;
			if ( item->pos.z_rot > LARA_LEAN_MAX )
				item->pos.z_rot = LARA_LEAN_MAX;
		}

		if (input & IN_FORWARD )
		{
			if ( lara.water_status==LARA_ABOVEWATER )
				item->goal_anim_state = AS_RUN;
			else
				item->goal_anim_state = AS_WADE;
		}
		else
			item->goal_anim_state = AS_STOP;
	}
}

void	lara_as_twist( ITEM_INFO *item, COLL_INFO *coll )
{
	// NEVER ACTUALLY USED (NO ANIM HAS THIS STATE, BUT LINKS DO)
}

void lara_as_kick( ITEM_INFO *item, COLL_INFO *coll )
{
}

void lara_as_deathslide( ITEM_INFO *item, COLL_INFO *coll )
{
	sint16 room_number;
	FLOOR_INFO *floor;

	camera.target_angle = ONE_DEGREE * 70;

	// test triggers
	room_number = item->room_number;
	floor = GetFloor(item->pos.x_pos, item->pos.y_pos, item->pos.z_pos, &room_number);
	GetHeight(floor, item->pos.x_pos, item->pos.y_pos, item->pos.z_pos);
	coll->trigger = trigger_index;

	if (!(input&IN_ACTION))
	{
		item->goal_anim_state = AS_FORWARDJUMP;
		AnimateLara(item);
		lara_item->gravity_status = 1;
		lara_item->speed = 100;
		lara_item->fallspeed = 40;
		lara.move_angle = item->pos.y_rot;
	}
}

/***************************** EXTRA ANIMATIONS ********************************/
void extra_as_breath(ITEM_INFO *item, COLL_INFO *coll)
{
	/* Finished extra animation, so jump back to normal breath stance */
	item->anim_number = BREATH_A;
	item->frame_number = BREATH_F;
	item->current_anim_state = item->goal_anim_state = AS_STOP;

	lara.gun_status = LG_ARMLESS;

	camera.type = CHASE_CAMERA;
	AlterFOV(GAME_FOV*ONE_DEGREE);

	lara.extra_anim = 0;
}

void extra_as_plunger(ITEM_INFO *item, COLL_INFO *coll)
{
	// erm... do some stuff here...
}

void extra_as_yetikill(ITEM_INFO *item, COLL_INFO *coll)
{
#if 0 //##
	camera.target_angle = ONE_DEGREE * 160;
	camera.target_distance = 3*WALL_L;
	lara.hit_direction = -1;

	if (item->frame_number < anims[item->anim_number].frame_end - 30)
		lara.death_count = 1;
#endif
}

void extra_as_sharkkill(ITEM_INFO *item, COLL_INFO *coll)
{
	int wh;

	camera.target_angle = ONE_DEGREE * 160;
	camera.target_distance = 3*WALL_L;
	lara.hit_direction = -1;

	/* Lara floats upwards at end of anim */
	if (item->frame_number == anims[item->anim_number].frame_end)
	{
		wh = GetWaterHeight( item->pos.x_pos, item->pos.y_pos, item->pos.z_pos, item->room_number );
		if ( wh!=NO_HEIGHT && wh<item->pos.y_pos-100 )
			item->pos.y_pos -= 5;
	}

	if (item->frame_number < anims[item->anim_number].frame_end - 30)
		lara.death_count = 1;
}

void extra_as_airlock(ITEM_INFO *item, COLL_INFO *coll)
{
	camera.target_angle = 80*ONE_DEGREE;
	camera.target_elevation = -25*ONE_DEGREE;
}

void extra_as_gongbong(ITEM_INFO *item, COLL_INFO *coll)
{
	camera.target_angle = -25*ONE_DEGREE;
	camera.target_elevation = -20*ONE_DEGREE;
	camera.target_distance = WALL_L*3;
}

void extra_as_dinokill(ITEM_INFO *item, COLL_INFO *coll)
{
	camera.flags = FOLLOW_CENTRE;
	camera.target_angle = 170*ONE_DEGREE;
	camera.target_elevation = -25*ONE_DEGREE;

	lara.hit_direction = -1;

	if (item->frame_number < anims[item->anim_number].frame_end - 30)
		lara.death_count = 1;
}

void extra_as_pulldagger(ITEM_INFO *item, COLL_INFO *coll)
{
#if 0
	sint16 room_number;
	int frame;
	FLOOR_INFO *floor;

	frame = item->frame_number - anims[item->anim_number].frame_base;
	if (frame == 1)
		S_StartSyncedAudio(28);
	else if (frame == 180)
	{
		lara.mesh_ptrs[HAND_R] = meshes[objects[LARA].mesh_index + HAND_R];
		Inv_AddItem(PUZZLE_ITEM2);
	}

	if (item->frame_number == anims[item->anim_number].frame_end)
	{
		item->pos.y_rot += 0x4000;

		room_number = item->room_number;
		floor = GetFloor(item->pos.x_pos, item->pos.y_pos, item->pos.z_pos, &room_number);
		GetHeight(floor, item->pos.x_pos, item->pos.y_pos, item->pos.z_pos);
		TestTriggers(trigger_index, 1); // activate HEAVY triggers for exit doors
	}
#endif
}

void extra_as_startanim(ITEM_INFO *item, COLL_INFO *coll)
{
	sint16 room_number;
	FLOOR_INFO *floor;
	room_number = item->room_number;
	floor = GetFloor(item->pos.x_pos, item->pos.y_pos, item->pos.z_pos, &room_number);
	GetHeight(floor, item->pos.x_pos, item->pos.y_pos, item->pos.z_pos);
	TestTriggers(trigger_index, 0);
}

void extra_as_starthouse(ITEM_INFO *item, COLL_INFO *coll)
{
#if 0
	int frame;

	frame = item->frame_number - anims[item->anim_number].frame_base;
	if (frame == 1)
	{
		S_StartSyncedAudio(63);
		lara.mesh_ptrs[HAND_R] = meshes[objects[LARA_EXTRA].mesh_index + HAND_R];
		lara.mesh_ptrs[HIPS] = meshes[objects[LARA_EXTRA].mesh_index + HIPS];
	}
	else if (frame == 401)
	{
		lara.mesh_ptrs[HAND_R] = meshes[objects[LARA].mesh_index + HAND_R];
		lara.mesh_ptrs[HIPS] = meshes[objects[LARA].mesh_index + HIPS];
		Inv_AddItem(PUZZLE_ITEM1);
	}
	else if (item->frame_number == anims[item->anim_number].frame_end)
	{
		camera.type = CHASE_CAMERA;
		AlterFOV(GAME_FOV*ONE_DEGREE);
	}
#endif
}

void extra_as_finalanim(ITEM_INFO *item, COLL_INFO *coll)
{
#if 0
	int frame;

	item->hit_points = LARA_HITPOINTS; // stop health bar showing

	frame = item->frame_number - anims[item->anim_number].frame_base;
	if (frame == 1)
	{
		lara.back_gun = 0;
		lara.mesh_ptrs[HAND_R] = meshes[objects[LARA].mesh_index + HAND_R];
		lara.mesh_ptrs[HEAD] = meshes[objects[LARA].mesh_index + HEAD];
		lara.mesh_ptrs[HIPS] = meshes[objects[LARA_EXTRA].mesh_index + HIPS];
		S_StartSyncedAudio(27);
	}
	else if (frame == 316)
		lara.mesh_ptrs[HAND_R] = meshes[objects[SHOTGUN].mesh_index + HAND_R];
	else if (item->frame_number == anims[item->anim_number].frame_end-1)
		level_complete = 1;
#endif
}


void extra_as_trainkill(ITEM_INFO *item, COLL_INFO *col)
{
	FLOOR_INFO *floor;
	sint16 room_number;

	lara.hit_direction = -1;

	room_number = item->room_number;
	floor = GetFloor(item->pos.x_pos, item->pos.y_pos, item->pos.z_pos, &room_number);
	item->pos.y_pos = GetHeight(floor, item->pos.x_pos, item->pos.y_pos, item->pos.z_pos);

	if (item->frame_number < (anims[item->anim_number].frame_end - 30))
		lara.death_count = 1;

	item->gravity_status = 0;
	item->hit_points = -1;
}

void extra_as_rapidsdrown(ITEM_INFO *item, COLL_INFO *coll)
{
	sint32 h;
	FLOOR_INFO *floor;
	sint16 room_number;
	GetLaraCollisionInfo( item, coll );

	room_number = item->room_number;
	floor = GetFloor(item->pos.x_pos, item->pos.y_pos, item->pos.z_pos, &room_number);
	h = GetHeight(floor, item->pos.x_pos, item->pos.y_pos, item->pos.z_pos);

	item->pos.y_pos = h+384;
	item->pos.y_rot += 1024;

	lara.death_count++;	// speed up death

	if ((wibble & 3) == 0)
		TriggerWaterfallMist(item->pos.x_pos, item->pos.y_pos, item->pos.z_pos, GetRandomControl()&4095);
}

//+++++++++++++++++++++++++++ WALK +++++++++++++++++++++++++++++++++++++++++
void	lara_col_walk( ITEM_INFO *item, COLL_INFO *coll )
{
	item->gravity_status = item->fallspeed = 0;				// No Gravity Effects
	lara.move_angle = item->pos.y_rot;
	coll->bad_pos = STEPUP_HEIGHT;
	coll->bad_neg = -STEPUP_HEIGHT;
	coll->bad_ceiling = 0;
	coll->slopes_are_walls = 1;
	coll->slopes_are_pits = 1;
	coll->lava_is_pit = 1;
	GetLaraCollisionInfo( item, coll );

	if ( LaraHitCeiling( item,coll ) )
		return;
	if ( TestLaraVault( item,coll ) )
		return;

	if (LaraDeflectEdge( item,coll ))						  // If Hit Wall or DropOff Head ON
	{
		if ( item->frame_number>=22+7 && item->frame_number<=22+25 )
		{
			item->anim_number = STOP_RIGHT_A;                 // Animation for Walk stop Right
			item->frame_number = STOP_RIGHT_F;
		}
		else if ( (item->frame_number>=22 && item->frame_number<=22+6) ||
		 	  	(item->frame_number>=22+26 && item->frame_number<=22+35)	)
		{
			item->anim_number = STOP_LEFT_A;                  // Animation for Walk stop Left
			item->frame_number = STOP_LEFT_F;
		}
		else
			LaraCollideStop(item, coll);
	}

	if (LaraFallen(item, coll))
		return;

	if ( coll->mid_floor > STEP_L/2 )									// Need to STEP DOWN
	{
		if ( item->frame_number>=28 && item->frame_number<=45 )
		{
			item->anim_number = WALKSTEPD_RIGHT_A;
			item->frame_number = WALKSTEPD_RIGHT_F;
		}
		else
		{
			item->anim_number = WALKSTEPD_LEFT_A;
			item->frame_number = WALKSTEPD_LEFT_F;
		}
	}
	if ( coll->mid_floor >= -STEPUP_HEIGHT && coll->mid_floor < -STEP_L/2 )	// Need to STEP UP
	{
		if ( item->frame_number>=27 && item->frame_number<=44 )
		{
			item->anim_number = WALKSTEPUP_RIGHT_A;
			item->frame_number = WALKSTEPUP_RIGHT_F;
		}
		else
		{
			item->anim_number = WALKSTEPUP_LEFT_A;
			item->frame_number = WALKSTEPUP_LEFT_F;
		}
	}

	if ( TestLaraSlide(item,coll ) )
		return;

	item->pos.y_pos += coll->mid_floor;							// Otherwise Position Is OK..
}

//+++++++++++++++++++++++++++ RUN +++++++++++++++++++++++++++++++++++++++++
void	lara_col_run( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.move_angle = item->pos.y_rot;
	coll->bad_pos = NO_BAD_POS;
	coll->bad_neg = -STEPUP_HEIGHT;
	coll->bad_ceiling = 0;
	coll->slopes_are_walls = 1;
//	coll->slopes_are_pits = 1;
	GetLaraCollisionInfo(item, coll);

	if (LaraHitCeiling(item, coll))
		return;

	if (TestLaraVault(item, coll))
		return;


	if (LaraDeflectEdge(item, coll))					// Make Lara Stop because hit wall
	{                                                   // straight on..
		item->pos.z_rot = 0;
		if ( item->anim_number!=STARTRUN_A &&
			 TestWall(item, 256, 0, -640)						// Test for wall at shoulder height
			 //coll->front_type==WALL &&
			 //coll->front_floor < -(STEP_L*5)/2
			)    // only splat if floor is above
		{															  		// certain height in front
			item->current_anim_state = AS_SPLAT;
			if ( item->frame_number>=0 && item->frame_number<=9 )
			{
				item->anim_number = HITWALLLEFT_A;
				item->frame_number = HITWALLLEFT_F;
				return;
			}
			if ( item->frame_number>=10 && item->frame_number<=21 )
			{
				item->anim_number = HITWALLRIGHT_A;
				item->frame_number = HITWALLRIGHT_F;
				return;
			}
		}

		LaraCollideStop(item, coll);
	}

	if (LaraFallen(item, coll))
		return;

	if ( coll->mid_floor >= -STEPUP_HEIGHT && coll->mid_floor < -STEP_L/2 )		// We need to step up
	{
		if ( item->frame_number>=3 && item->frame_number<=14 )
		{
			item->anim_number = RUNSTEPUP_LEFT_A; 			// So kick off Left or
			item->frame_number = RUNSTEPUP_LEFT_F;          // Right foot Animation
		}
		else
		{
			item->anim_number = RUNSTEPUP_RIGHT_A;
			item->frame_number = RUNSTEPUP_RIGHT_F;
		}
	}
	if ( TestLaraSlide(item,coll ) )
		return;
	if ( coll->mid_floor >= 50 ) 							// Weve RUN off a Smallish Step
	{                                                   	// so Let lara fall down
		item->pos.y_pos += 50;
		return;
	}
	item->pos.y_pos += coll->mid_floor;							// Otherwise Position Is OK..
}

//+++++++++++++++++++++++ FORWARD JUMP +++++++++++++++++++++++++++++++++++++
void	lara_col_forwardjump( ITEM_INFO *item, COLL_INFO *coll )
{
	if (item->speed >= 0)
		lara.move_angle = item->pos.y_rot;
	else
		lara.move_angle = item->pos.y_rot-0x8000;

	coll->bad_pos = NO_BAD_POS;
	coll->bad_neg = -STEPUP_HEIGHT;
	coll->bad_ceiling = BAD_JUMP_CEILING;
	GetLaraCollisionInfo(item, coll);
	LaraDeflectEdgeJump( item,coll );

	if (item->speed < 0)
		lara.move_angle = item->pos.y_rot;

	if ( coll->mid_floor<=0 && item->fallspeed>0 )		// We are now falling
	{                                                   // and have landed..
#ifndef INVINCABLE_LARA
		if ( LaraLandedBad(item,coll) )
			item->goal_anim_state = AS_DEATH;			// If Died cos fallen too far
		else
#endif
		{
			if ( lara.water_status==LARA_WADE)
			{
				item->goal_anim_state = AS_STOP;
			}
			else
			{
				if ( input&IN_FORWARD && !(input&IN_SLOW) )
					item->goal_anim_state = AS_RUN;    		// We are now landing
				else                                   		// into a run or stop
					item->goal_anim_state = AS_STOP;
			}
		}
		item->fallspeed = 0;
		item->pos.y_pos += coll->mid_floor;
		item->gravity_status = 0;
		item->speed = 0;
		AnimateLara(item);								// Move Lara and animate...
	}
}

//+++++++++++++++++++++++++++ POSE +++++++++++++++++++++++++++++++++++++++++
void	lara_col_pose( ITEM_INFO *item, COLL_INFO *coll )
{
	lara_col_stop( item,coll );
}

//+++++++++++++++++++++++++ FASTBACK +++++++++++++++++++++++++++++++++++++++
void	lara_col_fastback( ITEM_INFO *item, COLL_INFO *coll )
{
	item->gravity_status = item->fallspeed = 0;		// No Gravity Effects
	lara.move_angle = item->pos.y_rot - 32768;
	coll->bad_pos = NO_BAD_POS;
	coll->bad_neg = -STEPUP_HEIGHT;
	coll->bad_ceiling = 0;
	coll->slopes_are_pits = 1;
//	coll->slopes_are_walls = 1;
	coll->slopes_are_walls = 0;
	GetLaraCollisionInfo( item, coll );

	if (LaraHitCeiling(item, coll))
		return;

	if (coll->mid_floor > 200)
	{
		item->anim_number = FALLBACK_A;
		item->frame_number = FALLBACK_F;
		item->current_anim_state = AS_FALLBACK;
		item->goal_anim_state = AS_FALLBACK;
		item->fallspeed = 0;
		item->gravity_status = 1;
		return;
	}

	if (TestLaraSlide(item, coll))	// Gibby.
		return;					// Gibby.

	if (LaraDeflectEdge(item, coll))	// Stop Lara Dead
		LaraCollideStop(item, coll);

	item->pos.y_pos += coll->mid_floor;
}

//+++++++++++++++++++++++++++ TURN_R +++++++++++++++++++++++++++++++++++++++
void	lara_col_turn_r( ITEM_INFO *item, COLL_INFO *coll )
{
	item->gravity_status = item->fallspeed = 0;			// No Gravity Effects
	lara.move_angle = item->pos.y_rot;
	coll->bad_pos = STEPUP_HEIGHT;
	coll->bad_neg = -STEPUP_HEIGHT;
	coll->bad_ceiling = 0;
	coll->slopes_are_pits = 1;
	coll->slopes_are_walls = 1;
	GetLaraCollisionInfo( item, coll );
	if ( coll->mid_floor > 100 && !(room[item->room_number].flags & SWAMP))	// Floor Has Fallen Away From
	{                                                   					// Under Us...
		item->anim_number = FALLDOWN_A;								// So Initiate A Fall
		item->frame_number = FALLDOWN_F;
		item->current_anim_state = AS_FORWARDJUMP;
		item->goal_anim_state = AS_FORWARDJUMP;
		item->fallspeed = 0;
		item->gravity_status = 1;
		return;
	}
	if ( TestLaraSlide(item,coll ) )
		return;
	if (!(room[item->room_number].flags & SWAMP) || coll->mid_floor < 0)
		item->pos.y_pos += coll->mid_floor;                 // Enforce to floor height.. if not a swamp room.
	else if ((room[item->room_number].flags & SWAMP) && coll->mid_floor)
		item->pos.y_pos += SWAMP_GRAVITY;
}

//+++++++++++++++++++++++++++ TURN_L +++++++++++++++++++++++++++++++++++++++
void	lara_col_turn_l( ITEM_INFO *item, COLL_INFO *coll )
{
	lara_col_turn_r( item,coll );				// Exactly Same Collision as turn_r
}

//+++++++++++++++++++++++++++ DEATH ++++++++++++++++++++++++++++++++++++++++
void	lara_col_death( ITEM_INFO *item, COLL_INFO *coll )
{
	StopSoundEffect(30); // stop that screaming woman
	lara.move_angle = item->pos.y_rot;
	coll->bad_pos = STEPUP_HEIGHT;
	coll->bad_neg = -STEPUP_HEIGHT;
	coll->bad_ceiling = 0;
	coll->radius = LARA_RAD*4;
	GetLaraCollisionInfo( item, coll );
	ShiftItem( item,coll );
	item->pos.y_pos += coll->mid_floor;
	item->hit_points = -1;
	lara.air = -1;
}

//+++++++++++++++++++++++++++ FASTFALL +++++++++++++++++++++++++++++++++++++
void	lara_col_fastfall( ITEM_INFO *item, COLL_INFO *coll )
{
	item->gravity_status = 1;
	coll->bad_pos = NO_BAD_POS;					// DONT SET Move Angle
	coll->bad_neg = -STEPUP_HEIGHT;
	coll->bad_ceiling = BAD_JUMP_CEILING;
	GetLaraCollisionInfo( item, coll );
	LaraSlideEdgeJump( item,coll );
	if ( coll->mid_floor <= 0 )
	{                                                   // IF Landed
#ifndef INVINCABLE_LARA
  		if (  LaraLandedBad(item,coll) )      			// So either Die
			item->goal_anim_state = AS_DEATH;
		else
#endif
		{
			item->goal_anim_state = AS_STOP;			// or Stop
			item->current_anim_state = AS_STOP;
			item->frame_number = LANDFAR_F;
			item->anim_number = LANDFAR_A;
		}
		StopSoundEffect(30);
		item->pos.y_pos += coll->mid_floor;
		item->gravity_status = 0;
		item->fallspeed = 0;
	}
}

//+++++++++++++++++++++++++++ HANG +++++++++++++++++++++++++++++++++++++++++
void	lara_col_hang( ITEM_INFO *item, COLL_INFO *coll )
{
	LaraHangTest(item, coll);

	if (item->goal_anim_state == AS_HANG)
	{
		if (input & IN_FORWARD)
		{
			if ((coll->front_floor > -850)
			&&  (coll->front_floor < -650)
			&& ((coll->front_floor-coll->front_ceiling) >= 0)
//##			&& ((coll->left_floor-coll->left_ceiling) >= 0)
//##			&& ((coll->right_floor-coll->right_ceiling) >= 0)
			&& ((coll->left_floor2-coll->left_ceiling2) >= 0)
			&& ((coll->right_floor2-coll->right_ceiling2) >= 0)
			&&  (!coll->hit_static))
			{
				if (input & IN_SLOW)
					item->goal_anim_state = AS_GYMNAST;
				else
					item->goal_anim_state = AS_NULL;
				return;

			}

			else if ((lara.climb_status)
				&&  (item->anim_number == HANG_A)
				&&  (item->frame_number == HANG_F)
				&&  (coll->mid_ceiling <= -256))
				{
					item->goal_anim_state = AS_HANG;
					item->current_anim_state = AS_HANG;
					item->anim_number = HANGUP_A;
					item->frame_number = HANGUP_F;
					return;
				}
		}

		if ((input & (IN_DUCK|IN_FORWARD))
		&&  (coll->front_floor > -850)
		&&  (coll->front_floor < -650)
		&&  (coll->front_floor-coll->front_ceiling >= -STEP_L)
//##		&&  (coll->left_floor-coll->left_ceiling >= -STEP_L)
//##		&&  (coll->right_floor-coll->right_ceiling >= -STEP_L)
		&&  (coll->left_floor2-coll->left_ceiling2 >= -STEP_L)
		&&  (coll->right_floor2-coll->right_ceiling2 >= -STEP_L)
		&&  (!coll->hit_static))
		{
		    	item->goal_anim_state = AS_HANG2DUCK;
		    	item->required_anim_state = AS_DUCK;
		}

		else if ((input & IN_BACK)
			&&  (lara.climb_status)
			&&  (item->anim_number == HANG_A)
			&&  (item->frame_number == HANG_F))
			{
				item->goal_anim_state = AS_HANG;
				item->current_anim_state = AS_HANG;
				item->anim_number = HANGDOWN_A;
				item->frame_number = HANGDOWN_F;
			}
	}
}

//+++++++++++++++++++++++++++ REACH ++++++++++++++++++++++++++++++++++++++++
void	lara_col_reach( ITEM_INFO *item, COLL_INFO *coll )
{
	item->gravity_status = 1;
	lara.move_angle = item->pos.y_rot;
	coll->bad_pos = NO_BAD_POS;
	coll->bad_neg = 0;
//##	coll->bad_pos =  STEPUP_HEIGHT;
//##	coll->bad_neg = -STEPUP_HEIGHT;
	coll->bad_ceiling = BAD_JUMP_CEILING;

	GetLaraCollisionInfo(item, coll);

	if ( LaraTestHangJump( item,coll ) )			// First Check Reach Positions
		return;

	LaraSlideEdgeJump( item,coll );

	GetLaraCollisionInfo(item, coll);

	ShiftItem(item, coll);

	if ( item->fallspeed > 0 )					// We are now falling..
	{
		if ( coll->mid_floor <= 0 )				// IF Landed
		{
#ifndef INVINCABLE_LARA
  			if ( LaraLandedBad(item,coll) )		// either Die
				item->goal_anim_state = AS_DEATH;
			else
#endif
				item->goal_anim_state = AS_STOP;	// Or Stop
			item->fallspeed = 0;
			item->pos.y_pos += coll->mid_floor;
			item->gravity_status = 0;
		}
	}
}

//+++++++++++++++++++++++++++ SPLAT ++++++++++++++++++++++++++++++++++++++++
void	lara_col_splat( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.move_angle = item->pos.y_rot;
	coll->bad_pos = STEPUP_HEIGHT;
	coll->bad_neg = -STEPUP_HEIGHT;
	coll->bad_ceiling = 0;
	coll->slopes_are_pits = 1;
	coll->slopes_are_walls = 1;
	GetLaraCollisionInfo( item, coll );
	ShiftItem( item,coll );

	if (coll->mid_floor > -STEP_L && coll->mid_floor < STEP_L)
		item->pos.y_pos += coll->mid_floor;							// for lift
}

//+++++++++++++++++++++++++++ LAND +++++++++++++++++++++++++++++++++++++++++
void	lara_col_land( ITEM_INFO *item, COLL_INFO *coll )
{
	lara_col_stop( item,coll );				// Is this Routine Used???
}

//+++++++++++++++++++++++++++ COMPRESS +++++++++++++++++++++++++++++++++++++
void	lara_col_compress( ITEM_INFO *item, COLL_INFO *coll )
{
	item->gravity_status = item->fallspeed = 0;		// No Gravity Effects
	coll->bad_pos = NO_BAD_POS;
	coll->bad_neg = NO_BAD_NEG;
	coll->bad_ceiling = 0;
	GetLaraCollisionInfo( item, coll );
	if ( coll->mid_ceiling > -100 )
	{
		item->goal_anim_state = AS_STOP;			// PreEmptive Stop Jumping
		item->current_anim_state = AS_STOP;         // If Ceiling is very Low
		item->anim_number = STOP_A;
		item->frame_number = STOP_F;
		item->speed = 0;
		item->fallspeed = 0;
		item->gravity_status = 0;
		item->pos.x_pos = coll->old.x;
		item->pos.y_pos = coll->old.y;
		item->pos.z_pos = coll->old.z;
	}

	if (coll->mid_floor > -STEP_L && coll->mid_floor < STEP_L) // for jumping in lift (limit stops weirdness when on falling blocks)
		item->pos.y_pos += coll->mid_floor;
}

//+++++++++++++++++++++++++++ BACK +++++++++++++++++++++++++++++++++++++++++
void	lara_col_back( ITEM_INFO *item, COLL_INFO *coll )
{
	item->gravity_status = item->fallspeed = 0;		// No Gravity Effects
	lara.move_angle = item->pos.y_rot - 32768;

	if (lara.water_status == LARA_WADE)
		coll->bad_pos = NO_BAD_POS;
	else
		coll->bad_pos = STEPUP_HEIGHT;
	coll->bad_neg = -STEPUP_HEIGHT;
	coll->bad_ceiling = 0;
	coll->slopes_are_pits = 1;
	coll->slopes_are_walls = 1;
	GetLaraCollisionInfo( item, coll );

	if (LaraHitCeiling(item, coll))
		return;

	if (LaraDeflectEdge(item, coll))				// Stop Lara Dead
		LaraCollideStop(item, coll);

	if (LaraFallen(item,coll))
		return;
	if ( coll->mid_floor > STEP_L/2  && coll->mid_floor < (STEP_L*3)/2)
	{
		if ( item->frame_number>=964 && item->frame_number<=993 )       // We Need to Step Down
		{
			item->anim_number = BACKSTEPD_RIGHT_A; 						// So kick off Left or
			item->frame_number = BACKSTEPD_RIGHT_F;                     // Right foot Animation
		}
		else
		{
			item->anim_number = BACKSTEPD_LEFT_A;
			item->frame_number = BACKSTEPD_LEFT_F;
		}
	}
	if ( TestLaraSlide(item,coll ) )
		return;

	if (!(room[item->room_number].flags & SWAMP) || coll->mid_floor < 0)
		item->pos.y_pos += coll->mid_floor;                 // Enforce to floor height.. if not a swamp room.
	else if ((room[item->room_number].flags & SWAMP) && coll->mid_floor)
		item->pos.y_pos += SWAMP_GRAVITY;
}

//+++++++++++++++++++++++++++ NULL +++++++++++++++++++++++++++++++++++++++++
void	lara_col_null( ITEM_INFO *item, COLL_INFO *coll )
{
	lara_default_col( item,coll );
}

//+++++++++++++++++++++++++ FAST TURN ++++++++++++++++++++++++++++++++++++++
void	lara_col_fastturn( ITEM_INFO *item, COLL_INFO *coll )
{
	lara_col_stop( item,coll );
}

//++++++++++++++++++++++++ STEP RIGHT ++++++++++++++++++++++++++++++++++++++
void	lara_col_stepright( ITEM_INFO *item, COLL_INFO *coll )
{
	if (item->current_anim_state == AS_STEPRIGHT)
		lara.move_angle = item->pos.y_rot + 16384;
	else
		lara.move_angle = item->pos.y_rot - 16384;

	item->gravity_status = item->fallspeed = 0;		// No Gravity Effects
	if (lara.water_status == LARA_WADE)
		coll->bad_pos = NO_BAD_POS;
	else
		coll->bad_pos = STEP_L/2;
	coll->bad_neg = -STEP_L/2;
	coll->bad_ceiling = 0;
	coll->slopes_are_pits = 1;
	coll->slopes_are_walls = 1;
	GetLaraCollisionInfo( item, coll );
	if ( LaraHitCeiling( item,coll ) )
		return;
	if (LaraDeflectEdge( item,coll ))
		LaraCollideStop(item, coll);
	if (LaraFallen( item,coll ))
		return;
	if ( TestLaraSlide(item,coll ) )
		return;
	item->pos.y_pos += coll->mid_floor;
}

//++++++++++++++++++++++++ STEP LEFT +++++++++++++++++++++++++++++++++++++++
void	lara_col_stepleft( ITEM_INFO *item, COLL_INFO *coll )
{
	lara_col_stepright(item, coll);
}

//++++++++++++++++++++++++++ SLIDE ++++++++++++++++++++++++++++++++++++++++++
void	lara_col_slide( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.move_angle = item->pos.y_rot;
	lara_slide_slope( item,coll );
}

//++++++++++++++++++++++++++ BACKJUMP +++++++++++++++++++++++++++++++++++++++
void	lara_col_backjump( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.move_angle = item->pos.y_rot - 32768;
	lara_col_jumper( item,coll );
}

//++++++++++++++++++++++++++ RIGHTJUMP ++++++++++++++++++++++++++++++++++++++
void	lara_col_rightjump( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.move_angle = item->pos.y_rot + 16384;
	lara_col_jumper( item,coll );
}

//++++++++++++++++++++++++++ LEFTJUMP +++++++++++++++++++++++++++++++++++++++
void	lara_col_leftjump( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.move_angle = item->pos.y_rot - 16384;
	lara_col_jumper( item,coll );
}

//++++++++++++++++++++++++++ FALLBACK ++++++++++++++++++++++++++++++++++++++++++
void	lara_col_fallback( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.move_angle = item->pos.y_rot - 32768;
	coll->bad_pos = NO_BAD_POS;
	coll->bad_neg = -STEPUP_HEIGHT;
	coll->bad_ceiling = BAD_JUMP_CEILING;
	GetLaraCollisionInfo( item, coll );
	LaraDeflectEdgeJump( item,coll );
	if ( coll->mid_floor<=0 && item->fallspeed>0 )			// We are now falling
	{                                                   	// and have landed..
#ifndef INVINCABLE_LARA
  		if ( LaraLandedBad(item,coll) )    						// So either Die
			item->goal_anim_state = AS_DEATH;
		else
#endif
			item->goal_anim_state = AS_STOP;
		item->fallspeed = 0;
		item->pos.y_pos += coll->mid_floor;
		item->gravity_status = 0;
	}
}

//++++++++++++++++++++++++++ HANGLEFT ++++++++++++++++++++++++++++++++++++++++++
void	lara_col_hangleft( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.move_angle = item->pos.y_rot-16384;
	LaraHangTest( item,coll );
	lara.move_angle = item->pos.y_rot-16384;
}

//++++++++++++++++++++++++++ HANGRIGHT ++++++++++++++++++++++++++++++++++++++++++
void	lara_col_hangright( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.move_angle = item->pos.y_rot+16384;
	LaraHangTest( item,coll );
	lara.move_angle = item->pos.y_rot+16384;
}
//++++++++++++++++++++++++++ SLIDEBACK ++++++++++++++++++++++++++++++++++++++++++
void	lara_col_slideback( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.move_angle = item->pos.y_rot - 32768;
	lara_slide_slope( item,coll );
}

//++++++++++++++++++++++++++ PUSHBLOCK ++++++++++++++++++++++++++++++++++++++++++
void	lara_col_pushblock( ITEM_INFO *item, COLL_INFO *coll )
{
	lara_default_col( item,coll );
}

//++++++++++++++++++++++++++ PULLBLOCK ++++++++++++++++++++++++++++++++++++++++++
void	lara_col_pullblock( ITEM_INFO *item, COLL_INFO *coll )
{
	lara_default_col( item,coll );
}

//++++++++++++++++++++++++++ PPREADY ++++++++++++++++++++++++++++++++++++++++++
void	lara_col_ppready( ITEM_INFO *item, COLL_INFO *coll )
{
	lara_default_col( item,coll );
}


//++++++++++++++++++++++++++ PICKUP ++++++++++++++++++++++++++++++++++++++++++
void	lara_col_pickup( ITEM_INFO *item, COLL_INFO *coll )
{
	lara_default_col( item,coll );
}

//++++++++++++++++++++++++++ SWITCHON ++++++++++++++++++++++++++++++++++++++++++
void	lara_col_switchon( ITEM_INFO *item, COLL_INFO *coll )
{
	lara_default_col( item,coll );
}

//++++++++++++++++++++++++++ SWITCHOFF ++++++++++++++++++++++++++++++++++++++++++
void	lara_col_switchoff( ITEM_INFO *item, COLL_INFO *coll )
{
	lara_default_col( item,coll );
}

//++++++++++++++++++++++++++ USE KEY ++++++++++++++++++++++++++++++++++++++++++
void	lara_col_usekey( ITEM_INFO *item, COLL_INFO *coll )
{
	lara_default_col( item,coll );
}

//++++++++++++++++++++++++++ USE PUZZLE ++++++++++++++++++++++++++++++++++++++++++
void	lara_col_usepuzzle( ITEM_INFO *item, COLL_INFO *coll )
{
	lara_default_col( item,coll );
}

//++++++++++++++++++++++++++ ROLL ++++++++++++++++++++++++++++++++++++++++++
void	lara_col_roll( ITEM_INFO *item, COLL_INFO *coll )
{
	item->gravity_status = item->fallspeed = 0;		// No Gravity Effects
	lara.move_angle = item->pos.y_rot;
	coll->bad_pos = NO_BAD_POS;
	coll->bad_neg = -STEPUP_HEIGHT;
	coll->bad_ceiling = 0;
	coll->slopes_are_walls = 1;
	GetLaraCollisionInfo( item, coll );
	if ( LaraHitCeiling( item,coll ) )
		return;
	if ( TestLaraSlide(item,coll ) )
		return;
	if (LaraFallen(item,coll))
		return;
	ShiftItem( item,coll );
	item->pos.y_pos += coll->mid_floor;
}

//++++++++++++++++++++++++++ ROLL2 ++++++++++++++++++++++++++++++++++++++++++
void	lara_col_roll2( ITEM_INFO *item, COLL_INFO *coll )
{
	item->gravity_status = item->fallspeed = 0;		// No Gravity Effects
	lara.move_angle = item->pos.y_rot-32768;
	coll->bad_pos = NO_BAD_POS;
	coll->bad_neg = -STEPUP_HEIGHT;
	coll->bad_ceiling = 0;
	coll->slopes_are_walls = 1;
	GetLaraCollisionInfo( item, coll );
	if ( LaraHitCeiling( item,coll ) )
		return;
	if ( TestLaraSlide(item,coll ) )
		return;
	if ( coll->mid_floor > 200 )						// Weve Rolled Off A Big Edge..
	{
		item->anim_number = FALLBACK_A;
		item->frame_number = FALLBACK_F;                // so make her fall backwards
		item->current_anim_state = AS_FALLBACK;         // this allows her to do
		item->goal_anim_state = AS_FALLBACK;            // Handy forward Roll off Ledge
		item->fallspeed = 0;                            // and Grab hold of it!!
		item->gravity_status = 1;
		return;
	}
	ShiftItem( item,coll );
	item->pos.y_pos += coll->mid_floor;
}


//+++++++++++++++++++++++++ SPECIAL DEATH +++++++++++++++++++++++++++++++++++++
void	lara_col_special( ITEM_INFO *item, COLL_INFO *coll )
{
}


//+++++++++++++++++++++++++++ USE MIDAS +++++++++++++++++++++++++++++++++++++++
void	lara_col_usemidas( ITEM_INFO *item, COLL_INFO *coll )
{
	lara_default_col( item,coll );
}

//+++++++++++++++++++++++++++ DIE MIDAS +++++++++++++++++++++++++++++++++++++++
void	lara_col_diemidas( ITEM_INFO *item, COLL_INFO *coll )
{
	lara_default_col( item,coll );
}

//+++++++++++++++++++++++++++ SWAN DIVE +++++++++++++++++++++++++++++++++++++++
void	lara_col_swandive( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.move_angle = item->pos.y_rot;
	coll->bad_pos = NO_BAD_POS;
	coll->bad_neg = -STEPUP_HEIGHT;
	coll->bad_ceiling = BAD_JUMP_CEILING;
	GetLaraCollisionInfo( item, coll );
	LaraDeflectEdgeJump( item,coll );
	if ( coll->mid_floor<=0 && item->fallspeed>0 )		// We are now falling
	{                                                   // and have landed..
		item->goal_anim_state = AS_STOP;
		item->fallspeed = 0;
		item->pos.y_pos += coll->mid_floor;
		item->gravity_status = 0;
	}
}

//+++++++++++++++++++++++++++ FAST DIVE +++++++++++++++++++++++++++++++++++++++
void	lara_col_fastdive( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.move_angle = item->pos.y_rot;
	coll->bad_pos = NO_BAD_POS;
	coll->bad_neg = -STEPUP_HEIGHT;
	coll->bad_ceiling = BAD_JUMP_CEILING;
	GetLaraCollisionInfo( item, coll );
	LaraDeflectEdgeJump( item,coll );
	if ( coll->mid_floor<=0 && item->fallspeed>0 )		// We are now falling
	{                                                   // and have landed..
#ifndef INVINCABLE_LARA
		if ( item->fallspeed>133 )
			item->goal_anim_state = AS_DEATH;
		else
#endif
			item->goal_anim_state = AS_STOP;
		item->fallspeed = 0;
		item->pos.y_pos += coll->mid_floor;
		item->gravity_status = 0;
	}
}

//+++++++++++++++++++++++++++ GYMNAST +++++++++++++++++++++++++++++++++++++++
void	lara_col_gymnast( ITEM_INFO *item, COLL_INFO *coll )
{
	lara_default_col( item,coll );
}

//+++++++++++++++++++++++++++ WATER OUT +++++++++++++++++++++++++++++++++++++++++
void	lara_col_waterout( ITEM_INFO *item, COLL_INFO *coll )
{
	lara_default_col( item,coll );
}

void	lara_col_laratest1( ITEM_INFO *item, COLL_INFO *coll )
{

}
void	lara_col_laratest2( ITEM_INFO *item, COLL_INFO *coll )
{

}
void	lara_col_laratest3( ITEM_INFO *item, COLL_INFO *coll )
{

}
void	lara_col_wade( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.move_angle = item->pos.y_rot;
	coll->bad_pos = NO_BAD_POS;
	coll->bad_neg = -STEPUP_HEIGHT;
	coll->bad_ceiling = 0;
	coll->slopes_are_walls = 1;
	GetLaraCollisionInfo( item, coll );

	if ( LaraHitCeiling( item,coll ) )
		return;
	if ( TestLaraVault( item,coll ) )
		return;
	if (LaraDeflectEdge( item,coll ))					// Make Lara Stop because hit wall
	{                                                   // straight on..
		item->pos.z_rot = 0;
		if ((coll->front_type==WALL || coll->front_type==SPLIT_TRI) && coll->front_floor < -(STEP_L*5)/2 && !(room[item->room_number].flags & SWAMP))    // only splat if floor is above
		{													   // certain height in front
			item->current_anim_state = AS_SPLAT;
			if ( item->frame_number>=0 && item->frame_number<=9 )
			{
				item->anim_number = HITWALLLEFT_A;
				item->frame_number = HITWALLLEFT_F;
				return;
			}
			if ( item->frame_number>=10 && item->frame_number<=21 )
			{
				item->anim_number = HITWALLRIGHT_A;
				item->frame_number = HITWALLRIGHT_F;
				return;
			}
		}
		LaraCollideStop(item, coll);
	}

//	if (LaraFallen(item,coll))
//		return;
	if ( coll->mid_floor >= -STEPUP_HEIGHT && coll->mid_floor < -STEP_L/2 && !(room[item->room_number].flags & SWAMP))		// We need to step up
	{
		if ( item->frame_number>=3 && item->frame_number<=14 )
		{
			item->anim_number = RUNSTEPUP_LEFT_A; 			// So kick off Left or
			item->frame_number = RUNSTEPUP_LEFT_F;          // Right foot Animation
		}
		else
		{
			item->anim_number = RUNSTEPUP_RIGHT_A;
			item->frame_number = RUNSTEPUP_RIGHT_F;
		}
	}
//	if ( TestLaraSlide(item,coll ) )
//		return;

	if ( coll->mid_floor >= 50 && !(room[item->room_number].flags & SWAMP)) 		// Weve RUN off a Smallish Step
	{                                                   	// so Let lara fall down if not in a swamp room.
		item->pos.y_pos += 50;
		return;
	}

	if (!(room[item->room_number].flags & SWAMP) || coll->mid_floor < 0)
		item->pos.y_pos += coll->mid_floor;                 // Enforce to floor height.. if not a swamp room.
	else if ((room[item->room_number].flags & SWAMP) && coll->mid_floor)
		item->pos.y_pos += SWAMP_GRAVITY;
}

void	lara_col_twist( ITEM_INFO *item, COLL_INFO *coll )
{
}

/******************************************************************************
 *			Collision routine for switch pulling etc etc
 *****************************************************************************/
void		lara_default_col( ITEM_INFO *item, COLL_INFO *coll )
{
	lara.move_angle = item->pos.y_rot;
	coll->bad_pos = STEPUP_HEIGHT;
	coll->bad_neg = -STEPUP_HEIGHT;
	coll->bad_ceiling = 0;
	coll->slopes_are_pits = 1;
	coll->slopes_are_walls = 1;
	GetLaraCollisionInfo( item, coll );
}


/******************************************************************************
 *			Routine for MultiWay Jumps except forwards...
 *****************************************************************************/
void	lara_col_jumper( ITEM_INFO *item, COLL_INFO *coll )
{
	coll->bad_pos = NO_BAD_POS;
	coll->bad_neg = -STEPUP_HEIGHT;
	coll->bad_ceiling = BAD_JUMP_CEILING;
	GetLaraCollisionInfo( item, coll );
	LaraDeflectEdgeJump( item,coll );
	if ( item->fallspeed > 0 )								// We are now falling
	{
		if ( coll->mid_floor <= 0 )
		{                                                   // IF Landed
#ifndef INVINCABLE_LARA
  			if ( LaraLandedBad(item,coll) )    					// So either Die
				item->goal_anim_state = AS_DEATH;
			else
#endif
				item->goal_anim_state = AS_STOP;
			item->fallspeed = 0;
			item->pos.y_pos += coll->mid_floor;
			item->gravity_status = 0;
		}
	}
}

void lara_col_kick( ITEM_INFO *item, COLL_INFO *coll )
{
}

// death slide
void lara_col_deathslide( ITEM_INFO *item, COLL_INFO *coll )
{
	// may use another state
}

/****************************************************************************************
 *				Get Absolute World pos of certain joint on Lara
 ***************************************************************************************/

static void AddJointPos(ITEM_INFO *item, int mesh)
{
	sint16 room_num;

#ifdef PSX_VERSION
	VECTOR3D pos;

	room_num = item->room_number;

	gte_sttr(&pos);

	GetFloor(item->pos.x_pos + pos.x,
		    item->pos.y_pos + pos.y,
		    item->pos.z_pos + pos.z,
		    &room_num);
#else
	room_num = item->room_number;

	GetFloor((phd_mxptr[M03]>>W2V_SHIFT) + item->pos.x_pos,
		    (phd_mxptr[M13]>>W2V_SHIFT) + item->pos.y_pos,
		    (phd_mxptr[M23]>>W2V_SHIFT) + item->pos.z_pos,
		    &room_num);
#endif

	if (room[room_num].flags & UNDERWATER)
		IsJointUnderwater[mesh] = 1;
	else
		IsJointUnderwater[mesh] = 0;

	GotJointPos[mesh] = 1;
}

/****************************************************************************************
 *				Get Absolute World pos of left/right hand on Lara
 ***************************************************************************************/

void	GetLaraHandAbsPosition( PHD_VECTOR *vec, int leftright )	// 0 = left / 1 = right / 2=hips
{
	int			fire_arms;
	int			frac,rate,size;
	sint16		*frmptr[2];
	OBJECT_INFO 	*object;
	sint32 		*bone;
	sint16		*rotation;
	sint16 		*frame;
	ITEM_INFO 	*item;
#ifdef PSX_VERSION
	MATRIX3D *start;
#endif

	item = lara_item;

	if ( lara.hit_direction<0 && (frac=GetFrames(item,frmptr,&rate) ) )
	{
		GetLHAInt( item,vec,frmptr[0],frmptr[1],frac,rate,leftright );
		return;
	}

	object = &objects[item->object_number];
	if ( lara.hit_direction>=0 )
	{
		switch ( lara.hit_direction )
		{
			default:
			case NORTH:
				frame = anims[SPAZ_FORWARD_A].frame_ptr;
				size = anims[SPAZ_FORWARD_A].interpolation>>8;
				break;

			case EAST:
				frame = anims[SPAZ_RIGHT_A].frame_ptr;
				size = anims[SPAZ_RIGHT_A].interpolation>>8;
				break;

			case SOUTH:
				frame = anims[SPAZ_BACK_A].frame_ptr;
				size = anims[SPAZ_BACK_A].interpolation>>8;
				break;

			case WEST:
				frame = anims[SPAZ_LEFT_A].frame_ptr;
				size = anims[SPAZ_LEFT_A].interpolation>>8;
				break;
		}
		frame += (int)( lara.hit_frame*size );
	}
	else
		frame = frmptr[0];

	phd_PushUnitMatrix();
#ifdef PSX_VERSION
	mSetTrans(0, 0, 0);
#else
	*(phd_mxptr+M03) = 0;
	*(phd_mxptr+M13) = 0;
	*(phd_mxptr+M23) = 0;
#endif
	phd_RotYXZ(item->pos.y_rot, item->pos.x_rot, item->pos.z_rot);

#ifdef PSX_VERSION
	start = Matrix;
#endif

	phd_PushMatrix();

	bone = bones + object->bone_index;
	rotation = frame+9;

	phd_TranslateRel((sint32)*(frame+6), (sint32)*(frame+7), (sint32)*(frame+8));
	gar_RotYXZsuperpack(&rotation, 0);

/* -------- matrix = HIPS */

 	if (!GotJointPos[HIPS])
		AddJointPos(item, HIPS);

	if (leftright == LEFT_FOOT)
	{
		phd_TranslateRel(*(bone+1), *(bone+2), *(bone+3));
		gar_RotYXZsuperpack(&rotation, 0);

		if (!GotJointPos[THIGH_L])
			AddJointPos(item, THIGH_L);

		phd_TranslateRel(*(bone+1+4), *(bone+2+4), *(bone+3+4));
		gar_RotYXZsuperpack(&rotation, 0);

		if (!GotJointPos[CALF_L])
			AddJointPos(item, CALF_L);

		phd_TranslateRel(*(bone+1+8), *(bone+2+8), *(bone+3+8));
		gar_RotYXZsuperpack(&rotation, 0);

		if (!GotJointPos[FOOT_L])
			AddJointPos(item, FOOT_L);
	}

	else if (leftright == RIGHT_FOOT)
	{
		phd_TranslateRel(*(bone+1+12), *(bone+2+12), *(bone+3+12));
		gar_RotYXZsuperpack(&rotation, 3);

		if (!GotJointPos[THIGH_R])
			AddJointPos(item, THIGH_R);

		phd_TranslateRel(*(bone+1+16), *(bone+2+16), *(bone+3+16));
		gar_RotYXZsuperpack(&rotation, 0);

		if (!GotJointPos[CALF_R])
			AddJointPos(item, CALF_R);

		phd_TranslateRel(*(bone+1+20), *(bone+2+20), *(bone+3+20));
		gar_RotYXZsuperpack(&rotation, 0);

		if (!GotJointPos[FOOT_R])
			AddJointPos(item, FOOT_R);
	}

	else if (leftright != LARA_HIPS)
	{
		phd_TranslateRel( *(bone+1+24), *(bone+2+24), *(bone+3+24) );

		if ((lara.weapon_item != NO_ITEM)
		&&  (lara.gun_type == LG_M16)
		&& ((items[lara.weapon_item].current_anim_state == 0)
		||  (items[lara.weapon_item].current_anim_state == 2)
		||  (items[lara.weapon_item].current_anim_state == 4)))
		{
			rotation = lara.right_arm.frame_base + lara.right_arm.frame_number * (anims[lara.right_arm.anim_number].interpolation>>8) + 9;
			gar_RotYXZsuperpack(&rotation, 7);
		}
		else
			gar_RotYXZsuperpack(&rotation, 6);

		phd_RotYXZ( lara.torso_y_rot, lara.torso_x_rot, lara.torso_z_rot );

		if (!GotJointPos[TORSO])
			AddJointPos(item, TORSO);

	/* -------- matrix = TORSO */

		if (leftright == LARA_HEAD)
		{
			phd_TranslateRel(*(bone+1+52), *(bone+2+52), *(bone+3+52));
			gar_RotYXZsuperpack(&rotation, 6);
			phd_RotYXZ(lara.head_y_rot,lara.head_x_rot,lara.head_z_rot);

			if (!GotJointPos[HEAD])
				AddJointPos(item, HEAD);
		}

		if ((leftright == LEFT_HAND)
		||  (leftright == RIGHT_HAND))
		{
			if ((lara.gun_status == LG_READY)
			||  (lara.gun_status == LG_SPECIAL)
			||  (lara.gun_status == LG_DRAW)
			||  (lara.gun_status == LG_UNDRAW))
		 		fire_arms = lara.gun_type;
			else
				fire_arms = LG_UNARMED;

			if (leftright == LEFT_HAND)
			{
				phd_TranslateRel( *(bone+1+40), *(bone+2+40), *(bone+3+40) );

				switch(fire_arms)
				{
					case	LG_UNARMED:
					case LG_FLARE:
						if (lara.flare_control_left)
						{
							rotation = lara.left_arm.frame_base + (lara.left_arm.frame_number - anims[lara.left_arm.anim_number].frame_base)
																				* (anims[lara.left_arm.anim_number].interpolation>>8) + 9;
							gar_RotYXZsuperpack(&rotation, 11);
						}
						else
							gar_RotYXZsuperpack(&rotation, 3);
						break;

					case LG_PISTOLS:
					case LG_MAGNUMS:
					case LG_UZIS:
#ifdef PSX_VERSION
						Matrix->m00 = start->m00;
						Matrix->m01 = start->m01;
						Matrix->m02 = start->m02;
						Matrix->m10 = start->m10;
						Matrix->m11 = start->m11;
						Matrix->m12 = start->m12;
						Matrix->m20 = start->m20;
						Matrix->m21 = start->m21;
						Matrix->m22 = start->m22;
						mLoadMatrix(Matrix);
#else
						*(phd_mxptr+M00) = *(phd_mxptr+M00-12);
						*(phd_mxptr+M01) = *(phd_mxptr+M01-12);	  	// Restore Laras Main Rotations
						*(phd_mxptr+M02) = *(phd_mxptr+M02-12);     // Less any torso rotations
						*(phd_mxptr+M10) = *(phd_mxptr+M10-12);     // avoids Wobbly arms when
						*(phd_mxptr+M11) = *(phd_mxptr+M11-12);     // moving 'n' shooting COOL
						*(phd_mxptr+M12) = *(phd_mxptr+M12-12);
						*(phd_mxptr+M20) = *(phd_mxptr+M20-12);
						*(phd_mxptr+M21) = *(phd_mxptr+M21-12);
						*(phd_mxptr+M22) = *(phd_mxptr+M22-12);
#endif
						phd_RotYXZ( lara.left_arm.y_rot, lara.left_arm.x_rot, lara.left_arm.z_rot );
						rotation = lara.left_arm.frame_base + (lara.left_arm.frame_number - anims[lara.left_arm.anim_number].frame_base)
																			* (anims[lara.left_arm.anim_number].interpolation>>8) + 9;
						gar_RotYXZsuperpack(&rotation, 11);
						break;

					case LG_SHOTGUN:
					case LG_HARPOON:
					case LG_ROCKET:
					case LG_GRENADE:
					case LG_M16:
					default:
		 				gar_RotYXZsuperpack(&rotation, 3);
						break;
				}

			/* -------- matrix = UARM_L */

				if (!GotJointPos[UARM_L])
					AddJointPos(item, UARM_L);

				phd_TranslateRel( *(bone+1+44), *(bone+2+44), *(bone+3+44) );
				gar_RotYXZsuperpack(&rotation, 0);

				if (!GotJointPos[LARM_L])
					AddJointPos(item, LARM_L);

				phd_TranslateRel( *(bone+1+48), *(bone+2+48), *(bone+3+48) );
				gar_RotYXZsuperpack(&rotation, 0);

				if (!GotJointPos[HAND_L])
					AddJointPos(item, HAND_L);
			}

			else	if (leftright == RIGHT_HAND)
			{
				phd_TranslateRel( *(bone+1+28), *(bone+2+28), *(bone+3+28) );

				switch(fire_arms)
				{
					case	LG_UNARMED:
					case LG_FLARE:
						gar_RotYXZsuperpack(&rotation, 0);
						break;

					case LG_PISTOLS:
					case LG_MAGNUMS:
					case LG_UZIS:
#ifdef PSX_VERSION
						Matrix->m00 = start->m00;
						Matrix->m01 = start->m01;
						Matrix->m02 = start->m02;
						Matrix->m10 = start->m10;
						Matrix->m11 = start->m11;
						Matrix->m12 = start->m12;
						Matrix->m20 = start->m20;
						Matrix->m21 = start->m21;
						Matrix->m22 = start->m22;
						mLoadMatrix(Matrix);
#else
						*(phd_mxptr+M00) = *(phd_mxptr+M00-12);
						*(phd_mxptr+M01) = *(phd_mxptr+M01-12);	  	// Restore Laras Main Rotations
						*(phd_mxptr+M02) = *(phd_mxptr+M02-12);     // Less any torso rotations
						*(phd_mxptr+M10) = *(phd_mxptr+M10-12);     // avoids Wobbly arms when
						*(phd_mxptr+M11) = *(phd_mxptr+M11-12);     // moving 'n' shooting
						*(phd_mxptr+M12) = *(phd_mxptr+M12-12);
						*(phd_mxptr+M20) = *(phd_mxptr+M20-12);
						*(phd_mxptr+M21) = *(phd_mxptr+M21-12);
						*(phd_mxptr+M22) = *(phd_mxptr+M22-12);
#endif
						phd_RotYXZ( lara.right_arm.y_rot, lara.right_arm.x_rot, lara.right_arm.z_rot );
						rotation = lara.right_arm.frame_base + (lara.right_arm.frame_number - anims[lara.right_arm.anim_number].frame_base)
																			* (anims[lara.right_arm.anim_number].interpolation>>8) + 9;
						gar_RotYXZsuperpack(&rotation, 8);
						break;

					case LG_SHOTGUN:
					case LG_HARPOON:
					case LG_ROCKET:
					case LG_GRENADE:
					case LG_M16:
						rotation = lara.right_arm.frame_base + lara.right_arm.frame_number * (anims[lara.right_arm.anim_number].interpolation>>8) + 9;
						gar_RotYXZsuperpack(&rotation, 8);
						break;
				}

			/* -------- matrix = UARM_R */

				if (!GotJointPos[UARM_R])
					AddJointPos(item, UARM_R);

				phd_TranslateRel( *(bone+1+32), *(bone+2+32), *(bone+3+32) );
				gar_RotYXZsuperpack(&rotation, 0);

				if (!GotJointPos[LARM_R])
					AddJointPos(item, LARM_R);

				phd_TranslateRel( *(bone+1+36), *(bone+2+36), *(bone+3+36) );
				gar_RotYXZsuperpack(&rotation, 0);

				if (!GotJointPos[HAND_R])
					AddJointPos(item, HAND_R);
			}
		}
	}

/* -------- apply offset vector */

	phd_TranslateRel( vec->x, vec->y, vec->z );
#ifdef PSX_VERSION
	gte_sttr(vec);
	vec->x += item->pos.x_pos;
	vec->y += item->pos.y_pos;
	vec->z += item->pos.z_pos;
#else
	vec->x = (*(phd_mxptr+M03)>>W2V_SHIFT) + item->pos.x_pos;
	vec->y = (*(phd_mxptr+M13)>>W2V_SHIFT) + item->pos.y_pos;
	vec->z = (*(phd_mxptr+M23)>>W2V_SHIFT) + item->pos.z_pos;
#endif

	phd_PopMatrix();
	phd_PopMatrix();
}


void	GetLHAInt(ITEM_INFO *item, PHD_VECTOR *vec, sint16 *frame1, sint16 *frame2, int frac, int rate, long leftright)
{
	sint32 *bone;
	int fire_arms;
	OBJECT_INFO *object;
	sint16 *bounds, *rotation1, *rotation2;
#ifdef PSX_VERSION
	MATRIX3D *start;
#endif

	object = &objects[item->object_number];
//	bounds = GetBoundsAccurate( item );

	phd_PushUnitMatrix();
#ifdef PSX_VERSION
	mSetTrans(0, 0, 0);
#else
	*(phd_mxptr+M03) = 0;
	*(phd_mxptr+M13) = 0;
	*(phd_mxptr+M23) = 0;
#endif
	phd_RotYXZ(item->pos.y_rot, item->pos.x_rot, item->pos.z_rot);

#ifdef PSX_VERSION
	start = Matrix;
#endif

	phd_PushMatrix();
	phd_PushMatrix();

	bone = bones + object->bone_index;
	rotation1 = frame1+9;
	rotation2 = frame2+9;

#ifdef PSX_VERSION
	InitInterpolate(frac, rate, &iMatrixStack[0]);
#else
	InitInterpolate(frac,rate);
#endif

	phd_TranslateRel_ID((sint32)*(frame1+6), (sint32)*(frame1+7), (sint32)*(frame1+8),
					(sint32)*(frame2+6), (sint32)*(frame2+7), (sint32)*(frame2+8));
	gar_RotYXZsuperpack_I(&rotation1, &rotation2, 0);

	if (!GotJointPos[HIPS])
		AddJointPos(item, HIPS);

/* -------- matrix = HIPS */

	if (leftright == LEFT_FOOT)
	{
		phd_TranslateRel_I(*(bone+1), *(bone+2), *(bone+3));
		gar_RotYXZsuperpack_I(&rotation1, &rotation2, 0);
		if (!GotJointPos[THIGH_L])
			AddJointPos(item, THIGH_L);

		phd_TranslateRel_I(*(bone+1+4), *(bone+2+4), *(bone+3+4));
		gar_RotYXZsuperpack_I(&rotation1, &rotation2, 0);
		if (!GotJointPos[CALF_L])
			AddJointPos(item, CALF_L);

		phd_TranslateRel_I(*(bone+1+8), *(bone+2+8), *(bone+3+8));
		gar_RotYXZsuperpack_I(&rotation1, &rotation2, 0);
		if (!GotJointPos[FOOT_L])
			AddJointPos(item, FOOT_L);
	}

	else if (leftright == RIGHT_FOOT)
	{
		phd_TranslateRel_I(*(bone+1+12), *(bone+2+12), *(bone+3+12));
		gar_RotYXZsuperpack_I(&rotation1, &rotation2, 3);
		if (!GotJointPos[THIGH_R])
			AddJointPos(item, THIGH_R);

		phd_TranslateRel_I(*(bone+1+16), *(bone+2+16), *(bone+3+16));
		gar_RotYXZsuperpack_I(&rotation1, &rotation2, 0);
		if (!GotJointPos[CALF_R])
			AddJointPos(item, CALF_R);

		phd_TranslateRel_I(*(bone+1+20), *(bone+2+20), *(bone+3+20));
		gar_RotYXZsuperpack_I(&rotation1, &rotation2, 0);
		if (!GotJointPos[FOOT_R])
			AddJointPos(item, FOOT_R);
	}

	else if (leftright != LARA_HIPS)
	{
		phd_TranslateRel_I(*(bone+1+24), *(bone+2+24), *(bone+3+24));

		if ((lara.weapon_item != NO_ITEM)
		&&  (lara.gun_type == LG_M16)
		&& ((items[lara.weapon_item].current_anim_state == 0)
		||  (items[lara.weapon_item].current_anim_state == 2)
		||  (items[lara.weapon_item].current_anim_state == 4)))
		{
			rotation1 = rotation2 = lara.right_arm.frame_base + lara.right_arm.frame_number * (anims[lara.right_arm.anim_number].interpolation>>8) + 9;
			gar_RotYXZsuperpack_I(&rotation1, &rotation2, 7);
		}
		else
			gar_RotYXZsuperpack_I(&rotation1, &rotation2, 6);

		phd_RotYXZ_I( lara.torso_y_rot, lara.torso_x_rot, lara.torso_z_rot );

		if (!GotJointPos[TORSO])
			AddJointPos(item, TORSO);

	/* -------- matrix = TORSO */

		if (leftright == LARA_HEAD)
		{
			phd_TranslateRel_I( *(bone+1+52), *(bone+2+52), *(bone+3+52) );
			gar_RotYXZsuperpack_I(&rotation1, &rotation2, 6);
			phd_RotYXZ_I( lara.head_y_rot,lara.head_x_rot,lara.head_z_rot );
			if (!GotJointPos[HEAD])
				AddJointPos(item, HEAD);
		}

		if ((leftright == LEFT_HAND)
		||  (leftright == RIGHT_HAND))
		{
			if ((lara.gun_status == LG_READY)
			||  (lara.gun_status == LG_SPECIAL)
			||  (lara.gun_status == LG_DRAW)
			||  (lara.gun_status == LG_UNDRAW))
		 		fire_arms = lara.gun_type;
			else
				fire_arms = LG_UNARMED;

			if (leftright == LEFT_HAND)
			{
				phd_TranslateRel_I( *(bone+1+40), *(bone+2+40), *(bone+3+40) );

				switch (fire_arms)
				{
				/* -------------------- */
					case LG_UNARMED:
					case LG_FLARE:
				/* -------------------- */
						if ( lara.flare_control_left )
						{
							rotation1 = rotation2 = lara.left_arm.frame_base + (lara.left_arm.frame_number - anims[lara.left_arm.anim_number].frame_base)
																									* (anims[lara.left_arm.anim_number].interpolation>>8) + 9;
							gar_RotYXZsuperpack_I(&rotation1, &rotation2, 11);
						}
						else
							gar_RotYXZsuperpack_I(&rotation1, &rotation2, 3);

						if (!GotJointPos[UARM_L])
							AddJointPos(item, UARM_L);

					/* -------- matrix = UARM_L */

						phd_TranslateRel_I( *(bone+1+44), *(bone+2+44), *(bone+3+44) );
						gar_RotYXZsuperpack_I(&rotation1, &rotation2, 0);
						if (!GotJointPos[LARM_L])
							AddJointPos(item, LARM_L);

						phd_TranslateRel_I( *(bone+1+48), *(bone+2+48), *(bone+3+48) );
						gar_RotYXZsuperpack_I(&rotation1, &rotation2, 0);
						if (!GotJointPos[HAND_L])
							AddJointPos(item, HAND_L);
		    				break;

					case LG_PISTOLS:
					case LG_MAGNUMS:
					case LG_UZIS:
#ifdef PSX_VERSION
						InterpolateArmMatrix(start);
#else
						InterpolateArmMatrix();
#endif
						phd_RotYXZ( lara.left_arm.y_rot, lara.left_arm.x_rot, lara.left_arm.z_rot );
						rotation1 = lara.left_arm.frame_base + (lara.left_arm.frame_number - anims[lara.left_arm.anim_number].frame_base)
																				* (anims[lara.left_arm.anim_number].interpolation>>8) + 9;
						gar_RotYXZsuperpack(&rotation1, 11);

					/* -------- matrix = UARM_L */

						phd_TranslateRel( *(bone+1+44), *(bone+2+44), *(bone+3+44) );
						gar_RotYXZsuperpack(&rotation1, 0);

						phd_TranslateRel( *(bone+1+48), *(bone+2+48), *(bone+3+48) );
						gar_RotYXZsuperpack(&rotation1, 0);

						phd_TranslateRel( vec->x, vec->y, vec->z );
#ifdef PSX_VERSION
						gte_sttr(vec);
						vec->x += item->pos.x_pos;
						vec->y += item->pos.y_pos;
						vec->z += item->pos.z_pos;
#else
						vec->x = (*(phd_mxptr+M03)>>W2V_SHIFT) + item->pos.x_pos;
						vec->y = (*(phd_mxptr+M13)>>W2V_SHIFT) + item->pos.y_pos;
						vec->z = (*(phd_mxptr+M23)>>W2V_SHIFT) + item->pos.z_pos;
#endif
						phd_PopMatrix();
						phd_PopMatrix();
						phd_PopMatrix();
						return;
						break;

					case LG_SHOTGUN:
					case LG_HARPOON:
					case LG_ROCKET:
					case LG_GRENADE:
					case LG_M16:
						rotation1 = rotation2 = lara.right_arm.frame_base + lara.right_arm.frame_number * (anims[lara.right_arm.anim_number].interpolation>>8) + 9;
						gar_RotYXZsuperpack_I(&rotation1, &rotation2, 11);

					/* -------- matrix = UARM_L */

						phd_TranslateRel_I( *(bone+1+44), *(bone+2+44), *(bone+3+44) );
						gar_RotYXZsuperpack_I(&rotation1, &rotation2, 0);

						phd_TranslateRel_I( *(bone+1+48), *(bone+2+48), *(bone+3+48) );
						gar_RotYXZsuperpack_I(&rotation1, &rotation2, 0);
						break;
				}
			}
			else	if (leftright == RIGHT_HAND)
			{
				switch (fire_arms)
				{
					case LG_UNARMED:
					case LG_FLARE:
//						phd_PushMatrix_I();
						phd_TranslateRel_I( *(bone+1+28),*(bone+2+28),*(bone+3+28) );

						gar_RotYXZsuperpack_I(&rotation1, &rotation2, 0);

						if (!GotJointPos[UARM_R])
							AddJointPos(item, UARM_R);

					/* -------- matrix = UARM_R */

						phd_TranslateRel_I( *(bone+1+32), *(bone+2+32), *(bone+3+32) );
						gar_RotYXZsuperpack_I(&rotation1, &rotation2, 0);
						if (!GotJointPos[LARM_R])
							AddJointPos(item, LARM_R);

						phd_TranslateRel_I( *(bone+1+36), *(bone+2+36), *(bone+3+36) );
						gar_RotYXZsuperpack_I(&rotation1, &rotation2, 0);
						if (!GotJointPos[HAND_R])
							AddJointPos(item, HAND_R);
		    				break;

					case LG_PISTOLS:
					case LG_MAGNUMS:
					case LG_UZIS:
//						phd_PushMatrix_I();
						phd_TranslateRel_I( *(bone+1+28),*(bone+2+28),*(bone+3+28) );
#ifdef PSX_VERSION
						InterpolateArmMatrix(start);
#else
						InterpolateArmMatrix();
#endif
						phd_RotYXZ( lara.right_arm.y_rot, lara.right_arm.x_rot, lara.right_arm.z_rot );
						rotation1 = lara.right_arm.frame_base + (lara.right_arm.frame_number - anims[lara.right_arm.anim_number].frame_base)
																				* (anims[lara.right_arm.anim_number].interpolation>>8) + 9;
						gar_RotYXZsuperpack(&rotation1, 8);

					/* -------- matrix = UARM_R */

						phd_TranslateRel( *(bone+1+32), *(bone+2+32), *(bone+3+32) );
						gar_RotYXZsuperpack(&rotation1, 0);

						phd_TranslateRel( *(bone+1+36), *(bone+2+36), *(bone+3+36) );
						gar_RotYXZsuperpack(&rotation1, 0);

						phd_TranslateRel(vec->x, vec->y, vec->z);
#ifdef PSX_VERSION
						gte_sttr(vec);
						vec->x += item->pos.x_pos;
						vec->y += item->pos.y_pos;
						vec->z += item->pos.z_pos;
#else
						vec->x = (*(phd_mxptr+M03)>>W2V_SHIFT) + item->pos.x_pos;
						vec->y = (*(phd_mxptr+M13)>>W2V_SHIFT) + item->pos.y_pos;
						vec->z = (*(phd_mxptr+M23)>>W2V_SHIFT) + item->pos.z_pos;
#endif
						phd_PopMatrix();
						phd_PopMatrix();
						phd_PopMatrix();
						return;
						break;

					case LG_SHOTGUN:
					case LG_HARPOON:
					case LG_ROCKET:
					case LG_GRENADE:
					case LG_M16:
//						phd_PushMatrix_I();
						phd_TranslateRel_I( *(bone+1+28),*(bone+2+28),*(bone+3+28) );
						rotation1 = rotation2 = lara.right_arm.frame_base + lara.right_arm.frame_number * (anims[lara.right_arm.anim_number].interpolation>>8) + 9;
						gar_RotYXZsuperpack_I(&rotation1, &rotation2, 8);

					/* -------- matrix = UARM_R */

						phd_TranslateRel_I( *(bone+1+32), *(bone+2+32), *(bone+3+32) );
						gar_RotYXZsuperpack_I(&rotation1, &rotation2, 0);

						phd_TranslateRel_I( *(bone+1+36), *(bone+2+36), *(bone+3+36) );
						gar_RotYXZsuperpack_I(&rotation1, &rotation2, 0);
						break;
				}

			}
		}
	}

	phd_TranslateRel_I( vec->x, vec->y, vec->z );
	InterpolateMatrix();
#ifdef PSX_VERSION
	gte_sttr(vec);
	vec->x += item->pos.x_pos;
	vec->y += item->pos.y_pos;
	vec->z += item->pos.z_pos;
#else
	vec->x = (*(phd_mxptr+M03)>>W2V_SHIFT) + item->pos.x_pos;
	vec->y = (*(phd_mxptr+M13)>>W2V_SHIFT) + item->pos.y_pos;
	vec->z = (*(phd_mxptr+M23)>>W2V_SHIFT) + item->pos.z_pos;
#endif
	phd_PopMatrix();
	phd_PopMatrix();
	phd_PopMatrix();
}


void LookUpDown(void)
{
	/* Look up/down and cancel up/down keys so don't have any other effects */
	camera.type = LOOK_CAMERA;

#ifdef ANALOG_CONTROL
	if (input & (IN_LOOKLEFT|IN_LOOKRIGHT|IN_LOOKFORWARD|IN_LOOKBACK))
		lara.head_x_rot = LaraLookX;
	else
#endif
	{
		if (input & IN_FORWARD)
		{
			input -= IN_FORWARD;
			if (lara.head_x_rot > MIN_HEAD_TILT)
				lara.head_x_rot -= HEAD_TURN;
		}
		else if (input & IN_BACK)
		{
			input -= IN_BACK;
			if (lara.head_x_rot < MAX_HEAD_TILT)
				lara.head_x_rot += HEAD_TURN;
		}
	}

	/* Twist torso if Lara's hands are not busy */
	if (lara.gun_status != LG_HANDSBUSY && lara.skidoo==NO_ITEM && lara.left_arm.lock == 0 && lara.right_arm.lock == 0)
//	if (lara.gun_status != LG_HANDSBUSY)
		lara.torso_x_rot = lara.head_x_rot;
}

void LookLeftRight(void)
{
	camera.type = LOOK_CAMERA;

#ifdef ANALOG_CONTROL
	if (input & (IN_LOOKLEFT|IN_LOOKRIGHT|IN_LOOKFORWARD|IN_LOOKBACK))
		lara.head_y_rot = LaraLookY;
	else
#endif
	{
		if (input & IN_LEFT)
		{
			input -= IN_LEFT;
			if (lara.head_y_rot > -MAX_HEAD_ROTATION)
				lara.head_y_rot -= HEAD_TURN;
		}
		else if (input & IN_RIGHT)
		{
			input -= IN_RIGHT;
			if (lara.head_y_rot < MAX_HEAD_ROTATION)
				lara.head_y_rot += HEAD_TURN;
		}
	}

	/* Twist torso if Lara's hands are not busy */
//	if (lara.gun_status != LG_HANDSBUSY && lara.skidoo==NO_ITEM)
	if (lara.gun_status != LG_HANDSBUSY && lara.skidoo==NO_ITEM && lara.left_arm.lock == 0 && lara.right_arm.lock == 0)
		lara.torso_y_rot = lara.head_y_rot;
}

void ResetLook(void)
{
/* If looking at a target LOOK_CAMERA will be on when IN_LOOK is not pressed */
	if (camera.type == LOOK_CAMERA)
		return;

/* If not in Look mode and got no target then reset Torso and Head Rots */
	if ((lara.head_x_rot > -HEAD_TURN)
	&&  (lara.head_x_rot < HEAD_TURN))
		lara.head_x_rot = 0;
	else
		lara.head_x_rot -= lara.head_x_rot/8;


	if ((lara.head_y_rot > -HEAD_TURN)
	&&  (lara.head_y_rot < HEAD_TURN))
		lara.head_y_rot = 0;
	else
		lara.head_y_rot -= lara.head_y_rot/8;

	if (lara.gun_status != LG_HANDSBUSY && lara.skidoo==NO_ITEM)
	{
		lara.torso_x_rot = lara.head_x_rot;
		lara.torso_y_rot = lara.head_y_rot;
	}
}

void DeathSlideCollision(sint16 item_number, ITEM_INFO *laraitem, COLL_INFO *coll)
{
	ITEM_INFO *item;

	if (!(input&IN_ACTION) || laraitem->gravity_status || lara.gun_status!=LG_ARMLESS ||
		laraitem->current_anim_state != AS_STOP)
		return;

	item = &items[item_number];
	if (item->status != NOT_ACTIVE)
		return;

	if (TestLaraPosition(DeathSlideBounds, item, laraitem))
	{
		AlignLaraPosition(&DeathSlidePosition, item, laraitem);
		lara.gun_status = LG_HANDSBUSY;

		laraitem->goal_anim_state = AS_DEATHSLIDE;
		do
			AnimateItem(laraitem);
		while (laraitem->current_anim_state != AS_NULL);

		if (!item->active)
			AddActiveItem(item_number);
		item->status = ACTIVE;
		item->flags |= ONESHOT;
	}
}

void ControlDeathSlide(sint16 item_number)
{
	ITEM_INFO *item;
	FLOOR_INFO *floor;
	sint32 c, s, x, y, z;
	sint16 room_number;
	int lara_on_deathslide;
	GAME_VECTOR *old;

	item = &items[item_number];
	if (item->status == ACTIVE)
	{
		if (!(item->flags & ONESHOT)) // not a true triggering
		{
			/* Reset DEATHSLIDE */
			old = (GAME_VECTOR *)item->data;
			item->pos.x_pos = old->x;
			item->pos.y_pos = old->y;
			item->pos.z_pos = old->z;
			if (old->room_number != item->room_number)
				ItemNewRoom(item_number, old->room_number);
			item->status = NOT_ACTIVE;
			item->current_anim_state = item->goal_anim_state = DEATH_GRAB;
			item->anim_number = objects[item->object_number].anim_index;
			item->frame_number = anims[item->anim_number].frame_base;
			RemoveActiveItem(item_number);
			return;
		}

		if (item->current_anim_state == DEATH_GRAB)
		{
			AnimateItem(item);
			return;
		}

		AnimateItem(item);

		if (item->fallspeed < DEATH_SPEED)
			item->fallspeed += DEATH_ACC;

		c = phd_cos(item->pos.y_rot);
		s = phd_sin(item->pos.y_rot);

		item->pos.z_pos += item->fallspeed * c >> W2V_SHIFT;
		item->pos.x_pos += item->fallspeed * s >> W2V_SHIFT;
		item->pos.y_pos += item->fallspeed >> 2;
		room_number = item->room_number;
		GetFloor(item->pos.x_pos, item->pos.y_pos, item->pos.z_pos, &room_number);
		if (room_number != item->room_number)
			ItemNewRoom(item_number, room_number);

		/* If Lara is hanging on, then move her to the position of the slide */
		lara_on_deathslide = (lara_item->current_anim_state == AS_DEATHSLIDE);
		if (lara_on_deathslide)
		{
			lara_item->pos.x_pos = item->pos.x_pos;
			lara_item->pos.y_pos = item->pos.y_pos;
			lara_item->pos.z_pos = item->pos.z_pos;
		}

		/* Check for collide with wall (if so Lara, gets thrown off) */
		z = item->pos.z_pos + (WALL_L * c >> W2V_SHIFT);
		x = item->pos.x_pos + (WALL_L * s >> W2V_SHIFT);
		y = item->pos.y_pos + (STEP_L >> 2);
		floor = GetFloor(x, y, z, &room_number);
		if (GetHeight(floor, x, y, z) <= y+STEP_L || GetCeiling(floor, x, y, z) >= y-STEP_L)
		{
			if (lara_on_deathslide)
			{
				lara_item->goal_anim_state = AS_FORWARDJUMP;
				AnimateLara(lara_item);
				lara_item->gravity_status = 1;
				lara_item->speed = item->fallspeed;
				lara_item->fallspeed = item->fallspeed >> 2;
			}

			SoundEffect(281, &item->pos, 0); // slide stop sound
			RemoveActiveItem(item_number);
			item->status = NOT_ACTIVE;
			item->flags -= ONESHOT;
		}
		else
			SoundEffect(280, &item->pos, 0); // whizz sound
	}
}

/*******************************************************************************
 *			Handle When Lara Has Fallen Certain Distance
 ******************************************************************************/
int LaraLandedBad(ITEM_INFO *item, COLL_INFO *coll)
{
	int landspeed, oy;
	FLOOR_INFO *floor;
	sint16 room_number;

	room_number = item->room_number;

	floor = GetFloor( item->pos.x_pos, item->pos.y_pos, item->pos.z_pos, &room_number);
	oy = item->pos.y_pos;
	item->floor = item->pos.y_pos = GetHeight(floor, item->pos.x_pos, item->pos.y_pos-LARA_HITE, item->pos.z_pos );
	if (abs(oy-item->pos.y_pos) > 256)
		item->pos.y_pos = oy;

	LaraOnPad = 0;
	TestTriggers(trigger_index, 0);	// Gibbytesttriggers
	if (!LaraOnPad)
		lara_item->item_flags[1] = 0;	// Reset lara on pad flag.

	item->pos.y_pos = oy;
	landspeed = item->fallspeed - DAMAGE_START;

	if ( landspeed <= 0)
		return(0);

	else if (landspeed > DAMAGE_LENGTH)
		item->hit_points = -1;

	else
		item->hit_points -= (landspeed*landspeed*LARA_HITPOINTS)/(DAMAGE_LENGTH*DAMAGE_LENGTH);

	if (item->hit_points <= 0)
		return(1);

	return(0);
}

/*******************************************************************************
 *			Test If Lara Has Hit Ceiling whilst not jumping..
 *            If so make her come to Stop straight away
 ******************************************************************************/
int LaraHitCeiling( ITEM_INFO *item, COLL_INFO *coll )
{
	if ( coll->coll_type==COLL_TOP || coll->coll_type==COLL_CLAMP)
	{
		item->pos.x_pos = coll->old.x;
		item->pos.y_pos = coll->old.y;
		item->pos.z_pos = coll->old.z;
		item->goal_anim_state = AS_STOP;
		item->current_anim_state = AS_STOP;
		item->frame_number = STOP_F;
		item->anim_number = STOP_A;
		item->speed = 0;
		item->fallspeed = 0;
		item->gravity_status = 0;
		return(1);
	}
	return(0);
}

/************************************************************************************
 *	Return Relative floor Height of ITEM at dist in front at Angle
 ***********************************************************************************/
sint16 LaraFloorFront( ITEM_INFO *item, PHD_ANGLE ang, sint32 dist )
{
	sint16 room;
	FLOOR_INFO *floor;
	sint32 x, y, z, height;

	x = item->pos.x_pos + (( phd_sin(ang) * dist ) >> W2V_SHIFT );
	y = item->pos.y_pos - LARA_HITE;
	z = item->pos.z_pos + (( phd_cos(ang) * dist ) >> W2V_SHIFT );
	room = item->room_number;

	floor=GetFloor( x, y, z, &room );  				// Get Height directly in front
	height = GetHeight( floor, x, y, z );

	if (height != NO_HEIGHT)
		height -= item->pos.y_pos;

	return ((sint16)height);
}

/************************************************************************************
 *	Return Relative floor Height of ITEM at dist in front at Angle
 ***********************************************************************************/
sint16 LaraCeilingFront( ITEM_INFO *item, PHD_ANGLE ang, sint32 dist )
{
	sint16 room;
	FLOOR_INFO *floor;
	sint32 x, y, z, height;

	x = item->pos.x_pos + (( phd_sin(ang) * dist ) >> W2V_SHIFT );
	y = item->pos.y_pos - LARA_HITE;
	z = item->pos.z_pos + (( phd_cos(ang) * dist ) >> W2V_SHIFT );
	room = item->room_number;

	floor=GetFloor( x, y, z, &room );  				// Get Height directly in front
	height = GetCeiling( floor, x, y, z );

	if (height != NO_HEIGHT)
		height -= item->pos.y_pos-LARA_HITE;

	return ((sint16)height);
}

int LaraFallen( ITEM_INFO *item, COLL_INFO *coll )
{
	// if the ground has gone from under our feet (trapdoor or falling floor), then initiate a fall
	if ( coll->mid_floor > STEPUP_HEIGHT && lara.water_status != LARA_WADE )
	{
		item->anim_number = FALLDOWN_A;
		item->frame_number = FALLDOWN_F;
		item->current_anim_state = AS_FORWARDJUMP;
		item->goal_anim_state = AS_FORWARDJUMP;
		item->fallspeed = 0;
		item->gravity_status = 1;
		return 1;
	}
	return 0;
}

int LaraTestEdgeCatch( ITEM_INFO *item, COLL_INFO *coll, sint32 *edge )
{
	int hdif;
	sint16 *bounds;

	bounds = GetBoundsAccurate(item);
	hdif = coll->front_floor - bounds[2];

	if (((hdif < 0) && ((hdif + item->fallspeed) < 0))
	||  ((hdif > 0) && ((hdif + item->fallspeed) > 0)))
	{
// not got edge; see if got 1/4 block boundary (if climable wall, this is as good)

		hdif = item->pos.y_pos + bounds[2];

		if ((hdif>>(WALL_SHIFT-2)) != ((hdif+item->fallspeed)>>(WALL_SHIFT-2)))
		{
			if (item->fallspeed > 0)
				*edge = (hdif+item->fallspeed) & ~(STEP_L-1);
			else
				*edge = hdif & ~(STEP_L-1);

			return -1;
		}
		return 0;
	}

//##	if (ABS(coll->left_floor-coll->right_floor) >= SLOPE_DIF)
	if (ABS(coll->left_floor2-coll->right_floor2) >= SLOPE_DIF)
		return 0;

	return 1; // got edge
}

/*****************************************************************************
 *		Lara Has Walked To An Edge Of A DropOff
 *			so Deflect or Stop..
 ****************************************************************************/
int LaraDeflectEdge( ITEM_INFO *item, COLL_INFO *coll )
{
	if ((coll->coll_type == COLL_FRONT)
	||  (coll->coll_type == COLL_TOPFRONT))
	{
		ShiftItem(item, coll);

		item->goal_anim_state = AS_STOP;         // Make Player Stop Immediately
		item->current_anim_state = AS_STOP;      // Because cant slide along Wall
		item->speed = 0;
		item->gravity_status = 0;
		return (1);
	}

	else if ( coll->coll_type==COLL_LEFT )
	{
		ShiftItem( item,coll );
		item->pos.y_rot += LARA_DEF_ADD_EDGE;
	}

	else if ( coll->coll_type==COLL_RIGHT )
	{
		ShiftItem( item,coll );
		item->pos.y_rot -= LARA_DEF_ADD_EDGE;
	}
	return (0);
}


int GetStaticObjects( ITEM_INFO *item, PHD_ANGLE ang, sint32 hite, sint32 radius, sint32 dist )
{
	int			i,j;
	ROOM_INFO		*r;
	MESH_INFO		*mesh;
	STATIC_INFO	*sinfo;
	sint16 		room_number;
	sint32		xmin,xmax,ymin,ymax,zmin,zmax;
	sint32		inxmin,inxmax,inymin,inymax,inzmin,inzmax,x,y,z;

	x = item->pos.x_pos + (( phd_sin(ang) * dist ) >> W2V_SHIFT );
	y = item->pos.y_pos;
	z = item->pos.z_pos + (( phd_cos(ang) * dist ) >> W2V_SHIFT );
	room_number = item->room_number;

	inxmin = x - radius;
	inxmax = x + radius;
	inymin = y - hite;
	inymax = y;
	inzmin = z - radius;
	inzmax = z + radius;
	GetNearByRooms( x,y,z, radius+50, hite+50, room_number );
	for ( i=0; i<number_draw_rooms; i++ )
	{
		r = &room[ draw_rooms[i] ];
		mesh = r->mesh;

		for ( j=r->num_meshes; j>0; j--, mesh++ )
		{
			sinfo = &static_objects[mesh->static_number];
			if ( (sinfo->flags&1) ) 					// If Bit 0 of flag set Skip collision
				continue;

			ymin = mesh->y + sinfo->y_minc;
			ymax = mesh->y + sinfo->y_maxc;
			switch ( mesh->y_rot )
			{
				default:								// Object Facing NORTH
					xmin = mesh->x + sinfo->x_minc;
					xmax = mesh->x + sinfo->x_maxc;
					zmin = mesh->z + sinfo->z_minc;
					zmax = mesh->z + sinfo->z_maxc;
				break;

				case 16384:								// Object Facing EAST
					xmin = mesh->x + sinfo->z_minc;
					xmax = mesh->x + sinfo->z_maxc;
					zmin = mesh->z - sinfo->x_maxc;
					zmax = mesh->z - sinfo->x_minc;
				break;

				case -32768:							// Object Facing SOUTH
					xmin = mesh->x - sinfo->x_maxc;
					xmax = mesh->x - sinfo->x_minc;
					zmin = mesh->z - sinfo->z_maxc;
					zmax = mesh->z - sinfo->z_minc;
				break;

				case -16384:							// Object Facing WEST
					xmin = mesh->x - sinfo->z_maxc;
					xmax = mesh->x - sinfo->z_minc;
					zmin = mesh->z + sinfo->x_minc;
					zmax = mesh->z + sinfo->x_maxc;
				break;
			}

			if ( inxmax<=xmin || inxmin>=xmax ||
			 	inymax<=ymin || inymin>=ymax ||
			 	inzmax<=zmin || inzmin>=zmax )		// If Dont Collide Exit Pronto....
				continue;

			return (1);
		}
	}
	return(0);
}

