c1_lua/lua/app/module/battle/component/battle_unit_comp.lua
2023-04-19 18:39:46 +08:00

1167 lines
32 KiB
Lua

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.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: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.attackCount = 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: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
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 == 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:getIsCentralizedAttack()
return self.centralizedAttack
end
function BattleUnitComp:beforeAttack()
self.centralizedAttack = true
self.battleController:setIsPauseHpProgress(true)
self:checkPassiveEvent(PASSIVE_EVENT.ON_UNI_ATTACK_START, self)
end
function BattleUnitComp:useAssistingSkill(count, delay, 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 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.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)
self.centralizedAttack = false
callback()
return
end
if not self:changeState(UNIT_STATE.NORMAL_ATTACK) then
self.actionOverCallback = nil
self.battleController:setIsPauseHpProgress(false)
self.centralizedAttack = false
callback()
end
else
if not self:changeState(UNIT_STATE.SKILL_ATTACK) then
self.actionOverCallback = nil
self.battleController:setIsPauseHpProgress(false)
self.centralizedAttack = 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)
self.centralizedAttack = false
callback()
return
end
if not self:changeState(UNIT_STATE.NORMAL_ATTACK) then
self.actionOverCallback = nil
self.battleController:setIsPauseHpProgress(false)
self.centralizedAttack = false
callback()
end
else
if not self:changeState(UNIT_STATE.SKILL_ATTACK) then
self.actionOverCallback = nil
self.battleController:setIsPauseHpProgress(false)
self.centralizedAttack = 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)
self.centralizedAttack = 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()
elseif self.currState == UNIT_STATE.WAIT then
self:exitWaitState()
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.BORN then
self:enterBornState()
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()
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)
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
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: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: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.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:attackAndSpeedUp()
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)
self:attackAndSpeedUp()
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
if self.normalSkillCount == 1 and self.currActiveSkill == nil then -- 最后一次攻击
self.centralizedAttack = false
end
local skill = self.unitEntity:getNormalSkill()
self:onSkillTakeEffect(skill)
if self.normalSkillCount == 1 and self.currActiveSkill == nil then -- 最后一次攻击
self.battleController:setIsPauseHpProgress(false)
end
else
local isHaveNextAttack = self:getIsHaveNextAvailableActiveSkill()
if not isHaveNextAttack then
self.centralizedAttack = false
end
self:onSkillTakeEffect(self.currActiveSkill)
if not isHaveNextAttack 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:attackAndSpeedUp()
self.attackCount = self.attackCount + 1
if self.attackCount == 3 then
DataManager.BattleData:addTimeSpeed()
elseif self.attackCount == 5 then
DataManager.BattleData:addTimeSpeed()
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)
self:attackAndSpeedUp()
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)
self:attackAndSpeedUp()
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)
self:attackAndSpeedUp()
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)
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 -- 到达关键后使用
self.currAttackKeyTime = 0
if self.normalSkillCount == 1 then -- 如果是最后一次攻击,那么敌人受到这次攻击可以开始嗝屁了
self.centralizedAttack = false
end
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()
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)
if skill:getIsNormalType() then -- 普攻要计算一下格挡
local block = target.unitEntity:getBlock()
if block > 0 then
if BattleHelper:random(1, DEFAULT_FACTOR) <= block then -- 格挡成功
return
end
end
end
end
local succ = false
for k, effect in ipairs(effectList) do
if self:takeEffect(effect, target) then
succ = true
end
end
if succ and skill:getIsNormalType() then -- 普攻攻击成功的话
self:checkPassiveEvent(PASSIVE_EVENT.USE_NORMAL_SKILL, target)
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 self:getIsClear() then
return 0
end
if self.currState == UNIT_STATE.DEAD then
return 0
end
if num == 0 then
return 0
end
local shieldHpBefore = self.unitEntity:getShieldHp()
local hpRealReduce = self.unitEntity:takeDamageOrCure(num)
if hpRealReduce < 0 and self.side == BattleConst.SIDE_DEF then -- 实际掉血了
local exp = self.unitEntity:getExp()
if exp > 0 then
self.battleController:addBattleExp(math.floor(exp/self.unitEntity:getMaxHp()*-hpRealReduce))
end
end
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 atker:getIsCentralizedAttack() then
if self.currState == UNIT_STATE.IDLE then
self:playHurt()
end
else
if self.unitEntity:getIsDead() then
self:changeState(UNIT_STATE.DEAD)
elseif self.currState == UNIT_STATE.IDLE then
self:playHurt()
end
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 self:getIsClear() then
self.deadOverCallback = nil
return callback()
end
if self.currState ~= UNIT_STATE.DEAD and not self:changeState(UNIT_STATE.DEAD) then
self.deadOverCallback = 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: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)
elseif self.currState == UNIT_STATE.WAIT then
self:updateWaitState(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