/*********************************************************************************************/
/*                                                                                           */
/* Dog Control                                                                         TOMB2 */
/*                                                                                           */
/*********************************************************************************************/

#include "game.h"

/*********************************** TYPE DEFINITIONS ****************************************/

#define DOG_BITE_DAMAGE 100
#define DOG_LEAP_DAMAGE 200
#define DOG_LUNGE_DAMAGE 100

#define TIGER_BITE_DAMAGE 100

//-------------------------------------------------------------------------------------------------

/* Define all the bits of a Doberman that count as pain if they touch Lara */
#define DOG_TOUCH (0x13f7000)

enum dog_anims {DOG_EMPTY, DOG_WALK, DOG_RUN, DOG_STOP, DOG_BARK, DOG_CROUCH, DOG_STAND, DOG_ATTACK1, DOG_ATTACK2, DOG_ATTACK3, DOG_DEATH};

#define DOG_DIE_ANIM 13

#define DOG_WALK_TURN (3*ONE_DEGREE)
#define DOG_RUN_TURN  (6*ONE_DEGREE)

#define DOG_ATTACK1_RANGE SQUARE(WALL_L/3)
#define DOG_ATTACK2_RANGE SQUARE(WALL_L*3/4)
#define DOG_ATTACK3_RANGE SQUARE(WALL_L*2/3)

#define DOG_BARK_CHANCE		0x300
#define DOG_CROUCH_CHANCE	(DOG_BARK_CHANCE + 0x300)
#define DOG_STAND_CHANCE	(DOG_CROUCH_CHANCE + 0x500)
#define DOG_WALK_CHANCE		(DOG_CROUCH_CHANCE + 0x2000)

#define DOG_UNCROUCH_CHANCE 0x100
#define DOG_UNSTAND_CHANCE  0x200
#define DOG_UNBARK_CHANCE   0x500

BITE_INFO dog_bite = {0,30,141, 20};


#define TIGER_TOUCH (0x7fdc000)

enum tiger_anims {TIGER_EMPTY, TIGER_STOP, TIGER_WALK, TIGER_RUN, TIGER_WAIT, TIGER_ROAR, TIGER_ATTACK1, TIGER_ATTACK2, TIGER_ATTACK3, TIGER_DEATH};

#define TIGER_DIE_ANIM 11

#define TIGER_WALK_TURN (3*ONE_DEGREE)
#define TIGER_RUN_TURN  (6*ONE_DEGREE)

#define TIGER_ATTACK1_RANGE SQUARE(WALL_L/3)
#define TIGER_ATTACK2_RANGE SQUARE(WALL_L*3/2)
#define TIGER_ATTACK3_RANGE SQUARE(WALL_L)

#define TIGER_ROAR_CHANCE 0x60
#define TIGER_WALK_CHANCE (TIGER_ROAR_CHANCE + 0x400)

BITE_INFO tiger_bite = {19,-13,3, 26};

/*********************************** FUNCTION CODE *******************************************/

void DogControl(sint16 item_number)
{
	ITEM_INFO *item;
	CREATURE_INFO *dog;
	sint16 angle, head, tilt, random;
	AI_INFO info;

	if (!CreatureActive(item_number))
		return;

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

	if (item->hit_points <= 0)
	{
		if (item->current_anim_state != DOG_DEATH)
		{
			item->anim_number = objects[DOG].anim_index + DOG_DIE_ANIM;
			item->frame_number = anims[item->anim_number].frame_base;
			item->current_anim_state = DOG_DEATH;
		}
	}
	else
	{
		CreatureAIInfo(item, &info);

		if (info.ahead)
			head = info.angle;

		CreatureMood(item, &info, TIMID);

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

		switch (item->current_anim_state)
		{
		case DOG_STOP:
			dog->maximum_turn = 0;
			dog->flags = 0;

			if (dog->mood == BORED_MOOD)
			{
				if (item->required_anim_state)
					item->goal_anim_state = item->required_anim_state;
				else
				{
					random =(sint16) GetRandomControl();
					if (random < DOG_BARK_CHANCE)
						item->goal_anim_state = DOG_BARK;
					else if (random < DOG_CROUCH_CHANCE)
						item->goal_anim_state = DOG_CROUCH;
					else if (random < DOG_WALK_CHANCE)
						item->goal_anim_state = DOG_WALK;
				}
			}
			else if (dog->mood == ESCAPE_MOOD)
				item->goal_anim_state = DOG_RUN;
			else if (info.distance < DOG_ATTACK1_RANGE && info.ahead)
				item->goal_anim_state = DOG_ATTACK1;
			else
				item->goal_anim_state = DOG_RUN;
			break;

		case DOG_WALK:
			dog->maximum_turn = DOG_WALK_TURN;

			if (dog->mood == BORED_MOOD)
			{
				random =(sint16) GetRandomControl();
				if (random < DOG_BARK_CHANCE)
				{
					item->required_anim_state = DOG_BARK;
					item->goal_anim_state = DOG_STOP;
				}
				else if (random < DOG_CROUCH_CHANCE)
				{
					item->required_anim_state = DOG_CROUCH;
					item->goal_anim_state = DOG_STOP;
				}
				else if (random < DOG_STAND_CHANCE)
					item->goal_anim_state = DOG_STOP;
			}
			else
				item->goal_anim_state = DOG_RUN;
			break;

		case DOG_RUN:
			tilt = angle;
			dog->maximum_turn = DOG_RUN_TURN;

			if (dog->mood == BORED_MOOD)
				item->goal_anim_state = DOG_STOP;
			else if (info.distance < DOG_ATTACK2_RANGE)
				item->goal_anim_state = DOG_ATTACK2;
			break;

		case DOG_ATTACK2:
			// Charging leap attack
			if (dog->flags!=2 && (item->touch_bits & DOG_TOUCH))
			{
				CreatureEffect(item, &dog_bite, DoBloodSplat);
				lara_item->hit_points -= DOG_LEAP_DAMAGE;
				lara_item->hit_status = 1;
				dog->flags = 2;
			}

			// If leap ends near to Lara, bite or lunge to get her
			if (info.distance < DOG_ATTACK1_RANGE)
				item->goal_anim_state = DOG_ATTACK1;
			else if (info.distance < DOG_ATTACK3_RANGE)
				item->goal_anim_state = DOG_ATTACK3;
			break;

		case DOG_ATTACK1:
			// Standing bite attack
			dog->maximum_turn = 0;

			if (dog->flags!=1 && info.ahead && (item->touch_bits & DOG_TOUCH))
			{
				CreatureEffect(item, &dog_bite, DoBloodSplat);
				lara_item->hit_points -= DOG_BITE_DAMAGE;
				lara_item->hit_status = 1;
				dog->flags = 1;
			}

			// If Lara moves a small distance away, lunge at her
			if (info.distance > DOG_ATTACK1_RANGE && info.distance < DOG_ATTACK3_RANGE)
				item->goal_anim_state = DOG_ATTACK3;
			else
				item->goal_anim_state = DOG_STOP;
			break;

		case DOG_ATTACK3:
			// Lunging jump attack
			dog->maximum_turn = DOG_RUN_TURN;

			if (dog->flags!=3 && (item->touch_bits & DOG_TOUCH))
			{
				CreatureEffect(item, &dog_bite, DoBloodSplat);
				lara_item->hit_points -= DOG_LUNGE_DAMAGE;
				lara_item->hit_status = 1;
				dog->flags = 3;
			}

			// If lunge results in arriving next to Lara, bite her
			if (info.distance < DOG_ATTACK1_RANGE)
				item->goal_anim_state = DOG_ATTACK1;
			break;

		case DOG_BARK:
			if (dog->mood != BORED_MOOD || GetRandomControl() < DOG_UNBARK_CHANCE)
				item->goal_anim_state = DOG_STOP;
			break;

		case DOG_CROUCH:
			if (dog->mood != BORED_MOOD || GetRandomControl() < DOG_UNCROUCH_CHANCE)
				item->goal_anim_state = DOG_STOP;
			break;

		case DOG_STAND:
			if (dog->mood != BORED_MOOD || GetRandomControl() < DOG_UNSTAND_CHANCE)
				item->goal_anim_state = DOG_STOP;
			break;
		}
	}

	CreatureTilt(item, tilt);
	CreatureHead(item, head);

	CreatureAnimation(item_number, angle, tilt);
}


void TigerControl(sint16 item_number)
{
	ITEM_INFO *item;
	CREATURE_INFO *tiger;
	sint16 angle, head, tilt, random;
	AI_INFO info;

	if (!CreatureActive(item_number))
		return;

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

	if (item->hit_points <= 0)
	{
		if (item->current_anim_state != TIGER_DEATH)
		{
			item->anim_number = objects[TIGER].anim_index + TIGER_DIE_ANIM;
			item->frame_number = anims[item->anim_number].frame_base;
			item->current_anim_state = TIGER_DEATH;
		}
	}
	else
	{
		CreatureAIInfo(item, &info);

		if (info.ahead)
			head = info.angle;

		CreatureMood(item, &info, VIOLENT);

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

		switch (item->current_anim_state)
		{
		case TIGER_STOP:
			tiger->maximum_turn = 0;
			tiger->flags = 0;

			if (tiger->mood == ESCAPE_MOOD)
				item->goal_anim_state = TIGER_RUN;
			else if (tiger->mood == BORED_MOOD)
			{
				random =(sint16) GetRandomControl();
				if (random < TIGER_ROAR_CHANCE)
					item->goal_anim_state = TIGER_ROAR;
				else if (random < TIGER_WALK_CHANCE);
					item->goal_anim_state = TIGER_WALK;
			}
			else if (info.ahead && info.distance < TIGER_ATTACK1_RANGE)
				item->goal_anim_state = TIGER_ATTACK1;
			else if (info.ahead && info.distance < TIGER_ATTACK3_RANGE)
			{
				tiger->maximum_turn = TIGER_WALK_TURN;
				item->goal_anim_state = TIGER_ATTACK3;
			}
			else if (item->required_anim_state)
				item->goal_anim_state = item->required_anim_state;
			else if (tiger->mood != ATTACK_MOOD && GetRandomControl() < TIGER_ROAR_CHANCE)
				item->goal_anim_state = TIGER_ROAR;
			else
				item->goal_anim_state = TIGER_RUN;
			break;

		case TIGER_WALK:
			tiger->maximum_turn = TIGER_WALK_TURN;

			if (tiger->mood == ESCAPE_MOOD || tiger->mood == ATTACK_MOOD)
				item->goal_anim_state = TIGER_RUN;
			else if (GetRandomControl() < TIGER_ROAR_CHANCE)
			{
				item->goal_anim_state = TIGER_STOP;
				item->required_anim_state = TIGER_ROAR;
			}
			break;

		case TIGER_RUN:
			tiger->maximum_turn = TIGER_RUN_TURN;

			if (tiger->mood == BORED_MOOD)
				item->goal_anim_state = TIGER_STOP;
			else if (tiger->flags && info.ahead)
				/* After TIGER_ATTACK2, if close to Lara, stop and start close attacks */
				item->goal_anim_state = TIGER_STOP;
			else if (info.ahead && info.distance < TIGER_ATTACK2_RANGE)
			{
				if (lara_item->speed == 0) // this maybe should be a small range rather than zero
					item->goal_anim_state = TIGER_STOP;
				else
					item->goal_anim_state = TIGER_ATTACK2;
			}
			else if (tiger->mood != ATTACK_MOOD && GetRandomControl() < TIGER_ROAR_CHANCE)
			{
				item->required_anim_state = TIGER_ROAR;
				item->goal_anim_state = TIGER_STOP;
			}

			tiger->flags = 0;
			break;

		case TIGER_ATTACK1:
		case TIGER_ATTACK2:
		case TIGER_ATTACK3:
			if (!tiger->flags && (item->touch_bits & TIGER_TOUCH))
			{
				lara_item->hit_status = 1;
				lara_item->hit_points -= TIGER_BITE_DAMAGE;
				CreatureEffect(item, &tiger_bite, DoBloodSplat);

				tiger->flags = 1;
			}
			break;
		}
	}

	CreatureTilt(item, tilt);
	CreatureHead(item, head);

	CreatureAnimation(item_number, angle, tilt);
}
