local Passive = require "adv.AdvPassive" local AdvCommon = require "adv.AdvCommon" local AdvMap = require "adv.AdvMap" local Buff = require "adv.AdvBuff" local Adv = class("Adv") local AdvTask = import(".AdvTask") --任务相关数据搞出去 AdvTask.bind(Adv) function Adv:ctor(owner) assert(owner, "Adv instance must have owner(role)") self.owner = owner self.maps = {} self.battle = nil self.backEvents = {} --发给客户端的事件组 self.advTask = self.owner:getProperty("advTask") self.advMTask = self.owner:getProperty("advMTask") self.advTaskChange = false -- 任务改变才更新 self:initByInfo(self.owner:getProperty("advInfo")) end --初始化adv 信息 function Adv:initByInfo(advInfo) if not next(advInfo) then return end --还没有 开始新地图 self.chapterId = advInfo.chapterId self.level = advInfo.level or 1 self.round = advInfo.round or 0 self.score = advInfo.score or {} self.lastEnemyId = advInfo.lastEId or 1 self.mapStack = advInfo.mstack or {} self.lchoose = advInfo.lch or {} self.waitArtifact = advInfo.waitAF self.cacheUnlock = advInfo.cacheUnlock or {} self.maps = {} for id, map in ipairs(advInfo.maps or {}) do self.maps[id] = AdvMap.new(self, id, map) end self:initBattle() end -- 随机新的地图 function Adv:initByChapter(chapterId, level, isToNext, notNotify) if not self.chapterId then -- 开始新的章节 self.chapterId = chapterId self:checkAchievement(Adv.AchievType.StartBattle, 1) elseif chapterId ~= self.chapterId then -- 正常不会出现 return end self.level = level or 1 self.round = 0 self.score = self.score or {} self.lastEnemyId = 1 self.mapStack = {1} -- 最后一个为当前的地图 self.lchoose = self.lchoose or {} self.cacheUnlock = self.cacheUnlock or {} -- 随机出地图 local mapId = self:randomMapId(chapterId, level) self.maps = {} self.maps[1] = AdvMap.new(self, 1, mapId) self:initBattle() self:initLayerTask() self:checkTask(Adv.TaskType.Arrive) self:checkAdvUnlock(1, self.level) if isToNext then self.battle.player:afterLayer() -- 玩家的buff 清理一下 self:scoreChange(AdvScoreType.Level) --增加层级加分 end if not notNotify then self:saveDB(notNotify) end end function Adv:clear() self.chapterId = nil self.level = nil self.score = {} self.round = 0 self.lastEnemyId = 1 self.mapStack = {} self.lchoose = {} self.maps = {} self.battle = nil self.waitArtifact = nil self.cacheUnlock = {} end function Adv:saveDB(notNotify) local advInfo, advTeam = {}, self.owner:getProperty("advTeam") if self.chapterId then advInfo.chapterId = self.chapterId advInfo.level = self.level advInfo.round = self.round advInfo.score = self.score advInfo.lastEId = self.lastEnemyId advInfo.mstack = self.mapStack advInfo.lch = self.lchoose advInfo.waitAF = self.waitArtifact advInfo.cacheUnlock = self.cacheUnlock advInfo.maps = {} self.battle:saveDB() for id , map in ipairs(self.maps) do advInfo.maps[id] = map:getDB() end advTeam.player = self.battle.player:getDB() else advTeam.player = nil end self:updateTask(notNotify) self:updateAchievement(notNotify) self.owner:updateProperties({advInfo = advInfo, advTeam = advTeam}, notNotify) end -- 1=抵达x层;2=通关x层;3=完成指定事件;4=完成指定连锁事件 function Adv:checkAdvUnlock(utype, value) if not self.chapterId then return end local chapter = self.chapterId % 100 local reward = {} for id, data in pairs(csvdb["adv_unlockCsv"]) do if data.chapterid == chapter and data.type == utype and value == data.value then --0=立即获得;1=结算时获得 if data.time == 0 then reward[data.itemid] = 1 elseif data.time == 1 then table.insert(self.cacheUnlock, data.itemid) end end end if next(reward) then self.owner:award(reward) end end function Adv:clearAdvUnlockCache() local reward = {} for _, itemId in ipairs(self.cacheUnlock) do reward[itemId] = 1 end if next(reward) then self.owner:award(reward) end self.cacheUnlock = {} end function Adv:initBattle() self.battle = require("adv.AdvBattle").new(self) for _, passiveC in ipairs(self.cachePassiveEvent or {}) do self.battle:triggerPassive(passiveC[1], passiveC[2]) end self.cachePassiveEvent = {} end function Adv:triggerPassive(condType, params) self.cachePassiveEvent = self.cachePassiveEvent or {} if not self.battle then table.insert(self.cachePassiveEvent, {condType, params}) else self.battle:triggerPassive(condType, params) end end function Adv:getCurMap() return self.maps[self.mapStack[#self.mapStack]] end function Adv:getCurMapIdx() return self.mapStack[#self.mapStack] end function Adv:getRoom(roomId, mapIdx) mapIdx = mapIdx or self:getCurMapIdx() local map = self.maps[mapIdx] if map then return map.rooms[roomId] end end function Adv:getBlock(roomId, blockId, mapIdx) local room = self:getRoom(roomId, mapIdx) if room then return room.blocks[blockId] end end function Adv:isHaveArtifact(id) return self.owner:getProperty("advAFGet")[id] end function Adv:awardArtifact(id, params) if self:isHaveArtifact(id) then return end self.owner:changeUpdates({{type = "advAFGet", field = id, value = 1}}, params.notNotify) self:pushBackEvent(AdvBackEventType.Artifact, {id = id}) end function Adv:delArtifactEffect(effect) for _, eff in ipairs(effect:toArray()) do local etype, id = table.unpack(eff:toArray(true, "=")) if etype == 1 then self.battle.player:addPassive({id = id}) elseif etype == 2 then self.battle.player:addBuff(id) end end end function Adv:addArtifactEffect(effect) for _, eff in ipairs(effect:toArray()) do local etype, id = table.unpack(eff:toArray(true, "=")) if etype == 1 then self.battle.player:delPassiveById(id) elseif etype == 2 then self.battle.player:delBuffById(id) end end end function Adv:wearArtifact(slot, id) local advAFGet = self.owner:getProperty("advAFGet") local advAFWear = self.owner:getProperty("advAFWear") local curWear = {} for _, _id in pairs(advAFWear) do curWear[_id] = 1 end if curWear[id] then return end if advAFWear[slot] then local oldData = csvdb["adv_artifactCsv"][advAFWear[slot]][advAFGet[advAFWear[slot]]] self:delArtifactEffect(oldData.effect) if oldData.comboId ~= 0 then local comboData = csvdb["adv_artifact_comboCsv"][oldData.comboId] if comboData then local isHaveCombo = true for _, _id in ipairs(comboData.artifactid:toArray(true)) do if not curWear[_id] then isHaveCombo = false break end end if isHaveCombo then self:delArtifactEffect(comboData.effect) end end end curWear[advAFWear[slot]] = nil end curWear[id] = 1 local newData = csvdb["adv_artifactCsv"][id][advAFGet[id]] self:addArtifactEffect(newData.effect) if newData.comboId ~= 0 then local comboData = csvdb["adv_artifact_comboCsv"][newData.comboId] if comboData then local isHaveCombo = true for _, _id in ipairs(comboData.artifactid:toArray(true)) do if not curWear[_id] then isHaveCombo = false break end end if isHaveCombo then self:addArtifactEffect(comboData.effect) end end end self.owner:changeUpdates({{type = "advAFWear", field = slot, value = id}}) return true end function Adv:artifactLevelUp(id) local advAFGet = self.owner:getProperty("advAFGet") local advAFWear = self.owner:getProperty("advAFWear") local status = 0 if advAFWear[id] then -- 穿着呢 local oldData = csvdb["adv_artifactCsv"][id][advAFGet[id]] local newData = csvdb["adv_artifactCsv"][id][advAFGet[id] + 1] self:delArtifactEffect(oldData.effect) self:addArtifactEffect(newData.effect) status = 1 end self.owner:changeUpdates({{type = "advAFGet", field = id, value = advAFGet[id] + 1}}) return status end function Adv:waitChooseArtifact() local chooses = {} local pool = {} local count = 3 --需要多少个 for id, temp in pairs(csvdb["adv_artifactCsv"]) do if not self:isHaveArtifact(id) and self.owner:isArtifactOpen(id, self:isEndless()) then table.insert(pool, id) end end if #pool == 0 then self:award({[ItemId.AdvPoint] = 48}) else for i = 1, math.min(count, #pool) do local idx = math.randomInt(1, #pool) table.insert(chooses, pool[idx]) table.remove(pool, idx) end self.waitArtifact = chooses self:backChooseArtifact() end end function Adv:isWaitChooseArtifact() return self.waitArtifact end function Adv:chooseArtifact(index) if not self.waitArtifact or not self.waitArtifact[index] then return end self:award({[self.waitArtifact[index]] = 1}) self.waitArtifact = nil return true end function Adv:isEndless() return AdvCommon.isEndless(self.chapterId) end function Adv:getCurFloorData() if not self.chapterId then return end local chapter = self.chapterId % 100 return (csvdb["adv_chapter_floorCsv"][chapter] or {})[self.level] end --关卡通关,非层 score < 0 失败 function Adv:over(success, isAllPass) local score = self:getScore() local scoreInfo = self.score local reward self.battle.player:triggerPassive(Passive.ADV_OVER, {score = score, level = self.level}) if success then reward = self.owner:award(self.owner:getProperty("advItems"):toNumMap()) self.owner:checkTaskEnter("AdvPass", {id = self.chapterId, level = self.level, score = score}) if isAllPass then self.owner:checkTaskEnter("AdvAllPass", {id = self.chapterId}) end -- 冒险队等级升一下子 self.owner:checkAdvLvByAddWin() end self:clearAdvUnlockCache() self:clear() self.owner:checkTaskEnter("AdvScore", {score = score}) self.owner:updateProperty({field = "advItems", value = ""}) self.owner:updateProperty({field = "advAFGet", value = {}}) self.owner:updateProperty({field = "advAFWear", value = {}}) self:backEnd(success, score, scoreInfo, reward) end function Adv:exit() self:over(false) self:saveDB() end function Adv:randomMapId(chapterId, level) local chapterData = csvdb["adv_chapterCsv"][chapterId] if not chapterData then error("chapterId " .. chapterId .. " dont exist!") return end if AdvCommon.isEndless(chapterId) then level = AdvCommon.getEndlessDataLv(chapterId, level) else if level > chapterData.limitlevel then error("level overflow!") return end end --随出地图Id local raw_pool = chapterData.mapid:toArray(true, "=") local lastMapIds = {} for id, map in ipairs(self.maps or {}) do lastMapIds[map.mapId] = 1 end local pool = {} for _, mapId in ipairs(raw_pool) do local temp = csvdb["mapCsv"][mapId] if temp and not lastMapIds[mapId] then if AdvCommon.checkIsIn(level, temp.leveltype, temp.levellimit) then table.insert(pool, mapId) end end end if not next(pool) then error("mapIds is empty!") return end return pool[math.randomInt(1, #pool)] end -- 在冒险中获得的物品都发放在冒险背包内 function Adv:award(gift, params) params = params or {} local tgift = {} if type(gift) == "string" then for _, one in pairs(gift:toTableArray(true)) do tgift[one[1]] = (tgift[one[1]] or 0) + one[2] end else tgift = gift end local items = self.owner:getProperty("advItems") local oldItems = items for itemId, count in pairs(tgift) do if count > 0 then local buffAdd = self.battle.player:getRewardChange(itemId) count = math.floor(math.max(0, (count + buffAdd[0]) * (1 + buffAdd[1]))) --附加 buff 的影响 self:scoreChange(AdvScoreType.Item, {itemId, count}) self:checkTask(Adv.TaskType.Item, count, itemId) self:checkAchievement(Adv.AchievType.GetItem, count, itemId) end tgift[itemId] = count local origin = items:getv(itemId, 0) local nums = origin + count if csvdb["adv_artifactCsv"][itemId] then -- 获得神器 self:awardArtifact(itemId, params) else if nums <= 0 then items = items:delk(itemId) nums = 0 else items = items:setv(itemId, nums) end end end if items ~= oldItems then self.owner:updateProperty({field = "advItems", value = items, notNotify = params.notNotify}) end return tgift end -- 消耗物品 优先冒险背包 --check 只是检查够不够 function Adv:cost(item, params, check) local items = self.owner:getProperty("advItems") local less = {} local advCost = {} for itemId, count in pairs(item) do advCost[itemId] = - math.min(items:getv(itemId, 0), count) if advCost[itemId] == 0 then advCost[itemId] = nil end local last = items:getv(itemId, 0) - count if last < 0 then less[itemId] = -last end end if next(less) and not self.owner:checkItemEnough(less) then return end --不够 if check then return true end self:award(advCost, params) if next(less) then self.owner:costItems(less, params) end return true end --事件点击处理 local function clickOut(self, room, block, params) if self:getCurMap():checkOver() then --检查是否可以出去了 if #self.mapStack > 1 then -- 处于夹层中 table.remove(self.mapStack) --退出夹层 self:backLayer(-1) else --处于底层 local advPass = self.owner:getProperty("advPass") if self:isEndless() then -- 刷新最高层 if self.owner:getProperty("advElM") < self.level then self.owner:updateProperty({field = "advElM", value = self.level}) end else if self.level > (advPass[self.chapterId] or 0) then self.owner:changeUpdates({{type = "advPass", field = self.chapterId, value = self.level}}) end end if params.relay then if self.level % globalCsv.adv_can_out_layer_pre ~= 0 or not self.owner:isFuncOpen(FuncOpenType.AdvRelay) then return end end self:checkAchievement(Adv.AchievType.OverWin, 1, self.level) self:checkAdvUnlock(2, self.level) local levellimit = csvdb["adv_chapterCsv"][self.chapterId].limitlevel if params.relay or (not self:isEndless() and (self.level >= levellimit or not self.owner:advChapterIsOpen(self.chapterId, self.level + 1))) then --关卡结束 self:over(true, not self:isEndless() and self.level >= levellimit) else self.battle.player:triggerPassive(Passive.DOWN_LAYER) local curFloorData = self:getCurFloorData() if curFloorData then self:backReward(self:award({[ItemId.AdvPoint] = curFloorData.exp})) end self:initByChapter(self.chapterId, self.level + 1, true, true) self:backNext() --下一关 end end return true end end --战斗 普通攻击 local function clickMonster(self, room, block, params) self.battle:battleBegin(room.roomId, block.blockId, params) return true end local function chooseCommon(self, room, block, chooseData, choose, tag) if not chooseData or not chooseData["button".. choose .."cond"] then return end local cond = chooseData["button".. choose .."cond"]:toArray(true, "=") local checkCond = { -- 没有条件 [0] = function() return true end, -- 拥有道具 [1] = function() if self:cost({[cond[2]] = cond[3]}, {}, true) then return true end end, -- xx角色(todo 队长) [2] = function() local hero = self.owner.heros[self.owner:getProperty("advTeam").leader] if hero and hero:getProperty("type") == cond[2] then return true end end, --消灭所有怪 [3] = function() for _, room in pairs(self:getCurMap().rooms) do for _, block in pairs(room.blocks) do if block:isMonster() then return end end end return true end, --制定属性 [4] = function() if (self.battle.player[AttsEnumEx[cond[2]]] or 0) >= cond[3] then return true end end, -- 提交一个物品 [5] = function () if self:cost({[cond[2]] = cond[3]}, {}) then self:backCost({[cond[2]] = cond[3]}) return true end end, -- sp 到达指定值 [6] = function() if self.battle.player.sp >= cond[2] then return true end end, [7] = function() local buff = self.battle.player:getBuffById(cond[2]) if buff and buff:getLayer() >= cond[3] then return true end end, [8] = function() return self:isHaveArtifact(cond[2]) end } assert(not cond[1] or checkCond[cond[1]], "error cond, event_" .. (tag or "choose") .. "Csv id :" .. block.event.id) if cond[1] and not checkCond[cond[1]]() then return end local clearBlock = chooseData.keep ~= 1 local effects = chooseData["button".. choose .."effect"]:toTableArray(true) for _, effect in ipairs(effects) do local doEffect = { [1] = function() -- 获得某道具N个 local count = effect[3] or 1 local reward = {} for i = 1, count do local item = csvdb["event_dropCsv"][effect[2]]["range"]:randWeight(true) reward[item[1]] = (reward[item[1]] or 0) + item[2] end self:backReward(self:award(reward, {})) end, [2] = function() --获得冒险buff local layer = effect[3] or 1 for i = 1, layer do self.battle.player:addBuff(effect[2]) end end, [3] = function() --发现怪物 self:getCurMap():addNewMonsterRand(effect[2], {room, block}) clearBlock = false end, [4] = function() --无事发生 end, [5] = function() --5=属性枚举=数值;直接增加玩家属性 local attr if effect[3] == 0 then attr = "sp" else attr = AttsEnumEx[effect[3]] if not AdvAttsEnum[attr] then return end end self.battle.player:addBaseAttr(attr, effect[4], effect[2]) end, [6] = function() -- 商店 block:updateEvent({ etype = AdvEventType.Trader, id = effect[2] }) block:randomEvent() clearBlock = false end, [7] = function() -- 建筑 block:updateEvent({ etype = AdvEventType.Build, id = effect[2] }) block:randomEvent() clearBlock = false end, [8] = function() -- 选择 block:updateEvent({ etype = AdvEventType.Choose, id = effect[2] }) block:randomEvent() clearBlock = false end, [9] = function() -- click block:updateEvent({ etype = AdvEventType.Click, id = effect[2] }) block:randomEvent() clearBlock = false end, [10] = function() -- 陷阱 block:updateEvent({ etype = AdvEventType.Trap, id = effect[2] }) block:randomEvent() clearBlock = false end, [11] = function() -- 获得神器 self:waitChooseArtifact() --等待获取神器 end } assert(doEffect[effect[1]], "error effect, event_" .. (tag or "choose") .. "Csv id :" .. block.event.id) doEffect[effect[1]]() end return true, clearBlock end local function clickChoose(self, room, block, params) local choose = params.choose local chooseData = csvdb["event_chooseCsv"][block.event.id] local status, clearBlock = chooseCommon(self, room, block, chooseData, choose, "choose") if not status then return end self:checkAdvUnlock(3, block.event.id) self:checkTask(Adv.TaskType.Choose, 1, block.event.id) self:checkAchievement(Adv.AchievType.Choose, 1, block.event.id) if clearBlock then block:clear() end return true end local function clickLinkChoose(self, room, block, params) local choose = params.choose local chooseData = csvdb["event_linkchooseCsv"][block.event.id] local status, clearBlock = chooseCommon(self, room, block, chooseData, choose, "link") if not status then return end -- 完成统计次数 local idx = block.event.id % 10 if idx == 9 or not csvdb["event_linkchooseCsv"][block.event.id + 1] then --全部完成 local startId = math.floor(block.event.id / 10) * 10 + 1 self.lchoose[startId] = (self.lchoose[startId] or 0) + 1 self:checkAchievement(Adv.AchievType.LinkChoose, 1, startId) self:checkAdvUnlock(4, startId) else self.lchoose.ing = block.event.id + 1 --后面会出现后继事件 end if clearBlock then block:clear() end return true end local function clickDrop(self, room, block, params) local reward = {} if not block.event.item then return end self.battle.player:triggerPassive(Passive.CLICK_DROP) local reward = self:award({[block.event.item[1]] = block.event.item[2]}) -- local reward = self:award({[5801] = 1}) block:clear() self:backReward(reward) return true end local function clickTrader(self, room, block, params) local buyId = params.id local traderData = csvdb["event_traderCsv"][block.event.id] if not traderData then return end -- 偷偷改表了 if not block.event.shop or not block.event.shop[buyId] then return end if (block.event.status or ""):getv(buyId, 0) == 1 then return end -- 买过了 if not self:cost({[traderData.type] = block.event.shop[buyId][3]}, {}) then return end --不够 self:backCost({[traderData.type] = block.event.shop[buyId][3]}) local reward = self:award({[block.event.shop[buyId][1]] = block.event.shop[buyId][2]}) block.event.status = block.event.status:setv(buyId, 1) self:checkTask(Adv.TaskType.Shop, 1, block.event.id) self:checkAchievement(Adv.AchievType.Shop, 1, block.event.id) self:backReward(reward) return true end local function clickBuild(self, room, block, params) local choose = params.choose local chooseData = csvdb["event_buildingCsv"][block.event.id] local status, clearBlock = chooseCommon(self, room, block, chooseData, choose, "build") if not status then return end self:checkTask(Adv.TaskType.Build, 1, block.event.id) self:checkAchievement(Adv.AchievType.Build, 1, block.event.id) if clearBlock then block:clear() end return true end local function clickClick(self, room, block, params) local clickData = csvdb["event_clickCsv"][block.event.id] if not clickData then return end local clearBlock = true local doEffect = { [1] = function() -- 技能 for _, skillId in ipairs(clickData.effect:toArray(true, "=")) do self.battle.player:releaseSkill(skillId) end end, [2] = function() -- dropId local reward = {} for _, dropId in ipairs(clickData.effect:toArray(true, "=")) do local item = csvdb["event_dropCsv"][dropId]["range"]:randWeight(true) reward[item[1]] = (reward[item[1]] or 0) + item[2] end self:backReward(self:award(reward, {})) end, } assert(doEffect[clickData.type], "error effect, event_clickCsv id :" .. block.event.id) doEffect[clickData.type]() if clearBlock then block:clear() end return true end local function clickLayer(self, room, block, params) if block.event.mapIdx then table.insert(self.mapStack, block.event.mapIdx) --进入夹层 else --生成夹层 local mapId = csvdb["event_layerCsv"][block.event.id].effect local mapIdx = #self.maps + 1 block.event.mapIdx = mapIdx table.insert(self.mapStack, mapIdx) self.maps[mapIdx] = AdvMap.new(self, mapIdx, mapId) self.battle:initMapEnemys(mapIdx) self:checkAchievement(Adv.AchievType.EnterILayer, 1, mapId) end self:backLayer(1) return true end local function clickTask(self, room, block, params) if self:addTask(block.event.id) then --增加任务 block:clear() return true end end local eventCallFunc = { [AdvEventType.Out] = clickOut, [AdvEventType.BOSS] = clickMonster, [AdvEventType.Monster] = clickMonster, [AdvEventType.Choose] = clickChoose, [AdvEventType.LinkChoose] = clickLinkChoose, [AdvEventType.Drop] = clickDrop, [AdvEventType.Trader] = clickTrader, [AdvEventType.Build] = clickBuild, [AdvEventType.Click] = clickClick, [AdvEventType.Layer] = clickLayer, [AdvEventType.Task] = clickTask, } --点击处理 roomId, blockId --params 某些事件需要的客户端传递的参数 function Adv:clickBlock(roomId, blockId, params) local map = self:getCurMap() local room = self:getRoom(roomId) local block = self:getBlock(roomId, blockId) if not block then return end local status = false local clickEvent = false if not block.isOpen then local canOpen = false --如果未开放是否可以开放 local hadMonster = false -- 周围是否有解锁的怪未击败 for _, one in ipairs(map:getAroundBlocks(room, block)) do local _room, _block = one[1], one[2] if _block.isOpen then canOpen = true end if _block.isOpen and _block:isMonster() then local enemy = self.battle:getEnemy(_room.roomId, _block.blockId) if not enemy:hadBuff(Buff.DONT_DEFEND) then hadMonster = true end end end if canOpen and not hadMonster then --开放 self:getCurMap():openBlock(roomId, blockId, true, true) status = true end else clickEvent = true --点了空地 if not block.event then return end --可点击的事件 if not room.isBossRoom or block:isBoss() then if eventCallFunc[block.event.etype] then status = eventCallFunc[block:getEventType()](self, room, block, params) end end end local needChange = true if clickEvent and block.event then if block:getEventType() == AdvEventType.Out then needChange = false end end if status and needChange then --出去了就不计算回合了 self:backBlockChange(roomId, blockId) self:afterRound() end self:saveDB() return status end function Adv:doActive(activeId, target) local activeData = csvdb["adv_activeCsv"][activeId] if not activeData then return end local targers = {} -- 筛选对象 if activeData.usetype == 1 then -- 自己 elseif activeData.usetype == 2 then -- 敌人 if not target or not target.roomId or not target.blockId then return end local block = self:getBlock(target.roomId, target.blockId) if block:isBoss() then return end local enemy = self.battle:getEnemy(target.roomId, target.blockId) if not enemy then return end local blocks = self:getCurMap():getBlocksBySize(target.roomId, target.blockId, activeData.scope) for _, block in pairs(blocks) do if block:isMonster() and not block:isBoss() then local e = self.battle:getEnemy(block.room.roomId, block.blockId) if e then table.insert(targers, e) end end end elseif activeData.usetype == 3 then -- 地板 if not target or not target.roomId or not target.blockId then return end local block = self:getBlock(target.roomId, target.blockId) if block:isBoss() then return end local blocks = self:getCurMap():getBlocksBySize(target.roomId, target.blockId, activeData.scope) for _, block in pairs(blocks) do if not block:isBoss() then table.insert(targers, block) end end elseif activeData.usetype == 4 then -- 没有目标 全体成员 elseif activeData.usetype == 5 then -- 空地板 if not target or not target.roomId or not target.blockId then return end local block = self:getBlock(target.roomId, target.blockId) if not block.isOpen or block:getEventType() then return end local blocks = self:getCurMap():getBlocksBySize(target.roomId, target.blockId, activeData.scope) for _, block in pairs(blocks) do if not block:isBoss() then table.insert(targers, block) end end end local doActiveEffect = {} -- 1=map_buff_id:为范围内所有目标附加mapbuff doActiveEffect[1] = function(_, buffId) if not next(targers) then if activeData.usetype == 1 then table.insert(targers, self.battle.player) elseif activeData.usetype == 4 then targers = self.battle.player:getTeam(2) else return end end for _, target in ipairs(targers) do if target.class.__cname == "AdvBlock" then target = self.battle:getEnemy(target.room.roomId, target.blockId) end if target then target:addBuff(buffId, self.battle.player) end end return true end -- 2=trader_id:召唤商人 doActiveEffect[2] = function(_, traderId) for _, target in ipairs(targers) do if target.isOpen and not target:getEventType() then target:updateEvent({ etype = AdvEventType.Trader, id = traderId, }) target:randomEvent() self:backBlockChange(target.room.roomId, target.blockId) end end return true end -- 3=monster_id:替换怪物,仅使用方式为2时生效 doActiveEffect[3] = function(_, monsterId) for _, target in ipairs(targers) do if not target.lock and not target.isDead then self.battle:removeEnemyById(target.id) self:getCurMap():addNewMonsterRand(monsterId, {self:getRoom(target.roomId), self:getBlock(target.roomId, target.blockId)}) self:backBlockChange(target.roomId, target.blockId) end end return true end -- 4:显示本层 doActiveEffect[4] = function(_) self:getCurMap():showMap() self:backMapShow() return true end -- 5:放逐目标 doActiveEffect[5] = function(_) for _, target in ipairs(targers) do if not target.lock and not target.isDead then self.battle:removeEnemyById(target.id) local block = self:getBlock(target.roomId, target.blockId) block:clear() self:backBlockChange(target.roomId, target.blockId) end end return true end -- 6=陷阱id:移除陷阱,不填写id则移除所有陷阱 doActiveEffect[6] = function(_, trapId) if not next(targers) and activeData.usetype == 4 then -- 全屏 for _, room in pairs(self:getCurMap().rooms) do for _, block in pairs(room.blocks) do if block:getEventType() == AdvEventType.Trap then block:updateEvent(nil) self:backBlockChange(block.room.roomId, block.blockId) end end end else for _ , target in ipairs(targers) do if target:getEventType() == AdvEventType.Trap then target:updateEvent(nil) self:backBlockChange(target.room.roomId, target.blockId) end end end return true end -- 7=道具燃烧效果 doActiveEffect[7] = function(_) for _ , target in ipairs(targers) do if target:getEventType() == AdvEventType.Drop then target:updateEvent(nil) self:backBlockChange(target.room.roomId, target.blockId) end end return true end -- 8:翻开范围内的方格 doActiveEffect[8] = function(_) for _ , target in ipairs(targers) do if not target.isOpen then target:open() self:backBlockChange(target.room.roomId, target.blockId) end end return true end -- 9: 给玩家增加buff doActiveEffect[9] = function(_, buffId) self.battle.player:addBuff(buffId, self.battle.player) return true end for _, effect in ipairs(activeData.effect:toArray()) do local cur = effect:toArray(true, "=") if doActiveEffect[cur[1]] then if not doActiveEffect[cur[1]](table.unpack(cur)) then return end end end return true end -- 地图上物品变化 function Adv:mapItemChange(ctype) local clist = csvdb["transform_itemCsv"][ctype] if clist then for roomId, room in pairs(self:getCurMap().rooms) do for blockId, block in pairs(room.blocks) do if block:getEventType() == AdvEventType.Drop and block.event.item then local id = block.event.item[1] local changeTo = nil if clist[id] then changeTo = {clist[id].toId, clist[id].num} elseif clist[-1] then changeTo = {clist[-1].toId, clist[-1].num} end if changeTo and changeTo[1] ~= 0 and changeTo[2] ~= 0 then block.event.item = changeTo self:backBlockChange(roomId, blockId) end end end end end end --敌人死亡 function Adv:enemyDead(enemy, escape) local roomId, blockId = enemy.roomId, enemy.blockId local map = self:getCurMap() local room = self:getRoom(roomId) local block = self:getBlock(roomId, blockId) if not block then return end --死了以后掉东西 if block:isMonster() then --处理死亡 if block:isBoss() then room.isBossRoom = false end if escape then block:clear() else local enemyId = block.event.id local monsterData = csvdb["event_monsterCsv"][enemyId] self:scoreChange(AdvScoreType.Kill, monsterData.type) local changeV = self.battle.player:addExp(monsterData.exp) self:backDead(enemyId, changeV) if enemy:hadBuff(Buff.CHANGE_DROP_TO_CLICK) then -- 掉落转为 click local clickId = buff:effect() block:updateEvent({ etype = AdvEventType.Click, id = clickId }) self.battle.player:triggerPassive(Passive.BATTLE_WIN) else local item = block.event.item if not item then local buff = enemy:hadBuff(Buff.CHANGE_DROP) if buff then item = table.pack(buff:effect()) else local dropData = csvdb["event_dropCsv"][monsterData.dropid] item = dropData["range"]:randWeight(true) end end if item[1] == 0 then block:clear() self.battle.player:triggerPassive(Passive.BATTLE_WIN) else block:updateEvent({ etype = AdvEventType.Drop, item = item }) self.battle.player:triggerPassive(Passive.BATTLE_WIN, {count = item[2]}) end end self:checkTask(Adv.TaskType.Kill, 1, enemyId) self:checkTask(Adv.TaskType.KillAll) self:checkAchievement(Adv.AchievType.Kill, 1, enemyId) end end self:backBlockChange(roomId, blockId) end function Adv:pushBackEvent(btype, params) table.insert(self.backEvents, {btype = btype, params = params}) end function Adv:backReward(items) self:pushBackEvent(AdvBackEventType.Reward, {items = items}) end -- if is player enemyId is nil --isMax 是否是改变血量上限 function Adv:backHpChange(enemyId, change, isMax) self:pushBackEvent(AdvBackEventType.HpChange, {enemyId = enemyId, change = change, isMax = isMax}) end -- if is player enemyId is nil function Adv:backAtkChange(enemyId, change) self:pushBackEvent(AdvBackEventType.AtkChange, {enemyId = enemyId, change = change}) end -- if is player enemyId is nil function Adv:backDefChange(enemyId, change) self:pushBackEvent(AdvBackEventType.DefChange, {enemyId = enemyId, change = change}) end -- if is player enemyId is nil function Adv:backBuff(enemyId, buffId, isDel) self:pushBackEvent(AdvBackEventType.Buff, {enemyId = enemyId, buffId = buffId, isDel = isDel}) end -- if is player enemyId is nil function Adv:backSkill(enemyId, skillId, receiver) self:pushBackEvent(AdvBackEventType.Skill, {enemyId = enemyId, skillId = skillId, receiver = receiver}) end -- if is player enemyId is nil function Adv:backPassive(enemyId, passiveId) self:pushBackEvent(AdvBackEventType.Passive, {enemyId = enemyId, passiveId = passiveId}) end function Adv:backNext() self:pushBackEvent(AdvBackEventType.Next, {}) end function Adv:backEnd(success, score, scoreInfo, reward) self:pushBackEvent(AdvBackEventType.End, {success = success, score = score, scoreInfo = scoreInfo, reward = reward}) end function Adv:backBlockChange(roomId, blockId) self:pushBackEvent(AdvBackEventType.BlockChange, {roomId = roomId, blockId = blockId}) end function Adv:backDead(enemyId, exp) self:pushBackEvent(AdvBackEventType.Dead, {enemyId = enemyId, exp = exp}) end function Adv:backTrap() self:pushBackEvent(AdvBackEventType.Trap, {}) end function Adv:backLayer(status) self:pushBackEvent(AdvBackEventType.Layer, {status = status}) end function Adv:backMapShow() self:pushBackEvent(AdvBackEventType.MapShow, {}) end function Adv:backChooseArtifact() self:pushBackEvent(AdvBackEventType.ChooseArtifact, {}) end function Adv:backCost(items) self:pushBackEvent(AdvBackEventType.Cost, {items = items}) end function Adv:backUse(items) self:pushBackEvent(AdvBackEventType.Use, {items = items}) end function Adv:scoreChange(scoreType, pms) local cutTypes = {} local score = 0 cutTypes[AdvScoreType.Level] = function() score = globalCsv.adv_score_floor end cutTypes[AdvScoreType.Kill] = function() local chapterData = csvdb["adv_chapterCsv"][self.chapterId] score = globalCsv.adv_score_monster[pms] * chapterData["reward"] end cutTypes[AdvScoreType.Item] = function() score = csvdb["itemCsv"][pms[1]].adv_score_item * pms[2] end cutTypes[AdvScoreType.Hurt] = function() score = globalCsv.adv_score_hurt * pms end cutTypes[AdvScoreType.Block] = function() score = globalCsv.adv_score_block end if cutTypes[scoreType] then cutTypes[scoreType]() else return end self.score[scoreType] = self.score[scoreType] or 0 self.score[scoreType] = self.score[scoreType] + score end function Adv:getScore() self.score[AdvScoreType.Level] = math.floor(self.score[AdvScoreType.Level] or 0) self.score[AdvScoreType.Block] = math.floor(self.score[AdvScoreType.Block] or 0) self.score[AdvScoreType.Hurt] = math.max(math.floor(self.score[AdvScoreType.Hurt] or 0), - (self.score[AdvScoreType.Level] + self.score[AdvScoreType.Block])) self.score[AdvScoreType.Kill] = math.floor(self.score[AdvScoreType.Kill] or 0) self.score[AdvScoreType.Item] = math.floor(self.score[AdvScoreType.Item] or 0) return self.score[AdvScoreType.Level] + self.score[AdvScoreType.Block] + self.score[AdvScoreType.Hurt] + self.score[AdvScoreType.Kill] + self.score[AdvScoreType.Item] end function Adv:popBackEvents() local events = self.backEvents self.backEvents = {} return events end --回合事件处理 function Adv:afterRound() self.round = self.round + 1 if self.battle then self.battle:afterRound() end end return Adv