local BattleConst = require "app/module/battle/battle_const"
local BattleHelper = require "app/module/battle/helper/battle_helper"
local BattleBuffHandle = require "app/module/battle/helper/battle_buff_handle"
local BATTLE_BOARD_SKILL_HANDLE = require "app/module/battle/skill/battle_board_skill_handle"
local BATTLE_SKILL_CONDITION_HANDLE = require "app/module/battle/helper/battle_skill_condition_handle"
local BattleFormula = require "app/module/battle/helper/battle_formula"
local BattlePassive = require "app/module/battle/helper/battle_passive"

local BattleUnitComp = class("BattleUnitComp", LuaComponent)

local UNIT_STATE = BattleConst.UNIT_STATE
local SIDE_ATK = BattleConst.SIDE_ATK
local SPINE_ANIMATION_NAME = BattleConst.SPINE_ANIMATION_NAME
local DEFAULT_FACTOR = BattleConst.DEFAULT_FACTOR
local PASSIVE_EVENT = BattleConst.PASSIVE_EVENT
local HURT_STATE_CRIT = BattleConst.HURT_STATE_CRIT
local EFFECT_TYPE = BattleConst.EFFECT_TYPE
local TIME_FACTOR = BattleConst.TIME_FACTOR
local HURT_ANI_NAME_LIST = {SPINE_ANIMATION_NAME.HIT, SPINE_ANIMATION_NAME.HIT_2}

function BattleUnitComp:ctor()
	self.hurtNameList = {}
end

function BattleUnitComp:initPosition()
	if self.unitEntity:getSide() == SIDE_ATK then
		self.baseObject:setLocalPosition(-BattleConst.INIT_POS_X, 0, 0)
		self.body:setLocalScaleX(1)
		self.direction = 1
	else
		self.baseObject:setLocalPosition(BattleConst.INIT_POS_X, 0, 0)
		self.body:setLocalScaleX(-1)
		self.direction = -1
	end
	self.isOutside = false
end

function BattleUnitComp:playBorn()
	self:changeState(UNIT_STATE.IDLE)
end

function BattleUnitComp:playSwitchIn()
	self.baseObject:getTransform():SetAsLastSibling()
	self:changeState(UNIT_STATE.SWITCH_IN)
end

function BattleUnitComp:playSwitchOut()
	self:changeState(UNIT_STATE.SWITCH_OUT)
end

function BattleUnitComp:getModelId()
	return self.modelId
end

function BattleUnitComp:getMatchType()
	return self.unitEntity:getMatchType()
end

function BattleUnitComp:getIsBoss()
	return self.unitEntity:getIsBoss()
end

function BattleUnitComp:getIsLimit()
	return self.unitEntity:getIsLimit()
end

function BattleUnitComp:getIsLethargy()
	return self.unitEntity:getIsLethargy()
end

function BattleUnitComp:getIsStun()
	return self.unitEntity:getIsStun()
end

function BattleUnitComp:getIsFrozen()
	return self.unitEntity:getIsFrozen()
end

function BattleUnitComp:getActiveSkillLimit()
	return self.unitEntity:getActiveSkillLimit()
end

function BattleUnitComp:setTeam(team)
	self.team = team
end

function BattleUnitComp:_initBase()
	self.isClear = false
	self.isMove = false
	self.deadTime = 0
	self.attackTime = 0
	self.skillSlowDownTime = nil	 	-- 开始攻击后，x秒后开始子弹时间
	self.skillSlowDownDuration = 0	 	-- 子弹时间持续的时间
	self.skillSlowDownScale = 1	 		-- 子弹时间减慢的倍率
	self.currAttackDuration = 0
	self.currAttackKeyTime = 0
	self.currAttackBlockIndex = 0		-- 多段伤害索引
	self.validEffectIdx = {}
	self.switchTime = 0
	self.isPlayingSubAni = false
	self.playSubAniDuration = {}
	self.attackDurationMap = {}
	self.attackKeyFrameTimeMap = {}
	self.shieldBuffList = {}
	self.loopFxMap = {}
	self.activeSkillIndex = nil
	self.currActiveSkill = nil
	self.targetX = nil
	self.assistingDmgAddition = 0
	self.attackCount = 0
	self.currState = UNIT_STATE.INIT
	self.isOutside = false
end

function BattleUnitComp:initWithEntity(modelId, entity, battleController, target)
	self.modelId = modelId
	self.unitEntity = entity
	self.battleController = battleController
	self.target = target
	self.body = self.baseObject:getChildByName("body")
	self.side = entity:getSide()
	self:_initBase()
	self:initPosition()
	self:initPassiveSkills()
	self:playBorn()
	self:initHitAniInfo()
end

function BattleUnitComp:getSide()
	return self.side
end

function BattleUnitComp:initHitAniInfo()
	self.hurtAniNameList = {}
	self.hurtAniNameCount = 0
	for _, name in ipairs(HURT_ANI_NAME_LIST) do
		local duration = self:getAnimationDuration(name)
		if duration > 0 then
			table.insert(self.hurtAniNameList, name)
			self.hurtAniNameCount = self.hurtAniNameCount + 1
		end
	end
end

function BattleUnitComp:prepare()
	self:checkPassiveEvent(PASSIVE_EVENT.ON_UNIT_PREPARE_OVER, self)
	self:checkPassiveEvent(PASSIVE_EVENT.HP_LOWER_THAN, nil, self.unitEntity:getHpPercent())
end

function BattleUnitComp:resetBeforeAttack()
	self.attackCount = 0
	self.baseObject:getTransform():SetAsLastSibling()
end

function BattleUnitComp:initPassiveSkills()
	local pasSkills = self.unitEntity:getPassiveSkills()
	if pasSkills and #pasSkills > 0 then
		if self.passiveSkills == nil then
			self.passiveSkills = {}
		else
			self:removeAllPassiveSkills()
		end
		for k, skill in ipairs(pasSkills) do
			local id = skill:getPassiveTriggerId()
			if id then
				skill:clearRecordData()
				local skills = self.passiveSkills[id]
				if skills == nil then
					skills = {}
					self.passiveSkills[id] = skills
				end
				table.insert(skills, skill)
			end
		end
	end
end

function BattleUnitComp:addPassiveSkill(pasSkill)
	pasSkill:clearRecordData()
	if self.passiveSkills == nil then
		self.passiveSkills = {}
	end
	local id = pasSkill:getPassiveTriggerId()
	if id then
		local skills = self.passiveSkills[id]
		if skills == nil then
			skills = {}
			self.passiveSkills[id] = skills
		end
		table.insert(skills, pasSkill)
	end
end

function BattleUnitComp:removePassiveSkill(skill)
	if self.passiveSkills == nil then
		return
	end
	local id = skill:getPassiveTriggerId()
	if id then
		local skills = self.passiveSkills[id]
		if skills then
			for k, v in ipairs(skills) do
				if v == skill then
					table.remove(skills, k)
					break
				end
			end
		end
	end
end

function BattleUnitComp:removeAllPassiveSkills()
	if self.passiveSkills then
		for _, skills in pairs(self.passiveSkills) do
			local count = #skills
			for i = 1, count do
				table.remove(skills)
			end
		end
	end
end

function BattleUnitComp:addSkill(skillId)
	local skillEntity = self.unitEntity:addSkill(skillId)
	if skillEntity then
		if skillEntity:getIsPassiveType() then -- 添加被动
			self:addPassiveSkill(skillEntity)
		end
		return skillEntity:getSid()
	end
	return 0
end

function BattleUnitComp:removeSkill(skillId, sid)
	local skillEntity = self.unitEntity:removeSkill(skillId, sid)
	if skillEntity and skillEntity:getIsPassiveType() then
		self:removePassiveSkill(skillEntity)
	end
end

function BattleUnitComp:hideOutsideScreen()
	if self.unitEntity:getSide() == SIDE_ATK then
		self.baseObject:setLocalPosition(-GConst.UI_SCREEN_WIDTH/2 - BattleConst.UNIT_BODY_WIDTH, 0, 0)
	else
		self.baseObject:setLocalPosition(GConst.UI_SCREEN_WIDTH/2 + BattleConst.UNIT_BODY_WIDTH, 0, 0)
	end
	self.isOutside = true
end

function BattleUnitComp:playRunAction()
	self:playAnimation(SPINE_ANIMATION_NAME.MOVE, true)
end

function BattleUnitComp:stopRunAction()
	self:playAnimation(SPINE_ANIMATION_NAME.IDLE, true)
end

function BattleUnitComp:playAnimation(name, loop, forceRefresh)
	if name == self.curHurtName or name == SPINE_ANIMATION_NAME.BLOCK then
		self.isPlayingSubAni = true
	end
	self.currAnimationName = name
	self.baseObject:playAnimation(name, loop, forceRefresh)
end

function BattleUnitComp:getAnimationDuration(aniName)
	local duration = self.attackDurationMap[aniName]
	if duration == nil then
		duration = self.baseObject:getAnimationDuration(aniName)
		self.attackDurationMap[aniName] = duration
	end
	return duration or 0
end

function BattleUnitComp:getAnimationKeyFrameTime(animationName, index)
	index = index or 1
	local timeList = self.attackKeyFrameTimeMap[animationName]
	if timeList == nil then
		timeList = self.baseObject:getAnimationKeyFrameTimes(animationName)
		if not timeList[1] then
			table.insert(timeList, 0.3)
		end
		self.attackKeyFrameTimeMap[animationName] = timeList
	end
	return timeList[index] or 0.3
end

function BattleUnitComp:getKeyFrameTime(skill, blockIndex, animationName)
	if not skill then
		return 0
	end

	self.currAttackBlockIndex = blockIndex
	local time = 0
	local blockList = skill:getEffectBlock()
	if blockList[blockIndex] then
		local beforeIndex = blockIndex - 1
		self.validEffectIdx[1] = blockList[beforeIndex] or 0
		self.validEffectIdx[2] = blockList[blockIndex] or 1
		time = skill:getEffectBlockTime()[blockIndex]
		if not time then
			time = self:getAnimationKeyFrameTime(animationName, blockIndex)
		end
	end

	return time
end

function BattleUnitComp:getIsCentralizedAttack()
	return self.team:getCentralizedAttack()
end

function BattleUnitComp:getIsFinalBlock()
	return self.team:getIsFinalBlock()
end

function BattleUnitComp:getCurAttackActionState()
	return self.curAttackActionState
end

function BattleUnitComp:getHurtComboTag()
	return self.team:getHurtComboTag(self:getMatchType())
end

function BattleUnitComp:beforeAttack(actionState)
	self.team:setCentralizedAttack(true)
	self.team:setIsFinalBlock(false)
	self.battleController:setIsPauseHpProgress(true)
	self.curAttackActionState = actionState
	if actionState == BattleConst.ATTACK_ACTION_STATE.NORMAL then
		self:checkPassiveEvent(PASSIVE_EVENT.ON_UNI_ATTACK_START, self)
	end
end

-- function BattleUnitComp:useAssistingSkill(count, delay, callback)
-- 	local skill = self.unitEntity:getAssistingSkill()
-- 	if skill == nil then
-- 		callback()
-- 		return
-- 	end
-- 	local attrName = GConst.MATCH_ATTACK_NAME[self:getMatchType()]
-- 	self.assistingDmgAddition = count - 1
-- 	if self.assistingDmgAddition <= 0 then
-- 		self.assistingDmgAddition = 0
-- 		self.assistingDmgAddCount = 0
-- 	else
-- 		self.assistingDmgAddCount = self.unitEntity:addAttr(attrName, self.assistingDmgAddition*DEFAULT_FACTOR, true)
-- 	end
-- 	self.actionOverCallback = callback
-- 	if delay > 0 then
-- 		self.waitTime = delay
-- 		self.waitingState = UNIT_STATE.ASSISTING_ATTACK
-- 		if not self:changeState(UNIT_STATE.WAIT) then
-- 			if not self:changeState(UNIT_STATE.ASSISTING_ATTACK) then
-- 				self.actionOverCallback = nil
-- 				self.unitEntity:addAttr(attrName, -self.assistingDmgAddCount, false)
-- 				callback()
-- 			end
-- 		end
-- 	else
-- 		if not self:changeState(UNIT_STATE.ASSISTING_ATTACK) then
-- 			self.actionOverCallback = nil
-- 			self.unitEntity:addAttr(attrName, -self.assistingDmgAddCount, false)
-- 			callback()
-- 		end
-- 	end
-- end

function BattleUnitComp:useSkill(index, count, callback)
	self.unitEntity:addActiveSkillReleaseCount(1)

	self.actionOverCallback = callback
	self.activeSkillIndex = nil
	self.currActiveSkill = self.unitEntity:getAvailableActiveSkill(index)
	if self:getActiveSkillLimit() then
		self.currActiveSkill = nil
	end
	if count <= 0 then
		self.normalSkillCount = 0
	else
		self.normalSkillCount = count + self.unitEntity:getNormalAttackAddCount()
	end
	if self.currActiveSkill == nil then -- 没有技能就用普攻
		if self.normalSkillCount <= 0 then
			self.actionOverCallback = nil
			self.battleController:setIsPauseHpProgress(false)
			self.team:setCentralizedAttack(false)
			callback()
			return false
		end
		if self.isOutside then
			self:playSwitchIn()
		else
			if not self:changeState(UNIT_STATE.NORMAL_ATTACK) then
				self.actionOverCallback = nil
				self.battleController:setIsPauseHpProgress(false)
				self.team:setCentralizedAttack(false)
				callback()
				return false
			end
		end
	else
		if self.isOutside then
			self:playSwitchIn()
		else
			if count <= 0 then
				self:checkPassiveEvent(PASSIVE_EVENT.ON_ACTIVE_SKILL_BEFORE, self)
			end
			if not self:changeState(UNIT_STATE.SKILL_ATTACK) then
				self.actionOverCallback = nil
				self.battleController:setIsPauseHpProgress(false)
				self.team:setCentralizedAttack(false)
				callback()
				return false
			end
		end
	end
	return true
end

function BattleUnitComp:useAllSkills(callback)
	self.actionOverCallback = callback
	self.normalSkillCount = self.unitEntity:getNormalSkillCount() + self.unitEntity:getNormalAttackAddCount()
	self.activeSkillIndex = 1
	self.currActiveSkill = nil
	local activeSkillCount = self.unitEntity:getActiveSkillCount()
	if self:getActiveSkillLimit() then
		activeSkillCount = 0
	end
	while self.activeSkillIndex <= activeSkillCount do
		self.currActiveSkill = self.unitEntity:getAvailableActiveSkill(self.activeSkillIndex)
		if self.currActiveSkill then
			break
		end
		self.activeSkillIndex = self.activeSkillIndex + 1
	end
	if self.currActiveSkill == nil then -- 没有技能就用普攻
		if self.normalSkillCount <= 0 then
			self.actionOverCallback = nil
			self.battleController:setIsPauseHpProgress(false)
			self.team:setCentralizedAttack(false)
			callback()
			return
		end
		if not self:changeState(UNIT_STATE.NORMAL_ATTACK) then
			self.actionOverCallback = nil
			self.battleController:setIsPauseHpProgress(false)
			self.team:setCentralizedAttack(false)
			callback()
		end
	else
		if not self:changeState(UNIT_STATE.SKILL_ATTACK) then
			self.actionOverCallback = nil
			self.battleController:setIsPauseHpProgress(false)
			self.team:setCentralizedAttack(false)
			callback()
		end
	end
end

function BattleUnitComp:useNormalSkill(count, effectType, callback)
	self.actionOverCallback = callback
	self.normalSkillCount = count
	if effectType == BattleConst.EFFECT_TYPE.DIRECT then
		self.normalSkillCount = self.normalSkillCount + self.unitEntity:getNormalAttackAddCount()
	end
	if not self:changeState(UNIT_STATE.NORMAL_ATTACK) then
		self.actionOverCallback = nil
		self.battleController:setIsPauseHpProgress(false)
		self.team:setCentralizedAttack(false)
		callback()
	end
end

function BattleUnitComp:addShield(num, buffEffect)
	self.unitEntity:addShield(num)
	self.team:addShield(buffEffect)
end

function BattleUnitComp:removeShield(buffEffect)
	if buffEffect == nil then
		return
	end
	if buffEffect.result > 0 then
		self.unitEntity:addShield(-buffEffect.result)
		buffEffect.result = 0
	end
	self.team:removeShield(buffEffect)
end

function BattleUnitComp:changeState(state)
	if self.currState == UNIT_STATE.DEAD then -- 死亡后只能去死亡状态
		if state ~= UNIT_STATE.DEAD then
			return false
		end
	end

	-- 进入目标状态
	if state == UNIT_STATE.IDLE then -- idle为默认状态，其状态下判定特殊状态
		if self:getIsFrozen() then -- 有冰冻buff
			state = UNIT_STATE.FROZEN
		elseif self:getIsLethargy() or self:getIsStun() then
			state = UNIT_STATE.VERITGO
		end
	end

	if self.currState == state and not self:repeatCurrState() then
		return false
	end

	-- 离开当前状态
	if self.currState == UNIT_STATE.IDLE then
		self:exitIdleState()
	elseif self.currState == UNIT_STATE.NORMAL_ATTACK then
		self:exitNormalAttackState()
	elseif self.currState == UNIT_STATE.SKILL_ATTACK then
		self:exitSkillAttackState()
	elseif self.currState == UNIT_STATE.ASSISTING_ATTACK then
		self:exitAssistingAttackState()
	elseif self.currState == UNIT_STATE.DEAD then
		self:exitDeadState()
	elseif self.currState == UNIT_STATE.ENTER_BATTLEFIELD then
		self:exitEnterBattlefieldState()
	elseif self.currState == UNIT_STATE.SWITCH_IN then
		self:exitSwitchInState()
	elseif self.currState == UNIT_STATE.SWITCH_OUT then
		self:exitSwitchOutState()
	elseif self.currState == UNIT_STATE.WAIT then
		self:exitWaitState()
	elseif self.currState == UNIT_STATE.RECOVER_HP_WAVE then
		self:exitRecoverHpWaveState()
	elseif self.currState == UNIT_STATE.FROZEN then
		self:exitFrozenState()
	elseif self.currState == UNIT_STATE.VERITGO then
		self:exitVeritgoState()
	end

	self.currState = state

	if state == UNIT_STATE.IDLE then
		self:enterIdleState()
	elseif state == UNIT_STATE.NORMAL_ATTACK then
		self:enterNormalAttackState()
	elseif state == UNIT_STATE.SKILL_ATTACK then
		self:enterSkillAttackState()
	elseif state == UNIT_STATE.ASSISTING_ATTACK then
		self:enterAssistingAttackState()
	elseif state == UNIT_STATE.DEAD then
		self:enterDeadState()
	elseif state == UNIT_STATE.ENTER_BATTLEFIELD then
		self:enterEnterBattlefieldState()
	elseif state == UNIT_STATE.SWITCH_IN then
		self:enterSwitchInState()
	elseif state == UNIT_STATE.SWITCH_OUT then
		self:enterSwitchOutState()
	elseif state == UNIT_STATE.WAIT then
		self:enterWaitState()
	elseif state == UNIT_STATE.RECOVER_HP_WAVE then
		self:enterRecoverHpWaveState()
	elseif state == UNIT_STATE.FROZEN then
		self:enterFrozenState()
	elseif state == UNIT_STATE.VERITGO then
		self:enterVeritgoState()
	end
	return true
end

function BattleUnitComp:repeatCurrState()
	if self.currState == UNIT_STATE.NORMAL_ATTACK then
		return true
	elseif self.currState == UNIT_STATE.SKILL_ATTACK then
		return true
	end
	return false
end

function BattleUnitComp:updateSwitchInState(dt)
	self.switchTime = self.switchTime - dt
	if self.switchTime < 0 then
		if self.actionOverCallback then
			if self.currActiveSkill then
				self:checkPassiveEvent(PASSIVE_EVENT.ON_ACTIVE_SKILL_BEFORE, self)
				if not self:changeState(UNIT_STATE.SKILL_ATTACK) then
					local callback = self.actionOverCallback
					self.actionOverCallback = nil
					self.activeSkillIndex = nil
					self.battleController:setIsPauseHpProgress(false)
					self.team:setCentralizedAttack(false)
					callback()
				end
			elseif self.normalSkillCount > 0 then
				if not self:changeState(UNIT_STATE.NORMAL_ATTACK) then
					local callback = self.actionOverCallback
					self.actionOverCallback = nil
					self.battleController:setIsPauseHpProgress(false)
					self.team:setCentralizedAttack(false)
					callback()
				end
			else
				self:changeState(UNIT_STATE.IDLE)
				local callback = self.actionOverCallback
				self.actionOverCallback = nil
				self.battleController:setIsPauseHpProgress(false)
				self.team:setCentralizedAttack(false)
				callback()
			end
		else
			self:changeState(UNIT_STATE.IDLE)
		end
	end
end

function BattleUnitComp:enterSwitchInState()
	local aniName = SPINE_ANIMATION_NAME.BORN
	self.switchTime = self:getAnimationDuration(aniName) + 0.1
	self:initPosition()
	self:playAnimation(aniName, false, true)
end

function BattleUnitComp:exitSwitchInState()
end

function BattleUnitComp:updateSwitchOutState(dt)
	self.switchTime = self.switchTime - dt
	if self.switchTime < 0 then
		self:changeState(UNIT_STATE.IDLE)
	end
end

function BattleUnitComp:enterSwitchOutState()
	local aniName = SPINE_ANIMATION_NAME.OUT
	self.switchTime = self:getAnimationDuration(aniName) + 0.1
	self:playAnimation(aniName, false, true)
end

function BattleUnitComp:exitSwitchOutState()
	self:hideOutsideScreen()
end

function BattleUnitComp:updateDead(dt)
	self.deadTime = self.deadTime - dt
	if self.deadTime <= 0 then
		self:clear()
		if self.deadOverCallback then
			local callback = self.deadOverCallback
			self.deadOverCallback = nil
			callback()
		end
	end
end

function BattleUnitComp:exitDeadState()
end

function BattleUnitComp:enterDeadState()
	self:removeAllBuff()
	local aniName = SPINE_ANIMATION_NAME.DEAD
	self.deadTime = self:getAnimationDuration(aniName) + 0.1
	self:playAnimation(aniName, false, false)
end

function BattleUnitComp:updateEnterBattlefieldState(dt)
	if self.isMove then
		local addX = dt*BattleConst.MOVE_SPEED_ENTER*self.moveDirection
		self.positionX = self.positionX + addX
		if (self.moveDirection > 0 and self.positionX >= self.targetX) or (self.moveDirection < 0 and self.positionX <= self.targetX) then
			self.isMove = false
			self.positionX = self.targetX
			self:changeState(UNIT_STATE.IDLE)
		end
		self.baseObject:setLocalPosition(self.positionX, 0, 0)
	else
		self.waitTime = self.waitTime - dt
		if self.waitTime < 0 then
			self:changeState(UNIT_STATE.IDLE)
		end
	end
end

function BattleUnitComp:exitEnterBattlefieldState()
	local callback = self.finishEnterBattlefieldCallback
	self.finishEnterBattlefieldCallback = nil
	if callback then
		callback()
	end
end

function BattleUnitComp:enterEnterBattlefieldState()
	if self.isMove then
		self:playAnimation(SPINE_ANIMATION_NAME.IDLE, true, false)
		self.positionX = self.baseObject:fastGetLocalPosition()
		if self.side == BattleConst.SIDE_ATK then
			self.targetX = -BattleConst.INIT_POS_X
			self.moveDirection = 1
		else
			self.targetX = BattleConst.INIT_POS_X
			self.moveDirection = -1
		end
		local time = math.abs(self.targetX - self.positionX)/BattleConst.MOVE_SPEED_ENTER
		self.battleController:moveBattlefield(time)
	else
		self:playAnimation(SPINE_ANIMATION_NAME.BORN, false, false)
		self.waitTime = self:getAnimationDuration(SPINE_ANIMATION_NAME.BORN)
	end
end

function BattleUnitComp:exitIdleState()
end

function BattleUnitComp:enterIdleState()
	self:refreshHpSkin()
	self:playAnimation(SPINE_ANIMATION_NAME.IDLE, true, false)
end

function BattleUnitComp:updateIdle(dt)
	self:updateIdleSubAni(dt, SPINE_ANIMATION_NAME.IDLE)
end

function BattleUnitComp:updateIdleSubAni(...)
	if not self.currAnimationName or not self.isPlayingSubAni then
		return
	end
	if self.currAnimationName == self.curHurtName then
		self:updateHurt(...)
	elseif self.currAnimationName == SPINE_ANIMATION_NAME.BLOCK then
		self:updateBlock(...)
	end
end

function BattleUnitComp:playHurt()
	if self.currState == UNIT_STATE.IDLE or
		self.currState == UNIT_STATE.VERITGO then
		if self.hurtAniNameCount <= 0 then
			return
		end
		local name = self.hurtNameList[1]
		if not name then
			name = self.hurtAniNameList[math.random(1, self.hurtAniNameCount)]
		else
			table.remove(self.hurtNameList, 1)
		end
		self.playSubAniTime = 0
		self.curHurtName = name
		if self.playSubAniDuration[name] == nil then
			self.playSubAniDuration[name] = self:getAnimationDuration(name)
		end
		self:playAnimation(name, false, false)
	end
end

function BattleUnitComp:updateHurt(dt, overAniName)
	self.playSubAniTime = self.playSubAniTime + dt
	if self.playSubAniTime >= self.playSubAniDuration[self.curHurtName or SPINE_ANIMATION_NAME.HIT] then
		self:playAnimation(overAniName, true, false)
		self.isPlayingSubAni = false
	end
end

function BattleUnitComp:playBlock()
	if self.currState == UNIT_STATE.IDLE then
		local name = SPINE_ANIMATION_NAME.BLOCK
		self.playSubAniTime = 0
		if self.playSubAniDuration[name] == nil then
			self.playSubAniDuration[name] = self:getAnimationDuration(name)
		end
		self:playAnimation(name, false, false)
	end

	local direction = BattleConst.EFFECT_TYPE_MOVE_R
	local x, y = self.team:getMainUnitLocalPosition(self)
	if self.side == BattleConst.SIDE_ATK then
		direction = BattleConst.EFFECT_TYPE_MOVE_L
	end

	self:showEffectNumber(BattleConst.EFFECT_COLOR_SPECIAL, direction, I18N:getGlobalText(I18N.GlobalConst.BLOCK_DESC), x, y, 0)
end


function BattleUnitComp:updateBlock(dt, overAniName)
	self.playSubAniTime = self.playSubAniTime + dt
	if self.playSubAniTime >= self.playSubAniDuration[SPINE_ANIMATION_NAME.BLOCK] then
		self:playAnimation(overAniName, true, false)
		self.isPlayingSubAni = false
	end
end

function BattleUnitComp:exitFrozenState()
end

function BattleUnitComp:enterFrozenState()
	self:playAnimation(SPINE_ANIMATION_NAME.FROZEN, true, false)
end

function BattleUnitComp:updateFrozen(dt)
	self:updateIdleSubAni(dt, SPINE_ANIMATION_NAME.FROZEN)
end

function BattleUnitComp:exitVeritgoState()
end

function BattleUnitComp:enterVeritgoState()
	self:playAnimation(SPINE_ANIMATION_NAME.VERTIGO, true, false)
end

function BattleUnitComp:updateVeritgo(dt)
	self:updateIdleSubAni(dt, SPINE_ANIMATION_NAME.VERTIGO)
end

function BattleUnitComp:enterRecoverHpWaveState()
	self.recoverHpCount = BattleConst.RECOVER_HP_COUNT
	self.recoverHpTime = BattleConst.RECOVER_HP_INTERVAL / 2
end

function BattleUnitComp:exitRecoverHpWaveState()
end

function BattleUnitComp:updateRecoverHpWaveState(dt)
	if self.recoverHpCount <= 0 then
		return
	end
	self.recoverHpTime = self.recoverHpTime - dt
	if self.recoverHpTime < 0 then
		self.recoverHpCount = self.recoverHpCount - 1
		self.recoverHpTime = BattleConst.RECOVER_HP_INTERVAL
		local healNum = BattleConst.RECOVER_HP_PERCENT * self.unitEntity:getMaxHp() // DEFAULT_FACTOR
		if healNum < 0 then -- 治疗效果不能为负数
			healNum = 0
		end
		self:takeDamageOrCure(self, healNum, EFFECT_TYPE.HEAL, 0, BattleConst.SPECIAL_DAMAGE_OR_CURE_TYPE.ROUND_BEGIN_HEAL)
		if self.recoverHpCount <= 0 then
			self:changeState(UNIT_STATE.IDLE)
			if self.finishRecoverHpCallback then
				local callback = self.finishRecoverHpCallback
				self.finishRecoverHpCallback = nil
				callback()
			end
		end
	end
end

function BattleUnitComp:enterWaitState()
end

function BattleUnitComp:exitWaitState()
end

function BattleUnitComp:updateWaitState(dt)
	self.waitTime = self.waitTime - dt
	if self.waitTime < 0 then
		self:changeState(self.waitingState)
	end
end

function BattleUnitComp:enterAssistingAttackState()
	self.attackOver = false
	self.attackTime = 0
	self.skillSlowDownTime = nil
	self.isMove = false
	local skill = self.unitEntity:getAssistingSkill()
	skill:startUse()
	local attackName = skill:getSkillAttackName()
	self.currAttackDuration = self:getAnimationDuration(attackName)
	self.currAttackKeyTime = self:getKeyFrameTime(skill, 1, attackName)
	self:playSkillSound(skill:getSkillSound(), skill:getSoundDelay())
	self:playAnimation(attackName, false, false)
	self:playSkillFx(skill)
	self:initPosition()
end

function BattleUnitComp:exitAssistingAttackState()
	self:hideOutsideScreen()
	if self.assistingDmgAddition > 0 then
		local attrName = GConst.MATCH_ATTACK_NAME[self:getMatchType()]
		self.unitEntity:addAttr(attrName, -self.assistingDmgAddCount, false)
		self.assistingDmgAddition = 0
		self.assistingDmgAddCount = 0
	end
end

function BattleUnitComp:updateAssistingAttackState(dt)
	self.attackTime = self.attackTime + dt
	if self.attackTime >= self.currAttackDuration then
		self.attackOver = true
		self:onAttackOver()
	else
		if self.currAttackKeyTime > 0 and self.attackTime >= self.currAttackKeyTime then -- 到达关键后使用
			local skill = self.unitEntity:getAssistingSkill()
			local isFinalBlock = skill and skill:isFinalBlock(self.currAttackBlockIndex)
			self:onSkillTakeEffect(skill, isFinalBlock, self.validEffectIdx)

			if skill then
				local attackName = skill:getSkillAttackName()
				self.currAttackKeyTime = self:getKeyFrameTime(skill, self.currAttackBlockIndex + 1, attackName)
			else
				self.currAttackKeyTime = 0
			end

		end
	end
end

function BattleUnitComp:enterSkillAttackState()
	self.attackOver = false
	self.attackTime = 0
	self.targetX = nil
	local skill
	if self.normalSkillCount > 0 then
		skill = self.unitEntity:getNormalSkill(true)
		self.skillSlowDownTime = nil
	else
		skill = self.currActiveSkill
		local slowDownBulletTimeParams = skill:getSlowDownBulletTimeParams()
		if slowDownBulletTimeParams and #slowDownBulletTimeParams == 3 then
			self.skillSlowDownTime = slowDownBulletTimeParams[1] / TIME_FACTOR
			self.skillSlowDownScale = slowDownBulletTimeParams[2] / DEFAULT_FACTOR
			self.skillSlowDownDuration = slowDownBulletTimeParams[3] / TIME_FACTOR
		else
			self.skillSlowDownTime = nil
		end
	end
	skill:startUse()
	if skill:getMoveType() == BattleConst.SKILL_MOVE_TYPE.MOVE then
		self.isMove = true
		self:playAnimation(BattleConst.SPINE_ANIMATION_NAME.MOVE, true, false)
		self.positionX = self.baseObject:fastGetLocalPosition()
		if self.side == BattleConst.SIDE_ATK then
			self.targetX = - BattleConst.INIT_POS_X + skill:getMoveTypeParams()
			self.moveDirection = 1
		else
			self.targetX = BattleConst.INIT_POS_X - skill:getMoveTypeParams()
			self.moveDirection = -1
		end
	else
		self.isMove = false
		local attackName = skill:getSkillAttackName()
		if self.normalSkillCount > 0 then
			self:attackAndSpeedUp()
		else
			if not attackName then -- 没有攻击动画
				self.currAttackDuration = 0
				self.currAttackKeyTime = 0
				self.battleController:resetTimeSpeed()
				local isFinalBlock = true
				local isHaveNextAttack = self:getIsHaveNextAvailableActiveSkill()
				if not isHaveNextAttack and isFinalBlock then
					self.team:setCentralizedAttack(false)
					self.team:setIsFinalBlock(isFinalBlock)
				end
				self:onSkillTakeEffect(skill, isFinalBlock)
				if not isHaveNextAttack and isFinalBlock then
					self.battleController:setIsPauseHpProgress(false)
				end
				return
			end
		end
		self.currAttackDuration = self:getAnimationDuration(attackName)
		self.currAttackKeyTime = self:getKeyFrameTime(skill, 1, attackName)
		self:playSkillSound(skill:getSkillSound(), skill:getSoundDelay())
		self:playAnimation(attackName, false, false)
		self:playSkillFx(skill)
	end
end

function BattleUnitComp:checkSkillSlowDown(dt)
	if self.skillSlowDownTime == nil then
		return
	end
	self.skillSlowDownTime = self.skillSlowDownTime - dt
	if self.skillSlowDownTime >= 0 then
		return
	end
	self.skillSlowDownTime = nil
	self.battleController:setSkillSlowDown(self.skillSlowDownScale, self.skillSlowDownDuration)
end

function BattleUnitComp:exitSkillAttackState()
end

function BattleUnitComp:updateSkillAttack(dt)
	if self.isMove then
		local addX = dt*BattleConst.MOVE_SPEED*self.moveDirection
		self.positionX = self.positionX + addX
		if (self.moveDirection > 0 and self.positionX >= self.targetX) or (self.moveDirection < 0 and self.positionX <= self.targetX) then
			self.isMove = false
			self.positionX = self.targetX
			if self.attackOver then -- 归位后该下一步了
				self:onAttackOver()
			else -- 到位置该攻击了
				self:doNextAttack()
			end
		end
		self.baseObject:setLocalPosition(self.positionX, 0, 0)
		return
	end
	self:checkSkillSlowDown(dt)
	self.attackTime = self.attackTime + dt
	if self.attackTime >= self.currAttackDuration then
		self.attackOver = true
		if self.normalSkillCount > 0 then
			self.normalSkillCount = self.normalSkillCount - 1
			if self.normalSkillCount <= 0 then
				if self.currActiveSkill == nil then
					if self.targetX then -- 移动过，准备归位
						self:moveBackToInitPosition()
					else
						self:onAttackOver()
					end
					return
				else
					self:checkPassiveEvent(PASSIVE_EVENT.ON_ACTIVE_SKILL_BEFORE, self)
					self.currActiveSkill:startUse()
					self:doNextSkillAttack()
				end
			else -- 继续普攻
				self:doNextNormalAttack()
			end
		else
			if self.currAttackDuration <= 0 and self.currActiveSkill then -- 当前动画异常 没有进入onSkillTakeEffect，不会攻击次数减一，所以手动调用一次
				self.currActiveSkill:endUse()
			end
			local currActiveSkill = nil
			local skillCanUseTimes = self.currActiveSkill:getSkillCanUseTimes()
			if skillCanUseTimes and skillCanUseTimes > 0 then -- 当前技能可以多次使用
				currActiveSkill = self.currActiveSkill
			elseif self.activeSkillIndex then
				self.activeSkillIndex = self.activeSkillIndex + 1
				local activeSkillCount = self.unitEntity:getActiveSkillCount()
				while self.activeSkillIndex <= activeSkillCount do
					currActiveSkill = self.unitEntity:getAvailableActiveSkill(self.activeSkillIndex)
					if currActiveSkill then
						currActiveSkill:startUse()
						break
					end
					self.activeSkillIndex = self.activeSkillIndex + 1
				end
			end
			if currActiveSkill == nil then
				if self.targetX then -- 移动过，准备归位
					self:moveBackToInitPosition()
				else
					self:onAttackOver()
				end

				local target = self.battleController:getOtherSideMainUnit(self.side)
				if target and target.unitEntity:getIsDead() then
					self:checkPassiveEvent(PASSIVE_EVENT.ON_DEAD_BY_SKILL, self)
				end
				return
			else
				self.currActiveSkill = currActiveSkill
				self:doNextSkillAttack()
			end
		end
	else
		if self.currAttackKeyTime > 0 and self.attackTime >= self.currAttackKeyTime then -- 到达关键后使用
			if self.normalSkillCount > 0 then
				local skill = self.unitEntity:getNormalSkill()
				local isFinalBlock = skill and skill:isFinalBlock(self.currAttackBlockIndex)

				if self.normalSkillCount == 1 and self.currActiveSkill == nil and isFinalBlock then -- 最后一次攻击
					self.team:setCentralizedAttack(false)
				end
				self:onSkillTakeEffect(skill, isFinalBlock, self.validEffectIdx)
				if self.normalSkillCount == 1 and self.currActiveSkill == nil and isFinalBlock then -- 最后一次攻击
					self.battleController:setIsPauseHpProgress(false)
				end

				if skill then
					local attackName = skill:getSkillAttackName()
					self.currAttackKeyTime = self:getKeyFrameTime(skill, self.currAttackBlockIndex + 1, attackName)
				else
					self.currAttackKeyTime = 0
				end
			else
				local isFinalBlock = self.currActiveSkill:isFinalBlock(self.currAttackBlockIndex)

				local isHaveNextAttack = self:getIsHaveNextAvailableActiveSkill()
				if not isHaveNextAttack and isFinalBlock then
					self.team:setCentralizedAttack(false)
					self.team:setIsFinalBlock(isFinalBlock)
				end
				self:onSkillTakeEffect(self.currActiveSkill, isFinalBlock, self.validEffectIdx)
				if not isHaveNextAttack and isFinalBlock then
					self.battleController:setIsPauseHpProgress(false)
				end

				local attackName = self.currActiveSkill:getSkillAttackName()
				self.currAttackKeyTime = self:getKeyFrameTime(self.currActiveSkill, self.currAttackBlockIndex + 1, attackName)
			end
		end
	end
end

function BattleUnitComp:getIsHaveNextAvailableActiveSkill()
	local skillCanUseTimes = self.currActiveSkill:getSkillCanUseTimes()
	-- 当前技能可以多次使用,onSkillTakeEffect才会次数减1，所以这次大于1的时候才说明可以多次使用
	if skillCanUseTimes and skillCanUseTimes > 1 then
		return true
	elseif self.activeSkillIndex then
		local currActiveSkill = nil
		local activeSkillIndex = self.activeSkillIndex + 1
		local activeSkillCount = self.unitEntity:getActiveSkillCount()
		while activeSkillIndex <= activeSkillCount do
			currActiveSkill = self.unitEntity:getAvailableActiveSkill(activeSkillIndex)
			if currActiveSkill then
				return true
			end
			activeSkillIndex = activeSkillIndex + 1
		end
	end
	return false
end

function BattleUnitComp:moveBackToInitPosition()
	self.isMove = true
	self:playAnimation(BattleConst.SPINE_ANIMATION_NAME.MOVE, true, false)
	self.positionX = self.baseObject:fastGetLocalPosition()
	if self.side == BattleConst.SIDE_ATK then
		self.targetX = -BattleConst.INIT_POS_X
		self.moveDirection = -1
	else
		self.targetX = BattleConst.INIT_POS_X
		self.moveDirection = 1
	end
end

function BattleUnitComp:onAttackOver()
	self:changeState(UNIT_STATE.IDLE)
	local callback = self.actionOverCallback
	self.actionOverCallback = nil
	if callback then
		callback()
	end
end

function BattleUnitComp:attackAndSpeedUp()
	self.attackCount = self.attackCount + 1
	if self.attackCount == 3 then
		self.battleController:addTimeSpeed()
	elseif self.attackCount == 5 then
		self.battleController:addTimeSpeed()
	end
end

function BattleUnitComp:doNextSkillAttack()
	self.attackTime = 0
	local slowDownBulletTimeParams = self.currActiveSkill:getSlowDownBulletTimeParams()
	if slowDownBulletTimeParams and #slowDownBulletTimeParams == 3 then
		self.skillSlowDownTime = slowDownBulletTimeParams[1] / TIME_FACTOR
		self.skillSlowDownScale = slowDownBulletTimeParams[2] / DEFAULT_FACTOR
		self.skillSlowDownDuration = slowDownBulletTimeParams[3] / TIME_FACTOR
	else
		self.skillSlowDownTime = nil
	end
	local attackName = self.currActiveSkill:getSkillAttackName()
	if not attackName then -- 没有攻击动画
		self.currAttackDuration = 0
		self.currAttackKeyTime = 0
		self.battleController:resetTimeSpeed()
		local isFinalBlock = true
		local isHaveNextAttack = self:getIsHaveNextAvailableActiveSkill()
		if not isHaveNextAttack and isFinalBlock then
			self.team:setCentralizedAttack(false)
			self.team:setIsFinalBlock(isFinalBlock)
		end
		self:onSkillTakeEffect(self.currActiveSkill, isFinalBlock)
		if not isHaveNextAttack and isFinalBlock then
			self.battleController:setIsPauseHpProgress(false)
		end
		return
	end

	self.currAttackDuration = self:getAnimationDuration(attackName)
	self.currAttackKeyTime = self:getKeyFrameTime(self.currActiveSkill, 1, attackName)
	self:playSkillSound(self.currActiveSkill:getSkillSound(), self.currActiveSkill:getSoundDelay())
	self:playAnimation(attackName, false, false)
	self:playSkillFx(self.currActiveSkill)
	self.battleController:resetTimeSpeed()
end

function BattleUnitComp:doNextNormalAttack()
	self.attackTime = 0
	self.skillSlowDownTime = nil
	local skill = self.unitEntity:getNormalSkill(true)
	skill:startUse()
	local attackName = skill:getSkillAttackName()
	self.currAttackDuration = self:getAnimationDuration(attackName)
	self.currAttackKeyTime = self:getKeyFrameTime(skill, 1, attackName)
	self:playSkillSound(skill:getSkillSound(), skill:getSoundDelay())
	self:playAnimation(attackName, false, false)
	self:playSkillFx(skill)
	self:attackAndSpeedUp()
end

function BattleUnitComp:doNextAttack()
	self.attackTime = 0
	local attackName = nil
	if self.normalSkillCount > 0 then
		self.skillSlowDownTime = nil
		local skill = self.unitEntity:getNormalSkill(true)
		skill:startUse()
		attackName = skill:getSkillAttackName()
		if attackName then
			self.currAttackDuration = self:getAnimationDuration(attackName)
			self.currAttackKeyTime = self:getKeyFrameTime(skill, 1, attackName)
			self:playSkillSound(skill:getSkillSound(), skill:getSoundDelay())
			self:playAnimation(attackName, false, false)
			self:playSkillFx(skill)
			self:attackAndSpeedUp()
		else
			self:moveBackToInitPosition()
		end
	elseif self.currActiveSkill then
		local slowDownBulletTimeParams = self.currActiveSkill:getSlowDownBulletTimeParams()
		if slowDownBulletTimeParams and #slowDownBulletTimeParams == 3 then
			self.skillSlowDownTime = slowDownBulletTimeParams[1] / TIME_FACTOR
			self.skillSlowDownScale = slowDownBulletTimeParams[2] / DEFAULT_FACTOR
			self.skillSlowDownDuration = slowDownBulletTimeParams[3] / TIME_FACTOR
		else
			self.skillSlowDownTime = nil
		end
		self.currActiveSkill:startUse()
		attackName = self.currActiveSkill:getSkillAttackName()
		if attackName then
			self.currAttackDuration = self:getAnimationDuration(attackName)
			self.currAttackKeyTime = self:getKeyFrameTime(self.currActiveSkill, 1, attackName)
			self:playSkillSound(self.currActiveSkill:getSkillSound(), self.currActiveSkill:getSoundDelay())
			self:playAnimation(attackName, false, false)
			self:playSkillFx(self.currActiveSkill)
			self.battleController:resetTimeSpeed()
		else
			self:moveBackToInitPosition()
		end
	else
		self:moveBackToInitPosition()
	end
end

function BattleUnitComp:enterNormalAttackState()
	self.attackOver = false
	self.attackTime = 0
	self.skillSlowDownTime = nil
	local skill = self.unitEntity:getNormalSkill(true)
	if not skill then
		self:onAttackOver()
		return
	end
	skill:startUse()
	if skill:getMoveType() == BattleConst.SKILL_MOVE_TYPE.MOVE then
		self.isMove = true
		self:playAnimation(BattleConst.SPINE_ANIMATION_NAME.MOVE, true, false)
		self.positionX = self.baseObject:fastGetLocalPosition()
		if self.side == BattleConst.SIDE_ATK then
			self.targetX = - BattleConst.INIT_POS_X + skill:getMoveTypeParams()
			self.moveDirection = 1
		else
			self.targetX = BattleConst.INIT_POS_X - skill:getMoveTypeParams()
			self.moveDirection = -1
		end
	else
		self.isMove = false
		local attackName = skill:getSkillAttackName()
		self.currAttackDuration = self:getAnimationDuration(attackName)
		self.currAttackKeyTime = self:getKeyFrameTime(skill, 1, attackName)
		self:playSkillSound(skill:getSkillSound(), skill:getSoundDelay())
		self:playAnimation(attackName, false, false)
		self:playSkillFx(skill)
		self:attackAndSpeedUp()
	end
end

function BattleUnitComp:exitNormalAttackState()
end

function BattleUnitComp:updateNormalAttack(dt)
	if self.isMove then
		local addX = dt*BattleConst.MOVE_SPEED*self.moveDirection
		self.positionX = self.positionX + addX
		if (self.moveDirection > 0 and self.positionX >= self.targetX) or (self.moveDirection < 0 and self.positionX <= self.targetX) then
			self.isMove = false
			self.positionX = self.targetX
			if self.attackOver then -- 归位后该下一步了
				self:onAttackOver()
			else -- 到位置该攻击了
				self:doNextNormalAttack()
			end
		end
		self.baseObject:setLocalPosition(self.positionX, 0, 0)
		return
	end
	self.attackTime = self.attackTime + dt
	if self.attackTime >= self.currAttackDuration then
		self.attackOver = true
		self.normalSkillCount = self.normalSkillCount - 1
		if self.normalSkillCount <= 0 then
			local skill = self.unitEntity:getNormalSkill()
			if skill:getMoveType() == BattleConst.SKILL_MOVE_TYPE.MOVE then
				self:moveBackToInitPosition()
			else
				self:onAttackOver()
			end
			return
		else -- 继续攻击
			self:doNextNormalAttack()
		end
	else
		if self.currAttackKeyTime > 0 and self.attackTime >= self.currAttackKeyTime then -- 到达关键后使用
			local skill = self.unitEntity:getNormalSkill()
			local isFinalBlock = skill and skill:isFinalBlock(self.currAttackBlockIndex) or false
			if self.normalSkillCount == 1 and isFinalBlock then -- 如果是最后一次攻击，那么敌人受到这次攻击可以开始嗝屁了
				self.team:setCentralizedAttack(false)
				self.team:setIsFinalBlock(isFinalBlock)
			end
			self:onSkillTakeEffect(skill, isFinalBlock, self.validEffectIdx)
			if self.normalSkillCount == 1 and isFinalBlock then -- 如果是最后一次攻击，那么可以开始跑血条了
				self.battleController:setIsPauseHpProgress(false)
			end

			if skill then
				local attackName = skill:getSkillAttackName()
				self.currAttackKeyTime = self:getKeyFrameTime(skill, self.currAttackBlockIndex + 1, attackName)
			else
				self.currAttackKeyTime = 0
			end
		end
	end
end

function BattleUnitComp:addMaxHp(percent)
	self.unitEntity:addMaxHp(percent)
	local hpPercent = self.unitEntity:getHpPercent()
	local hp = self.unitEntity:getHp()
	self.battleController:refreshHp(self.side, hp, hpPercent)
end

function BattleUnitComp:addBuff(buffEffect, conditionResult)
	if buffEffect.buff:needShowName() and buffEffect.buff:getShowName(true) then
		local direction = BattleConst.EFFECT_TYPE_MOVE_R
		local x, y = self.team:getMainUnitLocalPosition(self)
		x = x + 80
		if self.side == BattleConst.SIDE_ATK then
			direction = BattleConst.EFFECT_TYPE_MOVE_L
			x = x - 80
		end
		y = y - 120
		local time = Time:getServerTime()
		if self.lastAddBuffTime == time then
			self.lastSameTimeAddBuffCount = self.lastSameTimeAddBuffCount + 1
		else
			self.lastAddBuffTime = time
			self.lastSameTimeAddBuffCount = 0
		end
		time = self.lastSameTimeAddBuffCount * BattleConst.EFFECT_NUMBER_INTERVAL
		local showCombo = conditionResult == BattleConst.SKILL_CONDITION_RESULT.CONDITION_PASS
		self:showEffectNumber(BattleConst.EFFECT_COLOR_SPECIAL, direction, buffEffect.buff:getShowName(true), x - 20, y - 20, time, showCombo)
	end

	return self.team:addBuff(buffEffect)
end

function BattleUnitComp:judgeBuffEffectEffectNumOverflow(buffEntity)
	return self.team:judgeBuffEffectEffectNumOverflow(buffEntity)
end

function BattleUnitComp:getBuffCountByName(buffName)
	return self.team:getBuffCountByName(buffName)
end

function BattleUnitComp:updateBuffState(buff, num)
	self.team:updateBuffState(buff, num)
end

function BattleUnitComp:removeAllBuff()
	if self.unitEntity:getCanRebirth() then
		return
	end
	self.team:removeAllBuff()
end

function BattleUnitComp:removeBuffByName(buffName)
	self.team:removeBuffByName(buffName)
end

function BattleUnitComp:removeBuffByDecr(buffDecr)
	self.team:removeBuffByDecr(buffDecr)
end

function BattleUnitComp:removeAllShield()
	self.team:removeAllShield()
end

function BattleUnitComp:putCacheBuff(buffEffect)
	self.team:putCacheBuff(buffEffect)
end

function BattleUnitComp:putCacheBuffByDecr(buffDecr)
	self.team:putCacheBuffByDecr(buffDecr)
end

function BattleUnitComp:popCacheBuffByDecr(buffDecr)
	self.team:popCacheBuffByDecr(buffDecr)
end

function BattleUnitComp:onSkillTakeEffect(skill, isFinalBlock, validEffectIdx)
	if isFinalBlock == nil then
		isFinalBlock = true
	end
	if isFinalBlock then
		skill:endUse()
		if skill:isAttackOverActive() then
			BATTLE_BOARD_SKILL_HANDLE.activeAttackOverSkill(self, skill, self.battleController)
		end
	end

	local effectList = skill:getEffectList()
	if effectList == nil then
		return
	end
	if #effectList == 0 then
		return
	end
	local targetType = skill:getTargetType()
	local target
	local targetIsSelf = false
	if targetType == 1 then -- 自己
		target = self
		targetIsSelf = true
	else
		target = self.battleController:getOtherSideMainUnit(self.side)
		if skill:getIsNormalType() then -- 普攻要计算一下格挡
			local block = target.unitEntity:getBlock()
			if block > 0 then
				if BattleHelper:random(1, DEFAULT_FACTOR) <= block then -- 格挡成功
					target:playBlock()
					return
				end
			end
		end
	end

	local succ = false
	local effectStartIdx = 1
	local effectEndIdx = 1
	if validEffectIdx then
		effectStartIdx = validEffectIdx[1] + 1
		effectEndIdx = validEffectIdx[2]
	else
		effectEndIdx = #effectList
	end
	for i = effectStartIdx, effectEndIdx do
		local effect = effectList[i]
		if effect then
			local conditionResult = self:judgeSkillEffectCondition(skill, i)
			if conditionResult ~= BattleConst.SKILL_CONDITION_RESULT.NOT_PASS then
				local isConditionPass = conditionResult == BattleConst.SKILL_CONDITION_RESULT.CONDITION_PASS
				if isConditionPass then
					self.team:addHurtComboTag(BattleConst.COMBO_DEFAULT_POSITION)
				end
				-- 增加受击动画逻辑
				target:setHurtList(skill:getHitNameList())
				if self:takeEffect(effect, target, conditionResult) then
					if isConditionPass and skill:getComboPosition() then
						self.team:addHurtComboTag(skill:getComboPosition())
					end
					succ = true
				end
				if isConditionPass then
					self.team:reduceHurtComboTag(BattleConst.COMBO_DEFAULT_POSITION)
				end
			end
		else
			break
		end
	end

	if isFinalBlock and targetIsSelf then -- 死亡判定
		local otherSideTarget = self.battleController:getOtherSideMainUnit(self.side)
		otherSideTarget:checkDeadStatus(target)
	end

	if succ then
		if skill:getIsHurtType() then
			self.team:addCombo()
		end
		if isFinalBlock then
			if skill:getIsNormalType() then -- 普攻攻击成功的话
				self:checkPassiveEvent(PASSIVE_EVENT.USE_NORMAL_SKILL, target)
			elseif skill:getIsActiveType() then
				self:checkPassiveEvent(PASSIVE_EVENT.ACTIVE_SKILL_HIT, target)
			end
		end

		local shakeType = skill:getShakeType()
		if shakeType then
			local shakeTime = skill:getShakeTime() or 0
			if shakeTime > 0 then
				self.battleController:shakeScreen(shakeType, shakeTime/TIME_FACTOR)
			end
		end
		local soundHit = skill:getSoundHit()
		if soundHit then
			local blocks = skill:getEffectBlock()
			if blocks then
				local soundIndex = 1
				for i, endIdx in ipairs(blocks) do
					if endIdx == effectEndIdx then
						soundIndex = i
						break
					end
				end
				if soundHit[soundIndex] and soundHit[soundIndex] > 0 then
					self:playSkillSound(soundHit[soundIndex], 0)
				end
			end
		end
	end
end

function BattleUnitComp:judgeSkillEffectCondition(skill, index)
	if not skill or not skill:haveBuffCondition() then
		return BattleConst.SKILL_CONDITION_RESULT.NO_CONDITION
	end

	local rel = skill:getBuffConditionRel(index)
	if not rel then
		return BattleConst.SKILL_CONDITION_RESULT.NO_CONDITION
	end
	local buffConditionIndex, conditionRel = rel[1], rel[2]
	local buffConditions = skill:getBuffCondition(buffConditionIndex)

	return BATTLE_SKILL_CONDITION_HANDLE.judgeSkillEffectCondition(buffConditions, conditionRel, self.battleController, self.side)
end

function BattleUnitComp:takeEffect(buff, target, conditionResult)
	local ratio = buff:getRatio()
	if ratio < DEFAULT_FACTOR then
		if BattleHelper:random(1, DEFAULT_FACTOR) > ratio then -- 没有通过命中概率
			return false
		end
	end

	if buff:isDecreaseGain() and target.unitEntity:getIsImmuneReductionBenefit() then -- 有免疫减益属性
		return false
	end

	if self:getIsFrozen() and buff:isIncreaseGain() then -- 冻结状态，缓存增益buff
		if buff:getRound() > 0 then
			local buffEffect = BattleHelper:getBuffEffect()
			buffEffect.buff = buff
			buffEffect.result = nil
			buffEffect.round = buff:getRound()
			buffEffect.target = target
			buffEffect.sender = self
			target:putCacheBuff(buffEffect)
		end
		return
	end
	if target.unitEntity:getIsInvalidControl() then -- 控制效果
		if buff:getBuffType() == BattleConst.BUFF_TYPE.CONTROL then
			return
		elseif buff:getName() == BattleConst.BUFF_NAME.FROZEN or
			buff:getName() == BattleConst.BUFF_NAME.IMPRISON or
			buff:getName() == BattleConst.BUFF_NAME.CHARM then
			return
		end
	end
	local round = buff:getRound()
	local buffEffect
	if round > 0 then
		buffEffect = BattleHelper:getBuffEffect()
		buffEffect.buff = buff
		buffEffect.result = nil
		buffEffect.round = round
		buffEffect.target = target
		buffEffect.sender = self
		buffEffect = target:addBuff(buffEffect, conditionResult)
		if not buffEffect then  -- 添加buff失败
			return
		end
	end
	if buffEffect and buffEffect.result then
		return
	end
	local func = BattleBuffHandle.takeBuffEffect[buff:getBuffType()]
	if func then
		local result = func(self, buff, target, buffEffect)
		if buffEffect then
			buffEffect.result = result
		end
		local success = result ~= nil
		if success then
			local fxList = buff:getFxGet()
			if fxList then
				for _, v in ipairs(fxList) do
					target:playFx(v, 0)
				end
			end
		end
		return success
	end
	return false
end

function BattleUnitComp:reTakeEffectByBuffEffect(buffEffect)
	local round = buffEffect.round
	local target = buffEffect.target
	local buff = buffEffect.buff
	if round > 0 then
		buffEffect.result = nil
		buffEffect = target:addBuff(buffEffect)
		if not buffEffect then -- 添加buff失败
			return
		end
	end
	if buffEffect and buffEffect.result then
		return
	end
	local func = BattleBuffHandle.takeBuffEffect[buff:getBuffType()]
	if func then
		local result = func(self, buff, target, buffEffect)
		if buffEffect then
			buffEffect.result = result
		end
		local success = result ~= nil
		if success then
			local fxList = buff:getFxGet()
			if fxList then
				for _, v in ipairs(fxList) do
					target:playFx(v, 0)
				end
			end
		end
		return success
	end
	return false
end

function BattleUnitComp:removeEffect(buff, target)
	local round = buff:getRound()
	if round > 0 then
		return
	end
	local func = BattleBuffHandle.removeEffect[buff:getBuffType()]
	if func then
		func(self, target, buff)
	end
end

function BattleUnitComp:takeDamageOrCure(atker, num, effectType, effectStatus, damageOrCureType)
	if self:getIsClear() then
		return 0
	end
	if self.currState == UNIT_STATE.DEAD then
		return 0
	end
	if num == 0 then
		return 0
	end
	if num < 0 and atker.unitEntity:getBeDmgToHeal() > 0 then
		num = -num * atker.unitEntity:getBeDmgToHeal() // DEFAULT_FACTOR
		num = BattleFormula:getAffectedHeal(num, self)
	end
	atker.unitEntity:addDamageCount(num)
	local showHurtCombo = atker:getHurtComboTag()
	if effectType ~= EFFECT_TYPE.DIRECT then
		showHurtCombo = false
	end

	local shieldHpBefore = self.unitEntity:getShieldHp()
	local hpRealReduce, shieldWorkOn = self.unitEntity:takeDamageOrCure(num, self)
	if hpRealReduce < 0 and self.side == BattleConst.SIDE_DEF then -- 实际掉血了
		self:addBattleExp(atker, hpRealReduce)
	end
	local shieldHpDiff = self.unitEntity:getShieldHp() - shieldHpBefore
	if shieldHpDiff < 0 or shieldWorkOn then -- 说明护盾减少了
		self.team:handleShield(shieldHpDiff, self)
	end
	local hp = self.unitEntity:getHp()
	local x, y = self.team:getMainUnitLocalPosition(self)
	local damage = num
	local time = Time:getServerTime()
	if num < 0 then -- 伤害
		local delayTime = 0
		if shieldHpDiff < 0 or shieldWorkOn then
			if shieldHpDiff == 0 then -- 护盾血量没有减少， 但是被抵消了
				shieldHpDiff = -1
				damage = 0
			else
				damage = damage - shieldHpDiff
			end
			delayTime = BattleConst.EFFECT_NUMBER_DELAY
			if self.lastBlueNumberTime == time then
				self.lastSameTimeBlueCount = self.lastSameTimeBlueCount + 1
			else
				self.lastBlueNumberTime = time
				self.lastSameTimeBlueCount = 0
			end
			delayTime = delayTime + self.lastSameTimeBlueCount * BattleConst.EFFECT_NUMBER_INTERVAL
			if self.side == BattleConst.SIDE_ATK then
				self:showEffectNumber(BattleConst.EFFECT_COLOR_BLUE, BattleConst.EFFECT_TYPE_MOVE_L, shieldHpDiff, x, y, 0, showHurtCombo)
			else
				self:showEffectNumber(BattleConst.EFFECT_COLOR_BLUE, BattleConst.EFFECT_TYPE_MOVE_R, shieldHpDiff, x, y, 0, showHurtCombo)
			end
		end
		if damage < 0 then
			if self.lastBlueNumberTime == time then
				self.lastSameTimeBlueCount = self.lastSameTimeBlueCount + 1
			else
				self.lastBlueNumberTime = time
				self.lastSameTimeBlueCount = 0
			end
			delayTime = delayTime + self.lastSameTimeBlueCount * BattleConst.EFFECT_NUMBER_INTERVAL
			if effectStatus == HURT_STATE_CRIT then
				self:showEffectNumber(BattleConst.EFFECT_COLOR_RED, BattleConst.EFFECT_TYPE_CRIT, "c" .. damage, x, y, delayTime, showHurtCombo)
			else
				local effectColor = BattleConst.EFFECT_COLOR_RED
				local damageStr = damage
				local direction = BattleConst.EFFECT_TYPE_MOVE_R
				local elementType = BattleHelper:getDamageOrCureType2MatchType(damageOrCureType)
				local weekNessValue = self.unitEntity:getWeakness(elementType)
				if weekNessValue > 0 then
					damageStr = "a" .. damage
				else
					local decGmgValue = self.unitEntity:getDecDmg(elementType)
					if decGmgValue > 0 then
						effectColor = BattleConst.EFFECT_COLOR_WHILTE
						damageStr = "d" .. damage
					end
				end

				if self.side == BattleConst.SIDE_ATK then
					direction = BattleConst.EFFECT_TYPE_MOVE_L
				end

				self:showEffectNumber(effectColor, direction, damageStr, x, y, delayTime, showHurtCombo)
			end
		end
		if atker:getCurAttackActionState() == BattleConst.ATTACK_ACTION_STATE.NORMAL then
			if self.unitEntity:getCounterAttack() > 0 then -- 触发反击
				local counterattack = self.unitEntity:getCounterAttack()
				if counterattack > DEFAULT_FACTOR or BattleHelper:random(1, DEFAULT_FACTOR) <= counterattack then -- 通过命中概率
					self.unitEntity:addCounterAttackCount(1)
					self.battleController:showCounterAttack(self.unitEntity:getCounterAttackCount(), self.side)
				end
			end
		end
		if effectType == EFFECT_TYPE.DIRECT then
			if hp > 0 and self.unitEntity:getShieldRebound() then -- 伤害反弹
				atker:takeDamageOrCure(self, num*self.unitEntity:getShieldRebound() // DEFAULT_FACTOR, EFFECT_TYPE.REBOUND, 0, BattleConst.BUFF_NAME.SHIELD_REBOUND_200)
			end
			if self.unitEntity:getBeSucked() > 0 then -- 吸血
				atker:takeDamageOrCure(self, -num*self.unitEntity:getBeSucked() // DEFAULT_FACTOR, EFFECT_TYPE.HEAL, 0, BattleConst.SPECIAL_DAMAGE_OR_CURE_TYPE.BE_SUCKED)
			end
			if self:getIsLethargy() then -- 移除昏睡
				self:removeBuffByName(BattleConst.BUFF_NAME.LETHARGY)
			end
			if self.unitEntity:getThorns() > 0 then -- 反伤
				atker:takeDamageOrCure(self, num*self.unitEntity:getThorns() // DEFAULT_FACTOR, EFFECT_TYPE.REBOUND, 0, BattleConst.BUFF_NAME.THORNS)
			end
		end
	elseif num > 0 then -- 治疗
		if self.lastHealTime == time then
			self.lastSameTimeHealCount = self.lastSameTimeHealCount + 1
		else
			self.lastHealTime = time
			self.lastSameTimeHealCount = 0
		end
		local delayTime = self.lastSameTimeHealCount * BattleConst.EFFECT_NUMBER_INTERVAL
		self:showEffectNumber(BattleConst.EFFECT_COLOR_GREEN, BattleConst.EFFECT_TYPE_BUFF, "+" .. num, x, y, delayTime)
	end
	self:refreshHpSkin()
	local hpPercent = self.unitEntity:getHpPercent()
	self.battleController:refreshHp(self.side, hp, hpPercent)
	if not atker:getIsFinalBlock() or atker:getIsCentralizedAttack() then
		if damage < 0 then
			self.team:playHurt()
		end
	else
		if self:checkDeadStatus(atker, damageOrCureType) then
		elseif damage < 0 then
			self.team:playHurt()
		end
	end

	if hp > 0 then
		self.team:checkPassiveEvent(PASSIVE_EVENT.HP_LOWER_THAN, atker, hpPercent)
	else
		self.team:checkPassiveEvent(PASSIVE_EVENT.ON_DEAD, atker)
	end
end

function BattleUnitComp:checkDeadStatus(atker, damageOrCureType)
	if self.unitEntity:getIsDead() and not self.unitEntity:getTagDeadStatus() then
		self.unitEntity:tagDeadStatus()
		if self.unitEntity:getCanRebirth() then -- 复活
			self.battleController:resetTimeSpeed(true)
			local mainUnit = self.team:getMainUnit()
			if mainUnit then
				local callback = self.actionOverCallback
				if not callback then
					callback = atker.actionOverCallback
				end
				self.actionOverCallback = nil
				atker.actionOverCallback = nil
				mainUnit.unitEntity:setIsRebirth()
				mainUnit:playDead(function()
					mainUnit:removeBuffByName(BattleConst.ATTR_NAME.REBIRTH)
					local hpPercent = self.unitEntity:getHpPercent()
					self.battleController:refreshHp(self.side, self.unitEntity:getHp(), hpPercent)
					self.team:checkPassiveEvent(PASSIVE_EVENT.HP_LOWER_THAN, atker, hpPercent)

					mainUnit:changeState(UNIT_STATE.IDLE)
					mainUnit:initPosition()
					if callback then
						callback()
					end
				end)
			end
			return
		end

		if damageOrCureType == BattleConst.BUFF_NAME.BURN then
			local team = self.battleController:getOtherSideTeam(self.side)
			team:checkPassiveEvent(BattleConst.PASSIVE_EVENT.ON_DEAD_BY_BURN)
		end
		if self.unitEntity:getAttrValue(BattleConst.ATTR_NAME.BLEED) > 0 then
			local team = self.battleController:getOtherSideTeam(self.side)
			team:checkPassiveEvent(BattleConst.PASSIVE_EVENT.ON_DEAD_WITH_BLEED)
		end

		if self.actionOverCallback then -- 被反伤时死亡
			self.actionOverCallback = nil
			self.battleController:enterNextTeamAction()
		end

		self.battleController:resetTimeSpeed(true)

		self.team:changeDead() -- 因为buff生效对象有可能不是当前主英雄，会导致状态不对，所以使用主英雄来播放动画
		return true
	end

	return false
end

function BattleUnitComp:addBattleExp(atker, hpRealReduce)
	if not atker or hpRealReduce > 0 then
		return
	end

	local hpExp = self.unitEntity:getHpExp()
	if hpExp then -- 有血量分段经验
		local beforeHp = math.min(self.unitEntity:getHp() - hpRealReduce, self.unitEntity:getMaxHp())
		local beforeHpp = self.unitEntity:getHpPercent(beforeHp) * DEFAULT_FACTOR
		local nowHpp = self.unitEntity:getHpPercent() * DEFAULT_FACTOR
		local curExpIndex
		local curHppSpan
		local beforeExpIndex
		local beforeHppSpan
		for index, info in ipairs(hpExp) do
			local nextHpp = 0
			if hpExp[index + 1] then
				nextHpp = hpExp[index + 1].hpp
			end
			if nowHpp < info.hpp and nowHpp >= nextHpp then -- 当前所处经验段
				if not curExpIndex then
					curExpIndex = index
					curHppSpan = info.hpp - nextHpp
				end
			end
			if beforeHpp < info.hpp and beforeHpp >= nextHpp then -- 上一次所处经验段
				if not beforeExpIndex then
					beforeExpIndex = index
					beforeHppSpan = info.hpp - nextHpp
				end
			end
		end
		if not curExpIndex then
			return
		end
		if not beforeExpIndex then
			beforeExpIndex = curExpIndex
			beforeHppSpan = curHppSpan
		end
		local addExp = 0
		if beforeExpIndex == curExpIndex then -- 前后都在一个经验段
			local exp = hpExp[curExpIndex].exp
			local expTime = atker.unitEntity:getExpTime()
			addExp = math.floor(exp * (beforeHpp - nowHpp) / curHppSpan)
			if expTime > 0 then
				addExp = addExp * (DEFAULT_FACTOR + expTime) // DEFAULT_FACTOR
			end
		elseif beforeExpIndex < curExpIndex then
			for i = beforeExpIndex + 1, curExpIndex do
				local exp = hpExp[i - 1].exp
				local hpp = hpExp[i].hpp
				local hppSpan = hpExp[i - 1].hpp - hpp
				addExp = addExp + exp * (beforeHpp - hpp) / hppSpan
				beforeHpp = hpp
			end
			local exp = hpExp[curExpIndex].exp
			addExp = math.floor(addExp + exp * (beforeHpp - nowHpp) / curHppSpan)
			local expTime = atker.unitEntity:getExpTime()
			if expTime > 0 then
				addExp = addExp * (DEFAULT_FACTOR + expTime) // DEFAULT_FACTOR
			end
		end
		self.battleController:addBattleExp(addExp)
	else
		local exp = self.unitEntity:getExp()
		if exp and exp > 0 then
			local expTime = atker.unitEntity:getExpTime()
			local addExp = math.floor(exp/self.unitEntity:getMaxHp()*-hpRealReduce)
			if expTime > 0 then
				addExp = addExp * (DEFAULT_FACTOR + expTime) // DEFAULT_FACTOR
			end
			self.battleController:addBattleExp(addExp)
		end
	end
end

function BattleUnitComp:showEffectNumber(colorType, effectType, num, x, y, delayTime, showCombo)
	local body = self.unitEntity:getBody()
	if self.team:getMainUnit() then
		body = self.team:getMainUnit().unitEntity:getBody()
	end
	local addY = BattleConst.MIN_NODE_HEIGHT[body] or BattleConst.MIN_NODE_HEIGHT_DEFAULT
	self.battleController:showEffectNumber(colorType, effectType, num, x, y + addY, delayTime, showCombo)
end

function BattleUnitComp:refreshHpSkin()
	if self.unitEntity:getHpSkinInfo() then
		local skin
		local hpp = self.unitEntity:getHpPercent() * DEFAULT_FACTOR
		for index, info in ipairs(self.unitEntity:getHpSkinInfo()) do
			if hpp <= info.hpp then
				skin = info.skin
				break
			end
		end
		if self.lastHpSkin == skin then
			return
		end
		self.lastHpSkin = skin
		self.baseObject:setSkin(skin)
	end
end

function BattleUnitComp:playDead(callback)
	self.deadOverCallback = callback
	if self:getIsClear() then
		self.deadOverCallback = nil
		if callback then
			callback()
		end
		return
	end
	if self.currState ~= UNIT_STATE.DEAD and not self:changeState(UNIT_STATE.DEAD) then
		self.deadOverCallback = nil
		if callback then
			callback()
		end
	end
end

function BattleUnitComp:recoverHpOnWaveOver(callback)
	self.finishRecoverHpCallback = callback
	if not self:changeState(UNIT_STATE.RECOVER_HP_WAVE) then
		self.finishRecoverHpCallback = nil
		callback()
	end
end

function BattleUnitComp:playEnterBattlefield(isBoss, callback)
	self.finishEnterBattlefieldCallback = callback
	if isBoss then
		self.isMove = true
		self:hideOutsideScreen()
		if not self:changeState(UNIT_STATE.ENTER_BATTLEFIELD) then
			self.finishEnterBattlefieldCallback = nil
			self.isMove = false
			self:initPosition()
			self:changeState(UNIT_STATE.IDLE)
			callback()
		end
	else
		self.isMove = false
		self:initPosition()
		if not self:changeState(UNIT_STATE.ENTER_BATTLEFIELD) then
			self.finishEnterBattlefieldCallback = nil
			self:changeState(UNIT_STATE.IDLE)
			callback()
		end
	end
end

function BattleUnitComp:onRoundEnd()
	self.unitEntity:onRoundEnd()
end

function BattleUnitComp:playSkillSound(soundName, delay)
	if not soundName then
		return
	end
	delay = delay or 0
	BattleHelper:playSkillSound(soundName, delay)
end

function BattleUnitComp:playSkillFx(skill)
	self:playSkillSelfBgFx(skill)
	self:playSkillSelfFx(skill)
	self:playSkillTargetFx(skill)
end

function BattleUnitComp:playSkillSelfBgFx(skill)
	local fxId = skill:getFxBg()
	if fxId == nil then
		return
	end
	local delay = skill:getFxSelfDelay() or 0
	self:playFx(fxId, delay)
end

function BattleUnitComp:playSkillSelfFx(skill)
	local fxId = skill:getFxSelf()
	if fxId == nil then
		return
	end
	local delay = skill:getFxSelfDelay()
	self:playFx(fxId, delay)
end

function BattleUnitComp:playSkillTargetFx(skill)
	local fxId = skill:getFxTarget()
	if fxId == nil then
		return
	end
	local delay = skill:getFxTargetDelay()
	local targetType = skill:getTargetType()
	if targetType == 1 then -- 自己
		self:playFx(fxId, delay)
	else
		local target = self.battleController:getOtherSideMainUnit(self.side)
		target:playFx(fxId, delay)
	end
end

function BattleUnitComp:playFx(fxId, delay)
	if delay and delay > 0 then
		if self.waitPlayFxList == nil then
			self.waitPlayFxList = {}
			self.waitPlayFxCount = 0
		end
		self.waitPlayFxCount = self.waitPlayFxCount + 1
		local waitPlayFxObj = self.waitPlayFxList[self.waitPlayFxCount]
		if waitPlayFxObj == nil then
			waitPlayFxObj = {}
			self.waitPlayFxList[self.waitPlayFxCount] = waitPlayFxObj
		end
		waitPlayFxObj.time = delay / TIME_FACTOR
		waitPlayFxObj.fxId = fxId
		waitPlayFxObj.sender = self
		return
	end
	local fxInfo = BattleHelper:getFxConfig()[fxId]
	if fxInfo then
		self:getEffectAndPlay(fxInfo)
	end
end

function BattleUnitComp:getEffectAndPlay(fxInfo, isLoop)
	local bindNode = fxInfo.bind
	local inScene = fxInfo.in_scene == 1
	local fxScale = fxInfo.scale or 1
	BattleHelper:getEffectAsync(fxInfo.res, self.battleController:getFxNode(), function(effectObj)
		if isLoop and self.team:getLoopFxResCount(fxInfo.res) <= 0 then
			BattleHelper:recycleEffect(effectObj)
			return
		end
		if inScene then
			if bindNode then
				local boneX, boneY, boneZ = self.baseObject:fastGetBonePosition(bindNode)
				effectObj:setLocalPosition(boneX, boneY, boneZ)
			else
				effectObj:setLocalPosition(0, 0, 0)
			end
		else
			if bindNode then
				local boneFollower = BattleHelper:addSpineBoneFollowerGraphic(effectObj)
				boneFollower.SkeletonGraphic = self.baseObject:getSkeletonGraphic()
				boneFollower:SetBone(bindNode)
			else
				effectObj:setLocalPosition(0, 0, 0)
			end
		end
		if fxInfo.flip then
			effectObj:setLocalEulerAngles(0, 180, 0)
			effectObj:setLocalScale(fxScale, fxScale, fxScale)
		else
			effectObj:setLocalEulerAngles(0, 0, 0)
			effectObj:setLocalScale(fxScale, fxScale, fxScale)
		end
		local baseOrder = BattleHelper:getBaseOrder()
		local order = 19 -- 背景特效预留9, 英雄的层级放在11
		if fxInfo.bg then
			order = 1
		end
		effectObj:setSortingOrder(baseOrder, order)
		effectObj:play()
		if isLoop then
			if self.loopFxMap[fxInfo.res] then
				BattleHelper:recycleEffect(effectObj)
			else
				self.loopFxMap[fxInfo.res] = effectObj
			end
		else
			BattleHelper:performDurationDelay(effectObj:getDuration(), function()
				BattleHelper:recycleEffect(effectObj)
			end)
		end
	end)
end

function BattleUnitComp:removeFx(res)
	local effect = self.loopFxMap[res]
	if effect then
		self.loopFxMap[res] = nil
		BattleHelper:recycleEffect(effect)
	end
end

function BattleUnitComp:tick(dt)
	if self.isClear then
		return
	end
	self:checkFx(dt)
	if self.currState == UNIT_STATE.DEAD then
		self:updateDead(dt)
		return
	end
	if self.currState == UNIT_STATE.IDLE then
		self:updateIdle(dt)
		return
	end
	if self.currState == UNIT_STATE.NORMAL_ATTACK then
		self:updateNormalAttack(dt)
	elseif self.currState == UNIT_STATE.SKILL_ATTACK then
		self:updateSkillAttack(dt)
	elseif self.currState == UNIT_STATE.ASSISTING_ATTACK then
		self:updateAssistingAttackState(dt)
	elseif self.currState == UNIT_STATE.ENTER_BATTLEFIELD then
		self:updateEnterBattlefieldState(dt)
	elseif self.currState == UNIT_STATE.SWITCH_IN then
		self:updateSwitchInState(dt)
	elseif self.currState == UNIT_STATE.SWITCH_OUT then
		self:updateSwitchOutState(dt)
	elseif self.currState == UNIT_STATE.WAIT then
		self:updateWaitState(dt)
	elseif self.currState == UNIT_STATE.RECOVER_HP_WAVE then
		self:updateRecoverHpWaveState(dt)
	elseif self.currState == UNIT_STATE.FROZEN then
		self:updateFrozen(dt)
	elseif self.currState == UNIT_STATE.VERITGO then
		self:updateVeritgo(dt)
	end
end

function BattleUnitComp:checkFx(dt)
	if self.waitPlayFxCount == nil then
		return
	end
	if self.waitPlayFxCount <= 0 then
		return
	end
	for i = self.waitPlayFxCount, 1, -1 do
		local fxObj = self.waitPlayFxList[i]
		fxObj.time = fxObj.time - dt
		if fxObj.time <= 0 then -- 该播了
			self:playFx(fxObj.fxId, 0)
			local tailFxObj = self.waitPlayFxList[self.waitPlayFxCount]
			fxObj.time = tailFxObj.time
			fxObj.fxId = tailFxObj.fxId
			fxObj.sender = tailFxObj.sender
			self.waitPlayFxCount = self.waitPlayFxCount - 1
		end
	end
end

function BattleUnitComp:checkPassiveEvent(eventId, targetComp, ...)
	if self.passiveSkills == nil then
		return
	end
	local skills = self.passiveSkills[eventId]
	if skills and #skills > 0 then
		local func = BattlePassive.checkTrigger[eventId]
		if func then
			for _, skill in ipairs(skills) do
				local count = func(self, skill, targetComp, ...)
				if count > 0 and skill:getIsAvailable() then
					for i = 1, count do
						self:usePassiveSkill(skill)
					end
				elseif count < 0 then
					count = -count
					for i = 1, count do
						self:cancelPassiveSkillEffect(skill)
					end
				end
			end
		end
	end
end

function BattleUnitComp:usePassiveSkill(skill)
	self:onSkillTakeEffect(skill)
end

function BattleUnitComp:cancelPassiveSkillEffect(skill)
	local effectList = skill:getEffectList()
	if effectList == nil then
		return
	end
	local targetType = skill:getTargetType()
	local target
	if targetType == 1 then -- 自己
		target = self
	else
		target = self.battleController:getOtherSideMainUnit(self.side)
	end
	for k, effect in ipairs(effectList) do
		self:removeEffect(effect, target)
	end
end

function BattleUnitComp:rebirth()
	self.isClear = false
	if self.currState == UNIT_STATE.DEAD then
		self.currState = UNIT_STATE.INIT
	end
	self.unitEntity:rebirth()
end

function BattleUnitComp:isInitState()
	return self.currState == UNIT_STATE.INIT
end

function BattleUnitComp:getIsClear()
	return self.isClear
end

function BattleUnitComp:clear()
	if self.unitEntity:getCanRebirth() then
		return
	end

	if self.isClear then
		return
	end
	self.isClear = true
	if self.waitPlayFxList then
		for i = 1, #self.waitPlayFxList do
			table.remove(self.waitPlayFxList)
		end
		self.waitPlayFxCount = 0
	end
end

function BattleUnitComp:recycle()
	for k, v in pairs(self.loopFxMap) do
		BattleHelper:recycleEffect(v)
		self.loopFxMap[k] = nil
	end
	BattleHelper:recycleBattleHeroModel(self.modelId, self.baseObject)
end

-- region
function BattleUnitComp:setHurtList(hurtNameList)
	self.hurtNameList = table.refCopy(hurtNameList)
end
-- endregion
return BattleUnitComp