#include <StdAfx.h>
#include "mafia2.h"
#include <trng_core.h>
#include "utility.h"
#include "Class/TRClass.h"
#include "phd_math.h"

extern TYPE_CreatureCollision CreatureCollision;
extern TYPE_InitialiseCreature InitialiseCreature;
extern TYPE_CreatureActive CreatureActive;
extern TYPE2_GetFloor GetFloor_2;
extern TYPE_GetHeight GetHeight;
extern TYPE_CreatureAIInfo CreatureAIInfo;
extern TYPE_GetAITarget GetAITarget;
extern TYPE_phd_atan phd_atan;
extern TYPE_GetCreatureMood GetCreatureMood;
extern TYPE_CreatureMood CreatureMood;
extern TYPE_CreatureTurn CreatureTurn;
extern TYPE_TargetVisible TargetVisible;
extern TYPE_AlertAllGuards AlertAllGuards;
extern TYPE_AIGuard AIGuard;
extern TYPE_Targetable Targetable;
extern TYPE_ShotLara ShotLara;
extern TYPE2_GetJointAbsPosition GetJointAbsPosition_2;
extern TYPE_TriggerDynamic TriggerDynamic;
extern TYPE_CreatureJoint CreatureJoint;
extern TYPE_CreatureAnimation CreatureAnimation;
extern TYPE_CreatureVault CreatureVault;

static BITE_INFO mafia_gun_left = EnemyBite[TROFF_MAFIA_LEFT];
static BITE_INFO mafia_gun_right = EnemyBite[TROFF_MAFIA_RIGHT];

void InitTR5_Mafia(short item_number)
{
	ITEM_INFO* item;

	item = &Ptr_VetItems[item_number];
	InitialiseCreature(item_number);
	item->anim_number = Ptr_VetObjects[item->object_number].anim_index;
	item->frame_number = Ptr_VetAnimations[item->anim_number].frame_base;
	item->goal_anim_state = 1;
	item->current_anim_state = 1;
	item->meshswap_meshbits = 9216;
}

void CtrlTR5_Mafia(short item_number)
{
	ITEM_INFO* item;
	ITEM_INFO* enemy_bak;
	CREATURE_INFO* mafia;
	FLOOR_INFO* floor;
	StrMovePosition pos;
	AI_INFO info;
	AI_INFO lara_info;
	AI_INFO laraAI;
	long Xoffset, Zoffset, x, y, z, nearheight, midheight, farheight, lara_dx, lara_dz;
	short angle, head, torso_x, torso_y, room_number, jump_ahead, long_jump_ahead, y_rot, dmg1;

	if (!CreatureActive(item_number))
		return;

	item = &Ptr_VetItems[item_number];
	mafia = (CREATURE_INFO*)item->data;
	angle = 0;
	head = 0;
	torso_x = 0;
	torso_y = 0;
    dmg1 = Utils.getObjectAttribute(tsu_slots[item->object_number], ATT_DMG1);
	room_number = item->room_number;
	y = item->pos.y_pos;
	Xoffset = 870 * phd_sin_tr2(item->pos.y_rot) >> 14;
	Zoffset = 870 * phd_cos_tr2(item->pos.y_rot) >> 14;
	x = item->pos.x_pos + Xoffset;
	z = item->pos.z_pos + Zoffset;
	floor = GetFloor_2(x, y, z, &room_number);
	nearheight = GetHeight(floor, x, y, z);
	room_number = item->room_number;
	x += Xoffset;
	z += Zoffset;
	floor = GetFloor_2(x, y, z, &room_number);
	midheight = GetHeight(floor, x, y, z);
	room_number = item->room_number;
	x += Xoffset;
	z += Zoffset;
	floor = GetFloor_2(x, y, z, &room_number);
	farheight = GetHeight(floor, x, y, z);

	if (item->box_number == LaraItem->box_number || y >= nearheight - 384 || y >= midheight + 256 || y <= midheight - 256)
		jump_ahead = 0;
	else
		jump_ahead = 1;

	if (item->box_number == LaraItem->box_number || y >= nearheight - 384 || y >= midheight - 384 || y >= farheight + 256 || y <= farheight - 256)
		long_jump_ahead = 0;
	else
		long_jump_ahead = 1;

	if (item->ai_bits)
		GetAITarget(mafia);
	else
		mafia->enemy = LaraItem;

	CreatureAIInfo(item, &info);

	if (item->hit_points > 0)
	{
		lara_info.angle = info.angle;
		lara_info.distance = info.distance;

		if (mafia->enemy == LaraItem)
		{
			laraAI.angle = info.angle;
			laraAI.distance = info.distance;
		}
		else
		{
			lara_dx = LaraItem->pos.x_pos - item->pos.x_pos;
			lara_dz = LaraItem->pos.z_pos - item->pos.z_pos;
			laraAI.angle = (short)(phd_atan(lara_dz, lara_dx) - item->pos.y_rot);
			laraAI.distance = ABS(lara_dx) <= 32000 && ABS(lara_dz) <= 32000 ? SQUARE(lara_dz) + SQUARE(lara_dx) : 0x7FFFFFFF;
		}

		GetCreatureMood(item, &info, VIOLENT);
		CreatureMood(item, &info, VIOLENT);
		angle = CreatureTurn(item, mafia->maximum_turn);
		enemy_bak = mafia->enemy;
		mafia->enemy = LaraItem;

		if (laraAI.distance < 0x400000 && LaraItem->speed > 20 || item->hit_status || TargetVisible(item, &laraAI))
			AlertAllGuards(item_number);

		mafia->enemy = enemy_bak;

		switch (item->current_anim_state)
		{
		case 1:
			head = lara_info.angle;
			mafia->flags = 0;
			mafia->LOT.is_jumping = 0;
			mafia->maximum_turn = 0;

			if (info.ahead && !(item->ai_bits & SAI_GUARD))
			{
				torso_y = info.angle >> 1;
				torso_x = info.x_angle;
			}

			if (item->ai_bits & SAI_GUARD)
			{
				head = AIGuard(mafia);
				break;
			}

			if (lara_info.angle <= 20480 && lara_info.angle >= -20480)
			{
				if (item->meshswap_meshbits == 9216)
				{
					item->goal_anim_state = 37;
					break;
				}
			}
			else if (item->meshswap_meshbits == 9216)
			{
				item->goal_anim_state = 2;
				break;
			}

			if (Targetable(item, &info))
			{
				if (info.distance >= 0x1000000 && info.src_zone == info.target_zone)
					item->goal_anim_state = 5;
				else
					item->goal_anim_state = 4;
			}
			else if (item->ai_bits & SAI_PATROL1)
				item->goal_anim_state = 5;
			else
			{
				if (jump_ahead || long_jump_ahead)
				{
					mafia->maximum_turn = 0;
					item->anim_number = Ptr_VetObjects[item->object_number].anim_index + 41;
					item->frame_number = Ptr_VetAnimations[item->anim_number].frame_base;
					item->current_anim_state = 26;
					
					if (long_jump_ahead)
						item->goal_anim_state = 28;
					else
						item->goal_anim_state = 27;

					mafia->LOT.is_jumping = 1;

					break;
				}

				if (mafia->mood != MOOD_BORED)
				{
					if (info.distance >= 0x900000)
						item->goal_anim_state = 7;
					else
						item->goal_anim_state = 5;
				}
				else
					item->goal_anim_state = 1;
			}

			break;

		case 2:
		case 32:
			mafia->maximum_turn = 0;

			if (info.angle >= 0)
				item->pos.y_rot -= 364;
			else
				item->pos.y_rot += 364;

			if (item->frame_number == Ptr_VetAnimations[item->anim_number].frame_base + 16 && item->meshswap_meshbits == 9216)
				item->meshswap_meshbits = 128;
			else if (item->frame_number == Ptr_VetAnimations[item->anim_number].frame_end)
				item->pos.y_rot += 0x8000;

			break;

		case 3:
			torso_y = lara_info.angle >> 1;
			head = lara_info.angle >> 1;

			if (info.ahead)
				torso_x = info.x_angle;

			mafia->maximum_turn = 0;

			if (ABS(info.angle) >= 364)
			{
				if (info.angle >= 0)
					item->pos.y_rot += 364;
				else
					item->pos.y_rot -= 364;
			}
			else
				item->pos.y_rot += info.angle;

			if (!mafia->flags)
			{
				ShotLara(item, &info, &mafia_gun_left, head, DOUBLE_VALUE_ITEM(dmg1, 17));
				ShotLara(item, &info, &mafia_gun_right, head, DOUBLE_VALUE_ITEM(dmg1, 17));
				mafia->flags = 1;
				item->fired_weapon = 4;
				item->reserved_1 = 3;
			}

			break;

		case 4:
			torso_y = lara_info.angle >> 1;
			head = lara_info.angle >> 1;
			mafia->flags = 0;
			mafia->maximum_turn = 0;

			if (info.ahead)
				torso_x = info.x_angle;

			if (ABS(info.angle) >= 364)
			{
				if (info.angle >= 0)
					item->pos.y_rot += 364;
				else
					item->pos.y_rot -= 364;
			}
			else
				item->pos.y_rot += info.angle;

			if (Targetable(item, &info))
				item->goal_anim_state = 3;
			else if (lara_info.angle > 20480 || lara_info.angle < -20480)
				item->goal_anim_state = 32;
			else
				item->goal_anim_state = 1;

			break;

		case 5:
			mafia->LOT.is_jumping = 0;
			mafia->maximum_turn = 910;

			if (!Targetable(item, &info) || info.distance >= 0x1000000 && info.src_zone == info.target_zone)
			{
				if (jump_ahead || long_jump_ahead)
				{
					mafia->maximum_turn = 0;
					item->anim_number = Ptr_VetObjects[item->object_number].anim_index + 41;
					item->frame_number = Ptr_VetAnimations[item->anim_number].frame_base;
					item->current_anim_state = 26;

					if (long_jump_ahead)
						item->goal_anim_state = 28;
					else
						item->goal_anim_state = 27;

					mafia->LOT.is_jumping = 1;

					break;
				}

				if (info.distance >= 0x100000)
				{
					if (info.distance > 0x900000)
						item->goal_anim_state = 7;
				}
				else
					item->goal_anim_state = 1;
			}
			else
				item->goal_anim_state = 4;

			break;

		case 7:
			mafia->LOT.is_jumping = 0;
			mafia->maximum_turn = 1820;

			if (!Targetable(item, &info) || info.distance >= 0x1000000 && info.src_zone == info.target_zone)
			{
				if (jump_ahead || long_jump_ahead)
				{
					mafia->maximum_turn = 0;
					item->anim_number = Ptr_VetObjects[item->object_number].anim_index + 50;
					item->frame_number = Ptr_VetAnimations[item->anim_number].frame_base;
					item->current_anim_state = 26;

					if (long_jump_ahead)
						item->goal_anim_state = 28;
					else
						item->goal_anim_state = 27;

					mafia->LOT.is_jumping = 1;
				}
				else if (info.distance < 0x900000)
					item->goal_anim_state = 5;
			}
			else
				item->goal_anim_state = 4;

			break;

		case 37:
			mafia->maximum_turn = 0;

			if (info.angle >= 0)
				item->pos.y_rot += 364;
			else
				item->pos.y_rot -= 364;

			if (item->frame_number == Ptr_VetAnimations[item->anim_number].frame_base + 16 && item->meshswap_meshbits == 9216)
				item->meshswap_meshbits = 128;

			break;
		}
	}
	else
	{
		if (item->current_anim_state != 8 && item->current_anim_state != 6)
		{
			if (info.angle >= 12288 || info.angle <= -12288)
			{
				item->current_anim_state = 8;
				item->anim_number = Ptr_VetObjects[item->object_number].anim_index + 16;
				y_rot = info.angle + 32768;
			}
			else
			{
				item->current_anim_state = 6;
				item->anim_number = Ptr_VetObjects[item->object_number].anim_index + 11;
				y_rot = info.angle;
			}

			item->pos.y_rot += y_rot;
			item->frame_number = Ptr_VetAnimations[item->anim_number].frame_base;
		}
	}

	if (item->fired_weapon)
	{
		pos.RelX = mafia_gun_left.x;
		pos.RelY = mafia_gun_left.y;
		pos.RelZ = mafia_gun_left.z;
		GetJointAbsPosition_2(item, &pos, mafia_gun_left.mesh_num);
		TriggerDynamic(pos.RelX, pos.RelY, pos.RelZ, (item->fired_weapon << 1) + 10, 192, 128, 32);
		pos.RelX = mafia_gun_right.x;
		pos.RelY = mafia_gun_right.y;
		pos.RelZ = mafia_gun_right.z;
		GetJointAbsPosition_2(item, &pos, mafia_gun_right.mesh_num);
		TriggerDynamic(pos.RelX, pos.RelY, pos.RelZ, (item->fired_weapon << 1) + 10, 192, 128, 32);
	}

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

	if (item->current_anim_state >= 20 || item->current_anim_state == 6 || item->current_anim_state == 8)
		CreatureAnimation(item_number, angle, 0);
	else
	{
		switch (CreatureVault(item_number, angle, 0, 256))
		{
		case -4:
			mafia->maximum_turn = 0;
			item->anim_number = Ptr_VetObjects[item->object_number].anim_index + 38;
			item->frame_number = Ptr_VetAnimations[item->anim_number].frame_base;
			item->current_anim_state = 23;
			break;

		case -3:
			mafia->maximum_turn = 0;
			item->anim_number = Ptr_VetObjects[item->object_number].anim_index + 39;
			item->frame_number = Ptr_VetAnimations[item->anim_number].frame_base;
			item->current_anim_state = 24;
			break;

		case -2:
			mafia->maximum_turn = 0;
			item->anim_number = Ptr_VetObjects[item->object_number].anim_index + 40;
			item->frame_number = Ptr_VetAnimations[item->anim_number].frame_base;
			item->current_anim_state = 25;
			break;

		case 2:
			mafia->maximum_turn = 0;
			item->anim_number = Ptr_VetObjects[item->object_number].anim_index + 35;
			item->frame_number = Ptr_VetAnimations[item->anim_number].frame_base;
			item->current_anim_state = 20;
			break;

		case 3:
			mafia->maximum_turn = 0;
			item->anim_number = Ptr_VetObjects[item->object_number].anim_index + 36;
			item->frame_number = Ptr_VetAnimations[item->anim_number].frame_base;
			item->current_anim_state = 21;
			break;

		case 4:
			mafia->maximum_turn = 0;
			item->anim_number = Ptr_VetObjects[item->object_number].anim_index + 37;
			item->frame_number = Ptr_VetAnimations[item->anim_number].frame_base;
			item->current_anim_state = 22;
			break;
		}
	}
}

void InitialiseTR5_Mafia2()
{
    for (int index = 0; index < SLOTS_NUMBER; ++index)
    {
        tomb[TR5_ARMED_BADDY_TWO1 + index].set_name("Mafia 2");
        tomb[TR5_ARMED_BADDY_TWO1 + index].initialise(TR5_ARMED_BADDY_TWO1 + index, FUNCTION_ZONE_BEFORE | FUNCTION_SHADOW, QUERY_GUNFLASH | QUERY_HEADSHOT | QUERY_PATROL | QUERY_PATROL2 | QUERY_VAULT);
        tomb[TR5_ARMED_BADDY_TWO1 + index].set_shadow_size(128);
        tomb[TR5_ARMED_BADDY_TWO1 + index].set_func_initialise(InitTR5_Mafia);
        tomb[TR5_ARMED_BADDY_TWO1 + index].set_func_collide(CreatureCollision);
        tomb[TR5_ARMED_BADDY_TWO1 + index].set_func_control(CtrlTR5_Mafia);
        tomb[TR5_ARMED_BADDY_TWO1 + index].set_bitoffset(TROFF_MAFIA_LEFT | DOUBLE_OFFSET_MUZZLEFLASH);
        tomb[TR5_ARMED_BADDY_TWO1 + index].set_func_draw(DrawAnimatingItemCustom, NULL);
        tomb[TR5_ARMED_BADDY_TWO1 + index].set_health(26);
        tomb[TR5_ARMED_BADDY_TWO1 + index].set_radius_and_pivot(102, 50);
        tomb[TR5_ARMED_BADDY_TWO1 + index].set_hit_effect(HIT_BLOOD);
        tomb[TR5_ARMED_BADDY_TWO1 + index].set_creature(TRUE);
        tomb[TR5_ARMED_BADDY_TWO1 + index].set_rotation_meshtree(6, ROT_X | ROT_Y);
        tomb[TR5_ARMED_BADDY_TWO1 + index].set_rotation_meshtree(13, ROT_X | ROT_Y);
        tomb[TR5_ARMED_BADDY_TWO1 + index].set_explodable_meshbits(0x4000);
        tomb[TR5_ARMED_BADDY_TWO1 + index].set_meshswap(7);
        tomb[TR5_ARMED_BADDY_TWO1 + index].set_meshswap(10);
        tomb[TR5_ARMED_BADDY_TWO1 + index].set_meshswap(13);
        tomb[TR5_ARMED_BADDY_TWO1 + index].set_save(TRUE, TRUE, TRUE, TRUE, TRUE);
    }
}
