#include "CS_Enemy_Ant.h"
#include "CS_PeSmoke.h"
#include "CS_Exp.h"
class RedAntAttack :
	public Entity
{
public:
	RedAntAttack(std::shared_ptr<Entity> parent)
	{
		attackParent = parent;
		type = 2;
		damage_reset_counter = 60;
		attackState_reset_counter_max = 60;
	}
	void Attack(std::weak_ptr<Entity> dst, int* outDamage, float* outAngle, bool* outTakedown, int* outElemType, float* outShockForce, float* outHeavy) override
	{
		*outDamage = 2;
		*outAngle = 0;
		*outTakedown = false;
		*outElemType = 0;
		*outShockForce = 0;
		*outHeavy = 1;
	}
};


CS_Enemy_Ant::CS_Enemy_Ant()
{
	type = 2;
	ani.png = L"CS_CaveStoryMod";
	//启用碰撞
	cbRect.enableCbRect = true;
	cbRect.enableSoild = true;
	//设置碰撞框
	cbRect.left = cbRect.right = 6;
	cbRect.top = 0;
	cbRect.bottom = 8;
	StateFunc = &CS_Enemy_Ant::StateMove;
	(this->*StateFunc)();
	//设置初始物理
	SetPhysice(false);
	gravity = gravity_default;
	//设置属性
	hp = 5;
	dropExp = 3;
}

void CS_Enemy_Ant::Init(std::weak_ptr<Entity> self)
{
	auto watkEntity = std::make_shared<RedAntAttack>(shared_from_this());
	atkEntity = watkEntity;
	gameFunc->SetEntity(shared_from_this(), watkEntity);
	stateSplash.Init(shared_from_this());
	Entity::Init(self);
}

void CS_Enemy_Ant::Step()
{
	//执行重力
	if (!attachWall)
	{
		StepGravity();
		stateSplash.Step();
	}
	//执行控制
	StepControl();
	//执行动画
	(this->*StateFunc)();
	//阻力
	if (cbRect.cbBottom)
		vx /= 2.0f;
	if (attachWall)
	{
		vx = 0;
		vy = 0;
	}
	//清除最后一次碰撞结果
	Entity::ClearCollisionResult();
	//执行运动
	Entity::Step();
	//执行碰撞
	Entity::Collision();
	//攻击区域绑定
	auto watkEntity = atkEntity.lock();
	if (watkEntity)
	{
		watkEntity->x = x;
		watkEntity->y = y;
	}
	if (attachWall)
	{
		vx = x - lastX;
		vy = y - lastY;
	}
	lastX = x;
	lastY = y;
}

void CS_Enemy_Ant::SetState(int stateID, int lr)
{
	this->lr = lr;
	ani.sprite_index = lr == 0 ? L"ls_ant_walk0_l" : L"ls_ant_walk0_r";
}

bool CS_Enemy_Ant::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_055_enemy_squeak2");
	}
	else
	{
		gameFunc->PlaySound(L"CS_071_little_crash");
		//创建云团
		SetCS_PeSmokeSmall(shared_from_this(), x, y);
		hp = 0;
		//掉落物品
		SetDropItem(shared_from_this(), x, y, dropExp);
		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());
	//面对被攻击方向
	auto wsrc = src.lock();
	if (wsrc)
	{
		lr = wsrc->lr == 0 ? 1 : 0;
	}
	//状态转换
	attachWall = false;
	disableAttachWallCounter = 120;
	StateFunc = &CS_Enemy_Ant::StateFall;
	//关闭攻击区
	auto watkEntity = atkEntity.lock();
	if (watkEntity)
	{
		watkEntity->attackState = false;
		watkEntity->damage_reset_counter = -1;
		watkEntity->attackState_reset_counter_max = -1;
	}
	return true;
}

void CS_Enemy_Ant::Destroy()
{
	auto watkEntity = atkEntity.lock();
	if (watkEntity)
		watkEntity->Destroy();
	ActionEntity::Destroy();
}

void CS_Enemy_Ant::SetPhysice(bool bInWater)
{
	if (cbRect.inWater)
	{
		gravity_default = inwater_gravity_default;
		max_fall_speed = inwater_max_fall_speed;
		move = inwater_move;
	}
	else
	{
		gravity_default = ground_gravity_default;
		max_fall_speed = ground_max_fall_speed;
		move = ground_move;
	}
}

void CS_Enemy_Ant::StepControl()
{
	//尝试吸附到墙上
	if (!attachWall &&
		disableAttachWallCounter == 0 &&
		struggleCounter == 0)
	{
		do
		{
			float srcX = x;
			float srcY = y;
			int lastDir = dir;
			if (lr == 0)
			{
				if (cbRect.bottom)
				{
					y += 1;
					srcY = y;
				}
				//检查底下是否有墙
				y += 2;
				dir = 0;
				SetEntityRect(dir);
				Entity::ClearCollisionResult();
				Entity::Collision();
				if (cbRect.cbBottom)
				{
					attachWall = true;
					vx = vy = 0;
					break;
				}
				else
				{
					x = srcX;
					y = srcY;
					dir = lastDir;
					SetEntityRect(dir);
				}
				//检查右边是否有墙
				x += 2;
				dir = 1;
				SetEntityRect(dir);
				Entity::ClearCollisionResult();
				Entity::Collision();
				if (cbRect.cbRight)
				{
					attachWall = true;
					vx = vy = 0;
					break;
				}
				else
				{
					x = srcX;
					y = srcY;
					dir = lastDir;
					SetEntityRect(dir);
				}
				//检查左边是否有墙
				x -= 2;
				dir = 3;
				SetEntityRect(dir);
				Entity::ClearCollisionResult();
				Entity::Collision();
				if (cbRect.cbLeft)
				{
					attachWall = true;
					vx = vy = 0;
					break;
				}
				else
				{
					x = srcX;
					y = srcY;
					dir = lastDir;
					SetEntityRect(dir);
				}
				//检查顶上是否有墙
				y -= 2;
				dir = 2;
				SetEntityRect(dir);
				Entity::ClearCollisionResult();
				Entity::Collision();
				if (cbRect.cbTop)
				{
					attachWall = true;
					vx = vy = 0;
					break;
				}
				else
				{
					x = srcX;
					y = srcY;
					dir = lastDir;
					SetEntityRect(dir);
				}
			}
			else
			{
				if (cbRect.bottom)
				{
					y += 1;
					srcY = y;
				}
				//检查底下是否有墙
				y += 2;
				dir = 0;
				SetEntityRect(dir);
				Entity::ClearCollisionResult();
				Entity::Collision();
				if (cbRect.cbBottom)
				{
					attachWall = true;
					vx = vy = 0;
					break;
				}
				else
				{
					x = srcX;
					y = srcY;
					dir = lastDir;
					SetEntityRect(dir);
				}
				//检查右边是否有墙
				x += 2;
				dir = 3;
				SetEntityRect(dir);
				Entity::ClearCollisionResult();
				Entity::Collision();
				if (cbRect.cbRight)
				{
					attachWall = true;
					vx = vy = 0;
					break;
				}
				else
				{
					x = srcX;
					y = srcY;
					dir = lastDir;
					SetEntityRect(dir);
				}
				//检查左边是否有墙
				x -= 2;
				dir = 1;
				SetEntityRect(dir);
				Entity::ClearCollisionResult();
				Entity::Collision();
				if (cbRect.cbLeft)
				{
					attachWall = true;
					vx = vy = 0;
					break;
				}
				else
				{
					x = srcX;
					y = srcY;
					dir = lastDir;
					SetEntityRect(dir);
				}
				//检查顶上是否有墙
				y -= 2;
				dir = 2;
				SetEntityRect(dir);
				Entity::ClearCollisionResult();
				Entity::Collision();
				if (cbRect.cbTop)
				{
					attachWall = true;
					vx = vy = 0;
					break;
				}
				else
				{
					x = srcX;
					y = srcY;
					dir = lastDir;
					SetEntityRect(dir);
				}
			}
		} while (false);
	}
	//吸附墙移动
	if (attachWall)
	{
		float lastX = x, lastY = y;
		int lastDir = dir;
		if (lr == 0)
		{
			switch (dir)
			{
			case 0://左
				//转向下
				x += 2;
				y += 2;
				Entity::ClearCollisionResult();
				Entity::Collision();
				if (cbRect.cbBottom)
				{
					//复原
					x = lastX;
					y = lastY;
					x -= 2;
					y += 2;
					Entity::ClearCollisionResult();
					Entity::Collision();
					if (!cbRect.cbBottom)
					{
						dir = 1;
						SetEntityRect(dir);
						x = floorf(x / 16.0f) * 16.0f + 8;
						break;
					}
				}
				//复原
				x = lastX;
				y = lastY;
				//转向上
				x += -move;
				dir = 3;
				SetEntityRect(dir);
				Entity::ClearCollisionResult();
				Entity::Collision();
				if (!cbRect.cbLeft)
				{
					x = lastX;
					y = lastY;
					x += -move;
					dir = lastDir;
					SetEntityRect(dir);
					Entity::ClearCollisionResult();
					Entity::Collision();
				}
				break;
			case 1://下
				//转向右
				x += 2;
				y -= 2;
				Entity::ClearCollisionResult();
				Entity::Collision();
				if (cbRect.cbRight)
				{
					//复原
					x = lastX;
					y = lastY;
					x += 2;
					Entity::ClearCollisionResult();
					Entity::Collision();
					if (!cbRect.cbRight)
					{
						dir = 2;
						SetEntityRect(dir);
						x += 8;
						Entity::ClearCollisionResult();
						Entity::Collision();
						break;
					}
				}
				//复原
				x = lastX;
				y = lastY;
				//转向左
				y += move;
				dir = 0;
				SetEntityRect(dir);
				Entity::ClearCollisionResult();
				Entity::Collision();
				if (!cbRect.cbBottom)
				{
					x = lastX;
					y = lastY;
					y += move;
					dir = lastDir;
					SetEntityRect(dir);
					Entity::ClearCollisionResult();
					Entity::Collision();
				}
				break;
			case 2://右
				//转向上
				x -= 2;
				y -= 6;
				Entity::ClearCollisionResult();
				Entity::Collision();
				if (cbRect.cbTop)
				{
					//复原
					x = lastX;
					y = lastY;
					x += 2;
					y -= 6;
					Entity::ClearCollisionResult();
					Entity::Collision();
					if (!cbRect.cbTop)
					{
						dir = 3;
						SetEntityRect(dir);
						break;
					}
				}
				//复原
				x = lastX;
				y = lastY;
				//转向下
				x += move;
				dir = 1;
				SetEntityRect(dir);
				Entity::ClearCollisionResult();
				Entity::Collision();
				if (!cbRect.cbRight)
				{
					x = lastX;
					y = lastY;
					x += move;
					dir = lastDir;
					SetEntityRect(dir);
					while (!cbRect.cbTop)
					{
						y += -move;
						Entity::ClearCollisionResult();
						Entity::Collision();
					}
				}
				break;
			case 3://上
				//转向左
				x -= 2;
				y += 2;
				Entity::ClearCollisionResult();
				Entity::Collision();
				if (cbRect.cbLeft)
				{
					//复原
					x = lastX;
					y = lastY;
					x -= 2;
					y -= 2;
					Entity::ClearCollisionResult();
					Entity::Collision();
					if (!cbRect.cbLeft)
					{
						dir = 0;
						SetEntityRect(dir);
						x -= 8;
						Entity::ClearCollisionResult();
						Entity::Collision();
						break;
					}
				}
				//复原
				x = lastX;
				y = lastY;
				//转向右
				y += -move;
				dir = 2;
				SetEntityRect(dir);
				Entity::ClearCollisionResult();
				Entity::Collision();
				if (!cbRect.cbTop)
				{
					dir = lastDir;
					SetEntityRect(dir);
					x = lastX;
					y = lastY;
					float ly = y;
					float dy = 1;
					while (ly == y)
					{
						y += -move * dy;
						Entity::ClearCollisionResult();
						Entity::Collision();
						dy++;
					}
				}
				break;
			}
		}
		else
		{
			switch (dir)
			{
			case 0://右
				//转向下
				x -= 2;
				y += 2;
				Entity::ClearCollisionResult();
				Entity::Collision();
				if (cbRect.cbBottom)
				{
					//复原
					x = lastX;
					y = lastY;
					x += 2;
					y += 2;
					Entity::ClearCollisionResult();
					Entity::Collision();
					if (!cbRect.cbBottom)
					{
						dir = 1;
						SetEntityRect(dir);
						x = floorf(x / 16.0f) * 16.0f + 8;
						break;
					}
				}
				//复原
				x = lastX;
				y = lastY;
				//转向上
				x += move;
				dir = 3;
				SetEntityRect(dir);
				Entity::ClearCollisionResult();
				Entity::Collision();
				if (!cbRect.cbRight)
				{
					x = lastX;
					y = lastY;
					x += move;
					dir = lastDir;
					SetEntityRect(dir);
					Entity::ClearCollisionResult();
					Entity::Collision();
				}
				break;
			case 1://下
				//转向左
				x -= 2;
				y -= 2;
				Entity::ClearCollisionResult();
				Entity::Collision();
				if (cbRect.cbLeft)
				{
					//复原
					x = lastX;
					y = lastY;
					x -= 2;
					Entity::ClearCollisionResult();
					Entity::Collision();
					if (!cbRect.cbLeft)
					{
						dir = 2;
						SetEntityRect(dir);
						x -= 8;
						Entity::ClearCollisionResult();
						Entity::Collision();
						break;
					}
				}
				//复原
				x = lastX;
				y = lastY;
				//转向左
				y += move;
				dir = 0;
				SetEntityRect(dir);
				Entity::ClearCollisionResult();
				Entity::Collision();
				if (!cbRect.cbBottom)
				{
					x = lastX;
					y = lastY;
					y += move;
					dir = lastDir;
					SetEntityRect(dir);
					Entity::ClearCollisionResult();
					Entity::Collision();
				}
				break;
			case 2://左
				//转向上
				x += 2;
				y -= 6;
				Entity::ClearCollisionResult();
				Entity::Collision();
				if (cbRect.cbTop)
				{
					//复原
					x = lastX;
					y = lastY;
					x -= 2;
					y -= 6;
					Entity::ClearCollisionResult();
					Entity::Collision();
					if (!cbRect.cbTop)
					{
						dir = 3;
						SetEntityRect(dir);
						break;
					}
				}
				//复原
				x = lastX;
				y = lastY;
				//转向下
				x -= move;
				dir = 1;
				SetEntityRect(dir);
				Entity::ClearCollisionResult();
				Entity::Collision();
				if (!cbRect.cbLeft)
				{
					x = lastX;
					y = lastY;
					x -= move;
					dir = lastDir;
					SetEntityRect(dir);
					while (!cbRect.cbTop)
					{
						y += -move;
						Entity::ClearCollisionResult();
						Entity::Collision();
					}
				}
				break;
			case 3://上
				//转向右
				x += 2;
				y += 2;
				Entity::ClearCollisionResult();
				Entity::Collision();
				if (cbRect.cbRight)
				{
					//复原
					x = lastX;
					y = lastY;
					x += 2;
					y -= 2;
					Entity::ClearCollisionResult();
					Entity::Collision();
					if (!cbRect.cbRight)
					{
						dir = 0;
						SetEntityRect(dir);
						x += 8;
						Entity::ClearCollisionResult();
						Entity::Collision();
						break;
					}
				}
				//复原
				x = lastX;
				y = lastY;
				//转向右
				y += -move;
				dir = 2;
				SetEntityRect(dir);
				Entity::ClearCollisionResult();
				Entity::Collision();
				if (!cbRect.cbTop)
				{
					dir = lastDir;
					SetEntityRect(dir);
					x = lastX;
					y = lastY;
					float ly = y;
					float dy = 1;
					while (ly == y)
					{
						y += -move * dy;
						Entity::ClearCollisionResult();
						Entity::Collision();
						dy++;
					}
				}
				break;
			}
		}
	}
}

void CS_Enemy_Ant::StepGravity()
{
	vy += gravity;
	//限制下落速度
	if (vy > max_fall_speed)
		vy = max_fall_speed;
}

void CS_Enemy_Ant::SetEntityRect(int dir)
{
	auto watkEntity = atkEntity.lock();
	//左
	if (lr == 0)
	{
		switch (dir)
		{
		case 0:
			cbRect.left = cbRect.right = 7;
			cbRect.top = 4;
			cbRect.bottom = 8;
			if (watkEntity)
			{
				watkEntity->cbRect = cbRect;
				watkEntity->cbRect.top = 0;
			}
			break;
		case 1:
			cbRect.top = cbRect.bottom = 7;
			cbRect.left = 4;
			cbRect.right = 8;
			if (watkEntity)
			{
				watkEntity->cbRect = cbRect;
				watkEntity->cbRect.left = 0;
			}
			break;
		case 2:
			cbRect.left = cbRect.right = 7;
			cbRect.top = 8;
			cbRect.bottom = 4;
			if (watkEntity)
			{
				watkEntity->cbRect = cbRect;
				watkEntity->cbRect.bottom = 0;
			}
			break;
		case 3:
			cbRect.top = cbRect.bottom = 7;
			cbRect.left = 8;
			cbRect.right = 4;
			if (watkEntity)
			{
				watkEntity->cbRect = cbRect;
				watkEntity->cbRect.right = 0;
			}
			break;
		}
	}
	//右
	else
	{
		switch (dir)
		{
		case 0:
			cbRect.left = cbRect.right = 7;
			cbRect.top = 4;
			cbRect.bottom = 8;
			if (watkEntity)
			{
				watkEntity->cbRect = cbRect;
				watkEntity->cbRect.top = 0;
			}
			break;
		case 1:
			cbRect.top = cbRect.bottom = 7;
			cbRect.left = 8;
			cbRect.right = 4;
			if (watkEntity)
			{
				watkEntity->cbRect = cbRect;
				watkEntity->cbRect.right = 0;
			}
			break;
		case 2:
			cbRect.left = cbRect.right = 7;
			cbRect.top = 8;
			cbRect.bottom = 4;
			if (watkEntity)
			{
				watkEntity->cbRect = cbRect;
				watkEntity->cbRect.bottom = 0;
			}
			break;
		case 3:
			cbRect.top = cbRect.bottom = 7;
			cbRect.left = 4;
			cbRect.right = 8;
			if (watkEntity)
			{
				watkEntity->cbRect = cbRect;
				watkEntity->cbRect.left = 0;
			}
			break;
		}
	}
}

void CS_Enemy_Ant::StateMove()
{
	const wchar_t* move = L"";
	switch (dir)
	{
	case 0:
		move = lr == 0 ? L"ls_ant_walk0_l" : L"ls_ant_walk0_r";
		break;
	case 1:
		move = lr == 0 ? L"ls_ant_walk1_l" : L"ls_ant_walk1_r";
		break;
	case 2:
		move = lr == 0 ? L"ls_ant_walk2_l" : L"ls_ant_walk2_r";
		break;
	case 3:
		move = lr == 0 ? L"ls_ant_walk3_l" : L"ls_ant_walk3_r";
		break;
	}
	ani.sprite_index = move;
}

void CS_Enemy_Ant::StateFall()
{
	const wchar_t* fall = L"";
	fall = lr == 0 ? L"ls_ant_fall_l" : L"ls_ant_fall_r";
	ani.sprite_index = fall;
	cbRect.left = cbRect.right = 7;
	cbRect.top = 6;
	cbRect.bottom = 5;
	if (cbRect.cbBottom && disableAttachWallCounter > 0)
		disableAttachWallCounter--;
	if (disableAttachWallCounter == 0)
	{
		struggleCounter = 120;
		StateFunc = &CS_Enemy_Ant::StateStruggle;
	}
}

void CS_Enemy_Ant::StateStruggle()
{
	const wchar_t* fall = L"";
	fall = lr == 0 ? L"ls_ant_struggle_l" : L"ls_ant_struggle_r";
	ani.sprite_index = fall;
	cbRect.left = cbRect.right = 7;
	cbRect.top = 6;
	cbRect.bottom = 5;
	if (struggleCounter > 0)
		struggleCounter--;
	if (struggleCounter == 0)
	{
		StateFunc = &CS_Enemy_Ant::StateMove;
		attachWall = false;
		dir = 0;
		SetEntityRect(dir);
		Entity::ClearCollisionResult();
		Entity::Collision();
		//启用攻击区
		auto watkEntity = atkEntity.lock();
		if (watkEntity)
		{
			watkEntity->attackState = true;
			watkEntity->damage_reset_counter = 60;
			watkEntity->attackState_reset_counter_max = 60;
		}
	}
}

std::shared_ptr<Entity> CreateCS_Enemy_Ant()
{
	return std::make_shared<CS_Enemy_Ant>();
}
