/*********************************************************************************************/
/*                                                                                           */
/* Dragon                                                                              TOMB2 */
/*                                                                                           */
/*********************************************************************************************/

#include "game.h"

#define DRAGON_SWIPE_DAMAGE 250
#define DRAGON_TOUCH_DAMAGE 10

/* Just touching the dino results in damage per frame (trample damage is when dino hits while running) */
#define DINO_TOUCH_DAMAGE 1
#define DINO_TRAMPLE_DAMAGE 10
#define DINO_BITE_DAMAGE 10000

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

enum dragon_anims {DRAGON_EMPTY, DRAGON_WALK, DRAGON_LEFT, DRAGON_RIGHT, DRAGON_AIM1, DRAGON_FIRE1, DRAGON_STOP, 
	DRAGON_TURNLEFT, DRAGON_TURNRIGHT, DRAGON_SWIPELEFT, DRAGON_SWIPERIGHT, DRAGON_DEATH};

#define DRAGON_DIE_ANIM 21
#define DRAGON_DEAD_ANIM 22

#define DRAGON_LIVE_TIME (30*11)
#define DRAGON_ALMOST_LIVE 100

#define DRAGON_WALK_TURN (ONE_DEGREE*2)
#define DRAGON_NEED_TURN (ONE_DEGREE*1)

#define DRAGON_TURN_TURN (ONE_DEGREE*1)

#define DRAGON_CLOSE_RANGE SQUARE(WALL_L*3)
#define DRAGON_STOP_RANGE SQUARE(WALL_L*6)

#define DRAGON_FLAME_SPEED 200

BITE_INFO dragon_mouth = {35,171,1168, 12};

#define DRAGON_TOUCH_R  0x0fe
#define DRAGON_TOUCH_L  0x7f000000


#define DINO_TOUCH (0x3000)

enum dino_anims {DINO_LINK, DINO_STOP, DINO_WALK, DINO_RUN, DINO_ATTACK1, DINO_DEATH, DINO_ROAR,
	DINO_ATTACK2, DINO_KILL};

#define DINO_ROAR_CHANCE 0x200

#define DINO_RUN_TURN  (ONE_DEGREE*4)
#define DINO_WALK_TURN (ONE_DEGREE*2)

#define DINO_RUN_RANGE SQUARE(WALL_L*5)
#define DINO_ATTACK_RANGE SQUARE(WALL_L*4)
#define DINO_BITE_RANGE SQUARE(1500)

#define DINO_KILL_ANIM 11

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

void ControlTwinkle(sint16 fx_number)
{
	int c, s;
	FX_INFO	*fx;
	ITEM_INFO *item;
	PHD_VECTOR pos;

	fx = &effects[fx_number];
	
	fx->frame_number--;
	if (fx->frame_number <= objects[fx->object_number].nmeshes)
		fx->frame_number = 0;

	if (fx->counter >= 0)
	{
		/* If positive it is an item to head towards */
		item = &items[fx->counter];

		pos.x = item->pos.x_pos;
		pos.y = item->pos.y_pos;
		pos.z = item->pos.z_pos;
		if (item->object_number == DRAGON_FRONT)
		{
			c = phd_cos(item->pos.y_rot);
			s = phd_sin(item->pos.y_rot);
			pos.z += (490*c - 1100*s) >> W2V_SHIFT;
			pos.x += (490*s + 1100*c) >> W2V_SHIFT;
			pos.y -= 540;
		}
		fx->pos.x_pos += (pos.x - fx->pos.x_pos)>>4;
		fx->pos.y_pos += (pos.y - fx->pos.y_pos)>>4;
		fx->pos.z_pos += (pos.z - fx->pos.z_pos)>>4;

		if (ABS(fx->pos.x_pos - pos.x) < STEP_L && ABS(fx->pos.y_pos - pos.y) < STEP_L && ABS(fx->pos.z_pos - pos.z) < STEP_L)
			KillEffect(fx_number);
	}
	else
	{
		/* If negative, it is a time to stay around for */
		fx->counter++;
		if (fx->counter == 0)
			KillEffect(fx_number);
	}
}

void CreateBartoliLight(sint16 item_number)
{
	ITEM_INFO *item;
	FX_INFO *fx;
	int fx_number;

	item = &items[item_number];
	fx_number = CreateEffect(item->room_number);
	if (fx_number != NO_ITEM)
	{
		fx = &effects[fx_number];
		fx->object_number = TWINKLE;
		fx->pos.y_rot = (sint16)(GetRandomDraw() << 1);
		fx->pos.x_pos = item->pos.x_pos + (WALL_L*5 * phd_sin(fx->pos.y_rot) >> W2V_SHIFT);
		fx->pos.y_pos = item->pos.y_pos + (GetRandomDraw() >> 2) - WALL_L;
		fx->pos.z_pos = item->pos.z_pos + (WALL_L*5 * phd_cos(fx->pos.y_rot) >> W2V_SHIFT);
		fx->room_number = item->room_number;
		fx->counter = item_number; // remember Bartoli position
		fx->frame_number = 0;
	}

	AddDynamicLight(item->pos.x_pos, item->pos.y_pos, item->pos.z_pos, (GetRandomDraw()*4>>15)+12, (GetRandomDraw()*4>>15)+10);
}

sint16 DragonFire(sint32 x, sint32 y, sint32 z, sint16 speed, PHD_ANGLE yrot, sint16 room_number)
{
	sint16 fx_number;
	FX_INFO *fx;

	fx_number = CreateEffect(room_number);
	if (fx_number != NO_ITEM)
	{
		fx = &effects[fx_number];
		fx->pos.x_pos = x;
		fx->pos.y_pos = y;
		fx->pos.z_pos = z;
		fx->room_number = room_number;
		fx->pos.x_rot = fx->pos.z_rot = 0;
		fx->pos.y_rot = yrot;
		fx->speed = DRAGON_FLAME_SPEED;
		fx->frame_number = GetRandomDraw() * (objects[DRAGON_FIRE].nmeshes+1) >> 15;
		fx->object_number = DRAGON_FIRE;
		fx->shade = 14 * 256;
		ShootAtLara(fx);

		// CUTE HACK: dragon and flame bloke are not on same level, so check for DRAGON_FRONT loaded
		if (objects[DRAGON_FRONT].loaded)
			fx->counter = 0x4000; // 'infinite' range for dragon fire
		else
			fx->counter = 20; // shorter range for flamethrower
	}

	return (fx_number);
}


#define DRAGON_CLOSE 900
#define DRAGON_FAR   2300
#define DRAGON_MID   ((DRAGON_CLOSE+DRAGON_FAR)/2)
#define DRAGON_LCOL  -512
#define DRAGON_RCOL  +512

void DragonCollision(sint16 item_number, ITEM_INFO *laraitem, COLL_INFO *coll)
{
	ITEM_INFO *item;
	int c, s, rx, rz, shift, side_shift, angle;
	int anim, frame;

	/* If Lara has collided with correct bit of dragon, then start him up */
	item = &items[item_number];

	if (!TestBoundsCollide(item, laraitem, coll->radius))
		return;
	if (!TestCollision(item, laraitem))
		return;

	/* Check for possible Lara extraction of knife */
	if (item->current_anim_state == DRAGON_DEATH)
	{
		rx = laraitem->pos.x_pos - item->pos.x_pos;
		rz = laraitem->pos.z_pos - item->pos.z_pos;
		c = phd_cos(item->pos.y_rot);
		s = phd_sin(item->pos.y_rot);

		/* See if Lara within leg space of dragon; if so use different collision to sphere stuff */
		side_shift = (rx * s + rz * c) >> W2V_SHIFT;
		if (side_shift > DRAGON_LCOL && side_shift < DRAGON_RCOL)
		{
			shift = (rx * c - rz * s) >> W2V_SHIFT;
			if (shift <= DRAGON_CLOSE && shift >= DRAGON_FAR)
				return;

			angle = laraitem->pos.y_rot - item->pos.y_rot;

			/* Check if in a position to pull dagger from dragon */
			anim = item->anim_number - objects[DRAGON_BACK].anim_index;
			frame = item->frame_number - anims[item->anim_number].frame_base;
			if ((anim == DRAGON_DEAD_ANIM || (anim == DRAGON_DEAD_ANIM+1 && frame <= DRAGON_ALMOST_LIVE)) &&
				(input & IN_ACTION) && item->object_number == DRAGON_BACK && !laraitem->gravity_status &&
				shift <= DRAGON_MID && shift > DRAGON_CLOSE-350 &&	side_shift > -350 && side_shift < 350 &&
				angle > 0x4000-30*ONE_DEGREE && angle < 0x4000+30*ONE_DEGREE)
			{
				/* Jump to animation state in LARA_EXTRA */
				laraitem->anim_number = objects[LARA_EXTRA].anim_index;
				laraitem->frame_number = anims[laraitem->anim_number].frame_base;
				laraitem->current_anim_state = EXTRA_BREATH;
				laraitem->goal_anim_state = EXTRA_PULLDAGGER;

				/* Move to position */
				laraitem->pos.x_pos = item->pos.x_pos;
				laraitem->pos.y_pos = item->pos.y_pos;
				laraitem->pos.z_pos = item->pos.z_pos;
				laraitem->pos.y_rot = item->pos.y_rot;
				laraitem->pos.x_rot = item->pos.x_rot;
				laraitem->pos.z_rot = item->pos.z_rot;
				laraitem->fallspeed = 0;
				laraitem->gravity_status = 0;
				laraitem->speed = 0;

				if (item->room_number != laraitem->room_number)
					ItemNewRoom(lara.item_number, item->room_number);

				/* Jump to that animation */
				AnimateItem(lara_item);
				
				/* Flag that Lara is running animations from another project */
				lara.extra_anim = 1;
				lara.gun_status = LG_HANDSBUSY;
				lara.hit_direction = -1;

				lara.mesh_ptrs[HAND_R] = meshes[objects[LARA_EXTRA].mesh_index + HAND_R];

				/* Do cinematic camera */
				camera.type = CINEMATIC_CAMERA;
				cine_frame = 0;
				S_MemCpy(&cinematic_pos, &laraitem->pos, sizeof(PHD_3DPOS));

				/* Flag dragon is dead forever */
				((CREATURE_INFO *)items[(int)item->data].data)->flags = -1;

				return;
			}

			/* Push away from body part (but not like ItemPushLara does it) */
			if (shift < DRAGON_MID)
				shift = DRAGON_CLOSE - shift;
			else
				shift = DRAGON_FAR - shift;

			laraitem->pos.x_pos += shift * c >> W2V_SHIFT;
			laraitem->pos.z_pos -= shift * s >> W2V_SHIFT;

			return;
		}
	}

	ItemPushLara(item, laraitem, coll, 1, 0);
}


void DragonBones(sint16 item_number)
{
	/* Create the bones of the dragon */
	sint16 bone_back, bone_front;
	ITEM_INFO *front, *back, *item;

	bone_front = CreateItem();
	bone_back = CreateItem();

	if (bone_back != NO_ITEM && bone_front != NO_ITEM)
	{
		item = &items[item_number];

		back = &items[bone_back];
		back->object_number = DEAD_DRAGON_BACK;
		back->pos.x_pos = item->pos.x_pos;
		back->pos.y_pos = item->pos.y_pos;
		back->pos.z_pos = item->pos.z_pos;
		back->pos.x_rot = back->pos.z_rot = 0;
		back->pos.y_rot = item->pos.y_rot;
		back->room_number = item->room_number;
		back->shade = -1;

		InitialiseItem(bone_back);
		
		front = &items[bone_front];
		front->object_number = DEAD_DRAGON_FRONT;
		front->pos.x_pos = item->pos.x_pos;
		front->pos.y_pos = item->pos.y_pos;
		front->pos.z_pos = item->pos.z_pos;
		front->pos.x_rot = front->pos.z_rot = 0;
		front->pos.y_rot = item->pos.y_rot;
		front->room_number = item->room_number;
		front->shade = -1;

		InitialiseItem(bone_front);

		front->mesh_bits = 0xff3fffff;
	}
	// else, rather sad effect
}


void DragonControl(sint16 back_number)
{
	ITEM_INFO *item, *back;
	CREATURE_INFO *dragon;
	sint16 angle, head, item_number;
	AI_INFO info;
	int ahead;

	back = &items[back_number];
	if (back->object_number == DRAGON_FRONT) // called by front of dragon so front is targetable
		return;

	item_number = (int)back->data;
	if (!CreatureActive(item_number))
		return;

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

	if (item->hit_points <= 0)
	{
		if (item->current_anim_state != DRAGON_DEATH)
		{
			item->anim_number = objects[DRAGON_FRONT].anim_index + DRAGON_DIE_ANIM;
			item->frame_number = anims[item->anim_number].frame_base;
			item->current_anim_state = item->goal_anim_state = DRAGON_DEATH;
			dragon->flags = 0;
		}
		else if (dragon->flags >= 0)
		{
			CreateBartoliLight(item_number);
			dragon->flags++;
			if (dragon->flags == DRAGON_LIVE_TIME) // initiate stand up anim (still can be killed)
				item->goal_anim_state = DRAGON_STOP;
			if (dragon->flags >= DRAGON_LIVE_TIME + DRAGON_ALMOST_LIVE) // too late! dragon is up
				item->hit_points = objects[DRAGON_FRONT].hit_points>>1; // half as many from now on
		}
		else
		{
			// dragon has truly popped his clogs
			if (dragon->flags > -20)
				AddDynamicLight(item->pos.x_pos, item->pos.y_pos, item->pos.z_pos, 
					(GetRandomDraw()*4>>15)+12+dragon->flags/2, (GetRandomDraw()*4>>15)+10+dragon->flags/2);

			if (dragon->flags == -100)
				DragonBones(item_number);
			else if (dragon->flags == -200)
			{
				// all over
				DisableBaddieAI(item_number);
				KillItem(back_number);
				back->status = DEACTIVATED;
				KillItem(item_number);
				item->status = DEACTIVATED;
				return;
			}
			else if (dragon->flags < -100)
			{
				// fade away
				item->pos.y_pos += 10;
				back->pos.y_pos += 10;
			}

			dragon->flags--;
			return; 
		}
	}
	else
	{
		CreatureAIInfo(item, &info);

		CreatureMood(item, &info, VIOLENT);

		angle = CreatureTurn(item, DRAGON_WALK_TURN);

		ahead = (info.ahead && info.distance > DRAGON_CLOSE_RANGE && info.distance < DRAGON_STOP_RANGE);

		/* Hurts just to touch dragon */
		if (item->touch_bits)
		{
			lara_item->hit_status = 1;
			lara_item->hit_points -= DRAGON_TOUCH_DAMAGE;
		}

		switch (item->current_anim_state)
		{
		case DRAGON_STOP:
			item->pos.y_rot -= angle;

			if (!ahead)
			{
				if (info.distance > DRAGON_STOP_RANGE || !info.ahead)
					item->goal_anim_state = DRAGON_WALK;
				else if (info.ahead && info.distance < DRAGON_CLOSE_RANGE && !dragon->flags)
				{
					dragon->flags = 1; // if not reset by swipe, then didn't hit Lara, so move next time
					if (info.angle < 0)
						item->goal_anim_state = DRAGON_SWIPELEFT;
					else
						item->goal_anim_state = DRAGON_SWIPERIGHT;
				}
				else if (info.angle < 0)
					item->goal_anim_state = DRAGON_TURNLEFT;
				else
					item->goal_anim_state = DRAGON_TURNRIGHT;
			}
			else
				item->goal_anim_state = DRAGON_AIM1;
			break;

		case DRAGON_SWIPELEFT:
			if (item->touch_bits & DRAGON_TOUCH_L)
			{
				lara_item->hit_status = 1;
				lara_item->hit_points -= DRAGON_SWIPE_DAMAGE;
				dragon->flags = 0;
			}
			break;

		case DRAGON_SWIPERIGHT:
			if (item->touch_bits & DRAGON_TOUCH_R)
			{
				lara_item->hit_status = 1;
				lara_item->hit_points -= DRAGON_SWIPE_DAMAGE;
				dragon->flags = 0;
			}
			break;

		case DRAGON_WALK:
			dragon->flags = 0;

			if (ahead)
				item->goal_anim_state = DRAGON_STOP;
			else if (angle < -DRAGON_NEED_TURN)
			{
				if (info.distance < DRAGON_STOP_RANGE && info.ahead)
					item->goal_anim_state = DRAGON_STOP;
				else
					item->goal_anim_state = DRAGON_LEFT;
			}
			else if (angle > DRAGON_NEED_TURN)
			{
				if (info.distance < DRAGON_STOP_RANGE && info.ahead)
					item->goal_anim_state = DRAGON_STOP;
				else
					item->goal_anim_state = DRAGON_RIGHT;
			}
			break;

		case DRAGON_LEFT:
			if (angle > -DRAGON_NEED_TURN || ahead)
				item->goal_anim_state = DRAGON_WALK;
			break;

		case DRAGON_RIGHT:
			if (angle < DRAGON_NEED_TURN || ahead)
				item->goal_anim_state = DRAGON_WALK;
			break;

		case DRAGON_TURNLEFT:
			dragon->flags = 0;
			item->pos.y_rot += -ONE_DEGREE - angle;
			break;

		case DRAGON_TURNRIGHT:
			dragon->flags = 0;
			item->pos.y_rot += ONE_DEGREE - angle;
			break;

		case DRAGON_AIM1:
			item->pos.y_rot -= angle;
			if (info.ahead)
				head = -info.angle;

			if (ahead)
			{
				dragon->flags = 30;
				item->goal_anim_state = DRAGON_FIRE1;
			}
			else
			{
				dragon->flags = 0;
				item->goal_anim_state = DRAGON_AIM1;
			}
			break;

		case DRAGON_FIRE1:
			item->pos.y_rot -= angle;
			if (info.ahead)
				head = -info.angle;

			SoundEffect(305, &item->pos, 0);

			if (dragon->flags)
			{
				if (info.ahead)
					CreatureEffect(item, &dragon_mouth, DragonFire);
				dragon->flags--;
			}
			else
				item->goal_anim_state = DRAGON_STOP;
			break;
		}
	}

	CreatureHead(item, head);
	CreatureAnimation(item_number, angle, 0);

	/* Set back end to same frame */
	back->current_anim_state = item->current_anim_state;
	back->anim_number = objects[DRAGON_BACK].anim_index + (item->anim_number - objects[DRAGON_FRONT].anim_index);
	back->frame_number = anims[back->anim_number].frame_base + (item->frame_number - anims[item->anim_number].frame_base);
	back->pos.x_pos = item->pos.x_pos;
	back->pos.y_pos = item->pos.y_pos;
	back->pos.z_pos = item->pos.z_pos;
	back->pos.x_rot = item->pos.x_rot;
	back->pos.y_rot = item->pos.y_rot;
	back->pos.z_rot = item->pos.z_rot;
	if (back->room_number != item->room_number)
		ItemNewRoom(back_number, item->room_number);
}


void InitialiseBartoli(sint16 item_number)
{
	ITEM_INFO *item, *back, *front;
	sint16 back_item, front_item;

	item = &items[item_number];
	item->pos.x_pos -= STEP_L*2;
	item->pos.z_pos -= STEP_L*2;

	/* Create dragon (but keep INVISIBLE for time being) */
	back_item = CreateItem();
	front_item = CreateItem();
	if (back_item != NO_ITEM && front_item != NO_ITEM)
	{
		back = &items[back_item];
		back->object_number = DRAGON_BACK;
		back->pos.x_pos = item->pos.x_pos;
		back->pos.y_pos = item->pos.y_pos;
		back->pos.z_pos = item->pos.z_pos;
		back->pos.y_rot = item->pos.y_rot;
		back->room_number = item->room_number;
		back->flags = NOT_VISIBLE;
		back->shade = -1;

		InitialiseItem(back_item);
		back->mesh_bits = 0x1fffff; // turn off spine
		
		item->data = (void *)back_item; // Bartoli points at back of dragon

		front = &items[front_item];
		front->object_number = DRAGON_FRONT;
		front->pos.x_pos = item->pos.x_pos;
		front->pos.y_pos = item->pos.y_pos;
		front->pos.z_pos = item->pos.z_pos;
		front->pos.y_rot = item->pos.y_rot;
		front->room_number = item->room_number;
		front->flags = NOT_VISIBLE;
		front->shade = -1;

		InitialiseItem(front_item);
		
		back->data = (void *)front_item; // back of dragon points at front

		level_items += 2;
	}
	else
		S_ExitSystem("FATAL: Unable to create dragon");
}


#define BOOM_TIME (130)
#define BARTOLI_RANGE (WALL_L*5)

void BartoliControl(sint16 item_number)
{
	ITEM_INFO *item, *back, *front;
	int front_item, back_item;

	item = &items[item_number];

	if (item->timer)
	{
		item->timer++;

		if (!(item->timer & 7))
			camera.bounce = item->timer;

		CreateBartoliLight(item_number);

		AnimateItem(item);

		if (item->timer == BOOM_TIME || item->timer == BOOM_TIME+10 || item->timer == BOOM_TIME+20)
		{
			front_item = CreateItem();
			if (front_item != NO_ITEM)
			{
				front = &items[front_item];
				if (item->timer == BOOM_TIME)
					front->object_number = SPHERE_OF_DOOM;
				else if (item->timer == BOOM_TIME+10)
					front->object_number = SPHERE_OF_DOOM2;
				else
					front->object_number = SPHERE_OF_DOOM3;
				front->pos.x_pos = item->pos.x_pos;
				front->pos.y_pos = item->pos.y_pos+STEP_L;
				front->pos.z_pos = item->pos.z_pos;
				front->room_number = item->room_number;
				front->shade = -1;
				InitialiseItem((sint16)front_item);
				AddActiveItem((sint16)front_item);
				front->status = ACTIVE;
			}
		}
		else if (item->timer >= 30*5)
		{
			/* Convert Bartoli into a dragon */
			back_item = (int)item->data;
			back = &items[back_item];

			front_item = (int)back->data;
			front = &items[front_item];

			front->touch_bits = back->touch_bits = 0;
			EnableBaddieAI((sint16)front_item, 1);
			AddActiveItem((sint16)front_item); // needed so dragon targeted, but no actual control routine

			AddActiveItem((sint16)back_item);
			back->status = ACTIVE;

			KillItem(item_number);
		}
	}
	else if (ABS(lara_item->pos.x_pos - item->pos.x_pos) < BARTOLI_RANGE && ABS(lara_item->pos.z_pos - item->pos.z_pos) < BARTOLI_RANGE)
		item->timer = 1;
}


/****************** BIG BAD TREX ************************/

void DinoControl(sint16 item_number)
{
	ITEM_INFO *item;
	CREATURE_INFO *dino;
	sint16 head, angle;
	AI_INFO info;

	if (!CreatureActive(item_number))
		return;

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

	/* Has dino been killed? */
	if (item->hit_points <= 0)
	{
		if (item->current_anim_state == DINO_STOP)
			item->goal_anim_state = DINO_DEATH;
		else
			item->goal_anim_state = DINO_STOP;
	}
	else
	{
		CreatureAIInfo(item, &info);

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

		CreatureMood(item, &info, VIOLENT);

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

		/* An enemy touching the dino takes damage just from that */
		if (item->touch_bits)
			lara_item->hit_points -= (item->current_anim_state == DINO_RUN)? DINO_TRAMPLE_DAMAGE : DINO_TOUCH_DAMAGE;

		/* Flag if enemy behind and facing us - stop and turn else they can chase in rings */
		dino->flags = (dino->mood != ESCAPE_MOOD && !info.ahead &&
						 info.enemy_facing > -FRONT_ARC && info.enemy_facing < FRONT_ARC);

		/* Flag if enemy is close ahead - walk to bite range */
		if (!dino->flags && info.distance > DINO_BITE_RANGE && info.distance < DINO_ATTACK_RANGE && info.bite)
			dino->flags = 1;

		/* Decide on dino's next move */
	 	switch (item->current_anim_state)
		{
			case DINO_STOP:
				if (item->required_anim_state)
					item->goal_anim_state = item->required_anim_state;
				else if (info.distance < DINO_BITE_RANGE && info.bite)
					item->goal_anim_state = DINO_ATTACK2;
				else if (dino->mood == BORED_MOOD || dino->flags)
					item->goal_anim_state = DINO_WALK;
				else
					item->goal_anim_state = DINO_RUN;
				break;

			case DINO_WALK:
				dino->maximum_turn = DINO_WALK_TURN;

				if (dino->mood != BORED_MOOD && !dino->flags)
					item->goal_anim_state = DINO_STOP;
				else if (info.ahead && GetRandomControl() < DINO_ROAR_CHANCE)
				{
					item->required_anim_state = DINO_ROAR;
					item->goal_anim_state = DINO_STOP;
				}
				break;

			case DINO_RUN:
				dino->maximum_turn = DINO_RUN_TURN;

				if (info.distance < DINO_RUN_RANGE && info.bite)
					item->goal_anim_state = DINO_STOP;
				else if (dino->flags)
					item->goal_anim_state = DINO_STOP;
				else if (dino->mood != ESCAPE_MOOD && info.ahead && GetRandomControl() < DINO_ROAR_CHANCE)
				{
					item->required_anim_state = DINO_ROAR;
					item->goal_anim_state = DINO_STOP;
				}
				else if (dino->mood == BORED_MOOD)
					item->goal_anim_state = DINO_STOP;
				break;

			case DINO_ATTACK2:
				if (item->touch_bits & DINO_TOUCH)
				{
					lara_item->hit_points -= DINO_BITE_DAMAGE;
					lara_item->hit_status = 1;

					/* Bye, bye Lara */
					CreatureKill(item, DINO_KILL_ANIM, DINO_KILL, EXTRA_DINOKILL);
					return;
				}

				/* Make dino walk if fail to kill Lara (avoids repeat miss attack) */
				item->required_anim_state = DINO_WALK;
				break;
		}
	}

	/* Split dino's head movement between head and neck */
	CreatureHead(item, (sint16)(head>>1));
	dino->neck_rotation = dino->head_rotation;

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