1627 lines
52 KiB
Lua
1627 lines
52 KiB
Lua
local BattleHelper = require "app/module/battle/helper/battle_helper"
|
||
local BattleScheduler = require "app/module/battle/helper/battle_scheduler"
|
||
local BattleTeam = require "app/module/battle/team/battle_team"
|
||
local BattlePassive = require "app/module/battle/helper/battle_passive"
|
||
|
||
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 BattleBuffHandle = require "app/module/battle/helper/battle_buff_handle"
|
||
|
||
local ELIMINATION_TOUCH_EVENT = GConst.ELIMINATION_TOUCH_EVENT
|
||
local BattleConst = GConst.BattleConst
|
||
local BUFF_NAME_TO_ATTR = BattleConst.BUFF_NAME_TO_ATTR
|
||
|
||
-- *************各个子模块的战斗需要重写的方法 START*************
|
||
function BattleController:getChapterId()
|
||
return 0
|
||
end
|
||
|
||
function BattleController:getInitBoard()
|
||
return {}
|
||
end
|
||
|
||
function BattleController:getNotInvolvedSkills()
|
||
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:loadOtherRes(callback)
|
||
return callback()
|
||
end
|
||
|
||
-- 一共有多少波
|
||
function BattleController:getMaxWave()
|
||
return 1
|
||
end
|
||
|
||
function BattleController:getMinEliminationCount()
|
||
if not self.minEliminationCount then
|
||
self.minEliminationCount = GFunc.getConstIntValue("element_combo")
|
||
end
|
||
return self.minEliminationCount
|
||
end
|
||
|
||
function BattleController:initDefUnits(callback)
|
||
callback()
|
||
end
|
||
|
||
function BattleController:findNextDefUnit()
|
||
self:enterRefreshBoard()
|
||
end
|
||
|
||
function BattleController:onDefDead()
|
||
end
|
||
|
||
function BattleController:tick(dt)
|
||
end
|
||
|
||
function BattleController:onLinkChange()
|
||
self.battleUI:hideAllSfxLine()
|
||
local needFalsePosMap = {}
|
||
for posId, entity in pairs(self.battleData:getGridEnties()) do
|
||
if entity:getCell() then
|
||
needFalsePosMap[posId] = entity:getCell()
|
||
end
|
||
end
|
||
|
||
local sequence = self.battleData:getGridSequence()
|
||
local elementTypeMap = {}
|
||
local posIdMap = {}
|
||
local mainElementType
|
||
local count = 0
|
||
for _, info in ipairs(sequence) do
|
||
posIdMap[info.posId] = true
|
||
local entity = self.battleData:getGridEntity(info.posId)
|
||
|
||
if not entity:getSkillId() then
|
||
local elementType = entity:getElementType()
|
||
elementTypeMap[elementType] = (elementTypeMap[elementType] or 0) + 1
|
||
mainElementType = elementType
|
||
end
|
||
count = count + 1
|
||
end
|
||
|
||
for index, info in ipairs(sequence) do
|
||
local entity = self.battleData:getGridEntity(info.posId)
|
||
if entity:getCell() then
|
||
entity:getCell():showHighLight(true, mainElementType, self.battleUI)
|
||
end
|
||
if needFalsePosMap[info.posId] then
|
||
needFalsePosMap[info.posId] = nil
|
||
end
|
||
if index < count then
|
||
local nextPosId = sequence[index + 1].posId
|
||
self.battleUI:getSfxLine(index, function(obj)
|
||
local curPos = ModuleManager.BattleManager:getPosInfo(info.posId)
|
||
local nextPos = ModuleManager.BattleManager:getPosInfo(nextPosId)
|
||
local pos, z = ModuleManager.BattleManager:getPosCenterAndDir(curPos, nextPos)
|
||
obj:setLocalScale(25, 25, 25)
|
||
obj:setLocalPosition(pos.x, pos.y, 0)
|
||
obj:setEulerAngles(0, 0, z)
|
||
end)
|
||
end
|
||
end
|
||
|
||
for posId, cell in pairs(needFalsePosMap) do
|
||
cell:showHighLight(false)
|
||
end
|
||
|
||
for posId, info in pairs(self.battleData:getSkillInfluenceGrids()) do
|
||
local entity = self.battleData:getGridEntity(posId)
|
||
if not posIdMap[posId] and info.direction ~= BattleConst.BOARD_RANGE_TYPE.RANDOM then
|
||
posIdMap[posId] = true
|
||
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)
|
||
if mainElementType then
|
||
self.atkTeam:changeMainUnit(mainElementType)
|
||
end
|
||
end
|
||
|
||
function BattleController:onRoundBegin()
|
||
|
||
end
|
||
|
||
function BattleController:onEliminationBegin()
|
||
|
||
end
|
||
|
||
-- *************各个子模块的战斗需要重写的方法 END*************
|
||
|
||
function BattleController:ctor()
|
||
self.battleData = DataManager.BattleData
|
||
end
|
||
|
||
function BattleController:init(params)
|
||
params = params or {}
|
||
self.chapterId = self:getChapterId()
|
||
self.waveIndex = 0
|
||
self.maxWaveIndex = self:getMaxWave()
|
||
self.victory = false
|
||
self.roundStep = BattleConst.BATTLE_ROUND_STEP.WAIT_BEGIN
|
||
self.effectTexts = {}
|
||
self.instructions = {}
|
||
self.time = 0
|
||
self.battleData:init()
|
||
BattleScheduler:init()
|
||
BattleHelper:init()
|
||
BattlePassive:init()
|
||
self:setTimeScale(DataManager.BattleData:getTimeScale())
|
||
self:bindData()
|
||
self:initBattleTeam()
|
||
self:initOther()
|
||
self:prepareFight()
|
||
end
|
||
|
||
function BattleController:bindData()
|
||
DataManager.BattleData:bind("timeSpeed", ModuleManager.BattleManager, function()
|
||
self:setTimeScale(DataManager.BattleData:getTimeScale())
|
||
end, false)
|
||
end
|
||
|
||
function BattleController:unBindAll()
|
||
DataManager.BattleData:unBind("timeSpeed", ModuleManager.BattleManager)
|
||
end
|
||
|
||
function BattleController:initBattleTeam()
|
||
self.atkTeam = BattleTeam:create()
|
||
self.atkTeam:init(BattleConst.SIDE_ATK, self)
|
||
self.defTeam = BattleTeam:create()
|
||
self.defTeam:init(BattleConst.SIDE_DEF, self)
|
||
end
|
||
|
||
function BattleController:setIsPauseHpProgress(value)
|
||
self.battleUI:setIsPauseHpProgress(value)
|
||
end
|
||
|
||
function BattleController:moveBattlefield(time)
|
||
self.battleUI:moveBattlefield(time)
|
||
end
|
||
|
||
function BattleController:refreshBuff(side, buffList)
|
||
self.battleUI:refreshBuff(side, buffList)
|
||
end
|
||
|
||
function BattleController:clearBuff(side)
|
||
self.battleUI:clearBuff(side)
|
||
end
|
||
|
||
function BattleController:showBuffTips(side)
|
||
if side == BattleConst.SIDE_ATK then
|
||
local buffList = self.atkTeam:getBuffList()
|
||
if #buffList <= 0 then
|
||
return
|
||
end
|
||
self.battleUI:showLeftBuffTips(buffList)
|
||
else
|
||
local buffList = self.defTeam:getBuffList()
|
||
if #buffList <= 0 then
|
||
return
|
||
end
|
||
self.battleUI:showRightBuffTips(buffList)
|
||
end
|
||
end
|
||
|
||
function BattleController:prepareFight()
|
||
local count = 0
|
||
local totalCount = 3
|
||
local function onPreloadFinished()
|
||
count = count + 1
|
||
if count == totalCount then
|
||
self:onLoadComplete()
|
||
end
|
||
end
|
||
UIManager:closeAllUI()
|
||
self.battleUI = UIManager:showUI(self:getBattleUIPath())
|
||
self.battleUI:setController(self)
|
||
self.battleUI:addLoadUICompleteListener(function()
|
||
BattleHelper:setEffectTextCache(self.battleUI:getBattleNumber(),
|
||
self.battleUI:getBattleNumberRed(),
|
||
self.battleUI:getBattleNumberYellow(),
|
||
self.battleUI:getBattleNumberGreen())
|
||
self:initAtkUnits(onPreloadFinished)
|
||
self:initDefUnits(onPreloadFinished)
|
||
end)
|
||
self:loadOtherRes(onPreloadFinished)
|
||
end
|
||
|
||
function BattleController:initAtkUnits(callback)
|
||
local atkTeamEntity = self.battleData:getAtkTeam()
|
||
local count = 0
|
||
local totalCount = atkTeamEntity:getMembersCount()
|
||
local function onloadFinished()
|
||
count = count + 1
|
||
if count == totalCount then
|
||
self.battleUI:refreshAtkHp(atkTeamEntity:getHp(), atkTeamEntity:getHpPercent())
|
||
callback()
|
||
end
|
||
end
|
||
local members = atkTeamEntity:getAllMembers()
|
||
for k, v in pairs(members) do
|
||
local modelId = v:getModelId()
|
||
BattleHelper:loadBattleHeroModel(modelId, self.battleUI:getBattleNode(), function(spineObject)
|
||
local heroComp = spineObject:addLuaComponent(BattleConst.TYPEOF_LUA_COMP.BATTLE_HERO_COMPONENT)
|
||
heroComp:initWithEntity(modelId, v, self)
|
||
if v:getIsMainUnit() then
|
||
self.atkTeam:addUnit(heroComp, true)
|
||
else
|
||
self.atkTeam:addUnit(heroComp)
|
||
heroComp:hideOutsideScreen()
|
||
end
|
||
onloadFinished()
|
||
end)
|
||
end
|
||
if totalCount == 0 then
|
||
callback()
|
||
end
|
||
end
|
||
|
||
function BattleController:refreshHp(side, num, percent)
|
||
if side == BattleConst.SIDE_ATK then
|
||
self.battleUI:refreshAtkHp(num, percent)
|
||
else
|
||
self.battleUI:refreshDefHp(num, percent)
|
||
end
|
||
end
|
||
|
||
function BattleController:getOtherSideMainUnit(side)
|
||
if side == BattleConst.SIDE_ATK then
|
||
return self.defTeam:getMainUnit()
|
||
else
|
||
return self.atkTeam:getMainUnit()
|
||
end
|
||
end
|
||
|
||
function BattleController:onLoadComplete()
|
||
self:battleStart()
|
||
end
|
||
|
||
function BattleController:battleStart()
|
||
self.atkTeam:prepare()
|
||
self.defTeam:prepare()
|
||
self.isBattleStart = true
|
||
self.tickSid = BattleScheduler:scheduleGlobal(function(dt)
|
||
self:_tick(dt)
|
||
end, 0)
|
||
self:enterNextWave()
|
||
end
|
||
|
||
function BattleController:setTimeScale(timeScale)
|
||
GFunc.setDOTweenTimeScale(GConst.DOTWEEN_IDS.BATTLE, timeScale)
|
||
BattleScheduler:setTimeScale(timeScale)
|
||
BattleHelper:setTimeScale(timeScale)
|
||
end
|
||
|
||
function BattleController:_findNextDefUnit()
|
||
if self.isBossWave then -- 如果上一波是boss波次,则重新生成棋盘
|
||
self:putBoardCacheSkill(function()
|
||
self:findNextDefUnit()
|
||
self:generateBoard()
|
||
end)
|
||
else
|
||
self:findNextDefUnit()
|
||
end
|
||
end
|
||
|
||
---- start 回合步骤
|
||
|
||
function BattleController:enterNextWave()
|
||
local atkTeam = self.battleData:getAtkTeam()
|
||
if not atkTeam or atkTeam:getIsDead() then
|
||
self.victory = false
|
||
self:battleEnd()
|
||
return
|
||
end
|
||
|
||
if self.waveIndex >= self.maxWaveIndex then
|
||
self.victory = true
|
||
self:battleEnd()
|
||
return
|
||
end
|
||
|
||
self.waveIndex = self.waveIndex + 1
|
||
if self.battleUI then
|
||
self.battleUI:refreshWave(self.waveIndex)
|
||
end
|
||
if self.waveIndex == 1 then -- 第一波
|
||
self:generateBoard(true)
|
||
end
|
||
|
||
self.defTeam:prepare()
|
||
self:enterRoundBegin()
|
||
self.isBossWave = self.defTeam:getMainUnit().unitEntity:getIsBoss()
|
||
end
|
||
|
||
function BattleController:enterRoundBegin()
|
||
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_BEGIN
|
||
self:onRoundBegin()
|
||
self:enterEliminationBegin()
|
||
end
|
||
|
||
function BattleController:enterEliminationBegin()
|
||
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_BEGIN
|
||
self:onEliminationBegin()
|
||
self:popBoardCacheSkill(function()
|
||
-- 检查棋盘
|
||
local find, pathList = self:findAttention()
|
||
if not find then -- 如果没找到,就要打乱棋盘
|
||
-- todo
|
||
Logger.logHighlight("----- 处于无法消除状态 -----")
|
||
else
|
||
self.attentionList = pathList
|
||
-- ModuleManager.BattleManager:performWithDelayGlobal(function()
|
||
-- for _, posId in ipairs(pathList) do
|
||
-- local entity = self.battleData:getGridEntity(posId)
|
||
-- Logger.logHighlight(entity:getCell() == nil)
|
||
-- if entity and entity:getCell() then
|
||
-- entity:getCell():showAni()
|
||
-- end
|
||
-- end
|
||
-- end, 2)
|
||
|
||
self:enterElimination()
|
||
end
|
||
end)
|
||
end
|
||
|
||
function BattleController:enterElimination()
|
||
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_ELIMINATION
|
||
end
|
||
|
||
function BattleController:enterAtkStep()
|
||
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_ATK_STEP
|
||
self:exeInstructions(function()
|
||
self:enterAtkStepOver()
|
||
end)
|
||
end
|
||
|
||
function BattleController:enterAtkStepOver()
|
||
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_ATK_STEP_OVER
|
||
|
||
local defTeam = self.battleData:getDefTeam()
|
||
if not defTeam or defTeam:getIsDead() then -- 怪物死了, 直接进入刷新逻辑
|
||
if self.waveIndex >= self.maxWaveIndex then
|
||
self:enterRoundEnd()
|
||
else
|
||
self:onDefDead()
|
||
self:enterRefreshBoard()
|
||
end
|
||
return
|
||
end
|
||
|
||
local atkTeam = self.battleData:getAtkTeam()
|
||
if not atkTeam or atkTeam:getIsDead() then -- 英雄死了, 直接结算
|
||
self:enterNextWave()
|
||
return
|
||
end
|
||
|
||
self:enterDefStep()
|
||
end
|
||
|
||
function BattleController:enterDefStep()
|
||
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_DEF_STEP
|
||
|
||
self.defTeam:mainUnitUseAllSkills(function()
|
||
self:enterDefStepOver()
|
||
end)
|
||
end
|
||
|
||
function BattleController:enterDefStepOver()
|
||
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_DEF_STEP_OVER
|
||
|
||
local atkTeam = self.battleData:getAtkTeam()
|
||
if not atkTeam or atkTeam:getIsDead() then -- 英雄死了, 直接结算
|
||
self:enterNextWave()
|
||
return
|
||
end
|
||
|
||
local defTeam = self.battleData:getDefTeam()
|
||
if not defTeam or defTeam:getIsDead() then -- 怪物死了, 直接进入刷新逻辑
|
||
if self.waveIndex >= self.maxWaveIndex then
|
||
self:enterRoundEnd()
|
||
else
|
||
self:onDefDead()
|
||
self:enterRefreshBoard()
|
||
end
|
||
return
|
||
end
|
||
|
||
self:enterRefreshBoard()
|
||
end
|
||
|
||
function BattleController:enterRefreshBoard()
|
||
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_REFRESH_BOARD
|
||
self:fillBoard()
|
||
end
|
||
|
||
function BattleController:enterRoundEnd()
|
||
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_END
|
||
local defTeam = self.battleData:getDefTeam()
|
||
if not defTeam or defTeam:getIsDead() then -- 怪物死了, 直接进入刷新逻辑
|
||
self.atkTeam:onRoundEnd()
|
||
self:enterNextWave()
|
||
return
|
||
end
|
||
|
||
local atkTeam = self.battleData:getAtkTeam()
|
||
if not atkTeam or atkTeam:getIsDead() then -- 英雄死了, 直接结算
|
||
self.defTeam:onRoundEnd()
|
||
self:enterNextWave()
|
||
return
|
||
end
|
||
self.atkTeam:onRoundEnd()
|
||
self.defTeam:onRoundEnd()
|
||
|
||
self:onRoundEnd()
|
||
end
|
||
|
||
function BattleController:onRoundEnd(toNextWave)
|
||
if self.battleData:useAddlvCount() then
|
||
ModuleManager.BattleManager:showSelectSkillUI(self:getRandomSkillList())
|
||
else
|
||
if toNextWave then
|
||
self:enterNextWave()
|
||
else
|
||
self:enterRoundBegin()
|
||
end
|
||
end
|
||
end
|
||
|
||
---- end回合步骤
|
||
|
||
function BattleController:onTouchEvent(eventType, posId)
|
||
if self.roundStep ~= BattleConst.BATTLE_ROUND_STEP.ON_ELIMINATION then
|
||
return
|
||
end
|
||
local entity = self.battleData:getGridEntity(posId)
|
||
if not entity or not entity:canLink() then
|
||
return
|
||
end
|
||
|
||
if eventType == ELIMINATION_TOUCH_EVENT.DOWN then
|
||
if #self.battleData:getGridSequence() > 0 then
|
||
self.battleData:clearGridSequence()
|
||
end
|
||
self.battleData:insertGridSequence(posId, self:snapshotBoard())
|
||
local skillEntity = self.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 = self.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 self.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 = self.battleData:removeGridSequence(lastPosId)
|
||
if snapshot then -- 如果有快照,则恢复一次
|
||
for posId, info in pairs(snapshot) do
|
||
local entity = self.battleData:getGridEntity(posId)
|
||
if entity then
|
||
entity:setInfoBySnapshop(info)
|
||
end
|
||
end
|
||
end
|
||
|
||
local lastEntity = self.battleData:getGridEntity(beforePosId)
|
||
local lastSkillEntity = self.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 = self.battleData:getSkillEntityBySkillId(skillId)
|
||
local elementType = entity:getElementType(skillEntity)
|
||
|
||
local lastEntity = self.battleData:getGridEntity(lastPosId)
|
||
local lastSkillId = lastEntity:getSkillId()
|
||
local lastSkillEntity = self.battleData:getSkillEntityBySkillId(lastSkillId)
|
||
local lastElementType = lastEntity:getElementType(lastSkillEntity)
|
||
|
||
if skillEntity and self.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)
|
||
|
||
self.battleData:insertGridSequence(posId, self:snapshotBoard())
|
||
if lastEntity:getNeedChangePos() and not entity:getNeedChangePos() then -- 需要移动到队列末尾
|
||
local lastSkillId = lastEntity:getSkillId()
|
||
local skillId = entity:getSkillId()
|
||
self:setGridSkillId(lastPosId, skillId)
|
||
self:setGridSkillId(posId, 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 = self.battleData:getGridSequence()
|
||
local count = #sequence
|
||
if count < self:getMinEliminationCount() then
|
||
if count <= 0 then
|
||
self.battleData:clearGridSequence()
|
||
self:onLinkChange()
|
||
return
|
||
end
|
||
|
||
local snapshot = self.battleData:getFirstSequenceSnapshot()
|
||
if snapshot then -- 如果有快照,则恢复一次
|
||
for posId, info in pairs(snapshot) do
|
||
local entity = self.battleData:getGridEntity(posId)
|
||
if entity then
|
||
entity:setInfoBySnapshop(info)
|
||
end
|
||
end
|
||
end
|
||
|
||
self.battleData:clearGridSequence()
|
||
self:onLinkChange()
|
||
return
|
||
end
|
||
|
||
self:onLinkOver()
|
||
end
|
||
end
|
||
|
||
function BattleController:onLinkOver()
|
||
self.battleUI:hideAllSfxLine()
|
||
local sequence = self.battleData:getGridSequence()
|
||
local count = #sequence
|
||
if count < self:getMinEliminationCount() then
|
||
return
|
||
end
|
||
|
||
local skillId = self.battleData:getSequenceHadSkill()
|
||
local skillEntity
|
||
local linkElementType
|
||
local influenceElementType
|
||
if skillId then
|
||
skillEntity = self.battleData:getSkillEntityBySkillId(skillId)
|
||
end
|
||
|
||
local elementTypeMap = {}
|
||
local eliminationPosIds = {}
|
||
local boomGridIds = {}
|
||
local lineCount = 0
|
||
|
||
for _, info in ipairs(sequence) do
|
||
if not eliminationPosIds[info.posId] then
|
||
local entity = self.battleData:getGridEntity(info.posId)
|
||
if not entity:getSkillId() then
|
||
local elementType = entity:getElementType()
|
||
elementTypeMap[elementType] = (elementTypeMap[elementType] or 0) + 1
|
||
linkElementType = elementType
|
||
lineCount = lineCount + 1
|
||
end
|
||
boomGridIds[info.posId] = true
|
||
|
||
local outline = BattleConst.GRID_OUT_LINE_POS_ID[info.posId]
|
||
for aroundPosId, _ in pairs(outline) do
|
||
boomGridIds[aroundPosId] = true
|
||
end
|
||
|
||
local entity = self.battleData:getGridEntity(info.posId)
|
||
entity:setIsIdle(true)
|
||
eliminationPosIds[info.posId] = true
|
||
end
|
||
end
|
||
|
||
for posId, _ in pairs(self.battleData:getSkillInfluenceGrids()) do
|
||
local entity = self.battleData:getGridEntity(posId)
|
||
if not entity:getIsIdle() then
|
||
if entity:isEmptyIdle() then
|
||
entity:setIsIdle(true)
|
||
if not eliminationPosIds[posId] 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
|
||
if not entity:getSkillId() then
|
||
local elementType = entity:getElementType()
|
||
if not influenceElementType then
|
||
influenceElementType = {}
|
||
end
|
||
influenceElementType[elementType] = true
|
||
end
|
||
else
|
||
boomGridIds[posId] = true
|
||
end
|
||
end
|
||
end
|
||
|
||
for posId, status in pairs(boomGridIds) do
|
||
local entity = self.battleData:getGridEntity(posId)
|
||
if entity then
|
||
local elementTypeInvalid = entity:isElmentTypeInvalid()
|
||
entity:addAroundEliminationCount()
|
||
if entity:getIsIdle() then
|
||
eliminationPosIds[posId] = true
|
||
if not eliminationPosIds[posId] then
|
||
table.insert(sequence, {posId = posId, noAni = elementTypeInvalid})
|
||
if not entity:getSkillId() and not elementTypeInvalid then
|
||
local elementType = entity:getElementType()
|
||
elementTypeMap[elementType] = (elementTypeMap[elementType] or 0) + 1
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
self.battleData:addSkillEnergy(elementTypeMap)
|
||
self.battleData:clearGridSequence()
|
||
|
||
self.battleUI:disableUITouch()
|
||
self.battleUI:eliminationAni(sequence, function()
|
||
self:generateInstructions(skillEntity, linkElementType, lineCount, influenceElementType, elementTypeMap)
|
||
self:enterAtkStep()
|
||
end)
|
||
end
|
||
|
||
function BattleController:fillBoard()
|
||
local pathMap = {}
|
||
local columnCount = {}
|
||
local gridMap = {}
|
||
for c = 1, BattleConst.COLUMN_COUNT do
|
||
for r = BattleConst.ROW_COUNT, 1, -1 do
|
||
local posId = ModuleManager.BattleManager:getPosId(r, c)
|
||
local entity = self.battleData:getGridEntity(posId)
|
||
if entity:getIsIdle() then
|
||
self:fillThisPos(posId, columnCount, gridMap)
|
||
end
|
||
end
|
||
end
|
||
|
||
while true do
|
||
local find = false
|
||
for c = 1, BattleConst.COLUMN_COUNT do
|
||
local list = gridMap[c]
|
||
if list and list[1] then -- 此列有需要填充的元素
|
||
local entity = table.remove(list, 1)
|
||
if entity then
|
||
self.battleData:setGridInfo(entity:getPosId(), self:getRandomGridInfo())
|
||
end
|
||
find = true
|
||
end
|
||
end
|
||
|
||
if not find then
|
||
break
|
||
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 = self.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()
|
||
end)
|
||
end
|
||
|
||
function BattleController:onFillBoardOver()
|
||
self:generateSkill(function()
|
||
self.battleUI:refreshSkill()
|
||
local defTeam = self.battleData:getDefTeam()
|
||
if not defTeam or defTeam:getIsDead() then -- 怪物死了, 直接进入刷新逻辑
|
||
if self.waveIndex >= self.maxWaveIndex then
|
||
self:enterRoundEnd()
|
||
else
|
||
self:_findNextDefUnit()
|
||
end
|
||
return
|
||
else
|
||
self:enterRoundEnd()
|
||
end
|
||
end)
|
||
end
|
||
|
||
function BattleController:generateInstructions(skillEntity, elementType, lineCount, influenceElementTypeMap, elementTypeMap)
|
||
local elementTypeCount = 0
|
||
local assistingList = nil
|
||
---- 援助
|
||
for element, count in pairs(elementTypeMap) do
|
||
if element == elementType then
|
||
elementTypeCount = count
|
||
else
|
||
if assistingList == nil then
|
||
assistingList = {}
|
||
end
|
||
local obj = {
|
||
count = count,
|
||
skillMatch = element,
|
||
}
|
||
table.insert(assistingList, obj)
|
||
end
|
||
end
|
||
|
||
---- 技能
|
||
if skillEntity then
|
||
table.insert(self.instructions, {
|
||
name = BattleConst.INSTRUCTION_NAME.PLAY_SKILL,
|
||
skillMatch = elementType,
|
||
count = elementTypeCount,
|
||
})
|
||
else
|
||
---- 普攻
|
||
if elementTypeCount > 0 then
|
||
table.insert(self.instructions, {
|
||
name = BattleConst.INSTRUCTION_NAME.GENERAL_ATTACK,
|
||
skillMatch = elementType,
|
||
count = elementTypeCount,
|
||
})
|
||
end
|
||
end
|
||
|
||
if assistingList then
|
||
table.insert(self.instructions, {
|
||
name = BattleConst.INSTRUCTION_NAME.ASSISTING,
|
||
assistingList = assistingList,
|
||
})
|
||
end
|
||
|
||
---- 加buff
|
||
if skillEntity then
|
||
if skillEntity:getLinkEffects() and elementType then
|
||
local effectList
|
||
for type, buffEntities in pairs(skillEntity:getLinkEffects()) do
|
||
local buffEntity = buffEntities[elementType]
|
||
if buffEntity then
|
||
if not effectList then
|
||
effectList = {}
|
||
end
|
||
table.insert(effectList, buffEntity)
|
||
end
|
||
end
|
||
if effectList then
|
||
local unit = {
|
||
name = BattleConst.INSTRUCTION_NAME.ADD_CUR_ROUND_ATTR,
|
||
effectList = effectList
|
||
}
|
||
table.insert(self.instructions, unit)
|
||
end
|
||
end
|
||
|
||
if skillEntity:getInInfluenceEffects() and influenceElementTypeMap then
|
||
for influenceElementType , _ in pairs(influenceElementTypeMap) do
|
||
local effectList
|
||
for type, buffEntities in pairs(skillEntity:getInInfluenceEffects()) do
|
||
local buffEntity = buffEntities[influenceElementType]
|
||
if buffEntity then
|
||
if not effectList then
|
||
effectList = {}
|
||
end
|
||
table.insert(effectList, buffEntity)
|
||
end
|
||
end
|
||
if effectList then
|
||
table.insert(self.instructions, {
|
||
name = BattleConst.INSTRUCTION_NAME.ADD_CUR_ROUND_ATTR,
|
||
effectList = effectList
|
||
})
|
||
end
|
||
end
|
||
end
|
||
|
||
if skillEntity:getElementCountEffect() and elementType then
|
||
local effectList
|
||
for type, buffEntities in pairs(skillEntity:getElementCountEffect()) do
|
||
local originBuffEntity = buffEntities.origin
|
||
local useBuffEntity = buffEntities.use
|
||
if not effectList then
|
||
effectList = {}
|
||
end
|
||
local newNum = originBuffEntity:getEffectNum() * lineCount
|
||
useBuffEntity:setEffectNum(newNum)
|
||
table.insert(effectList, useBuffEntity)
|
||
end
|
||
if effectList then
|
||
table.insert(self.instructions, {
|
||
name = BattleConst.INSTRUCTION_NAME.ADD_CUR_ROUND_ATTR,
|
||
effectList = effectList
|
||
})
|
||
end
|
||
end
|
||
|
||
--
|
||
if skillEntity:getSkillAttackBeforeEffects() and elementType then
|
||
local effectList
|
||
for type, buffEntity in pairs(skillEntity:getSkillAttackBeforeEffects()) do
|
||
if not effectList then
|
||
effectList = {}
|
||
end
|
||
table.insert(effectList, buffEntity)
|
||
end
|
||
if effectList then
|
||
table.insert(self.instructions, {
|
||
name = BattleConst.INSTRUCTION_NAME.ADD_CUR_ROUND_ATTR,
|
||
effectList = effectList
|
||
})
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
function BattleController:exeInstructions(callback)
|
||
Logger.logHighlight("--------exeInstructions----------")
|
||
if not self.instructions or #self.instructions <= 0 then
|
||
callback()
|
||
return
|
||
end
|
||
local instruction = table.remove(self.instructions)
|
||
local func = BattleController._doInstruction[instruction.name]
|
||
if func then
|
||
func(self, instruction, function()
|
||
DataManager.BattleData:resetTimeSpeed()
|
||
self:exeInstructions(callback)
|
||
end)
|
||
else
|
||
self:exeInstructions(callback)
|
||
end
|
||
end
|
||
|
||
function BattleController:generateBoard(isFirst)
|
||
local boardList, _ = self:getInitBoard()
|
||
if self.curBoardIndex and self.curBoardIndex >= #boardList then
|
||
return
|
||
end
|
||
|
||
if not self.battleUI then
|
||
return
|
||
end
|
||
|
||
self.curBoardIndex = (self.curBoardIndex or 0) + 1
|
||
local board = boardList[self.curBoardIndex]
|
||
self.battleUI:switchBoard(function()
|
||
self.battleData:refreshBoard(board)
|
||
self.battleUI:initGridCell()
|
||
end, function()
|
||
-- self:enterRoundBegin()
|
||
end, isFirst)
|
||
end
|
||
|
||
function BattleController:putBoardCacheSkill(callback)
|
||
if not self.battleUI then
|
||
return
|
||
end
|
||
self.battleData:cacheBoardSkill()
|
||
local skillList, skillCount = self.battleData:getCacheBoardSkill()
|
||
self.battleUI:cacheSkillAni(skillList, false, callback)
|
||
end
|
||
|
||
function BattleController:popBoardCacheSkill(callback)
|
||
local skillList, skillCount = self.battleData:getCacheBoardSkill()
|
||
self.battleData:clearCacheBoardSkill()
|
||
if self.battleUI and skillCount > 0 then
|
||
local posidList = {}
|
||
for posId, entity in pairs(self.battleData:getGridEnties()) do
|
||
if entity:isEmptyIdle() then
|
||
table.insert(posidList, posId)
|
||
end
|
||
end
|
||
|
||
posidList = table.shuffle(posidList)
|
||
local newSkillId = {}
|
||
for index, info in ipairs(skillList) do
|
||
if posidList[1] then
|
||
newSkillId[index] = info
|
||
newSkillId[index].posId = table.remove(posidList)
|
||
else
|
||
break
|
||
end
|
||
end
|
||
self.battleUI:cacheSkillAni(newSkillId, true, callback)
|
||
else
|
||
if callback then
|
||
callback()
|
||
end
|
||
end
|
||
end
|
||
|
||
function BattleController:generateSkill(callback)
|
||
local map = {}
|
||
local excludeMap = {}
|
||
for _, skillEntity in pairs(self.battleData:getSkillEntities()) do
|
||
if skillEntity:getEnergyEnough() then
|
||
local list = self:getSkillElementList(skillEntity:getPosition(), 1, true, excludeMap)
|
||
if list[1] then
|
||
map[skillEntity:getPosition()] =
|
||
{
|
||
skillId = skillEntity:getSkillId(),
|
||
posId = list[1]
|
||
}
|
||
excludeMap[list[1]] = true
|
||
end
|
||
end
|
||
end
|
||
|
||
if not self.battleUI then
|
||
if callback then
|
||
callback()
|
||
end
|
||
return
|
||
end
|
||
|
||
self.battleUI:generateSkillAni(map, function()
|
||
for elementType, info in pairs(map) do
|
||
self:setGridSkillId(info.posId, info.skillId)
|
||
end
|
||
|
||
if callback then
|
||
callback()
|
||
end
|
||
end)
|
||
end
|
||
|
||
function BattleController:setGridSkillId(posId, skillId)
|
||
local entity = self.battleData:getGridEntity(posId)
|
||
if entity then
|
||
entity:setSkilId(skillId)
|
||
local skillEntity = self.battleData:getSkillEntityBySkillId(skillId)
|
||
if skillEntity and entity:getElementType() ~= skillEntity:getPosition() then
|
||
entity:setElementType(skillEntity:getPosition())
|
||
end
|
||
end
|
||
end
|
||
|
||
function BattleController:generateGridType(gridType)
|
||
if not gridType then
|
||
return
|
||
end
|
||
|
||
local list = {}
|
||
local count = 0
|
||
for posId, entity in pairs(self.battleData:getGridEnties()) do
|
||
if entity:isEmptyIdle() then
|
||
table.insert(list, entity)
|
||
count = count + 1
|
||
end
|
||
end
|
||
if count > 0 then
|
||
local entity = list[math.random(1, count)]
|
||
self.battleData:setGridInfo(entity:getPosId(), {gridType = gridType, elementType = entity:getElementType()})
|
||
end
|
||
end
|
||
|
||
function BattleController:getSkillElementList(elementType, count, useAlternate, excludeMap)
|
||
local result = {}
|
||
local gridEntities = self.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() and not excludeMap[posId] 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, gridMap)
|
||
local entity = self.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 = self.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})
|
||
|
||
self.battleData:exchangeGridEntities(posId, fallPosId)
|
||
if not gridMap[c] then
|
||
gridMap[c] = {}
|
||
end
|
||
table.insert(gridMap[c], fallEntity)
|
||
else
|
||
for index, fallPosId in ipairs(list) do
|
||
local fallEntity = self.battleData:getGridEntity(fallPosId)
|
||
if not fallEntity then -- 异常情况,理论上不可能不存在
|
||
return
|
||
end
|
||
if not fallEntity:isCantFallType() then
|
||
if fallEntity:getIsIdle() then
|
||
self:fillThisPos(fallPosId, columnCount, gridMap)
|
||
end
|
||
fallEntity = self.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})
|
||
|
||
self.battleData:exchangeGridEntities(posId, fallPosId)
|
||
self:fillThisPos(fallPosId, columnCount, gridMap)
|
||
return
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
function BattleController:getRandomGridInfo()
|
||
local list, fixedRandomGrid = self:getInitBoard()
|
||
local fixedRandomList = fixedRandomGrid[self.curBoardIndex]
|
||
|
||
local gridType = 0
|
||
local elementType
|
||
if fixedRandomList and fixedRandomList[1] then
|
||
elementType = table.remove(fixedRandomList, 1)
|
||
else
|
||
local map = self.battleData:getElementTypeMap()
|
||
local indexs = {}
|
||
local typeList = {}
|
||
for typeName, typeNum in pairs(BattleConst.ELEMENT_TYPE) do
|
||
if not self:getSealElementType()[typeNum] and self.battleData:getSkillEntityByElement(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 = self.battleData:clearSkillInfluenceGrids()
|
||
for posId, _ in pairs(girds) do
|
||
local entity = self.battleData:getGridEntity(posId)
|
||
if entity:getCell() then
|
||
entity:getCell():showCircle(false)
|
||
end
|
||
end
|
||
|
||
local sequence = self.battleData:getGridSequence()
|
||
local sequenceEntities = {}
|
||
for _, info in ipairs(sequence) do
|
||
local entity = self.battleData:getGridEntity(info.posId)
|
||
table.insert(sequenceEntities, entity)
|
||
end
|
||
|
||
for _, info in ipairs(sequence) do
|
||
local entity = self.battleData:getGridEntity(info.posId)
|
||
local skillId = entity:getSkillId()
|
||
if skillId then
|
||
local skillEntity = self.battleData:getSkillEntityBySkillId(skillId)
|
||
if skillEntity then
|
||
BATTLE_BOARD_SKILL_HANDLE.activeBoardSkill(info.posId, skillEntity, self.battleData:getGridEnties(), sequenceEntities)
|
||
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 = self.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 self.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 pairs(cfg) do
|
||
if not self:getNotInvolvedSkills()[skillId] then
|
||
if info.universal then
|
||
if not info.limit_times or self.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
|
||
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, value)
|
||
self.battleData:addSkillCount(skillId, value)
|
||
BATTLE_ROGUE_SKILL_HANDLE.takeEffect(skillId, self.battleData, self, value)
|
||
|
||
local skillEntities = self.battleData:getSkillEntities()
|
||
for _, entity in pairs(skillEntities) do
|
||
entity:gotUpSKill(skillId)
|
||
end
|
||
|
||
self:onRoundEnd()
|
||
|
||
if self.battleUI then
|
||
self.battleUI:refreshBoard()
|
||
self.battleUI:refreshSkill()
|
||
end
|
||
end
|
||
|
||
function BattleController:changeElementType(count, elementType)
|
||
local list = {}
|
||
for _, entity in pairs(self.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)
|
||
if not self.battleData or not self.battleData.atkTeam then
|
||
return
|
||
end
|
||
|
||
local attr = BUFF_NAME_TO_ATTR[attrName]
|
||
if attr then
|
||
self.battleData.atkTeam:addAttr(attr[1], value, attr[2])
|
||
else
|
||
local func = BattleBuffHandle.addAttribute[attrName]
|
||
if func then
|
||
local unitComp
|
||
for matchType, comp in pairs(self.atkTeam:getUnitComp()) do
|
||
unitComp = comp
|
||
break
|
||
end
|
||
if unitComp then
|
||
func(unitComp, value)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
---- 快照一次棋盘
|
||
function BattleController:snapshotBoard()
|
||
local snapshot = {}
|
||
for _, entity in pairs(self.battleData:getGridEnties()) do
|
||
snapshot[entity:getPosId()] = entity:getSnapshoptInfo()
|
||
end
|
||
return snapshot
|
||
end
|
||
|
||
function BattleController:showAttention()
|
||
if not self.attentionList then
|
||
return
|
||
end
|
||
|
||
if self.attentionSid then
|
||
ModuleManager.BattleManager:unscheduleGlobal(self.attentionSid)
|
||
self.attentionSid = nil
|
||
end
|
||
|
||
self.attentionSid = ModuleManager.BattleManager:performWithDelayGlobal(function()
|
||
for _, posId in ipairs(self.attentionList) do
|
||
local entity = self.battleData:getGridEntity(posId)
|
||
if entity and entity:getCell() then
|
||
entity:getCell():showAni()
|
||
end
|
||
end
|
||
end, 2)
|
||
end
|
||
|
||
function BattleController:shuffleBoard()
|
||
-- local posList = {}
|
||
-- local gridEntityList = {}
|
||
-- local elementList = {}
|
||
-- for posId, entity in pairs(self.battleData:getGridEnties()) do
|
||
-- table.insert(posList, posId)
|
||
-- table.insert(gridEntityList, entity)
|
||
-- if entity:canLink() then
|
||
-- table.insert(elementList, entity)
|
||
-- end
|
||
-- end
|
||
|
||
-- local needCount = self:getMinEliminationCount()
|
||
-- local tempMap = {}
|
||
-- while needCount > 0 do
|
||
-- local find = false
|
||
-- for _, entity1 in ipairs(elementList) do
|
||
-- if not tempMap[entity1:getPosId] then
|
||
-- tempMap[entity1:getPosId] = true
|
||
-- for _, entity2 in ipairs(elementList) do
|
||
-- if not tempMap[entity2:getPosId] then
|
||
-- if entity2: then
|
||
-- -- body
|
||
-- end
|
||
-- end
|
||
-- end
|
||
-- end
|
||
-- end
|
||
-- if not find then
|
||
-- break
|
||
-- end
|
||
-- end
|
||
end
|
||
|
||
function BattleController:findAttention()
|
||
local find = false
|
||
local posIdMap = {}
|
||
local pathList
|
||
for r = 1, GConst.BattleConst.ROW_COUNT do
|
||
for c = 1, GConst.BattleConst.COLUMN_COUNT do
|
||
local posId = ModuleManager.BattleManager:getPosId(r, c)
|
||
local gridEntity = self.battleData:getGridEntity(posId)
|
||
local skillId = gridEntity:getSkillId()
|
||
local mainElementType = gridEntity:getElementType()
|
||
if skillId then
|
||
local skillEntity = self.battleData:getSkillEntityBySkillId(skillId)
|
||
if skillEntity:getIgnoreElementType() then
|
||
mainElementType = nil
|
||
end
|
||
end
|
||
|
||
pathList = {}
|
||
self:findLinkLine(posId, posIdMap, mainElementType == nil, mainElementType, pathList)
|
||
if table.nums(pathList) >= self:getMinEliminationCount() then
|
||
find = true
|
||
break
|
||
end
|
||
end
|
||
if find then
|
||
break
|
||
end
|
||
end
|
||
|
||
return find, pathList
|
||
end
|
||
|
||
function BattleController:findLinkLine(posId, posIdMap, hadSkill, mainElementType, lineList)
|
||
posIdMap[posId] = true
|
||
table.insert(lineList, posId)
|
||
local list = BattleConst.GRID_OUT_LINE_POS_ID[posId]
|
||
if not list then
|
||
return hadSkill
|
||
end
|
||
|
||
if #lineList >= self:getMinEliminationCount() then
|
||
return hadSkill
|
||
end
|
||
|
||
local lineCount = 0
|
||
local maxLineList
|
||
local maxPosIdMap
|
||
local maxGotSkill
|
||
for aroundposId, _ in pairs(list) do
|
||
if not posIdMap[aroundposId] then
|
||
local gridEntity = self.battleData:getGridEntity(aroundposId)
|
||
if gridEntity then
|
||
if gridEntity:isEmptyIdle() then
|
||
if not mainElementType or gridEntity:getElementType() == mainElementType then
|
||
mainElementType = mainElementType or gridEntity:getElementType()
|
||
local tempIdMap = GFunc.getTable(posIdMap)
|
||
local newList = GFunc.getTable(lineList)
|
||
local gotSkill = self:findLinkLine(aroundposId, tempIdMap, hadSkill, mainElementType, newList)
|
||
local count = #newList
|
||
if count > lineCount then
|
||
lineCount = count
|
||
maxLineList = newList
|
||
maxPosIdMap = tempIdMap
|
||
maxGotSkill = gotSkill
|
||
end
|
||
end
|
||
elseif gridEntity:getSkillId() and not hadSkill and mainElementType then
|
||
local skillId = gridEntity:getSkillId()
|
||
local skillEntity = self.battleData:getSkillEntityBySkillId(skillId)
|
||
if skillEntity then
|
||
if skillEntity:getIgnoreElementType() or skillEntity:getPosition() == mainElementType then
|
||
local tempIdMap = GFunc.getTable(posIdMap)
|
||
local newList = GFunc.getTable(lineList)
|
||
local gotSkill = self:findLinkLine(aroundposId, tempIdMap, true, mainElementType, newList)
|
||
local count = #newList
|
||
if count > lineCount then
|
||
lineCount = count
|
||
maxLineList = newList
|
||
maxPosIdMap = tempIdMap
|
||
maxGotSkill = gotSkill
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
if lineCount > 0 then
|
||
for index, id in ipairs(maxLineList) do
|
||
lineList[index] = id
|
||
end
|
||
|
||
for _, id in pairs(maxPosIdMap) do
|
||
posIdMap[id] = true
|
||
end
|
||
|
||
hadSkill = maxGotSkill
|
||
end
|
||
|
||
return hadSkill
|
||
end
|
||
|
||
function BattleController:randomDisruptionBoard()
|
||
|
||
end
|
||
|
||
function BattleController:addBattleExp(exp)
|
||
if not self.battleData or not exp then
|
||
return
|
||
end
|
||
self.battleData:addExp(exp)
|
||
end
|
||
|
||
function BattleController:_tick(dt)
|
||
if self.isPause then
|
||
return
|
||
end
|
||
self.time = self.time + dt
|
||
self.atkTeam:tick(dt)
|
||
self.defTeam:tick(dt)
|
||
local count = #self.effectTexts
|
||
for i = count, 1, -1 do
|
||
self.effectTexts[i]:tick(dt)
|
||
if self.effectTexts[i]:getDuration() < 0 then
|
||
BattleHelper:recycleEffectText(self.effectTexts[i])
|
||
table.remove(self.effectTexts, i)
|
||
end
|
||
end
|
||
self:tick(dt)
|
||
end
|
||
|
||
function BattleController:battleEnd()
|
||
if self.battleUI then
|
||
self.battleUI:enableUITouch()
|
||
end
|
||
self:controllBattleEnd()
|
||
end
|
||
|
||
function BattleController:clear()
|
||
if self.alreadyClear then
|
||
return
|
||
end
|
||
self.alreadyClear = true
|
||
if self.tickSid then
|
||
BattleScheduler:unscheduleGlobal(self.tickSid)
|
||
self.tickSid = nil
|
||
end
|
||
BattleScheduler:clear()
|
||
BattleHelper:clear()
|
||
BattlePassive:clear()
|
||
self:unBindAll()
|
||
DataManager.BattleData:resetTimeSpeed()
|
||
end
|
||
|
||
function BattleController:endBattleAndExit()
|
||
ModuleManager.BattleManager:exitBattle()
|
||
end
|
||
|
||
function BattleController:showEffectNumber(colorType, effectType, num, x, y)
|
||
local effectTextComp = BattleHelper:getEffectText(self.battleUI:getNumberNode(), colorType)
|
||
effectTextComp:showEffectNumber(effectType, num, x, y)
|
||
table.insert(self.effectTexts, effectTextComp)
|
||
end
|
||
|
||
local function _addCurRoundAttr(self, instruction, callback)
|
||
if instruction.effectList then
|
||
local defComp = self:getOtherSideMainUnit(BattleConst.SIDE_ATK)
|
||
local mainComp = self:getOtherSideMainUnit(BattleConst.SIDE_DEF)
|
||
for _, effect in ipairs(instruction.effectList) do
|
||
local target
|
||
if effect:getTartgetSide() == BattleConst.SIDE_DEF then
|
||
target = defComp
|
||
else
|
||
target = mainComp
|
||
end
|
||
mainComp:takeEffect(effect, target)
|
||
end
|
||
end
|
||
|
||
callback()
|
||
end
|
||
|
||
local function _assisting(self, instruction, callback)
|
||
self.atkTeam:useAssistingSkill(instruction.assistingList, callback)
|
||
end
|
||
|
||
local function _generalAttack(self, instruction, callback)
|
||
self.atkTeam:useNormalSkill(instruction.skillMatch, instruction.count, callback)
|
||
end
|
||
|
||
local function _playSkill(self, instruction, callback)
|
||
self.atkTeam:useSkill(instruction.skillMatch, instruction.count, callback)
|
||
end
|
||
|
||
BattleController._doInstruction = {
|
||
[BattleConst.INSTRUCTION_NAME.ADD_CUR_ROUND_ATTR] = _addCurRoundAttr,
|
||
[BattleConst.INSTRUCTION_NAME.ASSISTING] = _assisting,
|
||
[BattleConst.INSTRUCTION_NAME.GENERAL_ATTACK] = _generalAttack,
|
||
[BattleConst.INSTRUCTION_NAME.PLAY_SKILL] = _playSkill,
|
||
}
|
||
|
||
return BattleController |