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 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 function BattleUnitComp:ctor() 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 end function BattleUnitComp:playBorn() self:changeState(UNIT_STATE.IDLE) end function BattleUnitComp:playSwitchIn() 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:setTeam(team) self.team = team end function BattleUnitComp:_initBase() self.isClear = false self.isMove = false self.deadTime = 0 self.attackTime = 0 self.currAttackDuration = 0 self.currAttackKeyTime = 0 self.switchTime = 0 self.isPlayHurt = 0 self.attackDurationMap = {} self.attackKeyFrameTimeMap = {} self.shieldBuffList = {} self.activeSkillIndex = nil self.currActiveSkill = nil self.targetX = nil self.assistingDmgAddition = 0 self.currState = UNIT_STATE.INIT 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() 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: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 end function BattleUnitComp:playAnimation(name, loop, forceRefresh) if name == SPINE_ANIMATION_NAME.HIT then self.isPlayHurt = 1 else self.isPlayHurt = 0 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) local time = self.attackKeyFrameTimeMap[animationName] if time == nil then time = self.baseObject:getAnimationKeyFrameTime(animationName) if time <= 0 then -- 容错处理 time = 0.3 end self.attackKeyFrameTimeMap[animationName] = time end return time end function BattleUnitComp:beforeAttack() self:checkPassiveEvent(PASSIVE_EVENT.ON_UNI_ATTACK_START, self) end function BattleUnitComp:useAssistingSkill(count, callback) local skill = self.unitEntity:getAssistingSkill() if skill == nil then callback() return end self.assistingDmgAddition = count local attrName = GConst.MATCH_ATTACK_NAME[self:getMatchType()] self.assistingDmgAddCount = self.unitEntity:addAttr(attrName, count*DEFAULT_FACTOR, true) self.actionOverCallback = callback if not self:changeState(UNIT_STATE.ASSISTING_ATTACK) then self.actionOverCallback = nil self.unitEntity:addAttr(attrName, -self.assistingDmgAddCount, false) callback() end end function BattleUnitComp:useSkill(index, count, callback) self.actionOverCallback = callback self.activeSkillIndex = index self.currActiveSkill = self.unitEntity:getAvailableActiveSkill(index) self.normalSkillCount = count + self.unitEntity:getNormalAttackAddCount() if self.currActiveSkill == nil then -- 没有技能就用普攻 if self.normalSkillCount <= 0 then self.actionOverCallback = nil self.activeSkillIndex = nil self.battleController:setIsPauseHpProgress(false) callback() return end if not self:changeState(UNIT_STATE.NORMAL_ATTACK) then self.actionOverCallback = nil self.battleController:setIsPauseHpProgress(false) callback() end else if not self:changeState(UNIT_STATE.SKILL_ATTACK) then self.actionOverCallback = nil self.battleController:setIsPauseHpProgress(false) callback() end end 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() 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) callback() return end if not self:changeState(UNIT_STATE.NORMAL_ATTACK) then self.actionOverCallback = nil self.battleController:setIsPauseHpProgress(false) callback() end else if not self:changeState(UNIT_STATE.SKILL_ATTACK) then self.actionOverCallback = nil self.battleController:setIsPauseHpProgress(false) callback() end end end function BattleUnitComp:useNormalSkill(count, callback) self.actionOverCallback = callback self.normalSkillCount = count + self.unitEntity:getNormalAttackAddCount() if not self:changeState(UNIT_STATE.NORMAL_ATTACK) then self.actionOverCallback = nil self.battleController:setIsPauseHpProgress(false) callback() end end function BattleUnitComp:addShield(num, buffEffect) self.unitEntity:addShield(num) self.team:addShield(buffEffect) end function BattleUnitComp:changeState(state) if self.currState == state and not self:repeatCurrState() then return false end if self.currState == UNIT_STATE.DEAD then -- 死亡后只能去死亡状态 if state ~= UNIT_STATE.DEAD then return false end 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() 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 self.currState == UNIT_STATE.ASSISTING_ATTACK then self:enterAssistingAttackState() elseif state == UNIT_STATE.DEAD then self:enterDeadState() elseif self.currState == UNIT_STATE.BORN then self:enterBornState() elseif self.currState == UNIT_STATE.ENTER_BATTLEFIELD then self:enterEnterBattlefieldState() elseif self.currState == UNIT_STATE.SWITCH_IN then self:enterSwitchInState() elseif self.currState == UNIT_STATE.SWITCH_OUT then self:enterSwitchOutState() 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 self:changeState(UNIT_STATE.IDLE) 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() 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*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) end end function BattleUnitComp:exitEnterBattlefieldState() local callback = self.finishEnterBattlefieldCallback self.finishEnterBattlefieldCallback = nil if callback then callback() end end function BattleUnitComp:enterEnterBattlefieldState() self:hideOutsideScreen() self.isMove = true self:playAnimation(SPINE_ANIMATION_NAME.BORN, 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:exitIdleState() end function BattleUnitComp:enterIdleState() self:playAnimation(SPINE_ANIMATION_NAME.IDLE, true, false) end function BattleUnitComp:updateIdle(dt) self:updateHurt(dt) end function BattleUnitComp:playHurt() self.hurtTime = 0 if self.currHitDuration == nil then self.currHitDuration = self:getAnimationDuration(SPINE_ANIMATION_NAME.HIT) end self:playAnimation(SPINE_ANIMATION_NAME.HIT, false, false) end function BattleUnitComp:updateHurt(dt) if self.isPlayHurt == 0 then return end if self.isPlayHurt == 1 then self.hurtTime = self.hurtTime + dt if self.hurtTime >= self.currHitDuration then self:playAnimation(SPINE_ANIMATION_NAME.IDLE, true, false) self.isPlayHurt = 0 end end end function BattleUnitComp:enterAssistingAttackState() self.attackOver = false self.attackTime = 0 self.isMove = false local skill = self.unitEntity:getAssistingSkill() skill:startUse() local attackName = skill:getSkillAttackName() self.currAttackDuration = self:getAnimationDuration(attackName) self.currAttackKeyTime = self:getAnimationKeyFrameTime(attackName) self:playAnimation(attackName, false, false) 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 -- 到达关键后使用 self.currAttackKeyTime = 0 local skill = self.unitEntity:getAssistingSkill() self:onSkillTakeEffect(skill) 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() else skill = self.currActiveSkill 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.UNIT_FRONT_POS_X self.moveDirection = 1 else self.targetX = -BattleConst.UNIT_FRONT_POS_X self.moveDirection = -1 end else self.isMove = false self.attackTime = 0 local attackName if self.normalSkillCount > 0 then attackName = skill:getRandomNormalAttackName() else attackName = skill:getSkillAttackName() end self.currAttackDuration = self:getAnimationDuration(attackName) self.currAttackKeyTime = self:getAnimationKeyFrameTime(attackName) self:playAnimation(attackName, false, false) end 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.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.currActiveSkill:startUse() self:doNextSkillAttack() end else -- 继续普攻 self:doNextNormalAttack() end else 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 return else self.currActiveSkill = currActiveSkill self:doNextSkillAttack() end end else if self.currAttackKeyTime > 0 and self.attackTime >= self.currAttackKeyTime then -- 到达关键后使用 self.currAttackKeyTime = 0 if self.normalSkillCount > 0 then local skill = self.unitEntity:getNormalSkill() self:onSkillTakeEffect(skill) if self.normalSkillCount == 1 and self.currActiveSkill == nil then -- 最后一次攻击 self.battleController:setIsPauseHpProgress(false) end else self:onSkillTakeEffect(self.currActiveSkill) if not self:getIsHaveNextAvailableActiveSkill() then self.battleController:setIsPauseHpProgress(false) end end end end end function BattleUnitComp:getIsHaveNextAvailableActiveSkill() local skillCanUseTimes = self.currActiveSkill:getSkillCanUseTimes() if skillCanUseTimes and skillCanUseTimes > 0 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:doNextSkillAttack() self.attackTime = 0 local attackName = self.currActiveSkill:getSkillAttackName() self.currAttackDuration = self:getAnimationDuration(attackName) self.currAttackKeyTime = self:getAnimationKeyFrameTime(attackName) self:playAnimation(attackName, false, false) end function BattleUnitComp:doNextNormalAttack() self.attackTime = 0 local skill = self.unitEntity:getNormalSkill() local attackName = skill:getRandomNormalAttackName() self.currAttackDuration = self:getAnimationDuration(attackName) self.currAttackKeyTime = self:getAnimationKeyFrameTime(attackName) self:playAnimation(attackName, false, false) end function BattleUnitComp:doNextAttack() self.attackTime = 0 local attackName = nil if self.normalSkillCount > 0 then local skill = self.unitEntity:getNormalSkill() attackName = skill:getRandomNormalAttackName() elseif self.currActiveSkill then attackName = self.currActiveSkill:getSkillAttackName() end if attackName then self.currAttackDuration = self:getAnimationDuration(attackName) self.currAttackKeyTime = self:getAnimationKeyFrameTime(attackName) self:playAnimation(attackName, false, false) else -- 归位 self:moveBackToInitPosition() end end function BattleUnitComp:enterNormalAttackState() self.attackOver = false self.attackTime = 0 local skill = self.unitEntity:getNormalSkill() 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.UNIT_FRONT_POS_X self.moveDirection = 1 else self.targetX = -BattleConst.UNIT_FRONT_POS_X self.moveDirection = -1 end else self.isMove = false self.attackTime = 0 local attackName = skill:getRandomNormalAttackName() self.currAttackDuration = self:getAnimationDuration(attackName) self.currAttackKeyTime = self:getAnimationKeyFrameTime(attackName) self:playAnimation(attackName, false, false) 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 -- 到达关键后使用 self.currAttackKeyTime = 0 local skill = self.unitEntity:getNormalSkill() self:onSkillTakeEffect(skill) if self.normalSkillCount == 1 then -- 如果是最后一次攻击,那么可以开始跑血条了 self.battleController:setIsPauseHpProgress(false) end end end end function BattleUnitComp:addBuff(buffEffect) self.team:addBuff(buffEffect) end function BattleUnitComp:updateBuffState(buff, num) self.team:updateBuffState(buff, num) end function BattleUnitComp:onSkillTakeEffect(skill) skill:endUse() if self.side == GConst.BattleConst.SIDE_ATK and skill == self.unitEntity:getNormalSkill() then self.battleController:addBattleExp(self.side) end 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 local succ = false for k, effect in ipairs(effectList) do if self:takeEffect(effect, target) then succ = true end end end function BattleUnitComp:takeEffect(buff, target) local ratio = buff:getRatio() if ratio < DEFAULT_FACTOR then if BattleHelper:random(1, DEFAULT_FACTOR) > ratio then -- 没有通过命中概率 return false 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 target:addBuff(buffEffect) 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 fxId = buff:getBuffHitFxId() if fxId then target:playHurtFx(fxId) 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, buff, num, effectType, effectStatus) if num == 0 then return 0 end local shieldHpBefore = self.unitEntity:getShieldHp() self.unitEntity:takeDamageOrCure(num) local shieldHpDiff = self.unitEntity:getShieldHp() - shieldHpBefore if shieldHpDiff < 0 then -- 说明护盾减少了 self:handleShield(shieldHpDiff, self) end local x, y, z = self.baseObject:fastGetLocalPosition() self:showEffectNumber(num, x, y) local hp = self.unitEntity:getHp() local hpPercent = self.unitEntity:getHpPercent() self.battleController:refreshHp(self.side, hp, hpPercent) if self.currState == UNIT_STATE.IDLE then self:playHurt() end if hp > 0 then self:checkPassiveEvent(PASSIVE_EVENT.HP_LOWER_THAN, atker, hpPercent) end end function BattleUnitComp:showEffectNumber(num, x, y) self.battleController:showEffectNumber(num, x, y) end function BattleUnitComp:playDead(callback) self.deadOverCallback = callback if not self:changeState(UNIT_STATE.DEAD) then self.deadOverCallback = nil callback() end end function BattleUnitComp:playEnterBattlefield(callback) self.finishEnterBattlefieldCallback = callback self:hideOutsideScreen() if not self:changeState(UNIT_STATE.ENTER_BATTLEFIELD) then self.finishEnterBattlefieldCallback = nil callback() end end function BattleUnitComp:onRoundEnd() self.unitEntity:onRoundEnd() end function BattleUnitComp:tick(dt) if self.isClear then return end 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) 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:getIsClear() return self.isClear end function BattleUnitComp:clear() if self.isClear then return end self.isClear = true end function BattleUnitComp:recycle() BattleHelper:recycleBattleHeroModel(self.modelId, self.baseObject) end return BattleUnitComp