/*********************************************************************************************/
/*                                                                                           */
/* Hybrid Mutant Control - TS  - 14/8/98                                                     */
/*                                                                                           */
/*********************************************************************************************/

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

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

#include "objects.h"
#include "items.h"
#include "box.h"
#include "lara.h"
#include "laraanim.h"
#include "control.h"
#include "people.h"

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

//#define DEBUG_HYBRID
#define HYBRID_SLASH_DAMAGE 100
#define HYBRID_KICK_DAMAGE 80
#define HYBRID_JUMP_DAMAGE 20
#define HYBRID_SLASH_TOUCH (0x80)
#define HYBRID_KICK_TOUCH (0x800)

#define HYBRID_DIE_ANIM 18

#define HYBRID_WALK_TURN (3*ONE_DEGREE)
#define HYBRID_RUN_TURN  (6*ONE_DEGREE)

#define HYBRID_ATTACK1_RANGE SQUARE(WALL_L)
#define HYBRID_ATTACK2_RANGE SQUARE(WALL_L*2)
#define HYBRID_ATTACK3_RANGE SQUARE(WALL_L*4/3)
#define HYBRID_FIRE_RANGE SQUARE(WALL_L*3)
#define HYBRID_ROAR_CHANCE 0x60
#define HYBRID_WALK_CHANCE (HYBRID_ROAR_CHANCE + 0x400)
#define HYBRID_AWARE_DISTANCE SQUARE(WALL_L)

enum hybrid_anims {
	HYBRID_EMPTY,
	HYBRID_STOP,
	HYBRID_WALK,
	HYBRID_RUN,
	HYBRID_JUMP_STR,
	HYBRID_JUMP_MID,
	HYBRID_JUMP_END,
	HYBRID_SLASH_LEFT,
	HYBRID_KICK,
	HYBRID_RUN_ATAK,
	HYBRID_WALK_ATAK,
	HYBRID_DEATH
};

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

#ifdef DEBUG_HYBRID
extern char exit_message[];
#endif

#ifdef DEBUG_HYBRID
static char *HybridStrings[] = {
	"EMPTY",
	"STOP",
	"WALK",
	"RUN",
	"JUMP_STR",
	"JUMP_MID",
	"JUMP_END",
	"SLASH_LEFT",
	"KICK",
	"RUN_ATAK",
	"WALK_ATAK",
	"DEATH"
};
#endif

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

static BITE_INFO hybrid_bite_left = {19,-13,3, 7};
static BITE_INFO hybrid_bite_right = {19,-13,3, 14};


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

void HybridControl(sint16 item_number)
{
	ITEM_INFO *item, *real_enemy;
	CREATURE_INFO *hybrid;
	sint16 angle, head, torso_y, torso_x, tilt;
	sint32 lara_dx, lara_dz;
	AI_INFO info, lara_info;

	if (!CreatureActive(item_number))
		return;

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

	if (item->hit_points <= 0)
	{
		if (item->current_anim_state != HYBRID_DEATH)
		{
			item->anim_number = objects[item->object_number].anim_index + HYBRID_DIE_ANIM;
			item->frame_number = anims[item->anim_number].frame_base;
			item->current_anim_state = HYBRID_DEATH;
		}
	}
	else
	{
		if (item->ai_bits)
			GetAITarget(hybrid);

		CreatureAIInfo(item, &info);

	//	if (info.ahead)
	//		head = info.angle;
		if (hybrid->enemy == lara_item)
		{
			lara_info.angle = info.angle;
			lara_info.distance = info.distance;
		}
		else
		{
			lara_dz = lara_item->pos.z_pos - item->pos.z_pos;
			lara_dx = lara_item->pos.x_pos - item->pos.x_pos;
			lara_info.angle = phd_atan(lara_dz, lara_dx) - item->pos.y_rot; //only need to fill out the bits of lara_info that will be needed by TargetVisible
			lara_info.distance = lara_dz * lara_dz + lara_dx * lara_dx;
		}

		GetCreatureMood(item, &info, VIOLENT);
		CreatureMood(item, &info, VIOLENT);


		angle = CreatureTurn(item, hybrid->maximum_turn);

		real_enemy = hybrid->enemy; //TargetVisible uses enemy, so need to fill this in as lara if we're doing other things
		hybrid->enemy = lara_item;
		if (lara_info.distance < HYBRID_AWARE_DISTANCE || item->hit_status || TargetVisible(item, &lara_info))
			AlertAllGuards(item_number);
		hybrid->enemy = real_enemy;

		switch (item->current_anim_state)
		{
		case HYBRID_STOP:
			hybrid->maximum_turn = 0;
			hybrid->flags = 0;

//			hybrid->LOT.step = STEP_L;
//			hybrid->LOT.drop = -STEP_L*2;
//			hybrid->LOT.fly = NO_FLYING;

			head = info.angle;
			if (item->ai_bits & GUARD)
			{
				head = AIGuard(hybrid);
			//	torso_y = head >> 3;
				item->goal_anim_state = HYBRID_STOP;
				break;
			}
			else if (item->ai_bits & PATROL1)
			{
				item->goal_anim_state = HYBRID_WALK;
				head= 0;
			}
			else if (hybrid->mood == ESCAPE_MOOD)
			{
				if (lara.target != item && info.ahead)
					item->goal_anim_state = HYBRID_STOP;
				else
					item->goal_anim_state = HYBRID_RUN;
			}
			else if (info.angle < 0x2000 && info.angle > -0x2000 && info.distance > HYBRID_ATTACK1_RANGE)
					item->goal_anim_state = HYBRID_JUMP_STR;
			else if (info.bite && info.distance < HYBRID_ATTACK1_RANGE)
			{
				torso_y = info.angle;
				torso_x = info.x_angle;
				if (info.angle < 0)
					item->goal_anim_state = HYBRID_SLASH_LEFT;
				else
					item->goal_anim_state = HYBRID_KICK;
			}
			else if (item->required_anim_state)
				item->goal_anim_state = item->required_anim_state;
			else if (info.distance < HYBRID_ATTACK2_RANGE)
				item->goal_anim_state = HYBRID_WALK;
			else
				item->goal_anim_state = HYBRID_RUN;
			break;

		case HYBRID_WALK:
			hybrid->maximum_turn = HYBRID_WALK_TURN;
			if (info.ahead)
				head = info.angle;
			if (item->ai_bits & PATROL1)
			{
				item->goal_anim_state = HYBRID_WALK;
				head = 0;
			}
			else if (info.bite && info.distance < HYBRID_ATTACK3_RANGE)
			{
				hybrid->maximum_turn = HYBRID_WALK_TURN;
				item->goal_anim_state = HYBRID_WALK_ATAK;
			}
			else if (hybrid->mood == ESCAPE_MOOD || hybrid->mood == ATTACK_MOOD) // TS - come back to this, it's wrong (don't want to go into RUN all the time)
				item->goal_anim_state = HYBRID_RUN; 
			break;

		case HYBRID_RUN:
			hybrid->maximum_turn = HYBRID_RUN_TURN;
			if (info.ahead)
				head = info.angle;
			if (item->ai_bits & GUARD)
				item->goal_anim_state = HYBRID_STOP;
			else if (hybrid->mood == BORED_MOOD	|| (hybrid->mood == ESCAPE_MOOD && lara.target != item && info.ahead))
				item->goal_anim_state = HYBRID_STOP;
			else if (hybrid->flags && info.ahead)
				item->goal_anim_state = HYBRID_STOP;
			else if (info.bite && info.distance < HYBRID_ATTACK2_RANGE)
			{
				if (lara_item->speed == 0) // this maybe should be a small range rather than zero
					item->goal_anim_state = HYBRID_STOP;
				else
					item->goal_anim_state = HYBRID_RUN_ATAK;
			}
			else if (info.distance < HYBRID_ATTACK2_RANGE)
				item->goal_anim_state = HYBRID_WALK;
			hybrid->flags = 0;
			break;

		case HYBRID_WALK_ATAK:
		case HYBRID_RUN_ATAK:
		case HYBRID_SLASH_LEFT:
			hybrid->maximum_turn = HYBRID_WALK_TURN;

			if (info.ahead)
			{
				torso_y = info.angle;
				torso_x = info.x_angle;
			}

			if (!hybrid->flags && (item->touch_bits & HYBRID_SLASH_TOUCH))
			{
				lara_item->hit_status = 1;
				lara_item->hit_points -= HYBRID_SLASH_DAMAGE;
				CreatureEffect(item, &hybrid_bite_left, DoBloodSplat);
				hybrid->flags = 1;
			}

			if (!(info.bite && info.distance < HYBRID_ATTACK1_RANGE))
					item->goal_anim_state = HYBRID_STOP;

			if (item->frame_number == anims[item->anim_number].frame_end)
				hybrid->flags = 0;

			break;

		case HYBRID_KICK:
			hybrid->maximum_turn = HYBRID_WALK_TURN;

			if (info.ahead)
			{
				torso_y = info.angle;
				torso_x = info.x_angle;
			}

			if (!hybrid->flags && (item->touch_bits & HYBRID_KICK_TOUCH))
			{
				lara_item->hit_status = 1;
				lara_item->hit_points -= HYBRID_KICK_DAMAGE;
				CreatureEffect(item, &hybrid_bite_right, DoBloodSplat);
				hybrid->flags = 1;
			}

			if (!(info.bite && info.distance < HYBRID_ATTACK1_RANGE))
					item->goal_anim_state = HYBRID_STOP;

			if (item->frame_number == anims[item->anim_number].frame_end)
				hybrid->flags = 0;

			break;

		case HYBRID_JUMP_STR:
			hybrid->maximum_turn = HYBRID_WALK_TURN;
//			hybrid->LOT.step = STEP_L*2;
//			hybrid->LOT.drop =  -WALL_L;
//			hybrid->LOT.fly = STEP_L/32;
			break;

		case HYBRID_JUMP_MID:
		case HYBRID_JUMP_END:
			hybrid->maximum_turn = 0;

			if (info.ahead)
			{
				torso_y = info.angle;
				torso_x = info.x_angle;
			}

			if ((item->touch_bits & HYBRID_SLASH_TOUCH))
			{
				lara_item->hit_status = 1;
				lara_item->hit_points -= HYBRID_JUMP_DAMAGE;
				CreatureEffect(item, &hybrid_bite_left, DoBloodSplat);
			}

			break;


			/*
		case HYBRID_FIRE_ATAK:
			if (abs(info.angle) <  HYBRID_WALK_TURN)
				item->pos.y_rot += info.angle;
			else if (info.angle < 0)
				item->pos.y_rot -= HYBRID_WALK_TURN;
			else
				item->pos.y_rot += HYBRID_WALK_TURN;

			if (info.ahead)
			{
				torso_y = info.angle >> 1;
				torso_x = info.x_angle;
			}
			*/
		}
	}

	CreatureTilt(item, tilt);
//	CreatureJoint(item, 0, torso_y);
//	CreatureJoint(item, 1, torso_x);
	CreatureJoint(item, 0, torso_x);
	CreatureJoint(item, 1, torso_y);
	CreatureJoint(item, 2, head);

	#ifdef DEBUG_HYBRID
	sprintf(exit_message, "Bx:%d, LBx:%d, Z:%d, LZ:%d", item->box_number, lara_item->box_number, info.zone_number, info.enemy_zone);
	PrintDbug(2, 1, exit_message);
	sprintf(exit_message, "Mood: %d, BxH:%d, LBxH:%d", hybrid->mood, boxes[item->box_number].height, boxes[lara_item->box_number].height);
	PrintDbug(2, 2, exit_message);
	sprintf(exit_message, "%s", HybridStrings[item->current_anim_state]);
	PrintDbug(2, 3, exit_message);
	sprintf(exit_message, "%s", HybridStrings[item->goal_anim_state]);
	PrintDbug(2, 4, exit_message);
	sprintf(exit_message, "LRoom:%d, LRmFlags:%d", lara_item->room_number, room[lara_item->room_number].flags);
	PrintDbug(2, 5, exit_message);
	sprintf(exit_message, "H:%d, LH:%d", item->pos.y_pos, lara_item->pos.y_pos);
	PrintDbug(2, 6, exit_message);
//	sprintf(exit_message, "Anim Number; %d", item->anim_number - objects[MUTANT2].anim_index);
//	PrintDbug(2, 6, exit_message);
//	sprintf(exit_message, "Alert:%d, Goal:%d, Hurt:%d", hybrid->alerted, hybrid->reached_goal, hybrid->hurt_by_lara);
//	PrintDbug(2,6, exit_message);
//	sprintf(exit_message, "Flags: %d", hybrid->flags);
//	PrintDbug(2,7, exit_message);
	sprintf(exit_message, "Room %d  X:%d  Z:%d", lara_item->room_number, (int)(lara_item->pos.x_pos/1024), (int)(lara_item->pos.z_pos/1024));
	PrintDbug(2, 15, exit_message);

	#endif



	CreatureAnimation(item_number, angle, tilt);
}
