Commit 43babcff6fcbfd9940df4a5a1faa71f1686d092d

Authored by zhouhaihai
1 parent 836228c9

优化冒险结构 增加夹层功能

@@ -87,6 +87,7 @@ AdvEventType = { @@ -87,6 +87,7 @@ AdvEventType = {
87 Build = 5, --建筑物 87 Build = 5, --建筑物
88 Trap = 6, --陷阱 88 Trap = 6, --陷阱
89 Click = 7, --点击生效 89 Click = 7, --点击生效
  90 + Layer = 8, --切换层的点
90 } 91 }
91 92
92 AdvBackEventType = { 93 AdvBackEventType = {
@@ -106,7 +107,8 @@ AdvBackEventType = { @@ -106,7 +107,8 @@ AdvBackEventType = {
106 TurnEnd = 14, -- 回合结束 107 TurnEnd = 14, -- 回合结束
107 Miss = 15, -- miss 108 Miss = 15, -- miss
108 BattleBegin = 16, -- 战斗开始 109 BattleBegin = 16, -- 战斗开始
109 - Trap = 17, 110 + Trap = 17, --陷阱
  111 + Layer = 18, --切换层
110 } 112 }
111 113
112 AdvScoreType = { 114 AdvScoreType = {
1 local Passive = require "adv.AdvPassive" 1 local Passive = require "adv.AdvPassive"
2 2
3 --- 工具函数--第一象限 < 10000 < 第二象限 < 20000 < 第四象限 < 30000 < 第三象限  
4 -local function getIdByCr(c, r)  
5 - local crId = math.abs(r) + math.abs(c) * 100 -- row + column * 100  
6 - if c < 0 then  
7 - crId = crId + 10000  
8 - end  
9 - if r < 0 then  
10 - crId = crId + 20000  
11 - end  
12 - return crId  
13 -end 3 +local AdvCommon = require "adv.AdvCommon"
  4 +local AdvMap = require "adv.AdvMap"
14 5
15 -local function getCrById(crId)  
16 - local c = math.floor(crId % 10000 / 100)  
17 - local r = crId % 100  
18 - local last = math.floor(crId / 10000)  
19 - if last == 3 then  
20 - c, r = -c, -r  
21 - elseif last == 1 then  
22 - c = -c  
23 - elseif last == 2 then  
24 - r = -r  
25 - end  
26 - return c, r 6 +local Adv = class("Adv")
  7 +function Adv:ctor(owner)
  8 + assert(owner, "Adv instance must have owner(role)")
  9 + self.owner = owner
  10 + self.maps = {}
  11 + self.battle = nil
  12 + self.backEvents = {} --发给客户端的事件组
  13 + self:initByInfo(self.owner:getProperty("advInfo"))
27 end 14 end
28 15
29 ------------------------------随机地图-----------------------------  
30 ---检查 是否满足层数限制条件 -- if checktype == 1 then check value in range a=b else check value in array a=b=c  
31 -local function checkIsIn(checkValue, checkType, checkRange)  
32 - if not checkValue then return end  
33 - if checkType == 1 then  
34 - local limits = checkRange:toNumMap()  
35 - for min, max in pairs(limits) do  
36 - if checkValue >= min and checkValue <= max then  
37 - return true  
38 - end  
39 - end  
40 - else  
41 - local limit = checkRange:toArray(true, "=")  
42 - for _, _l in ipairs(limit) do  
43 - if _l == checkValue then  
44 - return true  
45 - end  
46 - end 16 +--初始化adv 信息
  17 +function Adv:initByInfo(advInfo)
  18 + if not next(advInfo) then return end --还没有 开始新地图
  19 +
  20 + self.chapterId = advInfo.chapterId
  21 + self.level = advInfo.level or 1
  22 + self.score = advInfo.score or {}
  23 + self.lastEnemyId = advInfo.lastEId or 1
  24 + self.mapStack = advInfo.mstack or {}
  25 + self.maps = {}
  26 + for id, map in ipairs(advInfo.maps or {}) do
  27 + self.maps[id] = AdvMap.new(self, id, map)
47 end 28 end
  29 +
  30 + self:initBattle()
48 end 31 end
49 32
50 ---关卡事件库  
51 -local function getEventLib(chapterId, level, needEventType) -- needEventType 需要的事件  
52 - local chapter = math.floor(chapterId / 100) % 100 33 +-- 随机新的地图
  34 +function Adv:initByChapter(chapterId, level, isToNext, notNotify)
  35 + if self.chapterId and chapterId ~= self.chapterId then return end --新的关卡 或者 去到下一层
  36 + self.chapterId = chapterId
  37 + self.level = level or 1
  38 + self.score = self.score or {}
  39 + self.lastEnemyId = 1
  40 + self.mapStack = {1} -- 最后一个为当前的地图
53 41
54 - local libsToType = {  
55 - ["event_monsterCsv"] = {AdvEventType.Monster, AdvEventType.BOSS, AdvEventType.Monster},  
56 - ["event_chooseCsv"] = AdvEventType.Choose,  
57 - ["event_dropCsv"] = AdvEventType.Drop,  
58 - ["event_buildingCsv"] = AdvEventType.Build,  
59 - ["event_traderCsv"] = AdvEventType.Trader,  
60 - ["event_trapCsv"] = AdvEventType.Trap,  
61 - ["event_clickCsv"] = AdvEventType.Click, 42 + -- 随机出地图
  43 + local mapId = self:randomMapId(chapterId, level)
  44 + self.maps = {}
  45 + self.maps[1] = AdvMap.new(self, 1, mapId)
62 46
63 - }  
64 - local eventLib = {}  
65 - for lib, eventType in pairs(libsToType) do  
66 - -- init eventLib  
67 - if type(eventType) == "table" then  
68 - for _, temp in ipairs(eventType) do  
69 - eventLib[temp] = {}  
70 - end  
71 - else  
72 - eventLib[eventType] = {}  
73 - end  
74 - -- needEventType 只获取这个事件类型  
75 - if not needEventType or eventLib[needEventType] then  
76 - for id, data in pairs(csvdb[lib]) do  
77 - if data.levelchapter == chapter then  
78 - if checkIsIn(level, data.leveltype, data.levellimit) then  
79 - if type(eventType) == "table" then  
80 - eventLib[eventType[data.type]][data.BlockEventType] = eventLib[eventType[data.type]][data.BlockEventType] or {}  
81 - eventLib[eventType[data.type]][data.BlockEventType][id] = {showup = data.showup, limit = data.limit}  
82 - else  
83 - eventLib[eventType][data.BlockEventType] = eventLib[eventType][data.BlockEventType] or {}  
84 - eventLib[eventType][data.BlockEventType][id] = {showup = data.showup, limit = data.limit}  
85 - end  
86 - end  
87 - end  
88 - end  
89 - if needEventType then  
90 - break  
91 - end  
92 - end 47 + if isToNext then
  48 + self:scoreChange(AdvScoreType.Level) --增加层级加分
93 end 49 end
94 - return eventLib  
95 -end  
96 50
97 --- 生成地图 是否可以生成地图上层判断  
98 -local function randomAdvMap(role, chapterId, level, notNotify)  
99 - local chapterData = csvdb["adv_chapterCsv"][chapterId]  
100 - if not chapterData then  
101 - error("chapterId " .. chapterId .. " dont exist!")  
102 - return  
103 - end  
104 - if level > chapterData.limitlevel then  
105 - error("level overflow!")  
106 - return 51 + self:initBattle()
  52 +
  53 + if not notNotify then
  54 + self:saveDB(notNotify)
107 end 55 end
108 - --随出地图  
109 - local raw_pool = chapterData.mapid:toArray(true, "=")  
110 - local advInfo = role:getProperty("advInfo") 56 +end
111 57
112 - local lastMapId = advInfo.mapId --非同一层不连续随出同一张类似的地图  
113 - local lastChapterId = advInfo.chapter  
114 - local lastScore = advInfo.score or {} -- 分数 58 +function Adv:clear()
  59 + self.chapterId = nil
  60 + self.level = nil
  61 + self.score = {}
  62 + self.lastEnemyId = 1
  63 + self.mapStack = {}
  64 + self.maps = {}
  65 + self.battle = nil
  66 +end
115 67
116 - local pool = {}  
117 - for _, mapId in ipairs(raw_pool) do  
118 - local temp = csvdb["mapCsv"][mapId]  
119 - if temp and (lastChapterId == chapterId or lastMapId ~= mapId) then --非同一层不连续随出同一张类似的地图  
120 - if checkIsIn(level, temp.leveltype, temp.levellimit) then  
121 - table.insert(pool, mapId)  
122 - end  
123 - end  
124 - end  
125 - if not next(pool) then  
126 - error("mapIds is empty!")  
127 - return  
128 - end  
129 - local mapId = pool[math.randomInt(1, #pool)]  
130 - --随出事件  
131 - local mapData = csvdb["map_" .. csvdb["mapCsv"][mapId]["path"] .. "Csv"]  
132 - if not mapData then  
133 - error("mapId " .. mapId .. " dont exist!")  
134 - return  
135 - end 68 +function Adv:saveDB(notNotify)
  69 + local advInfo, advTeam = {}, self.owner:getProperty("advTeam")
  70 + if self.chapterId then
136 71
137 - table.clear(advInfo)  
138 - advInfo.chapter = chapterId  
139 - advInfo.level = level  
140 - advInfo.mapId = mapId  
141 - advInfo.score = lastScore  
142 - advInfo.enemyId = 1 --怪递增的索引  
143 - advInfo.rooms = {} -- {[roomId] = {event = {}, open = {}},} -- event 事件信息(具体信息查看randomEvent), open 是否解锁  
144 - --事件随机  
145 - local eventLib = getEventLib(chapterId, level) -- 同时记录出现次数  
146 - local monsterEvents = {} --处理钥匙掉落  
147 - local haveBoss = false  
148 -  
149 - local function randomEvent(roomId, blockId, eventType)  
150 - if advInfo.rooms[roomId]["event"][blockId] then return end --已经有事件了 不覆盖  
151 - local etype, especial = eventType, 0  
152 - if eventType > 100 then -- 特殊事件(固定)  
153 - etype = math.floor(eventType / 100)  
154 - especial = eventType % 100  
155 - end  
156 -  
157 - local event = {etype = etype}  
158 - local randomFunc = {}  
159 -  
160 - local function randomCommon()  
161 - if not eventLib[etype] or not next(eventLib[etype]) or not eventLib[etype][especial] or not next(eventLib[etype][especial]) then return false end  
162 - event.id = math.randWeight(eventLib[etype][especial], "showup")  
163 - if not event.id then return false end  
164 - if eventLib[etype][especial][event.id].limit > 1 then  
165 - eventLib[etype][especial][event.id].limit = eventLib[etype][especial][event.id].limit - 1  
166 - elseif eventLib[etype][especial][event.id].limit == 1 then  
167 - eventLib[etype][especial][event.id] = nil  
168 - end  
169 - end 72 + advInfo.chapterId = self.chapterId
  73 + advInfo.level = self.level
  74 + advInfo.score = self.score
  75 + advInfo.lastEId = self.lastEnemyId
  76 + advInfo.mstack = self.mapStack
  77 + advInfo.maps = {}
170 78
171 - --入口  
172 - randomFunc[AdvEventType.In] = function()end  
173 - --出口  
174 - randomFunc[AdvEventType.Out] = function() end  
175 - --boss  
176 - randomFunc[AdvEventType.BOSS] = function()  
177 - if haveBoss then return false end  
178 - if randomCommon() == false then  
179 - return false  
180 - end  
181 - haveBoss = true  
182 - end  
183 - --怪物  
184 - randomFunc[AdvEventType.Monster] = function()  
185 - if randomCommon() == false then  
186 - return false  
187 - end  
188 - table.insert(monsterEvents, event)  
189 - end 79 + self.battle:saveDB()
190 80
191 - --选择点  
192 - randomFunc[AdvEventType.Choose] = randomCommon  
193 - --掉落点  
194 - randomFunc[AdvEventType.Drop] = randomCommon  
195 - --交易所  
196 - randomFunc[AdvEventType.Trader] = randomCommon  
197 - --建筑  
198 - randomFunc[AdvEventType.Build] = randomCommon  
199 - --陷阱  
200 - randomFunc[AdvEventType.Trap] = randomCommon  
201 - --点击生效  
202 - randomFunc[AdvEventType.Click] = randomCommon  
203 -  
204 -  
205 - if randomFunc[etype] then  
206 - if randomFunc[etype]() ~= false then  
207 - advInfo.rooms[roomId]["event"][blockId] = event  
208 - end 81 + for id , map in ipairs(self.maps) do
  82 + advInfo.maps[id] = map:getDB()
209 end 83 end
210 - end  
211 - local stagePool = {["global"] = {}}  
212 - for roomId, roomName in pairs(mapData["rooms"]) do  
213 - stagePool[roomId] = {}  
214 - advInfo.rooms[roomId] = {event = {}, open = {}} -- 事件, open open == 1 房间内地块全部开放  
215 - local roomData  
216 - if roomName == "path" then  
217 - roomData = mapData["path"]  
218 - else  
219 - roomName = roomName:gsub("/", "_")  
220 - roomData = csvdb["room_" .. roomName .. "Csv"]  
221 - end  
222 - for blockId, stageType in pairs(roomData["blocks"]) do  
223 - if AdvSpecialStage[stageType] then  
224 - local eventType = AdvEventType[AdvSpecialStage[stageType]] -- 地块固定类型  
225 - randomEvent(roomId, blockId, eventType)  
226 - else  
227 - stagePool["global"][stageType] = stagePool["global"][stageType] or {}  
228 - stagePool[roomId][stageType] = stagePool[roomId][stageType] or {}  
229 - table.insert(stagePool["global"][stageType], {room = roomId, block = blockId})  
230 - stagePool[roomId][stageType][blockId] = 1  
231 - end  
232 - end  
233 - end  
234 - -- 全地图事件 优先级高  
235 - for stageType, events in pairs(mapData["events"]) do  
236 - for _, event in ipairs(events) do  
237 - local lastCount = stagePool["global"][stageType] and #stagePool["global"][stageType] or 0  
238 - if lastCount <= 0 then break end  
239 - if math.randomFloat(0, 1) <= (event["rate"] or 1) then  
240 - local count = math.randomInt(math.min(lastCount, event["minc"]), math.min(lastCount, event["maxc"]))  
241 - for i = 1, count do  
242 - local idx = math.randomInt(1, lastCount)  
243 - local cur = stagePool["global"][stageType][idx]  
244 - randomEvent(cur["room"], cur["block"], event["event"])  
245 - table.remove(stagePool["global"][stageType], idx)  
246 - lastCount = lastCount - 1  
247 - stagePool[cur["room"]][stageType][cur["block"]] = nil  
248 - end  
249 - end  
250 - end  
251 - end  
252 - -- 随机单个房间的事件  
253 - for roomId, roomName in pairs(mapData["rooms"]) do  
254 - local roomData  
255 - if roomName == "path" then  
256 - roomData = mapData["path"]  
257 - else  
258 - roomName = roomName:gsub("/", "_")  
259 - roomData = csvdb["room_" .. roomName .. "Csv"]  
260 - end  
261 - for stageType, events in pairs(roomData["events"]) do  
262 - local bpool = {}  
263 - if stagePool[roomId][stageType] then  
264 - for block, _ in pairs(stagePool[roomId][stageType]) do  
265 - table.insert(bpool, block)  
266 - end  
267 - end  
268 - for _, event in ipairs(events) do  
269 - if #bpool <= 0 then break end  
270 - if math.randomFloat(0, 1) <= (event["rate"] or 1) then  
271 - local count = math.randomInt(math.min(#bpool, event["minc"]), math.min(#bpool, event["maxc"]))  
272 - for i = 1, count do  
273 - local idx = math.randomInt(1, #bpool)  
274 - randomEvent(roomId, bpool[idx], event["event"])  
275 - table.remove(bpool, idx)  
276 - end  
277 - end  
278 - end  
279 - end  
280 - end  
281 - if not haveBoss then  
282 - if not next(monsterEvents) then  
283 - print("这个地图没有钥匙!!! mapId : " .. mapId)  
284 - else  
285 - local event = monsterEvents[math.randomInt(1, #monsterEvents)]  
286 - event.item = {ItemId.AdvKey, 1} --掉落钥匙  
287 - end  
288 - end  
289 -end  
290 84
291 ---块类型  
292 -local Block = class("Block")  
293 -function Block:ctor(blockId, event, isOpen)  
294 - self.blockId = blockId  
295 - self.col, self.row = getCrById(self.blockId)  
296 - self.isOpen = isOpen and true or false  
297 - self.event = event -- 拿到的是引用可以直接更新  
298 -end  
299 -function Block:isBoss()  
300 - if not self.event then return end  
301 - return self.event["etype"] == AdvEventType.BOSS  
302 -end 85 + advTeam.player = self.battle.player:getDB()
303 86
304 ---事件有需要额外处理的部分  
305 -function Block:open(adv, room)  
306 - --如果翻开有数据处理在这里处理  
307 - local randomFunc = {}  
308 - --怪  
309 - randomFunc[AdvEventType.Monster] = function()  
310 - self.event.mId = adv.advInfo.enemyId --给怪一个有序id 回合逻辑时使用  
311 - adv.advInfo.enemyId = adv.advInfo.enemyId + 1  
312 - local enemy = adv.battle:getEnemy(room.roomId, self.blockId)  
313 - if enemy then  
314 - enemy:unlock(self.event.mId)  
315 - else  
316 - enemy = adv.battle:addEnemy(room, self)  
317 - end  
318 - enemy:triggerPassive(Passive.BORN_ONCE)  
319 - end  
320 - randomFunc[AdvEventType.BOSS] = randomFunc[AdvEventType.Monster]  
321 - --掉落  
322 - randomFunc[AdvEventType.Drop] = function()  
323 - self.event.item = csvdb["event_dropCsv"][self.event.id]["range"]:randWeight(true)  
324 - end  
325 - --交易  
326 - randomFunc[AdvEventType.Trader] = function()  
327 - local data = csvdb["event_traderCsv"][self.event.id]  
328 - self.event.shop = {}  
329 - self.event.status = "" --购买次数状态 1 就是购买过了 -- 购买id就是shop索引  
330 - for i = 1, 10 do  
331 - local numS, rangeS = "num" .. i, "range" .. i  
332 - if data[numS] and data[rangeS] then  
333 - for j = 1, data[numS] do  
334 - table.insert(self.event.shop, data[rangeS]:randWeight(true))  
335 - end  
336 - else  
337 - break  
338 - end  
339 - end  
340 - end  
341 - --建筑  
342 - randomFunc[AdvEventType.Build] = function()  
343 - local data = csvdb["event_buildingCsv"][self.event.id]  
344 - self.event.effect = data["range"]:randWeight(true) --随出建筑效果  
345 - if self.event.effect[1] == 1 then --获得某道具  
346 - local reward = csvdb["event_dropCsv"][self.event.effect[2]]["range"]:randWeight(true)  
347 - self.event.effect[2] = reward[1]  
348 - self.event.effect[3] = reward[2]  
349 - end  
350 - end  
351 - randomFunc[AdvEventType.Trap] = function()  
352 - local data = csvdb["event_trapCsv"][self.event.id]  
353 - for _, buffId in ipairs(data.effect:toArray(true, "=")) do  
354 - adv.battle.player:addBuff(buffId)  
355 - end  
356 - adv:backTrap()  
357 - room:clearBEvent(self)  
358 - end  
359 - if self.event then -- 随机出具体的事件  
360 - if randomFunc[self.event.etype] then  
361 - randomFunc[self.event.etype]()  
362 - end 87 + else
  88 + advTeam.player = nil
363 end 89 end
364 - self.isOpen = true 90 +
  91 + self.owner:updateProperties({advInfo = advInfo, advTeam = advTeam}, notNotify)
365 end 92 end
366 93
367 -local Room = class("Room")  
368 -function Room:ctor(adv, roomId, csvData, info, isPath)  
369 - self.roomId = roomId  
370 - self.col, self.row = getCrById(self.roomId)  
371 - self.isPath = isPath  
372 - self.isBossRoom = false -- boss房间 --击败boss 以后重置为false  
373 - self.info = info -- 拿到引用 方便更新advInfo  
374 - self.isShow = false  
375 - self.blocks = {}  
376 -  
377 - for blockId, _ in pairs(csvData["blocks"]) do  
378 - self.blocks[blockId] = Block.new(blockId, info.event[blockId], info.open == 1 or info.open[blockId])  
379 - if not self.isPath and self.blocks[blockId]:isBoss() then  
380 - self.isBossRoom = true  
381 - end  
382 - if self.blocks[blockId].isOpen then  
383 - self.isShow = true  
384 - else  
385 - if self.blocks[blockId].event and self.blocks[blockId].event.etype == AdvEventType.In then -- 开放  
386 - self.isShow = true  
387 - self.blocks[blockId].isOpen = true  
388 - self.info.open[blockId] = 1  
389 -  
390 - --入口房间只会在这里首次展示开放 --触发固有技  
391 - adv:triggerPassive(Passive.ROOM_SHOW, {roomId = self.roomId})  
392 - end  
393 - end 94 +function Adv:initBattle()
  95 + self.battle = require("adv.AdvBattle").new(self)
  96 + for _, passiveC in ipairs(self.cachePassiveEvent or {}) do
  97 + self.battle:triggerPassive(passiveC[1], passiveC[2])
394 end 98 end
  99 + self.cachePassiveEvent = {}
395 end 100 end
396 101
397 -function Room:tranGToL(c, r)  
398 - return c - self.col, r - self.row 102 +function Adv:triggerPassive(condType, params)
  103 + self.cachePassiveEvent = self.cachePassiveEvent or {}
  104 + if not self.battle then
  105 + table.insert(self.cachePassiveEvent, {condType, params})
  106 + else
  107 + self.battle:triggerPassive(condType, params)
  108 + end
399 end 109 end
400 110
401 -function Room:tranLtoG(c, r)  
402 - return c + self.col, r + self.row 111 +function Adv:getCurMap()
  112 + return self.maps[self.mapStack[#self.mapStack]]
403 end 113 end
404 114
405 -function Room:getBByGPos(c, r)  
406 - local c, r = self:tranGToL(c, r)  
407 - return self.blocks[getIdByCr(c, r)] 115 +function Adv:getCurMapIdx()
  116 + return self.mapStack[#self.mapStack]
408 end 117 end
409 118
410 -function Room:openBlock(block, adv)  
411 - if self.blocks[block.blockId] ~= block then return end  
412 - if block.isOpen == true then return end  
413 - if self.isBossRoom then  
414 - for _, _block in pairs(self.blocks) do  
415 - _block:open(adv, self)  
416 - end  
417 - else  
418 - block:open(adv, self) 119 +function Adv:getRoom(roomId, mapIdx)
  120 + mapIdx = mapIdx or self:getCurMapIdx()
  121 + local map = self.maps[mapIdx]
  122 + if map then
  123 + return map.rooms[roomId]
419 end 124 end
420 - local allOpen = true  
421 - for _, _block in pairs(self.blocks) do  
422 - if not _block.isOpen then  
423 - allOpen = false  
424 - break  
425 - end  
426 - end  
427 -  
428 - if allOpen then  
429 - self.info.open = 1  
430 - else  
431 - self.info.open[block.blockId] = 1  
432 - end  
433 -  
434 - adv:scoreChange(AdvScoreType.Block)  
435 -  
436 - if not self.isShow then  
437 - self.isShow = true  
438 - --首次展示房间  
439 - adv:triggerPassive(Passive.ROOM_SHOW, {roomId = self.roomId})  
440 - end  
441 end 125 end
442 126
443 -function Room:clearBEvent(block)  
444 - if self.blocks[block.blockId] ~= block then return end  
445 - if block.event.etype == AdvEventType.Trap then -- 记录陷阱位置  
446 - self.info.trap = self.info.trap or {}  
447 - self.info.trap[block.blockId] = block.event.id 127 +function Adv:getBlock(roomId, blockId, mapIdx)
  128 + local room = self:getRoom(roomId, mapIdx)
  129 + if room then
  130 + return room.blocks[blockId]
448 end 131 end
449 - block.event = nil  
450 - self.info.event[block.blockId] = nil  
451 end 132 end
452 133
453 134
454 135
455 -local Adv = class("Adv")  
456 -function Adv:ctor(owner)  
457 - assert(owner, "Adv instance must have owner(role)")  
458 - self.owner = owner  
459 - self.advInfo = self.owner:getProperty("advInfo") --这个变量置空使用 table.clear  
460 - self.advTeam = self.owner:getProperty("advTeam") --这个变量置空使用 table.clear  
461 - self:clear()  
462 - self.backEvents = {} --发给客户端的事件组  
463 - self.tempBackEvents = {} --发给客户端的事件组(缓存)  
464 -end  
465 -  
466 --- 清空自己组织的数据  
467 -function Adv:clear()  
468 - self.rooms = {}  
469 - self.cachePassiveEvent = {} -- 在battle 没有创建成功时 触发的被动技信息  
470 - self.battle = nil -- 战斗逻辑  
471 -end  
472 -  
473 --关卡通关,非层 score < 0 失败 136 --关卡通关,非层 score < 0 失败
474 function Adv:over(success) 137 function Adv:over(success)
475 local score = self:getScore() 138 local score = self:getScore()
476 - local scoreInfo = self.advInfo.score 139 + local scoreInfo = self.score
477 local reward 140 local reward
478 if success then 141 if success then
479 - self.owner:updateProperty({field = "advPass", self.owner:getProperty("advPass"):setv(self.advInfo.chapter, score)}) 142 + self.owner:updateProperty({field = "advPass", self.owner:getProperty("advPass"):setv(self.chapterId, score)})
480 reward = self.owner:award(self.owner:getProperty("advItems"):toNumMap()) 143 reward = self.owner:award(self.owner:getProperty("advItems"):toNumMap())
481 144
482 - self.owner:checkTaskEnter(self.owner.TaskType.AdvPass, {id = self.advInfo.chapter}) 145 + self.owner:checkTaskEnter(self.owner.TaskType.AdvPass, {id = self.chapterId})
483 end 146 end
484 - table.clear(self.advInfo) --清空advInfo  
485 - self.advTeam.player = nil --重置玩家的数据  
486 self:clear() 147 self:clear()
487 148
488 self.owner:updateProperty({field = "advItems", value = ""}) 149 self.owner:updateProperty({field = "advItems", value = ""})
@@ -495,162 +156,41 @@ function Adv:exit() @@ -495,162 +156,41 @@ function Adv:exit()
495 self:saveDB() 156 self:saveDB()
496 end 157 end
497 158
498 -function Adv:getMapInfo()  
499 - if not next(self.advInfo) then return end  
500 - return csvdb["mapCsv"][self.advInfo.mapId]  
501 -end  
502 -  
503 -function Adv:getMapData()  
504 - local mapInfo = self:getMapInfo()  
505 - if not mapInfo then return end  
506 - return csvdb["map_" .. self:getMapInfo()["path"] .. "Csv"]  
507 -end  
508 -  
509 -function Adv:initByInfo()  
510 - self:clear()  
511 - if not next(self.advInfo) then return end --未初始化的 advInfo  
512 -  
513 - local mapData = self:getMapData()  
514 - if not mapData then return end  
515 -  
516 - for roomId, roomName in pairs(mapData["rooms"]) do  
517 - if roomName == "path" then  
518 - self.rooms[roomId] = Room.new(self, roomId, mapData["path"], self.advInfo.rooms[roomId], true)  
519 - else  
520 - roomName = roomName:gsub("/", "_")  
521 - self.rooms[roomId] = Room.new(self, roomId, csvdb["room_" .. roomName .. "Csv"], self.advInfo.rooms[roomId], false)  
522 - end  
523 - end  
524 - self:initBattle()  
525 - return true  
526 -end  
527 -  
528 -function Adv:triggerPassive(condType, params)  
529 - if not self.battle then  
530 - table.insert(self.cachePassiveEvent, {condType, params})  
531 - else  
532 - self.battle:triggerPassive(condType, params)  
533 - end  
534 -end  
535 -  
536 -function Adv:initBattle()  
537 - self.battle = require("adv.AdvBattle").new(self)  
538 - for _, passiveC in ipairs(self.cachePassiveEvent) do  
539 - self.battle:triggerPassive(passiveC[1], passiveC[2])  
540 - end  
541 - self.cachePassiveEvent = {}  
542 -end  
543 -  
544 --- 随机地图  
545 -function Adv:initByChapter(chapterId, level, notNotify)  
546 - level = level or 1  
547 - randomAdvMap(self.owner, chapterId, level, notNotify)  
548 - if not next(self.advInfo) then return end  
549 - if level > 1 then  
550 - self:scoreChange(AdvScoreType.Level)  
551 - end  
552 - self:initByInfo() --初始化  
553 - self.owner:updateProperties({advInfo = self.advInfo, advTeam = self.advTeam}, notNotify)  
554 -end  
555 -  
556 ---获取,某个位置上的 room 和 block  
557 -function Adv:getRBByPos(c, r)  
558 - for roomId, room in pairs(self.rooms) do  
559 - local block = room:getBByGPos(c, r)  
560 - if block then  
561 - return room, block  
562 - end  
563 - end  
564 -end  
565 -  
566 -function Adv:getAroundBlocks(room, block)  
567 - local blocks = {}  
568 - local range = {1, -1}  
569 - local col, row = room:tranLtoG(block.col, block.row)  
570 - for _, add in ipairs(range) do  
571 - local rroom, rblock = self:getRBByPos(col + add, row)  
572 - if rroom then  
573 - table.insert(blocks, {rroom, rblock})  
574 - end 159 +function Adv:randomMapId(chapterId, level)
  160 + local chapterData = csvdb["adv_chapterCsv"][chapterId]
  161 + if not chapterData then
  162 + error("chapterId " .. chapterId .. " dont exist!")
  163 + return
575 end 164 end
576 - for _, add in ipairs(range) do  
577 - local rroom, rblock = self:getRBByPos(col, row + add)  
578 - if rroom then  
579 - table.insert(blocks, {rroom, rblock})  
580 - end 165 + if level > chapterData.limitlevel then
  166 + error("level overflow!")
  167 + return
581 end 168 end
582 - return blocks  
583 -end 169 + --随出地图Id
  170 + local raw_pool = chapterData.mapid:toArray(true, "=")
584 171
585 ---随机一个空的位置生成怪, 如果没有就没有  
586 -function Adv:addNewMonsterRand(monsterId, where)  
587 - local room, block  
588 - if where then  
589 - room, block = where[1], where[2]  
590 - else  
591 - local pool = {}  
592 - for _, room_ in pairs(self.rooms) do  
593 - for _, block_ in pairs(room_.blocks) do  
594 - if block_.isOpen and not block_.event then  
595 - table.insert(pool, {room_, block_})  
596 - end  
597 - end  
598 - end  
599 - if not next(pool) then return end  
600 - local idx = math.randomInt(1, #pool)  
601 - room, block = pool[idx][1], pool[idx][2] 172 + local lastMapIds = {}
  173 + for id, map in ipairs(self.maps or {}) do
  174 + lastMapIds[map.mapId] = 1
602 end 175 end
603 176
604 - if not monsterId then  
605 - local eventLib = getEventLib(self.advInfo.chapter, self.advInfo.level, AdvEventType.Monster)  
606 - if not next(eventLib[AdvEventType.Monster][0]) then return false end  
607 - monsterId = math.randWeight(eventLib[AdvEventType.Monster][0], "showup")  
608 - end  
609 -  
610 - local event = {etype = AdvEventType.Monster, mId = self.advInfo.enemyId}  
611 - self.advInfo.enemyId = self.advInfo.enemyId + 1  
612 - event.id = monsterId  
613 - block.event = event  
614 - room.info.event[block.blockId] = event  
615 - self.battle:addEnemy(room, block):triggerPassive(Passive.BORN_ONCE)  
616 -  
617 - return room, block  
618 -end  
619 -  
620 --- 随机翻开 num 个 以开放的房间的 地块  
621 -function Adv:openBlockRand(num)  
622 local pool = {} 177 local pool = {}
623 - for _, room in pairs(self.rooms) do  
624 - if room.isShow and not room.isPath then  
625 - for _, block in pairs(room.blocks) do  
626 - if not block.isOpen then  
627 - table.insert(pool, {room.roomId, block.blockId})  
628 - end 178 + for _, mapId in ipairs(raw_pool) do
  179 + local temp = csvdb["mapCsv"][mapId]
  180 + if temp and not lastMapIds[mapId] then
  181 + if AdvCommon.checkIsIn(level, temp.leveltype, temp.levellimit) then
  182 + table.insert(pool, mapId)
629 end 183 end
630 end 184 end
631 end 185 end
632 - if #pool <= num then  
633 - for _, temp in ipairs(pool) do  
634 - self:openBlock(temp[1], temp[2])  
635 - end  
636 - else  
637 - for i = 1, num do  
638 - local idx = math.randomInt(1, #pool)  
639 - self:openBlock(pool[idx][1], pool[idx][2])  
640 - table.remove(pool, idx)  
641 - end 186 + if not next(pool) then
  187 + error("mapIds is empty!")
  188 + return
642 end 189 end
643 -end  
644 --- 打开一个地块  
645 -function Adv:openBlock(roomId, blockId)  
646 - local room = self.rooms[roomId]  
647 - if not room then return end  
648 - local block = room.blocks[blockId]  
649 - if not block then return end  
650 - room:openBlock(block, self)  
651 - self:backBlockChange(roomId, blockId) 190 + return pool[math.randomInt(1, #pool)]
652 end 191 end
653 192
  193 +
654 -- 在冒险中获得的物品都发放在冒险背包内 194 -- 在冒险中获得的物品都发放在冒险背包内
655 function Adv:award(gift, params) 195 function Adv:award(gift, params)
656 params = params or {} 196 params = params or {}
@@ -707,13 +247,19 @@ end @@ -707,13 +247,19 @@ end
707 247
708 --事件点击处理 248 --事件点击处理
709 local function clickOut(self, room, block, params) 249 local function clickOut(self, room, block, params)
710 - if self:cost({[ItemId.AdvKey] = 1}, {}) then  
711 - if self.advInfo.level >= csvdb["adv_chapterCsv"][self.advInfo.chapter].limitlevel then --关卡结束  
712 - self:over(true)  
713 - else  
714 - self:initByChapter(self.advInfo.chapter, self.advInfo.level + 1, true)  
715 - self:backNext() --下一关 250 + if self:getCurMap():checkOver() then --检查是否可以出去了
  251 + if #self.mapStack > 1 then -- 处于夹层中
  252 + table.remove(self.mapStack) --退出夹层
  253 + self:backLayer()
  254 + else --处于底层
  255 + if self.level >= csvdb["adv_chapterCsv"][self.chapterId].limitlevel then --关卡结束
  256 + self:over(true)
  257 + else
  258 + self:initByChapter(self.chapterId, self.level + 1, true, true)
  259 + self:backNext() --下一关
  260 + end
716 end 261 end
  262 +
717 return true 263 return true
718 end 264 end
719 end 265 end
@@ -739,17 +285,14 @@ local function clickChoose(self, room, block, params) @@ -739,17 +285,14 @@ local function clickChoose(self, room, block, params)
739 end, 285 end,
740 -- xx角色(todo 队长) 286 -- xx角色(todo 队长)
741 [2] = function() 287 [2] = function()
742 - for slot, heroId in pairs(self.advTeam.heros) do  
743 - if self.owner.heros[heroId] then  
744 - if self.owner.heros[heroId]:getProperty("type") == cond[2] then  
745 - return true  
746 - end  
747 - end 288 + local hero = self.owner.heros[self.owner:getProperty("advTeam").leader]
  289 + if hero and hero:getProperty("type") == cond[2] then
  290 + return true
748 end 291 end
749 end, 292 end,
750 --消灭所有怪 293 --消灭所有怪
751 [3] = function() 294 [3] = function()
752 - for _, room in pairs(self.rooms) do 295 + for _, room in pairs(self:getCurMap().rooms) do
753 for _, block in pairs(room.blocks) do 296 for _, block in pairs(room.blocks) do
754 if block.event and (block.event.etype == AdvEventType.BOSS or block.event.etype == AdvEventType.Monster) then 297 if block.event and (block.event.etype == AdvEventType.BOSS or block.event.etype == AdvEventType.Monster) then
755 return 298 return
@@ -784,7 +327,7 @@ local function clickChoose(self, room, block, params) @@ -784,7 +327,7 @@ local function clickChoose(self, room, block, params)
784 self.battle.player:addBuff(effect[2]) 327 self.battle.player:addBuff(effect[2])
785 end, 328 end,
786 [3] = function() --发现怪物 329 [3] = function() --发现怪物
787 - self:addNewMonsterRand(effect[2], {room, block}) 330 + self:getCurMap():addNewMonsterRand(effect[2], {room, block})
788 clearBlock = false 331 clearBlock = false
789 end, 332 end,
790 [4] = function() --无事发生 333 [4] = function() --无事发生
@@ -795,7 +338,7 @@ local function clickChoose(self, room, block, params) @@ -795,7 +338,7 @@ local function clickChoose(self, room, block, params)
795 end 338 end
796 339
797 if clearBlock then 340 if clearBlock then
798 - room:clearBEvent(block) 341 + block:clear()
799 end 342 end
800 return true 343 return true
801 end 344 end
@@ -804,7 +347,7 @@ local function clickDrop(self, room, block, params) @@ -804,7 +347,7 @@ local function clickDrop(self, room, block, params)
804 local reward = {} 347 local reward = {}
805 if not block.event.item then return end 348 if not block.event.item then return end
806 local reward = self:award({[block.event.item[1]] = block.event.item[2]}) 349 local reward = self:award({[block.event.item[1]] = block.event.item[2]})
807 - room:clearBEvent(block) 350 + block:clear()
808 self:backReward(reward) 351 self:backReward(reward)
809 return true 352 return true
810 end 353 end
@@ -840,7 +383,7 @@ local function clickBuild(self, room, block, params) @@ -840,7 +383,7 @@ local function clickBuild(self, room, block, params)
840 self.battle.player:addBuff(effect[2]) 383 self.battle.player:addBuff(effect[2])
841 end, 384 end,
842 [3] = function() --发现怪物 385 [3] = function() --发现怪物
843 - self:addNewMonsterRand(effect[2], {room, block}) 386 + self:getCurMap():addNewMonsterRand(effect[2], {room, block})
844 clearBlock = false 387 clearBlock = false
845 end, 388 end,
846 [4] = function() --无事发生 389 [4] = function() --无事发生
@@ -850,7 +393,7 @@ local function clickBuild(self, room, block, params) @@ -850,7 +393,7 @@ local function clickBuild(self, room, block, params)
850 if not self:cost(buildData.required:toNumMap(), {}) then return end 393 if not self:cost(buildData.required:toNumMap(), {}) then return end
851 doEffect[effect[1]]() 394 doEffect[effect[1]]()
852 if clearBlock then 395 if clearBlock then
853 - room:clearBEvent(block) 396 + block:clear()
854 end 397 end
855 return true 398 return true
856 end 399 end
@@ -875,11 +418,28 @@ local function clickClick(self, room, block, params) @@ -875,11 +418,28 @@ local function clickClick(self, room, block, params)
875 end, 418 end,
876 } 419 }
877 if clearBlock then 420 if clearBlock then
878 - room:clearBEvent(block) 421 + block:clear()
879 end 422 end
880 return true 423 return true
881 end 424 end
882 425
  426 +local function clickLayer(self, room, block, params)
  427 + if block.event.mapIdx then
  428 + table.insert(self.mapStack, block.event.mapIdx) --进入夹层
  429 + else
  430 + --生成夹层
  431 + local mapId = csvdb["event_layerCsv"][block.event.id].effect
  432 + local mapIdx = #self.maps + 1
  433 + block.event.mapIdx = mapIdx
  434 + table.insert(self.mapStack, mapIdx)
  435 +
  436 + self.maps[mapIdx] = AdvMap.new(self, mapIdx, mapId)
  437 + self.battle:initMapEnemys(mapIdx)
  438 + end
  439 + self:backLayer()
  440 + return true
  441 +end
  442 +
883 local eventCallFunc = { 443 local eventCallFunc = {
884 [AdvEventType.Out] = clickOut, 444 [AdvEventType.Out] = clickOut,
885 [AdvEventType.BOSS] = clickMonster, 445 [AdvEventType.BOSS] = clickMonster,
@@ -889,14 +449,15 @@ local eventCallFunc = { @@ -889,14 +449,15 @@ local eventCallFunc = {
889 [AdvEventType.Trader] = clickTrader, 449 [AdvEventType.Trader] = clickTrader,
890 [AdvEventType.Build] = clickBuild, 450 [AdvEventType.Build] = clickBuild,
891 [AdvEventType.Click] = clickClick, 451 [AdvEventType.Click] = clickClick,
  452 + [AdvEventType.Layer] = clickLayer,
892 } 453 }
893 454
894 --点击处理 roomId, blockId 455 --点击处理 roomId, blockId
895 --params 某些事件需要的客户端传递的参数 456 --params 某些事件需要的客户端传递的参数
896 function Adv:clickBlock(roomId, blockId, params) 457 function Adv:clickBlock(roomId, blockId, params)
897 - local room = self.rooms[roomId]  
898 - if not room then return end  
899 - local block = room.blocks[blockId] 458 + local map = self:getCurMap()
  459 + local room = self:getRoom(roomId)
  460 + local block = self:getBlock(roomId, blockId)
900 if not block then return end 461 if not block then return end
901 462
902 local status = false 463 local status = false
@@ -904,15 +465,15 @@ function Adv:clickBlock(roomId, blockId, params) @@ -904,15 +465,15 @@ function Adv:clickBlock(roomId, blockId, params)
904 if not block.isOpen then 465 if not block.isOpen then
905 local canOpen = false --如果未开放是否可以开放 466 local canOpen = false --如果未开放是否可以开放
906 local hadMonster = false -- 周围是否有解锁的怪未击败 467 local hadMonster = false -- 周围是否有解锁的怪未击败
907 - for _, one in ipairs(self:getAroundBlocks(room, block)) do 468 + for _, one in ipairs(map:getAroundBlocks(room, block)) do
908 local _room, _block = one[1], one[2] 469 local _room, _block = one[1], one[2]
909 if _block.isOpen then canOpen = true end 470 if _block.isOpen then canOpen = true end
910 - if _block.isOpen and _block.event and (_block.event.etype == AdvEventType.BOSS or _block.event.etype == AdvEventType.Monster) then 471 + if _block.isOpen and _block:isMonster() then
911 hadMonster = true 472 hadMonster = true
912 end 473 end
913 end 474 end
914 if canOpen and not hadMonster then --开放 475 if canOpen and not hadMonster then --开放
915 - room:openBlock(block, self) 476 + room:openBlock(block)
916 status = true 477 status = true
917 end 478 end
918 else 479 else
@@ -922,15 +483,15 @@ function Adv:clickBlock(roomId, blockId, params) @@ -922,15 +483,15 @@ function Adv:clickBlock(roomId, blockId, params)
922 return 483 return
923 end 484 end
924 --可点击的事件 485 --可点击的事件
925 - if not room.isBossRoom or block.event.etype == AdvEventType.BOSS then 486 + if not room.isBossRoom or block:isBoss() then
926 if eventCallFunc[block.event.etype] then 487 if eventCallFunc[block.event.etype] then
927 - status = eventCallFunc[block.event.etype](self, room, block, params) 488 + status = eventCallFunc[block:getEventType()](self, room, block, params)
928 end 489 end
929 end 490 end
930 end 491 end
931 local needChange = true 492 local needChange = true
932 if clickEvent and block.event then 493 if clickEvent and block.event then
933 - if block.event.etype == AdvEventType.Out then 494 + if block:getEventType() == AdvEventType.Out then
934 needChange = false 495 needChange = false
935 end 496 end
936 end 497 end
@@ -991,34 +552,33 @@ end @@ -991,34 +552,33 @@ end
991 552
992 --敌人死亡 553 --敌人死亡
993 function Adv:enemyDead(roomId, blockId, escape) 554 function Adv:enemyDead(roomId, blockId, escape)
994 - local room = self.rooms[roomId]  
995 - local block = room.blocks[blockId] 555 + local map = self:getCurMap()
  556 + local room = self:getRoom(roomId)
  557 + local block = self:getBlock(roomId, blockId)
  558 + if not block then return end
996 --死了以后掉东西 559 --死了以后掉东西
997 - if block.event and (block.event.etype == AdvEventType.BOSS or block.event.etype == AdvEventType.Monster) then --处理死亡  
998 - if block.event.etype == AdvEventType.BOSS then 560 + if block:isMonster() then --处理死亡
  561 + if block:isBoss() then
999 room.isBossRoom = false 562 room.isBossRoom = false
1000 end 563 end
1001 if escape then 564 if escape then
1002 - room:clearBEvent(block) 565 + block:clear()
1003 else 566 else
1004 local monsterData = csvdb["event_monsterCsv"][block.event.id] 567 local monsterData = csvdb["event_monsterCsv"][block.event.id]
1005 self:scoreChange(AdvScoreType.Kill, monsterData.type) 568 self:scoreChange(AdvScoreType.Kill, monsterData.type)
1006 569
1007 local item = block.event.item 570 local item = block.event.item
1008 if not item then 571 if not item then
1009 - if block.event.etype == AdvEventType.BOSS then  
1010 - item = {ItemId.AdvKey, 1}  
1011 - else  
1012 - local dropData = csvdb["event_dropCsv"][monsterData.dropid]  
1013 - item = dropData["range"]:randWeight(true)  
1014 - end 572 + local dropData = csvdb["event_dropCsv"][monsterData.dropid]
  573 + item = dropData["range"]:randWeight(true)
1015 end 574 end
1016 if item[1] == 0 then 575 if item[1] == 0 then
1017 - room:clearBEvent(block) 576 + block:clear()
1018 else 577 else
1019 - table.clear(block.event)  
1020 - block.event.etype = AdvEventType.Drop  
1021 - block.event.item = item 578 + block:updateEvent({
  579 + etype = AdvEventType.Drop,
  580 + item = item
  581 + })
1022 end 582 end
1023 end 583 end
1024 end 584 end
@@ -1090,6 +650,10 @@ function Adv:backTrap() @@ -1090,6 +650,10 @@ function Adv:backTrap()
1090 self:pushBackEvent(AdvBackEventType.Trap, {}) 650 self:pushBackEvent(AdvBackEventType.Trap, {})
1091 end 651 end
1092 652
  653 +function Adv:backLayer()
  654 + self:pushBackEvent(AdvBackEventType.Layer, {})
  655 +end
  656 +
1093 function Adv:scoreChange(scoreType, pms) 657 function Adv:scoreChange(scoreType, pms)
1094 local cutTypes = {} 658 local cutTypes = {}
1095 local score = 0 659 local score = 0
@@ -1097,7 +661,7 @@ function Adv:scoreChange(scoreType, pms) @@ -1097,7 +661,7 @@ function Adv:scoreChange(scoreType, pms)
1097 score = globalCsv.adv_score_floor 661 score = globalCsv.adv_score_floor
1098 end 662 end
1099 cutTypes[AdvScoreType.Kill] = function() 663 cutTypes[AdvScoreType.Kill] = function()
1100 - local chapterData = csvdb["adv_chapterCsv"][self.advInfo.chapter] 664 + local chapterData = csvdb["adv_chapterCsv"][self.chapterId]
1101 score = globalCsv.adv_score_monster[pms] * chapterData["monRatio"] 665 score = globalCsv.adv_score_monster[pms] * chapterData["monRatio"]
1102 end 666 end
1103 cutTypes[AdvScoreType.Item] = function() 667 cutTypes[AdvScoreType.Item] = function()
@@ -1114,25 +678,23 @@ function Adv:scoreChange(scoreType, pms) @@ -1114,25 +678,23 @@ function Adv:scoreChange(scoreType, pms)
1114 else 678 else
1115 return 679 return
1116 end 680 end
1117 - self.advInfo.score[scoreType] = self.advInfo.score[scoreType] or 0  
1118 - self.advInfo.score[scoreType] = self.advInfo.score[scoreType] + score 681 + self.score[scoreType] = self.score[scoreType] or 0
  682 + self.score[scoreType] = self.score[scoreType] + score
1119 end 683 end
1120 684
1121 function Adv:getScore() 685 function Adv:getScore()
1122 - self.advInfo.score[AdvScoreType.Level] = math.floor(self.advInfo.score[AdvScoreType.Level] or 0)  
1123 - self.advInfo.score[AdvScoreType.Block] = math.floor(self.advInfo.score[AdvScoreType.Block] or 0)  
1124 - self.advInfo.score[AdvScoreType.Hurt] = math.max(math.floor(self.advInfo.score[AdvScoreType.Hurt] or 0), - (self.advInfo.score[AdvScoreType.Level] + self.advInfo.score[AdvScoreType.Block]))  
1125 - self.advInfo.score[AdvScoreType.Kill] = math.floor(self.advInfo.score[AdvScoreType.Kill] or 0)  
1126 - self.advInfo.score[AdvScoreType.Item] = math.floor(self.advInfo.score[AdvScoreType.Item] or 0)  
1127 -  
1128 - return self.advInfo.score[AdvScoreType.Level] + self.advInfo.score[AdvScoreType.Block] + self.advInfo.score[AdvScoreType.Hurt]  
1129 - + self.advInfo.score[AdvScoreType.Kill] + self.advInfo.score[AdvScoreType.Item] 686 + self.score[AdvScoreType.Level] = math.floor(self.score[AdvScoreType.Level] or 0)
  687 + self.score[AdvScoreType.Block] = math.floor(self.score[AdvScoreType.Block] or 0)
  688 + self.score[AdvScoreType.Hurt] = math.max(math.floor(self.score[AdvScoreType.Hurt] or 0), - (self.score[AdvScoreType.Level] + self.score[AdvScoreType.Block]))
  689 + self.score[AdvScoreType.Kill] = math.floor(self.score[AdvScoreType.Kill] or 0)
  690 + self.score[AdvScoreType.Item] = math.floor(self.score[AdvScoreType.Item] or 0)
  691 +
  692 + return self.score[AdvScoreType.Level] + self.score[AdvScoreType.Block] + self.score[AdvScoreType.Hurt]
  693 + + self.score[AdvScoreType.Kill] + self.score[AdvScoreType.Item]
1130 end 694 end
1131 695
1132 function Adv:popBackEvents() 696 function Adv:popBackEvents()
1133 local events = self.backEvents 697 local events = self.backEvents
1134 - -- TODO 缓存数据需要分类,防止发错,暂时只有战斗,可以不分  
1135 - self.tempBackEvents = events  
1136 self.backEvents = {} 698 self.backEvents = {}
1137 return events 699 return events
1138 end 700 end
@@ -1142,14 +704,6 @@ function Adv:afterRound() @@ -1142,14 +704,6 @@ function Adv:afterRound()
1142 if self.battle then 704 if self.battle then
1143 self.battle:afterRound() 705 self.battle:afterRound()
1144 end 706 end
1145 - -- TODO 房间回合事件  
1146 -end  
1147 -  
1148 -function Adv:saveDB()  
1149 - if self.battle then  
1150 - self.battle:getDB()  
1151 - end  
1152 - self.owner:updateProperties({advInfo = self.advInfo, advTeam = self.advTeam})  
1153 end 707 end
1154 708
1155 return Adv 709 return Adv
1156 \ No newline at end of file 710 \ No newline at end of file
src/adv/AdvBattle.lua
@@ -7,7 +7,7 @@ function Battle:ctor(adv) @@ -7,7 +7,7 @@ function Battle:ctor(adv)
7 self.player = nil --玩家 7 self.player = nil --玩家
8 self.isNewPlayer = false 8 self.isNewPlayer = false
9 self.enemys = {} --怪 9 self.enemys = {} --怪
10 - self.tempData = {} -- 临时回合数据 10 + self.cachePassiveEvent = {}
11 self:initPlayer() 11 self:initPlayer()
12 self:initEnemys() 12 self:initEnemys()
13 self:initAfter() 13 self:initAfter()
@@ -17,9 +17,11 @@ function Battle:ctor(adv) @@ -17,9 +17,11 @@ function Battle:ctor(adv)
17 end 17 end
18 18
19 function Battle:initAfter() 19 function Battle:initAfter()
20 - self.player:initAfter(self.adv.advTeam.player)  
21 - for _, enemy in pairs(self.enemys) do  
22 - enemy:initAfter(self.adv.rooms[enemy.roomId].blocks[enemy.blockId].event.enemy) 20 + self.player:initAfter(self.adv.owner:getProperty("advTeam").player)
  21 + for idx, mapEnemys in pairs(self.enemys) do
  22 + for _, enemy in ipairs(mapEnemys) do
  23 + enemy:initAfter(self.adv:getBlock(enemy.roomId, enemy.blockId, idx).event.enemy)
  24 + end
23 end 25 end
24 end 26 end
25 --[[ 27 --[[
@@ -33,12 +35,14 @@ end @@ -33,12 +35,14 @@ end
33 --]] 35 --]]
34 36
35 function Battle:initPlayer() 37 function Battle:initPlayer()
36 - if not next(self.adv.advTeam.heros) then return end  
37 - if not self.adv.advTeam.player then  
38 - local player = {} 38 + local advTeam = self.adv.owner:getProperty("advTeam")
  39 + if not next(advTeam.heros) then return end
  40 + local player = advTeam.player
  41 + if not player then
  42 + player = {}
39 player.passives = {} 43 player.passives = {}
40 local heroLevel = 0 44 local heroLevel = 0
41 - for slot, heroId in pairs(self.adv.advTeam.heros) do 45 + for slot, heroId in pairs(advTeam.heros) do
42 local hero = self.adv.owner.heros[heroId] 46 local hero = self.adv.owner.heros[heroId]
43 if hero then 47 if hero then
44 heroLevel = heroLevel + hero:getProperty("level") 48 heroLevel = heroLevel + hero:getProperty("level")
@@ -48,56 +52,77 @@ function Battle:initPlayer() @@ -48,56 +52,77 @@ function Battle:initPlayer()
48 end 52 end
49 end 53 end
50 end 54 end
51 - player.growth = (self.adv.owner:getRealBattleValue(self.adv.advTeam.heros) / 80) ^ 0.52 + math.floor(heroLevel / 50) / 50 55 + player.growth = (self.adv.owner:getRealBattleValue(advTeam.heros) / 80) ^ 0.52 + math.floor(heroLevel / 50) / 50
52 player.level = 1 56 player.level = 1
53 player.exp = 0 57 player.exp = 0
54 player.sp = 100 58 player.sp = 100
55 local activeRelation = self.adv.owner:getHeroActiveRelation() 59 local activeRelation = self.adv.owner:getHeroActiveRelation()
56 - local baseAttr = csvdb["adv_unitCsv"][math.floor(self.adv.advInfo.chapter / 100)] 60 + local baseAttr = csvdb["adv_unitCsv"][math.floor(self.adv.chapterId / 100)]
57 for _, attr in pairs(AttsEnumEx) do 61 for _, attr in pairs(AttsEnumEx) do
58 if baseAttr[attr] then 62 if baseAttr[attr] then
59 player[attr] = baseAttr[attr] + baseAttr[attr] * player.growth * (player.level - 1) 63 player[attr] = baseAttr[attr] + baseAttr[attr] * player.growth * (player.level - 1)
60 end 64 end
61 end 65 end
62 player.hpMax = player.hp or 0 66 player.hpMax = player.hp or 0
63 - self.adv.advTeam.player = player  
64 self.isNewPlayer = true 67 self.isNewPlayer = true
  68 + advTeam.player = player
65 end 69 end
66 - self.player = Player.new(self, self.adv.advTeam.player) 70 + self.player = Player.new(self, player)
67 end 71 end
68 72
69 function Battle:initEnemys() 73 function Battle:initEnemys()
70 - for _, room in pairs(self.adv.rooms) do  
71 - for _, block in pairs(room.blocks) do  
72 - self:addEnemy(room, block) 74 + for idx, map in pairs(self.adv.maps) do
  75 + self:initMapEnemys(idx)
  76 + end
  77 +end
  78 +
  79 +function Battle:initMapEnemys(mapIdx)
  80 + self.enemys[mapIdx] = {}
  81 + local map = self.adv.maps[mapIdx]
  82 + if map then
  83 + for _, room in pairs(map.rooms) do
  84 + for _, block in pairs(room.blocks) do
  85 + self:addEnemy(room, block, mapIdx)
  86 + end
  87 + end
  88 + end
  89 + if self.cachePassiveEvent[mapIdx] then
  90 + for _, passiveC in ipairs(self.cachePassiveEvent or {}) do
  91 + for _, enemy in ipairs(self.enemys[mapIdx]) do
  92 + enemy:triggerPassive(passiveC[1], passiveC[2])
  93 + end
73 end 94 end
74 end 95 end
  96 + self.cachePassiveEvent[mapIdx] = nil
75 end 97 end
76 98
77 -function Battle:addEnemy(room, block)  
78 - if block.event and (block.event.etype == AdvEventType.BOSS or block.event.etype == AdvEventType.Monster) then 99 +function Battle:addEnemy(room, block, mapIdx)
  100 + mapIdx = mapIdx or self.adv:getCurMapIdx()
  101 +
  102 + if block:isMonster() then
79 if not block.event.enemy then 103 if not block.event.enemy then
80 local enemyCsv = csvdb["event_monsterCsv"][block.event.id] 104 local enemyCsv = csvdb["event_monsterCsv"][block.event.id]
81 local enemy = {} 105 local enemy = {}
82 - enemy.hp = enemyCsv.hp + enemyCsv.levelhp * self.adv.advInfo.level  
83 - enemy.atk = enemyCsv.atk + enemyCsv.levelatk * self.adv.advInfo.level  
84 - enemy.hit = enemyCsv.hit + enemyCsv.levelhit * self.adv.advInfo.level  
85 - enemy.miss = enemyCsv.miss + enemyCsv.levelmiss * self.adv.advInfo.level  
86 - enemy.def = enemyCsv.def + enemyCsv.leveldef * self.adv.advInfo.level 106 + enemy.hp = enemyCsv.hp + enemyCsv.levelhp * self.adv.level
  107 + enemy.atk = enemyCsv.atk + enemyCsv.levelatk * self.adv.level
  108 + enemy.hit = enemyCsv.hit + enemyCsv.levelhit * self.adv.level
  109 + enemy.miss = enemyCsv.miss + enemyCsv.levelmiss * self.adv.level
  110 + enemy.def = enemyCsv.def + enemyCsv.leveldef * self.adv.level
87 enemy.passives = {} 111 enemy.passives = {}
88 for _, id in ipairs(enemyCsv.mapPassive:toArray(true, "=")) do 112 for _, id in ipairs(enemyCsv.mapPassive:toArray(true, "=")) do
89 table.insert(enemy.passives, {id = id}) 113 table.insert(enemy.passives, {id = id})
90 end 114 end
91 block.event.enemy = enemy 115 block.event.enemy = enemy
92 end 116 end
93 - local player = Enemy.new(self, block.event.mId or 999, block.event.id, room.roomId, block.blockId, not block.isOpen, block.event.enemy)  
94 - table.insert(self.enemys, player) 117 + local player = Enemy.new(self, block.event.mId or 999, block.event.id, room.roomId, block.blockId, not block.isOpen, block.event.enemy, mapIdx)
  118 + table.insert(self.enemys[mapIdx], player)
95 return player 119 return player
96 end 120 end
97 end 121 end
98 122
99 -function Battle:getEnemy(roomId, blockId)  
100 - for _, enemy in ipairs(self.enemys) do 123 +function Battle:getEnemy(roomId, blockId, mapIdx)
  124 + mapIdx = mapIdx or self.adv:getCurMapIdx()
  125 + for _, enemy in ipairs(self.enemys[mapIdx] or {}) do
101 if enemy.roomId == roomId and enemy.blockId == blockId then 126 if enemy.roomId == roomId and enemy.blockId == blockId then
102 return enemy 127 return enemy
103 end 128 end
@@ -105,45 +130,55 @@ function Battle:getEnemy(roomId, blockId) @@ -105,45 +130,55 @@ function Battle:getEnemy(roomId, blockId)
105 end 130 end
106 131
107 function Battle:getEnemyById(id) 132 function Battle:getEnemyById(id)
108 - for _, enemy in ipairs(self.enemys) do  
109 - if enemy.id == id then  
110 - return enemy 133 + for idx, mapEnemys in pairs(self.enemys) do
  134 + for _, enemy in ipairs(mapEnemys) do
  135 + if enemy.id == id then
  136 + return enemy
  137 + end
111 end 138 end
112 end 139 end
113 end 140 end
114 141
115 function Battle:getRBByEnemyId(enemyId) 142 function Battle:getRBByEnemyId(enemyId)
116 local enemy = self:getEnemyById(enemyId) 143 local enemy = self:getEnemyById(enemyId)
117 - return enemy.roomId, enemy.blockId 144 + return enemy.roomId, enemy.blockId, enemy.mapIdx
118 end 145 end
119 146
120 147
121 --触发全员被动技能 148 --触发全员被动技能
122 -function Battle:triggerPassive(condType, params) 149 +function Battle:triggerPassive(condType, params, mapIdx)
  150 + mapIdx = mapIdx or self.adv:getCurMapIdx()
123 self.player:triggerPassive(condType, params) 151 self.player:triggerPassive(condType, params)
124 - for _, enemy in ipairs(self.enemys) do  
125 - enemy:triggerPassive(condType, params) 152 + if not self.enemys[mapIdx] then
  153 + -- 缓存一下
  154 + self.cachePassiveEvent[mapIdx] = self.cachePassiveEvent[mapIdx] or {}
  155 + table.insert(self.cachePassiveEvent[mapIdx], {condType, params})
  156 + else
  157 + for _, enemy in ipairs(self.enemys[mapIdx]) do
  158 + enemy:triggerPassive(condType, params)
  159 + end
126 end 160 end
127 end 161 end
128 162
129 --回合 163 --回合
130 function Battle:afterRound() 164 function Battle:afterRound()
  165 + local mapIdx = self.adv:getCurMapIdx()
131 self.player:afterRound() 166 self.player:afterRound()
132 - table.sort(self.enemys, function(e1, e2) 167 + table.sort(self.enemys[mapIdx], function(e1, e2)
133 return e1.id < e2.id 168 return e1.id < e2.id
134 end) 169 end)
135 - for _, enemy in ipairs(self.enemys) do 170 + for _, enemy in ipairs(self.enemys[mapIdx]) do
136 enemy:afterRound() 171 enemy:afterRound()
137 end 172 end
138 self.player:clearRound() 173 self.player:clearRound()
139 - for _, enemy in ipairs(self.enemys) do 174 + for _, enemy in ipairs(self.enemys[mapIdx]) do
140 enemy:clearRound() 175 enemy:clearRound()
141 end 176 end
142 - for i = #self.enemys, 1, -1 do  
143 - if self.enemys[i].isDead then  
144 - self.adv:enemyDead(self.enemys[i].roomId, self.enemys[i].blockId)  
145 - self.enemys[i]:clear()  
146 - table.remove(self.enemys, i) 177 + for i = #self.enemys[mapIdx], 1, -1 do
  178 + if self.enemys[mapIdx][i].isDead then
  179 + self.adv:enemyDead(self.enemys[mapIdx][i].roomId, self.enemys[mapIdx][i].blockId)
  180 + self.enemys[mapIdx][i]:clear()
  181 + table.remove(self.enemys[mapIdx], i)
147 end 182 end
148 end 183 end
149 184
@@ -162,17 +197,25 @@ function Battle:battleBegin(roomId, blockId, params) @@ -162,17 +197,25 @@ function Battle:battleBegin(roomId, blockId, params)
162 enemy:hurt(enemy.hp, self.player, {hurtType = 5}) 197 enemy:hurt(enemy.hp, self.player, {hurtType = 5})
163 self.player:effectBattleBuff() 198 self.player:effectBattleBuff()
164 end 199 end
165 - self.player:hurt(math.max(0, math.ceil(self.player.hp - player.hp)), enemy, {hurtType = 5}) --战斗血量只会变少  
166 - self.player:changeSp(math.min(0, math.floor(player.sp - self.player.sp)) , 0) --战斗魔力只会变少 200 + if player.hp > self.player.hp then
  201 + self.player:recover(player.hp - self.player.hp, player)
  202 + else
  203 + self.player:hurt(math.max(0, math.ceil(self.player.hp - player.hp)), enemy, {hurtType = 5}) --战斗血量只会变少
  204 + end
  205 +
  206 + self.player:changeSp(math.floor(player.sp - self.player.sp) , 0) --战斗魔力只会变少
167 end 207 end
168 208
169 209
170 --写入数据 210 --写入数据
171 -function Battle:getDB()  
172 - self.adv.advTeam.player = self.player:getDB()  
173 - for _, enemy in ipairs(self.enemys) do  
174 - local block = self.adv.rooms[enemy.roomId].blocks[enemy.blockId]  
175 - block.event.enemy = enemy:getDB() 211 +function Battle:saveDB()
  212 + for idx, mapEnemys in pairs(self.enemys) do
  213 + for _, enemy in ipairs(mapEnemys) do
  214 + local block = self.adv:getBlock(enemy.roomId, enemy.blockId, idx)
  215 + if block and block:isMonster() then
  216 + block.event.enemy = enemy:getDB()
  217 + end
  218 + end
176 end 219 end
177 end 220 end
178 221
src/adv/AdvBlock.lua 0 → 100644
@@ -0,0 +1,108 @@ @@ -0,0 +1,108 @@
  1 +--块类型
  2 +local AdvCommon = require "adv.AdvCommon"
  3 +local Passive = require "adv.AdvPassive"
  4 +
  5 +local Block = class("AdvBlock")
  6 +function Block:ctor(room, blockId, event, isOpen, trapId)
  7 + self.room = room
  8 + self.blockId = blockId
  9 + self.col, self.row = AdvCommon.getCrById(self.blockId)
  10 +
  11 + self.isOpen = isOpen and true or false
  12 + self.trapId = trapId
  13 +
  14 + self:updateEvent(event)
  15 +end
  16 +function Block:isBoss()
  17 + return self:getEventType() == AdvEventType.BOSS
  18 +end
  19 +
  20 +function Block:isMonster()
  21 + return (self:getEventType() == AdvEventType.BOSS or self:getEventType() == AdvEventType.Monster)
  22 +end
  23 +
  24 +function Block:getEventType()
  25 + return self.event and self.event.etype
  26 +end
  27 +
  28 +function Block:updateEvent(event)
  29 + self.event = event
  30 +end
  31 +
  32 +function Block:clear()
  33 + if self:getEventType() == AdvEventType.Trap then
  34 + self.trapId = self.event.id
  35 + end
  36 + self.event = nil
  37 +end
  38 +
  39 +--事件有需要额外处理的部分
  40 +function Block:open()
  41 + local room = self.room
  42 + local map = room.map
  43 + local adv = map.adv
  44 + --如果翻开有数据处理在这里处理
  45 + local randomFunc = {}
  46 + --怪
  47 + randomFunc[AdvEventType.Monster] = function()
  48 + self.event.mId = adv.lastEnemyId --给怪一个有序id 回合逻辑时使用
  49 + adv.lastEnemyId = adv.lastEnemyId + 1
  50 + local enemy = adv.battle:getEnemy(room.roomId, self.blockId, map.mapIdx)
  51 + if enemy then
  52 + enemy:unlock(self.event.mId)
  53 + else
  54 + enemy = adv.battle:addEnemy(room, self, map.mapIdx)
  55 + end
  56 + enemy:triggerPassive(Passive.BORN_ONCE)
  57 + end
  58 + randomFunc[AdvEventType.BOSS] = randomFunc[AdvEventType.Monster]
  59 + --掉落
  60 + randomFunc[AdvEventType.Drop] = function()
  61 + self.event.item = csvdb["event_dropCsv"][self.event.id]["range"]:randWeight(true)
  62 + end
  63 + --交易
  64 + randomFunc[AdvEventType.Trader] = function()
  65 + local data = csvdb["event_traderCsv"][self.event.id]
  66 + self.event.shop = {}
  67 + self.event.status = "" --购买次数状态 1 就是购买过了 -- 购买id就是shop索引
  68 + for i = 1, 10 do
  69 + local numS, rangeS = "num" .. i, "range" .. i
  70 + if data[numS] and data[rangeS] then
  71 + for j = 1, data[numS] do
  72 + table.insert(self.event.shop, data[rangeS]:randWeight(true))
  73 + end
  74 + else
  75 + break
  76 + end
  77 + end
  78 + end
  79 + --建筑
  80 + randomFunc[AdvEventType.Build] = function()
  81 + local data = csvdb["event_buildingCsv"][self.event.id]
  82 + self.event.effect = data["range"]:randWeight(true) --随出建筑效果
  83 + if self.event.effect[1] == 1 then --获得某道具
  84 + local reward = csvdb["event_dropCsv"][self.event.effect[2]]["range"]:randWeight(true)
  85 + self.event.effect[2] = reward[1]
  86 + self.event.effect[3] = reward[2]
  87 + end
  88 + end
  89 +
  90 + randomFunc[AdvEventType.Trap] = function()
  91 + local data = csvdb["event_trapCsv"][self.event.id]
  92 + for _, buffId in ipairs(data.effect:toArray(true, "=")) do
  93 + adv.battle.player:addBuff(buffId)
  94 + end
  95 + adv:backTrap()
  96 + self:clear()
  97 + end
  98 +
  99 +
  100 + if self.event then -- 随机出具体的事件
  101 + if randomFunc[self:getEventType()] then
  102 + randomFunc[self:getEventType()]()
  103 + end
  104 + end
  105 + self.isOpen = true
  106 +end
  107 +
  108 +return Block
0 \ No newline at end of file 109 \ No newline at end of file
src/adv/AdvCommon.lua 0 → 100644
@@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
  1 +-- 工具函数--第一象限 < 10000 < 第二象限 < 20000 < 第四象限 < 30000 < 第三象限
  2 +
  3 +local AdvCommon = {}
  4 +
  5 +function AdvCommon.getIdByCr(c, r)
  6 + local crId = math.abs(r) + math.abs(c) * 100 -- row + column * 100
  7 + if c < 0 then
  8 + crId = crId + 10000
  9 + end
  10 + if r < 0 then
  11 + crId = crId + 20000
  12 + end
  13 + return crId
  14 +end
  15 +
  16 +function AdvCommon.getCrById(crId)
  17 + local c = math.floor(crId % 10000 / 100)
  18 + local r = crId % 100
  19 + local last = math.floor(crId / 10000)
  20 + if last == 3 then
  21 + c, r = -c, -r
  22 + elseif last == 1 then
  23 + c = -c
  24 + elseif last == 2 then
  25 + r = -r
  26 + end
  27 + return c, r
  28 +end
  29 +
  30 +--检查 是否满足层数限制条件 -- if checktype == 1 then check value in range a=b else check value in array a=b=c
  31 +function AdvCommon.checkIsIn(checkValue, checkType, checkRange)
  32 + if not checkValue then return end
  33 + if checkType == 1 then
  34 + local limits = checkRange:toNumMap()
  35 + for min, max in pairs(limits) do
  36 + if checkValue >= min and checkValue <= max then
  37 + return true
  38 + end
  39 + end
  40 + else
  41 + local limit = checkRange:toArray(true, "=")
  42 + for _, _l in ipairs(limit) do
  43 + if _l == checkValue then
  44 + return true
  45 + end
  46 + end
  47 + end
  48 +end
  49 +
  50 +return AdvCommon
0 \ No newline at end of file 51 \ No newline at end of file
src/adv/AdvMap.lua 0 → 100644
@@ -0,0 +1,383 @@ @@ -0,0 +1,383 @@
  1 +
  2 +local Room = require "adv.AdvRoom"
  3 +local Passive = require "adv.AdvPassive"
  4 +local AdvCommon = require "adv.AdvCommon"
  5 +-- 一层地图
  6 +local Map = class("AdvMap")
  7 +-- 内部方法声明
  8 +local createMap, getEventLib
  9 +
  10 +
  11 +function Map:ctor(adv, mapIdx, mapInfo)
  12 + self.adv = adv
  13 + if type(mapInfo) == "number" then -- mapInfo 传入 id
  14 + mapInfo = createMap(mapInfo, self.adv.chapterId, self.adv.level) -- 生成地图
  15 + end
  16 + if not mapInfo then return end
  17 +
  18 + self.mapIdx = mapIdx
  19 + self.mapId = mapInfo.mapId
  20 + self.rooms = {}
  21 + self:loadRooms(mapInfo.rooms)
  22 +end
  23 +
  24 +function Map:loadRooms(rooms)
  25 + local mapData = csvdb["map_" .. csvdb["mapCsv"][self.mapId]["path"] .. "Csv"]
  26 + for roomId, roomName in pairs(mapData["rooms"]) do
  27 + if roomName == "path" then
  28 + self.rooms[roomId] = Room.new(self, roomId, mapData["path"], rooms[roomId], true)
  29 + else
  30 + roomName = roomName:gsub("/", "_")
  31 + self.rooms[roomId] = Room.new(self, roomId, csvdb["room_" .. roomName .. "Csv"], rooms[roomId], false)
  32 + end
  33 + end
  34 +end
  35 +
  36 +function Map:getDB()
  37 + local map = {}
  38 + map.mapId = self.mapId
  39 + map.rooms = {}
  40 + for roomId, room in pairs(self.rooms) do
  41 + map.rooms[roomId] = room:getDB()
  42 + end
  43 + return map
  44 +end
  45 +
  46 +--结束本层的时候调用
  47 +function Map:checkOver()
  48 + local mapCsv = csvdb["mapCsv"][self.mapId]
  49 +
  50 + if mapCsv.clearType == 1 then -- 消耗
  51 + if self.adv:cost(mapCsv.clear:toNumMap()) then return true end
  52 + elseif mapCsv.clearType == 2 then -- 杀光
  53 + if #self.adv.battle.player:getTeam(2) == 0 then return true end
  54 + elseif mapCsv.clearType == 3 then -- 持有
  55 + if self.adv:cost(mapCsv.clear:toNumMap(), {}, true) then return true end
  56 + else
  57 + return true
  58 + end
  59 +end
  60 +
  61 +--随机一个空的位置生成怪, 如果没有就没有
  62 +function Map:addNewMonsterRand(monsterId, where)
  63 + local room, block
  64 + if where then
  65 + room, block = where[1], where[2]
  66 + else
  67 + local pool = {}
  68 + for _, room_ in pairs(self.rooms) do
  69 + for _, block_ in pairs(room_.blocks) do
  70 + if block_.isOpen and not block_.event then
  71 + table.insert(pool, {room_, block_})
  72 + end
  73 + end
  74 + end
  75 + if not next(pool) then return end
  76 + local idx = math.randomInt(1, #pool)
  77 + room, block = pool[idx][1], pool[idx][2]
  78 + end
  79 +
  80 + if not monsterId then
  81 + local eventLib = getEventLib(self.adv.chapterId, self.adv.level, AdvEventType.Monster)
  82 + if not next(eventLib[AdvEventType.Monster][0]) then return false end
  83 + monsterId = math.randWeight(eventLib[AdvEventType.Monster][0], "showup")
  84 + end
  85 +
  86 + local event = {etype = AdvEventType.Monster, mId = self.adv.lastEnemyId}
  87 + self.adv.lastEnemyId = self.adv.lastEnemyId + 1
  88 + event.id = monsterId
  89 + block:updateEvent(event)
  90 +
  91 + self.adv.battle:addEnemy(room, block):triggerPassive(Passive.BORN_ONCE)
  92 +
  93 + return room, block
  94 +end
  95 +
  96 +-- 随机翻开 num 个 以开放的房间的 地块
  97 +function Map:openBlockRand(num)
  98 + local pool = {}
  99 + for _, room in pairs(self.rooms) do
  100 + if room.isShow and not room.isPath then
  101 + for _, block in pairs(room.blocks) do
  102 + if not block.isOpen then
  103 + table.insert(pool, {room.roomId, block.blockId})
  104 + end
  105 + end
  106 + end
  107 + end
  108 + if #pool <= num then
  109 + for _, temp in ipairs(pool) do
  110 + self:openBlock(temp[1], temp[2])
  111 + end
  112 + else
  113 + for i = 1, num do
  114 + local idx = math.randomInt(1, #pool)
  115 + self:openBlock(pool[idx][1], pool[idx][2])
  116 + table.remove(pool, idx)
  117 + end
  118 + end
  119 +end
  120 +
  121 +
  122 +-- 打开一个地块
  123 +function Map:openBlock(roomId, blockId)
  124 + local room = self.rooms[roomId]
  125 + if not room then return end
  126 + local block = room.blocks[blockId]
  127 + if not block then return end
  128 + room:openBlock(block, self)
  129 + self:backBlockChange(roomId, blockId)
  130 +end
  131 +
  132 +
  133 +--获取,某个位置上的 room 和 block
  134 +function Map:getRBByPos(c, r)
  135 + for roomId, room in pairs(self.rooms) do
  136 + local block = room:getBByGPos(c, r)
  137 + if block then
  138 + return room, block
  139 + end
  140 + end
  141 +end
  142 +
  143 +function Map:getAroundBlocks(room, block)
  144 + local blocks = {}
  145 + local range = {1, -1}
  146 + local col, row = room:tranLtoG(block.col, block.row)
  147 + for _, add in ipairs(range) do
  148 + local rroom, rblock = self:getRBByPos(col + add, row)
  149 + if rroom then
  150 + table.insert(blocks, {rroom, rblock})
  151 + end
  152 + end
  153 + for _, add in ipairs(range) do
  154 + local rroom, rblock = self:getRBByPos(col, row + add)
  155 + if rroom then
  156 + table.insert(blocks, {rroom, rblock})
  157 + end
  158 + end
  159 + return blocks
  160 +end
  161 +
  162 +-----------------------------随机地图-----------------------------
  163 +
  164 +createMap = function(mapId, chapterId, level)
  165 + local mapInfo = {}
  166 + mapInfo.rooms = {}
  167 + mapInfo.mapId = mapId
  168 + local mapCsvData =csvdb["mapCsv"][mapId]
  169 + local mapData = csvdb["map_" .. mapCsvData["path"] .. "Csv"]
  170 + if not mapData then
  171 + error("mapId " .. mapId .. " dont exist!")
  172 + return
  173 + end
  174 + --事件随机
  175 + local eventLib = getEventLib(chapterId, level) -- 同时记录出现次数
  176 + local monsterEvents = {} --处理钥匙掉落
  177 + local haveBoss = false
  178 +
  179 +
  180 + local function randomEvent(roomId, blockId, eventType)
  181 + if mapInfo.rooms[roomId]["event"][blockId] then return end --已经有事件了 不覆盖
  182 + local etype, especial = eventType, 0
  183 + if eventType > 100 then -- 特殊事件(固定)
  184 + etype = math.floor(eventType / 100)
  185 + especial = eventType % 100
  186 + end
  187 +
  188 + local event = {etype = etype}
  189 + local randomFunc = {}
  190 +
  191 + local function randomCommon()
  192 + if not eventLib[etype] or not next(eventLib[etype]) or not eventLib[etype][especial] or not next(eventLib[etype][especial]) then return false end
  193 + event.id = math.randWeight(eventLib[etype][especial], "showup")
  194 + if not event.id then return false end
  195 + if eventLib[etype][especial][event.id].limit > 1 then
  196 + eventLib[etype][especial][event.id].limit = eventLib[etype][especial][event.id].limit - 1
  197 + elseif eventLib[etype][especial][event.id].limit == 1 then
  198 + eventLib[etype][especial][event.id] = nil
  199 + end
  200 + end
  201 +
  202 + --入口
  203 + randomFunc[AdvEventType.In] = function()end
  204 + --出口
  205 + randomFunc[AdvEventType.Out] = function() end
  206 + --boss
  207 + randomFunc[AdvEventType.BOSS] = function()
  208 + if haveBoss then return false end
  209 + if randomCommon() == false then
  210 + return false
  211 + end
  212 + haveBoss = true
  213 + end
  214 + --怪物
  215 + randomFunc[AdvEventType.Monster] = function()
  216 + if randomCommon() == false then
  217 + return false
  218 + end
  219 + table.insert(monsterEvents, event)
  220 + end
  221 +
  222 + --选择点
  223 + randomFunc[AdvEventType.Choose] = randomCommon
  224 + --掉落点
  225 + randomFunc[AdvEventType.Drop] = randomCommon
  226 + --交易所
  227 + randomFunc[AdvEventType.Trader] = randomCommon
  228 + --建筑
  229 + randomFunc[AdvEventType.Build] = randomCommon
  230 + --陷阱
  231 + randomFunc[AdvEventType.Trap] = randomCommon
  232 + --点击生效
  233 + randomFunc[AdvEventType.Click] = randomCommon
  234 + --跨层点
  235 + randomFunc[AdvEventType.Layer] = randomCommon
  236 +
  237 +
  238 + if randomFunc[etype] then
  239 + if randomFunc[etype]() ~= false then
  240 + if mapCsvData.clearType == 1 and etype == AdvEventType.BOSS then
  241 + event.item = mapCsvData.clear:toArray(true, "=")
  242 + end
  243 + mapInfo.rooms[roomId]["event"][blockId] = event
  244 + end
  245 + end
  246 + end
  247 +
  248 +
  249 + local stagePool = {["global"] = {}}
  250 + for roomId, roomName in pairs(mapData["rooms"]) do
  251 + stagePool[roomId] = {}
  252 + mapInfo.rooms[roomId] = {event = {}, open = {}, trap = {}} -- 事件, open open == 1 房间内地块全部开放
  253 + local roomData
  254 + if roomName == "path" then
  255 + roomData = mapData["path"]
  256 + else
  257 + roomName = roomName:gsub("/", "_")
  258 + roomData = csvdb["room_" .. roomName .. "Csv"]
  259 + end
  260 + for blockId, stageType in pairs(roomData["blocks"]) do
  261 + if AdvSpecialStage[stageType] then
  262 + local eventType = AdvEventType[AdvSpecialStage[stageType]] -- 地块固定类型
  263 + randomEvent(roomId, blockId, eventType)
  264 + else
  265 + stagePool["global"][stageType] = stagePool["global"][stageType] or {}
  266 + stagePool[roomId][stageType] = stagePool[roomId][stageType] or {}
  267 + table.insert(stagePool["global"][stageType], {room = roomId, block = blockId})
  268 + stagePool[roomId][stageType][blockId] = 1
  269 + end
  270 + end
  271 + end
  272 + -- 全地图事件 优先级高
  273 + for stageType, events in pairs(mapData["events"]) do
  274 + for _, event in ipairs(events) do
  275 + local lastCount = stagePool["global"][stageType] and #stagePool["global"][stageType] or 0
  276 + if lastCount <= 0 then break end
  277 + if math.randomFloat(0, 1) <= (event["rate"] or 1) then
  278 + local count = math.randomInt(math.min(lastCount, event["minc"]), math.min(lastCount, event["maxc"]))
  279 + for i = 1, count do
  280 + local idx = math.randomInt(1, lastCount)
  281 + local cur = stagePool["global"][stageType][idx]
  282 + randomEvent(cur["room"], cur["block"], event["event"])
  283 + table.remove(stagePool["global"][stageType], idx)
  284 + lastCount = lastCount - 1
  285 + stagePool[cur["room"]][stageType][cur["block"]] = nil
  286 + end
  287 + end
  288 + end
  289 + end
  290 + -- 随机单个房间的事件
  291 + for roomId, roomName in pairs(mapData["rooms"]) do
  292 + local roomData
  293 + if roomName == "path" then
  294 + roomData = mapData["path"]
  295 + else
  296 + roomName = roomName:gsub("/", "_")
  297 + roomData = csvdb["room_" .. roomName .. "Csv"]
  298 + end
  299 + for stageType, events in pairs(roomData["events"]) do
  300 + local bpool = {}
  301 + if stagePool[roomId][stageType] then
  302 + for block, _ in pairs(stagePool[roomId][stageType]) do
  303 + table.insert(bpool, block)
  304 + end
  305 + end
  306 + for _, event in ipairs(events) do
  307 + if #bpool <= 0 then break end
  308 + if math.randomFloat(0, 1) <= (event["rate"] or 1) then
  309 + local count = math.randomInt(math.min(#bpool, event["minc"]), math.min(#bpool, event["maxc"]))
  310 + for i = 1, count do
  311 + local idx = math.randomInt(1, #bpool)
  312 + randomEvent(roomId, bpool[idx], event["event"])
  313 + table.remove(bpool, idx)
  314 + end
  315 + end
  316 + end
  317 + end
  318 + end
  319 +
  320 + if mapCsvData.clearType == 1 and not haveBoss then
  321 + if not next(monsterEvents) then
  322 + error("这个地图没有钥匙!!! mapId : " .. mapId)
  323 + else
  324 + local event = monsterEvents[math.randomInt(1, #monsterEvents)]
  325 + event.item = mapCsvData.clear:toArray(true, "=") --掉落钥匙
  326 + end
  327 + end
  328 + return mapInfo
  329 +end
  330 +
  331 +--关卡事件库
  332 +getEventLib = function(chapterId, level, needEventType) -- needEventType 需要的事件
  333 + local chapter = math.floor(chapterId / 100) % 100
  334 +
  335 + local libsToType = {
  336 + ["event_monsterCsv"] = {AdvEventType.Monster, AdvEventType.BOSS, AdvEventType.Monster},
  337 + ["event_chooseCsv"] = AdvEventType.Choose,
  338 + ["event_dropCsv"] = AdvEventType.Drop,
  339 + ["event_buildingCsv"] = AdvEventType.Build,
  340 + ["event_traderCsv"] = AdvEventType.Trader,
  341 + ["event_trapCsv"] = AdvEventType.Trap,
  342 + ["event_clickCsv"] = AdvEventType.Click,
  343 + ["event_layerCsv"] = AdvEventType.Layer,
  344 +
  345 + }
  346 + local eventLib = {}
  347 + for lib, eventType in pairs(libsToType) do
  348 + -- init eventLib
  349 + if type(eventType) == "table" then
  350 + for _, temp in ipairs(eventType) do
  351 + eventLib[temp] = {}
  352 + end
  353 + else
  354 + eventLib[eventType] = {}
  355 + end
  356 + -- needEventType 只获取这个事件类型
  357 + if not needEventType or eventLib[needEventType] then
  358 + for id, data in pairs(csvdb[lib]) do
  359 + if data.levelchapter == chapter then
  360 + if AdvCommon.checkIsIn(level, data.leveltype, data.levellimit) then
  361 + if type(eventType) == "table" then
  362 + eventLib[eventType[data.type]][data.BlockEventType] = eventLib[eventType[data.type]][data.BlockEventType] or {}
  363 + eventLib[eventType[data.type]][data.BlockEventType][id] = {showup = data.showup, limit = data.limit}
  364 + else
  365 + eventLib[eventType][data.BlockEventType] = eventLib[eventType][data.BlockEventType] or {}
  366 + eventLib[eventType][data.BlockEventType][id] = {showup = data.showup, limit = data.limit}
  367 + end
  368 + end
  369 + end
  370 + end
  371 + if needEventType then
  372 + break
  373 + end
  374 + end
  375 + end
  376 + return eventLib
  377 +end
  378 +
  379 +
  380 +
  381 +return Map
  382 +
  383 +
src/adv/AdvPlayer.lua
@@ -327,7 +327,8 @@ function BaseObject:releaseSkill(skillId, target) @@ -327,7 +327,8 @@ function BaseObject:releaseSkill(skillId, target)
327 end 327 end
328 328
329 --0 全部 1 我方 2 敌方 329 --0 全部 1 我方 2 敌方
330 -function BaseObject:getTeam(nType, noSelf) 330 +function BaseObject:getTeam(nType, noSelf, mapIdx)
  331 + mapIdx = mapIdx or self.battle.adv:getCurMapIdx()
331 nType = nType or 0 332 nType = nType or 0
332 local team = {} 333 local team = {}
333 local function addPlayer() 334 local function addPlayer()
@@ -338,7 +339,7 @@ function BaseObject:getTeam(nType, noSelf) @@ -338,7 +339,7 @@ function BaseObject:getTeam(nType, noSelf)
338 end 339 end
339 end 340 end
340 local function addEnemy() 341 local function addEnemy()
341 - for _, enemy in pairs(self.battle.enemys) do 342 + for _, enemy in pairs(self.battle.enemys[mapIdx]) do
342 if not noSelf or enemy ~= self then 343 if not noSelf or enemy ~= self then
343 if not enemy.isDead and not enemy.lock then -- 已经翻开的 344 if not enemy.isDead and not enemy.lock then -- 已经翻开的
344 table.insert(team, enemy) 345 table.insert(team, enemy)
@@ -396,13 +397,14 @@ function BaseObject:changeSp() @@ -396,13 +397,14 @@ function BaseObject:changeSp()
396 end 397 end
397 398
398 local Enemy = class("Enemy", BaseObject) 399 local Enemy = class("Enemy", BaseObject)
399 -function Enemy:ctor(battle, mId, monsterId, roomId, blockId, lock, enemy) 400 +function Enemy:ctor(battle, mId, monsterId, roomId, blockId, lock, enemy, mapIdx)
400 Enemy.super.ctor(self, battle) 401 Enemy.super.ctor(self, battle)
401 self.id = mId 402 self.id = mId
402 self.monsterId = monsterId --数据id 403 self.monsterId = monsterId --数据id
403 self.roomId = roomId 404 self.roomId = roomId
404 self.blockId = blockId 405 self.blockId = blockId
405 self.lock = lock 406 self.lock = lock
  407 + self.mapIdx = mapIdx
406 self:initData(enemy) 408 self:initData(enemy)
407 end 409 end
408 function Enemy:unlock(id) 410 function Enemy:unlock(id)
src/adv/AdvRoom.lua 0 → 100644
@@ -0,0 +1,93 @@ @@ -0,0 +1,93 @@
  1 +-- 房间
  2 +
  3 +local AdvCommon = require "adv.AdvCommon"
  4 +local Block = require "adv.AdvBlock"
  5 +local Passive = require "adv.AdvPassive"
  6 +
  7 +local Room = class("AdvRoom")
  8 +function Room:ctor(map, roomId, csvData, info, isPath)
  9 + self.map = map
  10 + self.roomId = roomId
  11 + self.col, self.row = AdvCommon.getCrById(self.roomId)
  12 + self.isPath = isPath
  13 + self.isBossRoom = false -- boss房间 --击败boss 以后重置为false
  14 + self.isShow = false
  15 +
  16 + self.blocks = {}
  17 + self:loadBlocks(csvData, info)
  18 +
  19 +end
  20 +
  21 +function Room:loadBlocks(csvData, info)
  22 + for blockId, _ in pairs(csvData["blocks"]) do
  23 + self.blocks[blockId] = Block.new(self, blockId, info.event[blockId], info.open == 1 or info.open[blockId], info.trap[blockId])
  24 + if not self.isPath and self.blocks[blockId]:isBoss() then
  25 + self.isBossRoom = true
  26 + end
  27 + if self.blocks[blockId].isOpen then
  28 + self.isShow = true
  29 + else
  30 + if self.blocks[blockId]:getEventType() == AdvEventType.In then -- 开放
  31 + self.isShow = true
  32 + self.blocks[blockId].isOpen = true
  33 + --入口房间只会在这里首次展示开放 --触发固有技
  34 + self.map.adv:triggerPassive(Passive.ROOM_SHOW, {roomId = self.roomId})
  35 + end
  36 + end
  37 + end
  38 +end
  39 +
  40 +function Room:getDB()
  41 + local room = {event = {}, open = {}, trap = {}}
  42 + local allOpen = true
  43 + for blockId, block in pairs(self.blocks) do
  44 + room["event"][blockId] = block.event
  45 + room["open"][blockId] = block.isOpen and 1 or nil
  46 + if not block.isOpen then
  47 + allOpen = false
  48 + end
  49 + room["trap"][blockId] = block.trapId
  50 + end
  51 + if allOpen then
  52 + room["open"] = 1
  53 + end
  54 + return room
  55 +end
  56 +
  57 +function Room:openBlock(block)
  58 + if self.blocks[block.blockId] ~= block then return end
  59 + if block.isOpen == true then return end
  60 + if self.isBossRoom then
  61 + for _, _block in pairs(self.blocks) do
  62 + _block:open()
  63 + end
  64 + else
  65 + block:open()
  66 + end
  67 +
  68 + self.map.adv:scoreChange(AdvScoreType.Block)
  69 +
  70 + if not self.isShow then
  71 + self.isShow = true
  72 + --首次展示房间
  73 + self.map.adv:triggerPassive(Passive.ROOM_SHOW, {roomId = self.roomId})
  74 + end
  75 +end
  76 +
  77 +
  78 +function Room:tranGToL(c, r)
  79 + return c - self.col, r - self.row
  80 +end
  81 +
  82 +function Room:tranLtoG(c, r)
  83 + return c + self.col, r + self.row
  84 +end
  85 +
  86 +function Room:getBByGPos(c, r)
  87 + local c, r = self:tranGToL(c, r)
  88 + return self.blocks[AdvCommon.getIdByCr(c, r)]
  89 +end
  90 +
  91 +
  92 +
  93 +return Room
0 \ No newline at end of file 94 \ No newline at end of file
src/models/RolePlugin.lua
@@ -509,7 +509,6 @@ function RolePlugin.bind(Role) @@ -509,7 +509,6 @@ function RolePlugin.bind(Role)
509 function Role:getAdvData() 509 function Role:getAdvData()
510 if not self.advData then 510 if not self.advData then
511 self.advData = require("adv.Adv").new(self) 511 self.advData = require("adv.Adv").new(self)
512 - self.advData:initByInfo()  
513 end 512 end
514 return self.advData 513 return self.advData
515 end 514 end