2632 lines
91 KiB
Lua
2632 lines
91 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 BattlePool = require "app/module/battle/helper/battle_pool"
|
||
local BattleBuffEntity = require "app/userdata/battle/skill/battle_buff_entity"
|
||
|
||
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 BATTLE_GRID_EFFECT_HANDLE = require "app/module/battle/skill/battle_grid_effect_handle"
|
||
local BATTLE_INSTRUCTIONS_HELPER = require "app/module/battle/helper/battle_instructions_helper"
|
||
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
|
||
local GRID_BREAK_CONDITION = BattleConst.GRID_BREAK_CONDITION
|
||
|
||
-- *************各个子模块的战斗需要重写的方法 START*************
|
||
function BattleController:getChapterId()
|
||
return 0
|
||
end
|
||
|
||
function BattleController:getInitBoard()
|
||
return {}
|
||
end
|
||
|
||
function BattleController:getNotInvolvedSkills()
|
||
return {}
|
||
end
|
||
|
||
function BattleController:getFixedRogueSkill()
|
||
return {}
|
||
end
|
||
|
||
function BattleController:getSealElementType()
|
||
return {}
|
||
end
|
||
|
||
function BattleController:getBuffs()
|
||
return {}
|
||
end
|
||
|
||
function BattleController:handleBuffs(side)
|
||
for _, buffInfo in ipairs(self:getBuffs()) do
|
||
local buffEntity = buffInfo.buffEntity
|
||
local buffTargetSide = buffEntity:getTargetSide()
|
||
local target
|
||
if buffTargetSide == BattleConst.SIDE_DEF then
|
||
target = self.defTeam:getMainUnit()
|
||
elseif buffTargetSide == BattleConst.SIDE_ATK then
|
||
target = self.atkTeam:getMainUnit()
|
||
elseif buffTargetSide == BattleConst.SIDE_ATK_ALL then
|
||
if not side or side == buffTargetSide then
|
||
for matchtype, comp in pairs(self.atkTeam:getUnitComp()) do
|
||
local buffEntity = BattleBuffEntity:create()
|
||
buffEntity:init(buffInfo.effect, comp.unitEntity)
|
||
buffEntity:setTargetSide(buffTargetSide)
|
||
comp:takeEffect(buffEntity, comp)
|
||
end
|
||
end
|
||
else
|
||
local matchType = BattleConst.SIDE_OBJ_TO_MATCH_TYPE[buffTargetSide]
|
||
if matchType then
|
||
target = self.atkTeam:getUnitComp()[matchType]
|
||
end
|
||
end
|
||
|
||
if target then
|
||
if side then
|
||
if buffTargetSide == side then
|
||
buffEntity:setOwner(target)
|
||
target:takeEffect(buffEntity, target)
|
||
end
|
||
else
|
||
buffEntity:setOwner(target)
|
||
target:takeEffect(buffEntity, target)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
-- 战斗对应的ui
|
||
function BattleController:getBattleUIPath()
|
||
return "app/ui/battle/battle_ui"
|
||
end
|
||
|
||
-- 战斗结束
|
||
function BattleController:controllBattleEnd()
|
||
end
|
||
|
||
-- 不同模块的战斗需要初始化的东西
|
||
function BattleController:initOther()
|
||
end
|
||
|
||
-- 怪物攻击力加成
|
||
function BattleController:getMonsterAtkAddition()
|
||
return BattleConst.DEFAULT_FACTOR
|
||
end
|
||
|
||
-- 怪物血量加成
|
||
function BattleController:getMonsterHpAddition()
|
||
return BattleConst.DEFAULT_FACTOR
|
||
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:enterRoundEnd()
|
||
end
|
||
|
||
function BattleController:onDefDead(callback)
|
||
self.defTeam:getMainUnit():playDead(function()
|
||
local monsterId = self.defTeam:getMainUnit().unitEntity:getDeathSummon()
|
||
if monsterId > 0 then
|
||
self:generateMonsterById(monsterId, function()
|
||
if callback then
|
||
callback()
|
||
end
|
||
self:handleBuffs(BattleConst.SIDE_DEF)
|
||
end)
|
||
else
|
||
if callback then
|
||
callback()
|
||
end
|
||
end
|
||
end)
|
||
end
|
||
|
||
function BattleController:tick(dt)
|
||
end
|
||
|
||
function BattleController:onLinkChange()
|
||
self.battleUI:hideAllSfxLine()
|
||
self.linkChangeNeedFalsePosMap = table.clearOrCreate(self.linkChangeNeedFalsePosMap)
|
||
for posId, entity in pairs(self.battleData:getGridEnties()) do
|
||
if entity:getCell() then
|
||
self.linkChangeNeedFalsePosMap[posId] = entity:getCell()
|
||
end
|
||
end
|
||
|
||
local sequence = self.battleData:getGridSequence()
|
||
local mainElementType
|
||
|
||
for index, info in ipairs(sequence) do
|
||
local entity = self.battleData:getGridEntity(info.posId)
|
||
if not mainElementType then
|
||
local skillId = entity:getSkillId()
|
||
if not skillId then
|
||
mainElementType = entity:getElementType()
|
||
break
|
||
end
|
||
end
|
||
end
|
||
|
||
local count = #sequence
|
||
|
||
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 self.linkChangeNeedFalsePosMap[info.posId] then
|
||
self.linkChangeNeedFalsePosMap[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
|
||
if index == count then
|
||
if entity:getCell() then
|
||
entity:getCell():showAni()
|
||
end
|
||
end
|
||
end
|
||
|
||
for posId, cell in pairs(self.linkChangeNeedFalsePosMap) do
|
||
cell:showHighLight(false)
|
||
end
|
||
|
||
for posId, info in pairs(self.battleData:getSkillInfluenceGrids()) do
|
||
local entity = self.battleData:getGridEntity(posId)
|
||
if info.direction ~= BattleConst.BOARD_RANGE_TYPE.RANDOM then
|
||
if entity:getCell() then
|
||
entity:getCell():showCircle(true)
|
||
end
|
||
end
|
||
end
|
||
|
||
if not self.atkTeam:getMainUnit().unitEntity:getActiveSkillLimit() then
|
||
local aniSequence, influenceElementType, lineCount, elementTypeMap, linkElementType = self:calculateCurElimination(true)
|
||
self.battleUI:refreshSkill(elementTypeMap, count > 0)
|
||
end
|
||
|
||
if mainElementType then
|
||
self.atkTeam:changeMainUnit(mainElementType)
|
||
end
|
||
end
|
||
|
||
function BattleController:postWaveOver(atkDead, isQuit)
|
||
|
||
end
|
||
|
||
function BattleController:postFightStart()
|
||
|
||
end
|
||
|
||
function BattleController:onEliminationBegin()
|
||
|
||
end
|
||
|
||
---- 障碍格子图片
|
||
function BattleController:getBlockIcon()
|
||
return "battle_hinder_4"
|
||
end
|
||
|
||
function BattleController:getChessBoardBgName()
|
||
return "chessboard_1"
|
||
end
|
||
|
||
-- *************各个子模块的战斗需要重写的方法 END*************
|
||
|
||
function BattleController:ctor()
|
||
self.battleData = DataManager.BattleData
|
||
end
|
||
|
||
function BattleController:init(params)
|
||
params = params or {}
|
||
self.battleType = params.battleType or GConst.BattleConst.BATTLE_TYPE.STAGE
|
||
self.battleStartTime = Time:getServerTime()
|
||
self.waveStartTime = Time:getServerTime()
|
||
self.eliminateCount = 0
|
||
self.eliminateTotalCount = 0
|
||
self.realTime = 0
|
||
self.taskProgress = {}
|
||
self.waveRoundCount = {}
|
||
|
||
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.gotMysteryBoxIndexs = {}
|
||
self.showMysteryBoxIndexs = {}
|
||
self.delayEffectTextList = {}
|
||
self.delayEffectTextCount = 0
|
||
self.time = 0
|
||
self.battleData:init()
|
||
BattleScheduler:init()
|
||
BattlePool: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, autoClose)
|
||
if side == BattleConst.SIDE_ATK then
|
||
local buffList = self.atkTeam:getBuffList()
|
||
if #buffList <= 0 then
|
||
return
|
||
end
|
||
self.battleUI:showLeftBuffTips(buffList, autoClose)
|
||
else
|
||
local buffList = self.defTeam:getBuffList()
|
||
if #buffList <= 0 then
|
||
return
|
||
end
|
||
self.battleUI:showRightBuffTips(buffList, autoClose)
|
||
end
|
||
end
|
||
|
||
function BattleController:showCombo(count)
|
||
self.battleUI:showCombo(count)
|
||
end
|
||
|
||
function BattleController:hideCombo()
|
||
self.battleUI:hideCombo()
|
||
end
|
||
|
||
function BattleController:showCounterAttack(count, side)
|
||
self.battleUI:showCounterAttack(count, side)
|
||
end
|
||
|
||
function BattleController:hideCounterAttack()
|
||
self.battleUI:hideCounterAttack()
|
||
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:getBattleNumberRed(),
|
||
self.battleUI:getBattleNumberGreen(),
|
||
self.battleUI:getBattleNumberBlue(),
|
||
self.battleUI:getBattleNumberWhite(),
|
||
self.battleUI:getBattleNumberSpecial())
|
||
self:initAtkUnits(onPreloadFinished)
|
||
self:initDefUnits(onPreloadFinished)
|
||
self.battleUI:refreshChessBoard(self:getChessBoardBgName())
|
||
end)
|
||
BattleHelper:setBaseOrder(self.battleUI:getUIOrder())
|
||
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:getOtherSideTeam(side)
|
||
if side == BattleConst.SIDE_ATK then
|
||
return self.defTeam
|
||
else
|
||
return self.atkTeam
|
||
end
|
||
end
|
||
|
||
function BattleController:onLoadComplete()
|
||
self:handleBuffs()
|
||
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:addTimeSpeed()
|
||
if self.skillSlowDownDuration then
|
||
return
|
||
end
|
||
DataManager.BattleData:addTimeSpeed()
|
||
end
|
||
|
||
function BattleController:resetTimeSpeed()
|
||
DataManager.BattleData:resetTimeSpeed()
|
||
if self.skillSlowDownDuration then
|
||
self.skillSlowDownDuration = nil
|
||
end
|
||
end
|
||
|
||
function BattleController:setSkillSlowDown(timeScale, duration)
|
||
self.skillSlowDownDuration = duration
|
||
DataManager.BattleData:setSkillTimeSpeed(timeScale)
|
||
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.atkTeam:onRoundEnd()
|
||
self:findNextDefUnit()
|
||
self:generateBoard()
|
||
end)
|
||
else
|
||
self.atkTeam:onRoundEnd()
|
||
self:findNextDefUnit()
|
||
end
|
||
end
|
||
|
||
---- start 回合步骤
|
||
|
||
function BattleController:enterNextWave()
|
||
local atkTeam = self.battleData:getAtkTeam()
|
||
if not atkTeam or atkTeam:getIsDead() then
|
||
self.victory = false
|
||
self:postWaveOver(true)
|
||
self:battleEnd()
|
||
return
|
||
end
|
||
|
||
if self.waveIndex ~= 0 then
|
||
if self.isBossWave then
|
||
self:addTaskProgress(BattleConst.BATTLE_TASK_FIELD.KILL_BOSS, 1)
|
||
else
|
||
self:addTaskProgress(BattleConst.BATTLE_TASK_FIELD.KILL_NORMAL_MONSTER, 1)
|
||
end
|
||
end
|
||
|
||
if self.waveIndex >= self.maxWaveIndex then
|
||
self.victory = true
|
||
self:postWaveOver(false)
|
||
self:battleEnd()
|
||
return
|
||
end
|
||
|
||
if self.waveIndex ~= 0 then -- 第一波
|
||
self:postWaveOver(false)
|
||
end
|
||
|
||
self.waveIndex = self.waveIndex + 1
|
||
if self.battleUI then
|
||
self.battleUI:refreshWave(self.waveIndex)
|
||
end
|
||
if self.waveIndex == 1 then -- 第一波
|
||
self:generateBoard(true)
|
||
else
|
||
-- 上报关卡结束
|
||
self.defTeam:prepare()
|
||
end
|
||
|
||
self.waveStartTime = Time:getServerTime()
|
||
self.eliminateCount = 0
|
||
|
||
self.isBossWave = self.defTeam:getMainUnit().unitEntity:getIsBoss()
|
||
self:postFightStart()
|
||
self:enterRoundBegin()
|
||
end
|
||
|
||
function BattleController:enterRoundBegin()
|
||
self.waveRoundCount[self.waveIndex] = (self.waveRoundCount[self.waveIndex] or 0) + 1
|
||
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_BEGIN
|
||
self:takeGridEffect()
|
||
self:enterEliminationBegin()
|
||
end
|
||
|
||
function BattleController:takeGridEffect()
|
||
local gridEntities = self.battleData:getGridEnties()
|
||
local effectGrid = {}
|
||
for posId, entity in pairs(gridEntities) do
|
||
if entity:getEffectType() then
|
||
table.insert(effectGrid, entity)
|
||
end
|
||
end
|
||
|
||
effectGrid = table.shuffle(effectGrid)
|
||
local availableEffectTypeMap
|
||
for _, entity in ipairs(effectGrid) do
|
||
local effectType = entity:getEffectType()
|
||
if not availableEffectTypeMap or not availableEffectTypeMap[effectType] then
|
||
local succ = BATTLE_GRID_EFFECT_HANDLE.gridEffectOn(entity:getPosId(), gridEntities, BattleConst.GRID_EFFECT_TRIGGER_TYPE.ON_ROUND_BEGIN, self)
|
||
if succ and effectType == BattleConst.GRID_EFFECT_TYPE.CROSS_SPREAD then
|
||
if not availableEffectTypeMap then
|
||
availableEffectTypeMap = {}
|
||
end
|
||
availableEffectTypeMap[effectType] = true
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
function BattleController:enterEliminationBegin()
|
||
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_BEGIN
|
||
self:onEliminationBegin()
|
||
self:enterRefreshBoard(true)
|
||
end
|
||
|
||
function BattleController:enterElimination(needDelay)
|
||
if self.showSelectSkillSid then
|
||
ModuleManager.BattleManager:unscheduleGlobal(self.showSelectSkillSid)
|
||
self.showSelectSkillSid = nil
|
||
end
|
||
|
||
if self.battleData:useAddlvCount() then
|
||
self:tryShowSelectSkillComp(needDelay)
|
||
return
|
||
end
|
||
|
||
self.battleUI:hideAllBoardSfxs()
|
||
|
||
-- 检查棋盘
|
||
local find, pathList = self:findAttention()
|
||
if not find then -- 如果没找到,就要打乱棋盘
|
||
self:shuffleBoard(function()
|
||
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_ELIMINATION
|
||
end)
|
||
else
|
||
self.attentionList = pathList
|
||
-- ModuleManager.BattleManager:performWithDelayGlobal(function()
|
||
-- for _, posId in ipairs(pathList) do
|
||
-- local entity = self.battleData:getGridEntity(posId)
|
||
-- if entity and entity:getCell() then
|
||
-- entity:getCell():showAni()
|
||
-- end
|
||
-- end
|
||
-- end, 2)
|
||
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_ELIMINATION
|
||
end
|
||
end
|
||
|
||
function BattleController:enterBattleStep()
|
||
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_TEAM_ACTION
|
||
if not self.battleTeamActionList then
|
||
self.battleTeamActionList = {}
|
||
else
|
||
for i = #self.battleTeamActionList, 1, -1 do
|
||
self.battleTeamActionList[i] = nil
|
||
end
|
||
end
|
||
|
||
local atkAction = function()
|
||
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_ATK_STEP
|
||
self:exeInstructions(function()
|
||
self:enterNextTeamAction()
|
||
end)
|
||
end
|
||
|
||
local defAction = function()
|
||
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_DEF_STEP
|
||
self.defTeam:mainUnitUseAllSkills(BattleConst.ATTACK_ACTION_STATE.NORMAL, function()
|
||
self:enterNextTeamAction()
|
||
end)
|
||
end
|
||
|
||
if self.battleData:getAtkTeam():getFirstHand() < self.battleData:getDefTeam():getFirstHand() then
|
||
self:addTeamActionList(defAction, 1)
|
||
self:addTeamActionList(atkAction, 2)
|
||
else
|
||
self:addTeamActionList(atkAction, 1)
|
||
self:addTeamActionList(defAction, 2)
|
||
end
|
||
|
||
self:enterNextTeamAction()
|
||
end
|
||
|
||
function BattleController:addTeamActionList(func, index)
|
||
if not self.battleTeamActionList then
|
||
self.battleTeamActionList = {}
|
||
end
|
||
|
||
index = index or 1
|
||
table.insert(self.battleTeamActionList, index, func)
|
||
end
|
||
|
||
function BattleController:enterNextTeamAction()
|
||
self.atkTeam:onActionOver()
|
||
self.defTeam:onActionOver()
|
||
|
||
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_TEAM_ACTION_OVER
|
||
self:hideCombo()
|
||
self:hideCounterAttack()
|
||
|
||
if self:checkTeamIsDead(function() self:enterRoundEnd() end) then
|
||
return
|
||
end
|
||
|
||
if not self.battleTeamActionList or not self.battleTeamActionList[1] then
|
||
self:enterRoundEnd()
|
||
return
|
||
end
|
||
|
||
local action = table.remove(self.battleTeamActionList, 1)
|
||
action()
|
||
end
|
||
|
||
function BattleController:checkTeamIsDead(callback)
|
||
local atkTeam = self.battleData:getAtkTeam()
|
||
if not atkTeam or atkTeam:getIsDead() then -- 英雄死了, 直接结算
|
||
self:enterNextWave()
|
||
return true
|
||
end
|
||
|
||
local defTeam = self.battleData:getDefTeam()
|
||
if not defTeam or defTeam:getIsDead() then -- 怪物死了, 直接进入刷新逻辑
|
||
if self.waveIndex >= self.maxWaveIndex then
|
||
if callback then
|
||
callback()
|
||
end
|
||
else
|
||
self:onDefDead(function()
|
||
self.defTeam:removeAllBuff()
|
||
if self.battleData:getDefTeam():getIsDead() then
|
||
self:_findNextDefUnit()
|
||
else
|
||
if callback() then
|
||
callback()
|
||
end
|
||
end
|
||
end)
|
||
end
|
||
return true
|
||
end
|
||
return false
|
||
end
|
||
|
||
function BattleController:getIsAtkStep()
|
||
return self.roundStep == BattleConst.BATTLE_ROUND_STEP.ON_ATK_STEP
|
||
end
|
||
|
||
function BattleController:enterRefreshBoard(isRoundBeginCheck, callback)
|
||
if not isRoundBeginCheck then
|
||
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_REFRESH_BOARD
|
||
end
|
||
self.onFillBoardOverCallback = callback
|
||
self:fillBoard(isRoundBeginCheck)
|
||
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()
|
||
|
||
if self:checkTeamIsDead(function() self:enterNextWave() end) then
|
||
return
|
||
end
|
||
|
||
self:onRoundEnd()
|
||
end
|
||
|
||
function BattleController:onRoundEnd(toNextWave)
|
||
if toNextWave then
|
||
self:enterNextWave()
|
||
else
|
||
self:enterRoundBegin()
|
||
end
|
||
end
|
||
|
||
---- end回合步骤
|
||
|
||
function BattleController:onTouchEvent(eventType, posId, isVirtual)
|
||
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
|
||
self:onLinkStart(entity, posId, isVirtual)
|
||
elseif eventType == ELIMINATION_TOUCH_EVENT.ENTER then
|
||
if self.battleData:getIsVirtual() and not isVirtual then
|
||
return
|
||
end
|
||
|
||
self:onLinkEnter(entity, posId, isVirtual)
|
||
elseif eventType == ELIMINATION_TOUCH_EVENT.EXIT then
|
||
|
||
else -- 取消和抬起
|
||
self:onLinkCancelOrUp(entity, posId, isVirtual)
|
||
end
|
||
end
|
||
|
||
function BattleController:onLinkStart(entity, posId, isVirtual)
|
||
if DataManager.TutorialData:getIsInTutorial() then
|
||
local elementList = DataManager.TutorialData:getTargetElement()
|
||
if elementList then
|
||
local find = false
|
||
for _, curPosId in ipairs(elementList) do
|
||
if curPosId == posId then
|
||
find = true
|
||
break
|
||
end
|
||
end
|
||
if not find then
|
||
return
|
||
end
|
||
end
|
||
end
|
||
|
||
if not isVirtual then
|
||
self.battleUI:showTutorialFinger()
|
||
end
|
||
if #self.battleData:getGridSequence() > 0 then
|
||
self:clearGridSequence()
|
||
end
|
||
self.battleData:insertGridSequence(posId, self:snapshotBoard(), isVirtual)
|
||
local skillEntity = self.battleData:getSkillEntityBySkillId(entity:getSkillId())
|
||
local maskElementType = entity:getElementType(skillEntity)
|
||
self.battleUI:showBoardMask(maskElementType, skillEntity and entity:getPosId())
|
||
self:findSkillInfluenceGrids()
|
||
self:onLinkChange()
|
||
|
||
if not isVirtual then
|
||
AudioManager:playEffect(AudioManager.EFFECT_ID.LINK_BO_1)
|
||
if skillEntity then
|
||
AudioManager:playEffect(AudioManager.EFFECT_ID.LINK_SKILL)
|
||
end
|
||
end
|
||
end
|
||
|
||
function BattleController:onLinkEnter(entity, posId, isVirtual)
|
||
local sequence = self.battleData:getGridSequence()
|
||
local sequenceCount = #sequence
|
||
local info = sequence[sequenceCount]
|
||
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 beforePosId == posId then -- 进入的是倒数第二个,则移除倒数第一个
|
||
local snapshot = self.battleData:removeGridSequence(lastPosId)
|
||
if snapshot then -- 如果有快照,则恢复一次
|
||
for posId, info in pairs(snapshot) do
|
||
self.battleData:setInfoBySnapshop(posId, info)
|
||
end
|
||
end
|
||
|
||
local lastEntity = self.battleData:getGridEntity(beforePosId)
|
||
local lastSkillEntity = self.battleData:getSkillEntityBySkillId(lastEntity:getSkillId())
|
||
local maskElementType = lastEntity:getElementType(lastSkillEntity)
|
||
|
||
local _, skillPosId = self.battleData:getSequenceHadSkill()
|
||
self.battleUI:showBoardMask(maskElementType, skillPosId)
|
||
|
||
self:findSkillInfluenceGrids()
|
||
self:onLinkChange()
|
||
end
|
||
return
|
||
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)
|
||
|
||
local hadSkillId, skillPosId = self.battleData:getSequenceHadSkill()
|
||
if skillEntity and hadSkillId then
|
||
return
|
||
end
|
||
|
||
if not elementType or not lastElementType then
|
||
else
|
||
if lastElementType ~= elementType then
|
||
return
|
||
end
|
||
end
|
||
|
||
local maskElementType = elementType or lastElementType
|
||
if not skillPosId then
|
||
if skillId then
|
||
skillPosId = posId
|
||
end
|
||
end
|
||
self.battleUI:showBoardMask(maskElementType, skillPosId)
|
||
|
||
self.battleData:insertGridSequence(posId, self:snapshotBoard(), isVirtual)
|
||
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()
|
||
|
||
if not isVirtual then
|
||
if sequenceCount + 1 == self:getMinEliminationCount() then
|
||
AudioManager:playEffect(AudioManager.EFFECT_ID.LINK_READY)
|
||
end
|
||
AudioManager:playEffect(AudioManager:getBoEffectID(sequenceCount + 1))
|
||
if skillEntity then
|
||
AudioManager:playEffect(AudioManager.EFFECT_ID.LINK_SKILL)
|
||
end
|
||
end
|
||
end
|
||
|
||
function BattleController:onLinkCancelOrUp(entity, posId, isVirtual)
|
||
if isVirtual then
|
||
return
|
||
end
|
||
|
||
AudioManager:playEffect(AudioManager.EFFECT_ID.LINK_OVER)
|
||
|
||
local tutorialElementList
|
||
if DataManager.TutorialData:getIsInTutorial() then
|
||
tutorialElementList = DataManager.TutorialData:getTargetElement()
|
||
end
|
||
|
||
self.battleUI:showBoardMask(nil)
|
||
local sequence = self.battleData:getGridSequence()
|
||
local count = #sequence
|
||
if count < self:getMinEliminationCount() then
|
||
self:clearGridSequence()
|
||
|
||
if tutorialElementList then
|
||
self.battleUI:showTutorialFinger(tutorialElementList)
|
||
end
|
||
return
|
||
end
|
||
|
||
if tutorialElementList then
|
||
local posIdmap = {}
|
||
for _, info in ipairs(sequence) do
|
||
posIdmap[info.posId] = true
|
||
end
|
||
EventManager:dispatchEvent(EventManager.CUSTOM_EVENT.ELIMINATION_OVER, posIdmap)
|
||
else
|
||
self:onLinkOver()
|
||
end
|
||
end
|
||
|
||
function BattleController:clearGridSequence()
|
||
local sequence = self.battleData:getGridSequence()
|
||
local count = #sequence
|
||
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
|
||
self.battleData:setInfoBySnapshop(posId, info)
|
||
end
|
||
end
|
||
|
||
self.battleData:clearGridSequence()
|
||
self:onLinkChange()
|
||
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
|
||
if skillId then
|
||
skillEntity = self.battleData:getSkillEntityBySkillId(skillId)
|
||
self:addTaskProgress(BattleConst.BATTLE_TASK_FIELD.BOARD_SKILL_RELEASE_COUNT, 1)
|
||
end
|
||
|
||
local aniSequence, influenceElementTypeMap, lineCount, elementTypeMap, linkElementType, effectGridMap = self:calculateCurElimination()
|
||
|
||
if not self.atkTeam:getMainUnit().unitEntity:getActiveSkillLimit() then
|
||
self.battleData:addSkillEnergy(elementTypeMap)
|
||
end
|
||
self.battleData:clearGridSequence()
|
||
self.battleUI:disableUITouch()
|
||
self.battleUI:eliminationAni(aniSequence, effectGridMap, function()
|
||
self:enterRefreshBoard(nil, function()
|
||
self:generateInstructions(skillEntity, linkElementType, lineCount, influenceElementTypeMap, elementTypeMap)
|
||
end)
|
||
end)
|
||
|
||
self.eliminateCount = self.eliminateCount + 1
|
||
self.eliminateTotalCount = self.eliminateTotalCount + 1
|
||
end
|
||
|
||
function BattleController:calculateCurElimination(onlyCheck)
|
||
local sequence = self.battleData:getGridSequence()
|
||
local skillId = self.battleData:getSequenceHadSkill()
|
||
local skillEntity
|
||
if skillId then
|
||
skillEntity = self.battleData:getSkillEntityBySkillId(skillId)
|
||
end
|
||
self.breakedMap = table.clearOrCreate(self.breakedMap)
|
||
self.boomGridIds = table.clearOrCreate(self.boomGridIds)
|
||
self.sequenceMap = table.clearOrCreate(self.sequenceMap)
|
||
self.aniSequence = table.clearOrCreate(self.aniSequence)
|
||
for idx, info in ipairs(sequence) do
|
||
self.sequenceMap[info.posId] = idx
|
||
end
|
||
|
||
local time = 0
|
||
local skillTime = BattleConst.SKILL_ELIMINATION_TIME
|
||
for idx, info in ipairs(sequence) do
|
||
local posId = info.posId
|
||
self:dealGridBreak(posId, GRID_BREAK_CONDITION.LINE, time, self.breakedMap, self.sequenceMap, self.aniSequence, self.boomGridIds, onlyCheck)
|
||
time = time + BattleConst.ELIMINATION_INTERVAL
|
||
end
|
||
|
||
local randomPosList, influenceElementTypeMap
|
||
for i, info in ipairs(self.aniSequence) do
|
||
if info.isSkill then
|
||
randomPosList, influenceElementTypeMap = self:dealSkillElement(info.timeIdx + skillTime, self.breakedMap, self.sequenceMap, self.aniSequence, self.boomGridIds, onlyCheck)
|
||
local aniUnit = self.aniSequence[i]
|
||
if not BattleConst.NO_EFFECT_GRID_SKILL_TYPE[skillEntity:getSkillType()] then
|
||
aniUnit.rangeList = skillEntity:getBoardRange()
|
||
aniUnit.randomPosList = randomPosList
|
||
end
|
||
break
|
||
end
|
||
end
|
||
|
||
self.elementTypeMap = table.clearOrCreate(self.elementTypeMap)
|
||
self.effectGridMap = table.clearOrCreate(self.effectGridMap)
|
||
local linkElementType
|
||
local lineCount = 0
|
||
local gridEntities = self.battleData:getGridEnties()
|
||
for _, info in ipairs(self.aniSequence) do
|
||
local entity = gridEntities[info.posId]
|
||
local elementType = entity:getElementType()
|
||
if not info.noAni and info.isIdle then
|
||
if not info.isSkill then
|
||
if not entity:isElmentTypeInvalid() then
|
||
self.elementTypeMap[elementType] = (self.elementTypeMap[elementType] or 0) + 1
|
||
end
|
||
if self.boomGridIds[info.posId] and self.boomGridIds[info.posId][GRID_BREAK_CONDITION.LINE] then
|
||
lineCount = lineCount + 1
|
||
linkElementType = elementType
|
||
end
|
||
end
|
||
end
|
||
if entity:getEffectType() and info.isIdle then
|
||
self.effectGridMap[info.posId] = true
|
||
end
|
||
end
|
||
|
||
return self.aniSequence, influenceElementTypeMap, lineCount, self.elementTypeMap, linkElementType, self.effectGridMap
|
||
end
|
||
|
||
function BattleController:dealGridBreak(posId, condition, time, breakedMap, sequenceMap, aniSequence, gridMap, onlyCheck)
|
||
self:setGridBreakCondition(gridMap, posId, condition)
|
||
if breakedMap[posId] or (sequenceMap[posId] and condition ~= GRID_BREAK_CONDITION.LINE) then
|
||
return
|
||
end
|
||
|
||
local gridEntities = self.battleData:getGridEnties()
|
||
local entity = gridEntities[posId]
|
||
local breaked, isIdle = entity:tryBreakGrid(condition, true)
|
||
local aniUnit = self:getEliminattionAniInfo(posId, time)
|
||
aniUnit.noAni = entity:isElmentTypeInvalid()
|
||
aniUnit.isIdle = isIdle
|
||
if entity:getSkillId() then
|
||
aniUnit.isSkill = true
|
||
end
|
||
|
||
if breaked then
|
||
breakedMap[posId] = true
|
||
|
||
aniUnit.breakSfxName = entity:getBreakSfx()
|
||
aniUnit.callback = function()
|
||
entity:tryBreakGrid(condition)
|
||
end
|
||
|
||
table.insert(aniSequence, aniUnit)
|
||
else
|
||
if entity:canBreakByThisCondition(condition) then
|
||
breakedMap[posId] = true
|
||
aniUnit.callback = function()
|
||
entity:tryBreakGrid(condition)
|
||
end
|
||
table.insert(aniSequence, aniUnit)
|
||
end
|
||
end
|
||
|
||
if isIdle then
|
||
if condition == GRID_BREAK_CONDITION.LINE then
|
||
local outline = BattleConst.UP_DOWN_LEFT_RIGHT[posId]
|
||
for _, id in ipairs(outline) do
|
||
self:dealGridBreak(id, GRID_BREAK_CONDITION.AROUND, time, breakedMap, sequenceMap, aniSequence, gridMap, onlyCheck)
|
||
end
|
||
end
|
||
if entity:getEffectType() then
|
||
local succ, list = BATTLE_GRID_EFFECT_HANDLE.gridEffectOn(posId, gridEntities, BattleConst.GRID_EFFECT_TRIGGER_TYPE.ON_GRID_BREAK, self, onlyCheck)
|
||
if list then
|
||
aniUnit.aniPosList = table.clearOrCreate(aniUnit.aniPosList)
|
||
aniUnit.overCallback = aniUnit.callback
|
||
aniUnit.callback = nil
|
||
for index, id in ipairs(list) do
|
||
if id ~= posId then
|
||
self:dealGridBreak(id, GRID_BREAK_CONDITION.SKILL, time + BattleConst.GRID_BREAK_EFFECT_INTERVAL * index, breakedMap, sequenceMap, aniSequence, gridMap, onlyCheck)
|
||
table.insert(aniUnit.aniPosList, id)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
if entity:getBreakFlyToCharacter() then
|
||
aniUnit.breakFlyToCharacter = true
|
||
aniUnit.noAni = false
|
||
aniUnit.overCallback = aniUnit.callback
|
||
aniUnit.callback = nil
|
||
if entity:getBreakFlyToCharacterIcon() then
|
||
aniUnit.callback = function()
|
||
local cell = entity:getCell()
|
||
if not cell then
|
||
return
|
||
end
|
||
cell:setGridTypeIcon(entity:getBreakFlyToCharacterIcon())
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
return isIdle
|
||
end
|
||
|
||
function BattleController:dealSkillElement(time, breakedMap, sequenceMap, aniSequence, boomGridIds, onlyCheck)
|
||
local randomPosList
|
||
local influenceElementTypeMap = {}
|
||
for posId, info in pairs(self.battleData:getSkillInfluenceGrids()) do
|
||
local entity = self.battleData:getGridEntity(posId)
|
||
if not entity:getIsIdle() then
|
||
if entity:isEmptyIdle() then
|
||
if info.direction == BattleConst.BOARD_RANGE_TYPE.RANDOM then
|
||
if not randomPosList then
|
||
randomPosList = {}
|
||
end
|
||
table.insert(randomPosList, posId)
|
||
end
|
||
influenceElementTypeMap[entity:getElementType()] = (influenceElementTypeMap[entity:getElementType()] or 0) + 1
|
||
end
|
||
self:dealGridBreak(posId, GRID_BREAK_CONDITION.SKILL, time, breakedMap, sequenceMap, aniSequence, boomGridIds, onlyCheck)
|
||
end
|
||
end
|
||
|
||
return randomPosList, influenceElementTypeMap
|
||
end
|
||
|
||
function BattleController:getEliminattionAniInfo(posId, timeIdx)
|
||
return {
|
||
posId = posId,
|
||
noAni = nil,
|
||
aniPosList = nil,
|
||
breakSfxName = nil,
|
||
timeIdx = timeIdx,
|
||
conditions = nil,
|
||
isSkill = false,
|
||
isIdle = false,
|
||
callback = nil,
|
||
overCallback = nil,
|
||
}
|
||
end
|
||
|
||
function BattleController:setGridBreakCondition(gridMap, posId, condition)
|
||
if not gridMap[posId] then
|
||
gridMap[posId] = {}
|
||
gridMap[posId][condition] = true
|
||
end
|
||
gridMap[posId][condition] = true
|
||
end
|
||
|
||
function BattleController:tryShowSelectSkillComp(needDelay, onlyCommonSkill)
|
||
local skillList = self:getRandomSkillList(nil, onlyCommonSkill)
|
||
if needDelay then
|
||
self.showSelectSkillSid = ModuleManager.BattleManager:performWithDelayGlobal(function()
|
||
self.battleUI:showSelectSkillComp(skillList, onlyCommonSkill)
|
||
self.showSelectSkillSid = nil
|
||
end, 0.3)
|
||
else
|
||
self.battleUI:showSelectSkillComp(skillList, onlyCommonSkill)
|
||
end
|
||
|
||
local totalTime = Time:getServerTime() - self.battleStartTime
|
||
BIReport:postShowFightSkillSelect(self.battleType, skillList, self.chapterId, totalTime, self.waveIndex)
|
||
end
|
||
|
||
function BattleController:fillBoard(isRoundBeginCheck)
|
||
self.fillBoardPathMap = table.clearOrCreate(self.fillBoardPathMap)
|
||
self.fillColumnCount = table.clearOrCreate(self.fillColumnCount)
|
||
self.fillGridMap = table.clearOrCreate(self.fillGridMap)
|
||
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, self.fillColumnCount, self.fillGridMap)
|
||
end
|
||
end
|
||
end
|
||
|
||
while true do
|
||
local find = false
|
||
for c = 1, BattleConst.COLUMN_COUNT do
|
||
local list = self.fillGridMap[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
|
||
self.fillBoardPathMap[posId] = entity:getPath()
|
||
entity:clearPath()
|
||
end
|
||
end
|
||
end
|
||
|
||
self.battleUI:fallGrid(self.fillBoardPathMap, isRoundBeginCheck, function()
|
||
self:onFillBoardOver(isRoundBeginCheck)
|
||
end)
|
||
end
|
||
|
||
function BattleController:onFillBoardOver(isRoundBeginCheck)
|
||
self.battleUI:enableUITouch()
|
||
|
||
if not isRoundBeginCheck then -- 检查一些表现
|
||
if self.showMysteryBoxIndexs[1] then -- 检查宝箱
|
||
local index = table.remove(self.showMysteryBoxIndexs, 1)
|
||
local boardList, _, mysteryBoxIndexMap = self:getInitBoard()
|
||
local rewards = mysteryBoxIndexMap[index]
|
||
ModuleManager.BattleManager:showBoxOpenUI(rewards, function()
|
||
self:onFillBoardOver()
|
||
end)
|
||
return
|
||
end
|
||
|
||
if self.battleData:useCommonSelectSkillCount() then -- 检查神灯
|
||
self:tryShowSelectSkillComp(false, true)
|
||
return
|
||
end
|
||
end
|
||
|
||
if self.onFillBoardOverCallback then
|
||
self.onFillBoardOverCallback()
|
||
end
|
||
|
||
if isRoundBeginCheck then
|
||
EventManager:dispatchEvent(EventManager.CUSTOM_EVENT.BOARD_FILL_OVER)
|
||
self:popBoardCacheSkill(function()
|
||
self:generateSkill(function()
|
||
self:enterElimination(true)
|
||
end)
|
||
end)
|
||
else
|
||
self:generateSkill(function()
|
||
self.battleUI:refreshSkill()
|
||
self:enterBattleStep()
|
||
end)
|
||
end
|
||
end
|
||
|
||
function BattleController:generateInstructions(skillEntity, elementType, lineCount, influenceElementTypeMap, elementTypeMap)
|
||
self.instructions = BATTLE_INSTRUCTIONS_HELPER.generateInstructions(skillEntity, elementType, lineCount, influenceElementTypeMap, elementTypeMap, self)
|
||
end
|
||
|
||
function BattleController:exeInstructions(callback)
|
||
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:getIsLastInstruction()
|
||
if not self.instructions or not self.instructions[1] then
|
||
return true
|
||
end
|
||
|
||
return false
|
||
end
|
||
|
||
function BattleController:generateBoard(isFirst)
|
||
local boardList, _, mysteryBoxIndexMap = 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
|
||
if not boardList[self.curBoardIndex] then -- 容错
|
||
return
|
||
end
|
||
local board = boardList[self.curBoardIndex].board
|
||
local mysteryBoard = boardList[self.curBoardIndex].mysteryBoard
|
||
if mysteryBoard and mysteryBoxIndexMap and mysteryBoxIndexMap[self.curBoardIndex] then
|
||
board = mysteryBoard
|
||
end
|
||
self.battleUI:switchBoard(function()
|
||
self.battleData:refreshBoard(board, self:getBlockIcon())
|
||
self.battleUI:initGridCell()
|
||
end, function()
|
||
-- self:enterRoundBegin()
|
||
end, isFirst)
|
||
end
|
||
|
||
function BattleController:onGotMysteryBoxIndexs()
|
||
self.gotMysteryBoxIndexs[self.curBoardIndex] = true
|
||
table.insert(self.showMysteryBoxIndexs, self.curBoardIndex)
|
||
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
|
||
self.popSkillPosIdList = table.clearOrCreate(self.popSkillPosIdList)
|
||
for posId, entity in pairs(self.battleData:getGridEnties()) do
|
||
if entity:isEmptyIdle() and not entity:getIsIdle() then
|
||
table.insert(self.popSkillPosIdList, posId)
|
||
end
|
||
end
|
||
|
||
self.popSkillPosIdList = table.shuffle(self.popSkillPosIdList)
|
||
self.popNewSkillId = table.clearOrCreate(self.popNewSkillId)
|
||
for index, info in ipairs(skillList) do
|
||
if self.popSkillPosIdList[1] then
|
||
self.popNewSkillId[index] = info
|
||
self.popNewSkillId[index].posId = table.remove(self.popSkillPosIdList)
|
||
else
|
||
break
|
||
end
|
||
end
|
||
self.battleUI:cacheSkillAni(self.popNewSkillId, true, callback)
|
||
else
|
||
if callback then
|
||
callback()
|
||
end
|
||
end
|
||
end
|
||
|
||
function BattleController:generateSkill(callback)
|
||
self.generateSkillMap = table.clearOrCreate(self.generateSkillMap)
|
||
self.generateExcludeMap = table.clearOrCreate(self.generateExcludeMap)
|
||
for _, skillEntity in pairs(self.battleData:getSkillEntities()) do
|
||
if skillEntity:getEnergyEnough() then
|
||
local list = self:getSkillElementList(skillEntity:getPosition(), 1, true, self.generateExcludeMap)
|
||
if list[1] then
|
||
self.generateSkillMap[skillEntity:getPosition()] =
|
||
{
|
||
skillId = skillEntity:getSkillId(),
|
||
posId = list[1]
|
||
}
|
||
self.generateExcludeMap[list[1]] = true
|
||
end
|
||
end
|
||
end
|
||
|
||
if not self.battleUI then
|
||
if callback then
|
||
callback()
|
||
end
|
||
return
|
||
end
|
||
|
||
self.battleUI:generateSkillAni(self.generateSkillMap, function()
|
||
for elementType, info in pairs(self.generateSkillMap) 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(skillTypeParameter, monsterPos)
|
||
if not skillTypeParameter then
|
||
return
|
||
end
|
||
|
||
self.generateGridTypeList = table.clearOrCreate(self.generateGridTypeList)
|
||
local count = 0
|
||
for posId, entity in pairs(self.battleData:getGridEnties()) do
|
||
if entity:isEmptyIdle() then
|
||
table.insert(self.generateGridTypeList, entity)
|
||
count = count + 1
|
||
end
|
||
end
|
||
self.generateGridTypeList = table.shuffle(self.generateGridTypeList)
|
||
if count > 0 then
|
||
self.generateGridTypeMap = table.clearOrCreate(self.generateGridTypeMap)
|
||
local minCount = math.min(skillTypeParameter[2], count)
|
||
for i = minCount, 1, -1 do
|
||
local entity = table.remove(self.generateGridTypeList, math.random(1, i))
|
||
self.generateGridTypeMap[entity:getPosId()] = {
|
||
gridType = skillTypeParameter[1],
|
||
elementType = entity:getElementType()
|
||
}
|
||
end
|
||
|
||
self.battleUI:showMonsterSkillAni(self.generateGridTypeMap, monsterPos, function()
|
||
for posId, info in pairs(self.generateGridTypeMap) do
|
||
self.battleData:setGridInfo(posId, info)
|
||
end
|
||
end)
|
||
end
|
||
end
|
||
|
||
function BattleController:lockElement(lcokElementType, isUnlock)
|
||
if not self.lockElementElementTypeMap then
|
||
self.lockElementElementTypeMap = table.clearOrCreate(self.lockElementElementTypeMap)
|
||
else
|
||
for k, v in pairs(self.lockElementElementTypeMap) do
|
||
self.lockElementElementTypeMap[k] = table.clearOrCreate(self.lockElementElementTypeMap[k])
|
||
end
|
||
end
|
||
if not self.lockElementMap then
|
||
self.lockElementMap = table.clearOrCreate(self.lockElementMap)
|
||
else
|
||
for k, v in pairs(self.lockElementMap) do
|
||
self.lockElementMap[k] = table.clearOrCreate(self.lockElementMap[k])
|
||
end
|
||
end
|
||
self.lockElementList = table.clearOrCreate(self.lockElementList)
|
||
local locked = false
|
||
for posId, entity in pairs(self.battleData:getGridEnties()) do
|
||
local elementType = entity:getElementType()
|
||
if not isUnlock then
|
||
if entity:isEmptyIdle() then
|
||
local elementTypeMapUnit = self.lockElementElementTypeMap[elementType]
|
||
if not elementTypeMapUnit or not elementTypeMapUnit[1] then
|
||
self.lockElementElementTypeMap[elementType] = table.clearOrCreate(self.lockElementElementTypeMap[elementType])
|
||
elementTypeMapUnit = self.lockElementElementTypeMap[elementType]
|
||
if not isUnlock then
|
||
table.insert(self.lockElementList, elementType)
|
||
end
|
||
end
|
||
|
||
table.insert(elementTypeMapUnit, posId)
|
||
end
|
||
if entity:isLock() then
|
||
locked = true
|
||
end
|
||
else
|
||
if entity:isLock() then
|
||
if not self.lockElementMap[elementType] then
|
||
self.lockElementMap[elementType] = table.clearOrCreate(self.lockElementMap[elementType])
|
||
end
|
||
table.insert(self.lockElementMap[elementType], posId)
|
||
end
|
||
end
|
||
end
|
||
|
||
if isUnlock then
|
||
for elementType, list in pairs(self.lockElementMap) do
|
||
self.battleData:cacheLockElement(elementType, nil)
|
||
for _, posId in ipairs(list) do
|
||
self.battleData:setGridType(posId, BattleConst.GRID_TYPE.EMPTY)
|
||
end
|
||
end
|
||
else
|
||
if locked then -- 锁定过就不新锁了
|
||
return
|
||
end
|
||
local elementType = lcokElementType
|
||
if elementType == BattleConst.ELEMENT_TYPE.NONE then
|
||
if not self.lockElementList[1] then
|
||
return
|
||
end
|
||
elementType = self.lockElementList[math.random(1, #self.lockElementList)]
|
||
end
|
||
self.battleData:cacheLockElement(elementType, true)
|
||
local list = self.lockElementElementTypeMap[elementType]
|
||
if list then
|
||
for _, posId in ipairs(list) do
|
||
self.battleData:setGridType(posId, BattleConst.GRID_TYPE.LOCK)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
function BattleController:getSkillElementList(elementType, count, useAlternate, excludeMap)
|
||
self.getSkillElementListResult = table.clearOrCreate(self.getSkillElementListResult)
|
||
local gridEntities = self.battleData:getGridEnties()
|
||
if not gridEntities then
|
||
return self.getSkillElementListResult
|
||
end
|
||
|
||
self.getSkillElementListSameElementList = table.clearOrCreate(self.getSkillElementListSameElementList)
|
||
self.getSkillElementListAlternateList = table.clearOrCreate(self.getSkillElementListAlternateList)
|
||
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(self.getSkillElementListSameElementList, posId)
|
||
else
|
||
table.insert(self.getSkillElementListAlternateList, posId)
|
||
end
|
||
end
|
||
end
|
||
|
||
local remainCount = count - addCount
|
||
if remainCount <= 0 then
|
||
return self.getSkillElementListResult
|
||
end
|
||
|
||
for i = 1, remainCount do
|
||
if not self.getSkillElementListSameElementList[i] then
|
||
break
|
||
end
|
||
table.insert(self.getSkillElementListResult, table.remove(self.getSkillElementListSameElementList, math.random(1, #self.getSkillElementListSameElementList)))
|
||
addCount = addCount + 1
|
||
if addCount >= count then
|
||
return self.getSkillElementListResult
|
||
end
|
||
end
|
||
|
||
if addCount < count and useAlternate then
|
||
for i = 1, count - addCount do
|
||
if not self.getSkillElementListAlternateList[1] then
|
||
break
|
||
end
|
||
table.insert(self.getSkillElementListResult, table.remove(self.getSkillElementListAlternateList, math.random(1, #self.getSkillElementListAlternateList)))
|
||
addCount = addCount + 1
|
||
if addCount >= count then
|
||
return self.getSkillElementListResult
|
||
end
|
||
end
|
||
end
|
||
|
||
if addCount >= count then
|
||
return self.getSkillElementListResult
|
||
end
|
||
end
|
||
|
||
return self.getSkillElementListResult
|
||
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()
|
||
self.getRandomGridInfoIndexs = table.clearOrCreate(self.getRandomGridInfoIndexs)
|
||
self.getRandomGridInfoTypeList = table.clearOrCreate(self.getRandomGridInfoTypeList)
|
||
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(self.getRandomGridInfoIndexs, weight)
|
||
table.insert(self.getRandomGridInfoTypeList, typeNum)
|
||
end
|
||
end
|
||
|
||
local index = GFunc.getRandomIndex(self.getRandomGridInfoIndexs)
|
||
elementType = self.getRandomGridInfoTypeList[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()
|
||
self.skillInfluenceGridsSequenceEntities = table.clearOrCreate(self.skillInfluenceGridsSequenceEntities)
|
||
for _, info in ipairs(sequence) do
|
||
local entity = self.battleData:getGridEntity(info.posId)
|
||
table.insert(self.skillInfluenceGridsSequenceEntities, 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(), self.skillInfluenceGridsSequenceEntities, self)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
function BattleController:getRandomSkillList(getCount, onlyCommonSkill, excludeMap)
|
||
local fixedList = self:getFixedRogueSkill()
|
||
if fixedList[1] then
|
||
return table.remove(fixedList, 1)
|
||
end
|
||
|
||
getCount = getCount or BattleConst.SKILL_SELECT_COUNT
|
||
self.randomSkillList = table.clearOrCreate(self.randomSkillList)
|
||
self.randomSkillMap = table.clearOrCreate(self.randomSkillMap)
|
||
self.randomSkillNewSkillPool = table.clearOrCreate(self.randomSkillNewSkillPool)
|
||
self.randomSkillSkillWeight = table.clearOrCreate(self.randomSkillSkillWeight)
|
||
local cfg = ConfigManager:getConfig("skill_rogue")
|
||
local skillPool = self.battleData:getSkillPool()
|
||
local count = 0
|
||
|
||
if not onlyCommonSkill then
|
||
for elementType, list in pairs(skillPool) do -- 先遍历一下未解锁的技能
|
||
if not self.battleData:isUnlockedSkillElementType(elementType) then
|
||
local skillEntity = self.battleData:getSkillEntityByElement(elementType)
|
||
if skillEntity then
|
||
local skillId = skillEntity:getUnlockId()
|
||
if skillId and not self.randomSkillMap[skillId] then
|
||
local skillCfg = cfg[skillId]
|
||
table.insert(self.randomSkillNewSkillPool, skillId)
|
||
table.insert(self.randomSkillSkillWeight, skillCfg.weight)
|
||
count = count + 1
|
||
self.randomSkillMap[skillId] = true
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
if count >= 3 then -- 如果未解锁的技能大于等于3,则直接返回三个解锁技能
|
||
for i = 1, 3 do
|
||
local index = GFunc.getRandomIndex(self.randomSkillSkillWeight)
|
||
local skillId = table.remove(self.randomSkillNewSkillPool, index)
|
||
table.remove(self.randomSkillSkillWeight, index)
|
||
count = count - 1
|
||
table.insert(self.randomSkillList, skillId)
|
||
end
|
||
|
||
return table.shuffle(self.randomSkillList)
|
||
end
|
||
|
||
if excludeMap then
|
||
for skillId, _ in pairs(excludeMap) do
|
||
self.randomSkillMap[skillId] = true
|
||
end
|
||
end
|
||
|
||
for elementType, list in pairs(skillPool) do
|
||
if self.battleData:isUnlockedSkillElementType(elementType) then
|
||
for _, skillId in ipairs(list) do
|
||
local skillCfg = cfg[skillId]
|
||
if skillCfg and (not skillCfg.limit_times or self.battleData:getSkillCount(skillId) < skillCfg.limit_times) then
|
||
|
||
if not self.randomSkillMap[skillId] and (not skillCfg.unlock or self.battleData:getSkillCount(skillCfg.unlock) > 0) then
|
||
table.insert(self.randomSkillNewSkillPool, skillId)
|
||
table.insert(self.randomSkillSkillWeight, skillCfg.weight)
|
||
count = count + 1
|
||
self.randomSkillMap[skillId] = true
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
if count > 0 then
|
||
local index = GFunc.getRandomIndex(self.randomSkillSkillWeight)
|
||
local skillId = table.remove(self.randomSkillNewSkillPool, index)
|
||
table.remove(self.randomSkillSkillWeight, index)
|
||
count = count - 1
|
||
table.insert(self.randomSkillList, skillId)
|
||
getCount = getCount - 1
|
||
end
|
||
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 self.randomSkillMap[skillId] then
|
||
table.insert(self.randomSkillNewSkillPool, skillId)
|
||
table.insert(self.randomSkillSkillWeight, info.weight)
|
||
count = count + 1
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
for i = 1, getCount do
|
||
local index = GFunc.getRandomIndex(self.randomSkillSkillWeight)
|
||
local skillId = table.remove(self.randomSkillNewSkillPool, index)
|
||
table.remove(self.randomSkillSkillWeight, index)
|
||
count = count - 1
|
||
table.insert(self.randomSkillList, skillId)
|
||
if count <= 0 then
|
||
break
|
||
end
|
||
end
|
||
|
||
local result = table.shuffle(self.randomSkillList)
|
||
return result
|
||
end
|
||
|
||
function BattleController:onSelectSkill(skillId, value, pos)
|
||
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
|
||
|
||
local totalTime = Time:getServerTime() - self.battleStartTime
|
||
BIReport:postFightSkillSelect(self.battleType, {skillId}, self.chapterId, totalTime, self.waveIndex)
|
||
|
||
local elementType = ModuleManager.HeroManager:getSkillRoguePosition(skillId)
|
||
|
||
if elementType then
|
||
if self.battleUI then
|
||
self.battleUI:gotOneSkillAni(skillId, elementType, function()
|
||
self:selectSKillNextToStep()
|
||
self.battleUI:refreshBoard()
|
||
self.battleUI:refreshSkill()
|
||
end, pos)
|
||
return
|
||
end
|
||
end
|
||
|
||
self:selectSKillNextToStep()
|
||
|
||
self.battleUI:showCommonSkillTips(skillId)
|
||
end
|
||
|
||
function BattleController:selectSKillNextToStep()
|
||
if self.roundStep == BattleConst.BATTLE_ROUND_STEP.ON_REFRESH_BOARD then
|
||
self:onFillBoardOver()
|
||
else
|
||
self:enterElimination()
|
||
end
|
||
end
|
||
|
||
function BattleController:changeElementType(count, elementType)
|
||
self.changeElementTypeMap = table.clearOrCreate(self.changeElementTypeMap)
|
||
for _, entity in pairs(self.battleData:getGridEnties()) do
|
||
if entity:canChangeInfo() and entity:getElementType() ~= elementType then
|
||
self.changeElementTypeMap[entity] = elementType
|
||
count = count - 1
|
||
if count <= 0 then
|
||
break
|
||
end
|
||
end
|
||
end
|
||
|
||
self:changeElementTypeByMap(self.changeElementTypeMap)
|
||
end
|
||
|
||
function BattleController:changeElementTypeByMap(changeMap)
|
||
local index = 1
|
||
for entity, elementType in pairs(changeMap) do
|
||
self.battleData:setGridInfo(entity:getPosId(), {gridType = entity:getGridType(), elementType = elementType})
|
||
self.battleUI:playChangeElementSfx(entity:getPosId(), index)
|
||
index = index + 1
|
||
end
|
||
end
|
||
|
||
function BattleController:killGrids(posIdList)
|
||
if not posIdList[1] then
|
||
return
|
||
end
|
||
|
||
for _, posId in ipairs(posIdList) do
|
||
local entity = DataManager.BattleData:getGridEntity(posId)
|
||
entity:setIsIdle(true)
|
||
end
|
||
|
||
self.battleUI:removeGridOutOfScreen(posIdList)
|
||
end
|
||
|
||
function BattleController:killRowOrColumn(infoList)
|
||
self.killRowOrColumnMap = table.clearOrCreate(self.killRowOrColumnMap)
|
||
for _, info in ipairs(infoList) do
|
||
if info.posList then
|
||
for i, posId in ipairs(info.posList) do
|
||
if not self.killRowOrColumnMap[posId] then
|
||
self.killRowOrColumnMap[posId] = true
|
||
local entity = DataManager.BattleData:getGridEntity(posId)
|
||
entity:setIsIdle(true)
|
||
end
|
||
end
|
||
self.battleUI:removeGridOutOfScreen(info.posList)
|
||
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(callback)
|
||
local changeInfo = self:getShuffleBoardInfo()
|
||
if changeInfo then
|
||
self.battleData:setGridEntitiesPosId(changeInfo)
|
||
self.battleUI:shuffleBoard(changeInfo, callback)
|
||
else
|
||
self.resetList = table.clearOrCreate(self.resetList)
|
||
for posId, entity in pairs(self.battleData:getGridEnties()) do
|
||
if entity:isCanFallStatus() then
|
||
table.insert(self.resetList, entity)
|
||
end
|
||
end
|
||
local resetInfo = self:resetGrids(self.resetList)
|
||
if not resetInfo then
|
||
if EDITOR_MODE then
|
||
Logger.logHighlight("----- 处于无法消除状态 -----")
|
||
end
|
||
if callback then
|
||
callback()
|
||
end
|
||
else
|
||
if self.resetGridSid then
|
||
ModuleManager.BattleManager:unscheduleGlobal(self.resetGridSid)
|
||
self.resetGridSid = nil
|
||
end
|
||
|
||
self.resetGridSid = ModuleManager.BattleManager:performWithDelayGlobal(function()
|
||
local count = 1
|
||
for posId, info in pairs(resetInfo) do
|
||
self.battleData:setInfoBySnapshop(posId, info)
|
||
self.battleUI:playChangeElementSfx(posId, count)
|
||
count = count + 1
|
||
end
|
||
self.resetGridSid = nil
|
||
if callback then
|
||
callback()
|
||
end
|
||
end, 0.5)
|
||
end
|
||
end
|
||
end
|
||
|
||
function BattleController:getShuffleBoardInfo()
|
||
self.shuffleBoardPosList = table.clearOrCreate(self.shuffleBoardPosList)
|
||
self.shuffleBoardAnySkillList = table.clearOrCreate(self.shuffleBoardAnySkillList)
|
||
self.shuffleBoardPosMap = table.clearOrCreate(self.shuffleBoardPosMap)
|
||
self.shuffleBoardCountMap = table.clearOrCreate(self.shuffleBoardCountMap)
|
||
self.shuffleBoardCantLinkMap = table.clearOrCreate(self.shuffleBoardCantLinkMap)
|
||
if not self.shuffleBoardList then
|
||
self.shuffleBoardList = table.clearOrCreate(self.shuffleBoardList)
|
||
else
|
||
for elementType, _ in pairs(self.shuffleBoardList) do
|
||
self.shuffleBoardList[elementType] = table.clearOrCreate(self.shuffleBoardList[elementType])
|
||
end
|
||
end
|
||
local anySkillCount = 0
|
||
for posId, entity in pairs(self.battleData:getGridEnties()) do
|
||
if entity:isCanFallStatus() then
|
||
if entity:getSkillId() then
|
||
local skillEntity = self.battleData:getSkillEntityBySkillId(entity:getSkillId())
|
||
local elementType = skillEntity:getPosition()
|
||
if skillEntity:getIgnoreElementType() then
|
||
table.insert(self.shuffleBoardAnySkillList, entity)
|
||
anySkillCount = anySkillCount + 1
|
||
else
|
||
if not self.shuffleBoardList[elementType] then
|
||
self.shuffleBoardList[elementType] = table.clearOrCreate(self.shuffleBoardList[elementType])
|
||
end
|
||
table.insert(self.shuffleBoardList[elementType], entity)
|
||
self.shuffleBoardCountMap[elementType] = (self.shuffleBoardCountMap[elementType] or 0) + 1
|
||
end
|
||
else
|
||
local elementType = entity:getElementType()
|
||
if not self.shuffleBoardList[elementType] then
|
||
self.shuffleBoardList[elementType] = table.clearOrCreate(self.shuffleBoardList[elementType])
|
||
end
|
||
table.insert(self.shuffleBoardList[elementType], entity)
|
||
self.shuffleBoardCountMap[elementType] = (self.shuffleBoardCountMap[elementType] or 0) + 1
|
||
if not entity:canLink() then
|
||
self.shuffleBoardCantLinkMap[elementType] = (self.shuffleBoardCantLinkMap[elementType] or 0) + 1
|
||
end
|
||
end
|
||
table.insert(self.shuffleBoardPosList, posId)
|
||
self.shuffleBoardPosMap[posId] = true
|
||
end
|
||
end
|
||
|
||
for elementType, list in pairs(self.shuffleBoardList) do
|
||
table.sort(self.shuffleBoardList[elementType], function(a, b)
|
||
if a:getSkillId() and not b:getSkillId() then
|
||
return false
|
||
elseif not a:getSkillId() and b:getSkillId() then
|
||
return true
|
||
else
|
||
return a:getPosId() < b:getPosId()
|
||
end
|
||
end)
|
||
end
|
||
|
||
|
||
local needCount = self:getMinEliminationCount()
|
||
local find = false
|
||
for elementType, list in pairs(self.shuffleBoardList) do
|
||
local count = self.shuffleBoardCountMap[elementType] or 0
|
||
local cantLinkCount = self.shuffleBoardCantLinkMap[elementType] or 0
|
||
local skillCount = 0
|
||
if anySkillCount > 0 then
|
||
skillCount = 1
|
||
end
|
||
if count + skillCount - cantLinkCount >= needCount then
|
||
local haveSkill = false
|
||
local listCount = 0
|
||
self.shuffleBoardTempList = table.clearOrCreate(self.shuffleBoardTempList)
|
||
find = false
|
||
local add = false
|
||
for _, entity in ipairs(list) do
|
||
add = false
|
||
if haveSkill then
|
||
if not entity:getSkillId() then
|
||
add = entity:canLink()
|
||
end
|
||
else
|
||
if entity:getSkillId() then
|
||
haveSkill = true
|
||
end
|
||
add = entity:canLink()
|
||
end
|
||
if add then
|
||
table.insert(self.shuffleBoardTempList, entity)
|
||
listCount = listCount + 1
|
||
|
||
if listCount >= needCount then -- 可连接的 普通的元素+元素技能
|
||
find = true
|
||
break
|
||
end
|
||
end
|
||
end
|
||
|
||
if listCount >= needCount then -- 可连接的 普通的元素+元素技能
|
||
find = true
|
||
break
|
||
elseif not haveSkill and skillCount > 0 then -- 可连接的 普通元素 + 任意元素技能
|
||
table.insert(self.shuffleBoardTempList, self.shuffleBoardAnySkillList[1])
|
||
listCount = listCount + 1
|
||
if listCount >= needCount then
|
||
find = true
|
||
break
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
if find then
|
||
return self:shufflePos(self.shuffleBoardTempList, self.shuffleBoardPosMap, needCount, self.shuffleBoardPosList)
|
||
end
|
||
end
|
||
|
||
function BattleController:shufflePos(tempList, posMap, needCount, posList)
|
||
local gotPos, useMap, list = self:findCanLinkPosList(posMap, needCount)
|
||
|
||
if gotPos and list[1] then
|
||
self.shufflePosInfo = table.clearOrCreate(self.shufflePosInfo)
|
||
self.shufflerPosUsedPos = table.clearOrCreate(self.shufflerPosUsedPos)
|
||
self.shufflerSetedPos = table.clearOrCreate(self.shufflerSetedPos)
|
||
for index, entity in ipairs(tempList) do
|
||
self.shufflePosInfo[entity:getPosId()] = list[index]
|
||
self.shufflerPosUsedPos[list[index]] = true
|
||
self.shufflerSetedPos[entity:getPosId()] = true
|
||
end
|
||
|
||
self.shufflePosList1 = table.clearOrCreate(self.shufflePosList1)
|
||
self.shufflePosList2 = table.clearOrCreate(self.shufflePosList2)
|
||
for index = #posList, 1, -1 do
|
||
local posId = posList[index]
|
||
if not self.shufflerPosUsedPos[posId] then
|
||
table.insert(self.shufflePosList2, posId)
|
||
end
|
||
if not self.shufflerSetedPos[posId] then
|
||
table.insert(self.shufflePosList1, posId)
|
||
end
|
||
end
|
||
|
||
self.shufflePosList2 = table.shuffle(self.shufflePosList2)
|
||
for index, posId in ipairs(self.shufflePosList1) do
|
||
if not self.shufflePosList2[index] then
|
||
break
|
||
end
|
||
self.shufflePosInfo[posId] = self.shufflePosList2[index]
|
||
end
|
||
|
||
return self.shufflePosInfo
|
||
end
|
||
end
|
||
|
||
function BattleController:findAttention()
|
||
local find = false
|
||
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 mainElementType = gridEntity:getElementType()
|
||
if gridEntity:canChangeInfo() then
|
||
self.findAttentionPathList = table.clearOrCreate(self.findAttentionPathList)
|
||
self.findAttentionPosIdMap = table.clearOrCreate(self.findAttentionPosIdMap)
|
||
self:findLinkLine(posId, self.findAttentionPosIdMap, false, mainElementType, self.findAttentionPathList)
|
||
if table.nums(self.findAttentionPathList) >= self:getMinEliminationCount() then
|
||
find = true
|
||
break
|
||
end
|
||
end
|
||
end
|
||
if find then
|
||
break
|
||
end
|
||
end
|
||
|
||
return find, self.findAttentionPathList
|
||
end
|
||
|
||
function BattleController:_dealResetGridsDataFunc(posList)
|
||
self.dealResetFunc1PosMap = table.clearOrCreate(self.dealResetFunc1PosMap)
|
||
self.dealResetFunc1LockElementMap = table.clearOrCreate(self.dealResetFunc1LockElementMap)
|
||
self.dealResetFunc1KeepSnapList = table.clearOrCreate(self.dealResetFunc1KeepSnapList)
|
||
self.dealResetFunc1KeepSnapSkillList = table.clearOrCreate(self.dealResetFunc1KeepSnapSkillList)
|
||
self.dealResetFunc1EmptySnapList = table.clearOrCreate(self.dealResetFunc1EmptySnapList)
|
||
local emptyCount = 0
|
||
for _, entity in ipairs(posList) do
|
||
local posId = entity:getPosId()
|
||
self.dealResetFunc1PosMap[posId] = entity
|
||
if entity:isEmptyIdle() then
|
||
emptyCount = emptyCount + 1
|
||
table.insert(self.dealResetFunc1EmptySnapList, entity:getSnapshoptInfo())
|
||
elseif entity:isLock() and not entity:getSkillId() then
|
||
self.dealResetFunc1LockElementMap[entity:getElementType()] = true
|
||
emptyCount = emptyCount + 1
|
||
local snapInfo = entity:getSnapshoptInfo()
|
||
snapInfo.gridType = BattleConst.GRID_TYPE.EMPTY
|
||
table.insert(self.dealResetFunc1EmptySnapList, snapInfo)
|
||
else
|
||
if entity:getSkillId() then
|
||
table.insert(self.dealResetFunc1KeepSnapSkillList, entity:getSnapshoptInfo())
|
||
else
|
||
table.insert(self.dealResetFunc1KeepSnapList, entity:getSnapshoptInfo())
|
||
end
|
||
end
|
||
end
|
||
|
||
return self.dealResetFunc1PosMap, self.dealResetFunc1LockElementMap, emptyCount, self.dealResetFunc1KeepSnapList, self.dealResetFunc1KeepSnapSkillList, self.dealResetFunc1EmptySnapList
|
||
end
|
||
|
||
function BattleController:_dealResetGridsDataFunc2(useMap, emptySnapList, mainElement, backupSkill, keepSnapList, posMap, canRandomElmentList, elementCount, lockElementMap)
|
||
self.dealResetFunc2ResetPosInfo = table.clearOrCreate(self.dealResetFunc2ResetPosInfo)
|
||
for posId, _ in pairs(useMap) do
|
||
local snapInfo
|
||
if emptySnapList[1] then
|
||
snapInfo = table.remove(emptySnapList)
|
||
snapInfo.elementType = mainElement
|
||
snapInfo.posId = posId
|
||
snapInfo.gridType = BattleConst.GRID_TYPE.EMPTY
|
||
else
|
||
snapInfo = backupSkill
|
||
end
|
||
self.dealResetFunc2ResetPosInfo[posId] = snapInfo
|
||
end
|
||
|
||
for _, snap in ipairs(emptySnapList) do
|
||
table.insert(keepSnapList, snap)
|
||
end
|
||
|
||
keepSnapList = table.shuffle(keepSnapList)
|
||
|
||
for posId, entity in pairs(posMap) do
|
||
if not useMap[posId] then
|
||
local snapInfo
|
||
if keepSnapList[1] then
|
||
snapInfo = table.remove(keepSnapList)
|
||
snapInfo.posId = posId
|
||
if not snapInfo.skillId or snapInfo.skillId <= 0 then
|
||
if snapInfo.gridType == BattleConst.GRID_TYPE.EMPTY then
|
||
snapInfo.elementType = canRandomElmentList[math.random(1, elementCount)]
|
||
if lockElementMap[snapInfo.elementType] then
|
||
snapInfo.gridType = BattleConst.GRID_TYPE.LOCK
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
if snapInfo then
|
||
self.dealResetFunc2ResetPosInfo[posId] = snapInfo
|
||
end
|
||
end
|
||
end
|
||
|
||
return self.dealResetFunc2ResetPosInfo
|
||
end
|
||
|
||
function BattleController:resetGrids(posList)
|
||
local needCount = self:getMinEliminationCount()
|
||
if not posList[needCount] then
|
||
return
|
||
end
|
||
|
||
local posMap, lockElementMap, emptyCount, keepSnapList, keepSnapSkillList, emptySnapList = self:_dealResetGridsDataFunc(posList)
|
||
|
||
local canUseSkillCount = 0
|
||
if keepSnapSkillList[1] then -- 技能可以直接链接, 不判断元素技能了
|
||
canUseSkillCount = 1
|
||
end
|
||
|
||
if emptyCount + canUseSkillCount < needCount then -- 格子不够
|
||
return
|
||
end
|
||
|
||
local backupSkill
|
||
if emptyCount < needCount then
|
||
backupSkill = table.remove(keepSnapSkillList)
|
||
end
|
||
|
||
for _, snap in ipairs(keepSnapSkillList) do
|
||
table.insert(keepSnapList, snap)
|
||
end
|
||
|
||
local gotPos, useMap = self:findCanLinkPosList(posMap, needCount)
|
||
if not gotPos then
|
||
return
|
||
end
|
||
|
||
self.canRandomElmentList = table.clearOrCreate(self.canRandomElmentList)
|
||
|
||
local elementCount = 0
|
||
for typeName, typeNum in pairs(BattleConst.ELEMENT_TYPE) do
|
||
if not lockElementMap[typeNum] and not self:getSealElementType()[typeNum] and self.battleData:getSkillEntityByElement(typeNum) then
|
||
table.insert(self.canRandomElmentList, typeNum)
|
||
elementCount = elementCount + 1
|
||
end
|
||
end
|
||
|
||
if elementCount <= 0 then
|
||
return
|
||
end
|
||
|
||
local mainElement = self.canRandomElmentList[math.random(1, elementCount)]
|
||
|
||
for typeNum, _ in pairs(lockElementMap) do
|
||
table.insert(self.canRandomElmentList, typeNum)
|
||
elementCount = elementCount + 1
|
||
end
|
||
|
||
local resetPosInfo = self:_dealResetGridsDataFunc2(useMap, emptySnapList, mainElement, backupSkill, keepSnapList, posMap, self.canRandomElmentList, elementCount, lockElementMap)
|
||
|
||
return resetPosInfo
|
||
end
|
||
|
||
function BattleController:findCanLinkPosList(posMap, needCount)
|
||
self.findCanLinkList = table.clearOrCreate(self.findCanLinkList)
|
||
self.findCanUseMap = table.clearOrCreate(self.findCanUseMap)
|
||
local gotPos = false
|
||
for posId, _ in pairs(posMap) do
|
||
table.clear(self.findCanLinkList)
|
||
table.clear(self.findCanUseMap)
|
||
local count = 0
|
||
local findPodId = posId
|
||
gotPos = false
|
||
while true do
|
||
local aounrdList = BattleConst.GRID_OUT_LINE_POS_ID[findPodId]
|
||
if not aounrdList then
|
||
break
|
||
end
|
||
local got = false
|
||
for id, status in pairs(aounrdList) do
|
||
if posMap[id] and not self.findCanUseMap[id] then
|
||
table.insert(self.findCanLinkList, id)
|
||
count = count + 1
|
||
self.findCanUseMap[id] = true
|
||
findPodId = id
|
||
got = true
|
||
break
|
||
end
|
||
end
|
||
if not got then
|
||
break
|
||
end
|
||
if count >= needCount then
|
||
gotPos = true
|
||
break
|
||
end
|
||
end
|
||
|
||
if gotPos then
|
||
break
|
||
end
|
||
end
|
||
|
||
return gotPos, self.findCanUseMap, self.findCanLinkList
|
||
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:canLink() and not gridEntity:getSkillId() 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:generateMonsterById(monsterId, callback)
|
||
local unitEntity = DataManager.BattleData:addMonster(monsterId, true)
|
||
local modelId = unitEntity:getModelId()
|
||
BattleHelper:loadBattleHeroModel(modelId, self.battleUI:getBattleNode(), function(spineObject)
|
||
self.defTeam:removeAllUnits()
|
||
local monsterComp = spineObject:addLuaComponent(GConst.BattleConst.TYPEOF_LUA_COMP.BATTLE_MONSTER_COMPONENT)
|
||
monsterComp:initWithEntity(modelId, unitEntity, self)
|
||
self.defTeam:addUnit(monsterComp, true)
|
||
self.battleUI:refreshDefHp(unitEntity:getHp(), unitEntity:getHpPercent())
|
||
monsterComp:playEnterBattlefield(false, callback)
|
||
end)
|
||
end
|
||
|
||
function BattleController:addBattleExp(exp)
|
||
if not self.battleData or not exp then
|
||
return
|
||
end
|
||
self.battleData:addExp(exp)
|
||
end
|
||
|
||
function BattleController:addTaskProgress(fieldName, count)
|
||
if not count then
|
||
return
|
||
end
|
||
self.taskProgress[fieldName] = (self.taskProgress[fieldName] or 0) + count
|
||
end
|
||
|
||
function BattleController:getTaskProgress()
|
||
return self.taskProgress
|
||
end
|
||
|
||
function BattleController:_tick(dt)
|
||
self.realTime = self.realTime + 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:checkDelayEffectText(dt)
|
||
self:checkSkillSlowDown(dt)
|
||
self:tick(dt)
|
||
end
|
||
|
||
function BattleController:battleEnd()
|
||
if self.battleEndSid then
|
||
ModuleManager.BattleManager:unscheduleGlobal(self.battleEndSid)
|
||
self.battleEndSid = nil
|
||
end
|
||
self.battleUI:disableUITouch()
|
||
self.battleEndSid = ModuleManager.BattleManager:performWithDelayGlobal(function()
|
||
if self.battleUI then
|
||
self.battleUI:enableUITouch()
|
||
end
|
||
self:controllBattleEnd()
|
||
ModuleManager.TaskManager:addTaskProgress(GConst.TaskConst.TASK_TYPE.X_BATTLE_VICTORY)
|
||
end, 1)
|
||
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()
|
||
BattlePool:clear()
|
||
self:unBindAll()
|
||
DataManager.BattleData:resetTimeSpeed()
|
||
ModuleManager.BattleManager:unscheduleAll()
|
||
end
|
||
|
||
function BattleController:endBattleAndExit()
|
||
ModuleManager.BattleManager:exitBattle()
|
||
end
|
||
|
||
function BattleController:checkSkillSlowDown(dt)
|
||
if self.skillSlowDownDuration == nil then
|
||
return
|
||
end
|
||
self.skillSlowDownDuration = self.skillSlowDownDuration - dt
|
||
if self.skillSlowDownDuration >= 0 then
|
||
return
|
||
end
|
||
self.skillSlowDownDuration = nil
|
||
self:resetTimeSpeed()
|
||
end
|
||
|
||
function BattleController:checkDelayEffectText(dt)
|
||
if self.delayEffectTextCount <= 0 then
|
||
return
|
||
end
|
||
for i = self.delayEffectTextCount, 1, -1 do
|
||
local delayEffectText = self.delayEffectTextList[i]
|
||
delayEffectText.time = delayEffectText.time - dt
|
||
if delayEffectText.time <= 0 then
|
||
local effectTextComp = BattleHelper:getEffectText(self.battleUI:getNumberNode(), delayEffectText.colorType)
|
||
effectTextComp:showEffectNumber(delayEffectText.effectType, delayEffectText.num, delayEffectText.x, delayEffectText.y)
|
||
table.insert(self.effectTexts, effectTextComp)
|
||
local tailDelayEffectText = self.delayEffectTextList[self.delayEffectTextCount]
|
||
delayEffectText.colorType = tailDelayEffectText.colorType
|
||
delayEffectText.effectType = tailDelayEffectText.effectType
|
||
delayEffectText.num = tailDelayEffectText.num
|
||
delayEffectText.x = tailDelayEffectText.x
|
||
delayEffectText.y = tailDelayEffectText.y
|
||
delayEffectText.time = tailDelayEffectText.time
|
||
self.delayEffectTextCount = self.delayEffectTextCount - 1
|
||
end
|
||
end
|
||
end
|
||
|
||
function BattleController:showEffectNumber(colorType, effectType, num, x, y, delayTime)
|
||
if delayTime > 0 then
|
||
self.delayEffectTextCount = self.delayEffectTextCount + 1
|
||
local obj = self.delayEffectTextList[self.delayEffectTextCount]
|
||
if obj == nil then
|
||
obj = {}
|
||
self.delayEffectTextList[self.delayEffectTextCount] = obj
|
||
end
|
||
obj.colorType = colorType
|
||
obj.effectType = effectType
|
||
obj.num = num
|
||
obj.x = x
|
||
obj.y = y
|
||
obj.time = delayTime
|
||
else
|
||
local effectTextComp = BattleHelper:getEffectText(self.battleUI:getNumberNode(), colorType)
|
||
effectTextComp:showEffectNumber(effectType, num, x, y)
|
||
table.insert(self.effectTexts, effectTextComp)
|
||
end
|
||
end
|
||
|
||
function BattleController:getFxNode()
|
||
return self.battleUI:getFxNode()
|
||
end
|
||
|
||
function BattleController:shakeScreen(shakeType, duration)
|
||
self.battleUI:shakeScreen(shakeType, duration)
|
||
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:getTargetSide() == BattleConst.SIDE_DEF then
|
||
target = defComp
|
||
elseif effect:getTargetSide() == BattleConst.SIDE_ATK then
|
||
target = mainComp
|
||
else
|
||
local matchType = BattleConst.SIDE_OBJ_TO_MATCH_TYPE[effect:getTargetSide()]
|
||
if matchType then
|
||
target = self.atkTeam:getUnitComp()[matchType]
|
||
end
|
||
end
|
||
if target then
|
||
mainComp:takeEffect(effect, target)
|
||
end
|
||
end
|
||
end
|
||
|
||
callback()
|
||
end
|
||
|
||
local function _assisting(self, instruction, callback)
|
||
self.atkTeam:useAssistingSkill(instruction.assistingList, #self.instructions == 0, callback)
|
||
end
|
||
|
||
local function _generalAttack(self, instruction, callback)
|
||
self.atkTeam:useNormalSkill(instruction.skillMatch, instruction.count, #self.instructions == 0, BattleConst.EFFECT_TYPE.DIRECT, BattleConst.ATTACK_ACTION_STATE.NORMAL, callback)
|
||
end
|
||
|
||
local function _playSkill(self, instruction, callback)
|
||
self.atkTeam:useSkill(instruction.skillMatch, instruction.count, #self.instructions == 0, BattleConst.EFFECT_TYPE.DIRECT, BattleConst.ATTACK_ACTION_STATE.NORMAL, 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 |