local Room = require "adv.AdvRoom" local Passive = require "adv.AdvPassive" local AdvCommon = require "adv.AdvCommon" -- 一层地图 local Map = class("AdvMap") -- 内部方法声明 local createMap, getEventLib function Map:ctor(adv, mapIdx, mapInfo) self.adv = adv if type(mapInfo) == "number" then -- mapInfo 传入 id mapInfo = createMap(self, mapInfo) -- 生成地图 end if not mapInfo then return end self.mapIdx = mapIdx self.mapId = mapInfo.mapId self.rooms = {} self:loadRooms(mapInfo.rooms) end function Map:loadRooms(rooms) local mapData = csvdb["map_" .. csvdb["mapCsv"][self.mapId]["path"] .. "Csv"] for roomId, roomName in pairs(mapData["rooms"]) do if roomName == "path" then self.rooms[roomId] = Room.new(self, roomId, mapData["path"], rooms[roomId], true) else roomName = roomName:gsub("/", "_") self.rooms[roomId] = Room.new(self, roomId, csvdb["room_" .. roomName .. "Csv"], rooms[roomId], false) end end end function Map:getDB() local map = {} map.mapId = self.mapId map.rooms = {} for roomId, room in pairs(self.rooms) do map.rooms[roomId] = room:getDB() end return map end --结束本层的时候调用 function Map:checkOver() local mapCsv = csvdb["mapCsv"][self.mapId] if mapCsv.clearType == 1 then -- 消耗 if self.adv:cost(mapCsv.clear:toNumMap()) then return true end elseif mapCsv.clearType == 2 then -- 杀光 if #self.adv.battle.player:getTeam(2) == 0 then return true end elseif mapCsv.clearType == 3 then -- 持有 if self.adv:cost(mapCsv.clear:toNumMap(), {}, true) then return true end else return true end end --随机一个空的位置生成怪, 如果没有就没有 function Map:addNewMonsterRand(monsterId, where) local room, block if where then room, block = where[1], where[2] else local pool = {} for _, room_ in pairs(self.rooms) do for _, block_ in pairs(room_.blocks) do if block_.isOpen and not block_.event then table.insert(pool, {room_, block_}) end end end if not next(pool) then return end local idx = math.randomInt(1, #pool) room, block = pool[idx][1], pool[idx][2] end if not monsterId then local eventLib = getEventLib(self, AdvEventType.Monster) if not next(eventLib[AdvEventType.Monster][0]) then return false end monsterId = math.randWeight(eventLib[AdvEventType.Monster][0], "showup") end local event = {etype = AdvEventType.Monster, mId = self.adv.lastEnemyId} self.adv.lastEnemyId = self.adv.lastEnemyId + 1 event.id = monsterId block:updateEvent(event) self.adv.battle:addEnemy(room, block):triggerPassive(Passive.BORN_ONCE) return room, block end -- 随机翻开 num 个 以开放的房间的 地块 function Map:openBlockRand(num) local pool = {} for _, room in pairs(self.rooms) do if room.isShow and not room.isPath then for _, block in pairs(room.blocks) do if not block.isOpen then table.insert(pool, {room.roomId, block.blockId}) end end end end if #pool <= num then for _, temp in ipairs(pool) do self:openBlock(temp[1], temp[2]) end else for i = 1, num do local idx = math.randomInt(1, #pool) self:openBlock(pool[idx][1], pool[idx][2]) table.remove(pool, idx) end end end -- 打开一个地块 function Map:openBlock(roomId, blockId) local room = self.rooms[roomId] if not room then return end local block = room.blocks[blockId] if not block then return end room:openBlock(block, self) self:backBlockChange(roomId, blockId) end --获取,某个位置上的 room 和 block function Map:getRBByPos(c, r) for roomId, room in pairs(self.rooms) do local block = room:getBByGPos(c, r) if block then return room, block end end end function Map:getAroundBlocks(room, block) local blocks = {} local range = {1, -1} local col, row = room:tranLtoG(block.col, block.row) for _, add in ipairs(range) do local rroom, rblock = self:getRBByPos(col + add, row) if rroom then table.insert(blocks, {rroom, rblock}) end end for _, add in ipairs(range) do local rroom, rblock = self:getRBByPos(col, row + add) if rroom then table.insert(blocks, {rroom, rblock}) end end return blocks end -----------------------------随机地图----------------------------- createMap = function(self, mapId) local mapInfo = {} mapInfo.rooms = {} mapInfo.mapId = mapId local mapCsvData =csvdb["mapCsv"][mapId] local mapData = csvdb["map_" .. mapCsvData["path"] .. "Csv"] if not mapData then error("mapId " .. mapId .. " dont exist!") return end --事件随机 local eventLib = getEventLib(self) -- 同时记录出现次数 local monsterEvents = {} --处理钥匙掉落 local haveBoss = false local haveLChoose = false local function randomEvent(roomId, blockId, eventType) if mapInfo.rooms[roomId]["event"][blockId] then return end --已经有事件了 不覆盖 local etype, especial = eventType, 0 if eventType > 100 then -- 特殊事件(固定) etype = math.floor(eventType / 100) especial = eventType % 100 end local event = {etype = etype} local randomFunc = {} local function randomCommon() if not eventLib[etype] or not next(eventLib[etype]) or not eventLib[etype][especial] or not next(eventLib[etype][especial]) then return false end event.id = math.randWeight(eventLib[etype][especial], "showup") if not event.id then return false end if eventLib[etype][especial][event.id].limit > 1 then eventLib[etype][especial][event.id].limit = eventLib[etype][especial][event.id].limit - 1 elseif eventLib[etype][especial][event.id].limit == 1 then eventLib[etype][especial][event.id] = nil end end --入口 randomFunc[AdvEventType.In] = function()end --出口 randomFunc[AdvEventType.Out] = function() end --boss randomFunc[AdvEventType.BOSS] = function() if haveBoss then return false end if randomCommon() == false then return false end haveBoss = true end randomFunc[AdvEventType.LinkChoose] = function() if haveLChoose then return false end if self.adv.lchoose.ing then -- 有正在进行的 event.id = self.adv.lchoose.ing self.adv.lchoose.ing = nil else if randomCommon() == false then return false end end haveLChoose = true end --怪物 randomFunc[AdvEventType.Monster] = function() if randomCommon() == false then return false end table.insert(monsterEvents, event) end --选择点 randomFunc[AdvEventType.Choose] = randomCommon --掉落点 randomFunc[AdvEventType.Drop] = randomCommon --交易所 randomFunc[AdvEventType.Trader] = randomCommon --建筑 randomFunc[AdvEventType.Build] = randomCommon --陷阱 randomFunc[AdvEventType.Trap] = randomCommon --点击生效 randomFunc[AdvEventType.Click] = randomCommon --跨层点 randomFunc[AdvEventType.Layer] = randomCommon --层级任务 randomFunc[AdvEventType.Task] = randomCommon if randomFunc[etype] then if randomFunc[etype]() ~= false then if mapCsvData.clearType == 1 and etype == AdvEventType.BOSS then event.item = mapCsvData.clear:toArray(true, "=") end mapInfo.rooms[roomId]["event"][blockId] = event end end end local stagePool = {["global"] = {}} for roomId, roomName in pairs(mapData["rooms"]) do stagePool[roomId] = {} mapInfo.rooms[roomId] = {event = {}, open = {}, trap = {}} -- 事件, open open == 1 房间内地块全部开放 local roomData if roomName == "path" then roomData = mapData["path"] else roomName = roomName:gsub("/", "_") roomData = csvdb["room_" .. roomName .. "Csv"] end for blockId, stageType in pairs(roomData["blocks"]) do if AdvSpecialStage[stageType] then local eventType = AdvEventType[AdvSpecialStage[stageType]] -- 地块固定类型 randomEvent(roomId, blockId, eventType) else stagePool["global"][stageType] = stagePool["global"][stageType] or {} stagePool[roomId][stageType] = stagePool[roomId][stageType] or {} table.insert(stagePool["global"][stageType], {room = roomId, block = blockId}) stagePool[roomId][stageType][blockId] = 1 end end end -- 全地图事件 优先级高 for stageType, events in pairs(mapData["events"]) do for _, event in ipairs(events) do local lastCount = stagePool["global"][stageType] and #stagePool["global"][stageType] or 0 if lastCount <= 0 then break end if math.randomFloat(0, 1) <= (event["rate"] or 1) then local count = math.randomInt(math.min(lastCount, event["minc"]), math.min(lastCount, event["maxc"])) for i = 1, count do local idx = math.randomInt(1, lastCount) local cur = stagePool["global"][stageType][idx] randomEvent(cur["room"], cur["block"], event["event"]) table.remove(stagePool["global"][stageType], idx) lastCount = lastCount - 1 stagePool[cur["room"]][stageType][cur["block"]] = nil end end end end -- 随机单个房间的事件 for roomId, roomName in pairs(mapData["rooms"]) do local roomData if roomName == "path" then roomData = mapData["path"] else roomName = roomName:gsub("/", "_") roomData = csvdb["room_" .. roomName .. "Csv"] end for stageType, events in pairs(roomData["events"]) do local bpool = {} if stagePool[roomId][stageType] then for block, _ in pairs(stagePool[roomId][stageType]) do table.insert(bpool, block) end end for _, event in ipairs(events) do if #bpool <= 0 then break end if math.randomFloat(0, 1) <= (event["rate"] or 1) then local count = math.randomInt(math.min(#bpool, event["minc"]), math.min(#bpool, event["maxc"])) for i = 1, count do local idx = math.randomInt(1, #bpool) randomEvent(roomId, bpool[idx], event["event"]) table.remove(bpool, idx) end end end end end if mapCsvData.clearType == 1 and not haveBoss then if not next(monsterEvents) then error("这个地图没有钥匙!!! mapId : " .. mapId) else local event = monsterEvents[math.randomInt(1, #monsterEvents)] event.item = mapCsvData.clear:toArray(true, "=") --掉落钥匙 end end return mapInfo end --关卡事件库 getEventLib = function(self, needEventType) -- needEventType 需要的事件 local chapterId, level = self.adv.chapterId, self.adv.level if AdvCommon.isEndless(chapterId) then level = AdvCommon.getEndlessDataLv(chapterId, level) end local libsToType = { ["event_monsterCsv"] = {AdvEventType.Monster, AdvEventType.BOSS, AdvEventType.Monster}, ["event_chooseCsv"] = AdvEventType.Choose, ["event_dropCsv"] = AdvEventType.Drop, ["event_buildingCsv"] = AdvEventType.Build, ["event_traderCsv"] = AdvEventType.Trader, ["event_trapCsv"] = AdvEventType.Trap, ["event_clickCsv"] = AdvEventType.Click, ["event_layerCsv"] = AdvEventType.Layer, ["event_questCsv"] = AdvEventType.Task, ["event_linkchooseCsv"] = AdvEventType.LinkChoose, } local eventLib = {} local advEventOpenStatus = self.adv.owner:advEventOpenStatus() for lib, eventType in pairs(libsToType) do -- init eventLib if type(eventType) == "table" then for _, temp in ipairs(eventType) do eventLib[temp] = {} end else eventLib[eventType] = {} end -- needEventType 只获取这个事件类型 if not needEventType or eventLib[needEventType] then for id, data in pairs(csvdb[lib]) do local etype = type(eventType) == "table" and eventType[data.type] or eventType if data.levelchapter == chapterId and (data.unlockType == 0 or (advEventOpenStatus[etype] or {})[data.unlockType]) then local add = true if etype == AdvEventType.LinkChoose then --link 只有起始任务并且还没完成的进入池子 if id % 10 ~= 1 or (data.limit ~= 0 and data.limit <= (self.adv.lchoose[id] or 0)) then add = false end end if add then if AdvCommon.checkIsIn(level, data.leveltype, data.levellimit) then eventLib[etype][data.BlockEventType] = eventLib[etype][data.BlockEventType] or {} eventLib[etype][data.BlockEventType][id] = {showup = data.showup, limit = data.limit} end end end end if needEventType then break end end end return eventLib end return Map