#include "CS_King.h"
#include "CS_PeSmoke.h"
#include "CS_Exp.h"
#include "CS_Heart.h"
#include "PeSmog.h"
CS_King::CS_King()
{
	type = 1;
	//初始动画设置
	ani.png = L"CS_CaveStoryMod";
	//启用碰撞
	cbRect.enableCbRect = true;
	cbRect.enableSoild = true;
	//设置碰撞框
	cbRect.left = cbRect.right = 5;
	cbRect.top = 6;
	cbRect.bottom = 8;
	//初始数值
	uiName = L"king";
	saveName = CS_KING_CREATENAME;
	throwItem = 0;
	throwItem_max = 0;
	throwItem_type = 1;
	hp_max = 40;
	hp = 40;
	mp_max = 80;
	mp = 0;
}

void CS_King::Init(std::weak_ptr<Entity> self)
{
	//添加状态控制器（也是执行顺序）
	AddState(&stateFlash);
	AddState(&stateInvincible);
	AddState(&stateGravity);
	AddState(&stateWater);
	AddState(&stateDrown);
	AddState(&stateControl);
	AddState(&stateResist);//在stateControl后面
	AddState(&stateJump);
	AddState(&stateStand);
	AddState(&stateMove);
	AddState(&stateAir);
	AddState(&stateFaceToBack);
	AddState(&stateClimb);
	AddState(&stateHurt);
	//添加技能
	AddSkill(&skillSwordV1);
	AddSkill(&skillSwordV2);
	AddSkill(&skillSwordV3);
	AddSkill(&skillGuard);
	AddSkill(&skillLifeUp);
	//设置初始状态
	ChangeState(stateStand.GetStateID());
	//设置初始物理状态
	SetPhysice(false);
	//设置初始技能绑定
	SetSkillBindIndex(&skillSwordV1, 0);
	skillSwordV1.lock = false;
	SetSkillBindIndex(&skillSwordV2, 1);
	skillSwordV2.lock = false;
	SetSkillBindIndex(&skillSwordV3, 2);
	skillSwordV3.lock = false;
	SetSkillBindIndex(&skillGuard, 3);
	skillGuard.lock = false;
	SetSkillBindIndex(&skillLifeUp, 4);
	skillLifeUp.lock = false;
	stateStand.Step();
	MyCharEntity::Init(self);
}

void CS_King::Step()
{
	//防止掉地图外面
	Entity::KeepInMap();
	//跟上移动平台
	Entity::BeginMovingPlatform();
	//检测被移动平台压死
	if (CheckCrush(&crushEvent))
		CrushDeath();
	//状态机
	if (stateID == 0 && type == 1)
	{
		//玩家控制
		for (auto& p : stateList)
			p->Step();
		if (atkFeedBack > 0)
			atkFeedBack--;
		else if (action_timecounter > 0)
			action_timecounter--;
	}
	else if (type == 0 || stateID != 0)
	{
		//动画
		switch (stateID)
		{
		case 0://站立
			stateStand.State();
			vx = 0;
			//重力
			stateGravity.State();
			break;
		case 1://走路
			if (cbRect.cbBottom)
				stateMove.State();
			else
				stateAir.State();
			stateGravity.State();
			break;
		case 4://受伤
			vx = 0;
			//重力
			stateGravity.State();
			stateWater.State();
			break;
		case 5://被击飞
			vx = lr == 0 ? 0x600 / ts : -0x600 / ts;
			if (lr == 0 && cbRect.cbRight)
			{
				lr = 1;
				stateID = 6;
				vy = -0x400 / ts;
				vx = -0x200 / ts;
				gameFunc->PlaySound(L"CS_071_little_crash");
				SetCS_PeSmokeSmall(shared_from_this(), x, y);
			}
			else if (lr != 0 && cbRect.cbLeft)
			{
				lr = 0;
				stateID = 6;
				vy = -0x400 / ts;
				vx = 0x200 / ts;
				gameFunc->PlaySound(L"CS_071_little_crash");
				SetCS_PeSmokeSmall(shared_from_this(), x, y);
			}
			ani.sprite_index = lr == 0 ? L"mc_king_hurt2_l" : L"mc_king_hurt2_r";
			break;
		case 6://掉落
			if (cbRect.cbBottom)
			{
				stateID = 7;
			}
			stateResist.State();
			stateGravity.State();
			ani.sprite_index = lr == 0 ? L"mc_king_hurt2_l" : L"mc_king_hurt2_r";
			break;
		case 7://趴在地上
			stateResist.State();
			stateGravity.State();
			ani.sprite_index = lr == 0 ? L"mc_king_lie_l" : L"mc_king_lie_r";
			break;
		case 200://变成鱼了
			ani.image_index = 0;
			stateResist.State();
			stateGravity.State();
			break;
		}
	}
	//更新UI
	MyCharEntity::UpdateUI();
	//风场
	Entity::Wind();
	//跟上移动平台
	Entity::EndMovingPlatform();
	//清除最后一次碰撞结果
	Entity::ClearCollisionResult();
	//动画延迟一帧
	if (animation_delay)
		animation_delay = false;
	else
		Entity::Step();//执行运动
	//执行碰撞
	Entity::Collision();
	//维持在斜坡上
	Entity::KeepOnSlopes();
}

void CS_King::SetState(int stateID, int lr)
{
	if (stateID < 200)
	{
		this->stateID = stateID;
		this->lr = lr;
		switch (stateID)
		{
		case 0://没有动画（恢复玩家控制）
			faceToBack = false;
			vx = 0;
			break;
		case 1://走路
			animation_delay = true;
			if (lr == 0)
				vx = -animation_moveSpeed;
			else
				vx = animation_moveSpeed;
			stateMove.State();
			//重力
			stateGravity.State();
			break;
		case 2://背对着
			vx = 0;
			ani.sprite_index = lr == 0 ? L"mc_king_back_l" : L"mc_king_back_r";
			break;
		case 3://躺下
			vx = 0;
			ani.sprite_index = lr == 0 ? L"mc_king_lie_l" : L"mc_king_lie_r";
			break;
		case 4://受伤
			ani.sprite_index = lr == 0 ? L"mc_king_hurt_l" : L"mc_king_hurt_r";
			break;
		case 5://被闪电击中
			cbRect.left = cbRect.right = 5;
			cbRect.top = 6;
			cbRect.bottom = 8;
			y -= 16;
			ani.sprite_index = lr == 0 ? L"mc_king_hurt2_l" : L"mc_king_hurt2_r";
			break;
		}
	}
	else
	{
		switch (stateID)
		{
		case 200://变成鱼
			this->stateID = stateID;
			cbRect.left = cbRect.right = 5;
			cbRect.top = 4;
			cbRect.bottom = 4;
			ani.sprite_index = this->lr == 0 ? L"mc_kingfish_stand_l" : L"mc_kingfish_stand_r";
			SetPeSmog(shared_from_this(), x, y, 3);
			break;
		case 201://变回来
			cbRect.left = cbRect.right = 5;
			cbRect.top = 6;
			cbRect.bottom = 8;
			this->stateID = 0;
			SetPeSmog(shared_from_this(), x, y, 3);
			break;
		}
	}
}

void CS_King::SetState(std::wstring stateName, int lr)
{
	MyCharEntity::SetState(stateName, lr);
	if (stateName == L"normal")
		SetState(0, lr);
	else if (stateName == L"walk")
		SetState(1, lr);
	else if (stateName == L"back")
		SetState(2, lr);
	else if (stateName == L"lie")
		SetState(3, lr);
	else if (stateName == L"hurt")
		SetState(4, lr);
	else if (stateName == L"smoke")
	{
		for (int i = 0; i < 4; i++)
		{
			auto pe = std::make_shared<CS_PeSmoke>();
			pe->x = x + Random(-12, 12);
			pe->y = y + Random(-12, 12);
			pe->vx = Random(-341, 341) / ts;
			pe->vy = Random(-0x600, 0) / ts;
			gameFunc->SetEntity(shared_from_this(), pe);
		}
	}
	else if(stateName == L"knocked_away")
		SetState(5, lr);
	else if (stateName == L"transform_fish")
		SetState(200, lr);
	else if (stateName == L"transform_back")
		SetState(201, lr);
}

void CS_King::LoadSaveData()
{
	MyCharEntity::LoadSaveData();
}

void CS_King::WriteSaveData()
{
	MyCharEntity::WriteSaveData();
}

bool CS_King::Hurt(std::weak_ptr<Entity> src, int getDamage, float angle, bool bTakedown, int elemType, float shockForce, float heavy, int* outRealDamage)
{
	//运行事件时，无敌状态
	if (gameFunc->ScriptIsRunning)
	{
		if (gameFunc->ScriptIsRunning(gameFunc->gameScript))
			return false;
	}
	//状态处理
	for (auto& p : stateList)
	{
		bool retVal = true;
		if (p->Hurt(src, &getDamage, &angle, &bTakedown, &elemType, &shockForce, &heavy, outRealDamage, &retVal))
			return retVal;
	}
	//技能处理
	for (auto& p : skillList)
	{
		bool retVal = true;
		if (p->Hurt(src, &getDamage, &angle, &bTakedown, &elemType, &shockForce, &heavy, outRealDamage, &retVal))
			return retVal;
	}
	if (getDamage == 0)
		return false;
	*outRealDamage = getDamage;
	stateInvincible.SetDamage(getDamage);
	hp -= getDamage;
	if (hp > 0)
	{
		gameFunc->PlaySound(L"CS_050_mimiga_squeak");
	}
	else
	{
		//创建云团
		SetCS_PeSmokeMedium(shared_from_this(), x, y);
		hp = 0;
		UpdateUI();
		//游戏结束
		hide = true;
		//设置
		if (gameFunc->StartEvent)
		{
			gameFunc->PlaySound(L"CS_017_quote_die");
			gameFunc->StopMusic();
			gameFunc->StartEvent(gameFunc->gameScript, L"Died", L"tDeath");
		}
	}
	//伤害冲击处理
	if (shockForce > 0)
	{
		//被攻击弹反
		float radian = angle * deg2rad;
		vx = shockForce * cosf(radian);
		vy = shockForce * sinf(radian);
		vy -= 1;
	}
	//设置闪光
	stateFlash.flash_counter = 5;
	//显示伤害值
	if (gameFunc->dmgNum)
		gameFunc->SetDmgNum(gameFunc->dmgNum, getDamage, x, y - 16, 1, shared_from_this());
	//转换状态
	ChangeState(stateHurt.GetStateID());
	return true;
}

void CS_King::Gain(std::weak_ptr<Entity> item)
{
	//拾取到了经验
	auto witem = item.lock();
	if (!witem)
		return;
	if (witem->el.name == CS_EXP_CREATENAME && witem->inUsing)
	{
		//Mp条闪烁
		if (gameFunc->GetPlayerIndex)
		{
			int playerIndex = gameFunc->GetPlayerIndex(gameFunc->game, shared_from_this());
			if (playerIndex >= 0)
			{
				auto& ui = *gameFunc->GetPlayerUIData(gameFunc->gameUI, playerIndex);
				ui.MpBar_flash_counter = 30;
			}
		}
		mp += witem->dropExp;
		if (mp > mp_max)
			mp = mp_max;
		gameFunc->PlaySound(L"CS_014_get_xp");
		//显示经验值
		if (gameFunc->dmgNum)
			gameFunc->SetDmgNum(gameFunc->dmgNum, witem->dropExp, x, y - 16, 3, shared_from_this());
		witem->Destroy();
	}
	//拾取到了生命
	else if (witem->el.name == CS_HEART_CREATENAME && witem->inUsing)
	{
		//生命恢复
		hp += witem->hp;
		if (hp > hp_max)
			hp = hp_max;
		gameFunc->PlaySound(L"CS_020_health_refill");
		witem->Destroy();
	}
}

void CS_King::Destroy()
{
	MyCharEntity::Destroy();
}

void CS_King::GetIcon(std::wstring& png, std::wstring& sprite_index, int& image_index, std::set<int>& hideLayerList)
{
	png = L"CS_CaveStoryMod";
	sprite_index = L"mc_king_stand_r";
	image_index = 0;
	hideLayerList = ani.hideLayerList;
}

void CS_King::CrushDeath()
{
	//创建云团
	SetCS_PeSmokeMedium(shared_from_this(), x, y);
	hp = 0;
	UpdateUI();
	//游戏结束
	hide = true;
	//游戏结束
	if (gameFunc->StartEvent)
	{
		gameFunc->PlaySound(L"CS_017_quote_die");
		gameFunc->StopMusic();
		if (crushEvent.length())
			gameFunc->StartEvent(gameFunc->gameScript, crushEvent.c_str(), L"tCrush");
		else
			gameFunc->StartEvent(gameFunc->gameScript, L"DeathByMovingPlatform", L"tCrush");
	}
}

void CS_King::CopyFrom(std::shared_ptr<Entity>& another)
{
	MyCharEntity::CopyFrom(another);
}

void CS_King::GetAnimateOffset(float& outDx, float& outDy)
{
	outDx = 0;
	outDy = 0;
	if (stateAir.GetEnable())
	{
		outDy = -1;
	}
	else if (stateMove.GetEnable())
	{
		if (ani.image_index % 2 == 0)
		{
			outDy = -1;
		}
	}
}

std::shared_ptr<Entity> CreateCS_King()
{
	return std::make_shared<CS_King>();
}
