#include "CS_Boss_Tala.h"
#include "CS_PeSmoke.h"
#include "CS_Boss_Tala_AtkZone.h"
#include "CS_Boss_TalaBlade.h"
#include "CS_Boss_GroupHpBar.h"
CS_Boss_Tala::CS_Boss_Tala()
{
	type = 2;
	ani.png = L"CS_CaveStoryMod";
	//启用碰撞
	cbRect.enableCbRect = true;
	cbRect.enableSoild = true;
	
	hp_max = hp = 200;
	drawBeforeOtherEntity = true;
	damage_reset_counter = 60;
	attackState_reset_counter_max = 60;
	ani.hideLayerList.insert(0);
	ani.hideLayerList.insert(1);
	ani.hideLayerList.insert(2);
	ani.hideLayerList.insert(3);
}

void CS_Boss_Tala::Init(std::weak_ptr<Entity> self)
{
	if (gameFunc->pGameOption_difficulty)
		if (*gameFunc->pGameOption_difficulty == 0)
			bNormalMode = true;
	stateResist.Init(shared_from_this());
	auto watkZoneEx = std::make_shared<CS_Boss_Tala_AtkZone>(shared_from_this());
	atkZoneEx = watkZoneEx;
	gameFunc->SetEntity(shared_from_this(), watkZoneEx);
	Entity::Init(self);
}

void CS_Boss_Tala::Step()
{
	if (bFindGroupHpBar)
	{
		bFindGroupHpBar = false;
		//寻找公用血条
		if (gameFunc->GetLoadedEntity)
		{
			auto& allRes = *gameFunc->GetLoadedEntity(gameFunc->entityRes);
			for (auto& p : allRes)
			{
				if (p.first->layerType == 0)
				{
					for (auto& e : p.second.Ls)
					{
						if (e->el.name == CS_BOSS_GROUPHPBAR_CREATENAME)
						{
							groupHpBar = e;
							break;
						}
					}
					break;
				}
			}
		}
	}
	switch (stateID)
	{
	case 0:
		//设置面对方向
		if (gameFunc->GetPlayerDistance)
		{
			auto wplayer = gameFunc->GetPlayerDistance(gameFunc->game, x, y).lock();
			if (wplayer)
				lr = x > wplayer->x ? 0 : 1;
		}
		walk_counter = Random(60, 120);
		stateID = 1;
		break;
	case 1://移动
		if (walk_counter > 0)
		{
			walk_counter--;
			if (lr == 0)
				vx -= 0x20 / ts;
			else
				vx += 0x20 / ts;
			ani.sprite_index = lr == 0 ? L"mc_soapwalker_move_l" : L"mc_soapwalker_move_r";
		}
		else
		{
			if (gameFunc->GetPlayerDistance)
			{
				auto wplayer = gameFunc->GetPlayerDistance(gameFunc->game, x, y).lock();
				if (wplayer)
					lr = x > wplayer->x ? 0 : 1;
			}
			ani.sprite_index = lr == 0 ? L"mc_soapwalker_jump_l" : L"mc_soapwalker_jump_r";
			vy = -Random(0x400, 0x800) / ts;
			float vxSpeed = Random(0x400, 0x800) / ts;
			vx = lr == 0 ? -vxSpeed : vxSpeed;
			stateID = 2;
		}	
		break;
	case 2://跳跃
		if (cbRect.cbBottom)
		{
			stateID = 0;
		}
		break;
	case 3://被击败
		ani.sprite_index = lr == 0 ? L"mc_soapwalker_defeated_l" : L"mc_soapwalker_defeated_r";
		stateResist.State();
		break;
	}
	//限制速度
	if (vx < -0x600 / ts)
		vx = -0x600 / ts;
	if (vx > 0x400 / ts)
		vx = 0x400 / ts;
	vy += 0x20 / ts;
	if (vy > 0x5FF / ts)
		vy = 0x5FF / ts;
	//清除最后一次碰撞结果
	Entity::ClearCollisionResult();
	//执行运动
	Entity::Step();
	//设置墙体碰撞矩形
	SetCbRect_Collision();
	//执行碰撞
	Entity::Collision();
	//维持在斜坡上
	Entity::KeepOnSlopes();
	//设置实体碰撞矩形
	SetCbRect_Entity();
	//绑定攻击区域
	auto watkZoneEx = atkZoneEx.lock();
	if (watkZoneEx)
	{
		watkZoneEx->x = x;
		watkZoneEx->y = y;
		watkZoneEx->last_x = last_x;
		watkZoneEx->last_y = last_y;
	}
}

void CS_Boss_Tala::SetState(int stateID, int lr)
{
	this->stateID = stateID;
	this->lr = lr;
	ani.sprite_index = lr == 0 ? L"mc_soapwalker_stand_l" : L"mc_soapwalker_stand_r";
}

void CS_Boss_Tala::Attack(std::weak_ptr<Entity> dst, int* outDamage, float* outAngle, bool* outTakedown, int* outElemType, float* outShockForce, float* outHeavy)
{
	if (hp <= 0)
		return;
	*outDamage = 5;
	auto wdst = dst.lock();
	if (wdst)
	{
		if (wdst->lr == 0)
		{
			*outAngle = 315;
		}
		else
		{
			*outAngle = 225;
		}
	}
	*outTakedown = true;
	*outElemType = 0;
	*outShockForce = 0x200 / ts;
	*outHeavy = 2;
}

bool CS_Boss_Tala::Hurt(std::weak_ptr<Entity> src, int getDamage, float angle, bool bTakedown, int elemType, float shockForce, float heavy, int* outRealDamage)
{
	if (getDamage == 0)
		return false;
	if (hp == 0)
		return false;
	*outRealDamage = getDamage;
	shock_counter = 30;
	hp -= getDamage;
	//在groupHpBar记录伤害
	auto wgroupHpBar = groupHpBar.lock();
	if (wgroupHpBar)
	{
		int out;
		int dmg = getDamage;
		if (hp < 0)
			dmg += hp;
		wgroupHpBar->Hurt(src, dmg, angle, bTakedown, elemType, shockForce, heavy, &out);
	}
	if (hp > 0)
	{
		gameFunc->PlaySound(L"CS_051_enemy_hurt");
		//受伤时朝目标发射抛射物
		if (!bNormalMode)
		{
			float srcX, srcY, dirX, dirY;
			srcX = x;
			srcY = y - 40;
			auto wsrc = src.lock();
			if (wsrc)
			{
				auto dir = XMVector2Normalize(XMVectorSet(wsrc->x - srcX, wsrc->y - srcY, 0, 0));
				dirX = XMVectorGetX(dir);
				dirY = XMVectorGetY(dir);
				auto srcParent = wsrc->attackParent.lock();
				if (srcParent)
				{
					dir = XMVector2Normalize(XMVectorSet(srcParent->x - srcX, srcParent->y - srcY, 0, 0));
					dirX = XMVectorGetX(dir);
					dirY = XMVectorGetY(dir);
				}
				SetCS_Boss_TalaBlade(shared_from_this(), srcX, srcY, dirX, dirY);
			}
		}
	}
	if (hp <= 0)
	{
		gameFunc->PlaySound(L"CS_071_little_crash");
		//创建云团
		SetCS_PeSmokeMedium(shared_from_this(), x, y);
		hp = 0;
		stateID = 3;
	}
	//显示伤害值
	if (gameFunc->dmgNum)
		gameFunc->SetDmgNum(gameFunc->dmgNum, getDamage, x, y - 16, 0, shared_from_this());
	return true;
}

void CS_Boss_Tala::Destroy()
{
	auto we = atkZoneEx.lock();
	if (we)
		we->Destroy();
	Entity::Destroy();
}

void CS_Boss_Tala::SetCbRect_Entity()
{
	float dy = -40;
	//设置实体碰撞框（攻击脑袋才会受伤）
	cbRect.left = cbRect.right = 12;
	cbRect.top = 8 - dy;
	cbRect.bottom = 8 + dy;
	
}

void CS_Boss_Tala::SetCbRect_Collision()
{
	//设置地形碰撞框
	cbRect.left = cbRect.right = 12;
	cbRect.top = 8;
	cbRect.bottom = 8;
}

std::shared_ptr<Entity> CreateCS_Boss_Tala()
{
	return std::make_shared<CS_Boss_Tala>();
}
