#include "CS_Boss_SoapKing.h"
#include "CS_PeSmoke.h"
#include "CS_MagicBubble.h"
#include "CS_LightningStrike.h"
#include "CS_LightningStrikeTarget.h"
#include "CS_Boss_SoapKingMagicFloor_Wall.h"
#include "CS_Boss_SoapKingMagicFloor_FloatFloor.h"
#include "CS_Boss_SoapKingMagicFloor_PressWall.h"
CS_Boss_SoapKing::CS_Boss_SoapKing()
{
	type = 2;
	ani.png = L"CS_CaveStoryMod";
	cbRect.enableCbRect = true;
	cbRect.enableSoild = true;
	cbRect.left = cbRect.right = 15;
	cbRect.top = 35;
	cbRect.bottom = 8;
	hp_max = hp = 500;
	damage_reset_counter = 60;
	attackState_reset_counter_max = 60;
	drawBeforeOtherEntity = true;
	coyote_max = coyote_counter = 0;
}

void CS_Boss_SoapKing::Init(std::weak_ptr<Entity> self)
{
	ActionEntity::Init(self);
}

void CS_Boss_SoapKing::Step()
{
	switch (stateID)
	{
	case 0://站立
		vx = 0;
		break;
	case 1://移动
		vx = lr == 0 ? -animation_moveSpeed : animation_moveSpeed;
		break;
	case 2://对玩家1施展泡泡
		if (action_timecounter > 0)
			action_timecounter--;
		if (action_timecounter == 0)
		{
			auto we = std::make_shared<CS_MagicBubble>(gameFunc->GetMyChar_Player1(gameFunc->entityRes).lock());
			we->x = x - 40 + (lr == 1? 1 : 0) * 2;
			we->y = y - 64;
			gameFunc->SetEntity(shared_from_this(), we);
			action_timecounter = 30;
			stateID = 3;
		}
		break;
	case 3://僵直复原
		if (action_timecounter > 0)
			action_timecounter--;
		if (action_timecounter == 0)
		{
			ani.sprite_index = lr == 0 ? L"mc_soapking_stand_l" : L"mc_soapking_stand_r";
			stateID = 0;
		}
		break;
	case 4://对玩家1施展雷击
		if (action_timecounter > 0)
			action_timecounter--;
		if (action_timecounter == 0)
		{
			//释放雷击
			auto wtarget = target.lock();
			if (wtarget)
			{
				auto we = std::make_shared<CS_LightningStrike>();
				we->x = wtarget->x;
				we->y = wtarget->y;
				gameFunc->SetEntity(shared_from_this(), we);
			}
			action_timecounter = 30;
			enableflash = true;
			stateID = 5;
		}
		break;
	case 5://闪烁
		if (action_timecounter > 0)
			action_timecounter--;
		if (action_timecounter == 0)
		{
			enableflash = false;
			action_timecounter = 30;
			stateID = 3;
		}
		break;
	case 20://设置战斗
		//施法墙面
		bFloorX = x;
		bFloorY = y;
		ani.sprite_index = lr == 0 ? L"mc_soapking_spell_l" : L"mc_soapking_spell_r";
		action_timecounter = 30;
		stateID = 21;
		break;
	case 21:
		if (action_timecounter > 0)
			action_timecounter--;
		if (action_timecounter == 0)
		{
			SetCS_Boss_SoapKingMagicFloor_Wall(shared_from_this(), x - 16 * 6, y, 0, 16, 300);
			action_timecounter = 128 + 8;
			stateID = 22;
		}
		break;
	case 22://施法悬浮地面
		if (action_timecounter > 0)
			action_timecounter--;
		if (action_timecounter == 0)
		{
			floor = SetCS_Boss_SoapKingMagicFloor_FloatFloor(shared_from_this(), x, bFloorY - 16 * 6);
			action_timecounter = 30;
			stateID = 23;
		}
		break;
	case 23://施法完毕
		if (action_timecounter > 0)
			action_timecounter--;
		if (action_timecounter == 0)
		{
			
			ani.sprite_index = lr == 0 ? L"mc_soapking_stand_l" : L"mc_soapking_stand_r";
			action_timecounter = 30;
			stateID = 24;
		}
		break;
	case 24://准备跳到悬浮地板上
		if (action_timecounter > 0)
			action_timecounter--;
		if (action_timecounter == 0)
		{
			ani.sprite_index = lr == 0 ? L"mc_soapking_landing_l" : L"mc_soapking_landing_r";
			action_timecounter = 30;
			stateID = 25;
		}
		break;
	case 25://跳跃
		if (action_timecounter > 0)
			action_timecounter--;
		if (action_timecounter == 0)
		{
			vy = -0x800 / ts;
			cbRect.enableCbRect = false;
			cbRect.enableSoild = false;
			Entity::ClearCollisionResult();
			ani.sprite_index = lr == 0 ? L"mc_soapking_jump_l" : L"mc_soapking_jump_r";
			action_timecounter = 30;
			stateID = 26;
		}
		break;
	case 26://跳跃途中
		if (vy >= 0)
		{
			cbRect.enableCbRect = true;
			cbRect.enableSoild = true;
			if (cbRect.cbBottom)
			{
				gameFunc->PlaySound(L"CS_026_quake");
				if (gameFunc->SetQuake)
					gameFunc->SetQuake(gameFunc->game, 30, 0);
				auto wfloor = floor.lock();
				if (wfloor)
				{
					wfloor->vx = 0x180 / ts;
					wfloor->vy = 0x200 / ts;
				}
				bFixOnFloor = true;
				ani.sprite_index = lr == 0 ? L"mc_soapking_landing_l" : L"mc_soapking_landing_r";
				action_timecounter = 30;
				stateID = 27;
			}
		}
		vy += 0x20 / ts;
		break;
	case 27://在平台上站稳
		if (action_timecounter > 0)
			action_timecounter--;
		if (action_timecounter == 0)
		{
			auto wfloor = floor.lock();
			if (wfloor)
			{
				wfloor->vx = 0;
				wfloor->SetFloatCenter(bFloorY - 16 * 10);
			}
			ani.sprite_index = lr == 0 ? L"mc_soapking_stand_l" : L"mc_soapking_stand_r";
			action_timecounter = 60;
			stateID = 28;
		}
		break;
	case 28://平台上升完后开始施展魔法
		if (action_timecounter > 0)
			action_timecounter--;
		if (action_timecounter == 0)
		{
			stateID = 29;
		}
		break;
	case 29://施展墙压魔法
		for (int j = 0; j < 2; j++)
		{
			PressFloorMagic pfm;
			pfm.x = -2 * 16.0f + x - 8.0f;
			pfm.y = -15 * 16.0f + bFloorY;
			pfm.angle = 180.0f;
			pfm.count = 5;
			pfm.pressAngle = 90.0f;
			for (int i = 0; i < 7; i++)
			{
				pfmList.push_back(pfm);
				pfm.x -= pfm.count * 16.0f;
			}
		}
		stateID = 30;
		break;
	case 30:
		if (pfmList.empty())
		{
			//去下一个攻击方式
			stateID = 40;
		}
		else
		{
			//继续走施法列表
			ani.sprite_index = lr == 0 ? L"mc_soapking_spell_l" : L"mc_soapking_spell_r";
			action_timecounter = 30;
			stateID = 31;
		}
		break;
	case 31:
		if (action_timecounter > 0)
			action_timecounter--;
		if (action_timecounter == 0)
		{
			auto& m = pfmList.front();
			//施法
			SetCS_Boss_SoapKingMagicFloor_PressWall(shared_from_this(), m.x, m.y, m.angle, m.count, m.pressAngle);
			pfmList.pop_front();
			action_timecounter = 10;
			stateID = 32;
		}
		break;
	case 32://施法僵直
		if (action_timecounter > 0)
			action_timecounter--;
		if (action_timecounter == 0)
			stateID = 30;
		break;
	case 40://飞到左边
		{
			ani.sprite_index = lr == 0 ? L"mc_soapking_stand_l" : L"mc_soapking_stand_r";
			auto wfloor = floor.lock();
			if (wfloor)
			{
				wfloor->vx = -0x600 / ts;
			}
			action_timecounter = 185;
			stateID = 41;
		}
		break;
	case 41://到左边后转身
		if (action_timecounter > 0)
			action_timecounter--;
		if (action_timecounter == 0)
		{
			auto wfloor = floor.lock();
			if (wfloor)
			{
				wfloor->vx = 0;
				lr = 1;
				ani.sprite_index = lr == 0 ? L"mc_soapking_stand_l" : L"mc_soapking_stand_r";
				action_timecounter = 30;
				stateID = 42;
			}
		}
		break;
	case 42://使用垂直墙面攻击
		for (int j = 0; j < 4; j++)
		{
			PressFloorMagic pfm;
			pfm.x = -2 * 16.0f + x;
			pfm.y = -9.01f * 16.0f + bFloorY;
			pfm.angle = 90.0f;
			pfm.count = 5;
			pfm.pressAngle = 0;
			for (int i = 0; i < 2; i++)
			{
				pfmList.push_back(pfm);
				pfm.y += pfm.count * 16.0f;
			}
		}
		stateID = 43;
		break;
	case 43:
		if (action_timecounter > 0)
			action_timecounter--;
		if (action_timecounter == 0)
		{
			stateID = 44;
		}
		break;
	case 44:
		if (pfmList.empty())
		{
			//去下一个攻击方式
			stateID = 50;
		}
		else
		{
			//继续走施法列表
			ani.sprite_index = lr == 0 ? L"mc_soapking_spell_l" : L"mc_soapking_spell_r";
			action_timecounter = 30;
			stateID = 45;
		}
		break;
	case 45:
		if (action_timecounter > 0)
			action_timecounter--;
		if (action_timecounter == 0)
		{
			auto& m = pfmList.front();
			//施法
			SetCS_Boss_SoapKingMagicFloor_PressWall(shared_from_this(), m.x, m.y, m.angle, m.count, m.pressAngle);
			pfmList.pop_front();
			action_timecounter = 10;
			stateID = 46;
		}
		break;
	case 46://施法僵直
		if (action_timecounter > 0)
			action_timecounter--;
		if (action_timecounter == 0)
			stateID = 44;
		break;
	case 50://飞到中央
		{
			ani.sprite_index = lr == 0 ? L"mc_soapking_stand_l" : L"mc_soapking_stand_r";
			auto wfloor = floor.lock();
			if (wfloor)
			{
				wfloor->vx = 0x600 / ts;
			}
			action_timecounter = 92;
			stateID = 51;
		}
		break;
	case 51://飞行停止
		if (action_timecounter > 0)
			action_timecounter--;
		if (action_timecounter == 0)
		{
			ani.sprite_index = lr == 0 ? L"mc_soapking_stand_c" : L"mc_soapking_stand_c";
			auto wfloor = floor.lock();
			if (wfloor)
			{
				wfloor->vx = 0;
				action_timecounter = 30;
				stateID = 52;
			}
		}
		break;
	case 52://开始施法
		if (action_timecounter > 0)
			action_timecounter--;
		if (action_timecounter == 0)
		{
			ani.sprite_index = lr == 0 ? L"mc_soapking_spell_c" : L"mc_soapking_spell_c";
			action_timecounter = 30;
			stateID = 53;
		}
		break;
	case 53://对玩家1释放变形法术
		if (action_timecounter > 0)
			action_timecounter--;
		if (action_timecounter == 0)
		{
			auto wp1 = gameFunc->GetMyChar_Player1(gameFunc->entityRes).lock();
			if (wp1)
			{
				auto am = std::make_shared<CS_MagicBubble>(wp1);
				am->x = x - 40 + (lr == 1 ? 1 : 0) * 2;
				am->y = y - 64;
				gameFunc->SetEntity(wp1, am);
			}
			action_timecounter = 30;
			stateID = 54;
		}
		break;
	case 54://对玩家2释放变形法术
		if (action_timecounter > 0)
			action_timecounter--;
		if (action_timecounter == 0)
		{
			auto wp1 = gameFunc->GetMyChar_Player2(gameFunc->entityRes).lock();
			if (wp1)
			{
				auto am = std::make_shared<CS_MagicBubble>(wp1);
				am->x = x - 40 + (lr == 1 ? 1 : 0) * 2;
				am->y = y - 64;
				gameFunc->SetEntity(wp1, am);
			}
			action_timecounter = 30;
			stateID = 55;
		}
		break;
	case 55://准备释放闪电
		if (action_timecounter > 0)
			action_timecounter--;
		if (action_timecounter == 0)
		{
			ani.sprite_index = lr == 0 ? L"mc_soapking_stand_c" : L"mc_soapking_stand_c";
			action_timecounter = 30;
			stateID = 56;
		}
		break;
	case 56:
		if (action_timecounter > 0)
			action_timecounter--;
		if (action_timecounter == 0)
		{
			ani.sprite_index = lr == 0 ? L"mc_soapking_spell_c" : L"mc_soapking_spell_c";
			action_timecounter = 30;
			stateID = 57;
		}
		break;
	case 57://设置释放的闪电数量
		if (action_timecounter > 0)
			action_timecounter--;
		if (action_timecounter == 0)
		{
			enableflash = true;
			lightning_counter = 10;
			stateID = 58;
		}
		break;
	case 58:
		if (lightning_counter > 0)
		{
			lightning_counter--;
			//分别在对玩家1、玩家2的位置设置闪电
			auto wp1 = gameFunc->GetMyChar_Player1(gameFunc->entityRes).lock();
			if (wp1)
				SetCS_LightningStrikeTarget(shared_from_this(), wp1->x, bFloorY);
			auto wp2 = gameFunc->GetMyChar_Player2(gameFunc->entityRes).lock();
			if (wp2)
				SetCS_LightningStrikeTarget(shared_from_this(), wp2->x, bFloorY);
			action_timecounter = 30;
			stateID = 59;
		}
		else
		{
			enableflash = false;
			action_timecounter = 30;
			stateID = 60;
		}
		break;
	case 59://直到闪电释放完毕
		if (action_timecounter > 0)
			action_timecounter--;
		if (action_timecounter == 0)
			stateID = 58;
		break;
	case 60://回到最右端
		{
			lr = 1;
			ani.sprite_index = lr == 0 ? L"mc_soapking_stand_l" : L"mc_soapking_stand_r";
			auto wfloor = floor.lock();
			if (wfloor)
			{
				wfloor->vx = 0x600 / ts;
			}
			action_timecounter = 93;
			stateID = 61;
		}
		break;
	case 61:
		if (action_timecounter > 0)
			action_timecounter--;
		if (action_timecounter == 0)
		{
			auto wfloor = floor.lock();
			if (wfloor)
			{
				wfloor->vx = 0;
			}
			lr = 0;
			ani.sprite_index = lr == 0 ? L"mc_soapking_stand_l" : L"mc_soapking_stand_r";
			stateID = 29;
		}
		break;
	case 100://被击败了
		ani.sprite_index = lr == 0 ? L"mc_soapking_defeated2_l" : L"mc_soapking_defeated2_r";
		vy += 0x20 / ts;
		if (vy > 0x5FF / ts)
			vy = 0x5FF / ts;
		action_timecounter++;
		//产生烟雾
		if (action_timecounter >= 10)
		{
			action_timecounter = 0;
			float offset_x = (float)Random((int)-cbRect.left, (int)cbRect.right);
			float offset_y = (float)Random((int)-cbRect.top, (int)cbRect.bottom);
			auto e = std::make_shared<CS_PeSmoke>();
			e->x = x + offset_x;
			e->y = y + offset_y;
			gameFunc->SetEntity(shared_from_this(), e);
		}
		break;
	case 101://变成了雕塑
		ani.sprite_index = lr == 0 ? L"mc_soapking_defeated_l" : L"mc_soapking_defeated_r";
		break;
	}
	if (bFixOnFloor)
	{
		vx = 0;
		vy = 0;
		auto wfloor = floor.lock();
		if (wfloor)
		{
			x = wfloor->x;
			y = wfloor->y - 16;
			last_x = wfloor->last_x;
			last_y = wfloor->last_y - 16;
		}
	}
	else
	{
		//跟上移动平台
		Entity::EndMovingPlatform();
		//清除最后一次碰撞结果
		Entity::ClearCollisionResult();
		//动画延迟一帧
		if (animation_delay)
			animation_delay = false;
		else
			Entity::Step();//执行运动
		//执行碰撞
		Entity::Collision();
		//维持在斜坡上
		Entity::KeepOnSlopes();
	}
	if (enableflash)
	{
		flashcounter++;
		if (flashcounter / 2 % 2 == 0)
		{
			shader.usingShader = false;
		}
		else
		{
			shader.usingShader = true;
			shader.ps = shader.vs = L"flash";
		}
	}
	else
	{
		flashcounter = 0;
		shader.usingShader = false;
	}
}

void CS_Boss_SoapKing::SetState(int stateID, int lr)
{
	this->lr = lr;
	this->stateID = stateID;
	switch (stateID)
	{
	case 0://没有动画（恢复玩家控制）
		vx = 0;
		ani.sprite_index = lr == 0 ? L"mc_soapking_stand_l" : L"mc_soapking_stand_r";
		break;
	case 1://走路
		animation_delay = true;
		if (lr == 0)
			vx = -animation_moveSpeed;
		else
			vx = animation_moveSpeed;
		ani.sprite_index = lr == 0 ? L"mc_soapking_move_l" : L"mc_soapking_move_r";
		break;
	case 2://对玩家1施展泡泡
		ani.sprite_index = lr == 0 ? L"mc_soapking_spell_l" : L"mc_soapking_spell_r";
		action_timecounter = 30;
		break;
	case 4://对玩家1施展雷击
		ani.sprite_index = lr == 0 ? L"mc_soapking_spell_l" : L"mc_soapking_spell_r";
		action_timecounter = 30;
		target = gameFunc->GetMyChar_Player1(gameFunc->entityRes);
		break;
	case 101://变成了雕塑
		gameFunc->PlaySound(L"CS_071_little_crash");
		//创建云团
		SetCS_PeSmokeLarge(shared_from_this(), x, y);
		break;
	}

}

void CS_Boss_SoapKing::SetState(std::wstring stateName, int lr)
{
	if(stateName == L"normal")
		SetState(0, lr);
	else if (stateName == L"walk")
		SetState(1, lr);
	else if (stateName == L"magicbubble_player1")
		SetState(2, lr);
	else if (stateName == L"lightningstrike_player1")
		SetState(4, lr);
	else if (stateName == L"fight")
		SetState(20, lr);
	else if (stateName == L"defeated")
		SetState(101, lr);
}

void CS_Boss_SoapKing::Attack(std::weak_ptr<Entity> dst, int* outDamage, float* outAngle, bool* outTakedown, int* outElemType, float* outShockForce, float* outHeavy)
{
	if (hp <= 0)
		return;
	*outDamage = 10;
	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_SoapKing::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;
	if (hp > 0)
	{
		gameFunc->PlaySound(L"CS_054_enemy_hurt_cool");
	}
	else
	{
		gameFunc->PlaySound(L"CS_071_little_crash");
		//创建云团
		SetCS_PeSmokeLarge(shared_from_this(), x, y);
		hp = 0;
		stateID = 100;
		action_timecounter = 0;
		bFixOnFloor = false;
		auto wfloor = floor.lock();
		if (wfloor)
			wfloor->Disappear();
	}
	//显示伤害值
	if (gameFunc->dmgNum)
		gameFunc->SetDmgNum(gameFunc->dmgNum, getDamage, x, y - 16, 0, shared_from_this());
	return true;
}

std::shared_ptr<Entity> CreateCS_Boss_SoapKing()
{
	return std::make_shared<CS_Boss_SoapKing>();
}
