local BattleBuffHandle = require "app/module/battle/helper/battle_buff_handle" local BattleConst = require "app/module/battle/battle_const" local BattleHelper = require "app/module/battle/helper/battle_helper" local BattleTeam = class("BattleTeam") function BattleTeam:init(side, battleController) self.side = side self.battleController = battleController self.unitList = {} self.unitMap = {} self.buffList = {} self.sameBuffCount = {} self.sameBuffEffectNum = {} -- 相同的buff参数,用于判定buff数值上限 self.shieldBuffList = {} self.loopFxMap = {} self.comboCount = 0 self.cacheBuffDecr = {} self.cacheComboTag = {} end function BattleTeam:addUnit(unit, isMainUnit) unit:setTeam(self) self.unitMap[unit:getMatchType()] = unit table.insert(self.unitList, unit) if isMainUnit then self.mainUnit = unit end end function BattleTeam:checkPassiveEvent(...) for k, v in ipairs(self.unitList) do v:checkPassiveEvent(...) end end function BattleTeam:prepare() for k, v in ipairs(self.unitList) do v:prepare() end end function BattleTeam:getBuffList() return self.buffList end function BattleTeam:getMainUnit() return self.mainUnit end function BattleTeam:removeAllUnits() for k, v in pairs(self.unitMap) do self.unitMap[k] = nil end local count = #self.unitList for i = 1, count do self.unitList[i]:recycle() table.remove(self.unitList) end self.mainUnit = nil end function BattleTeam:useNormalSkill(matchType, count, isFinalAction, effectType, actionState, callback) self.isFinalAction = isFinalAction local unit = nil if matchType == nil then unit = self.unitList[1] else unit = self.unitMap[matchType] end if unit == nil then return callback() end if unit:getIsLimit() then return callback() end self.mainUnit = unit unit:beforeAttack(actionState) unit:resetBeforeAttack() unit:useNormalSkill(count, effectType, callback) end function BattleTeam:useSkill(matchType, count, isFinalAction, effectType, actionState, callback) self.isFinalAction = isFinalAction local unit = nil if matchType == nil then unit = self.unitList[1] else unit = self.unitMap[matchType] end if unit == nil then return callback() end if unit:getIsLimit() then return callback() end local lastMainUnit = self.mainUnit self.mainUnit = unit unit:beforeAttack(actionState) unit:resetBeforeAttack() if unit:useSkill(1, count, callback) then if lastMainUnit and lastMainUnit ~= unit then lastMainUnit:playSwitchOut() end else if lastMainUnit and lastMainUnit ~= unit then self.mainUnit = lastMainUnit end end end -- function BattleTeam:useAssistingSkill(assistingList, isFinalAction, callback) -- self.isFinalAction = isFinalAction -- if self.mainUnit == nil then -- return callback() -- end -- if self.mainUnit:getIsLimit() then -- return callback() -- end -- local count = #assistingList -- if count <= 0 then -- return callback() -- end -- self:setCentralizedAttack(true) -- local function finish() -- count = count - 1 -- if count == 0 then -- self:setCentralizedAttack(false) -- callback() -- end -- end -- local delay = 0 -- for _, v in ipairs(assistingList) do -- local unit = self.unitMap[v.skillMatch] -- if unit then -- unit:resetBeforeAttack() -- unit:useAssistingSkill(v.count, delay, finish) -- delay = delay + BattleHelper:getSupportInterval() -- else -- finish() -- end -- end -- end function BattleTeam:mainUnitUseAllSkills(actionState, callback) self.isFinalAction = true if self.mainUnit == nil then return callback() end if self.mainUnit:getIsLimit() then return callback() end self.mainUnit:beforeAttack(actionState) self.mainUnit:resetBeforeAttack() self.mainUnit:useAllSkills(callback) end function BattleTeam:changeMainUnit(matchType) if self.mainUnit and matchType == self.mainUnit:getMatchType() then return end local unit = self.unitMap[matchType] if unit == nil then return end self.mainUnit:playSwitchOut() self.mainUnit = unit unit:playSwitchIn() end function BattleTeam:changeDead() if not self.mainUnit then return end self.mainUnit:changeState(BattleConst.UNIT_STATE.DEAD) end function BattleTeam:playHurt() if not self.mainUnit then return end self.mainUnit:playHurt() end function BattleTeam:getMainUnitLocalPosition(backup) if not self.mainUnit then return backup.baseObject:fastGetLocalPosition() end return self.mainUnit.baseObject:fastGetLocalPosition() end -- 回合结束的时候要结算buff和技能 function BattleTeam:onRoundEnd() for k, v in ipairs(self.unitList) do v:onRoundEnd() end self:doBuffWork() self:doFinalBuffWork() self.comboCount = 0 if self:getMainUnit():isInitState() then return end self:getMainUnit():changeState(BattleConst.UNIT_STATE.IDLE) end function BattleTeam:addShield(buffEffect) if buffEffect then table.insert(self.shieldBuffList, buffEffect) end end function BattleTeam:addInvincibleShield(buffEffect) if buffEffect then table.insert(self.shieldBuffList, 1, buffEffect) end end function BattleTeam:removeShield(buffEffect) for k, v in ipairs(self.shieldBuffList) do if v == buffEffect then table.remove(self.shieldBuffList, k) break end end end function BattleTeam:handleShield(reduceShield, unit) if #self.shieldBuffList <= 0 then return end local needReedRefreshBuff = false local currShieldBuff = self.shieldBuffList[1] while currShieldBuff do if reduceShield <= 0 and currShieldBuff.buff and currShieldBuff.buff:getName() == BattleConst.BUFF_NAME.INVINCIBLE_SHIELD then reduceShield = currShieldBuff.result - 1 needReedRefreshBuff = true else reduceShield = reduceShield + currShieldBuff.result end if reduceShield > 0 then currShieldBuff.result = reduceShield reduceShield = 0 break else currShieldBuff.result = 0 for k, v in ipairs(self.buffList) do if v == currShieldBuff then if not needReedRefreshBuff and currShieldBuff.buff:getIcon() then needReedRefreshBuff = true end self:updateBuffState(currShieldBuff.buff, -1) table.remove(self.buffList, k) BattleBuffHandle.removeBuff(unit, currShieldBuff) currShieldBuff = nil break end end if currShieldBuff then table.remove(self.shieldBuffList, 1) end end currShieldBuff = self.shieldBuffList[1] end if needReedRefreshBuff then self.battleController:refreshBuff(self.side, self.buffList) end self:calSameBuffEffectNum() end function BattleTeam:addBuff(buffEffect) if not self:judgeBuffEffectEffectNumOverflow(buffEffect.buff) then return end local stack = buffEffect.buff:getStack() local needRecycle if not stack or stack == BattleConst.BUFF_STACK_TYPE.CANT_ADD then local buffName = buffEffect.buff:getName() local buffNum = self.sameBuffCount[buffName] if buffNum and buffNum > 0 then for _, bEffect in ipairs(self.buffList) do if bEffect.buff:getName() == buffName then if bEffect.round < buffEffect.round then bEffect.round = buffEffect.round for fieldName, v in pairs(bEffect) do if fieldName ~= "buff" and fieldName ~= "round" and fieldName ~= "result" then bEffect[fieldName] = buffEffect[fieldName] end end if bEffect.buff:getEffectNum() < buffEffect.buff:getEffectNum() then bEffect.buff:setEffectNum(buffEffect.buff:getEffectNum()) end needRecycle = bEffect break elseif bEffect.buff:getEffectNum() < buffEffect.buff:getEffectNum() then bEffect.buff:setEffectNum(buffEffect.buff:getEffectNum()) needRecycle = bEffect break else return bEffect end end end end elseif stack == BattleConst.BUFF_STACK_TYPE.ADD_ROUND then local buffName = buffEffect.buff:getName() local buffNum = self.sameBuffCount[buffName] if buffNum and buffNum > 0 then for _, bEffect in ipairs(self.buffList) do if bEffect.buff:getName() == buffName then bEffect.round = bEffect.round + buffEffect.round for fieldName, v in pairs(bEffect) do if fieldName ~= "buff" and fieldName ~= "round" and fieldName ~= "result" then bEffect[fieldName] = buffEffect[fieldName] end end if bEffect.buff:getEffectNum() < buffEffect.buff:getEffectNum() then bEffect.buff:setEffectNum(buffEffect.buff:getEffectNum()) end needRecycle = bEffect break end end end elseif stack == BattleConst.BUFF_STACK_TYPE.ADD then elseif stack == BattleConst.BUFF_STACK_TYPE.REMOVE_LAST then local buffName = buffEffect.buff:getName() self:removeBuffByName(buffName) end if needRecycle then BattleHelper:recycleBuffEffect(buffEffect) else table.insert(self.buffList, buffEffect) self:updateBuffState(buffEffect.buff, 1) needRecycle = buffEffect end if buffEffect.buff:getIcon() then self.battleController:refreshBuff(self.side, self.buffList) end self:calSameBuffEffectNum() return needRecycle end function BattleTeam:removeAllBuff() local buffEffect = nil local count = #self.buffList for i = count, 1, -1 do buffEffect = self.buffList[i] if buffEffect then self:updateBuffState(buffEffect.buff, -1) table.remove(self.buffList, i) BattleBuffHandle.removeBuff(self.mainUnit, buffEffect) end end if self.cacheBuffDecr then for decr, list in pairs(self.cacheBuffDecr) do count = #list for i = count, 1, -1 do buffEffect = self.cacheBuffDecr[decr][i] table.remove(self.cacheBuffDecr[decr], i) BattleHelper:recycleBuffEffect(buffEffect) end end end self.battleController:clearBuff(self.side) self:calSameBuffEffectNum() end function BattleTeam:putCacheBuff(buffEffect) local buffDecr = buffEffect.buff:getDecr() if not self.cacheBuffDecr[buffDecr] then self.cacheBuffDecr[buffDecr] = {} end table.insert(self.cacheBuffDecr[buffDecr], buffEffect) end function BattleTeam:putCacheBuffByDecr(buffDecr) if not buffDecr then return end local needRefresh = false local buffEffect = nil local count = #self.buffList for i = count, 1, -1 do buffEffect = self.buffList[i] if buffEffect and buffEffect.buff:getDecr() == buffDecr and not buffEffect.buff:isCantRemove() then self:updateBuffState(buffEffect.buff, -1) table.remove(self.buffList, i) BattleBuffHandle.removeBuff(self.mainUnit, buffEffect, true) if not self.cacheBuffDecr[buffDecr] then self.cacheBuffDecr[buffDecr] = {} end table.insert(self.cacheBuffDecr[buffDecr], buffEffect) if buffEffect.buff:getIcon() then needRefresh = true end end end if needRefresh then self.battleController:refreshBuff(self.side, self.buffList) end self:calSameBuffEffectNum() end function BattleTeam:popCacheBuffByDecr(buffDecr) if not buffDecr or not self.cacheBuffDecr or not self.cacheBuffDecr[buffDecr] then return end local list = self.cacheBuffDecr[buffDecr] local needRefresh = false local count = #list local buffEffect for i = count, 1, -1 do buffEffect = self.cacheBuffDecr[buffDecr][i] self:getMainUnit():reTakeEffectByBuffEffect(buffEffect) table.remove(self.cacheBuffDecr[buffDecr]) if buffEffect.buff:getIcon() then needRefresh = true end end if needRefresh then self.battleController:refreshBuff(self.side, self.buffList) end self:calSameBuffEffectNum() end function BattleTeam:calSameBuffEffectNum() if not self.buffList then return end self.sameBuffEffectNum = table.clearOrCreate(self.sameBuffEffectNum) for _, buffEffect in ipairs(self.buffList) do local buffEntity = buffEffect.buff if buffEntity then local buffName = buffEntity:getName() local buffNum = buffEntity:getEffectNum() if buffName and buffNum then self.sameBuffEffectNum[buffName] = (self.sameBuffEffectNum[buffName] or 0) + buffNum end end end end function BattleTeam:judgeBuffEffectEffectNumOverflow(buffEntity) if not buffEntity then return true end local limitNum = buffEntity:getLimitParameter() if not limitNum then return true end local buffName = buffEntity:getName() local buffNum = buffEntity:getEffectNum() local curNum = self.sameBuffEffectNum[buffName] or 0 local remainNum = limitNum - curNum if remainNum <= 0 then -- 已经超出上限了,直接返回失败 return false end if buffNum > remainNum then buffEntity:setEffectNum(remainNum) end return true end function BattleTeam:doBuffWork() local count = nil local buffEffect = nil if self.cacheBuffDecr then for decr, list in pairs(self.cacheBuffDecr) do count = #list for i = count, 1, -1 do buffEffect = self.cacheBuffDecr[decr][i] buffEffect.round = buffEffect.round - 1 if buffEffect.round <= 0 then table.remove(self.cacheBuffDecr[decr], i) BattleHelper:recycleBuffEffect(buffEffect) end end end end count = #self.buffList if count <= 0 then return end buffEffect = nil for i = count, 1, -1 do buffEffect = self.buffList[i] if not buffEffect then break end if not BattleConst.FINAL_WORK_BUFF[buffEffect.buff:getName()] then buffEffect.round = buffEffect.round - 1 local target = self.mainUnit if buffEffect.target then target = buffEffect.target end BattleBuffHandle.doBuffWork(target, buffEffect) if not self.buffList[i] then -- dot伤害致死后,buff已经全部移除 break end if buffEffect.round <= 0 then self:updateBuffState(buffEffect.buff, -1) table.remove(self.buffList, i) BattleBuffHandle.removeBuff(target, buffEffect) end end end self.battleController:refreshBuff(self.side, self.buffList) self:calSameBuffEffectNum() end -- 比如复活类,需要最后触发buff function BattleTeam:doFinalBuffWork() if not self:getMainUnit() or self:getMainUnit().unitEntity:getIsDead() or self:getMainUnit().unitEntity:getIsRebirth() then return end local count = nil local buffEffect = nil count = #self.buffList if count <= 0 then return end local refreshUI = false for i = count, 1, -1 do buffEffect = self.buffList[i] if not buffEffect then break end if BattleConst.FINAL_WORK_BUFF[buffEffect.buff:getName()] then refreshUI = true buffEffect.round = buffEffect.round - 1 local target = self.mainUnit if buffEffect.target then target = buffEffect.target end BattleBuffHandle.doBuffWork(target, buffEffect) if not self.buffList[i] then -- dot伤害致死后,buff已经全部移除 break end if buffEffect.round <= 0 then self:updateBuffState(buffEffect.buff, -1) table.remove(self.buffList, i) BattleBuffHandle.removeBuff(target, buffEffect) end end end if refreshUI then self.battleController:refreshBuff(self.side, self.buffList) end self:calSameBuffEffectNum() end function BattleTeam:removeBuffByName(buffName) local count = #self.buffList if count <= 0 then return end local buffEffect = nil for i = count, 1, -1 do buffEffect = self.buffList[i] if buffEffect.buff:getName() == buffName and not buffEffect.buff:isCantRemove() then self:updateBuffState(buffEffect.buff, -1) table.remove(self.buffList, i) BattleBuffHandle.removeBuff(self.mainUnit, buffEffect) end end self.battleController:refreshBuff(self.side, self.buffList) self:calSameBuffEffectNum() end function BattleTeam:removeBuffByDecr(buffDecr) local count = #self.buffList if count <= 0 then return end local buffEffect = nil for i = count, 1, -1 do buffEffect = self.buffList[i] if buffEffect.buff:getDecr() == buffDecr and not buffEffect.buff:isCantRemove() then self:updateBuffState(buffEffect.buff, -1) table.remove(self.buffList, i) BattleBuffHandle.removeBuff(self.mainUnit, buffEffect) end end self.battleController:refreshBuff(self.side, self.buffList) self:calSameBuffEffectNum() end function BattleTeam:removeAllShield() local count = nil count = #self.buffList if count <= 0 then return end local buffEffect = nil for i = count, 1, -1 do buffEffect = self.buffList[i] if not buffEffect then break end local buff = buffEffect.buff if buff:isShield() and not buff:isCantRemove() then local target = self.mainUnit self:updateBuffState(buff, -1) table.remove(self.buffList, i) BattleBuffHandle.removeBuff(target, buffEffect) end end self.battleController:refreshBuff(self.side, self.buffList) self:calSameBuffEffectNum() end function BattleTeam:updateBuffState(buff, num) local buffName = buff:getName() local buffNum = (self.sameBuffCount[buffName] or 0) + num self.sameBuffCount[buffName] = buffNum if buffNum == 0 then -- 移除buff local fxList = buff:getFxContinued() if fxList then local fxCfg = BattleHelper:getFxConfig() for k, v in ipairs(fxList) do local fxInfo = fxCfg[v] if fxInfo then local res = fxInfo.res local count = self.loopFxMap[res] or 0 self.loopFxMap[res] = count - 1 if count == 1 then for k2, v2 in ipairs(self.unitList) do v2:removeFx(res) end end end end end local fxDisappear = buff:getFxDisappear() if fxDisappear then local fxCfg = BattleHelper:getFxConfig() for k, v in ipairs(fxDisappear) do local fxInfo = fxCfg[v] if fxInfo then self.mainUnit:getEffectAndPlay(fxInfo, false) end end end elseif buffNum == 1 then -- 新添加buff local fxList = buff:getFxContinued() if fxList then local fxCfg = BattleHelper:getFxConfig() for k, v in ipairs(fxList) do local fxInfo = fxCfg[v] if fxInfo then local res = fxInfo.res local count = self.loopFxMap[res] or 0 self.loopFxMap[res] = count + 1 if count == 0 then for k2, v2 in ipairs(self.unitList) do v2:getEffectAndPlay(fxInfo, true) end end end end end end end function BattleTeam:hadUniversalBuff() for i,v in ipairs(self.buffList) do if v.buff:getName() == BattleConst.BUFF_NAME.RANDOM_UNIVERSAL and v.buff:isActive() then return true end end return false end function BattleTeam:hadUMainHeroExtAddBuff() for i,v in ipairs(self.buffList) do if v.buff:getName() == BattleConst.BUFF_NAME.MAIN_HERO_ENERGYADD then return true, v.buff:getEffectNum() end end return false end function BattleTeam:getElementExtRatio() local weights = {} for i,v in ipairs(self.buffList) do if v.buff:getName() == BattleConst.BUFF_NAME.RED_REFRESH_WEIGHT then weights[BattleConst.ELEMENT_TYPE.RED] = v.buff:getEffectNum() elseif v.buff:getName() == BattleConst.BUFF_NAME.GREEN_REFRESH_WEIGHT then weights[BattleConst.ELEMENT_TYPE.GREEN] = v.buff:getEffectNum() elseif v.buff:getName() == BattleConst.BUFF_NAME.YELLOW_REFRESH_WEIGHT then weights[BattleConst.ELEMENT_TYPE.YELLOW] = v.buff:getEffectNum() elseif v.buff:getName() == BattleConst.BUFF_NAME.BLUE_REFRESH_WEIGHT then weights[BattleConst.ELEMENT_TYPE.BLUE] = v.buff:getEffectNum() elseif v.buff:getName() == BattleConst.BUFF_NAME.PURPLE_REFRESH_WEIGHT then weights[BattleConst.ELEMENT_TYPE.PURPLE] = v.buff:getEffectNum() end end return weights end -- 检查是否带有万能块buff function BattleTeam:checkUniversal() if self:hadUniversalBuff() then return true end end -- 检查是否带有额外能量加层 function BattleTeam:checkMainHeroExtAdd() local hadBuff, effectNum = self:hadUMainHeroExtAddBuff() if hadBuff then return true, effectNum end end function BattleTeam:getBuffCountByName(buffName) return self.sameBuffCount[buffName] or 0 end function BattleTeam:getLoopFxResCount(res) return self.loopFxMap[res] or 0 end function BattleTeam:getUnitComp() return self.unitMap end function BattleTeam:getIsBoss() if self.mainUnit == nil then return false end return self.mainUnit:getIsBoss() end function BattleTeam:playRunAction() if self.mainUnit then self.mainUnit:playRunAction() end end function BattleTeam:stopRunAction() if self.mainUnit then self.mainUnit:stopRunAction() end end function BattleTeam:playWinAction() if self.mainUnit then self.mainUnit:playWinAction() end end function BattleTeam:recoverHpOnWaveOver(callback) if self.mainUnit then self.mainUnit:recoverHpOnWaveOver(callback) else callback() end end function BattleTeam:getCentralizedAttack() return self.centralizedAttack end function BattleTeam:setCentralizedAttack(centralizedAttack) if not self.isFinalAction and not centralizedAttack then return end self.centralizedAttack = centralizedAttack end function BattleTeam:setIsFinalBlock(isFinalBlock) if not self.isFinalBlock and not isFinalBlock then return end self.isFinalBlock = isFinalBlock end function BattleTeam:getIsFinalBlock() if self.isFinalBlock == nil then return true end return self.isFinalBlock end function BattleTeam:addCombo() if self.side ~= BattleConst.SIDE_ATK then if not BattleConst.IS_PVP_BATTLE[self.battleController.battleType] then return end end self.comboCount = self.comboCount + 1 self.battleController:showCombo(self.comboCount, self.side) if self.side == BattleConst.SIDE_ATK then -- 任务 if self.comboCount == 10 then self.battleController:addTaskProgress(BattleConst.BATTLE_TASK_FIELD.COMBO_OVER_10, 1) end end end function BattleTeam:addHurtComboTag(matchType) self.cacheComboTag[matchType] = (self.cacheComboTag[matchType] or 0) + 1 end function BattleTeam:reduceHurtComboTag(matchType) if not self.cacheComboTag[matchType] or self.cacheComboTag[matchType] <= 0 then return end self.cacheComboTag[matchType] = (self.cacheComboTag[matchType] or 0) - 1 end function BattleTeam:getHurtComboTag(matchType) local combotag = self.cacheComboTag[matchType] if not combotag or combotag <= 0 then combotag = self.cacheComboTag[BattleConst.COMBO_DEFAULT_POSITION] -- 全部 end if not combotag or combotag <= 0 then return false end return true end function BattleTeam:clearHurtComboTag() table.clear(self.cacheComboTag) end function BattleTeam:onActionOver() self:setIsFinalBlock(true) self:setCentralizedAttack(false) self:clearHurtComboTag() -- 处理反击 local counterAttackCount = self:getMainUnit().unitEntity:getCounterAttackCount() if counterAttackCount <= 0 then return end self:getMainUnit().unitEntity:clearCounterAttackCount() local teamAction = function() ---- 普攻 local skillMatch if self.side == BattleConst.SIDE_ATK then self.battleController.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_ATK_STEP skillMatch = self:getMainUnit().unitEntity:getMatchType() else self.battleController.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_DEF_STEP skillMatch = self:getMainUnit().unitEntity:getMatchType() end self:useNormalSkill(skillMatch, counterAttackCount, true, BattleConst.EFFECT_TYPE.DIRECT, BattleConst.ATTACK_ACTION_STATE.COUNTERATTACK, function() self.battleController:enterNextTeamAction() end) end self.battleController:addTeamActionList(teamAction, 1) self.comboCount = 0 end function BattleTeam:tick(dt) for k, v in ipairs(self.unitList) do v:tick(dt) end end return BattleTeam