c1_lua/lua/app/module/battle/controller/battle_base_controller.lua
2023-08-03 09:47:21 +08:00

3085 lines
108 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 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.waveIndex)
end
-- 战斗结束
function BattleBaseController:controllBattleEnd()
end
-- 不同模块的战斗需要初始化的东西
function BattleBaseController:initOther()
end
-- 怪物攻击力加成
function BattleBaseController:getMonsterAtkAddition()
return 0
end
-- 怪物血量加成
function BattleBaseController:getMonsterHpAddition()
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:generateNextMonster()
local config = self:getChapterConfig()[self.chapterId]
local monsterId = config.monster[self.waveIndex + 1]
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.battleUI: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.battleUI: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()
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 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
for posId, info in pairs(self.battleData:getSkillInfluenceGrids()) do
local entity = self.battleData:getGridEntity(posId)
if info.direction ~= BattleConst.BOARD_RANGE_TYPE.RANDOM then
if entity:getCell() then
entity:getCell():showCircle(true)
end
end
end
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
self.battleUI:refreshSkill(elementTypeMap, count > 0, self.curActionSide)
end
if mainElementType then
self:getSideTeam(self.curActionSide):changeMainUnit(mainElementType)
end
local elementTypeCount = 0
for element, count in pairs(dmgElementTypeMap) do
elementTypeCount = elementTypeCount + count
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)})
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.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 config = self:getChapterConfig()[self.chapterId]
local initIndex = self.waveIndex
if self.waveIndex <= 0 then
initIndex = 1
end
local unitEntity = self.battleData:addMonster(config.monster[initIndex], 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:_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()
if self.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, self.waveIndex)
end
if self.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 self.waveIndex ~= 0 then -- 第一波
self:postWaveOver(false)
end
self.curWaveMonsterDead = false
self.waveIndex = self.waveIndex + 1
self:refreshWave(self.waveIndex)
if self.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.waveIndex)
self.needWaitingBoardOver = true
self:generateBoard(true, snapShot.boardSnapInfo)
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:hideTouchCancel()
self:resetSideActionCount()
self:setCurActionSide(SIDE_ATK)
self.needWaitingBoardOver = nil
self.waveRoundCount[self.waveIndex] = (self.waveRoundCount[self.waveIndex] or 0) + 1
self.battleUI:enterShowBoardAni(function()
self:takeGridEffect()
self:enterEliminationBegin()
end)
table.clear(self.lastRoundBreakedGridType)
end
function BattleBaseController:takeGridEffect()
local gridEntities = self.battleData:getGridEnties()
local effectGrid = {}
for posId, entity in pairs(gridEntities) do
if entity:getEffectType() then
table.insert(effectGrid, entity)
end
end
effectGrid = table.shuffle(effectGrid)
local availableEffectTypeMap
for _, entity in ipairs(effectGrid) do
local effectType = entity:getEffectType()
if 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
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
end
end
end
end
function BattleBaseController:enterEliminationBegin()
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_BEGIN
self:enterRefreshBoard(true)
end
function BattleBaseController:enterElimination(needDelay)
if self.showSelectSkillSid then
ModuleManager.BattleManager:unscheduleGlobal(self.showSelectSkillSid)
self.showSelectSkillSid = nil
end
if self.battleData:useAddlvCount() then
self:tryShowSelectSkillComp(needDelay)
return
end
self.battleUI:hideAllBoardSfxs()
-- 检查棋盘
local find, pathList = self:findAttention()
if not find then -- 如果没找到,就要打乱棋盘
self:shuffleBoard(function()
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_ELIMINATION
end)
else
self.attentionList = pathList
-- ModuleManager.BattleManager:performWithDelayGlobal(function()
-- for _, posId in ipairs(pathList) do
-- local entity = self.battleData:getGridEntity(posId)
-- if entity and entity:getCell() then
-- entity:getCell():showAni()
-- end
-- end
-- end, 2)
self.roundStep = BattleConst.BATTLE_ROUND_STEP.ON_ELIMINATION
end
end
function 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()
if self:checkTeamIsDead(function() self:enterRoundEnd() end) then
return
end
if not self.battleTeamActionList or not self.battleTeamActionList[1] then
self:enterRoundEnd()
return
end
local action = table.remove(self.battleTeamActionList, 1)
action()
end
function BattleBaseController:checkTeamIsDead(callback)
local defTeam = self.battleData:getDefTeam()
if not defTeam or defTeam:getIsDead() then -- 怪物死了, 直接进入刷新逻辑
self.curWaveMonsterDead = true
self:onDefDead(function()
self.defTeam:removeAllBuff()
if self.battleData:getDefTeam():getIsDead() then
if self.waveIndex >= self.maxWaveIndex then
if callback() then
callback()
end
else
self:_findNextDefUnit()
end
else
if callback() then
callback()
end
end
end)
return true
end
local atkTeam = self.battleData:getAtkTeam()
if not atkTeam or atkTeam:getIsDead() then -- 英雄死了, 直接结算
self:enterNextWave()
return true
end
return false
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()
if self:checkTeamIsDead(function() self:enterNextWave() end) then
return
end
self:onRoundEnd()
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
local aniSequence, influenceElementTypeMap, lineCount, elementTypeMap, linkElementType, effectGridMap = self:calculateCurElimination()
if not self:getCurActionUnitComp():getActiveSkillLimit() then
self:addSkillEnergy(elementTypeMap)
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)
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()
self.lastRoundBreakedGridType[entity:getGridType()] = true
entity:tryBreakGrid(condition)
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
self:dealGridBreak(id, GRID_BREAK_CONDITION.AROUND, time, breakedMap, sequenceMap, aniSequence, gridMap, onlyCheck)
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())
end
end
end
end
return isIdle
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)
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.waveIndex)
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]
ModuleManager.BattleManager:showBoxOpenUI(rewards, function()
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()
self:enterElimination(true)
if self.onFillBoardOverCallback then
local callback = self.onFillBoardOverCallback
self.onFillBoardOverCallback = nil
callback()
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 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
self.battleUI:switchBoard(function()
self.battleData:refreshBoard(board, 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 -- 第一排
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 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
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 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)
side = side or self:getCurActionSide()
self:dealSelectSkill(skillId, value, side)
BIReport:postFightSkillSelect(self.battleType, self.battleData, {skillId}, self.chapterId, self.totalDurationTime, self.waveIndex)
local elementType = ModuleManager.HeroManager:getSkillRoguePosition(skillId)
if elementType then
if self.battleUI then
self.battleUI:gotOneSkillAni(skillId, elementType, function()
self:selectSKillNextToStep()
self.battleUI:refreshBoard()
self.battleUI:refreshSkill(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: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() 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() 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] 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] 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
-- 处理战斗任务
if self.victory then
self:setTaskProgress(GConst.BattleConst.BATTLE_TASK_FIELD.KILLS_BOSS_TURN, self.waveRoundCount[self.waveIndex])
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
totalRound = totalRound + round
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 not atkUnitComp then
return 0
end
local dmg = BattleFormula:getExpectedDamageResult(atkUnitComp, count, self:getCurOtherActionUnitComp(), skillId, atkCompMap)
return dmg
end
return BattleBaseController