c1_lua/lua/app/module/battle/component/battle_unit_comp.lua
2023-05-25 10:37:49 +08:00

1898 lines
56 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 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()
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: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: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)
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:getKeyFrameTime(skill, blockIndex, animationName)
self.validEffectIdx[1] = 1
self.validEffectIdx[2] = 1
if not skill then
return 0
end
self.currAttackBlockIndex = blockIndex
local time = skill:getEffectBlockTime()[blockIndex]
if not time then
if blockIndex == 1 then
time = self:getAnimationKeyFrameTime(animationName)
else
time = 0
end
else
local blockList = skill:getEffectBlock()
local beforeIndex = blockIndex - 1
self.validEffectIdx[1] = blockList[beforeIndex] or 1
self.validEffectIdx[2] = blockList[blockIndex] or 1
end
return time
end
function BattleUnitComp:getIsCentralizedAttack()
return self.team:getCentralizedAttack()
end
function BattleUnitComp:getCurAttackActionState()
return self.curAttackActionState
end
function BattleUnitComp:beforeAttack(actionState)
self.team:setCentralizedAttack(true)
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.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 state == UNIT_STATE.IDLE then -- idle为默认状态其状态下判定特殊状态
if self.unitEntity:getIsFrozen() then -- 有冰冻buff
state = UNIT_STATE.FROZEN
elseif self.unitEntity:getIsLethargy() or self.unitEntity: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.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()
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: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.hurtAniNameList[math.random(1, self.hurtAniNameCount)]
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.baseObject:fastGetLocalPosition()
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
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: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()
if skill then
local attackName = skill:getSkillAttackName()
self.currAttackKeyTime = self:getKeyFrameTime(skill, self.currAttackBlockIndex + 1, attackName)
else
self.currAttackKeyTime = 0
end
self:onSkillTakeEffect(skill, self.currAttackKeyTime <= 0, self.validEffectIdx)
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.UNIT_FRONT_POS_X
self.moveDirection = 1
else
self.targetX = -BattleConst.UNIT_FRONT_POS_X
self.moveDirection = -1
end
else
self.isMove = false
local attackName = skill:getSkillAttackName()
if self.normalSkillCount > 0 then
self:attackAndSpeedUp()
end
self.currAttackDuration = self:getAnimationDuration(attackName)
self.currAttackKeyTime = self:getKeyFrameTime(skill, 1, attackName)
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.currActiveSkill:startUse()
self:doNextSkillAttack()
self:checkPassiveEvent(PASSIVE_EVENT.ON_ACTIVE_SKILL_BEFORE, self)
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
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()
if skill then
local attackName = skill:getSkillAttackName()
self.currAttackKeyTime = self:getKeyFrameTime(skill, self.currAttackBlockIndex + 1, attackName)
else
self.currAttackKeyTime = 0
end
local isFinalBlock = self.currAttackKeyTime <= 0
if self.normalSkillCount == 1 and self.currActiveSkill == nil and isFinalBlock then -- 最后一次攻击
self.team:setCentralizedAttack(false)
end
self:onSkillTakeEffect(skill, self.currAttackKeyTime <= 0, self.validEffectIdx)
if self.normalSkillCount == 1 and self.currActiveSkill == nil and isFinalBlock then -- 最后一次攻击
self.battleController:setIsPauseHpProgress(false)
end
else
local attackName = self.currActiveSkill:getSkillAttackName()
self.currAttackKeyTime = self:getKeyFrameTime(self.currActiveSkill, self.currAttackBlockIndex + 1, attackName)
local isFinalBlock = self.currAttackKeyTime <= 0
local isHaveNextAttack = self:getIsHaveNextAvailableActiveSkill()
if not isHaveNextAttack and isFinalBlock then
self.team:setCentralizedAttack(false)
end
self:onSkillTakeEffect(self.currActiveSkill, isFinalBlock, self.validEffectIdx)
if not isHaveNextAttack and isFinalBlock then
self.battleController:setIsPauseHpProgress(false)
end
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()
self.currAttackDuration = self:getAnimationDuration(attackName)
self.currAttackKeyTime = self:getKeyFrameTime(self.currActiveSkill, 1, attackName)
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: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: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: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)
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
local attackName = skill:getSkillAttackName()
self.currAttackDuration = self:getAnimationDuration(attackName)
self.currAttackKeyTime = self:getKeyFrameTime(skill, 1, attackName)
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()
if skill then
local attackName = skill:getSkillAttackName()
self.currAttackKeyTime = self:getKeyFrameTime(skill, self.currAttackBlockIndex + 1, attackName)
else
self.currAttackKeyTime = 0
end
local isFinalBlock = self.currAttackKeyTime <= 0
if self.normalSkillCount == 1 and isFinalBlock then -- 如果是最后一次攻击,那么敌人受到这次攻击可以开始嗝屁了
self.team:setCentralizedAttack(false)
end
self:onSkillTakeEffect(skill, isFinalBlock, self.validEffectIdx)
if self.normalSkillCount == 1 and isFinalBlock then -- 如果是最后一次攻击,那么可以开始跑血条了
self.battleController:setIsPauseHpProgress(false)
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)
return self.team:addBuff(buffEffect)
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()
self.team:removeAllBuff()
end
function BattleUnitComp:removeBuffByName(buffName)
self.team:removeBuffByName(buffName)
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
if not validEffectIdx then
validEffectIdx = {1, 1}
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 -- 格挡成功
target:playBlock()
return
end
end
end
end
local succ = false
for k, effect in ipairs(effectList) do
if k >= validEffectIdx[1] and k <= validEffectIdx[2] then
if self:judgeSkillEffectCondition(skill, k) then
if self:takeEffect(effect, target) then
succ = true
end
end
end
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
BattleHelper:playSkillSound(soundHit, 0)
end
end
end
function BattleUnitComp:judgeSkillEffectCondition(skill, index)
if not skill then
return true
end
local buffConditions = skill:getBuffCondition(index)
local conditionRel = skill:getBuffConditionRel(index)
return BATTLE_SKILL_CONDITION_HANDLE.judgeSkillEffectCondition(buffConditions, conditionRel, self.battleController)
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
if self.unitEntity:getIsFrozen() and buff:getDecr() == BattleConst.BUFF_DECR_TYPE.INCREASE_GAIN 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
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)
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)
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
end
atker.unitEntity:addDamageCount(num)
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
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
local shieldHpDiff = self.unitEntity:getShieldHp() - shieldHpBefore
if shieldHpDiff < 0 then -- 说明护盾减少了
self.team:handleShield(shieldHpDiff, self)
end
local hp = self.unitEntity:getHp()
local x, y = self.baseObject:fastGetLocalPosition()
local damage = num
if num < 0 then -- 伤害
local delayTime = 0
if shieldHpDiff < 0 then
damage = damage - shieldHpDiff
delayTime = BattleConst.EFFECT_NUMBER_DELAY
if self.side == BattleConst.SIDE_ATK then
self:showEffectNumber(BattleConst.EFFECT_COLOR_BLUE, BattleConst.EFFECT_TYPE_MOVE_L, shieldHpDiff, x, y, 0)
else
self:showEffectNumber(BattleConst.EFFECT_COLOR_BLUE, BattleConst.EFFECT_TYPE_MOVE_R, shieldHpDiff, x, y, 0)
end
end
if damage < 0 then
if effectStatus == HURT_STATE_CRIT then
self:showEffectNumber(BattleConst.EFFECT_COLOR_RED, BattleConst.EFFECT_TYPE_CRIT, "c" .. damage, x, y, delayTime)
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)
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.unitEntity: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 -- 治疗
local time = Time:getServerTime()
if self.lastHealTime == time then
self.lastSameTimeHealCount = self.lastSameTimeHealCount + 1
else
self.lastHealTime = time
self.lastSameTimeHealCount = 0
end
local delayTime = self.lastSameTimeHealCount * 0.1
self:showEffectNumber(BattleConst.EFFECT_COLOR_GREEN, BattleConst.EFFECT_TYPE_BUFF, "+" .. num, x, y, delayTime)
end
local hpPercent = self.unitEntity:getHpPercent()
self.battleController:refreshHp(self.side, hp, hpPercent)
if atker:getIsCentralizedAttack() then
if damage < 0 then
self:playHurt()
end
else
if self.unitEntity:getIsDead() then
self:changeState(UNIT_STATE.DEAD)
if damageOrCureType == BattleConst.BUFF_NAME.BURN then
local target = self.battleController:getOtherSideMainUnit(self.side)
target:checkPassiveEvent(BattleConst.PASSIVE_EVENT.ON_DEAD_BY_BURN, target)
end
elseif damage < 0 then
self: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:showEffectNumber(colorType, effectType, num, x, y, delayTime)
local addY = BattleConst.MIN_NODE_HEIGHT[self.unitEntity:getBody()] or BattleConst.MIN_NODE_HEIGHT_DEFAULT
self.battleController:showEffectNumber(colorType, effectType, num, x, y + addY, delayTime)
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:playSkillFx(skill)
self:playSkillSelfFx(skill)
self:playSkillTargetFx(skill)
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.follow_direction then
if self.side == BattleConst.SIDE_ATK then
if effectObj:getIsEulerAnglesFlip() then
effectObj:setLocalEulerAngles(0, 0, 0)
end
effectObj:setLocalScale(fxScale, fxScale, fxScale)
else
if effectObj:getIsEulerAnglesFlip() then
effectObj:setLocalEulerAngles(0, 180, 0)
effectObj:setLocalScale(fxScale, fxScale, fxScale)
else
effectObj:setLocalScale(-fxScale, fxScale, fxScale)
end
end
else
if effectObj:getIsEulerAnglesFlip() then
effectObj:setLocalEulerAngles(0, 0, 0)
end
effectObj:setLocalScale(fxScale, fxScale, fxScale)
end
local baseOrder = BattleHelper:getBaseOrder()
effectObj:setSortingOrder(baseOrder, 10)
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:getIsClear()
return self.isClear
end
function BattleUnitComp:clear()
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
return BattleUnitComp