#ifndef LOS_H
#define LOS_H

//#define LOS_DEBUG


// fixed-point arithmetic definitions start here

typedef INT32 FIXEDPT;
// rem 1 signed bit at the top
#define FIXEDPT_WHOLE_BITS 11
#define FIXEDPT_FRACTIONAL_BITS 20
#define FIXEDPT_FRACTIONAL_RESOLUTION 1048576

#define INT32_TO_FIXEDPT( n ) ( (n) << FIXEDPT_FRACTIONAL_BITS )
#define FIXEDPT_TO_INT32( n ) ( (n) / FIXEDPT_FRACTIONAL_RESOLUTION )

#define FIXEDPT_TO_TILE_NUM( n ) (FIXEDPT_TO_INT32( (n) ) / CELL_X_SIZE)
#define FIXEDPT_TO_LOS_INDEX( n ) (CONVERT_WITHINTILE_TO_INDEX( FIXEDPT_TO_INT32( (n) ) % CELL_X_SIZE))

// fixed-point arithmetic definitions end here

#define	OK_CHANCE_TO_GET_THROUGH		10

enum
{
	COLLISION_NONE,
	COLLISION_GROUND,
	COLLISION_MERC,
	COLLISION_WINDOW_SOUTHEAST,
	COLLISION_WINDOW_SOUTHWEST,
	COLLISION_WINDOW_NORTHEAST,
	COLLISION_WINDOW_NORTHWEST,
	COLLISION_WINDOW_NORTH,
	COLLISION_WALL_SOUTHEAST,
	COLLISION_WALL_SOUTHWEST,
	COLLISION_WALL_NORTHEAST,
	COLLISION_WALL_NORTHWEST,
	COLLISION_STRUCTURE,
	COLLISION_ROOF,
	COLLISION_INTERIOR_ROOF,
	COLLISION_STRUCTURE_Z,
	COLLISION_WATER,

} CollisionEnums;


INT32	CheckForCollision( FLOAT dX, FLOAT dY, FLOAT dZ, FLOAT dDeltaX, FLOAT dDeltaY, FLOAT dDeltaZ, INT16 *pusStructureID, FLOAT *pdNormalX, FLOAT *pdNormalY, FLOAT *pdNormalZ );


INT8 ChanceToGetThrough( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOAT dEndZ );
INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOAT dEndZ, UINT16 usHandItem, INT16 sHitBy, BOOLEAN fBuckshot, BOOLEAN fFake );

INT32 SoldierToSoldierLineOfSightTest( SOLDIERTYPE * pStartSoldier, SOLDIERTYPE * pEndSoldier, UINT8 ubSightLimit, INT8 bAware );
INT32 SoldierToLocationLineOfSightTest( SOLDIERTYPE * pStartSoldier, INT16 sGridNo, UINT8 ubSightLimit, INT8 bAware );
INT32 SoldierTo3DLocationLineOfSightTest( SOLDIERTYPE * pStartSoldier, INT16 sGridNo, INT8 bLevel, INT8 bCubeLevel, UINT8 ubSightLimit, INT8 bAware );
INT32 SoldierToBodyPartLineOfSightTest( SOLDIERTYPE * pStartSoldier, INT16 sGridNo, INT8 bLevel, UINT8 ubAimLocation, UINT8 ubTileSightLimit, INT8 bAware );
INT32 SoldierToVirtualSoldierLineOfSightTest( SOLDIERTYPE * pStartSoldier, INT16 sGridNo, INT8 bLevel, INT8 bStance, UINT8 ubTileSightLimit, INT8 bAware );
UINT8 SoldierToSoldierChanceToGetThrough( SOLDIERTYPE * pStartSoldier, SOLDIERTYPE * pEndSoldier );
UINT8 SoldierToSoldierBodyPartChanceToGetThrough( SOLDIERTYPE * pStartSoldier, SOLDIERTYPE * pEndSoldier, UINT8 ubAimLocation );
UINT8 AISoldierToSoldierChanceToGetThrough( SOLDIERTYPE * pStartSoldier, SOLDIERTYPE * pEndSoldier );
UINT8 AISoldierToLocationChanceToGetThrough( SOLDIERTYPE * pStartSoldier, INT16 sGridNo, INT8 bLevel, INT8 bCubeLevel );
UINT8 SoldierToLocationChanceToGetThrough( SOLDIERTYPE * pStartSoldier, INT16 sGridNo, INT8 bLevel, INT8 bCubeLevel, UINT8 ubTargetID );
INT32 SoldierToLocationVisibleDistance( SOLDIERTYPE * pStartSoldier, INT16 sGridNo, UINT8 ubTileSightLimit, INT8 bAware );
INT16 SoldierToLocationWindowTest( SOLDIERTYPE * pStartSoldier, INT16 sEndGridNo );
INT32 LocationToLocationLineOfSightTest( INT16 sStartGridNo, INT8 bStartLevel, INT16 sEndGridNo, INT8 bEndLevel, UINT8 ubTileSightLimit, INT8 bAware );

BOOLEAN CalculateSoldierZPos( SOLDIERTYPE * pSoldier, UINT8 ubPosType, FLOAT * pdZPos );

BOOLEAN SoldierToSoldierLineOfSightTimingTest( SOLDIERTYPE * pStartSoldier, SOLDIERTYPE * pEndSoldier, UINT8 ubSightLimit, INT8 bAware );
BOOLEAN TestFireBullet( SOLDIERTYPE * pStartSoldier, SOLDIERTYPE * pEndSoldier );
void DoChrisTest( SOLDIERTYPE * pSoldier );


#define HEIGHT_UNITS 256
#define HEIGHT_UNITS_PER_INDEX (HEIGHT_UNITS / PROFILE_Z_SIZE)
#define MAX_STRUCTURE_HEIGHT 50
// 5.12 == HEIGHT_UNITS / MAX_STRUCTURE_HEIGHT
#define CONVERT_PIXELS_TO_HEIGHTUNITS( n ) ((n) * HEIGHT_UNITS / MAX_STRUCTURE_HEIGHT)
#define CONVERT_PIXELS_TO_INDEX( n ) ((n) * HEIGHT_UNITS / MAX_STRUCTURE_HEIGHT / HEIGHT_UNITS_PER_INDEX)
#define CONVERT_HEIGHTUNITS_TO_INDEX( n ) ((n) / HEIGHT_UNITS_PER_INDEX)
#define CONVERT_HEIGHTUNITS_TO_DISTANCE( n ) ((n) / (HEIGHT_UNITS / CELL_X_SIZE) )
#define CONVERT_HEIGHTUNITS_TO_PIXELS( n ) ((n) * MAX_STRUCTURE_HEIGHT / HEIGHT_UNITS )
#define CONVERT_WITHINTILE_TO_INDEX( n ) ((n) >> 1)
#define CONVERT_INDEX_TO_WITHINTILE( n ) ((n) << 1)
#define CONVERT_INDEX_TO_PIXELS( n ) ((n) * MAX_STRUCTURE_HEIGHT * HEIGHT_UNITS_PER_INDEX / HEIGHT_UNITS)


#define TREE_SIGHT_REDUCTION 6
#define NORMAL_TREES 10

enum {
	LOS_POS,
	FIRING_POS,
	TARGET_POS,
	HEAD_TARGET_POS,
	TORSO_TARGET_POS,
	LEGS_TARGET_POS,
	HEIGHT
};

// 191 is 6' (structures of height 3)
// 127 is 4' (structures of height 2)
//  63 is 2' (structures of height 1)


#define STANDING_HEIGHT 191.0f
#define STANDING_LOS_POS 175.0f
#define STANDING_FIRING_POS 175.0f
#define STANDING_HEAD_TARGET_POS 175.0f
#define STANDING_HEAD_BOTTOM_POS 159.0f
#define STANDING_TORSO_TARGET_POS 127.0f
#define STANDING_TORSO_BOTTOM_POS 95.0f
#define STANDING_LEGS_TARGET_POS 47.0f
#define STANDING_TARGET_POS STANDING_HEAD_TARGET_POS

#define CROUCHED_HEIGHT 130.0f
#define CROUCHED_LOS_POS 111.0f
#define CROUCHED_FIRING_POS 111.0f

#define CROUCHED_HEAD_TARGET_POS 111.0f
#define CROUCHED_HEAD_BOTTOM_POS 95.0f
#define CROUCHED_TORSO_TARGET_POS 71.0f
#define CROUCHED_TORSO_BOTTOM_POS 47.0f
#define CROUCHED_LEGS_TARGET_POS 31.0f
#define CROUCHED_TARGET_POS CROUCHED_HEAD_TARGET_POS

#define PRONE_HEIGHT 63.0f
#define PRONE_LOS_POS 31.0f
#define PRONE_FIRING_POS 31.0f
#define PRONE_TORSO_TARGET_POS 31.0f
#define PRONE_HEAD_TARGET_POS 31.0f
#define PRONE_LEGS_TARGET_POS 31.0f
#define PRONE_TARGET_POS PRONE_HEAD_TARGET_POS

#define WALL_HEIGHT_UNITS HEIGHT_UNITS
#define WINDOW_BOTTOM_HEIGHT_UNITS 87
#define WINDOW_TOP_HEIGHT_UNITS 220

#define CLOSE_TO_FIRER 25
#define VERY_CLOSE_TO_FIRER 21

#ifdef LOS_DEBUG
typedef struct LOSResults
{
	BOOLEAN			fLOSTestPerformed;
	BOOLEAN			fLOSClear;
	BOOLEAN			fOutOfRange;
	INT32				iDistance;
	INT32				iMaxDistance;
	UINT8				ubTreeSpotsHit;
	INT32				iStartX;
	INT32				iStartY;
	INT32				iStartZ;
	INT32				iEndX;
	INT32				iEndY;
	INT32				iEndZ;
	INT32				iStoppedX;
	INT32				iStoppedY;
	INT32				iStoppedZ;
	INT32				iCurrCubesZ;
	UINT8				ubChanceToGetThrough;
} LOSResults;

extern LOSResults gLOSTestResults;

#endif

void MoveBullet( INT32 iBullet );
//BOOLEAN FireBullet2( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOAT dEndZ, INT16 sHitBy );

#endif