Commit 43babcff6fcbfd9940df4a5a1faa71f1686d092d
1 parent
836228c9
优化冒险结构 增加夹层功能
Showing
9 changed files
with
931 additions
and
697 deletions
Show diff stats
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 | ... | ... |
... | ... | @@ -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 | ... | ... |
... | ... | @@ -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 | ... | ... |
... | ... | @@ -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) | ... | ... |
... | ... | @@ -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