#include "CS_Enemy_RollRock.h"
#include "PeSpark.h"
#include "CS_PeSmoke.h"

CS_Enemy_RollRock::CS_Enemy_RollRock()
{
	type = 2;
	cbRect.left = cbRect.right = cbRect.top = cbRect.bottom = 7;
	cbRect.enableCbRect = true;
	cbRect.enableSoild = true;
	ani.png = L"CS_CaveStoryMod";
	ani.sprite_index = L"ls_rollrock_l";
	ani.image_index = 0;
	hp_max = hp = 2;
	damage_reset_counter = 60;
	attackState_reset_counter_max = 60;
	speedDir = true;

	slopeLow_cos60 = 0.5f;
	slopeHigh_cos45 = sqrtf(2) / 2.0f;
}

void CS_Enemy_RollRock::Init(std::weak_ptr<Entity> self)
{
	stateGravity.Init(shared_from_this());
	stateGravity.SetPhysice(false);
	stateSplash.Init(shared_from_this());
	Entity::Init(self);
}

void CS_Enemy_RollRock::Step()
{
	//跟上移动平台
	Entity::BeginMovingPlatform();
	//阻力
	if (cbRect.cbBottom)
	{
		if (abs(vx) < 0.01f)
			vx = 0;
		//地面阻力
		vx /= 1.005f;
	}
	//重力
	stateGravity.SetPhysice(cbRect.inWater);
	stateGravity.Step();
	stateSplash.Step();
	//撞墙会反向移动
	if (cbRect.cbLeft)
		vx = abs(lastHSpeed) / 2;
	if (cbRect.cbRight)
		vx = -abs(lastHSpeed) / 2;
	//斜坡改变速度
	//在矮斜坡上
	bool bOnSlopeLow_l = cbRect.pxaBottom == 0x7 ||
		cbRect.pxaBottom == 0x8 ||
		cbRect.pxaBottom == 0x17 ||
		cbRect.pxaBottom == 0x18;
	bool bOnSlopeLow_r = cbRect.pxaBottom == 0x9 ||
		cbRect.pxaBottom == 0xa ||
		cbRect.pxaBottom == 0x19 ||
		cbRect.pxaBottom == 0x1a;
	//在高斜坡上
	bool bOnSlopeHigh_l = cbRect.pxaBottom == 0xd ||
		cbRect.pxaBottom == 0x1d;
	bool bOnSlopeHigh_r = cbRect.pxaBottom == 0xe ||
		cbRect.pxaBottom == 0x1e;
	int SlopeDir = 0;//斜坡方向
	if (bOnSlopeLow_l || bOnSlopeHigh_l)
		SlopeDir = 0;
	else if(bOnSlopeLow_r || bOnSlopeHigh_r)
		SlopeDir = 1;

	float maxspeed = stateGravity.GetMaxFallSpeed();
	//计算重力加速度
	float acc = stateGravity.GetGravityDefault();
	if (bOnSlopeLow_l || bOnSlopeLow_r)
		acc = stateGravity.GetGravityDefault() * slopeLow_cos60;
	else if (bOnSlopeHigh_l || bOnSlopeHigh_r)
		acc = stateGravity.GetGravityDefault() * slopeHigh_cos45;
	else
		acc = 0;
	if (SlopeDir == 0)
		acc = abs(acc);
	else
		acc = -abs(acc);
	//限制最大速度
	if (cbRect.cbBottom)
	{
		if (acc > 0)
		{
			if (vx + acc < maxspeed)
				vx += acc;
		}
		else
		{
			if (vx + acc > -maxspeed)
				vx += acc;
		}
	}
	//速度改变朝向
	if (vx > 0)
		lr = 1;
	else
		lr = 0;
	//速度改变动画
	ani.image_counter_speed = 2 * abs(vx) / (0x4ff / ts);
	ani.sprite_index = lr == 0 ? L"ls_rollrock_l" : L"ls_rollrock_r";
	lastHSpeed = vx;
	//跟上移动平台
	Entity::EndMovingPlatform();
	//清除最后一次碰撞结果
	Entity::ClearCollisionResult();
	//执行运动
	Entity::Step();
	//执行碰撞
	Entity::Collision();
	//维持在斜坡上
	Entity::KeepOnSlopes();
	//攻击状态
	attackState = !(abs(vx) < 0.2f && abs(vy) < 0.2f);
}

void CS_Enemy_RollRock::SetState(int stateID, int lr)
{
	this->lr = lr;
	ani.sprite_index = lr == 0 ? L"ls_rollrock_l" : L"ls_rollrock_r";
}

void CS_Enemy_RollRock::Attack(std::weak_ptr<Entity> dst, int* outDamage, float* outAngle, bool* outTakedown, int* outElemType, float* outShockForce, float* outHeavy)
{
	*outDamage = 2;
	*outAngle = lr == 0 ? 180.0f : 0;
	*outTakedown = false;
	*outElemType = 0;
	*outShockForce = 0x400 / ts;
	*outHeavy = 30;//僵直时间
}

void CS_Enemy_RollRock::AttackEffectObject(std::weak_ptr<Entity> target, float centerX, float centerY, int realDamage)
{
	if (lr == 0)
	{
		SetPeSpark(shared_from_this(), centerX, centerY, 1, 3, 180);
		SetPeSpark(shared_from_this(), centerX, centerY, 0, 2, 0);
	}
	else
	{
		SetPeSpark(shared_from_this(), centerX, centerY, 1, 3, 0);
		SetPeSpark(shared_from_this(), centerX, centerY, 0, 2, 180);
	}
}

bool CS_Enemy_RollRock::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;
	*outRealDamage = getDamage;
	shock_counter = 30;
	hp -= getDamage;
	if (hp > 0)
	{
		gameFunc->PlaySound(L"CS_104");
	}
	else
	{
		auto wsrc = src.lock();
		int srcType = wsrc->type;
		auto wattackParent = wsrc->attackParent.lock();
		if (wattackParent)
			srcType = wattackParent->type;
		if (srcType == 1)
		{
			gameFunc->PlaySound(L"CS_071_little_crash");
		}
		//创建云团
		SetCS_PeSmokeSmall(shared_from_this(), x, y);
		hp = 0;
		Destroy();
	}
	//伤害冲击处理
	if (shockForce > 0)
	{
		//被攻击弹反
		float radian = angle * deg2rad;
		vx = shockForce * cosf(radian);
		vy = shockForce * sinf(radian);
		vy -= 1;
	}
	//显示伤害值
	if (gameFunc->dmgNum)
		gameFunc->SetDmgNum(gameFunc->dmgNum, getDamage, x, y - 16, 0, shared_from_this());
	return true;
}

std::shared_ptr<Entity> CreateCS_Enemy_RollRock()
{
	return std::make_shared<CS_Enemy_RollRock>();
}
