#include "CS_Jack.h"
#include "CS_PeSmoke.h"
#include "CS_PeLevelUp.h"
#include "CS_Exp.h"
#include "CS_Heart.h"
#include "CS_JackAi.h"
CS_Jack::CS_Jack()
{
	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"mimiga";
	saveName = CS_JACK_CREATENAME;
	throwItem = 0;
	throwItem_max = 0;
	throwItem_type = 1;
	hp_max = 15;
	hp = 15;
	mp_max = 50;
	mp = 0;
	//设置ai
	aiName = CS_JACKAI_CREATENAME;
}

void CS_Jack::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(&stateHurt);
	//添加技能
	AddSkill(&skillBubbler);
	AddSkill(&skillCatcher);
	AddSkill(&skillLevelReset);
	//设置初始状态
	ChangeState(stateStand.GetStateID());
	//设置初始物理状态
	SetPhysice(false);
	//设置初始技能绑定
	SetSkillBindIndex(&skillBubbler, 0);
	skillBubbler.lock = false;
	/*SetSkillBindIndex(&skillCatcher, 1);
	skillCatcher.lock = false;*/
	stateStand.Step();
	AnimateStep();
	MyCharEntity::Init(self);
}

void CS_Jack::Step()
{
	//防止掉地图外面
	Entity::KeepInMap();
	//跟上移动平台
	Entity::BeginMovingPlatform();
	//图层动画
	AnimateStep();
	//检测被移动平台压死
	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://走路
			stateMove.State();
			stateGravity.State();
			break;
		case 4://受伤
			vx = 0;
			//重力
			stateGravity.State();
			stateWater.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_Jack::SetState(int stateID, int lr)
{
	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_jack_back_l" : L"mc_jack_back_r";
		break;
	case 3://躺下
		vx = 0;
		ani.sprite_index = lr == 0 ? L"mc_jack_lie_l" : L"mc_jack_lie_r";
		break;
	case 4://受伤
		ani.sprite_index = lr == 0 ? L"mc_jack_hurt_l" : L"mc_jack_hurt_r";
		break;
	}
}

void CS_Jack::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"show_gun")
		showGun = true;
	else if (stateName == L"hide_gun")
		showGun = false;
	else if (stateName == L"catcher_get")
	{
		SetSkillBindAdd(&skillCatcher);
		skillCatcher.lock = false;
	}
	else if (stateName == L"levelreset_get")
	{
		SetSkillBindAdd(&skillLevelReset);
		skillLevelReset.lock = false;
	}
	else if (stateName == L"levelreset_lose")
	{
		RemoveSkillBind(&skillLevelReset);
		skillLevelReset.lock = true;
	}
}

void CS_Jack::LoadSaveData()
{
	MyCharEntity::LoadSaveData();
	showGun = std::stoi(gameFunc->ReadData(CS_JACK_CREATENAME, L"showGun", L"0")) != 0;
}

void CS_Jack::WriteSaveData()
{
	MyCharEntity::WriteSaveData();
	gameFunc->WriteData(CS_JACK_CREATENAME, L"showGun", std::to_wstring(showGun ? 1 : 0).c_str());
}

bool CS_Jack::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");
		//触发等级下降
		if ((mp >= 30 && mp - 2 * getDamage < 30) ||
			(mp >= 10 && mp - 2 * getDamage < 10))
			SetCS_PeLevelDown(shared_from_this(), x, y);
	}
	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");
		}
	}
	//掉经验
	mp -= 2 * getDamage;
	if (mp < 0)
		mp = 0;
	//伤害冲击处理
	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_Jack::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;
			}
		}
		//触发等级上升
		if ((mp < 10 && mp + witem->dropExp >= 10) ||
			(mp < 30 && mp + witem->dropExp >= 30))
			SetCS_PeLevelUp(shared_from_this(), x, y);
		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_Jack::Destroy()
{
	MyCharEntity::Destroy();
}

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

void CS_Jack::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_Jack::CopyFrom(std::shared_ptr<Entity>& another)
{
	MyCharEntity::CopyFrom(another);
	auto mychar = std::dynamic_pointer_cast<CS_Jack>(another);
	if (mychar)
	{
		showGun = mychar->showGun;
	}
}

void CS_Jack::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;
		}
	}
}

void CS_Jack::AnimateStep()
{
	ani.hideLayerList.insert(0);
	ani.hideLayerList.insert(3);
	if (showGun)
	{
		ani.hideLayerList.erase(0);
		ani.hideLayerList.erase(3);
	}
}

std::shared_ptr<Entity> CreateCS_Jack()
{
	return std::make_shared<CS_Jack>();
}
