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 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 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:playAnimation(SPINE_ANIMATION_NAME.IDLE, true, false) end function BattleUnitComp:_initBase() self.isClear = false self.isDead = false self.isMove = false self.attackTime = 0 self.currAttackDuration = 0 self.currAttackKeyTime = 0 self.isPlayHurt = 0 self.attackDurationMap = {} 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:playBorn() 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:useNormalSkill(count, callback) self.baseObject:getTransform():SetAsLastSibling() self.actionOverCallback = callback self.normalSkillCount = count if not self:changeState(UNIT_STATE.NORMAL_ATTACK) then self.actionOverCallback = nil callback() end end function BattleUnitComp:changeState(state) if self.currState == state and not self:repeatCurrState() then return false end if self.isDead 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 then self:exitSkillState() elseif self.currState == UNIT_STATE.DEAD then self:exitDeadState() 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 then self:enterSkillState() elseif state == UNIT_STATE.DEAD then self:enterDeadState() elseif self.currState == UNIT_STATE.BORN then self:enterBornState() end return true end function BattleUnitComp:repeatCurrState() if self.currState == UNIT_STATE.IDLE then return false elseif self.currState == UNIT_STATE.NORMAL_ATTACK then return true elseif self.currState == UNIT_STATE.SKILL then return true elseif self.currState == UNIT_STATE.DEAD then return false end return false 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:enterNormalAttackState() self.attackOver = false self.attackTime = 0 self.currAttackKeyTime = 0.3 local skill = self.unitEntity:getNormalSkill() 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: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:changeState(UNIT_STATE.IDLE) local callback = self.actionOverCallback self.actionOverCallback = nil if callback then callback() end else -- 到位置该攻击了 self.attackTime = 0 local skill = self.unitEntity:getNormalSkill() local attackName = skill:getRandomNormalAttackName() self.currAttackDuration = self:getAnimationDuration(attackName) self:playAnimation(attackName, false, false) 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.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 else self:changeState(UNIT_STATE.IDLE) local callback = self.actionOverCallback self.actionOverCallback = nil if callback then callback() end end return else -- 继续攻击 self.attackTime = 0 local skill = self.unitEntity:getNormalSkill() local attackName = skill:getRandomNormalAttackName() self.currAttackDuration = self:getAnimationDuration(attackName) self:playAnimation(attackName, false, false) end else if self.currAttackKeyTime > 0 and self.attackTime >= self.currAttackKeyTime then -- 到达关键后使用 self.currAttackKeyTime = 0 local skill = self.unitEntity:getNormalSkill() self:onSkillTakeEffect(skill) end end end function BattleUnitComp:onSkillTakeEffect(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 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) 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:takeDamageOrCure(atker, buff, num, effectType, effectStatus) if num == 0 then return 0 end self.unitEntity:takeDamageOrCure(num) if self.currState == UNIT_STATE.INIT or self.currState == UNIT_STATE.IDLE then self:playHurt() end local x, y, z = self.baseObject:fastGetLocalPosition() self:showEffectNumber(num, x, y) local hpPercent = self.unitEntity:getHpPercent() -- self.controlUnitComp:RefreshHpBar(hpPercent) -- local shieldHp = self.unitEntity:getShieldHp() -- if shieldHp and shieldHp.value > 0 then -- local percent = self.unitEntity:getShieldHpPercent() -- self.controlUnitComp:RefreshShieldBar(percent, true) -- else -- self.controlUnitComp:RefreshShieldBar(0, false) -- end end function BattleUnitComp:showEffectNumber(num, x, y) self.battleController:showEffectNumber(num, x, y) end function BattleUnitComp:tick(dt) if self.isClear then return end if self.isDead 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 then self:updateSkill(dt) end end return BattleUnitComp