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

#ifdef PSX_VERSION
#include "../spec_psx/typedefs.h"
#else
#include "../specific/stypes.h"
#endif

#include "objects.h"
#include "lara.h"
#include "sound.h"
#include "control.h"

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

#define TRIBEAXE_AXE_DAMAGE 16
#define TRIBEAXE_AXE_ENEMY_DAMAGE 2

enum tribeaxe_anims {TRIBEAXE_EMPTY, TRIBEAXE_WAIT1, TRIBEAXE_WALK, TRIBEAXE_RUN, TRIBEAXE_ATTACK1, TRIBEAXE_ATTACK2, TRIBEAXE_ATTACK3, TRIBEAXE_ATTACK4, TRIBEAXE_AIM3, TRIBEAXE_DEATH, TRIBEAXE_ATTACK5, TRIBEAXE_WAIT2, TRIBEAXE_ATTACK6};

#define TRIBEAXE_WALK_TURN (ONE_DEGREE*9)
#define TRIBEAXE_RUN_TURN (ONE_DEGREE*6)
#define TRIBEAXE_OTHER_TURN (ONE_DEGREE*4)

#define TRIBEAXE_CLOSE_RANGE SQUARE(WALL_L*2/3)
#define TRIBEAXE_LONG_RANGE SQUARE(WALL_L)
#define TRIBEAXE_ATTACK5_RANGE SQUARE(WALL_L*3)
#define TRIBEAXE_WALK_RANGE SQUARE(WALL_L*2)
#define TRIBE_ESCAPE_RANGE SQUARE(WALL_L*3)
#define TRIBEAXE_HIT_RANGE (STEP_L*2)

#define TRIBEAXE_TOUCH (1<<13)

#define TRIBEAXE_DIE_ANIM_STAND 20
#define TRIBEAXE_DIE_ANIM_DOWN 21

//#define DEBUG_TRIBEAXE

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

#ifdef DEBUG_TRIBEAXE
extern char exit_message[];
#endif

#ifdef DEBUG_TRIBEAXE
static char *TribeStrings[] = {
"EMPTY", "WAIT1", "WALK", "RUN", "ATTACK1", "ATTACK2", "ATTACK3", "ATTACK4", "AIM3", "DEATH", "ATTACK5", "WAIT2", "ATTACK6"};
#endif

static BITE_INFO tribeaxe_hit = {0,16,265, 13};

static unsigned char tribeaxe_hitframes[13][3] = {
	{0,0,0},		//	0 	TRIBEAXE_EMPTY
	{0,0,0},  	//	1 	TRIBEAXE_WAIT1
	{0,0,0},  	//	2 	TRIBEAXE_WALK
	{0,0,0},  	//	3 	TRIBEAXE_RUN
	{0,0,0},  	//	4 	TRIBEAXE_ATTACK1
	{2,12,8}, 	//	5 	TRIBEAXE_ATTACK2
	{8,9,32},  	//	6 	TRIBEAXE_ATTACK3
	{19,28,8},	//	7 	TRIBEAXE_ATTACK4
	{0,0,0},  	//	8 	TRIBEAXE_AIM3
	{0,0,0},  	//	9 	TRIBEAXE_DEATH
	{7,14,8}, 	//	10	TRIBEAXE_ATTACK5
	{0,0,0},  	//	11	TRIBEAXE_WAIT2
	{15,19,32} 	//	12	TRIBEAXE_ATTACK6
};

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

void TribeAxeControl(sint16 item_number)
{
	ITEM_INFO *item, *enemy;
	CREATURE_INFO *tribeaxe;
	sint16 angle, head, tilt;
	AI_INFO info;

	if (!CreatureActive(item_number))
		return;

	item = &items[item_number];
	tribeaxe = (CREATURE_INFO *)item->data;
	head = angle = tilt = 0;

	if (item->hit_points <= 0)
	{
		if (item->current_anim_state != TRIBEAXE_DEATH)
		{
			if (	item->current_anim_state == TRIBEAXE_WAIT1 ||
				item->current_anim_state == TRIBEAXE_ATTACK4)
				item->anim_number = objects[item->object_number].anim_index + TRIBEAXE_DIE_ANIM_DOWN;
			else
				item->anim_number = objects[item->object_number].anim_index + TRIBEAXE_DIE_ANIM_STAND;
			item->frame_number = anims[item->anim_number].frame_base;
			item->current_anim_state = TRIBEAXE_DEATH;
		}
	}
	else
	{
		CreatureAIInfo(item, &info);

		GetCreatureMood(item, &info, VIOLENT);
		//## TS - test hide code
		if (tribeaxe->enemy == lara_item && tribeaxe->hurt_by_lara && info.distance > TRIBE_ESCAPE_RANGE && info.enemy_facing < 0x3000 && info.enemy_facing > -0x3000)		
			tribeaxe->mood = ESCAPE_MOOD;
		CreatureMood(item, &info, VIOLENT);

		angle = CreatureTurn(item, tribeaxe->maximum_turn);
		if (info.ahead)
			head = info.angle;

		switch (item->current_anim_state)
		{
			case TRIBEAXE_WAIT1:	// Ducking and waiting.
				tribeaxe->maximum_turn = TRIBEAXE_OTHER_TURN;
				tribeaxe->flags = 0;

				if (tribeaxe->mood == BORED_MOOD)
				{
					tribeaxe->maximum_turn = 0;
					if (GetRandomControl() < 0x100)
						item->goal_anim_state = TRIBEAXE_WALK;
				}
				else if (tribeaxe->mood == ESCAPE_MOOD)
				{
					if (lara.target != item && info.ahead && !item->hit_status)
						item->goal_anim_state = TRIBEAXE_WAIT1;
					else
						item->goal_anim_state = TRIBEAXE_RUN;
				}
				else if (item->item_flags[0])
				{
					item->item_flags[0] = 0;
				    	item->goal_anim_state = TRIBEAXE_WAIT2;
				}
				else	if (info.ahead && info.distance < TRIBEAXE_CLOSE_RANGE)	// Close enough to attack?
				{
					item->goal_anim_state = TRIBEAXE_ATTACK4;
				}
				else if (info.ahead && info.distance < TRIBEAXE_LONG_RANGE)
				{
					if (GetRandomControl() < 0x4000)
						item->goal_anim_state = TRIBEAXE_WALK;
					else
					{
						item->goal_anim_state = TRIBEAXE_ATTACK4;
					}
				}
				else if (info.ahead && info.distance < TRIBEAXE_WALK_RANGE)
					item->goal_anim_state = TRIBEAXE_WALK;
				else
					item->goal_anim_state = TRIBEAXE_RUN;

				break;

			case TRIBEAXE_WAIT2:
				tribeaxe->maximum_turn = TRIBEAXE_OTHER_TURN;
				tribeaxe->flags = 0;

				if (tribeaxe->mood == BORED_MOOD)
				{
					tribeaxe->maximum_turn = 0;
					if (GetRandomControl() < 0x100)
						item->goal_anim_state = TRIBEAXE_WALK;
				}
				else if (tribeaxe->mood == ESCAPE_MOOD)
				{
					if (lara.target != item && info.ahead && !item->hit_status)
						item->goal_anim_state = TRIBEAXE_WAIT1;
					else
						item->goal_anim_state = TRIBEAXE_RUN;
				}
				else	if (info.ahead && info.distance < TRIBEAXE_CLOSE_RANGE)	// Close enough to attack?
				{
					if (GetRandomControl() < 0x800)
						item->goal_anim_state = TRIBEAXE_ATTACK2;
					else
						item->goal_anim_state = TRIBEAXE_AIM3;
				}
				else if (info.distance < TRIBEAXE_WALK_RANGE)
					item->goal_anim_state = TRIBEAXE_WALK;
				else
					item->goal_anim_state = TRIBEAXE_RUN;

				break;

			case TRIBEAXE_WALK:
				tribeaxe->flags = 0;
				tribeaxe->maximum_turn = TRIBEAXE_WALK_TURN;
				tilt = angle>>3;

				if (tribeaxe->mood == BORED_MOOD)
				{
					tribeaxe->maximum_turn >>= 2;
					if (GetRandomControl() < 0x100)
					{
						if (GetRandomControl() < 0x2000)
							item->goal_anim_state = TRIBEAXE_WAIT1;
						else
							item->goal_anim_state = TRIBEAXE_WAIT2;
					}
				}
				else if (tribeaxe->mood == ESCAPE_MOOD)
					item->goal_anim_state = TRIBEAXE_RUN;
				else if (info.ahead && info.distance < TRIBEAXE_CLOSE_RANGE)
				{
					if (GetRandomControl() < 0x2000)
						item->goal_anim_state = TRIBEAXE_WAIT1;
					else
						item->goal_anim_state = TRIBEAXE_WAIT2;
				}
				else if (info.distance > TRIBEAXE_WALK_RANGE)
					item->goal_anim_state = TRIBEAXE_RUN;
				break;

			case TRIBEAXE_RUN:
				tribeaxe->flags = 0;
				tribeaxe->maximum_turn = TRIBEAXE_RUN_TURN;
				tilt = angle>>2;

				if (tribeaxe->mood == BORED_MOOD)
				{
					tribeaxe->maximum_turn >>= 2;
					if (GetRandomControl() < 0x100)
					{
						if (GetRandomControl() < 0x4000)
							item->goal_anim_state = TRIBEAXE_WAIT1;
						else
							item->goal_anim_state = TRIBEAXE_WAIT2;
					}
				}
				else if (tribeaxe->mood == ESCAPE_MOOD && lara.target != item && info.ahead)
					item->goal_anim_state = TRIBEAXE_WAIT2;
				else if (info.bite || info.distance < TRIBEAXE_WALK_RANGE)
				{
					if (GetRandomControl() < 0x4000)
						item->goal_anim_state = TRIBEAXE_ATTACK6;
					else if (GetRandomControl() < 0x2000)
						item->goal_anim_state = TRIBEAXE_ATTACK5;
					else
						item->goal_anim_state = TRIBEAXE_WALK;
				}

				break;

			case TRIBEAXE_AIM3:
				tribeaxe->maximum_turn = TRIBEAXE_OTHER_TURN;
			/*
				if (!info.ahead || info.distance > (TRIBEAXE_CLOSE_RANGE<<1))
					item->goal_anim_state = TRIBEAXE_WAIT2;
				else
					item->goal_anim_state = TRIBEAXE_ATTACK3;
				break;
			*/
				if (info.bite || info.distance < TRIBEAXE_CLOSE_RANGE)
					item->goal_anim_state = TRIBEAXE_ATTACK3;
				else
					item->goal_anim_state = TRIBEAXE_WAIT2;
				break;



			case TRIBEAXE_ATTACK2:
			case TRIBEAXE_ATTACK3:
			case TRIBEAXE_ATTACK4:
			case TRIBEAXE_ATTACK5:
			case TRIBEAXE_ATTACK6:
				item->item_flags[0] = 1;
				tribeaxe->maximum_turn = TRIBEAXE_OTHER_TURN;
				enemy = tribeaxe->enemy;
				tribeaxe->flags = item->frame_number - anims[item->anim_number].frame_base;

				if (enemy == lara_item)
				{
					if ((item->touch_bits & TRIBEAXE_TOUCH) &&
						tribeaxe->flags >= tribeaxe_hitframes[item->current_anim_state][0] &&
						tribeaxe->flags <= tribeaxe_hitframes[item->current_anim_state][1])
					{
						long	lp;
						lara_item->hit_points -= tribeaxe_hitframes[item->current_anim_state][2];
						lara_item->hit_status = 1;

//##						SoundEffect(245, &item->pos, 0);
						for (lp=0;lp<tribeaxe_hitframes[item->current_anim_state][2];lp+=8)
							CreatureEffect(item, &tribeaxe_hit, DoBloodSplat);
							SoundEffect(70, &item->pos, 0);

					}
				}
				else
				{
					if (enemy)
					{
						if (ABS(enemy->pos.x_pos - item->pos.x_pos) < TRIBEAXE_HIT_RANGE &&
						 	ABS(enemy->pos.y_pos - item->pos.y_pos) < TRIBEAXE_HIT_RANGE &&
						 	ABS(enemy->pos.z_pos - item->pos.z_pos) < TRIBEAXE_HIT_RANGE &&
							tribeaxe->flags >= tribeaxe_hitframes[item->current_anim_state][0] &&
							tribeaxe->flags <= tribeaxe_hitframes[item->current_anim_state][1])
						{
							enemy->hit_points -= TRIBEAXE_AXE_ENEMY_DAMAGE;
							enemy->hit_status = 1;
							CreatureEffect(item, &tribeaxe_hit, DoBloodSplat);
							SoundEffect(70, &item->pos, 0);

//##							SoundEffect(245, &item->pos, 0);
						}
					}
				}

				break;

		}
	}

#ifdef DEBUG_TRIBEAXE
	sprintf(exit_message, "%s", TribeStrings[item->current_anim_state]);
	PrintDbug(2, 4, exit_message);
	sprintf(exit_message, "%s", TribeStrings[item->goal_anim_state]);
	PrintDbug(2, 5, exit_message);
//	sprintf(exit_message, "%s", TribeStrings[item->required_anim_state]);
//	PrintDbug(2, 6, exit_message);
//	sprintf(exit_message, "Near Cover:%d, OilRed Y:%d", near_cover, item->pos.y_pos);
//	PrintDbug(2,7, exit_message);
#endif


	CreatureTilt(item, tilt);
	CreatureJoint(item, 0, head>>1);
	CreatureJoint(item, 1, head>>1);

	/* Actually do animation allowing for collisions */
	CreatureAnimation(item_number, angle, 0);
}
