Commit 43babcff6fcbfd9940df4a5a1faa71f1686d092d

Authored by zhouhaihai
1 parent 836228c9

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

src/GlobalVar.lua
... ... @@ -87,6 +87,7 @@ AdvEventType = {
87 87 Build = 5, --建筑物
88 88 Trap = 6, --陷阱
89 89 Click = 7, --点击生效
  90 + Layer = 8, --切换层的点
90 91 }
91 92  
92 93 AdvBackEventType = {
... ... @@ -106,7 +107,8 @@ AdvBackEventType = {
106 107 TurnEnd = 14, -- 回合结束
107 108 Miss = 15, -- miss
108 109 BattleBegin = 16, -- 战斗开始
109   - Trap = 17,
  110 + Trap = 17, --陷阱
  111 + Layer = 18, --切换层
110 112 }
111 113  
112 114 AdvScoreType = {
... ...
src/adv/Adv.lua
1 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 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 28 end
  29 +
  30 + self:initBattle()
48 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 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 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 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 89 end
364   - self.isOpen = true
  90 +
  91 + self.owner:updateProperties({advInfo = advInfo, advTeam = advTeam}, notNotify)
365 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 98 end
  99 + self.cachePassiveEvent = {}
395 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 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 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 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 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 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 131 end
449   - block.event = nil
450   - self.info.event[block.blockId] = nil
451 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 136 --关卡通关,非层 score < 0 失败
474 137 function Adv:over(success)
475 138 local score = self:getScore()
476   - local scoreInfo = self.advInfo.score
  139 + local scoreInfo = self.score
477 140 local reward
478 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 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 146 end
484   - table.clear(self.advInfo) --清空advInfo
485   - self.advTeam.player = nil --重置玩家的数据
486 147 self:clear()
487 148  
488 149 self.owner:updateProperty({field = "advItems", value = ""})
... ... @@ -495,162 +156,41 @@ function Adv:exit()
495 156 self:saveDB()
496 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 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 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 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 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 183 end
630 184 end
631 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 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 191 end
653 192  
  193 +
654 194 -- 在冒险中获得的物品都发放在冒险背包内
655 195 function Adv:award(gift, params)
656 196 params = params or {}
... ... @@ -707,13 +247,19 @@ end
707 247  
708 248 --事件点击处理
709 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 261 end
  262 +
717 263 return true
718 264 end
719 265 end
... ... @@ -739,17 +285,14 @@ local function clickChoose(self, room, block, params)
739 285 end,
740 286 -- xx角色(todo 队长)
741 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 291 end
749 292 end,
750 293 --消灭所有怪
751 294 [3] = function()
752   - for _, room in pairs(self.rooms) do
  295 + for _, room in pairs(self:getCurMap().rooms) do
753 296 for _, block in pairs(room.blocks) do
754 297 if block.event and (block.event.etype == AdvEventType.BOSS or block.event.etype == AdvEventType.Monster) then
755 298 return
... ... @@ -784,7 +327,7 @@ local function clickChoose(self, room, block, params)
784 327 self.battle.player:addBuff(effect[2])
785 328 end,
786 329 [3] = function() --发现怪物
787   - self:addNewMonsterRand(effect[2], {room, block})
  330 + self:getCurMap():addNewMonsterRand(effect[2], {room, block})
788 331 clearBlock = false
789 332 end,
790 333 [4] = function() --无事发生
... ... @@ -795,7 +338,7 @@ local function clickChoose(self, room, block, params)
795 338 end
796 339  
797 340 if clearBlock then
798   - room:clearBEvent(block)
  341 + block:clear()
799 342 end
800 343 return true
801 344 end
... ... @@ -804,7 +347,7 @@ local function clickDrop(self, room, block, params)
804 347 local reward = {}
805 348 if not block.event.item then return end
806 349 local reward = self:award({[block.event.item[1]] = block.event.item[2]})
807   - room:clearBEvent(block)
  350 + block:clear()
808 351 self:backReward(reward)
809 352 return true
810 353 end
... ... @@ -840,7 +383,7 @@ local function clickBuild(self, room, block, params)
840 383 self.battle.player:addBuff(effect[2])
841 384 end,
842 385 [3] = function() --发现怪物
843   - self:addNewMonsterRand(effect[2], {room, block})
  386 + self:getCurMap():addNewMonsterRand(effect[2], {room, block})
844 387 clearBlock = false
845 388 end,
846 389 [4] = function() --无事发生
... ... @@ -850,7 +393,7 @@ local function clickBuild(self, room, block, params)
850 393 if not self:cost(buildData.required:toNumMap(), {}) then return end
851 394 doEffect[effect[1]]()
852 395 if clearBlock then
853   - room:clearBEvent(block)
  396 + block:clear()
854 397 end
855 398 return true
856 399 end
... ... @@ -875,11 +418,28 @@ local function clickClick(self, room, block, params)
875 418 end,
876 419 }
877 420 if clearBlock then
878   - room:clearBEvent(block)
  421 + block:clear()
879 422 end
880 423 return true
881 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 443 local eventCallFunc = {
884 444 [AdvEventType.Out] = clickOut,
885 445 [AdvEventType.BOSS] = clickMonster,
... ... @@ -889,14 +449,15 @@ local eventCallFunc = {
889 449 [AdvEventType.Trader] = clickTrader,
890 450 [AdvEventType.Build] = clickBuild,
891 451 [AdvEventType.Click] = clickClick,
  452 + [AdvEventType.Layer] = clickLayer,
892 453 }
893 454  
894 455 --点击处理 roomId, blockId
895 456 --params 某些事件需要的客户端传递的参数
896 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 461 if not block then return end
901 462  
902 463 local status = false
... ... @@ -904,15 +465,15 @@ function Adv:clickBlock(roomId, blockId, params)
904 465 if not block.isOpen then
905 466 local canOpen = false --如果未开放是否可以开放
906 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 469 local _room, _block = one[1], one[2]
909 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 472 hadMonster = true
912 473 end
913 474 end
914 475 if canOpen and not hadMonster then --开放
915   - room:openBlock(block, self)
  476 + room:openBlock(block)
916 477 status = true
917 478 end
918 479 else
... ... @@ -922,15 +483,15 @@ function Adv:clickBlock(roomId, blockId, params)
922 483 return
923 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 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 489 end
929 490 end
930 491 end
931 492 local needChange = true
932 493 if clickEvent and block.event then
933   - if block.event.etype == AdvEventType.Out then
  494 + if block:getEventType() == AdvEventType.Out then
934 495 needChange = false
935 496 end
936 497 end
... ... @@ -991,34 +552,33 @@ end
991 552  
992 553 --敌人死亡
993 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 562 room.isBossRoom = false
1000 563 end
1001 564 if escape then
1002   - room:clearBEvent(block)
  565 + block:clear()
1003 566 else
1004 567 local monsterData = csvdb["event_monsterCsv"][block.event.id]
1005 568 self:scoreChange(AdvScoreType.Kill, monsterData.type)
1006 569  
1007 570 local item = block.event.item
1008 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 574 end
1016 575 if item[1] == 0 then
1017   - room:clearBEvent(block)
  576 + block:clear()
1018 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 582 end
1023 583 end
1024 584 end
... ... @@ -1090,6 +650,10 @@ function Adv:backTrap()
1090 650 self:pushBackEvent(AdvBackEventType.Trap, {})
1091 651 end
1092 652  
  653 +function Adv:backLayer()
  654 + self:pushBackEvent(AdvBackEventType.Layer, {})
  655 +end
  656 +
1093 657 function Adv:scoreChange(scoreType, pms)
1094 658 local cutTypes = {}
1095 659 local score = 0
... ... @@ -1097,7 +661,7 @@ function Adv:scoreChange(scoreType, pms)
1097 661 score = globalCsv.adv_score_floor
1098 662 end
1099 663 cutTypes[AdvScoreType.Kill] = function()
1100   - local chapterData = csvdb["adv_chapterCsv"][self.advInfo.chapter]
  664 + local chapterData = csvdb["adv_chapterCsv"][self.chapterId]
1101 665 score = globalCsv.adv_score_monster[pms] * chapterData["monRatio"]
1102 666 end
1103 667 cutTypes[AdvScoreType.Item] = function()
... ... @@ -1114,25 +678,23 @@ function Adv:scoreChange(scoreType, pms)
1114 678 else
1115 679 return
1116 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 683 end
1120 684  
1121 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 694 end
1131 695  
1132 696 function Adv:popBackEvents()
1133 697 local events = self.backEvents
1134   - -- TODO 缓存数据需要分类,防止发错,暂时只有战斗,可以不分
1135   - self.tempBackEvents = events
1136 698 self.backEvents = {}
1137 699 return events
1138 700 end
... ... @@ -1142,14 +704,6 @@ function Adv:afterRound()
1142 704 if self.battle then
1143 705 self.battle:afterRound()
1144 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 707 end
1154 708  
1155 709 return Adv
1156 710 \ No newline at end of file
... ...
src/adv/AdvBattle.lua
... ... @@ -7,7 +7,7 @@ function Battle:ctor(adv)
7 7 self.player = nil --玩家
8 8 self.isNewPlayer = false
9 9 self.enemys = {} --怪
10   - self.tempData = {} -- 临时回合数据
  10 + self.cachePassiveEvent = {}
11 11 self:initPlayer()
12 12 self:initEnemys()
13 13 self:initAfter()
... ... @@ -17,9 +17,11 @@ function Battle:ctor(adv)
17 17 end
18 18  
19 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 25 end
24 26 end
25 27 --[[
... ... @@ -33,12 +35,14 @@ end
33 35 --]]
34 36  
35 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 43 player.passives = {}
40 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 46 local hero = self.adv.owner.heros[heroId]
43 47 if hero then
44 48 heroLevel = heroLevel + hero:getProperty("level")
... ... @@ -48,56 +52,77 @@ function Battle:initPlayer()
48 52 end
49 53 end
50 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 56 player.level = 1
53 57 player.exp = 0
54 58 player.sp = 100
55 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 61 for _, attr in pairs(AttsEnumEx) do
58 62 if baseAttr[attr] then
59 63 player[attr] = baseAttr[attr] + baseAttr[attr] * player.growth * (player.level - 1)
60 64 end
61 65 end
62 66 player.hpMax = player.hp or 0
63   - self.adv.advTeam.player = player
64 67 self.isNewPlayer = true
  68 + advTeam.player = player
65 69 end
66   - self.player = Player.new(self, self.adv.advTeam.player)
  70 + self.player = Player.new(self, player)
67 71 end
68 72  
69 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 94 end
74 95 end
  96 + self.cachePassiveEvent[mapIdx] = nil
75 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 103 if not block.event.enemy then
80 104 local enemyCsv = csvdb["event_monsterCsv"][block.event.id]
81 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 111 enemy.passives = {}
88 112 for _, id in ipairs(enemyCsv.mapPassive:toArray(true, "=")) do
89 113 table.insert(enemy.passives, {id = id})
90 114 end
91 115 block.event.enemy = enemy
92 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 119 return player
96 120 end
97 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 126 if enemy.roomId == roomId and enemy.blockId == blockId then
102 127 return enemy
103 128 end
... ... @@ -105,45 +130,55 @@ function Battle:getEnemy(roomId, blockId)
105 130 end
106 131  
107 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 138 end
112 139 end
113 140 end
114 141  
115 142 function Battle:getRBByEnemyId(enemyId)
116 143 local enemy = self:getEnemyById(enemyId)
117   - return enemy.roomId, enemy.blockId
  144 + return enemy.roomId, enemy.blockId, enemy.mapIdx
118 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 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 160 end
127 161 end
128 162  
129 163 --回合
130 164 function Battle:afterRound()
  165 + local mapIdx = self.adv:getCurMapIdx()
131 166 self.player:afterRound()
132   - table.sort(self.enemys, function(e1, e2)
  167 + table.sort(self.enemys[mapIdx], function(e1, e2)
133 168 return e1.id < e2.id
134 169 end)
135   - for _, enemy in ipairs(self.enemys) do
  170 + for _, enemy in ipairs(self.enemys[mapIdx]) do
136 171 enemy:afterRound()
137 172 end
138 173 self.player:clearRound()
139   - for _, enemy in ipairs(self.enemys) do
  174 + for _, enemy in ipairs(self.enemys[mapIdx]) do
140 175 enemy:clearRound()
141 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 182 end
148 183 end
149 184  
... ... @@ -162,17 +197,25 @@ function Battle:battleBegin(roomId, blockId, params)
162 197 enemy:hurt(enemy.hp, self.player, {hurtType = 5})
163 198 self.player:effectBattleBuff()
164 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 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 219 end
177 220 end
178 221  
... ...
src/adv/AdvBlock.lua 0 → 100644
... ... @@ -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 109 \ No newline at end of file
... ...
src/adv/AdvCommon.lua 0 → 100644
... ... @@ -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 51 \ No newline at end of file
... ...
src/adv/AdvMap.lua 0 → 100644
... ... @@ -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 327 end
328 328  
329 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 332 nType = nType or 0
332 333 local team = {}
333 334 local function addPlayer()
... ... @@ -338,7 +339,7 @@ function BaseObject:getTeam(nType, noSelf)
338 339 end
339 340 end
340 341 local function addEnemy()
341   - for _, enemy in pairs(self.battle.enemys) do
  342 + for _, enemy in pairs(self.battle.enemys[mapIdx]) do
342 343 if not noSelf or enemy ~= self then
343 344 if not enemy.isDead and not enemy.lock then -- 已经翻开的
344 345 table.insert(team, enemy)
... ... @@ -396,13 +397,14 @@ function BaseObject:changeSp()
396 397 end
397 398  
398 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 401 Enemy.super.ctor(self, battle)
401 402 self.id = mId
402 403 self.monsterId = monsterId --数据id
403 404 self.roomId = roomId
404 405 self.blockId = blockId
405 406 self.lock = lock
  407 + self.mapIdx = mapIdx
406 408 self:initData(enemy)
407 409 end
408 410 function Enemy:unlock(id)
... ...
src/adv/AdvRoom.lua 0 → 100644
... ... @@ -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 94 \ No newline at end of file
... ...
src/models/RolePlugin.lua
... ... @@ -509,7 +509,6 @@ function RolePlugin.bind(Role)
509 509 function Role:getAdvData()
510 510 if not self.advData then
511 511 self.advData = require("adv.Adv").new(self)
512   - self.advData:initByInfo()
513 512 end
514 513 return self.advData
515 514 end
... ...