/***********************************************************************************************************/
/*                                                                                                         */
/* Lara Climbing Control                                                                                   */
/*                                                                                                         */
/***********************************************************************************************************/

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

#ifdef PSX_VERSION
#include "../spec_psx/typedefs.h"
#include "../spec_psx/psxinput.h"
#else
#include "../specific/stypes.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 "laramisc.h"

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

#define CLIMB_HITE (STEP_L*2)
#define CLIMB_HANG (900)

/* 70 will allow Lara to go allow steep edges, but she's on a climb wall, so
 * what the hell anyway, it is needed for UP/DOWN anims to shift correctly
 *  when hit edges */
#define CLIMB_SHIFT 70

#define CAM_E_CLIMBS	-20*ONE_DEGREE

#define CAM_A_CLIMBL	-30*ONE_DEGREE
#define CAM_E_CLIMBL	-15*ONE_DEGREE

#define CAM_A_CLIMBR	30*ONE_DEGREE
#define CAM_E_CLIMBR	-15*ONE_DEGREE

#define CAM_E_CLIMBU	30*ONE_DEGREE

#define CAM_E_CLIMBD	-45*ONE_DEGREE

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


#ifdef GAMEDEBUG
char	*clmb_txt[]={
	 "ONTO",
	 "UPTO",
	 "DOWNTO",
	 "HANG",
	 "LIMIT"
 };
#endif

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

static sint32 LaraCheckForLetGo(ITEM_INFO *item, COLL_INFO *coll)
{
	sint16 room_number;
	FLOOR_INFO *floor;

	item->gravity_status = item->fallspeed = 0;

	// get info about triggers first
	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;

	// then check if Lara is still interested in hanging on
	if ( !(input&IN_ACTION) || item->hit_points<=0)	// If user Dies Or releases Action
	{
		lara.head_x_rot = lara.head_y_rot = lara.torso_x_rot = lara.torso_y_rot = 0;

		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->gravity_status = 1;
		item->speed = 2;
		item->fallspeed = 1;
		lara.gun_status = LG_ARMLESS;
		return(1);
	}
	return(0);
}


/************************************************************************************************/
/******************************* LARA LEFT/RIGHT CLIMB TESTS ************************************/
/************************************************************************************************/

int LaraTestClimb(int x, int y, int z, int xfront, int zfront, int item_height, sint16 item_room, int *shift)
{
	// x,y,z is at hands and against wall; xfront,zfront shift into wall; item_height is top to bottom height
	// Return 0 if bad, 1 if can climb, -1 if need to hang
	// Also sets 'shift' to allow for small movements when near the edge of walls
	sint16 room_number;
	int height, ceiling;
	int hang=1;
	FLOOR_INFO *floor;

	*shift = 0;

	// check if even climbable
	if (!lara.climb_status)
		return 0;

	// check if anything blocking position from above/below
	room_number = item_room;
	floor = GetFloor(x, y-STEP_L/2, z, &room_number); // hands minus a bit so get right room
	height = GetHeight(floor, x, y, z);
	if (height == NO_HEIGHT)
		return 0;

	height -= (y + item_height + (STEP_L/2)); // item_height + a bit so don't get TOO close to ground
	if (height < - CLIMB_SHIFT)
		return 0;
	else if (height < 0)
		*shift = height;

	ceiling = GetCeiling(floor, x, y, z) - y;

//##	room_number = item_room;
//##	floor = GetFloor(lara_item->pos.x_pos, lara_item->pos.y_pos, lara_item->pos.z_pos, &room_number);
//##	ceiling = GetCeiling(floor, lara_item->pos.x_pos, lara_item->pos.y_pos, lara_item->pos.z_pos) - lara_item->pos.y_pos;

	if (ceiling > CLIMB_SHIFT)
		return 0;
	else if (ceiling > 0)
	{
		if (*shift)
			return 0;			// cannot shift both up and down, so bad pos
		*shift = ceiling;
	}


	if (item_height + height < CLIMB_HANG)
		hang = 0;				// if not much room below feet, can forget trying to hang

	// test point on wall by hands
	floor = GetFloor(x+xfront, y, z+zfront, &room_number);
	height = GetHeight(floor, x+xfront, y, z+zfront);
	if (height != NO_HEIGHT)
		height -= y;

	if (height > CLIMB_SHIFT)
	{
		// if floor is below hands, then need to check if ceiling is there to hang onto instead
		ceiling = GetCeiling(floor, x+xfront, y, z+zfront) - y;
		if (ceiling >= CLIMB_HITE)
			return 1;				// ceiling goes below feet so can climb
		else if (ceiling > CLIMB_HITE - CLIMB_SHIFT)
		{
			if (*shift > 0)	// a small up shift is all that is needed to climb; but may not be possible
			{
				if (hang)
					return -1;
				else
					return 0;
			}
			*shift = ceiling - CLIMB_HITE;
			return 1;
		}
		else if (ceiling > 0)
		{
			if (hang)
				return -1;				// ceiling goes below hands, so can hang...
			else
				return 0;				// ...assuming there's room
		}
		else if (ceiling > -CLIMB_SHIFT)
		{
			if (hang && *shift <= 0) // with a little up shift, can hang (assuming there is room)
			{
				if (*shift > ceiling)
					*shift = ceiling;
				return -1;
			}
			else
				return 0;
		}
		else
			return 0;					// no ceiling or floor to hang onto
	}
	else if (height > 0)
	{
		if (*shift < 0)					// allow shift down to edge, assuming no conflicting shifts already
			return 0;
		if (height > *shift)
			*shift = height;
	}

	// OK, so floor goes above hands; but sadly feet may be below a ceiling on the wall below
	room_number = item_room;
	floor = GetFloor(x, y+item_height, z, &room_number); // establish correct room
	floor = GetFloor(x+xfront, y+item_height, z+zfront, &room_number);
	ceiling = GetCeiling(floor, x+xfront, y+item_height, z+zfront);
	if (ceiling == NO_HEIGHT)
		return 1;

	ceiling -= y;
	if (ceiling <= height)
		return 1;						// if ceiling is still above floor, then OK

	// otherwise, there IS a ceiling below our hands; if above feet then hang only
	if (ceiling >= CLIMB_HITE)
		return 1;
	else if (ceiling > CLIMB_HITE - CLIMB_SHIFT)
	{
		if (*shift > 0)	// a small up shift is all that is needed to climb; but may not be possible
		{
			if (hang)
				return -1;
			else
				return 0;
		}
		*shift = ceiling - CLIMB_HITE;
		return 1;
	}
	else
	{
		if (hang)
			return -1;				// ceiling goes below hands, so can hang...
		else
			return 0;				// ...assuming there's room
	}
}

static void LaraDoClimbLeftRight(ITEM_INFO *item, COLL_INFO *coll, int result, int shift)
{
	// everything OK, so allow user input
	if (result == 1)
	{
		if ( input&IN_LEFT )
			item->goal_anim_state = AS_CLIMBLEFT;
		else if ( input&IN_RIGHT )
			item->goal_anim_state = AS_CLIMBRIGHT;
		else
			item->goal_anim_state = AS_CLIMBSTNC;
		item->pos.y_pos += shift;
	}
	else if (!result)
	{
		// need to stop right here; either to go to hang or to stop moving altogether
		item->pos.x_pos = coll->old.x;
		item->pos.z_pos = coll->old.z;
		item->goal_anim_state = AS_CLIMBSTNC;
		item->current_anim_state = AS_CLIMBSTNC;
		if (coll->old_anim_state != AS_CLIMBSTNC)
		{
			item->frame_number = CLIMBSTNC_F;
			item->anim_number = CLIMBSTNC_A;
		}
		else
		{
			item->frame_number = coll->old_frame_number;
			item->anim_number = coll->old_anim_number;
			AnimateLara(item);
		}
	}
	else
	{
		item->goal_anim_state = AS_HANG;
		do
			AnimateItem(item);
		while (item->current_anim_state != AS_HANG);
		item->pos.x_pos = coll->old.x; // snap back (as will have moved during AnimateItem())
		item->pos.z_pos = coll->old.z;
	}
}


int LaraTestClimbUpPos(ITEM_INFO *item, int front, int right, int *shift, int *ledge)
{
// VERSION OF LaraTestClimb PURELY FOR CLIMB UP TESTS (AS NEED TO KNOW IF CAN
// CLIMB ONTO LEDGES)
// x,y,z is at hands and against wall;
// xfront,zfront shift into wall;
// item_height is top to bottom height
// Return 0 if bad, 1 if can climb, -1 if need to climb onto ledge
// Also sets 'shift' to give slight push, and 'ledge' to give distance to ledge

	FLOOR_INFO *floor;
	sint16 room_number;
	int angle, x, y, z;
	int height, ceiling;
	int xfront=0, zfront=0;

	y = item->pos.y_pos - CLIMB_HITE - STEP_L;

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

	switch ( angle )
	{
		case NORTH:
			z = item->pos.z_pos + front;
			x = item->pos.x_pos + right;
			zfront = 4;
			break;
		case EAST:
			x = item->pos.x_pos + front;
			z = item->pos.z_pos - right;
			xfront = 4;
			break;
		case SOUTH:
			z = item->pos.z_pos - front;
			x = item->pos.x_pos - right;
			zfront = -4;
			break;
		default:
			x = item->pos.x_pos - front;
			z = item->pos.z_pos + right;
			xfront = -4;
			break;
	}

	*shift = 0;

// check if anything blocking position from above (leave a bit of room for Lara's head too)

	room_number = item->room_number;
	floor = GetFloor(x, y, z, &room_number);
	ceiling = GetCeiling(floor, x, y, z) - (y - STEP_L);

//##	floor = GetFloor(lara_item->pos.x_pos, lara_item->pos.y_pos, lara_item->pos.z_pos, &room_number);
//##	ceiling = GetCeiling(floor, lara_item->pos.x_pos, lara_item->pos.y_pos, lara_item->pos.z_pos) - (lara_item->pos.y_pos - STEP_L);

	if (ceiling > CLIMB_SHIFT)
		return 0;

	else if (ceiling > 0)
		*shift = ceiling;

// test point on wall by hands
	floor = GetFloor(x+xfront, y, z+zfront, &room_number);
	height = GetHeight(floor, x+xfront, y, z+zfront);
	if (height == NO_HEIGHT)
	{
		*ledge = NO_HEIGHT;
		return 1;				// pure wall
	}

	height -= y;
	*ledge = height;
	if (height > (STEP_L/2))
	{
	// if floor is below hands, then need to check if ceiling is there to hang onto instead
		ceiling = GetCeiling(floor, x+xfront, y, z+zfront) - y;
		if (ceiling >= CLIMB_HITE)
			return 1;				// ceiling goes below feet so can climb

		else if (height - ceiling > LARA_HITE)
		{
//			printf("ledge = %d\n", *ledge);
			*shift = height;
			return -1;				// must have climbed onto ledge; and enough room to do climb up
		}
		else
			return 0;				// not enough room
	}

	else if (height > 0)
	{
		if (height > *shift)		// shift to edge
			*shift = height;
	}

// OK, so floor goes above hands; but sadly feet may be below a ceiling on the wall below
	room_number = item->room_number;
	floor = GetFloor(x, y+CLIMB_HITE, z, &room_number); // establish correct room
	floor = GetFloor(x+xfront, y+CLIMB_HITE, z+zfront, &room_number);
	ceiling = GetCeiling(floor, x+xfront, y+CLIMB_HITE, z+zfront) - y;
	if (ceiling <= height)
		return 1;						// if ceiling is still above floor, then OK

	if (ceiling>=CLIMB_HITE)
		return 1;						// if below feet, OK too
	else
		return 0;						// otherwise, must be a thin gap that we're trying to climb up over
}

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

int LaraTestClimbPos(ITEM_INFO *item, int front, int right, int origin, int height, int *shift)
{
	/* Get information about climb/hang status of wall to front/right of Lara position */
	int angle, x, z;
	int xfront=0, zfront=0;

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

	switch ( angle )
	{
		case NORTH:
			z = item->pos.z_pos + front;
			x = item->pos.x_pos + right;
			zfront = 4;
			break;
		case EAST:
			x = item->pos.x_pos + front;
			z = item->pos.z_pos - right;
			xfront = 4;
			break;
		case SOUTH:
			z = item->pos.z_pos - front;
			x = item->pos.x_pos - right;
			zfront = -4;
			break;
		default:
			x = item->pos.x_pos - front;
			z = item->pos.z_pos + right;
			xfront = -4;
			break;
	}

	return LaraTestClimb(x, item->pos.y_pos+origin, z, xfront, zfront, height, item->room_number, shift);
}


//-------------------------------- CLIMBLEFT ----------------------------
void	lara_as_climbleft( ITEM_INFO *item, COLL_INFO *coll )
{
	coll->enable_spaz = 0;
	coll->enable_baddie_push = 0;
	camera.target_angle = CAM_A_CLIMBL;
	camera.target_elevation = CAM_E_CLIMBL;
	if ( !(input&IN_LEFT) && !(input&IN_STEPL) )
		item->goal_anim_state = AS_CLIMBSTNC;
}


//-------------------------------- CLIMBRIGHT ----------------------------
void	lara_as_climbright( ITEM_INFO *item, COLL_INFO *coll )
{
	coll->enable_spaz = 0;
	coll->enable_baddie_push = 0;
	camera.target_angle = CAM_A_CLIMBR;
	camera.target_elevation = CAM_E_CLIMBR;
	if ( !(input&IN_RIGHT) && !(input&IN_STEPR) )
		item->goal_anim_state = AS_CLIMBSTNC;
}


//-------------------------------CLIMB STANCE ------------------------------------
void	lara_as_climbstnc( ITEM_INFO *item, COLL_INFO *coll )
{
	coll->enable_spaz = 0;
	coll->enable_baddie_push = 0;
	camera.target_elevation = CAM_E_CLIMBS;

	if (input & IN_LOOK)
		LookUpDown();

	if ( input&IN_LEFT || input&IN_STEPL )
		item->goal_anim_state = AS_CLIMBLEFT;
	else if ( input&IN_RIGHT || input&IN_STEPR )
		item->goal_anim_state = AS_CLIMBRIGHT;
	else if ( input&IN_JUMP )
	{
		item->goal_anim_state = AS_BACKJUMP;
		lara.move_angle = item->pos.y_rot-32768;
		lara.gun_status = LG_ARMLESS;
	}
}
//-------------------------------CLIMBING ------------------------------------
void	lara_as_climbing( ITEM_INFO *item, COLL_INFO *coll )
{
	coll->enable_spaz = 0;
	coll->enable_baddie_push = 0;
	camera.target_elevation = CAM_E_CLIMBU;
}
//-------------------------------CLIMB END ------------------------------------
void	lara_as_climbend( ITEM_INFO *item, COLL_INFO *coll )
{
	coll->enable_spaz = 0;
	coll->enable_baddie_push = 0;
	camera.flags = FOLLOW_CENTRE;
	camera.target_angle = -45*ONE_DEGREE;
}
//-------------------------------CLIMB DOWN ------------------------------------
void	lara_as_climbdown( ITEM_INFO *item, COLL_INFO *coll )
{
	coll->enable_spaz = 0;
	coll->enable_baddie_push = 0;
	camera.target_elevation = CAM_E_CLIMBD;
}

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


//++++++++++++++++++++++++++ CLIMBLEFT ++++++++++++++++++++++++++++++++++++++++++
void	lara_col_climbleft( ITEM_INFO *item, COLL_INFO *coll )
{
	int result, shift;

	if (LaraCheckForLetGo(item, coll))
		return;

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

	result = LaraTestClimbPos(item, coll->radius, -(coll->radius+CLIMB_WIDTHL), -CLIMB_HITE, CLIMB_HITE, &shift);

	LaraDoClimbLeftRight(item, coll, result, shift);
}

//++++++++++++++++++++++++++ CLIMBRIGHT ++++++++++++++++++++++++++++++++++++++++++
void	lara_col_climbright( ITEM_INFO *item, COLL_INFO *coll )
{
	int result, shift;

	if (LaraCheckForLetGo(item, coll))
		return;

	lara.move_angle = item->pos.y_rot+16384;

	result = LaraTestClimbPos(item, coll->radius, (coll->radius+CLIMB_WIDTHR), -CLIMB_HITE, CLIMB_HITE, &shift);

	LaraDoClimbLeftRight(item, coll, result, shift);
}

//+++++++++++++++++++++++++++ CLIMB STANCE +++++++++++++++++++++++++++++++++++++++++
void	lara_col_climbstnc( ITEM_INFO *item, COLL_INFO *coll )
{
	int result_r, result_l, shift_r, shift_l, ledge_r, ledge_l;

	if (LaraCheckForLetGo(item, coll))
		return;

// only check user control if player is in the climb stance anim
	if (item->anim_number != CLIMBSTNC_A)
		return;


// If player pushes forward then go into climbing anim or climb up
	if (input & IN_FORWARD)
	{
		if (item->goal_anim_state == AS_NULL)
			return;

		item->goal_anim_state = AS_CLIMBSTNC;

	// test if point quarter block ahead is OK to go to before initiating upward move
		result_r = LaraTestClimbUpPos(item, coll->radius, coll->radius+CLIMB_WIDTHR, &shift_r, &ledge_r);
		result_l = LaraTestClimbUpPos(item, coll->radius, -(coll->radius+CLIMB_WIDTHL), &shift_l, &ledge_l);

		if ((!result_r)
		||  (!result_l))
			return;

	// ledges must be pretty similar, else too steep a slope to hold
		if ((result_r < 0)
		||  (result_l < 0))
		{
			if (ABS(ledge_l-ledge_r) > 120)
				return;
//printf("off\n");
			item->pos.y_pos += (ledge_l + ledge_r)/2 - STEP_L;
			item->goal_anim_state = AS_NULL;
			return;
		}

	// resolve shifts
		if (shift_r)
		{
			if (shift_l)
			{
				if ((shift_r<0) ^ (shift_l<0))
					return;
				if (shift_r<0 && shift_r<shift_l)
					shift_l = shift_r;
				else if (shift_r>0 && shift_r>shift_l)
					shift_l = shift_r;
			}
			else
				shift_l = shift_r;
		}

		item->goal_anim_state = AS_CLIMBING;
		item->pos.y_pos += shift_l;
	}

	else if (input & IN_BACK)
	{
		if (item->goal_anim_state == AS_HANG)
			return;

		item->goal_anim_state = AS_CLIMBSTNC;

	// test if point quarter block ahead is OK to go to before initiating downward move
		item->pos.y_pos += STEP_L;
		result_r = LaraTestClimbPos(item, coll->radius, coll->radius+CLIMB_WIDTHR, -CLIMB_HITE, CLIMB_HITE, &shift_r);
		result_l = LaraTestClimbPos(item, coll->radius, -(coll->radius+CLIMB_WIDTHL), -CLIMB_HITE, CLIMB_HITE, &shift_l);
		item->pos.y_pos -= STEP_L;

	// bad position, so don't move
		if ((!result_r)
		||  (!result_l))
			return;

	// resolve shifts
		if (shift_r && shift_l)
		{
			if ((shift_r<0) ^ (shift_l<0))
				return;
			if (shift_r<0 && shift_r<shift_l)
				shift_l = shift_r;
			else if (shift_r>0 && shift_r>shift_l)
				shift_l = shift_r;
		}

	// good position, so climb down
		if ((result_r == 1)
		&&  (result_l == 1))
		{
			item->goal_anim_state = AS_CLIMBDOWN;
			item->pos.y_pos += shift_l;
		}
	// hangable position, so do climb down to hang
		else
			item->goal_anim_state = AS_HANG;
	}
}

//+++++++++++++++++++++++++++ CLIMBING +++++++++++++++++++++++++++++++++++++++++
void	lara_col_climbing( ITEM_INFO *item, COLL_INFO *coll )
{
	int result_r, result_l, shift_r, shift_l, ledge_r, ledge_l;
	int yshift, frame;

	if (LaraCheckForLetGo(item, coll))
		return;

// NASTY: climb up loop is one big anim, so need to check ahead at link points to see
// whether to continue climbing or not. If not, then need to shift origin (and do AnimateLara
// to avoid 1 frame origin jump) so link to climb stance works properly
	if (item->anim_number == CLIMBING_A)
	{
		frame = item->frame_number - anims[CLIMBING_A].frame_base;

		if (frame == 0)
			yshift = 0;

		else if (frame == CLIMBUP_LNK1-1 || frame == CLIMBUP_LNK1)
			yshift = -STEP_L;

		else if (frame == CLIMBUP_LNK2-1)
			yshift = -STEP_L*2;

		else
			return;
	}
	else
		return;

// need to look another 1/4 ahead as Lara is bit behind in loop
	item->pos.y_pos += yshift-STEP_L;
	result_r = LaraTestClimbUpPos(item, coll->radius, coll->radius+CLIMB_WIDTHR, &shift_r, &ledge_r);
	result_l = LaraTestClimbUpPos(item, coll->radius, -(coll->radius+CLIMB_WIDTHL), &shift_l, &ledge_l);
	item->pos.y_pos += STEP_L;

// if a problem with this position or no longer want to go up, stop
	if (!result_r || !result_l || !(input&IN_FORWARD))
	{
  		item->goal_anim_state = AS_CLIMBSTNC;
		if (yshift)
			AnimateLara(item);
		return;
	}

	// go to AS_NULL if reached edge (climb up onto it)
	if (result_r<0 || result_l<0)
	{
		item->goal_anim_state = AS_CLIMBSTNC;
		AnimateLara(item);
		if (ABS(ledge_l-ledge_r) <= 120) // shifts must be pretty similar, else to steep a slope to hold
		{
			item->goal_anim_state = AS_NULL;
			item->pos.y_pos += (ledge_r+ledge_l)/2 - STEP_L;
		}
		return;
	}

	// continue climbing OK
	item->goal_anim_state = AS_CLIMBING;
	item->pos.y_pos -= yshift;
}

//+++++++++++++++++++++++++++ CLIMB END +++++++++++++++++++++++++++++++++++++++++
void	lara_col_climbend( ITEM_INFO *item, COLL_INFO *coll )
{
}

//+++++++++++++++++++++++++++ CLIMB DOWN +++++++++++++++++++++++++++++++++++++++++
void	lara_col_climbdown( ITEM_INFO *item, COLL_INFO *coll )
{
	int result_r, result_l, shift_r, shift_l;
	int yshift, frame;

	if (LaraCheckForLetGo(item, coll))
		return;

	// NASTY: climb down loop is one big anim, so need to check ahead at link points to see
	// whether to continue climbing or not. If not, then need to shift origin (and do AnimateLara
	// to avoid 1 frame origin jump) so link to climb stance works properly
	if (item->anim_number == CLIMBDOWN_A)
	{
		frame = item->frame_number - anims[CLIMBDOWN_A].frame_base;
		if (frame == 0)
			yshift = 0;
		else if (frame == CLIMBDN_LNK1-1 || frame == CLIMBDN_LNK1)
			yshift = STEP_L;
		else if (frame == CLIMBDN_LNK2-1)
			yshift = STEP_L*2;
		else
			return;
	}
	else
		return;

	// test a quarter block ahead
	item->pos.y_pos += yshift + STEP_L;
	result_r = LaraTestClimbPos(item, coll->radius, coll->radius+CLIMB_WIDTHR, -CLIMB_HITE, CLIMB_HITE, &shift_r);
	result_l = LaraTestClimbPos(item, coll->radius, -(coll->radius+CLIMB_WIDTHL), -CLIMB_HITE, CLIMB_HITE, &shift_l);
	item->pos.y_pos -= STEP_L;

	// if a problem with this position
	if (!result_r || !result_l || !(input&IN_BACK))
	{
  		item->goal_anim_state = AS_CLIMBSTNC;
		if (yshift)
			AnimateLara(item);
		return;
	}

	if (shift_r && shift_l) // resolve shifts
	{
		if ((shift_r<0) ^ (shift_l<0))
		{
			item->goal_anim_state = AS_CLIMBSTNC;
			AnimateLara(item);
			return;
		}
		if (shift_r<0 && shift_r<shift_l)
			shift_l = shift_r;
		else if (shift_r>0 && shift_r>shift_l)
			shift_l = shift_r;
	}

	// if either result says hang, then better go to hang
	if (result_r == -1 || result_l == -1)
	{
  		item->current_anim_state = AS_CLIMBSTNC;
  		item->frame_number = CLIMBSTNC_F;
  		item->anim_number = CLIMBSTNC_A;
		item->goal_anim_state = AS_HANG;
		AnimateLara(item);
		return;
	}

	// continue climb down, so remove yshift
	item->goal_anim_state = AS_CLIMBDOWN;
	item->pos.y_pos -= yshift;
}



