3304 lines
117 KiB
Lua
3304 lines
117 KiB
Lua
local BattleScheduler = require "app/module/battle/helper/battle_scheduler"
|
||
local BattlePassive = require "app/module/battle/helper/battle_passive"
|
||
local BattlePool = require "app/module/battle/helper/battle_pool"
|
||
local BattleHelper = require "app/module/battle/helper/battle_helper"
|
||
local BattleBuffEntity = require "app/userdata/battle/skill/battle_buff_entity"
|
||
local BattleTeam = require "app/module/battle/team/battle_team"
|
||
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 BattleBoardTouchHelper = require "app/module/battle/helper/battle_board_touch_helper"
|
||
local BattleBuffHandle = require "app/module/battle/helper/battle_buff_handle"
|
||
local BATTLE_SNAPSHOT_HELPER = require "app/module/battle/helper/battle_snapshot_helper"
|
||
local BOARD_HELER = require "app/module/battle/helper/board_helper"
|
||
local BattleFormula = require "app/module/battle/helper/battle_formula"
|
||
local BattleBaseController = class("BattleBaseController")
|
||
local BattleConst = GConst.BattleConst
|
||
local BUFF_NAME_TO_ATTR = BattleConst.BUFF_NAME_TO_ATTR
|
||
local GRID_BREAK_CONDITION = BattleConst.GRID_BREAK_CONDITION
|
||
local SIDE_ATK = BattleConst.SIDE_ATK
|
||
local SIDE_DEF = BattleConst.SIDE_DEF
|
||
|
||
function BattleBaseController:getPosInfo(posId)
|
||
return ModuleManager.BattleManager:getPosInfo(posId, self:getRowCount())
|
||
end
|
||
|
||
function BattleBaseController:getRowCount()
|
||
return self.battleData:getRowCount()
|
||
end
|
||
|
||
function BattleBaseController:getSkillEntityBySkillId(skillId)
|
||
return self.battleData:getSkillEntityBySkillId(skillId, self.curActionSide)
|
||
end
|
||
|
||
function BattleBaseController:getSkillEntityByElement(elementType)
|
||
return self.battleData:getSkillEntityByElement(elementType, self.curActionSide)
|
||
end
|
||
|
||
function BattleBaseController:isUnlockedSkillElementType(elementType)
|
||
return self.battleData:isUnlockedSkillElementType(elementType, self.curActionSide)
|
||
end
|
||
|
||
function BattleBaseController:getSkillCount(skillId)
|
||
return self.battleData:getSkillCount(skillId, self.curActionSide)
|
||
end
|
||
|
||
function BattleBaseController:getSkillPool()
|
||
return self.battleData:getSkillPool(self.curActionSide)
|
||
end
|
||
|
||
function BattleBaseController:getSkillEntities(side)
|
||
side = side or self.curActionSide
|
||
return self.battleData:getSkillEntities(side)
|
||
end
|
||
|
||
function BattleBaseController:addSkillEnergy(elementMap, side)
|
||
side = side or self.curActionSide
|
||
self.battleData:addSkillEnergy(elementMap, side)
|
||
end
|
||
|
||
-- *************各个子模块的战斗需要重写的方法 START*************
|
||
function BattleBaseController:getBoardConfig()
|
||
return {}
|
||
end
|
||
|
||
function BattleBaseController:getChapterConfig()
|
||
return {}
|
||
end
|
||
|
||
function BattleBaseController:getChapterId()
|
||
return 0
|
||
end
|
||
|
||
function BattleBaseController:getBuffs()
|
||
return {}
|
||
end
|
||
|
||
function BattleBaseController:getBattleUIPath()
|
||
return "app/ui/battle/battle_ui"
|
||
end
|
||
|
||
---- 障碍格子图片
|
||
function BattleBaseController:getBlockIcon()
|
||
local chapterInfo = self:getChapterConfig()[self.chapterId]
|
||
if not chapterInfo then
|
||
return "battle_hinder_4"
|
||
end
|
||
return chapterInfo.block_icon
|
||
end
|
||
|
||
function BattleBaseController:getChessBoardBgName()
|
||
local chapterInfo = self:getChapterConfig()[self.chapterId]
|
||
if not chapterInfo then
|
||
return "chessboard_1"
|
||
end
|
||
return chapterInfo.chess_board
|
||
end
|
||
|
||
function BattleBaseController:getScene()
|
||
local chapterInfo = self:getChapterConfig()[self.chapterId]
|
||
if not chapterInfo then
|
||
return "bg_1"
|
||
end
|
||
return chapterInfo.scene
|
||
end
|
||
|
||
function BattleBaseController:refreshWave()
|
||
if not self.battleUI then
|
||
return
|
||
end
|
||
self.battleUI:refreshWave(self:getWaveIndex())
|
||
end
|
||
|
||
-- 战斗结束
|
||
function BattleBaseController:controllBattleEnd()
|
||
end
|
||
|
||
-- 不同模块的战斗需要初始化的东西
|
||
function BattleBaseController:initOther()
|
||
end
|
||
|
||
-- 怪物攻击力加成
|
||
function BattleBaseController:getMonsterAtkAddition()
|
||
return 0
|
||
end
|
||
|
||
-- 怪物血量加成
|
||
function BattleBaseController:getMonsterHpAddition()
|
||
return 0
|
||
end
|
||
|
||
-- 怪物攻击力固定
|
||
function BattleBaseController:getMonsterAtkFixed()
|
||
return 0
|
||
end
|
||
|
||
-- 怪物血量固定
|
||
function BattleBaseController:getMonsterHpFixed()
|
||
return 0
|
||
end
|
||
|
||
-- 需要额外加载的资源
|
||
function BattleBaseController:loadOtherRes(callback)
|
||
return callback()
|
||
end
|
||
|
||
function BattleBaseController:tick(dt)
|
||
end
|
||
|
||
-- 一共有多少波
|
||
function BattleBaseController:getMaxWave()
|
||
local config = self:getChapterConfig()[self.chapterId]
|
||
if not config or not config.monster then
|
||
return 0
|
||
end
|
||
return #config.monster
|
||
end
|
||
|
||
function BattleBaseController:getMinEliminationCount()
|
||
if not self.minEliminationCount then
|
||
self.minEliminationCount = GFunc.getConstIntValue("element_combo")
|
||
end
|
||
return self.minEliminationCount
|
||
end
|
||
|
||
function BattleBaseController:getNextMonsterId(waveIndex)
|
||
waveIndex = waveIndex or self:getWaveIndex() + 1
|
||
local config = self:getChapterConfig()[self.chapterId]
|
||
local monsterId = config.monster[waveIndex]
|
||
return monsterId
|
||
end
|
||
|
||
function BattleBaseController:showBossEnterAni(bornTime, bossName, monsterComp, callback)
|
||
self.battleUI:showBossEnterAni(bornTime, bossName, monsterComp, callback)
|
||
end
|
||
|
||
function BattleBaseController:generateNextMonster()
|
||
local monsterId = self:getNextMonsterId()
|
||
if monsterId == nil then
|
||
return self:enterNextWave()
|
||
end
|
||
local isBoss = self.defTeam:getIsBoss()
|
||
local unitEntity = self.battleData:addMonster(monsterId, true, self)
|
||
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:handleBuffs(GConst.BattleConst.SIDE_DEF)
|
||
self.battleUI:refreshDefHp(unitEntity:getHp(), unitEntity:getHpPercent())
|
||
local bornTime = monsterComp:getAnimationDuration(GConst.BattleConst.SPINE_ANIMATION_NAME.BORN)
|
||
if isBoss then -- 如果是boss就跑过去
|
||
local count = 0
|
||
local function onFinish()
|
||
count = count + 1
|
||
if count == 2 then
|
||
self.atkTeam:stopRunAction()
|
||
self:onRoundEnd(true)
|
||
end
|
||
end
|
||
self.atkTeam:playRunAction()
|
||
self.atkTeam:recoverHpOnWaveOver(onFinish)
|
||
|
||
isBoss = self.defTeam:getIsBoss()
|
||
if isBoss then
|
||
local monsterInfo = ConfigManager:getConfig("monster")[monsterId]
|
||
self:showBossEnterAni(bornTime, ModuleManager.HeroManager:getMonsterName(monsterInfo.monster_base), monsterComp, function()
|
||
monsterComp:playEnterBattlefield(true, onFinish)
|
||
end)
|
||
else
|
||
monsterComp:playEnterBattlefield(true, onFinish)
|
||
end
|
||
else
|
||
local count = 0
|
||
local function onFinish()
|
||
count = count + 1
|
||
if count == 2 then
|
||
self:onRoundEnd(true)
|
||
end
|
||
end
|
||
self.atkTeam:recoverHpOnWaveOver(onFinish)
|
||
|
||
isBoss = self.defTeam:getIsBoss()
|
||
if isBoss then
|
||
local monsterInfo = ConfigManager:getConfig("monster")[monsterId]
|
||
self:showBossEnterAni(bornTime, ModuleManager.HeroManager:getMonsterName(monsterInfo.monster_base), monsterComp, function()
|
||
monsterComp:playEnterBattlefield(false, onFinish)
|
||
end)
|
||
else
|
||
monsterComp:playEnterBattlefield(false, onFinish)
|
||
end
|
||
end
|
||
end)
|
||
end
|
||
|
||
function BattleBaseController:findNextDefUnit()
|
||
self:generateNextMonster()
|
||
end
|
||
|
||
function BattleBaseController:onDefDead(callback)
|
||
self.defTeam:getMainUnit():playDead(function()
|
||
local monsterId = self.defTeam:getMainUnit().unitEntity:getDeathSummon()
|
||
if monsterId > 0 then
|
||
self:generateMonsterById(monsterId, function()
|
||
self.curWaveMonsterDead = false
|
||
if callback then
|
||
callback()
|
||
end
|
||
self:handleBuffs(BattleConst.SIDE_DEF)
|
||
end)
|
||
else
|
||
if callback then
|
||
callback()
|
||
end
|
||
end
|
||
end)
|
||
end
|
||
|
||
function BattleBaseController: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
|
||
local dmgSkillId
|
||
for index, info in ipairs(sequence) do
|
||
local entity = self.battleData:getGridEntity(info.posId)
|
||
if not mainElementType or not dmgSkillId then
|
||
local skillId = entity:getSkillId()
|
||
if not skillId and not mainElementType then
|
||
mainElementType = entity:getElementType()
|
||
end
|
||
if skillId and not dmgSkillId then
|
||
dmgSkillId = skillId
|
||
end
|
||
if mainElementType and dmgSkillId then
|
||
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 = self:getPosInfo(info.posId)
|
||
local nextPos = self: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
|
||
|
||
self.teampSkillBreakEnergyMap = table.clearOrCreate(self.teampSkillBreakEnergyMap)
|
||
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)
|
||
if dmgSkillId then
|
||
local skillEntity = self.battleData:getSkillEntityBySkillId(dmgSkillId)
|
||
local multiple = skillEntity and skillEntity:getSkillBreakEnergyMultiple() or 1
|
||
if multiple > 1 then
|
||
entity:getCell():setCountStr(skillEntity:getSkillBreakEnergyMultipleStr())
|
||
local elementType = entity:getElementType()
|
||
if entity:canLink() and elementType and elementType > 0 then
|
||
self.teampSkillBreakEnergyMap[elementType] = (self.teampSkillBreakEnergyMap[elementType] or 0) + (multiple - 1)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
local dmgElementTypeMap
|
||
if not self:getCurActionUnitComp():getActiveSkillLimit() then
|
||
local aniSequence, influenceElementType, lineCount, elementTypeMap, linkElementType, effectGridMap, randomPosList = self:calculateCurElimination(true)
|
||
dmgElementTypeMap = elementTypeMap
|
||
if randomPosList then
|
||
for _, posId in ipairs(randomPosList) do
|
||
local gridEntity = self.battleData:getGridEntity(posId)
|
||
if gridEntity and gridEntity:canLink() then
|
||
local elementType = gridEntity:getElementType()
|
||
if elementTypeMap[elementType] and elementTypeMap[elementType] > 0 then
|
||
elementTypeMap[elementType] = elementTypeMap[elementType] - 1
|
||
end
|
||
end
|
||
end
|
||
end
|
||
for elementType, count in pairs(elementTypeMap) do
|
||
self.teampSkillBreakEnergyMap[elementType] = (self.teampSkillBreakEnergyMap[elementType] or 0) + count
|
||
end
|
||
self.battleUI:refreshSkill(elementTypeMap, count > 0, self.curActionSide)
|
||
end
|
||
|
||
if mainElementType then
|
||
self:getSideTeam(self.curActionSide):changeMainUnit(mainElementType)
|
||
end
|
||
|
||
local elementTypeCount = 0
|
||
if dmgElementTypeMap then
|
||
for element, count in pairs(dmgElementTypeMap) do
|
||
elementTypeCount = elementTypeCount + count
|
||
end
|
||
end
|
||
local dmg = self:calExpectedInjury(mainElementType, elementTypeCount, dmgSkillId)
|
||
local defMainUnitcomp = self:getCurOtherActionUnitComp()
|
||
if defMainUnitcomp then
|
||
local hp = defMainUnitcomp.unitEntity:getHp()
|
||
local hpPercent = (hp - dmg) / defMainUnitcomp.unitEntity:getMaxHp()
|
||
if self.curActionSide == SIDE_ATK then
|
||
self.battleUI:setDefHp(hp, hpPercent)
|
||
else
|
||
self.battleUI:setAtkHp(hp, hpPercent)
|
||
end
|
||
end
|
||
end
|
||
|
||
function BattleBaseController:getInitBoard()
|
||
if not self.boradList then
|
||
self.boradList = {}
|
||
self.fixedRandomGrid = {}
|
||
self.mysteryBoxIndexMap = {}
|
||
|
||
local config = self:getChapterConfig()[self.chapterId]
|
||
local boardCfg = self:getBoardConfig()
|
||
for _, boardId in ipairs(config.board) do
|
||
local cfg = boardCfg[boardId]
|
||
if cfg then
|
||
table.insert(self.boradList, {board = GFunc.getTable(cfg.board), mysteryBoard = GFunc.getTable(cfg.mystery_box_board), gridEdge = GFunc.getTable(cfg.grid_edge)})
|
||
table.insert(self.fixedRandomGrid, GFunc.getTable(cfg.control_element))
|
||
end
|
||
end
|
||
end
|
||
|
||
return self.boradList, self.fixedRandomGrid, self.mysteryBoxIndexMap
|
||
end
|
||
|
||
function BattleBaseController:getNotInvolvedSkills()
|
||
if not self.notInvolvedSkills then
|
||
self.notInvolvedSkills = {}
|
||
local config = self:getChapterConfig()[self.chapterId]
|
||
if config.not_involved_skill then
|
||
for _, skillId in ipairs(config.not_involved_skill) do
|
||
self.notInvolvedSkills[skillId] = true
|
||
end
|
||
end
|
||
end
|
||
|
||
return self.notInvolvedSkills
|
||
end
|
||
|
||
function BattleBaseController:getFixedRogueSkill()
|
||
if not self.fixedRogueSkill then
|
||
self.fixedRogueSkill = {}
|
||
end
|
||
|
||
return self.fixedRogueSkill
|
||
end
|
||
|
||
function BattleBaseController:getSealElementType()
|
||
if not self.sealElementType then
|
||
self.sealElementType = {}
|
||
local config = self:getChapterConfig()[self.chapterId]
|
||
if config.seal_element then
|
||
for _, elementType in ipairs(config.seal_element) do
|
||
self.sealElementType[elementType] = true
|
||
end
|
||
end
|
||
end
|
||
|
||
return self.sealElementType
|
||
end
|
||
|
||
function BattleBaseController:getAtkMinRow()
|
||
return 0
|
||
end
|
||
|
||
-- *************各个子模块的战斗需要重写的方法 end*************
|
||
|
||
function BattleBaseController: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
|
||
|
||
function BattleBaseController:ctor()
|
||
self.battleData = DataManager.BattleData
|
||
end
|
||
|
||
function BattleBaseController:init(params, snapshot)
|
||
params = params or {}
|
||
self.snapshot = snapshot
|
||
self.params = params
|
||
self.battleType = params.battleType or GConst.BattleConst.BATTLE_TYPE.STAGE
|
||
self.waveDurationTime = 0
|
||
self.totalDurationTime = 0
|
||
self.eliminateCount = 0
|
||
self.eliminateTotalCount = 0
|
||
self.maxLinkCount = 0
|
||
self.realTime = 0
|
||
self.taskProgress = {}
|
||
self.waveRoundCount = {}
|
||
self.lastRoundBreakedGridType = {}
|
||
self.waitingFillCount = 0
|
||
self.needWaitingBoardOver = nil
|
||
self.curWaveMonsterDead = false
|
||
self.totalBreakedGridType = {}
|
||
self.totalEliminateCountMap = {}
|
||
|
||
self.curActionSide = SIDE_ATK
|
||
self:resetSideActionCount()
|
||
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
|
||
if snapshot then -- 处理战斗快照
|
||
self:dealSnapshotBattleBaseInfo(snapshot)
|
||
self.battleData:init(params, snapshot.battledataShopInfo)
|
||
else
|
||
self.battleData:init(params)
|
||
end
|
||
BattleScheduler:init()
|
||
BattlePool:init()
|
||
BattleHelper:init()
|
||
BattlePassive:init()
|
||
self:setTimeScale(self.battleData:getTimeScale())
|
||
self:bindData()
|
||
self:initBattleTeam()
|
||
self:initOther()
|
||
self:prepareFight()
|
||
end
|
||
|
||
function BattleBaseController:dealSnapshotBattleExtraInfo(snapshot)
|
||
BATTLE_SNAPSHOT_HELPER:dealSnapshotBattleExtraInfo(self, snapshot)
|
||
end
|
||
|
||
function BattleBaseController:dealSnapshotBattleBaseInfo(snapInfo)
|
||
BATTLE_SNAPSHOT_HELPER:dealSnapshotBattleBaseInfo(self, snapInfo)
|
||
end
|
||
|
||
function BattleBaseController:snapshotBattleInfo()
|
||
BATTLE_SNAPSHOT_HELPER:snapshotBattleInfo(self)
|
||
end
|
||
|
||
function BattleBaseController:bindData()
|
||
self.battleData:bind("timeSpeed", ModuleManager.BattleManager, function()
|
||
self:setTimeScale( self.battleData:getTimeScale())
|
||
end, false)
|
||
end
|
||
|
||
function BattleBaseController:unBindAll()
|
||
self.battleData:unBind("timeSpeed", ModuleManager.BattleManager)
|
||
end
|
||
|
||
function BattleBaseController: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 BattleBaseController:resetSideActionCount()
|
||
if not self.sideActionCount then
|
||
self.sideActionCount = {
|
||
[SIDE_ATK] = 1,
|
||
[SIDE_DEF] = 1,
|
||
}
|
||
else
|
||
self.sideActionCount[SIDE_ATK] = 1
|
||
self.sideActionCount[SIDE_DEF] = 1
|
||
end
|
||
end
|
||
|
||
function BattleBaseController:resduceSideActionCount(side)
|
||
if not self.sideActionCount or not self.sideActionCount[side] then
|
||
return false
|
||
end
|
||
if self.sideActionCount[side] > 0 then
|
||
self.sideActionCount[side] = self.sideActionCount[side] - 1
|
||
return true
|
||
else
|
||
return false
|
||
end
|
||
end
|
||
|
||
function BattleBaseController:getSideActionCount(side)
|
||
if not self.sideActionCount or not self.sideActionCount[side] then
|
||
return 0
|
||
end
|
||
return self.sideActionCount[side]
|
||
end
|
||
|
||
function BattleBaseController:getControllerParams()
|
||
return self.params
|
||
end
|
||
|
||
function BattleBaseController:setCurActionSide(side)
|
||
self.curActionSide = side or SIDE_ATK
|
||
end
|
||
|
||
function BattleBaseController:setIsPauseHpProgress(value)
|
||
self.battleUI:setIsPauseHpProgress(value)
|
||
end
|
||
|
||
function BattleBaseController:getIsPvpBattle()
|
||
return BattleConst.IS_PVP_BATTLE[self.battleType] == true
|
||
end
|
||
|
||
function BattleBaseController:moveBattlefield(time)
|
||
self.battleUI:moveBattlefield(time)
|
||
end
|
||
|
||
function BattleBaseController:refreshBuff(side, buffList)
|
||
self.battleUI:refreshBuff(side, buffList)
|
||
end
|
||
|
||
function BattleBaseController:clearBuff(side)
|
||
self.battleUI:clearBuff(side)
|
||
end
|
||
|
||
function BattleBaseController: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 BattleBaseController:showCombo(count, side)
|
||
self.battleUI:showCombo(count, side)
|
||
end
|
||
|
||
function BattleBaseController:hideCombo()
|
||
self.battleUI:hideCombo()
|
||
end
|
||
|
||
function BattleBaseController:showCounterAttack(count, side)
|
||
self.battleUI:showCounterAttack(count, side)
|
||
end
|
||
|
||
function BattleBaseController:hideCounterAttack()
|
||
self.battleUI:hideCounterAttack()
|
||
end
|
||
|
||
function BattleBaseController: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(), {battleController = 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())
|
||
self.battleUI:loadBg(self:getScene())
|
||
end)
|
||
BattleHelper:setBaseOrder(self.battleUI:getUIOrder())
|
||
BattleHelper:setBattleData(self.battleData)
|
||
BattleBoardTouchHelper:init(self)
|
||
self:loadOtherRes(onPreloadFinished)
|
||
end
|
||
|
||
function BattleBaseController: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 BattleBaseController:initDefUnits(callback)
|
||
local initIndex = self:getWaveIndex()
|
||
if initIndex <= 0 then
|
||
initIndex = 1
|
||
end
|
||
local monsterId = self:getNextMonsterId(initIndex)
|
||
local unitEntity = self.battleData:addMonster(monsterId, nil, self)
|
||
local modelId = unitEntity:getModelId()
|
||
BattleHelper:loadBattleHeroModel(modelId, self.battleUI:getBattleNode(), function(spineObject)
|
||
local monsterComp = spineObject:addLuaComponent(BattleConst.TYPEOF_LUA_COMP.BATTLE_MONSTER_COMPONENT)
|
||
monsterComp:initWithEntity(modelId, unitEntity, self)
|
||
self.defTeam:addUnit(monsterComp, true)
|
||
self.battleUI:refreshDefHp(unitEntity:getHp(), unitEntity:getHpPercent())
|
||
callback()
|
||
end)
|
||
end
|
||
|
||
function BattleBaseController:refreshHp(side, num, percent)
|
||
if side == BattleConst.SIDE_ATK then
|
||
self.battleUI:refreshAtkHp(num, percent)
|
||
else
|
||
self.battleUI:refreshDefHp(num, percent)
|
||
end
|
||
end
|
||
|
||
function BattleBaseController:getOtherSideMainUnit(side)
|
||
if side == BattleConst.SIDE_ATK then
|
||
return self.defTeam:getMainUnit()
|
||
else
|
||
return self.atkTeam:getMainUnit()
|
||
end
|
||
end
|
||
|
||
function BattleBaseController:getOtherSideTeam(side)
|
||
if side == BattleConst.SIDE_ATK then
|
||
return self.defTeam
|
||
else
|
||
return self.atkTeam
|
||
end
|
||
end
|
||
|
||
function BattleBaseController:getSideTeam(side)
|
||
if side == BattleConst.SIDE_ATK then
|
||
return self.atkTeam
|
||
else
|
||
return self.defTeam
|
||
end
|
||
end
|
||
|
||
function BattleBaseController:getCurActionTeam(side)
|
||
side = side or self.curActionSide
|
||
local isAtkAction = side == SIDE_ATK
|
||
local team = isAtkAction and self.atkTeam or self.defTeam
|
||
return team
|
||
end
|
||
|
||
function BattleBaseController:getCurActionSide()
|
||
return self.curActionSide
|
||
end
|
||
|
||
function BattleBaseController:getCurActionOtherSide()
|
||
if self.curActionSide == SIDE_ATK then
|
||
return SIDE_DEF
|
||
else
|
||
return SIDE_ATK
|
||
end
|
||
end
|
||
|
||
function BattleBaseController:getCurActionUnitComp()
|
||
return self:getCurActionTeam():getMainUnit()
|
||
end
|
||
|
||
function BattleBaseController:getCurOtherActionUnitComp()
|
||
local side = self:getCurActionOtherSide()
|
||
if not side then
|
||
return
|
||
end
|
||
local team = self:getCurActionTeam(side)
|
||
if not team then
|
||
return
|
||
end
|
||
return team:getMainUnit()
|
||
end
|
||
|
||
function BattleBaseController:getCurActionBoardRowRange(side)
|
||
side = side or self.curActionSide
|
||
local isAtkAction = side == SIDE_ATK
|
||
if isAtkAction then
|
||
return self:getAtkMinRow() + 1, self:getRowCount()
|
||
else
|
||
return 1, self:getAtkMinRow()
|
||
end
|
||
end
|
||
|
||
function BattleBaseController:getPosIdInCurActionBoardRowRange(posId)
|
||
local min, max = self:getCurActionBoardRowRange()
|
||
local r = ModuleManager.BattleManager:getPosRC(posId).r
|
||
if r < min or r > max then
|
||
return false
|
||
end
|
||
|
||
return true
|
||
end
|
||
|
||
function BattleBaseController:getPosIdInActionBoardRowRange(side, posId)
|
||
local min, max = self:getCurActionBoardRowRange(side)
|
||
local r = ModuleManager.BattleManager:getPosRC(posId).r
|
||
if r < min or r > max then
|
||
return false
|
||
end
|
||
|
||
return true
|
||
end
|
||
|
||
function BattleBaseController:onLoadComplete()
|
||
UIManager:closeLoading()
|
||
self:handleBuffs()
|
||
if self.snapshot then
|
||
self:dealSnapshotBattleExtraInfo(self.snapshot)
|
||
end
|
||
self:battleStart()
|
||
end
|
||
|
||
function BattleBaseController:battleStart()
|
||
self.atkTeam:prepare()
|
||
self.defTeam:prepare()
|
||
self.isBattleStart = true
|
||
self.tickSid = BattleScheduler:scheduleGlobal(function(dt, originDt)
|
||
self:_tick(dt, originDt)
|
||
end, 0)
|
||
|
||
if self.snapshot then
|
||
self:enterNextWaveBySnapshot(self.snapshot)
|
||
else
|
||
self:enterNextWave()
|
||
end
|
||
end
|
||
|
||
function BattleBaseController:addTimeSpeed()
|
||
if self.skillSlowDownDuration then
|
||
return
|
||
end
|
||
self.battleData:addTimeSpeed()
|
||
end
|
||
|
||
function BattleBaseController:resetTimeSpeed(isDeadReset)
|
||
if isDeadReset then
|
||
if self.skillSlowDownDuration then
|
||
return
|
||
end
|
||
end
|
||
|
||
self.battleData:resetTimeSpeed()
|
||
if self.skillSlowDownDuration then
|
||
self.skillSlowDownDuration = nil
|
||
end
|
||
end
|
||
|
||
function BattleBaseController:setSkillSlowDown(timeScale, duration)
|
||
self.skillSlowDownDuration = duration
|
||
self.battleData:setSkillTimeSpeed(timeScale)
|
||
end
|
||
|
||
function BattleBaseController:setTimeScale(timeScale)
|
||
GFunc.setDOTweenTimeScale(GConst.DOTWEEN_IDS.BATTLE, timeScale)
|
||
BattleScheduler:setTimeScale(timeScale)
|
||
BattleHelper:setTimeScale(timeScale)
|
||
end
|
||
|
||
function BattleBaseController:addWaveIndex(wave)
|
||
local origin = self:getWaveIndex()
|
||
self.waveIndex = GFunc.encryptNumber(origin + wave)
|
||
end
|
||
|
||
function BattleBaseController:setWaveIndex(wave)
|
||
self.waveIndex = GFunc.encryptNumber(wave)
|
||
end
|
||
|
||
function BattleBaseController:getWaveIndex()
|
||
if self.waveIndex <= 0 then
|
||
return 0
|
||
end
|
||
return GFunc.decryptNumber(self.waveIndex)
|
||
end
|
||
|
||
function BattleBaseController:_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 BattleBaseController:enterNextWave()
|
||
local waveIndex = self:getWaveIndex()
|
||
if waveIndex ~= 0 and self.curWaveMonsterDead 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
|
||
self:setTaskProgress(BattleConst.BATTLE_TASK_FIELD.PASS_WAVE, waveIndex)
|
||
end
|
||
|
||
if waveIndex >= self.maxWaveIndex then
|
||
self.victory = self.curWaveMonsterDead
|
||
self:postWaveOver(not self.curWaveMonsterDead)
|
||
self:battleEnd()
|
||
return
|
||
end
|
||
|
||
local atkTeam = self.battleData:getAtkTeam()
|
||
if not atkTeam or atkTeam:getIsDead() then
|
||
self.victory = false
|
||
self:postWaveOver(true)
|
||
self:battleEnd()
|
||
return
|
||
end
|
||
|
||
if waveIndex ~= 0 then -- 第一波
|
||
self:postWaveOver(false)
|
||
end
|
||
|
||
self.curWaveMonsterDead = false
|
||
self:addWaveIndex(1)
|
||
waveIndex = self:getWaveIndex()
|
||
self:refreshWave(waveIndex)
|
||
if waveIndex == 1 then -- 第一波
|
||
self.needWaitingBoardOver = true
|
||
self:generateBoard(true)
|
||
else
|
||
-- 上报关卡结束
|
||
self.defTeam:prepare()
|
||
end
|
||
|
||
self.waveDurationTime = 0
|
||
self.eliminateCount = 0
|
||
|
||
self:snapshotBattleInfo()
|
||
|
||
self.isBossWave = self.defTeam:getMainUnit().unitEntity:getIsBoss()
|
||
self:postFightStart()
|
||
if not self.needWaitingBoardOver then
|
||
self:enterRoundBegin()
|
||
end
|
||
if not self.isBossWave then
|
||
self.battleUI:hideBuffTips()
|
||
end
|
||
end
|
||
|
||
function BattleBaseController:enterNextWaveBySnapshot(snapShot)
|
||
local atkTeam = self.battleData:getAtkTeam()
|
||
if not atkTeam or atkTeam:getIsDead() then
|
||
self.victory = false
|
||
self:battleEnd()
|
||
return
|
||
end
|
||
|
||
self.curWaveMonsterDead = false
|
||
self:refreshWave(self:getWaveIndex())
|
||
self.needWaitingBoardOver = true
|
||
self:generateBoard(true, snapShot)
|
||
|
||
self.waveDurationTime = 0
|
||
self.eliminateCount = 0
|
||
|
||
self:snapshotBattleInfo()
|
||
|
||
self.isBossWave = self.defTeam:getMainUnit().unitEntity:getIsBoss()
|
||
self:postFightStart()
|
||
if not self.needWaitingBoardOver then
|
||
self:enterRoundBegin()
|
||
end
|
||
if not self.isBossWave then
|
||
self.battleUI:hideBuffTips()
|
||
end
|
||
end
|
||
|
||
function BattleBaseController:enterRoundBegin()
|
||
self.battleData:clearBreakGridEdgeTag()
|
||
self:hideTouchCancel()
|
||
self:resetSideActionCount()
|
||
self:setCurActionSide(SIDE_ATK)
|
||
self.needWaitingBoardOver = nil
|
||
local waveIndex = self:getWaveIndex()
|
||
self.waveRoundCount[waveIndex] = (self.waveRoundCount[waveIndex] or 0) + 1
|
||
self.battleUI:enterShowBoardAni(function()
|
||
self:enterEliminationBegin()
|
||
end)
|
||
table.clear(self.lastRoundBreakedGridType)
|
||
end
|
||
|
||
function BattleBaseController:takeGridEffect()
|
||
local haveGridEffectSucc = false
|
||
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 effectType ~= BattleConst.GRID_EFFECT_TYPE.CROSS_MOVE_NOT_BREAK and (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 or
|
||
effectType == BattleConst.GRID_EFFECT_TYPE.CROSS_SPREAD_NOT_BREAK) then
|
||
if not availableEffectTypeMap then
|
||
availableEffectTypeMap = {}
|
||
end
|
||
availableEffectTypeMap[effectType] = true
|
||
haveGridEffectSucc = succ
|
||
end
|
||
end
|
||
end
|
||
|
||
for _, entity in ipairs(effectGrid) do -- gridEffect == 6的最后处理
|
||
local effectType = entity:getEffectType()
|
||
if effectType == BattleConst.GRID_EFFECT_TYPE.CROSS_MOVE_NOT_BREAK and (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 then
|
||
if not availableEffectTypeMap then
|
||
availableEffectTypeMap = {}
|
||
end
|
||
availableEffectTypeMap[effectType] = true
|
||
haveGridEffectSucc = succ
|
||
end
|
||
end
|
||
end
|
||
|
||
return haveGridEffectSucc
|
||
end
|
||
|
||
function BattleBaseController:enterEliminationBegin()
|
||
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_BEGIN
|
||
self:enterRefreshBoard(true, function()
|
||
local haveGridEffectSucc = self:takeGridEffect()
|
||
if haveGridEffectSucc then -- 如果成功,则等待效果播放完成后,进入消除逻辑
|
||
if self.haveGridEffectSuccSid then
|
||
ModuleManager.BattleManager:unscheduleGlobal(self.haveGridEffectSuccSid)
|
||
self.haveGridEffectSuccSid = nil
|
||
end
|
||
ModuleManager.BattleManager:performWithDelayGlobal(function()
|
||
self:enterElimination(true)
|
||
end, 1.1)
|
||
else
|
||
self:enterElimination(true)
|
||
end
|
||
end)
|
||
end
|
||
|
||
function BattleBaseController:enterElimination(needDelay)
|
||
if self.haveGridEffectSuccSid then
|
||
ModuleManager.BattleManager:unscheduleGlobal(self.haveGridEffectSuccSid)
|
||
self.haveGridEffectSuccSid = nil
|
||
end
|
||
|
||
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 BattleBaseController:enterBattleStep()
|
||
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_TEAM_ACTION
|
||
self.battleTeamActionList = table.clearOrCreate(self.battleTeamActionList)
|
||
|
||
local atkAction = function()
|
||
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_ATK_STEP
|
||
self:exeInstructions(function()
|
||
self:enterNextTeamAction()
|
||
end, self.curActionSide)
|
||
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 BattleBaseController:addTeamActionList(func, index)
|
||
if not self.battleTeamActionList then
|
||
self.battleTeamActionList = {}
|
||
end
|
||
|
||
index = index or 1
|
||
table.insert(self.battleTeamActionList, index, func)
|
||
end
|
||
|
||
function BattleBaseController:enterNextTeamAction()
|
||
self.atkTeam:onActionOver()
|
||
self.defTeam:onActionOver()
|
||
|
||
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_TEAM_ACTION_OVER
|
||
self:hideCombo()
|
||
self:hideCounterAttack()
|
||
|
||
self:checkTeamIsDead(function() self:enterRoundEnd() end, function()
|
||
if not self.battleTeamActionList or not self.battleTeamActionList[1] then
|
||
self:enterRoundEnd()
|
||
return
|
||
end
|
||
|
||
local action = table.remove(self.battleTeamActionList, 1)
|
||
action()
|
||
end)
|
||
end
|
||
|
||
function BattleBaseController:checkTeamIsDead(callback, falseCallback)
|
||
local defTeam = self.battleData:getDefTeam()
|
||
local atkTeam = self.battleData:getAtkTeam()
|
||
if atkTeam:getIsDead() and defTeam:getIsDead() then -- 都死了,直接结算
|
||
self.curWaveMonsterDead = true
|
||
self:enterNextWave()
|
||
return true
|
||
end
|
||
|
||
if not defTeam or defTeam:getIsDead() then -- 怪物死了, 直接进入刷新逻辑
|
||
self.curWaveMonsterDead = true
|
||
self:onDefDead(function()
|
||
self.defTeam:removeAllBuff()
|
||
if self.battleData:getDefTeam():getIsDead() then
|
||
if self:getWaveIndex() >= self.maxWaveIndex then
|
||
if callback() then
|
||
callback()
|
||
end
|
||
else
|
||
self:_findNextDefUnit()
|
||
end
|
||
else
|
||
if callback() then
|
||
callback()
|
||
end
|
||
end
|
||
end)
|
||
return true
|
||
end
|
||
|
||
if not atkTeam or atkTeam:getIsDead() then -- 英雄死了, 直接结算
|
||
self:enterNextWave()
|
||
return true
|
||
end
|
||
|
||
if falseCallback then
|
||
falseCallback()
|
||
end
|
||
end
|
||
|
||
function BattleBaseController:getIsAtkStep()
|
||
return self.roundStep == BattleConst.BATTLE_ROUND_STEP.ON_ATK_STEP
|
||
end
|
||
|
||
function BattleBaseController:enterRefreshBoard(isRoundBeginCheck, callback)
|
||
if not isRoundBeginCheck then
|
||
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_REFRESH_BOARD
|
||
end
|
||
self.onFillBoardOverCallback = callback
|
||
self.isRoundBeginCheck = isRoundBeginCheck
|
||
if self.isRoundBeginCheck and self.waitingFillCount > 0 then
|
||
self.isWaitingFill = true
|
||
return
|
||
end
|
||
|
||
self:fillBoard(self.isRoundBeginCheck)
|
||
end
|
||
|
||
function BattleBaseController:enterRoundEnd()
|
||
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_END
|
||
local defTeam = self.battleData:getDefTeam()
|
||
if not defTeam or defTeam:getIsDead() then -- 怪物死了, 直接进入刷新逻辑
|
||
self.curWaveMonsterDead = true
|
||
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:checkTeamIsDead(function() self:enterNextWave() end, function()
|
||
self:onRoundEnd()
|
||
end)
|
||
end
|
||
|
||
function BattleBaseController:onRoundEnd(toNextWave)
|
||
if toNextWave then
|
||
self:enterNextWave()
|
||
else
|
||
self:enterRoundBegin()
|
||
end
|
||
end
|
||
|
||
---- end回合步骤
|
||
function BattleBaseController:onTouchEvent(eventType, posId, isVirtual)
|
||
BattleBoardTouchHelper:onTouchEvent(eventType, posId, isVirtual)
|
||
end
|
||
|
||
function BattleBaseController:showTouchCancel()
|
||
self.battleUI:showTouchCancel()
|
||
end
|
||
|
||
function BattleBaseController:hideTouchCancel()
|
||
self.battleUI:hideTouchCancel()
|
||
end
|
||
|
||
function BattleBaseController:clearGridSequence()
|
||
self:hideTouchCancel()
|
||
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 BattleBaseController:onLinkOver()
|
||
local hp = self.atkTeam:getMainUnit().unitEntity:getHp()
|
||
local hpPercent = self.atkTeam:getMainUnit().unitEntity:getHpPercent()
|
||
self.battleUI:setAtkHp(hp, hpPercent)
|
||
|
||
local hp = self.defTeam:getMainUnit().unitEntity:getHp()
|
||
local hpPercent = self.defTeam:getMainUnit().unitEntity:getHpPercent()
|
||
self.battleUI:setDefHp(hp, hpPercent)
|
||
|
||
self.battleUI:hideAllSfxLine()
|
||
local sequence = self.battleData:getGridSequence()
|
||
local count = #sequence
|
||
if count < self:getMinEliminationCount() then
|
||
return
|
||
end
|
||
|
||
local isAtkAction = self.curActionSide == SIDE_ATK
|
||
local skillId = self.battleData:getSequenceHadSkill()
|
||
local skillEntity
|
||
if skillId then
|
||
skillEntity = self:getSkillEntityBySkillId(skillId)
|
||
if isAtkAction then
|
||
self:addTaskProgress(BattleConst.BATTLE_TASK_FIELD.BOARD_SKILL_RELEASE_COUNT, 1)
|
||
end
|
||
end
|
||
|
||
self.teampSkillBreakEnergyMap = table.clearOrCreate(self.teampSkillBreakEnergyMap)
|
||
if skillEntity then
|
||
for posId, info in pairs(self.battleData:getSkillInfluenceGrids()) do
|
||
local entity = self.battleData:getGridEntity(posId)
|
||
if entity then
|
||
local multiple = skillEntity and skillEntity:getSkillBreakEnergyMultiple() or 1
|
||
if multiple > 1 then
|
||
entity:getCell():setCountStr(skillEntity:getSkillBreakEnergyMultipleStr())
|
||
local elementType = entity:getElementType()
|
||
if entity:canLink() and elementType and elementType > 0 then
|
||
self.teampSkillBreakEnergyMap[elementType] = (self.teampSkillBreakEnergyMap[elementType] or 0) + (multiple - 1)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
local aniSequence, influenceElementTypeMap, lineCount, elementTypeMap, linkElementType, effectGridMap = self:calculateCurElimination()
|
||
|
||
if not self:getCurActionUnitComp():getActiveSkillLimit() then
|
||
for elementType, count in pairs(elementTypeMap) do
|
||
self.teampSkillBreakEnergyMap[elementType] = (self.teampSkillBreakEnergyMap[elementType] or 0) + count
|
||
end
|
||
self:addSkillEnergy(self.teampSkillBreakEnergyMap)
|
||
end
|
||
self.battleData:clearGridSequence()
|
||
self.battleUI:disableUITouch()
|
||
self.battleUI:eliminationAni(aniSequence, effectGridMap, function()
|
||
self:enterRefreshBoard(nil, function()
|
||
self:onLinkOverDone(skillEntity, linkElementType, lineCount, influenceElementTypeMap, elementTypeMap)
|
||
end)
|
||
end, self.curActionSide)
|
||
|
||
for element, count in pairs(elementTypeMap) do
|
||
self.totalEliminateCountMap[element] = (self.totalEliminateCountMap[element] or 0) + count
|
||
end
|
||
|
||
self.eliminateCount = self.eliminateCount + 1
|
||
self.eliminateTotalCount = self.eliminateTotalCount + 1
|
||
if count > self.maxLinkCount then
|
||
self.maxLinkCount = count
|
||
end
|
||
end
|
||
|
||
function BattleBaseController:onLinkOverDone(skillEntity, linkElementType, lineCount, influenceElementTypeMap, elementTypeMap)
|
||
self.battleUI:enterHideBoardAni(function()
|
||
self:generateInstructions(skillEntity, linkElementType, lineCount, influenceElementTypeMap, elementTypeMap)
|
||
self:enterBattleStep()
|
||
end)
|
||
end
|
||
|
||
function BattleBaseController:calculateCurElimination(onlyCheck)
|
||
local sequence = self.battleData:getGridSequence()
|
||
local skillId = self.battleData:getSequenceHadSkill()
|
||
local skillEntity
|
||
if skillId then
|
||
skillEntity = self: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 and skillEntity 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, randomPosList
|
||
end
|
||
|
||
function BattleBaseController: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 or entity:canBreakByThisCondition(condition) then
|
||
breakedMap[posId] = true
|
||
|
||
aniUnit.breakSfxName = entity:getBreakSfx()
|
||
aniUnit.callback = function()
|
||
local gridType = entity:getGridType()
|
||
self.lastRoundBreakedGridType[gridType] = true
|
||
self.totalBreakedGridType[gridType] = (self.totalBreakedGridType[gridType] or 0) + 1
|
||
entity:tryBreakGrid(condition)
|
||
if entity:getIsIdle() then
|
||
self:dealGridEdge(posId)
|
||
end
|
||
end
|
||
|
||
table.insert(aniSequence, aniUnit)
|
||
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
|
||
if self.battleData:getGridEntity(id) then
|
||
if not BOARD_HELER:hasGridEdgeBetween(self, posId, id) then
|
||
self:dealGridBreak(id, GRID_BREAK_CONDITION.AROUND, time, breakedMap, sequenceMap, aniSequence, gridMap, onlyCheck)
|
||
end
|
||
end
|
||
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
|
||
local timeIdx = time + BattleConst.GRID_BREAK_EFFECT_INTERVAL * (index - 1) -- 因为第一个是自己,所以-1
|
||
self:dealGridBreak(id, GRID_BREAK_CONDITION.SKILL, timeIdx, breakedMap, sequenceMap, aniSequence, gridMap, onlyCheck)
|
||
table.insert(aniUnit.aniPosList, id)
|
||
end
|
||
end
|
||
|
||
---- 技能效果特效
|
||
aniUnit.effectSfxName = entity:getEffectSfx()
|
||
aniUnit.effectSfxFlow = entity:getEffectSfxFlow()
|
||
aniUnit.effectSfxDir = entity:getEffectParams()[1]
|
||
end
|
||
end
|
||
aniUnit.bftcTime = entity:getBftcTime()
|
||
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())
|
||
self:dealGridEdge(posId)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
return isIdle
|
||
end
|
||
|
||
function BattleBaseController:dealGridEdge(posId)
|
||
-- 能进来一定已经可以消除了
|
||
if not self.upDownLeftRightList then
|
||
self.upDownLeftRightList = {BattleConst.BOARD_RANGE_TYPE.UP, BattleConst.BOARD_RANGE_TYPE.DOWN, BattleConst.BOARD_RANGE_TYPE.LEFT, BattleConst.BOARD_RANGE_TYPE.RIGHT}
|
||
self.upDownLeftRightOppositeMap = {
|
||
[BattleConst.BOARD_RANGE_TYPE.UP] = BattleConst.BOARD_RANGE_TYPE.DOWN,
|
||
[BattleConst.BOARD_RANGE_TYPE.DOWN] = BattleConst.BOARD_RANGE_TYPE.UP,
|
||
[BattleConst.BOARD_RANGE_TYPE.LEFT] = BattleConst.BOARD_RANGE_TYPE.RIGHT,
|
||
[BattleConst.BOARD_RANGE_TYPE.RIGHT] = BattleConst.BOARD_RANGE_TYPE.LEFT
|
||
}
|
||
end
|
||
|
||
for _, direction in ipairs(self.upDownLeftRightList) do
|
||
-- 周围的
|
||
local aroundId = ModuleManager.BattleManager:getPosByDirection(posId, direction, self.battleData:getRowCount())
|
||
if aroundId then
|
||
local breaked, breakSfx, breakCount, cell = self.battleData:breakGridEdge(aroundId, self.upDownLeftRightOppositeMap[direction])
|
||
if breaked and breakSfx and breakCount and cell then
|
||
if self.battleUI then
|
||
self.battleUI:getSfxGridEdgeBreak(breakSfx, breakCount, function(obj)
|
||
local posX, posY = cell:getBaseObject():fastGetAnchoredPosition()
|
||
obj:setLocalPosition(posX, posY, 0)
|
||
obj:play()
|
||
end)
|
||
end
|
||
end
|
||
end
|
||
|
||
-- 本身
|
||
local breaked, breakSfx, breakCount, cell = self.battleData:breakGridEdge(posId, direction)
|
||
if breaked and breakSfx and breakCount and cell then
|
||
if self.battleUI then
|
||
self.battleUI:getSfxGridEdgeBreak(breakSfx, breakCount, function(obj)
|
||
local posX, posY = cell:getBaseObject():fastGetAnchoredPosition()
|
||
obj:setLocalPosition(posX, posY, 0)
|
||
obj:play()
|
||
end)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
function BattleBaseController: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 BattleBaseController:getEliminattionAniInfo(posId, timeIdx)
|
||
return {
|
||
posId = posId,
|
||
noAni = nil,
|
||
aniPosList = nil,
|
||
breakSfxName = nil,
|
||
timeIdx = timeIdx,
|
||
conditions = nil,
|
||
isSkill = false,
|
||
isIdle = false,
|
||
callback = nil,
|
||
overCallback = nil,
|
||
bftcTime = 0,
|
||
effectSfxName = nil,
|
||
effectSfxFlow = nil,
|
||
effectSfxDir = nil,
|
||
}
|
||
end
|
||
|
||
function BattleBaseController:setGridBreakCondition(gridMap, posId, condition)
|
||
if not gridMap[posId] then
|
||
gridMap[posId] = {}
|
||
gridMap[posId][condition] = true
|
||
end
|
||
gridMap[posId][condition] = true
|
||
end
|
||
|
||
function BattleBaseController:tryShowSelectSkillComp(needDelay, onlyCommonSkill)
|
||
self.canChoseSkillCount = 1
|
||
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
|
||
|
||
BIReport:postShowFightSkillSelect(self.battleType, self.battleData, skillList, self.chapterId, self.totalDurationTime, self:getWaveIndex())
|
||
end
|
||
|
||
|
||
function BattleBaseController:fillBoard(isRoundBeginCheck)
|
||
local reverse = self.curActionSide == SIDE_DEF
|
||
self.fillBoardPathMap = table.clearOrCreate(self.fillBoardPathMap)
|
||
self.fillColumnCount = table.clearOrCreate(self.fillColumnCount)
|
||
self.fillGridMap = table.clearOrCreate(self.fillGridMap)
|
||
|
||
if reverse then
|
||
for c = 1, BattleConst.COLUMN_COUNT do
|
||
for r = 1, self:getRowCount() do
|
||
local posId = ModuleManager.BattleManager:getPosId(r, c)
|
||
local entity = self.battleData:getGridEntity(posId)
|
||
if entity and entity:getIsIdle() then
|
||
self:fillThisPos(posId, self.fillColumnCount, self.fillGridMap, reverse)
|
||
end
|
||
end
|
||
end
|
||
else
|
||
for c = 1, BattleConst.COLUMN_COUNT do
|
||
for r = self:getRowCount(), 1, -1 do
|
||
local posId = ModuleManager.BattleManager:getPosId(r, c)
|
||
local entity = self.battleData:getGridEntity(posId)
|
||
if entity and entity:getIsIdle() then
|
||
self:fillThisPos(posId, self.fillColumnCount, self.fillGridMap, reverse)
|
||
end
|
||
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 posId, entity in pairs(self.battleData:getGridEnties()) do
|
||
if #entity:getPath() > 0 then
|
||
self.fillBoardPathMap[posId] = entity:getPath()
|
||
entity:clearPath()
|
||
end
|
||
end
|
||
|
||
self.battleUI:fallGrid(self.fillBoardPathMap, isRoundBeginCheck, function()
|
||
self:onFillBoardOver(isRoundBeginCheck)
|
||
self.isRoundBeginCheck = nil
|
||
self.isWaitingFill = false
|
||
end)
|
||
end
|
||
|
||
function BattleBaseController: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]
|
||
if rewards then
|
||
ModuleManager.BattleManager:showBoxOpenUI(rewards, function()
|
||
self:onFillBoardOver()
|
||
end)
|
||
else
|
||
self:onFillBoardOver()
|
||
end
|
||
return
|
||
end
|
||
|
||
if self.battleData:useCommonSelectSkillCount() then -- 检查神灯
|
||
self:tryShowSelectSkillComp(false, true)
|
||
return
|
||
end
|
||
end
|
||
|
||
if isRoundBeginCheck then
|
||
EventManager:dispatchEvent(EventManager.CUSTOM_EVENT.BOARD_FILL_OVER)
|
||
self:popBoardCacheSkill(function()
|
||
self:generateSkill(function()
|
||
if self.onFillBoardOverCallback then
|
||
local callback = self.onFillBoardOverCallback
|
||
self.onFillBoardOverCallback = nil
|
||
callback()
|
||
else
|
||
self:enterElimination(true)
|
||
end
|
||
end)
|
||
end)
|
||
else
|
||
self:generateSkill(function()
|
||
self.battleUI:refreshSkill(nil, nil, self:getCurActionSide())
|
||
if self.onFillBoardOverCallback then
|
||
local callback = self.onFillBoardOverCallback
|
||
self.onFillBoardOverCallback = nil
|
||
callback()
|
||
end
|
||
end)
|
||
end
|
||
end
|
||
|
||
function BattleBaseController:generateInstructions(skillEntity, elementType, lineCount, influenceElementTypeMap, elementTypeMap)
|
||
self.instructions = BATTLE_INSTRUCTIONS_HELPER.generateInstructions(skillEntity, elementType, lineCount, influenceElementTypeMap, elementTypeMap, self)
|
||
end
|
||
|
||
function BattleBaseController:exeInstructions(callback, side)
|
||
side = side or self:getCurActionSide()
|
||
if not self.instructions or #self.instructions <= 0 then
|
||
callback()
|
||
return
|
||
end
|
||
local instruction = table.remove(self.instructions)
|
||
local func = BattleBaseController._doInstruction[instruction.name]
|
||
if func then
|
||
func(self, side, instruction, function()
|
||
self.battleData:resetTimeSpeed()
|
||
self:exeInstructions(callback, side)
|
||
end)
|
||
else
|
||
self:exeInstructions(callback, side)
|
||
end
|
||
end
|
||
|
||
function BattleBaseController:getIsLastInstruction()
|
||
if not self.instructions or not self.instructions[1] then
|
||
return true
|
||
end
|
||
|
||
return false
|
||
end
|
||
|
||
function BattleBaseController:generateBoard(isFirst, snapshot)
|
||
local boardList, _, mysteryBoxIndexMap = self:getInitBoard()
|
||
if self.curBoardIndex and self.curBoardIndex >= #boardList then
|
||
if isFirst then
|
||
self.needWaitingBoardOver = false
|
||
end
|
||
return
|
||
end
|
||
|
||
if not self.battleUI then
|
||
if isFirst then
|
||
self.needWaitingBoardOver = false
|
||
end
|
||
return
|
||
end
|
||
|
||
self.curBoardIndex = (self.curBoardIndex or 0) + 1
|
||
if snapshot and snapshot.curBoardIndex then
|
||
self.curBoardIndex = snapshot.curBoardIndex
|
||
end
|
||
if not boardList[self.curBoardIndex] then -- 容错
|
||
if isFirst then
|
||
self.needWaitingBoardOver = false
|
||
end
|
||
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
|
||
local gridEdge = boardList[self.curBoardIndex].gridEdge
|
||
self.battleUI:switchBoard(function()
|
||
self.battleData:refreshBoard(board, gridEdge, self:getBlockIcon(), snapshot)
|
||
self.battleUI:initGridCell(function()
|
||
if isFirst then
|
||
self.needWaitingBoardOver = false
|
||
end
|
||
end)
|
||
end, function()
|
||
end, isFirst)
|
||
end
|
||
|
||
function BattleBaseController:onGotMysteryBoxIndexs()
|
||
self.gotMysteryBoxIndexs[self.curBoardIndex] = true
|
||
table.insert(self.showMysteryBoxIndexs, self.curBoardIndex)
|
||
end
|
||
|
||
|
||
function BattleBaseController: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 BattleBaseController: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)
|
||
self:setGridSkillId(self.popNewSkillId[index].posId, info.skillId, true)
|
||
else
|
||
break
|
||
end
|
||
end
|
||
|
||
self.battleUI:cacheSkillAni(self.popNewSkillId, true, function()
|
||
for index, info in ipairs(self.popNewSkillId) do
|
||
self.battleData:setGridDirty(info.posId)
|
||
end
|
||
|
||
if callback then
|
||
callback()
|
||
end
|
||
end)
|
||
else
|
||
if callback then
|
||
callback()
|
||
end
|
||
end
|
||
end
|
||
|
||
function BattleBaseController:generateSkill(callback)
|
||
self.generateSkillMap = table.clearOrCreate(self.generateSkillMap)
|
||
self.generateExcludeMap = table.clearOrCreate(self.generateExcludeMap)
|
||
for _, skillEntity in pairs(self: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, self.curActionSide)
|
||
end
|
||
|
||
function BattleBaseController:setGridSkillId(posId, skillId, noDirty)
|
||
local entity = self.battleData:getGridEntity(posId)
|
||
if entity then
|
||
entity:setSkilId(skillId, noDirty, self.curActionSide)
|
||
local skillEntity = self:getSkillEntityBySkillId(skillId)
|
||
if skillEntity and entity:getElementType() ~= skillEntity:getPosition() then
|
||
entity:setElementType(skillEntity:getPosition(), noDirty)
|
||
end
|
||
end
|
||
end
|
||
|
||
|
||
function BattleBaseController: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 BattleBaseController: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 BattleBaseController:getSkillElementListRow()
|
||
self.skillElementListRow = table.clearOrCreate(self.skillElementListRow)
|
||
local min, max = self:getCurActionBoardRowRange()
|
||
for row = min, max do
|
||
table.insert(self.skillElementListRow, row)
|
||
end
|
||
return self.skillElementListRow
|
||
end
|
||
|
||
function BattleBaseController: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 in ipairs(self:getSkillElementListRow()) 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 BattleBaseController:fillThisPos(posId, columnCount, gridMap, reverse)
|
||
local entity = self.battleData:getGridEntity(posId)
|
||
if not entity or not entity:getIsIdle() then
|
||
return
|
||
end
|
||
|
||
local list
|
||
if reverse then
|
||
list = BattleConst.DOWN_LINE_FILL_LIST[posId]
|
||
else
|
||
list = BattleConst.UP_LINE_FILL_LIST[posId]
|
||
end
|
||
if not list[1] then -- 第一排
|
||
if reverse then
|
||
local gridEdgeEntity = self.battleData:getGridEdgeEntity(posId, BattleConst.BOARD_RANGE_TYPE.DOWN)
|
||
if gridEdgeEntity and not gridEdgeEntity:getIsIdle() then
|
||
return
|
||
end
|
||
else
|
||
local gridEdgeEntity = self.battleData:getGridEdgeEntity(posId, BattleConst.BOARD_RANGE_TYPE.UP)
|
||
if gridEdgeEntity and not gridEdgeEntity:getIsIdle() then
|
||
return
|
||
end
|
||
end
|
||
|
||
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
|
||
if reverse then
|
||
newStartPosId = ModuleManager.BattleManager:getLastLineLastRowPosId(i, c, self:getRowCount())
|
||
else
|
||
newStartPosId = ModuleManager.BattleManager:getFirstLineLastRowPosId(i, c)
|
||
end
|
||
|
||
local curPos = self:getPosInfo(newStartPosId)
|
||
fallEntity:addPath({x = curPos.x, y = curPos.y})
|
||
end
|
||
|
||
local curPos = self: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 self:judgeGridEdgeCanFall(posId, fallPosId, reverse) then
|
||
if not fallEntity:isCantFallType() then
|
||
if fallEntity:getIsIdle() then
|
||
self:fillThisPos(fallPosId, columnCount, gridMap, reverse)
|
||
end
|
||
fallEntity = self.battleData:getGridEntity(fallPosId)
|
||
if not fallEntity:getIsIdle() then
|
||
if not fallEntity:getPath()[1] then
|
||
local curPos = self:getPosInfo(fallPosId)
|
||
fallEntity:addPath({x = curPos.x, y = curPos.y})
|
||
end
|
||
|
||
local curPos = self:getPosInfo(posId)
|
||
fallEntity:addPath({x = curPos.x, y = curPos.y})
|
||
|
||
self.battleData:exchangeGridEntities(posId, fallPosId)
|
||
self:fillThisPos(fallPosId, columnCount, gridMap, reverse)
|
||
return
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
function BattleBaseController:judgeGridEdgeCanFall(posId, fallPosId, reverse)
|
||
return BattleBoardTouchHelper:judgeGridEdgeCanLink(fallPosId, posId)
|
||
end
|
||
|
||
|
||
function BattleBaseController: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:getSkillEntityByElement(typeNum) then
|
||
local weight = ((map[typeNum] or 0) + 1) * BattleConst.ELEMENT_WIGHT
|
||
if self.elementWeightMap and self.elementWeightMap[typeNum] then
|
||
weight = weight + self.elementWeightMap[typeNum]
|
||
end
|
||
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 BattleBaseController: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:getSkillEntityBySkillId(skillId)
|
||
if skillEntity then
|
||
BATTLE_BOARD_SKILL_HANDLE.activeBoardSkill(info.posId, skillEntity, self.battleData:getGridEnties(), self.skillInfluenceGridsSequenceEntities, self)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
function BattleBaseController: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:getSkillPool()
|
||
local count = 0
|
||
|
||
if not onlyCommonSkill then
|
||
for elementType, list in pairs(skillPool) do -- 先遍历一下未解锁的技能
|
||
if not self:isUnlockedSkillElementType(elementType) then
|
||
local skillEntity = self: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:isUnlockedSkillElementType(elementType) then
|
||
for _, skillId in ipairs(list) do
|
||
local skillCfg = cfg[skillId]
|
||
if skillCfg and (not skillCfg.limit_times or self:getSkillCount(skillId) < skillCfg.limit_times) then
|
||
|
||
if not self.randomSkillMap[skillId] and (not skillCfg.unlock or self: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: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 BattleBaseController:dealSelectSkill(skillId, value, side, isSnapshot)
|
||
side = side or self:getCurActionSide()
|
||
self.battleData:addSkillCount(skillId, value, side)
|
||
BATTLE_ROGUE_SKILL_HANDLE.takeEffect(skillId, self.battleData, self, value, side, isSnapshot)
|
||
|
||
local skillEntities = self:getSkillEntities(side)
|
||
for _, entity in pairs(skillEntities) do
|
||
entity:gotUpSKill(skillId)
|
||
end
|
||
end
|
||
|
||
function BattleBaseController:onSelectSkill(skillId, value, pos, side)
|
||
if not self.canChoseSkillCount or self.canChoseSkillCount <= 0 then
|
||
return
|
||
end
|
||
self.canChoseSkillCount = self.canChoseSkillCount - 1
|
||
side = side or self:getCurActionSide()
|
||
self:dealSelectSkill(skillId, value, side)
|
||
|
||
BIReport:postFightSkillSelect(self.battleType, self.battleData, {skillId}, self.chapterId, self.totalDurationTime, self:getWaveIndex())
|
||
|
||
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(nil, nil, self:getCurActionSide())
|
||
end, pos)
|
||
return
|
||
end
|
||
end
|
||
|
||
self:selectSKillNextToStep()
|
||
|
||
self.battleUI:showCommonSkillTips(skillId)
|
||
end
|
||
|
||
function BattleBaseController:selectSKillNextToStep()
|
||
if self.roundStep == BattleConst.BATTLE_ROUND_STEP.ON_REFRESH_BOARD then
|
||
self:onFillBoardOver()
|
||
else
|
||
self:enterElimination()
|
||
end
|
||
end
|
||
|
||
|
||
function BattleBaseController:changeElementType(count, elementType, side)
|
||
self.changeElementTypeMap = table.clearOrCreate(self.changeElementTypeMap)
|
||
self.changeElementTypeList = table.clearOrCreate(self.changeElementTypeList)
|
||
local listCount = 0
|
||
for _, entity in pairs(self.battleData:getGridEnties()) do
|
||
if entity:canChangeInfo() and entity:getElementType() ~= elementType then
|
||
if side then
|
||
if self:getPosIdInActionBoardRowRange(side, entity:getPosId()) then
|
||
table.insert(self.changeElementTypeList, entity)
|
||
listCount = listCount + 1
|
||
end
|
||
else
|
||
table.insert(self.changeElementTypeList, entity)
|
||
listCount = listCount + 1
|
||
end
|
||
end
|
||
end
|
||
|
||
count = math.min(count, listCount)
|
||
for i = 1, count do
|
||
if listCount <= 0 then
|
||
break
|
||
end
|
||
local index = math.random(1, listCount)
|
||
self.changeElementTypeList[index], self.changeElementTypeList[listCount] = self.changeElementTypeList[listCount], self.changeElementTypeList[index]
|
||
local entity = table.remove(self.changeElementTypeList)
|
||
listCount = listCount - 1
|
||
self.changeElementTypeMap[entity] = elementType
|
||
end
|
||
|
||
self:changeElementTypeByMap(self.changeElementTypeMap)
|
||
end
|
||
|
||
function BattleBaseController: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 BattleBaseController:killGrids(posIdList)
|
||
if not posIdList[1] then
|
||
return
|
||
end
|
||
|
||
for _, posId in ipairs(posIdList) do
|
||
local entity = self.battleData:getGridEntity(posId)
|
||
entity:setIsIdle(true)
|
||
end
|
||
|
||
self.battleUI:removeGridOutOfScreen(posIdList)
|
||
end
|
||
|
||
function BattleBaseController: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 = self.battleData:getGridEntity(posId)
|
||
entity:setIsIdle(true)
|
||
end
|
||
end
|
||
self.battleUI:removeGridOutOfScreen(info.posList)
|
||
end
|
||
end
|
||
end
|
||
|
||
function BattleBaseController:addHeroAttr(attrName, value, side)
|
||
if not self.battleData or not self.battleData.atkTeam then
|
||
return
|
||
end
|
||
|
||
local attr = BUFF_NAME_TO_ATTR[attrName]
|
||
if attr then
|
||
self.battleData:getTeamBySide(side):addAttr(attr[1], value, attr[2])
|
||
else
|
||
local func = BattleBuffHandle.addAttribute[attrName]
|
||
if func then
|
||
local unitComp
|
||
for matchType, comp in pairs(self:getCurActionTeam(side):getUnitComp()) do
|
||
unitComp = comp
|
||
break
|
||
end
|
||
if unitComp then
|
||
func(unitComp, value)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
---- 快照一次棋盘
|
||
function BattleBaseController:snapshotBoard()
|
||
local snapshot = {}
|
||
for _, entity in pairs(self.battleData:getGridEnties()) do
|
||
snapshot[entity:getPosId()] = entity:getSnapshoptInfo()
|
||
end
|
||
return snapshot
|
||
end
|
||
|
||
function BattleBaseController:snapshotGridEdge()
|
||
local snapshot = {}
|
||
for posId, info in pairs(self.battleData:getGridEdgeEntities()) do
|
||
for direction, entity in pairs(info) do
|
||
if not entity:getIsIdle() then
|
||
table.insert(snapshot, {pos = posId, type = entity:getType(), direction = direction})
|
||
end
|
||
end
|
||
end
|
||
return snapshot
|
||
end
|
||
|
||
function BattleBaseController: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 BattleBaseController: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 self:getPosIdInCurActionBoardRowRange(posId) and entity:isCanFallStatus() and not entity:getCantUpset() 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 BattleBaseController: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 self:getPosIdInCurActionBoardRowRange(posId) and entity:isCanFallStatus() and not entity:getCantUpset() then
|
||
if entity:getSkillId() then
|
||
local skillEntity = self: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 BattleBaseController: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 BattleBaseController:findAttention()
|
||
local find = false
|
||
local min, max = self:getCurActionBoardRowRange()
|
||
for r = min, max 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 BattleBaseController:_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 BattleBaseController:_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 BattleBaseController: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: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 BattleBaseController: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] and BattleBoardTouchHelper:judgeGridEdgeCanLink(findPodId, 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 BattleBaseController: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 self:getPosIdInCurActionBoardRowRange(aroundposId) and not posIdMap[aroundposId] and BattleBoardTouchHelper:judgeGridEdgeCanLink(posId, 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:canLink() and gridEntity:getSkillId() and not hadSkill and mainElementType then
|
||
local skillId = gridEntity:getSkillId()
|
||
local skillEntity = self: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 BattleBaseController:generateMonsterById(monsterId, callback)
|
||
local unitEntity = self.battleData:addMonster(monsterId, true, self)
|
||
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 BattleBaseController:addBattleExp(exp)
|
||
if not self.battleData or not exp then
|
||
return
|
||
end
|
||
self.battleData:addExp(exp)
|
||
end
|
||
|
||
function BattleBaseController:addTaskProgress(fieldName, count)
|
||
if self:getCurActionSide() ~= SIDE_ATK then
|
||
return
|
||
end
|
||
if not count then
|
||
return
|
||
end
|
||
self.taskProgress[fieldName] = (self.taskProgress[fieldName] or 0) + count
|
||
end
|
||
|
||
function BattleBaseController:setTaskProgress(fieldName, count)
|
||
if not count then
|
||
return
|
||
end
|
||
self.taskProgress[fieldName] = count
|
||
end
|
||
|
||
|
||
function BattleBaseController:getTaskProgress()
|
||
return self.taskProgress
|
||
end
|
||
|
||
function BattleBaseController:addFillWaitingCount()
|
||
self.waitingFillCount = self.waitingFillCount + 1
|
||
end
|
||
|
||
function BattleBaseController:reduceFillWaitingCount()
|
||
self.waitingFillCount = self.waitingFillCount - 1
|
||
end
|
||
|
||
function BattleBaseController:_tick(dt, originDt)
|
||
self.realTime = self.realTime + dt
|
||
self.waveDurationTime = self.waveDurationTime + originDt
|
||
self.totalDurationTime = self.totalDurationTime + originDt
|
||
if self.isPause then
|
||
return
|
||
end
|
||
if self.needWaitingBoardOver == false then
|
||
self:enterRoundBegin()
|
||
end
|
||
if self.waitingFillCount <= 0 and self.isWaitingFill and self.isRoundBeginCheck then
|
||
self:fillBoard(self.isRoundBeginCheck)
|
||
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)
|
||
BattleBoardTouchHelper:tick(dt)
|
||
end
|
||
|
||
function BattleBaseController: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
|
||
|
||
-- 处理战斗任务
|
||
local curWaveIndex = self:getWaveIndex()
|
||
if self.victory then
|
||
self:setTaskProgress(GConst.BattleConst.BATTLE_TASK_FIELD.KILLS_BOSS_TURN, self.waveRoundCount[curWaveIndex])
|
||
end
|
||
|
||
local teamEntity = self.battleData:getAtkTeam()
|
||
local hpp = math.floor(teamEntity:getHpPercent() * 100 + 0.0001)
|
||
self:setTaskProgress(GConst.BattleConst.BATTLE_TASK_FIELD.SPARE_HP, hpp)
|
||
|
||
local totalRound = 0
|
||
for wave, round in pairs(self.waveRoundCount) do
|
||
if wave == curWaveIndex then
|
||
if self.victory then
|
||
totalRound = totalRound + round
|
||
end
|
||
else
|
||
totalRound = totalRound + round
|
||
end
|
||
end
|
||
self:setTaskProgress(GConst.BattleConst.BATTLE_TASK_FIELD.TOTAL_TURN, totalRound)
|
||
-- end处理战斗任务
|
||
|
||
self:controllBattleEnd()
|
||
if self.victory then
|
||
ModuleManager.TaskManager:addTaskProgress(GConst.TaskConst.TASK_TYPE.X_BATTLE_VICTORY)
|
||
end
|
||
end, 1)
|
||
end
|
||
|
||
function BattleBaseController: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()
|
||
self.battleData:clear()
|
||
self.battleData:resetTimeSpeed()
|
||
ModuleManager.BattleManager:unscheduleAll()
|
||
|
||
if DataManager.TutorialData:getIsInTutorial() then
|
||
ModuleManager.TutorialManager:stopTutorial()
|
||
end
|
||
end
|
||
|
||
function BattleBaseController:endBattleAndExit()
|
||
BATTLE_SNAPSHOT_HELPER:clearSnap(self)
|
||
ModuleManager.BattleManager:exitBattle()
|
||
end
|
||
|
||
function BattleBaseController: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 BattleBaseController: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, delayEffectText.showCombo)
|
||
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
|
||
delayEffectText.showCombo = tailDelayEffectText.showCombo
|
||
self.delayEffectTextCount = self.delayEffectTextCount - 1
|
||
end
|
||
end
|
||
end
|
||
|
||
function BattleBaseController:showEffectNumber(colorType, effectType, num, x, y, delayTime, showCombo)
|
||
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
|
||
obj.showCombo = showCombo
|
||
else
|
||
local effectTextComp = BattleHelper:getEffectText(self.battleUI:getNumberNode(), colorType)
|
||
effectTextComp:showEffectNumber(effectType, num, x, y, showCombo)
|
||
table.insert(self.effectTexts, effectTextComp)
|
||
end
|
||
end
|
||
|
||
function BattleBaseController:getFxNode()
|
||
return self.battleUI:getFxNode()
|
||
end
|
||
|
||
function BattleBaseController:shakeScreen(shakeType, duration)
|
||
self.battleUI:shakeScreen(shakeType, duration)
|
||
end
|
||
|
||
local function _addCurRoundAttr(self, side, instruction, callback)
|
||
if instruction.effectList then
|
||
local defComp = self.defTeam:getMainUnit()
|
||
local atkComp = self.atkTeam:getMainUnit()
|
||
local isAtkSide = side == SIDE_ATK
|
||
local actionComp = isAtkSide and atkComp or defComp
|
||
for _, effect in ipairs(instruction.effectList) do
|
||
local target
|
||
if effect:getTargetSide() == BattleConst.SIDE_DEF then
|
||
target = isAtkSide and defComp or atkComp
|
||
elseif effect:getTargetSide() == BattleConst.SIDE_ATK then
|
||
target = isAtkSide and atkComp or defComp
|
||
else
|
||
local matchType = BattleConst.SIDE_OBJ_TO_MATCH_TYPE[effect:getTargetSide()]
|
||
if matchType then
|
||
if isAtkSide then
|
||
target = self.atkTeam:getUnitComp()[matchType]
|
||
else
|
||
target = self.defTeam:getUnitComp()[matchType]
|
||
end
|
||
end
|
||
end
|
||
if target then
|
||
actionComp:takeEffect(effect, target)
|
||
end
|
||
end
|
||
end
|
||
|
||
callback()
|
||
end
|
||
|
||
local function _assisting(self, side, instruction, callback)
|
||
local actionTeam = self.atkTeam
|
||
if side == SIDE_DEF then
|
||
actionTeam = self.defTeam
|
||
end
|
||
actionTeam:useAssistingSkill(instruction.assistingList, #self.instructions == 0, callback)
|
||
end
|
||
|
||
local function _generalAttack(self, side, instruction, callback)
|
||
local actionTeam = self.atkTeam
|
||
if side == SIDE_DEF then
|
||
actionTeam = self.defTeam
|
||
end
|
||
actionTeam:useNormalSkill(instruction.skillMatch, instruction.count, #self.instructions == 0, BattleConst.EFFECT_TYPE.DIRECT, BattleConst.ATTACK_ACTION_STATE.NORMAL, callback)
|
||
end
|
||
|
||
local function _playSkill(self, side, instruction, callback)
|
||
local actionTeam = self.atkTeam
|
||
if side == SIDE_DEF then
|
||
actionTeam = self.defTeam
|
||
end
|
||
actionTeam:useSkill(instruction.skillMatch, instruction.count, #self.instructions == 0, BattleConst.EFFECT_TYPE.DIRECT, BattleConst.ATTACK_ACTION_STATE.NORMAL, callback)
|
||
end
|
||
|
||
BattleBaseController._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,
|
||
}
|
||
|
||
function BattleBaseController:calExpectedInjury(mainElementType, count, skillId)
|
||
local atkCompMap = self:getCurActionTeam():getUnitComp()
|
||
if not atkCompMap then
|
||
return 0
|
||
end
|
||
local atkUnitComp = atkCompMap[mainElementType]
|
||
if mainElementType and not atkUnitComp then
|
||
return 0
|
||
end
|
||
if not mainElementType or not atkUnitComp then
|
||
count = 0
|
||
atkUnitComp = self:getCurActionTeam():getMainUnit()
|
||
end
|
||
local dmg = BattleFormula:getExpectedDamageResult(atkUnitComp, count, self:getCurOtherActionUnitComp(), skillId, atkCompMap)
|
||
return dmg
|
||
end
|
||
|
||
return BattleBaseController |