local BattleController = class("BattleController") local BATTLE_BOARD_SKILL_HANDLE = require "app/module/battle/skill/battle_board_skill_handle" local BATTLE_ROGUE_SKILL_HANDLE = require "app/module/battle/skill/battle_rogue_skill_handle" local ELIMINATION_TOUCH_EVENT = GConst.ELIMINATION_TOUCH_EVENT local BattleConst = GConst.BattleConst -- *************各个子模块的战斗需要重写的方法 START************* function BattleController:getInitBoard() return {} end function BattleController:getFixedRandomGrid() return {} end function BattleController:getSealElementType() return {} end -- 战斗对应的ui function BattleController:getBattleUIPath() return "app/ui/battle/battle_ui" end -- 战斗结束 function BattleController:controllBattleEnd() end -- 不同模块的战斗需要初始化的东西 function BattleController:initOther() end function BattleController:onLinkChange() for posId, entity in pairs(DataManager.BattleData:getGridEnties()) do if entity:getCell() then entity:getCell():showHighLight(false) end end local sequence = DataManager.BattleData:getGridSequence() local elementTypeMap = {} local posIdMap = {} for _, info in ipairs(sequence) do posIdMap[info.posId] = true local entity = DataManager.BattleData:getGridEntity(info.posId) if not entity:getSkillId() then local elementType = entity:getElementType() elementTypeMap[elementType] = (elementTypeMap[elementType] or 0) + 1 end if entity:getCell() then entity:getCell():showHighLight(true) end end for posId, _ in pairs(DataManager.BattleData:getSkillInfluenceGrids()) do if not posIdMap[posId] then posIdMap[posId] = true local entity = DataManager.BattleData:getGridEntity(posId) if not entity:getSkillId() then local elementType = entity:getElementType() elementTypeMap[elementType] = (elementTypeMap[elementType] or 0) + 1 end if entity:getCell() then entity:getCell():showCircle(true) end end end self.battleUI:refreshSkill(elementTypeMap) Logger.logHighlight("---------onLinkChange--------------") Logger.printTable(elementTypeMap) end -- *************各个子模块的战斗需要重写的方法 END************* function BattleController:ctor() end function BattleController:init(params) params = params or {} DataManager.BattleData:init(self:getInitBoard()) UIManager:closeAllUI() self.battleUI = UIManager:showUI(self:getBattleUIPath()) self.battleUI:setController(self) self.battleUI:addLoadUICompleteListener(function() end) end function BattleController:onTouchEvent(eventType, posId) local entity = DataManager.BattleData:getGridEntity(posId) if not entity:canLink() then return end if eventType == ELIMINATION_TOUCH_EVENT.DOWN then if #DataManager.BattleData:getGridSequence() > 0 then DataManager.BattleData:clearGridSequence() end DataManager.BattleData:insertGridSequence(posId, self:snapshotBoard()) local skillEntity = DataManager.BattleData:getSkillEntityBySkillId(entity:getSkillId()) local maskElementType = entity:getElementType(skillEntity) self.battleUI:showBoardMask(maskElementType) self:findSkillInfluenceGrids() self:onLinkChange() elseif eventType == ELIMINATION_TOUCH_EVENT.ENTER then local sequence = DataManager.BattleData:getGridSequence() local info = sequence[#sequence] local lastPosId = info and info.posId if not lastPosId then return end local outLineMap = BattleConst.GRID_OUT_LINE_POS_ID[lastPosId] if not outLineMap or not outLineMap[posId] then return end if DataManager.BattleData:alreadyInsertSequence(posId) then local info = sequence[#sequence - 1] local beforePosId = info and info.posId if not beforePosId then return end if beforePosId == posId then -- 进入的是倒数第二个,则移除倒数第一个 local snapshot = DataManager.BattleData:removeGridSequence(lastPosId) if snapshot then -- 如果有快照,则恢复一次 for posId, info in pairs(snapshot) do local entity = DataManager.BattleData:getGridEntity(posId) if entity then entity:setInfoBySnapshop(info) end end end local lastEntity = DataManager.BattleData:getGridEntity(beforePosId) local lastSkillEntity = DataManager.BattleData:getSkillEntityBySkillId(lastEntity:getSkillId()) local maskElementType = lastEntity:getElementType(lastSkillEntity) self.battleUI:showBoardMask(maskElementType) self:findSkillInfluenceGrids() self:onLinkChange() return end end local skillId = entity:getSkillId() local skillEntity = DataManager.BattleData:getSkillEntityBySkillId(skillId) local elementType = entity:getElementType(skillEntity) local lastEntity = DataManager.BattleData:getGridEntity(lastPosId) local lastSkillId = lastEntity:getSkillId() local lastSkillEntity = DataManager.BattleData:getSkillEntityBySkillId(lastSkillId) local lastElementType = lastEntity:getElementType(lastSkillEntity) if skillEntity and DataManager.BattleData:getSequenceHadSkill() then return end if not elementType or not lastElementType then else if lastElementType ~= elementType then return end end local maskElementType = elementType or lastElementType self.battleUI:showBoardMask(maskElementType) DataManager.BattleData:insertGridSequence(posId, self:snapshotBoard()) if lastEntity:getNeedChangePos() and not entity:getNeedChangePos() then -- 需要移动到队列末尾 local lastSkillId = lastEntity:getSkillId() local skillId = entity:getSkillId() lastEntity:setSkilId(skillId) entity:setSkilId(lastSkillId) end local newElementType = elementType or lastElementType if newElementType then entity:setElementType(newElementType) lastEntity:setElementType(newElementType) end entity:addLinkSkillCount() self:findSkillInfluenceGrids() self:onLinkChange() elseif eventType == ELIMINATION_TOUCH_EVENT.EXIT then else -- 取消和抬起 self.battleUI:showBoardMask(nil) local sequence = DataManager.BattleData:getGridSequence() local count = #sequence if count < BattleConst.ELIMINATION_MIN_COUNT then if count <= 0 then DataManager.BattleData:clearGridSequence() self:onLinkChange() return end local snapshot = DataManager.BattleData:removeGridSequence(sequence[1].posId) if snapshot then -- 如果有快照,则恢复一次 for posId, info in pairs(snapshot) do local entity = DataManager.BattleData:getGridEntity(posId) if entity then entity:setInfoBySnapshop(info) end end end DataManager.BattleData:clearGridSequence() self:onLinkChange() return end self:onLinkOver() end end function BattleController:onLinkOver() local sequence = DataManager.BattleData:getGridSequence() local count = #sequence if count < BattleConst.ELIMINATION_MIN_COUNT then return end local skillId = DataManager.BattleData:getSequenceHadSkill() local skillEntity local linkElementType local influenceElementType if skillId then skillEntity = DataManager.BattleData:getSkillEntityBySkillId(skillId) end local elementTypeMap = {} local eliminationPosIds = {} local boomGridIds = {} for _, info in ipairs(sequence) do if not eliminationPosIds[info.posId] then local entity = DataManager.BattleData:getGridEntity(info.posId) if not entity:getSkillId() then local elementType = entity:getElementType() elementTypeMap[elementType] = (elementTypeMap[elementType] or 0) + 1 linkElementType = elementType end local outline = BattleConst.GRID_OUT_LINE_POS_ID[info.posId] for aroundPosId, _ in pairs(outline) do boomGridIds[aroundPosId] = true end local entity = DataManager.BattleData:getGridEntity(info.posId) entity:setIsIdle(true) eliminationPosIds[info.posId] = true end end for posId, _ in pairs(DataManager.BattleData:getSkillInfluenceGrids()) do local entity = DataManager.BattleData:getGridEntity(posId) if not entity:getIsIdle() then if entity:isEmptyType() then entity:setIsIdle(true) if not eliminationPosIds[posId] then eliminationPosIds[posId] = true table.insert(sequence, {posId = posId}) end if not entity:getSkillId() then local elementType = entity:getElementType() elementTypeMap[elementType] = (elementTypeMap[elementType] or 0) + 1 if not influenceElementType then influenceElementType = {} end influenceElementType[elementType] = true end else boomGridIds[posId] = true end end end for posId, status in pairs(boomGridIds) do if not eliminationPosIds[posId] then local entity = DataManager.BattleData:getGridEntity(posId) if entity then entity:addAroundEliminationCount() if entity:getIsIdle() then eliminationPosIds[posId] = true table.insert(sequence, {posId = posId}) if not entity:getSkillId() then local elementType = entity:getElementType() elementTypeMap[elementType] = (elementTypeMap[elementType] or 0) + 1 end end end end end DataManager.BattleData:addSkillEnergy(elementTypeMap) DataManager.BattleData:clearGridSequence() self.battleUI:disableUITouch() self.battleUI:eliminationAni(sequence, function() local instructions = self:generateInstructions(skillEntity, linkElementType, influenceElementType, elementTypeMap) self:exeInstructions(instructions, function() self:fillBoard() end) end) end function BattleController:fillBoard() local pathMap = {} local columnCount = {} for c = 1, BattleConst.COLUMN_COUNT do for r = BattleConst.ROW_COUNT, 1, -1 do local posId = ModuleManager.BattleManager:getPosId(r, c) local entity = DataManager.BattleData:getGridEntity(posId) if entity:getIsIdle() then self:fillThisPos(posId, columnCount) end end end for c = 1, BattleConst.COLUMN_COUNT do for r = BattleConst.ROW_COUNT, 1, -1 do local posId = ModuleManager.BattleManager:getPosId(r, c) local entity = DataManager.BattleData:getGridEntity(posId) if #entity:getPath() > 0 then pathMap[posId] = entity:getPath() entity:clearPath() end end end self.battleUI:fallGrid(pathMap, function() self:onFillBoardOver() self.battleUI:enableUITouch() ---- 临时 ModuleManager.BattleManager:showSelectSkillUI(self:getRandomSkillList()) end) end function BattleController:onFillBoardOver() self:generateSkill() self.battleUI:refreshSkill() end function BattleController:generateInstructions(skillEntity, elementType, influenceElementType, elementTypeMap) local instructions = {} ---- 加buff if skillEntity then if skillEntity:getLinkAtkp() > 0 and elementType then local attrType = BattleConst.ELEMENT_TYPE_ATKP_NAME[elementType] if attrType then table.insert(instructions, { name = BattleConst.INSTRUCTION_NAME.ADD_CUR_ROUND_ATTR, attr = { type = attrType, num = skillEntity:getLinkAtkp() } }) end end if skillEntity:getInInfluenceAtkp() > 0 and influenceElementType then for elementType, _ in pairs(influenceElementType) do local attrType = BattleConst.ELEMENT_TYPE_ATKP_NAME[elementType] if attrType then table.insert(instructions, { name = BattleConst.INSTRUCTION_NAME.ADD_CUR_ROUND_ATTR, attr = { type = attrType, num = skillEntity:getInInfluenceAtkp() } }) end end end end local elementTypeCount = 0 ---- 援助 for element, count in pairs(elementTypeMap) do if element == elementType then elementTypeCount = count else table.insert(instructions, { name = BattleConst.INSTRUCTION_NAME.ASSISTING, count = count, skillMatch = element, }) end end ---- 普攻 if elementTypeCount > 0 then table.insert(instructions, { name = BattleConst.INSTRUCTION_NAME.GENERAL_ATTACK, count = elementTypeCount }) end ---- 技能 if skillEntity then table.insert(instructions, { name = BattleConst.INSTRUCTION_NAME.PLAY_SKILL, skillMatch = elementType }) end return instructions end function BattleController:exeInstructions(instructions, callback) Logger.logHighlight("--------exeInstructions----------") Logger.printTable(instructions) -- todo if callback then callback() end end function BattleController:generateSkill() local map = {} for _, skillEntity in pairs(DataManager.BattleData:getSkillEntities()) do if skillEntity:getEnergyEnough() then map[skillEntity:getPosition()] = skillEntity:getSkillId() end end for elementType, skillId in pairs(map) do local list = self:getSkillElementList(elementType, 1, true) for _, posId in ipairs(list) do local entity = DataManager.BattleData:getGridEntity(posId) if entity then entity:setSkilId(skillId) if entity:getElementType() ~= elementType then entity:setElementType(elementType) end end end end end function BattleController:getSkillElementList(elementType, count, useAlternate) local result = {} local gridEntities = DataManager.BattleData:getGridEnties() if not gridEntities then return result end local sameElementList = {} local alternateList = {} local addCount = 0 for row = 1, BattleConst.ROW_COUNT do for column = 1, BattleConst.COLUMN_COUNT do local posId = ModuleManager.BattleManager:getPosId(row, column) local entity = gridEntities[posId] if entity and entity:canChangeInfo() then if entity:getElementType() == elementType then table.insert(sameElementList, posId) else table.insert(alternateList, posId) end end end local remainCount = count - addCount if remainCount <= 0 then return result end for i = 1, remainCount do if not sameElementList[i] then break end table.insert(result, table.remove(sameElementList, math.random(1, #sameElementList))) addCount = addCount + 1 if addCount >= count then return result end end if addCount < count and useAlternate then for i = 1, count - addCount do if not alternateList[1] then break end table.insert(result, table.remove(alternateList, math.random(1, #alternateList))) addCount = addCount + 1 if addCount >= count then return result end end end if addCount >= count then return result end end return result end ---- 从一个点直接遍历所有相关的路径 function BattleController:fillThisPos(posId, columnCount) local entity = DataManager.BattleData:getGridEntity(posId) if not entity or not entity:getIsIdle() then return end local list = BattleConst.UP_LINE_FILL_LIST[posId] if not list[1] then -- 第一排 local rc = ModuleManager.BattleManager:getPosRC(posId) local c = rc.c if not columnCount[c] then columnCount[c] = 0 end columnCount[c] = columnCount[c] + 1 local fallPosId = posId local fallEntity = DataManager.BattleData:getGridEntity(fallPosId) if not fallEntity then -- 异常情况,理论上不可能不存在 return end local newStartPosId for i = columnCount[c], 1, -1 do newStartPosId = ModuleManager.BattleManager:getFirstLineLastRowPosId(i, c) local curPos = ModuleManager.BattleManager:getPosInfo(newStartPosId) fallEntity:addPath({x = curPos.x, y = curPos.y}) end local curPos = ModuleManager.BattleManager:getPosInfo(posId) fallEntity:addPath({x = curPos.x, y = curPos.y}) DataManager.BattleData:exchangeGridEntities(posId, fallPosId) DataManager.BattleData:setGridInfo(posId, self:getRandomGridInfo()) else for index, fallPosId in ipairs(list) do local fallEntity = DataManager.BattleData:getGridEntity(fallPosId) if not fallEntity then -- 异常情况,理论上不可能不存在 return end if fallEntity then if not fallEntity:isCantFallType() then if fallEntity:getIsIdle() then self:fillThisPos(fallPosId, columnCount) end fallEntity = DataManager.BattleData:getGridEntity(fallPosId) if not fallEntity:getIsIdle() then if not fallEntity:getPath()[1] then local curPos = ModuleManager.BattleManager:getPosInfo(fallPosId) fallEntity:addPath({x = curPos.x, y = curPos.y}) end local curPos = ModuleManager.BattleManager:getPosInfo(posId) fallEntity:addPath({x = curPos.x, y = curPos.y}) DataManager.BattleData:exchangeGridEntities(posId, fallPosId) self:fillThisPos(fallPosId, columnCount) return end end end end end end function BattleController:getRandomGridInfo() if not self.fixedRandomList then self.fixedRandomList = {} for _, elementType in ipairs(self:getFixedRandomGrid()) do table.insert(self.fixedRandomList, elementType) end end local gridType = 0 local elementType if self.fixedRandomList[1] then elementType = table.remove(self.fixedRandomList, 1) else local map = DataManager.BattleData:getElementTypeMap() local indexs = {} local typeList = {} for typeName, typeNum in pairs(BattleConst.ELEMENT_TYPE) do if not self:getSealElementType()[typeNum] then local weight = ((map[typeNum] or 0) + 1) * BattleConst.ELEMENT_WIGHT if weight > BattleConst.MAX_ELEMENT_WIGHT then weight = BattleConst.MAX_ELEMENT_WIGHT end table.insert(indexs, weight) table.insert(typeList, typeNum) end end local index = GFunc.getRandomIndex(indexs) elementType = typeList[index] end return {gridType = gridType, elementType = elementType} end function BattleController:findSkillInfluenceGrids() local girds = DataManager.BattleData:clearSkillInfluenceGrids() for posId, _ in pairs(girds) do local entity = DataManager.BattleData:getGridEntity(posId) entity:setNeedElimination(false) end local sequence = DataManager.BattleData:getGridSequence() for _, info in ipairs(sequence) do local entity = DataManager.BattleData:getGridEntity(info.posId) local skillId = entity:getSkillId() if skillId then local skillEntity = DataManager.BattleData:getSkillEntityBySkillId(skillId) if skillEntity then BATTLE_BOARD_SKILL_HANDLE.activeBoardSkill(info.posId, skillEntity, DataManager.BattleData:getGridEnties()) end end end end function BattleController:getRandomSkillList(getCount) getCount = getCount or BattleConst.SKILL_SELECT_COUNT local result = {} local cfg = ConfigManager:getConfig("skill_rogue") local skillPool = DataManager.BattleData:getSkillPool() local map = {} local count = 0 local newSkillPool = {} local skillWeight = {} for _, skillId in ipairs(skillPool) do local skillCfg = cfg[skillId] if skillCfg and not skillCfg.limit_times or DataManager.BattleData:getSkillCount(skillId) < skillCfg.limit_times then if not map[skillId] then table.insert(newSkillPool, skillId) table.insert(skillWeight, skillCfg.weight) count = count + 1 map[skillId] = true end end end if count > 0 then local index = GFunc.getRandomIndex(skillWeight) local skillId = table.remove(newSkillPool, index) table.remove(skillWeight, index) count = count - 1 table.insert(result, skillId) getCount = getCount - 1 end for skillId, info in ipairs(cfg) do if info.universal then if not info.limit_times or DataManager.BattleData:getSkillCount(skillId) < info.limit_times then if not map[skillId] then table.insert(newSkillPool, skillId) table.insert(skillWeight, info.weight) count = count + 1 end end end end for i = 1, getCount do local index = GFunc.getRandomIndex(skillWeight) local skillId = table.remove(newSkillPool, index) table.remove(skillWeight, index) count = count - 1 table.insert(result, skillId) end result = table.shuffle(result) return result end function BattleController:onSelectSkill(skillId) DataManager.BattleData:addSkillCount(skillId) BATTLE_ROGUE_SKILL_HANDLE.takeEffect(skillId, DataManager.BattleData, self) end function BattleController:changeElementType(count, elementType) local list = {} for _, entity in pairs(DataManager.BattleData:getGridEnties()) do if entity:canChangeInfo() and entity:getElementType() ~= elementType then table.insert(list, entity) end end for i = 1, count do if not list[1] then break end local entity = table.remove(list, math.random(1, #list)) if entity then entity:setElementType(elementType) end end end function BattleController:addHeroAttr(attrName, value) Logger.logHighlight("------addHeroAttr------ " .. attrName .. " " .. value) -- if attrName == then -- -- body -- elseif attrName == then -- -- body -- elseif attrName == then -- -- body -- elseif attrName == then -- -- body -- elseif attrName == then -- -- body -- else -- end end function BattleController:changeSkillId(elementType, skillId) Logger.logHighlight("------changeSkillId------ " .. elementType .. " " .. skillId) end function BattleController:addSkillReleaseCount(elementType, count) Logger.logHighlight("------addSkillReleaseCount------ " .. elementType .. " " .. count) end function BattleController:addSkillEffectParams(elementType, effect) Logger.logHighlight("------addSkillEffectParams------ " .. elementType .. " " .. json.encode(effect)) end function BattleController:addSkillRound(elementType, effect) Logger.logHighlight("------addSkillRound------ " .. elementType .. " " .. json.encode(effect)) end function BattleController:addSkillEffect(elementType, effects) Logger.logHighlight("------addSkillEffect------ " .. elementType .. " " .. json.encode(effects)) end ---- 快照一次棋盘 function BattleController:snapshotBoard() local snapshot = {} for _, entity in pairs(DataManager.BattleData:getGridEnties()) do snapshot[entity:getPosId()] = entity:getSnapshoptInfo() end return snapshot end function BattleController:clear() end function BattleController:endBattleAndExit() ModuleManager.BattleManager:exitBattle() end return BattleController