#include "CS_Boss_Ironhead.h"
#include "CS_PeSmoke.h"
#include "CS_Enemy_MannanBlade.h"
#include "CS_FallRock_Locator.h"
#include "PeLightTail.h"
CS_Boss_Ironhead::CS_Boss_Ironhead()
{
	type = 2;
	ani.png = L"CS_CaveStoryMod";
	cbRect.enableCbRect = true;
	cbRect.enableSoild = true;
	//设置碰撞框
	hp = hp_max = 300;
	cbRect.left = cbRect.right = 28;
	cbRect.top = 11;
	cbRect.bottom = 12;
	damage_reset_counter = 60;
	attackState_reset_counter_max = 60;
}

void CS_Boss_Ironhead::Init(std::weak_ptr<Entity> self)
{
	if (gameFunc->pGameOption_difficulty)
		if (*gameFunc->pGameOption_difficulty == 0)
			bNormalMode = true;
	ActionEntity::Init(self);
}

void CS_Boss_Ironhead::Step()
{
	if (hp <= 0)
	{
		vx = 0;
		vy = 0;
		//清除最后一次碰撞结果
		Entity::ClearCollisionResult();
		//执行运动
		Entity::Step();
		//执行碰撞
		Entity::Collision();
		ani.sprite_index = lr == 0 ? L"mc_ironhead_l" : L"mc_ironhead_r";
		return;
	}
	swimSpeed = lerp(0x300 / ts, 0x600 / ts, (float)(hp_max - hp) / hp_max);
	dashMaxSpeed = lerp(0x900 / ts, 0x1000 / ts, (float)(hp_max - hp) / hp_max);
	if (bNormalMode)
	{
		swimSpeed *= 0.8f;
		dashMaxSpeed *= 0.8f;
	}
	switch (stateID)
	{
	case 0://选一个目标最近的玩家
		{
			auto wplayer = GetTracePlayer().lock();
			if (wplayer)
			{
				//面向这个玩家
				target = wplayer;
				lr = x > wplayer->x ? 0 : 1;
				action_timecounter = 60;
				stateID = 1;
			}
		}
		break;
	case 1://向这个玩家追逐至少一秒
		if (action_timecounter > 0)
		{
			action_timecounter--;
		}
		else
		{
			//如果和玩家垂直距离小于16则停下发射子弹
			stateID = 2;
			action_timecounter = (int)lerp(60, 120, (float)(hp_max - hp) / hp_max);
		}
		TraceTarget();
		break;
	case 2://停下并发射子弹
		vx = vy = 0;
		if (action_timecounter > 0)
		{
			int interval = (int)lerp(10, 6, (float)(hp_max - hp) / hp_max);
			if (action_timecounter % interval == 0)
			{
				if (bNormalMode)
				{
					if (Random(0, 10) < 5)
						SetAm();
				}
				else
				{
					SetAm();
				}
			}
			action_timecounter--;
		}
		else
		{
			//继续追踪玩家
			auto wplayer = GetTracePlayer().lock();
			if (wplayer)
			{
				//面向这个玩家
				target = wplayer;
				lr = x > wplayer->x ? 0 : 1;
				action_timecounter = 180;
				stateID = 3;
			}
		}
		break;
	case 3://向这个玩家追逐至少三秒
		if (action_timecounter > 0)
		{
			action_timecounter--;
		}
		else
		{
			//如果和玩家垂直距离小于16则进行撞击准备动作
			stateID = 4;
			action_timecounter = 30;
		}
		TraceTarget();
		break;
	case 4://撞击准备动作
		if (action_timecounter > 0)
		{
			action_timecounter--;
			vx = lr == 0 ? -0x50 / ts : 0x50 / ts;
			vy = 0;
		}
		else
		{
			stateID = 5;
			SetLightTail();
		}
		break;
	case 5://撞击直到碰到墙
		vy = 0;
		if (lr == 0)
		{
			//向左加速冲撞
			if (vx - dashAcc > -dashMaxSpeed)
				vx -= dashAcc;
			else
				vx = -dashMaxSpeed;
			if (cbRect.cbLeft)
			{
				SetQuake();
				//切换到冲撞结束状态
				stateID = 0;
				vy = -0x400 / ts;
			}
		}
		else
		{
			if (vx + dashAcc < dashMaxSpeed)
				vx += dashAcc;
			else
				vx = dashMaxSpeed;
			if (cbRect.cbRight)
			{
				SetQuake();
				//切换到冲撞结束状态
				stateID = 0;
				vy = -0x400 / ts;
			}
		}
		break;
	default:
		break;
	}
	//清除最后一次碰撞结果
	Entity::ClearCollisionResult();
	//执行运动
	Entity::Step();
	//执行碰撞
	Entity::Collision();
	ani.sprite_index = lr == 0 ? L"mc_ironhead_l" : L"mc_ironhead_r";
}

void CS_Boss_Ironhead::SetState(int stateID, int lr)
{
	this->lr = lr;
	ani.sprite_index = lr == 0 ? L"mc_ironhead_l" : L"mc_ironhead_r";
}

void CS_Boss_Ironhead::Attack(std::weak_ptr<Entity> dst, int* outDamage, float* outAngle, bool* outTakedown, int* outElemType, float* outShockForce, float* outHeavy)
{
	if (hp <= 0)
		return;
	*outDamage = 4;
	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_Ironhead::Hurt(std::weak_ptr<Entity> src, int getDamage, float angle, bool bTakedown, int elemType, float shockForce, float heavy, int* outRealDamage)
{
	if (hp <= 0)
		return false;
	if (getDamage == 0)
		return false;
	*outRealDamage = getDamage;
	flash_counter = 30;
	hp -= getDamage;
	if (hp > 0)
	{
		gameFunc->PlaySound(L"CS_sea_enemy_hurt1");
	}
	else
	{
		gameFunc->PlaySound(L"CS_sea_destroy1");
		//创建云团
		SetCS_PeSmokeWater(shared_from_this(), x, y, 3);
		hp = 0;
	}
	//显示伤害值
	if (gameFunc->dmgNum)
		gameFunc->SetDmgNum(gameFunc->dmgNum, getDamage, x, y - 16, 0, shared_from_this());
	return true;
}

void CS_Boss_Ironhead::TraceTarget()
{
	auto wtarget = target.lock();
	if (wtarget && !(abs(wtarget->x - x) <= 8 && abs(wtarget->y - y) <= 8))
	{
		XMVECTOR vec = XMVector2Normalize(XMVectorSet(wtarget->x - x, wtarget->y - y, 0, 0));
		vx = swimSpeed * XMVectorGetX(vec);
		vy = swimSpeed * XMVectorGetY(vec);
		lr = x > wtarget->x ? 0 : 1;
	}
	else
	{
		vx /= 2.0f;
		vy /= 2.0f;
		if (abs(vx) < 0.001f)
			vx = 0;
		if (abs(vy) < 0.001f)
			vy = 0;
	}
}

void CS_Boss_Ironhead::SetAm()
{
	auto am = std::make_shared<CS_Enemy_MannanBlade>(shared_from_this());
	am->existTime = 200;
	//在范围内随机生成
	am->x = x + Random(-16, 16);
	am->y = y + Random(-48, 48);
	am->vy = Random(-0x300, 0x300) / ts;
	gameFunc->SetEntity(shared_from_this(), am);
}

void CS_Boss_Ironhead::SetQuake()
{
	//屏幕震动
	gameFunc->PlaySound(L"CS_071_little_crash");
	SetCS_PeSmokeMedium(shared_from_this(), x, y);
	if (gameFunc->SetQuake)
		gameFunc->SetQuake(gameFunc->game, 30, 0);
	//下落石块
	//激活一次房间里所有的落石定位器
	auto& roomRes = *gameFunc->GetLoadedEntity(gameFunc->entityRes);
	std::list<std::shared_ptr<Entity>>* pLs = nullptr;
	for (auto& p : roomRes)
	{
		if (p.first->layerType == 0)
		{
			pLs = &p.second.Ls;
			break;
		}
	}
	if (pLs)
	{
		for (auto& e : *pLs)
		{
			if (e->el.name == CS_FALLROCK_LOCATOR_CREATENAME)
			{
				if (bNormalMode)
				{
					if (Random(0, 10) < 5)
						e->SetState(L"fallrock", 0);
				}
				else
					e->SetState(L"fallrock", 0);
			}
		}
	}
}

std::weak_ptr<Entity> CS_Boss_Ironhead::GetTracePlayer()
{
	std::weak_ptr<Entity> ret;
	if (gameFunc->GetGlobalEntityTable)
	{
		auto& allPlayer = *gameFunc->GetGlobalEntityTable(gameFunc->game);
		float r = 100000000;
		for (auto& p : allPlayer)
		{
			auto we = p.second.lock();
			if (we)
			{
				if (we->el.name == L"null")
					continue;
				if (we->hide)
					continue;
				if (we->enableAI)
					continue;
				float dx = we->x - x;
				float dy = we->y - y;
				float sq = dx * dx + dy * dy;
				if (sq < r)
				{
					r = sq;
					ret = we;
				}
			}
		}
	}
	return ret;
}

bool CS_Boss_Ironhead::LightTail_Leave(std::weak_ptr<Entity> e)
{
	auto we = e.lock();
	if (we)
	{
		auto _this = std::static_pointer_cast<CS_Boss_Ironhead>(we);
		return _this->stateID != 5;
	}
	return true;
}

void CS_Boss_Ironhead::SetLightTail()
{
	//特效
	auto nE = std::make_shared<PeLightTail>(shared_from_this(), 80, 16);
	nE->SetLeaveFunc(&CS_Boss_Ironhead::LightTail_Leave);
	gameFunc->SetEntity(shared_from_this(), nE);
}

std::shared_ptr<Entity> CreateCS_Boss_Ironhead()
{
	return std::make_shared<CS_Boss_Ironhead>();
}
