#include "CS_Boss_Puu.h"
#include "CS_PuuBubble_Empty.h"
#include "CS_PuuBubble_SoapA.h"
#include "CS_PuuBubble_SoapB.h"
#include "CS_PuuBubble_SoapC.h"
#include "CS_PeSmoke.h"
#include "CS_Boss_GroupHpBar.h"
CS_Boss_Puu::CS_Boss_Puu()
{
	type = 2;
	ani.png = L"CS_CaveStoryMod";
	//启用碰撞
	cbRect.enableCbRect = true;
	cbRect.enableSoild = true;
	//设置碰撞框
	cbRect.left = cbRect.right = 14;
	cbRect.top = 15;
	cbRect.bottom = 8;
	hp_max = hp = 300;
	ani.hideLayerList.insert(1);
	ani.hideLayerList.insert(2);
	drawBeforeOtherEntity = true;

	damage_reset_counter = 60;
	attackState_reset_counter_max = 60;
}

void CS_Boss_Puu::Init(std::weak_ptr<Entity> self)
{
	if (gameFunc->pGameOption_difficulty)
		if (*gameFunc->pGameOption_difficulty == 0)
			bNormalMode = true;
	stateResist.Init(shared_from_this());
	Entity::Init(self);
}

void CS_Boss_Puu::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;
				}
			}
		}
	}
	if (caught_counter > 0)
	{
		caught_counter--;
		stateResist.Step();
		if (caught_counter == 0)
		{
			//将目标抛出
			auto wcaughtTarget = caughtTarget.lock();
			if (wcaughtTarget)
			{
				float throwSpeed = 0x800 / ts;
				wcaughtTarget->hide = false;
				wcaughtTarget->vx = lr == 0 ? -throwSpeed : throwSpeed;
				wcaughtTarget->vy = -0x500 / ts;
			}
			//设置僵直时间
			action_timecounter = 60;
		}
	}
	else
	{
		if (action_timecounter > 0)
		{
			action_timecounter--;
			ani.sprite_index = lr == 0 ? L"mc_puu_jump_l" : L"mc_puu_jump_r";
		}
		else
		{
			switch (stateID)
			{
			case 0:
				//设置面对方向
				if (gameFunc->GetPlayerDistance)
				{
					auto wplayer = gameFunc->GetPlayerDistance(gameFunc->game, x, y).lock();
					if (wplayer)
						lr = x > wplayer->x ? 0 : 1;
				}
				bubbleCloud_counter = Random(30, 70);
				stateID = 1;
				break;
			case 1://发射泡泡云【状态1】
				ani.sprite_index = lr == 0 ? L"mc_puu_openmouth_l" : L"mc_puu_openmouth_r";
				if (bubbleCloud_counter > 0)
				{
					bubbleCloud_counter--;
					if (bubbleCloud_counter % 2 == 0)
					{
						if (bNormalMode)
						{
							if (Random(0, 10) < 3)
								ShootBubble();
						}
						else
						{
							ShootBubble();
						}
					}
				}
				else
				{
					stateID = 2;
					runJump_counter = 3;//设置移动跳跃次数
				}
				break;
			case 2://走向或跳向目标【状态2】
				if (runJump_counter > 0)
				{
					runJump_counter--;
					if (Random(0, 10) >= 3)
					{
						//设置跳跃
						jump_counter = 30;
						stateID = 4;
					}
					else
					{
						//设置移动
						//随机移动时间
						run_counter = Random(60, 120);
						stateID = 3;
					}
					//设置面对方向
					if (gameFunc->GetPlayerDistance)
					{
						auto wplayer = gameFunc->GetPlayerDistance(gameFunc->game, x, y).lock();
						if (wplayer)
							lr = x > wplayer->x ? 0 : 1;
					}
				}
				else
				{
					stateID = 6;
				}
				break;
			case 3://移动
				if (run_counter > 0)
					run_counter--;
				else
				{
					stateID = 5;
					runJumpInterval_counter = 30;//移动跳跃休息时间
				}
				if (lr == 0)
					vx -= 0x20 / ts;
				else
					vx += 0x20 / ts;
				ani.sprite_index = lr == 0 ? L"mc_puu_move_l" : L"mc_puu_move_r";
				break;
			case 4://跳跃
				ani.sprite_index = lr == 0 ? L"mc_puu_jump_l" : L"mc_puu_jump_r";
				if (jump_counter > 0)
				{
					jump_counter--;
					ani.sprite_index = lr == 0 ? L"mc_puu_landing_l" : L"mc_puu_landing_r";
					if (jump_counter == 0)
					{
						vy = -0x400 / ts;
						float vxSpeed = Random(0x400, 0x800) / ts;
						if(bNormalMode)
							vxSpeed = Random(0x200, 0x300) / ts;
						vx = lr == 0 ? -vxSpeed : vxSpeed;
					}
				}
				else
				{
					if (cbRect.cbBottom)
					{
						stateID = 5;
						runJumpInterval_counter = 30;//移动跳跃休息时间
					}
				}
				break;
			case 5://移动/跳跃间隔时间
				if (runJumpInterval_counter > 0)
					runJumpInterval_counter--;
				else
					stateID = 2;//回到状态2
				ani.sprite_index = lr == 0 ? L"mc_puu_stand_l" : L"mc_puu_stand_r";
				vx = 0;
				break;
			case 6://【状态3】
				stateID = 0;
				break;
			case 7://被击败
				ani.sprite_index = lr == 0 ? L"mc_puu_defeated_l" : L"mc_puu_defeated_r";
				stateResist.State();
				break;
			}
		}
	}
	//限制速度
	if (bNormalMode)
	{
		if (vx < -0x600 / ts)
			vx = -0x600 / ts;
		if (vx > 0x600 / ts)
			vx = 0x600 / ts;
	}
	else
	{
		if (vx < -0x300 / ts)
			vx = -0x300 / ts;
		if (vx > 0x300 / ts)
			vx = 0x300 / ts;
	}
	vy += 0x20 / ts;
	if (vy > 0x5FF / ts)
		vy = 0x5FF / ts;
	//清除最后一次碰撞结果
	Entity::ClearCollisionResult();
	//执行运动
	Entity::Step();
	//执行碰撞
	Entity::Collision();
	//维持在斜坡上
	Entity::KeepOnSlopes();
}

void CS_Boss_Puu::SetState(int stateID, int lr)
{
	this->stateID = stateID;
	this->lr = lr;
	ani.sprite_index = lr == 0 ? L"mc_puu_stand_l" : L"mc_puu_stand_r";
}

void CS_Boss_Puu::Attack(std::weak_ptr<Entity> dst, int* outDamage, float* outAngle, bool* outTakedown, int* outElemType, float* outShockForce, float* outHeavy)
{
	if (hp <= 0)
		return;
	auto wdst = dst.lock();
	if (wdst->type == 1 && caught_counter == 0 && action_timecounter == 0 && (stateID == 3 || stateID == 4))
	{
		//捕获玩家
		*outDamage = 10;
		auto wcaught = wdst->BeginCaught(shared_from_this()).lock();
		if (wcaught)
		{
			wdst->hide = true;
			caughtTarget = dst;
			ani.sprite_index = lr == 0 ? L"mc_puu_caught_l" : L"mc_puu_caught_r";
			caught_counter = 120;
		}
	}
	else
	{
		*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_Puu::Hurt(std::weak_ptr<Entity> src, int getDamage, float angle, bool bTakedown, int elemType, float shockForce, float heavy, int* outRealDamage)
{
	if (caught_counter > 0)
		return false;
	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");
	}
	else
	{
		gameFunc->PlaySound(L"CS_071_little_crash");
		//创建云团
		SetCS_PeSmokeMedium(shared_from_this(), x, y);
		hp = 0;
		stateID = 7;
	}
	//显示伤害值
	if (gameFunc->dmgNum)
		gameFunc->SetDmgNum(gameFunc->dmgNum, getDamage, x, y - 16, 0, shared_from_this());
	return true;
}

void CS_Boss_Puu::ShootBubble()
{
	float radian;
	if (lr == 0)
		radian = Random(180 + 15, 270 - 15) * deg2rad;
	else
		radian = Random(270 + 15, 360 - 15) * deg2rad;
	float shootSpeed = Random(0x200, 0x800) / ts;
	float shootVx = shootSpeed * cosf(radian);
	float shootVy = shootSpeed * sinf(radian);
	int type = Random(0, 100);
	gameFunc->PlaySound(L"CS_021_bubble");
	float dx = lr == 0 ? -4.0f : 4.0f;
	if (type <= 80)
		SetCS_PuuBubble_Empty(shared_from_this(), x + dx, y, shootVx, shootVy);
	else if (type <= 90)
		SetCS_PuuBubble_SoapA(shared_from_this(), x + dx, y, shootVx, shootVy);
	else if (type <= 95)
		SetCS_PuuBubble_SoapB(shared_from_this(), x + dx, y, shootVx, shootVy);
	else
		SetCS_PuuBubble_SoapC(shared_from_this(), x + dx, y, shootVx, shootVy);
}

std::shared_ptr<Entity> CreateCS_Boss_Puu()
{
	return std::make_shared<CS_Boss_Puu>();
}
