local BattleManager = class("BattleManager", BaseModule) local BattleConst = GConst.BattleConst BattleManager.SKILL_CFG = ConfigManager:getConfig("skill") local BATTLE_CONTROLLER_BASE = "app/module/battle/controller/battle_controller" local BATTLE_CONTROLLER = { [BattleConst.BATTLE_TYPE.STAGE] = "app/module/battle/controller/battle_controller_stage", [BattleConst.BATTLE_TYPE.DAILY_CHALLENGE] = "app/module/battle/controller/battle_controller_daily_challenge", [BattleConst.BATTLE_TYPE.DUNGEON_GOLD] = "app/module/battle/controller/battle_controller_dungeon_gold", [BattleConst.BATTLE_TYPE.DUNGEON_SHARDS] = "app/module/battle/controller/battle_controller_dungeon_shards", [BattleConst.BATTLE_TYPE.ARENA] = "app/module/battle/controller/battle_controller_arena", [BattleConst.BATTLE_TYPE.DUNGEON_WEAPON] = "app/module/battle/controller/battle_controller_dungeon_weapon", [BattleConst.BATTLE_TYPE.DUNGEON_ARMOR] = "app/module/battle/controller/battle_controller_dungeon_armor", [BattleConst.BATTLE_TYPE.ACT_BOSS_RUSH] = "app/module/battle/controller/battle_controller_boss_rush", [BattleConst.BATTLE_TYPE.DUNGEON_RUNE] = "app/module/battle/controller/battle_controller_dungeon_rune", } function BattleManager:showPauseUI(battleType, battleController) if battleType == BattleConst.BATTLE_TYPE.ARENA then UIManager:showUI("app/ui/battle/battle_arena_pause_ui", {battleType = battleType, battleController = battleController}) else UIManager:showUI("app/ui/battle/battle_pause_ui", {battleType = battleType, battleController = battleController}) end end function BattleManager:showBattleResultUI(battleType, rewards, combatReport, mysteryBoxIdx, firstPassIdx, noMergeReward) UIManager:showUI("app/ui/battle/battle_result_ui", { battleType = battleType, isWin = combatReport.victory, rewards = rewards, atkReport = combatReport.atkReport, wave = combatReport.wave, mysteryBoxIdx = mysteryBoxIdx or 0, firstPassIdx = firstPassIdx or 0, remainRound = combatReport.remainRound or 0, noMergeReward = noMergeReward, }) end function BattleManager:showBattleArmorResultUI(battleType, rewards, combatReport, mysteryBoxIdx, firstPassIdx, noMergeReward) UIManager:showUI("app/ui/battle/battle_armor_result_ui", { battleType = battleType, isWin = combatReport.victory, rewards = rewards, atkReport = combatReport.atkReport, wave = combatReport.wave, mysteryBoxIdx = mysteryBoxIdx or 0, firstPassIdx = firstPassIdx or 0, remainRound = combatReport.remainRound or 0, noMergeReward = noMergeReward, }) end function BattleManager:showArenaBattleResultUI(settlement, rewards, checkCount) UIManager:showUI("app/ui/battle/battle_result_ui", { battleType = GConst.BattleConst.BATTLE_TYPE.ARENA, isWin = settlement.win, rewards = rewards, incrScore = settlement.incr_score, arenaTotalCount = checkCount, }) end function BattleManager:showBossRushBattleResultUI(battleType, combatReport, taskProgress) UIManager:showUI("app/ui/battle/battle_bossrush_result_ui", { battleType = battleType, combatReport = combatReport, taskProgress = taskProgress, }) end function BattleManager:showBoxOpenUI(rewards, callback) UIManager:showUI("app/ui/battle/battle_box_open_ui", {rewards = rewards, callback = callback}) end function BattleManager:reqSkillRefresh(isAd) if not isAd then local cost = GFunc.getConstReward("refresh_skill_cost") if not GFunc.checkCost(GFunc.getRewardId(cost), GFunc.getRewardNum(cost), true) then return end end self:sendMessage(ProtoMsgType.FromMsgEnum.BattleSkillRefreshReq, {ad = isAd}, {}, self.rspSkillRefresh, BIReport.ITEM_GET_TYPE.BATTLE_SKILL_REFRESH, true) end function BattleManager:rspSkillRefresh(result) if result.err_code == GConst.ERROR_STR.SUCCESS then if self.battleController and result.reqData then self.battleController.battleData:addRefreshSkillCount(result.reqData.ad) end EventManager:dispatchEvent(EventManager.CUSTOM_EVENT.SKILL_REFRESH_SUCC) end end function BattleManager:isInBattle() return self.battleController ~= nil end -- params = {atkFormation= {elementType = heroEntity}, defFormation= ?} function BattleManager:playBattle(battleType, params, returnFunc, snapshot) UIManager:showLoading(UIManager.LOADING_TYPE.CLOUD, function() params = params or {} if self.battleController then -- 同一时间只能有一场战斗 self:clear() end self.returnFunc = returnFunc UIManager:stopCurrentBGM() self:_play(battleType, params, snapshot) end) end function BattleManager:_play(battleType, params, snapshot) params.battleType = battleType if not params.atkFormation then params.atkFormation = {} local formation = DataManager.FormationData:getStageFormation() for elementType, heroId in pairs(formation) do local heroEntity = DataManager.HeroData:getHeroById(heroId) if heroEntity then params.atkFormation[elementType] = heroEntity end end end local controllerPath = BATTLE_CONTROLLER[battleType] or BATTLE_CONTROLLER_BASE self.battleController = require(controllerPath):create() self.battleController:init(params, snapshot) end function BattleManager:onSelectSkill(skillId, value, pos) if not self.battleController then return end self.battleController:onSelectSkill(skillId, value, pos) end function BattleManager:endBattleAndExit(proactivelyExit) if self.battleController then if proactivelyExit then self.battleController:postWaveOver(false, true) end self.battleController:endBattleAndExit() else self:exitBattle() end end function BattleManager:exitBattle() self:clear() if self.returnFunc then local returnFunc = self.returnFunc self.returnFunc = nil returnFunc() else -- 没有指定返回则直接去主城 UIManager:closeAllUI() ModuleManager.MaincityManager:showMainCityUI() end self:performWithDelayGlobal(function() Game:garbageCollect() end, 0.02) end function BattleManager:clear() if self.battleController == nil then return end GFunc.killDOTween(GConst.DOTWEEN_IDS.BATTLE) self.battleController:clear() self.battleController = nil self.bindUnitAttributeData = nil end ----------------------- start 一些公共相关的方法 ----------------------------- function BattleManager:getPosInfo(posId, rowCount) rowCount = rowCount or BattleConst.ROW_COUNT if not GConst.BattleConst.GRID_POS[rowCount] then GConst.BattleConst.GRID_POS[rowCount] = {} end local posInfo = GConst.BattleConst.GRID_POS[rowCount][posId] if not posInfo then local r = self:getPosRC(posId).r local c = self:getPosRC(posId).c local offset = self:posNeedOffset(rowCount) local offsetC = c - BattleConst.HALF_COLUMN_COUNT local halfR = (rowCount + 1) / 2 local offsetR = (rowCount + 1) / 2 - r local info = {x = offsetC * BattleConst.GRID_STEP_H, y = offsetR * BattleConst.GRID_STEP_H} if r > halfR then info.y = info.y - offset else info.y = info.y + offset end GConst.BattleConst.GRID_POS[rowCount][posId] = info posInfo = GConst.BattleConst.GRID_POS[rowCount][posId] end return posInfo end function BattleManager:posNeedOffset(rowCount) if rowCount == GConst.BattleConst.PVP_ROW_COUNT then return 23 end return 0 end function BattleManager:getElementIcon(elementType) local icon = GConst.BattleConst.ELEMENT_ICON[elementType] if not icon then return GConst.ATLAS_PATH.COMMON, "common_alpha" end return GConst.ATLAS_PATH.BATTLE, icon end function BattleManager:getPosId(row, column) if not BattleConst.RC_2_POS_ID[row] then BattleConst.RC_2_POS_ID[row] = {} end if not BattleConst.RC_2_POS_ID[row][column] then local posId local rowValue = row * BattleConst.ROW_STEP if rowValue >= 0 then posId = rowValue + column else rowValue = rowValue + BattleConst.ROW_STEP posId = rowValue - column end BattleConst.RC_2_POS_ID[row][column] = posId end return BattleConst.RC_2_POS_ID[row][column] end function BattleManager:getFirstLineLastRowPosId(row, column) return self:getPosId(1 - row, column) end function BattleManager:getLastLineLastRowPosId(row, column, maxRow) return self:getPosId(maxRow + row, column) end function BattleManager:getAroundPosIdsByList(posId, boardrange, cludePosIdsMap, maxRow) local posIdInfos = {} local randomExclusion = {} for _, info in ipairs(boardrange) do local list = self:getAroundPosIds(posId, info.type, info.range, cludePosIdsMap, randomExclusion, maxRow) for _, info in ipairs(list) do table.insert(posIdInfos, info) cludePosIdsMap[info.posId] = nil randomExclusion[info.posId] = true end end return posIdInfos end function BattleManager:getAroundPosIds(posId, direction, range, cludePosIdsMap, randomExclusion, maxRow) maxRow = maxRow or BattleConst.ROW_COUNT local rc = self:getPosRC(posId) local r = rc.r local c = rc.c local posIdList = {} if direction == BattleConst.BOARD_RANGE_TYPE.RANDOM then if cludePosIdsMap then local cludePosIds = {} for posId, _ in pairs(cludePosIdsMap) do if not randomExclusion or not randomExclusion[posId] then table.insert(cludePosIds, posId) end end local count = math.min(#cludePosIds, range) for i = 1, count do table.insert(posIdList, {posId = table.remove(cludePosIds, math.random(1, #cludePosIds)), direction = direction}) end end elseif direction == BattleConst.BOARD_RANGE_TYPE.UP then for i = r - 1, r - range, -1 do if i >= 1 then table.insert(posIdList, {posId = self:getPosId(i, c), direction = direction}) end end elseif direction == BattleConst.BOARD_RANGE_TYPE.DOWN then for i = r + 1, r + range do if i <= maxRow then table.insert(posIdList, {posId = self:getPosId(i, c), direction = direction}) end end elseif direction == BattleConst.BOARD_RANGE_TYPE.LEFT then for i = c - 1, c - range, -1 do if i >= 1 then table.insert(posIdList, {posId = self:getPosId(r, i), direction = direction}) end end elseif direction == BattleConst.BOARD_RANGE_TYPE.RIGHT then for i = c + 1, c + range do if i <= BattleConst.COLUMN_COUNT then table.insert(posIdList, {posId = self:getPosId(r, i), direction = direction}) end end elseif direction == BattleConst.BOARD_RANGE_TYPE.LEFT_UP then for i = 1, range do local newR = r - i local newC = c - i if newR >= 1 and newC >= 1 then table.insert(posIdList, {posId = self:getPosId(newR, newC), direction = direction}) end end elseif direction == BattleConst.BOARD_RANGE_TYPE.LEFT_DOWN then for i = 1, range do local newR = r + i local newC = c - i if newR <= maxRow and newC >= 1 then table.insert(posIdList, {posId = self:getPosId(newR, newC), direction = direction}) end end elseif direction == BattleConst.BOARD_RANGE_TYPE.RIGHT_UP then for i = 1, range do local newR = r - i local newC = c + i if newR >= 1 and newC <= BattleConst.COLUMN_COUNT then table.insert(posIdList, {posId = self:getPosId(newR, newC), direction = direction}) end end elseif direction == BattleConst.BOARD_RANGE_TYPE.RIGHT_DOWN then for i = 1, range do local newR = r + i local newC = c + i if newR <= maxRow and newC <= BattleConst.COLUMN_COUNT then table.insert(posIdList, {posId = self:getPosId(newR, newC), direction = direction}) end end end if cludePosIdsMap then local newList = {} for _, info in ipairs(posIdList) do if cludePosIdsMap[info.posId] then table.insert(newList, info) end end return newList else return posIdList end end function BattleManager:getPosRC(posId) if not BattleConst.POS_ID_2_RC[posId] then local r = posId // BattleConst.ROW_STEP local c if r <= 0 then local adsPosId = math.abs(posId) c = adsPosId % BattleConst.ROW_STEP else c = posId % BattleConst.ROW_STEP end BattleConst.POS_ID_2_RC[posId] = {r = r , c = c} end return BattleConst.POS_ID_2_RC[posId] end function BattleManager:getBuffElementType(buffName) local cfg = ConfigManager:getConfigWithOtherKey("buff", "name")[buffName] return cfg and cfg.position end function BattleManager:getPosCenterAndDir(pos1, pos2) local centerPos = {x = 0, y = 0} centerPos.x = (pos1.x + pos2.x) / 2 centerPos.y = (pos1.y + pos2.y) / 2 local zEuler = - math.deg(math.atan(pos2.x - pos1.x, pos2.y - pos1.y)) + 90 return centerPos, zEuler end function BattleManager:getPosIdsByDirection(posId, direction, maxRow) maxRow = maxRow or BattleConst.ROW_COUNT local rc = self:getPosRC(posId) local list = {} if direction == BattleConst.BOARD_RANGE_TYPE.UP then for r = rc.r, 1, -1 do local id = self:getPosId(r, rc.c) table.insert(list, id) end elseif direction == BattleConst.BOARD_RANGE_TYPE.DOWN then for r = rc.r, maxRow do local id = self:getPosId(r, rc.c) table.insert(list, id) end elseif direction == BattleConst.BOARD_RANGE_TYPE.LEFT then for c = rc.c, 1, -1 do local id = self:getPosId(rc.r, c) table.insert(list, id) end elseif direction == BattleConst.BOARD_RANGE_TYPE.RIGHT then for c = rc.c, BattleConst.COLUMN_COUNT do local id = self:getPosId(rc.r, c) table.insert(list, id) end end return list end function BattleManager:getPosDirection(originPosId, posId) local originR, originC = self:getPosRC(originPosId).r, self:getPosRC(originPosId).c local r, c = self:getPosRC(posId).r, self:getPosRC(posId).c if originR < r and originC == c then return BattleConst.BOARD_RANGE_TYPE.DOWN elseif originR > r and originC == c then return BattleConst.BOARD_RANGE_TYPE.UP elseif originR == r and originC < c then return BattleConst.BOARD_RANGE_TYPE.RIGHT elseif originR == r and originC > c then return BattleConst.BOARD_RANGE_TYPE.LEFT elseif originR < r and originC > c then return BattleConst.BOARD_RANGE_TYPE.LEFT_DOWN elseif originR < r and originC < c then return BattleConst.BOARD_RANGE_TYPE.RIGHT_DOWN elseif originR > r and originC > c then return BattleConst.BOARD_RANGE_TYPE.LEFT_UP elseif originR > r and originC < c then return BattleConst.BOARD_RANGE_TYPE.RIGHT_UP end end function BattleManager:getPosByDirection(posId, direction, maxRow) maxRow = maxRow or BattleConst.ROW_COUNT local rc = self:getPosRC(posId) if direction == BattleConst.BOARD_RANGE_TYPE.UP then local r = rc.r - 1 if r > 0 then return self:getPosId(r, rc.c) end elseif direction == BattleConst.BOARD_RANGE_TYPE.DOWN then local r = rc.r + 1 if r <= maxRow then return self:getPosId(r, rc.c) end elseif direction == BattleConst.BOARD_RANGE_TYPE.LEFT then local c = rc.c - 1 if c > 0 then return self:getPosId(rc.r, c) end elseif direction == BattleConst.BOARD_RANGE_TYPE.RIGHT then local c = rc.c + 1 if c <= BattleConst.COLUMN_COUNT then return self:getPosId(rc.r, c) end end end function BattleManager:getReverseDirection(direction) if direction == BattleConst.BOARD_RANGE_TYPE.UP then return BattleConst.BOARD_RANGE_TYPE.DOWN elseif direction == BattleConst.BOARD_RANGE_TYPE.DOWN then return BattleConst.BOARD_RANGE_TYPE.UP elseif direction == BattleConst.BOARD_RANGE_TYPE.LEFT then return BattleConst.BOARD_RANGE_TYPE.RIGHT elseif direction == BattleConst.BOARD_RANGE_TYPE.RIGHT then return BattleConst.BOARD_RANGE_TYPE.LEFT end end ----------------------- end 一些公共相关的方法 ----------------------------- function BattleManager:bindBattleUnitAttribute(hashCode, side) if self.battleController then local team = nil if side == 1 then team = self.battleController.atkTeam else team = self.battleController.defTeam end local unitAttrHelper = nil local teamEntity = nil for _, unit in ipairs(team.unitList) do local code = unit.baseObject:getGameObject():GetHashCode() if code == hashCode then if side == 1 then unitAttrHelper = unit.baseObject:getComponent(typeof(CS.BF.BattleUnitAttr)) else unitAttrHelper = unit.baseObject:getComponent(typeof(CS.BF.BattleUnitAttr)) end teamEntity = unit.unitEntity.team break end end if unitAttrHelper and teamEntity then -- 创建并绑定相关数据 if self.bindUnitAttributeData == nil then self.bindUnitAttributeData = {} end -- 组合必要数据 local unitData = {} unitData.unitAttrHelper = unitAttrHelper unitData.teamEntity = teamEntity self.bindUnitAttributeData[hashCode] = unitData -- bind方法 unitAttrHelper:BindGetAttributeFunc(function(hashCode) self:getBattleUnitAttribute(hashCode) end) -- 刷新数据 self:getBattleUnitAttribute(hashCode) end end end -- 将lua端属性传回CS端 function BattleManager:getBattleUnitAttribute(hashCode) if self.bindUnitAttributeData and self.bindUnitAttributeData[hashCode] then local data = self.bindUnitAttributeData[hashCode] local unitAttrHelper = data.unitAttrHelper local teamEntity = data.teamEntity if unitAttrHelper and teamEntity then local attr = {} for key, value in pairs(teamEntity.attr) do attr[key] = value end attr.sheild_hp = teamEntity.shieldHp unitAttrHelper:GetAttribute(json.encode(attr)) end end end function BattleManager:clearOnExitScene() if self.battleController == nil then return end self:clear() self.returnFunc = nil end return BattleManager