Commit 46fac6f1866667f3ba878d4cc6c1f9df991b1d01
1 parent
23d89d13
酱料
Showing
13 changed files
with
1988 additions
and
261 deletions
Show diff stats
src/GlobalVar.lua
... | ... | @@ -75,4 +75,17 @@ AdvEventType = { |
75 | 75 | Monster = 3, -- 普通怪 |
76 | 76 | Trader = 4, --商人 |
77 | 77 | Build = 5, --建筑物 |
78 | +} | |
79 | + | |
80 | +AdvBackEventType = { | |
81 | + Reward = 1 --奖励 | |
82 | + HpChange = 2 --血量改变 | |
83 | + AtkChange = 3 --攻击改变 | |
84 | + Buff = 4 --buff 改变 | |
85 | + Skill = 5 --释放技能 | |
86 | + Atk = 6 --攻击动作 | |
87 | + Next = 7 --进入下一层 | |
88 | + End = 8 -- 结束 | |
89 | + BlockChange = 9 -- 块改变 | |
90 | + | |
78 | 91 | } |
79 | 92 | \ No newline at end of file | ... | ... |
src/ProtocolCode.lua
src/actions/AdvAction.lua
... | ... | @@ -16,18 +16,74 @@ local table_unpack = table.unpack |
16 | 16 | |
17 | 17 | local _M = {} |
18 | 18 | |
19 | +--开始一个新的关卡 | |
19 | 20 | function _M.startAdvRpc( agent, data ) |
20 | 21 | local role = agent.role |
21 | 22 | local msg = MsgPack.unpack(data) |
22 | - | |
23 | + local chapterId = msg.chapterId | |
24 | + | |
25 | + --上一个关卡结束才可以开始新的关卡 | |
23 | 26 | local advInfo = role:getProperty("advInfo") |
27 | + if next(advInfo) then return end | |
28 | + role:getAdvData():initByChapter(chapterId, 1) | |
24 | 29 | |
25 | - role:randomAdvMap(10101, 1) --测试 | |
26 | - | |
27 | 30 | SendPacket(actionCodes.Adv_startAdvRpc, '') |
28 | 31 | return true |
29 | 32 | end |
30 | 33 | |
34 | +function _M.roleFormatRpc(agent , data) | |
35 | + local role = agent.role | |
36 | + local msg = MsgPack.unpack(data) | |
37 | + local advTeam = role:getProperty("advTeam") | |
38 | + for slot, heroId in ipairs(msg.heros) do | |
39 | + if not role.heros[heroId] then | |
40 | + return | |
41 | + end | |
42 | + end | |
43 | + table.clear(advTeam) | |
44 | + advTeam.heros = {} | |
45 | + for slot, heroId in ipairs(msg.heros) do | |
46 | + advTeam.heros[slot] = heroId | |
47 | + end | |
48 | + role:updateProperty({field = "advTeam", value = advTeam}) | |
49 | + SendPacket(actionCodes.Adv_roleFormatRpc, '') | |
50 | + return true | |
51 | +end | |
52 | + | |
53 | +-- 点击地块(解锁)(触发事件) | |
54 | +function _M.clickBlockRpc(agent, data) | |
55 | + local role = agent.role | |
56 | + local msg = MsgPack.unpack(data) | |
57 | + | |
58 | + local adv = role:getAdvData() | |
59 | + local status = adv:clickBlock(msg.roomId, msg.blockId, msg) | |
60 | + if not status then return end | |
61 | + SendPacket(actionCodes.Adv_clickBlockRpc, MsgPack.pack({events = adv:popBackEvents()})) | |
62 | + return true | |
63 | +end | |
64 | + | |
65 | +--use item 使用背包道具 | |
66 | +function _M.useItemRpc(agent, data) | |
67 | + local role = agent.role | |
68 | + local msg = MsgPack.unpack(data) | |
69 | + | |
70 | + local adv = role:getAdvData() | |
71 | + local status = adv:useItem(msg.itemId, msg.count, msg.target) -- target {roomId = 1, blockId = 1} 选择的目标 | |
72 | + if not status then return end | |
73 | + SendPacket(actionCodes.Adv_useItemRpc, MsgPack.pack({events = adv:popBackEvents()})) | |
74 | + return true | |
75 | +end | |
76 | + | |
77 | +--使用技能 | |
78 | +function _M.useSkillRpc(agent, data) | |
79 | + local role = agent.role | |
80 | + local msg = MsgPack.unpack(data) | |
81 | + local adv = role:getAdvData() | |
82 | + local status = adv:useSkill(msg.skillId, msg.target) -- target {roomId = 1, blockId = 1} 选择的目标 | |
83 | + if not status then return end | |
84 | + SendPacket(actionCodes.Adv_useSkillRpc, MsgPack.pack({events = adv:popBackEvents()})) | |
85 | + return true | |
86 | +end | |
31 | 87 | |
32 | 88 | |
33 | 89 | ... | ... |
... | ... | @@ -0,0 +1,965 @@ |
1 | +local Passive = require "adv.AdvPassive" | |
2 | + | |
3 | +-- 工具函数 | |
4 | +local function getIdByCr(c, r) | |
5 | + local crId = math.abs(r) + math.abs(c) * 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 | |
14 | + | |
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 | |
27 | +end | |
28 | + | |
29 | +-----------------------------随机地图----------------------------- | |
30 | +--检查 是否满足层数限制条件 | |
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 | |
47 | + end | |
48 | +end | |
49 | + | |
50 | +--关卡事件库 | |
51 | +local function getEventLib(chapterId, level, needEventType) | |
52 | + local chapter = math.floor(chapterId / 100) % 100 | |
53 | + | |
54 | + local libsToType = { | |
55 | + ["event_monsterCsv"] = {AdvEventType.Monster, AdvEventType.BOSS}, | |
56 | + ["event_chooseCsv"] = AdvEventType.Choose, | |
57 | + ["event_dropCsv"] = AdvEventType.Drop, | |
58 | + ["event_buildingCsv"] = AdvEventType.Build, | |
59 | + ["event_traderCsv"] = AdvEventType.Trader, | |
60 | + | |
61 | + } | |
62 | + local eventLib = {} | |
63 | + for lib, eventType in pairs(libsToType) do | |
64 | + if type(eventType) == "table" then | |
65 | + for _, temp in ipairs(eventType) do | |
66 | + eventLib[temp] = {} | |
67 | + end | |
68 | + else | |
69 | + eventLib[eventType] = {} | |
70 | + end | |
71 | + if not needEventType or eventLib[needEventType] then | |
72 | + for id, data in pairs(csvdb[lib]) do | |
73 | + if data.levelchapter == chapter then | |
74 | + if checkIsIn(level, data.leveltype, data.levellimit) then | |
75 | + if type(eventType) == "table" then | |
76 | + eventLib[eventType[data.type]][id] = data | |
77 | + else | |
78 | + eventLib[eventType][id] = data | |
79 | + end | |
80 | + end | |
81 | + end | |
82 | + end | |
83 | + if needEventType then | |
84 | + break | |
85 | + end | |
86 | + end | |
87 | + end | |
88 | + return eventLib | |
89 | +end | |
90 | + | |
91 | +-- 生成地图 是否可以生成地图上层判断 | |
92 | +local function randomAdvMap(role, chapterId, level, notNotify) | |
93 | + local chapterData = csvdb["adv_chapterCsv"][chapterId] | |
94 | + if not chapterData then return end | |
95 | + if level > chapterData.limitlevel then return end | |
96 | + --随出地图 | |
97 | + local raw_pool = chapterData.mapid:toArray(true, "=") | |
98 | + local advInfo = role:getProperty("advInfo") | |
99 | + local lastMapId = advInfo.mapId --非同一层不连续随出同一张类似的地图 | |
100 | + local lastChapterId = advInfo.chapter | |
101 | + local power = advInfo.power or 0 --体力 | |
102 | + local pool = {} | |
103 | + for _, mapId in ipairs(raw_pool) do | |
104 | + local temp = csvdb["mapCsv"][mapId] | |
105 | + if temp and (lastChapterId == chapterId or lastMapId ~= mapId) then --非同一层不连续随出同一张类似的地图 | |
106 | + if checkIsIn(level, temp.leveltype, temp.levellimit) then | |
107 | + table.insert(pool, mapId) | |
108 | + end | |
109 | + end | |
110 | + end | |
111 | + if not next(pool) then return end | |
112 | + local mapId = pool[math.randomInt(1, #pool)] | |
113 | + --随出事件 | |
114 | + local mapData = csvdb["map_" .. csvdb["mapCsv"][mapId]["path"] .. "Csv"] | |
115 | + if not mapData then return end | |
116 | + | |
117 | + | |
118 | + table.clear(advInfo) | |
119 | + advInfo.chapter = chapterId | |
120 | + advInfo.level = level | |
121 | + advInfo.mapId = mapId | |
122 | + advInfo.power = power | |
123 | + advInfo.enemyId = 1 --怪递增的索引 | |
124 | + advInfo.rooms = {} -- {[roomId] = {event = {}, open = {}},} -- event 事件信息(具体信息查看randomEvent), open 是否解锁 | |
125 | + | |
126 | + --事件随机 | |
127 | + local eventLib = getEventLib(chapterId, level) | |
128 | + local monsterEvents = {} --处理钥匙掉落 | |
129 | + local haveBoss = false | |
130 | + | |
131 | + local function randomEvent(roomId, blockId, eventType) | |
132 | + if advInfo.rooms[roomId]["event"][blockId] then return end --已经有事件了 不覆盖 | |
133 | + local event = {etype = eventType} | |
134 | + local randomFunc = {} | |
135 | + --入口 | |
136 | + randomFunc[AdvEventType.In] = function()end | |
137 | + --出口 | |
138 | + randomFunc[AdvEventType.Out] = function() end | |
139 | + | |
140 | + --boss | |
141 | + randomFunc[AdvEventType.BOSS] = function() | |
142 | + if not next(eventLib[eventType]) or haveBoss then return false end | |
143 | + haveBoss = true | |
144 | + event.id = math.randWeight(eventLib[eventType], "showup") | |
145 | + end | |
146 | + --怪物 | |
147 | + randomFunc[AdvEventType.Monster] = function() | |
148 | + if not next(eventLib[eventType]) then return false end | |
149 | + event.id = math.randWeight(eventLib[eventType], "showup") | |
150 | + table.insert(monsterEvents, event) | |
151 | + end | |
152 | + --选择点 | |
153 | + randomFunc[AdvEventType.Choose] = function() | |
154 | + if not next(eventLib[eventType]) then return false end | |
155 | + event.id = math.randWeight(eventLib[eventType], "showup") | |
156 | + end | |
157 | + --掉落点 | |
158 | + randomFunc[AdvEventType.Drop] = randomFunc[AdvEventType.Choose] | |
159 | + --交易所 | |
160 | + randomFunc[AdvEventType.Trader] = randomFunc[AdvEventType.Choose] | |
161 | + --建筑 | |
162 | + randomFunc[AdvEventType.Build] = randomFunc[AdvEventType.Choose] | |
163 | + | |
164 | + if randomFunc[eventType] then | |
165 | + if randomFunc[eventType]() ~= false then | |
166 | + advInfo.rooms[roomId]["event"][blockId] = event | |
167 | + end | |
168 | + end | |
169 | + end | |
170 | + | |
171 | + stagePool = {["global"] = {}} | |
172 | + for roomId, roomName in pairs(mapData["rooms"]) do | |
173 | + stagePool[roomId] = {} | |
174 | + advInfo.rooms[roomId] = {event = {}, open = {}} -- 事件, open open == 1 房间内地块全部开放 | |
175 | + local roomData | |
176 | + if roomName == "path" then | |
177 | + roomData = mapData["path"] | |
178 | + else | |
179 | + roomName = roomName:gsub("/", "_") | |
180 | + roomData = csvdb["room_" .. roomName .. "Csv"] | |
181 | + end | |
182 | + for blockId, stageType in pairs(roomData["blocks"]) do | |
183 | + if AdvSpecialStage[stageType] then | |
184 | + eventType = AdvEventType[AdvSpecialStage[stageType]] | |
185 | + randomEvent(roomId, blockId, eventType) | |
186 | + else | |
187 | + stagePool["global"][stageType] = stagePool["global"][stageType] or {} | |
188 | + stagePool[roomId][stageType] = stagePool[roomId][stageType] or {} | |
189 | + table.insert(stagePool["global"][stageType], {room = roomId, block = blockId}) | |
190 | + stagePool[roomId][stageType][blockId] = 1 | |
191 | + end | |
192 | + end | |
193 | + end | |
194 | + -- 全地图事件 优先级高 | |
195 | + for stageType, events in pairs(mapData["events"]) do | |
196 | + for _, event in ipairs(events) do | |
197 | + local lastCount = #stagePool["global"][stageType] | |
198 | + if lastCount <= 0 then break end | |
199 | + if math.randomFloat(0, 1) <= (event["rate"] or 1) then | |
200 | + local count = math.randomInt(math.min(lastCount, event["minc"]), math.min(lastCount, event["maxc"])) | |
201 | + for i = 1, count do | |
202 | + local idx = math.randomInt(1, lastCount) | |
203 | + local cur = stagePool["global"][stageType][idx] | |
204 | + randomEvent(cur["room"], cur["block"], event["event"]) | |
205 | + table.remove(stagePool["global"][stageType], idx) | |
206 | + lastCount = lastCount - 1 | |
207 | + stagePool[cur["room"]][stageType][cur["block"]] = nil | |
208 | + end | |
209 | + end | |
210 | + end | |
211 | + end | |
212 | + -- 随机单个房间的事件 | |
213 | + for roomId, roomName in pairs(mapData["rooms"]) do | |
214 | + local roomData | |
215 | + if roomName == "path" then | |
216 | + roomData = mapData["path"] | |
217 | + else | |
218 | + roomName = roomName:gsub("/", "_") | |
219 | + roomData = csvdb["room_" .. roomName .. "Csv"] | |
220 | + end | |
221 | + for stageType, events in pairs(roomData["events"]) do | |
222 | + local bpool = {} | |
223 | + if stagePool[roomId][stageType] then | |
224 | + for block, _ in pairs(stagePool[roomId][stageType]) do | |
225 | + table.insert(bpool, block) | |
226 | + end | |
227 | + end | |
228 | + for _, event in ipairs(events) do | |
229 | + if #bpool <= 0 then break end | |
230 | + if math.randomFloat(0, 1) <= (event["rate"] or 1) then | |
231 | + local count = math.randomInt(math.min(#bpool, event["minc"]), math.min(#bpool, event["maxc"])) | |
232 | + for i = 1, count do | |
233 | + local idx = math.randomInt(1, #bpool) | |
234 | + randomEvent(roomId, bpool[idx], event["event"]) | |
235 | + table.remove(bpool, idx) | |
236 | + end | |
237 | + end | |
238 | + end | |
239 | + end | |
240 | + end | |
241 | + if not haveBoss then | |
242 | + if not next(monsterEvents) then | |
243 | + print("这个地图没有钥匙!!! mapId : " .. mapId) | |
244 | + else | |
245 | + local event = monsterEvents[math.randomInt(1, #monsterEvents)] | |
246 | + event.item = {1, 1} --掉落钥匙 --todo | |
247 | + end | |
248 | + end | |
249 | +end | |
250 | + | |
251 | +--块类型 | |
252 | +local Block = class("Block") | |
253 | +function Block:ctor(blockId, event, isOpen) | |
254 | + self.blockId = blockId | |
255 | + self.col, self.row = getCrById(self.blockId) | |
256 | + self.isOpen = isOpen and true or false | |
257 | + self.event = event -- 拿到的是引用可以直接更新 | |
258 | +end | |
259 | +function Block:isBoss() | |
260 | + if not self.event then return end | |
261 | + return self.event["etype"] == AdvEventType.BOSS | |
262 | +end | |
263 | + | |
264 | +--事件有需要额外处理的部分 | |
265 | +function Block:open(adv, room) | |
266 | + --如果翻开有数据处理在这里处理 | |
267 | + local randomFunc = {} | |
268 | + --怪 | |
269 | + randomFunc[AdvEventType.Monster] = function() | |
270 | + self.event.mId = adv.advInfo.enemyId --给怪一个有序id 回合逻辑时使用 | |
271 | + adv.advInfo.enemyId = adv.advInfo.enemyId + 1 | |
272 | + local enemy = self.battle:getEnemy(room.roomId, self.blockId) | |
273 | + if enemy then | |
274 | + enemy:unlock(self.event.mId) | |
275 | + else | |
276 | + self.battle:addEnemy(room, self) | |
277 | + end | |
278 | + end | |
279 | + randomFunc[AdvEventType.BOSS] = randomFunc[AdvEventType.Monster] | |
280 | + --掉落 | |
281 | + randomFunc[AdvEventType.Drop] = function() | |
282 | + self.event.item = csvdb["event_dropCsv"][self.event.id]["range"]:randWeight(true) | |
283 | + end | |
284 | + --交易 | |
285 | + randomFunc[AdvEventType.Trader] = function() | |
286 | + local data = csvdb["event_traderCsv"][self.event.id] | |
287 | + self.event.shop = {} | |
288 | + self.event.status = "" --购买次数状态 1 就是购买过了 -- 购买id就是shop索引 | |
289 | + for i = 1, 10 do | |
290 | + local numS, rangeS = "num" .. i, "range" .. i | |
291 | + if data[numS] and data[rangeS] then | |
292 | + for j = 1, data[numS] do | |
293 | + table.insert(self.event.shop, data[rangeS]:randWeight(true)) | |
294 | + end | |
295 | + else | |
296 | + break | |
297 | + end | |
298 | + end | |
299 | + end | |
300 | + --建筑 | |
301 | + [AdvEventType.Build] = function() | |
302 | + local data = csvdb["event_buildingCsv"][self.event.id] | |
303 | + self.event.effect = data["range"]:randWeight(true) --随出建筑效果 | |
304 | + if self.event.effect[1] == 1 then --获得某道具 | |
305 | + local reward = csvdb["event_dropCsv"][self.event.effect[2]]["range"]:randWeight(true) | |
306 | + self.event.effect[2] = reward[1] | |
307 | + self.event.effect[3] = reward[2] | |
308 | + end | |
309 | + end | |
310 | + --抉择点 | |
311 | + [AdvEventType.Choose] = function() | |
312 | + local data = csvdb["event_chooseCsv"][self.event.id] | |
313 | + self.event.effect = {} | |
314 | + for i = 1, 2 do | |
315 | + self.event.effect[i] = data["button".. i .."effect"]:toArray(true, "=") | |
316 | + if self.event.effect[i][1] == 1 then --获得某道具 | |
317 | + local reward = csvdb["event_dropCsv"][self.event.effect[i][2]]["range"]:randWeight(true) | |
318 | + self.event.effect[i][2] = reward[1] | |
319 | + self.event.effect[i][3] = reward[2] | |
320 | + end | |
321 | + end | |
322 | + end | |
323 | + if self.event then -- 随机出具体的事件 | |
324 | + if randomFunc[self.event.etype] then | |
325 | + randomFunc[self.event.etype]() | |
326 | + end | |
327 | + end | |
328 | + self.isOpne = true | |
329 | +end | |
330 | + | |
331 | +local Room = class("Room") | |
332 | +function Room:ctor(adv, roomId, csvData, info, isPath) | |
333 | + self.roomId = roomId | |
334 | + self.col, self.row = getCrById(self.roomId) | |
335 | + self.isPath = isPath | |
336 | + self.isBossRoom = false -- boss房间 --击败boss 以后重置为false | |
337 | + self.info = info -- 拿到引用 方便更新advInfo | |
338 | + self.isShow = false | |
339 | + self.blocks = {} | |
340 | + | |
341 | + for blockId, _ in pairs(csvData["blocks"]) do | |
342 | + self.blocks[blockId] = Block.new(blockId, info.event[blockId], info.open == 1 or info.open[blockId]) | |
343 | + if not self.isPath and self.blocks[blockId]:isBoss() then | |
344 | + self.isBossRoom = true | |
345 | + end | |
346 | + if self.blocks[blockId].isOpen then | |
347 | + self.isShow = true | |
348 | + else | |
349 | + if self.blocks[blockId].event and self.blocks[blockId].event.etype == AdvEventType.In then -- 开放 | |
350 | + self.isShow = true | |
351 | + self.blocks[blockId].isOpen = true | |
352 | + self.info.open[blockId] = 1 | |
353 | + | |
354 | + --入口房间只会在这里首次展示开放 --触发固有技 | |
355 | + adv:triggerPassive(Passive.ROOM_SHOW, {roomId = self.roomId}) | |
356 | + end | |
357 | + end | |
358 | + end | |
359 | +end | |
360 | + | |
361 | +function Room:tranGToL(c, r) | |
362 | + return c - self.col, r - self.row | |
363 | +end | |
364 | + | |
365 | +function Room:tranLtoG(c, r) | |
366 | + return c + self.col, r + self.row | |
367 | +end | |
368 | + | |
369 | +function Room:getBByGPos(c, r) | |
370 | + local c, r = self:tranGToL(c, r) | |
371 | + return self.blocks[getIdByCr(c, r)] | |
372 | +end | |
373 | + | |
374 | +function Room:openBlock(block, adv) | |
375 | + if self.blocks[block.blockId] ~= block then return end | |
376 | + if block.isOpen == true then return end | |
377 | + block:open(adv, self) | |
378 | + local allOpen = true | |
379 | + if not self.isBossRoom then | |
380 | + for _, _block in pairs(self.blocks) do | |
381 | + if not _block.isOpen then | |
382 | + allOpen = false | |
383 | + break | |
384 | + end | |
385 | + end | |
386 | + end | |
387 | + | |
388 | + if allOpen then | |
389 | + self.info.open = 1 | |
390 | + else | |
391 | + self.info.open[block.blockId] = 1 | |
392 | + end | |
393 | + | |
394 | + if not self.isShow then | |
395 | + self.isShow = true | |
396 | + --首次展示房间 | |
397 | + adv:triggerPassive(Passive.ROOM_SHOW, {roomId = self.roomId}) | |
398 | + end | |
399 | +end | |
400 | + | |
401 | +function Room:clearBEvent(block) | |
402 | + if self.blocks[block.blockId] ~= block then return end | |
403 | + block.event = nil | |
404 | + self.info.event[block.blockId] = nil | |
405 | +end | |
406 | + | |
407 | + | |
408 | + | |
409 | +local Adv = class("Adv") | |
410 | +function Adv:ctor(owner) | |
411 | + assert(owner, "Adv instance must have owner(role)") | |
412 | + self.owner = owner | |
413 | + self.advInfo = self.owner:getProperty("advInfo") --这个变量置空使用 table.clear | |
414 | + self.advTeam = self.owner:getProperty("advTeam") --这个变量置空使用 table.clear | |
415 | + self:clear() | |
416 | + self.events = {} --发给客户端的事件组 | |
417 | +end | |
418 | + | |
419 | +-- 清空自己组织的数据 | |
420 | +function Adv:clear() | |
421 | + self.rooms = {} | |
422 | + self.cachePassiveEvent = {} -- 在battle 没有创建成功时 触发的被动技信息 | |
423 | + self.battle = nil -- 战斗逻辑 | |
424 | +end | |
425 | + | |
426 | +--关卡通关,非层 score < 0 失败 | |
427 | +function Adv:over(success) | |
428 | + local score = -1 | |
429 | + if success then | |
430 | + -- todo success 计算分数 | |
431 | + score = 1 | |
432 | + self.owner:updateProperty({field = "advPass", self.owner:getProperty("advPass"):setv(self.advInfo.chapter, score)}) | |
433 | + end | |
434 | + table.clear(self.advInfo) --清空advInfo | |
435 | + self.advTeam.player = nil --重置玩家的数据 | |
436 | + self:clear() | |
437 | + self:backEnd(score) | |
438 | +end | |
439 | + | |
440 | +function Adv:getMapInfo() | |
441 | + if not next(self.advInfo) then return end | |
442 | + return csvdb["mapCsv"][self.advInfo.mapId] | |
443 | +end | |
444 | + | |
445 | +function Adv:getMapData() | |
446 | + local mapInfo = self:getMapInfo() | |
447 | + if not mapInfo then return end | |
448 | + return csvdb["map_" .. self:getMapInfo()["path"] .. "Csv"] | |
449 | +end | |
450 | + | |
451 | +function Adv:initByInfo() | |
452 | + self:clear() | |
453 | + if not next(self.advInfo) then return end --未初始化的 advInfo | |
454 | + | |
455 | + local mapData = self:getMapData() | |
456 | + if not mapData then return end | |
457 | + | |
458 | + for roomId, roomName in pairs(mapData["rooms"]) do | |
459 | + if roomName == "path" then | |
460 | + self.rooms[roomId] = Room.new(self, roomId, mapData["path"], self.advInfo.rooms[roomId], true) | |
461 | + else | |
462 | + roomName = roomName:gsub("/", "_") | |
463 | + self.rooms[roomId] = Room.new(self, roomId, csvdb["room_" .. roomName .. "Csv"], self.advInfo.rooms[roomId], false) | |
464 | + end | |
465 | + end | |
466 | + self:initBattle() | |
467 | + return true | |
468 | +end | |
469 | + | |
470 | +function Adv:triggerPassive(condType, params) | |
471 | + if not self.battle then | |
472 | + table.insert(self.cachePassiveEvent, {condType, params}) | |
473 | + else | |
474 | + self.battle:triggerPassive(condType, params) | |
475 | + end | |
476 | +end | |
477 | + | |
478 | +function Adv:initBattle() | |
479 | + self.battle = require("adv.AdvBattle").new(self) | |
480 | + for _, passiveC in ipairs(self.cachePassiveEvent) do | |
481 | + self.battle:triggerPassive(passiveC[1], passiveC[2]) | |
482 | + end | |
483 | + self.cachePassiveEvent = {} | |
484 | +end | |
485 | + | |
486 | +-- 随机地图 | |
487 | +function Adv:initByChapter(chapterId, level, notNotify) | |
488 | + randomAdvMap(self.owner, chapterId, level, notNotify) | |
489 | + self:initByInfo() --初始化 | |
490 | + role:updateProperties({advInfo = self.advInfo, advTeam = self.advTeam}, notNotify) | |
491 | +end | |
492 | + | |
493 | +--获取,某个位置上的 room 和 block | |
494 | +function Adv:getRBByPos(c, r) | |
495 | + for roomId, room in pairs(self.rooms) do | |
496 | + local block = room:getBByGPos(c, r) | |
497 | + if block then | |
498 | + return room, block | |
499 | + end | |
500 | + end | |
501 | +end | |
502 | + | |
503 | +function Adv:getAroundBlocks(room, block) | |
504 | + local blocks = {} | |
505 | + local range = {1, -1} | |
506 | + local col, row = room:tranLtoG(block.col, block.row) | |
507 | + for _, add in ipairs(range) do | |
508 | + local rroom, rblock = self:getRBByPos(col + add, row) | |
509 | + if rroom then | |
510 | + table.insert(blocks, {rroom, rblock}) | |
511 | + end | |
512 | + end | |
513 | + for _, add in ipairs(range) do | |
514 | + local rroom, rblock = self:getRBByPos(col, row + add) | |
515 | + if rroom then | |
516 | + table.insert(blocks, {rroom, rblock}) | |
517 | + end | |
518 | + end | |
519 | + return blocks | |
520 | +end | |
521 | + | |
522 | +--随机一个空的位置生成怪, 如果没有就没有 | |
523 | +function Adv:addNewMonsterRand() | |
524 | + local pool = {} | |
525 | + for _, room in pairs(self.rooms) do | |
526 | + for _, block in pairs(self.blocks) do | |
527 | + if not block.event then | |
528 | + table.insert(pool, {room, block}) | |
529 | + end | |
530 | + end | |
531 | + end | |
532 | + if not next(pool) then return end | |
533 | + local idx = math.randomInt(1, #pool) | |
534 | + local room, block = pool[idx][1], pool[idx][2] | |
535 | + | |
536 | + local event = {mId = self.advInfo.enemyId} | |
537 | + self.advInfo.enemyId = self.advInfo.enemyId + 1 | |
538 | + | |
539 | + local eventLib = getEventLib(self.advInfo.chapter, self.advInfo.level, AdvEventType.Monster) | |
540 | + if not next(eventLib[AdvEventType.Monster]) then return false end | |
541 | + event.id = math.randWeight(eventLib[AdvEventType.Monster], "showup") | |
542 | + | |
543 | + block.event = event | |
544 | + room.info.event[block.blockId] = event | |
545 | + self.battle:addEnemy(room, block) | |
546 | + return room, block | |
547 | +end | |
548 | + | |
549 | +-- 随机翻开 num 个 以开放的房间的 地块 | |
550 | +function Adv:openBlockRand(num) | |
551 | + local pool = {} | |
552 | + for _, room in pairs(self.rooms) do | |
553 | + if room.isShow and not room.isPath then | |
554 | + for _, block in pairs(room.blocks) do | |
555 | + if not block.isOpen then | |
556 | + table.insert(pool, {room.roomId, block.blockId}) | |
557 | + end | |
558 | + end | |
559 | + end | |
560 | + end | |
561 | + if #pool <= num then | |
562 | + for _, temp in ipairs(pool) do | |
563 | + self:openBlock(temp[1], temp[2]) | |
564 | + end | |
565 | + else | |
566 | + for i = 1, num do | |
567 | + local idx = math.randomInt(1, #pool) | |
568 | + self:openBlock(pool[idx][1], pool[idx][2]) | |
569 | + table.remove(pool, idx) | |
570 | + end | |
571 | + end | |
572 | +end | |
573 | +-- 打开一个地块 | |
574 | +function Adv:openBlock(roomId, blockId) | |
575 | + local room = self.rooms[roomId] | |
576 | + local block = room.blocks[blockId] | |
577 | + room:openBlock(block, self) | |
578 | + self:backBlockChange(roomId, blockId) | |
579 | +end | |
580 | + | |
581 | +-- 在冒险中获得的物品都发放在冒险背包内 | |
582 | +function Adv:award(gift, params) | |
583 | + local tgift = {} | |
584 | + if type(gift) == "string" then | |
585 | + for _, one in pairs(gift:toTableArray(true)) do | |
586 | + tgift[one[1]] = (tgift[one[1]] or 0) + one[2] | |
587 | + end | |
588 | + else | |
589 | + tgift = gift | |
590 | + end | |
591 | + local items = self.owner:getProperty("advItems") | |
592 | + for itemId, count in pairs(tgift) do | |
593 | + local origin = items:getv(itemId, 0) | |
594 | + local nums = origin + count | |
595 | + if nums <= 0 then | |
596 | + items = items:delk(itemId) | |
597 | + nums = 0 | |
598 | + else | |
599 | + items = items:incrv(itemId, count) | |
600 | + end | |
601 | + end | |
602 | + self.owner:updateProperty({field = "advItems", value = items, notNotify = params.notNotify}) | |
603 | + return tgift | |
604 | +end | |
605 | + | |
606 | +-- 消耗物品 优先冒险背包 --check 只是检查够不够 | |
607 | +function Adv:cost(item, params, check) | |
608 | + local items = self.owner:getProperty("advItems") | |
609 | + local less = {} | |
610 | + local advCost = {} | |
611 | + for itemId, count in pairs(item) do | |
612 | + advCost[itemId] = - math.min(items:getv(itemId, 0), count) | |
613 | + if advCost[itemId] == 0 then | |
614 | + advCost[itemId] = nil | |
615 | + end | |
616 | + | |
617 | + local last = items:getv(itemId, 0) - count | |
618 | + if last < 0 then | |
619 | + less[itemId] = -last | |
620 | + end | |
621 | + | |
622 | + end | |
623 | + if next(less) and not self.owner:checkItemEnough(less) then return end --不够 | |
624 | + if check then return true end | |
625 | + self:award(advCost, params) | |
626 | + self.owner:costItems(less, params) | |
627 | + return true | |
628 | +end | |
629 | + | |
630 | +--事件点击处理 | |
631 | +local function clickOut(self, room, block, params) | |
632 | + if self:cost({[1] = 1}, {}) then --todo 钥匙id | |
633 | + if self.advInfo.level >= csvdb["adv_chapterCsv"][self.advInfo.chapter].limitlevel then --关卡结束 | |
634 | + self:over(true) | |
635 | + else | |
636 | + self:initByChapter(self.advInfo.chapter, self.advInfo.level + 1, true) | |
637 | + self:backNext() --下一关 | |
638 | + end | |
639 | + return true | |
640 | + end | |
641 | +end | |
642 | + | |
643 | +--战斗 普通攻击 | |
644 | +local function clickMonster(self, room, block, params) | |
645 | + self.battle:playerAtk(room.roomId, block.blockId) | |
646 | + return true | |
647 | +end | |
648 | + | |
649 | +local function clickChoose(self, room, block, params) | |
650 | + local choose = params.choose | |
651 | + local chooseData = csvdb["event_chooseCsv"][block.event.id] | |
652 | + if not chooseData or not chooseData["button".. choose .."cond"] then return end | |
653 | + | |
654 | + local cond = chooseData["button".. choose .."cond"]:toArray(true, "=") | |
655 | + local checkCond = { | |
656 | + -- 拥有道具 | |
657 | + [1] = function() | |
658 | + if self:cost({[cond[2]] = cond[3]}, {}, true) then | |
659 | + return true | |
660 | + end | |
661 | + end, | |
662 | + -- xx角色(todo 队长) | |
663 | + [2] = function() | |
664 | + for slot, heroId in pairs(self.advTeam.heros) do | |
665 | + if self.owner.heros[heroId] then | |
666 | + if self.owner.heros[heroId]:getProperty("type") == cond[2] then | |
667 | + return true | |
668 | + end | |
669 | + end | |
670 | + end | |
671 | + end, | |
672 | + --消灭所有怪 | |
673 | + [3] = function() | |
674 | + for _, room in pairs(self.rooms) do | |
675 | + for _, block in pairs(self.blocks) do | |
676 | + if block.event and (block.event.etype == AdvEventType.BOSS or block.event.etype == AdvEventType.Monster) then | |
677 | + return | |
678 | + end | |
679 | + end | |
680 | + end | |
681 | + return true | |
682 | + end, | |
683 | + --制定属性 > | |
684 | + [4] = function() | |
685 | + if (self.battle.player[AttsEnumEx[cond[2]]] or 0) > cond[3] then | |
686 | + return true | |
687 | + end | |
688 | + end, | |
689 | + } | |
690 | + assert(checkCond[cond[1]], "error cond, event_chooseCsv id :" .. block.event.id) | |
691 | + if not checkCond[cond[1]]() then return end | |
692 | + | |
693 | + local effect = block.event.effect[choose] | |
694 | + local doEffect = { | |
695 | + [1] = function() -- 获得某道具N个 | |
696 | + self:backReward(self:award({[effect[2]] = effect[3]}, {})) | |
697 | + end, | |
698 | + [2] = function() --获得冒险buff | |
699 | + self.battle.player:addBuff(effect[2]) | |
700 | + end, | |
701 | + [3] = function() --发现怪物 | |
702 | + local r, b = self:addNewMonsterRand() | |
703 | + self:backBlockChange(r.roomId, b.blockId) | |
704 | + end, | |
705 | + [4] = function() --无事发生 | |
706 | + end | |
707 | + } | |
708 | + assert(doEffect[effect[1]], "error effect, event_chooseCsv id :" .. block.event.id) | |
709 | + doEffect[effect[1]]() | |
710 | + room:clearBEvent(block) | |
711 | + return true | |
712 | +end | |
713 | + | |
714 | +local function clickDrop(self, room, block, params) | |
715 | + local reward = {} | |
716 | + if not block.event.item then return end | |
717 | + local reward = self:award({[block.event.item[1]] = block.event.item[2]}, {}) | |
718 | + room:clearBEvent(block) | |
719 | + self:backReward(reward) | |
720 | + return true | |
721 | +end | |
722 | + | |
723 | +local function clickTrader(self, room, block, params) | |
724 | + local buyId = params.id | |
725 | + local traderData = csvdb["event_traderCsv"][block.event.id] | |
726 | + if not traderData then return end -- 偷偷改表了 | |
727 | + | |
728 | + if not block.event.shop or not block.event.shop[buyId] then return end | |
729 | + if (block.event.status or ""):getv(buyId, 0) == 1 then return end -- 买过了 | |
730 | + | |
731 | + if not self:cost(traderData.type:toNumMap(), {}) then return end --不够 | |
732 | + | |
733 | + local reward = self:award({[block.event.shop[buyId][1]] = block.event.shop[buyId][2]}, {}) | |
734 | + block.event.status = block.event.status:setv(buyId, 1) | |
735 | + self:backReward(reward) | |
736 | + return true | |
737 | +end | |
738 | + | |
739 | +local function clickBuild(self, room, block, params) | |
740 | + local buildData = csvdb["event_buildingCsv"][block.event.id] | |
741 | + if not buildData then return end-- 偷偷改表了 | |
742 | + if not block.event.effect then return end -- 没有效果 气人不 | |
743 | + local effect = block.event.effect | |
744 | + --todo 效果生效 | |
745 | + local doEffect = { | |
746 | + [1] = function() -- 获得某道具N个 | |
747 | + self:backReward(self:award({[effect[2]] = effect[3]}, {})) | |
748 | + end, | |
749 | + [2] = function() --获得冒险buff | |
750 | + self.battle.player:addBuff(effect[2]) | |
751 | + end, | |
752 | + [3] = function() --发现怪物 | |
753 | + local r, b = self:addNewMonsterRand() | |
754 | + self:backBlockChange(r.roomId, b.blockId) | |
755 | + end, | |
756 | + [4] = function() --无事发生 | |
757 | + end | |
758 | + } | |
759 | + assert(doEffect[effect[1]], "error effect, event_buildingCsv id :" .. block.event.id) | |
760 | + if not self:cost({[buildData.type] = 1}, {}) then return end | |
761 | + doEffect[effect[1]]() | |
762 | + room:clearBEvent(block) | |
763 | + return true | |
764 | +end | |
765 | + | |
766 | +local eventCallFunc = { | |
767 | + [AdvEventType.Out] = clickOut, | |
768 | + [AdvEventType.BOSS] = clickMonster, | |
769 | + [AdvEventType.Monster] = clickMonster, | |
770 | + [AdvEventType.Choose] = clickChoose, | |
771 | + [AdvEventType.Drop] = clickDrop, | |
772 | + [AdvEventType.Trader] = clickTrader, | |
773 | + [AdvEventType.Build] = clickBuild, | |
774 | +} | |
775 | + | |
776 | +--点击处理 roomId, blockId | |
777 | +--params 某些事件需要的客户端传递的参数 | |
778 | +function Adv:clickBlock(roomId, blockId, params) | |
779 | + local room = self.rooms[roomId] | |
780 | + if not room then return end | |
781 | + local block = room.blocks[blockId] | |
782 | + if not block then return end | |
783 | + | |
784 | + local canOpen = false --如果未开放是否可以开放 | |
785 | + local hadMonster = false -- 周围是否有解锁的怪未击败 | |
786 | + for _, one in ipairs(self:getAroundBlocks(room, block)) do | |
787 | + local _room, _block = one[1], one[2] | |
788 | + if _block.isOpen then canOpen = true end | |
789 | + if _block.isOpen and _block.event and (_block.event.etype == AdvEventType.BOSS or _block.event.etype == AdvEventType.Monster) then | |
790 | + hadMonster = true | |
791 | + end | |
792 | + end | |
793 | + local status = false | |
794 | + if not block.isOpen then | |
795 | + if canOpen and not hadMonster then --开放 | |
796 | + room:openBlock(block, self) | |
797 | + status = true | |
798 | + end | |
799 | + else | |
800 | + --点了空地 | |
801 | + if not block.event then | |
802 | + return | |
803 | + end | |
804 | + --可点击的事件 | |
805 | + if not hadMonster and not room.isBossRoom then | |
806 | + if eventCallFunc[block.event.etype] then | |
807 | + status = eventCallFunc[block.event.etype](self, room, block, params) | |
808 | + end | |
809 | + end | |
810 | + end | |
811 | + if status and block.event.etype ~= AdvEventType.Out then --出去了就不计算回合了 | |
812 | + self:backBlockChange(roomId, blockId) | |
813 | + self:afterRound() | |
814 | + end | |
815 | + self.battle:getDB() | |
816 | + role:updateProperties({advInfo = self.advInfo, advTeam = self.advTeam}) | |
817 | + return status | |
818 | +end | |
819 | + | |
820 | +--使用道具产生效果 | |
821 | +function Adv:useItem(itemId, count, target) | |
822 | + count = count or 1 | |
823 | + local itemData = csvdb["adv_itemCsv"][itemId] | |
824 | + if not itemData then return end | |
825 | + --重置数量 | |
826 | + if itemData["function"] == 0 or itemData["function"] == 2 then count = 1 end | |
827 | + if not self:cost({[itemId] = count}, {}, true) then return true end | |
828 | + --消耗 | |
829 | + if itemData["function"] == 0 or itemData["function"] == 1 then | |
830 | + self:cost({[itemId] = count}, {}) | |
831 | + end | |
832 | + --生效 | |
833 | + if itemData.type == 1 or itemData.type == 0 then --技能 | |
834 | + self.battle.player:releaseSkill(itemData.effect, 1, target) | |
835 | + elseif itemData.type == 2 then --掉落 | |
836 | + local item = csvdb["event_dropCsv"][itemData.effect]["range"]:randWeight(true) | |
837 | + self:backReward(self:award({[item[1]] = item[2]}, {})) | |
838 | + else | |
839 | + return | |
840 | + end | |
841 | + | |
842 | + self:afterRound() | |
843 | + self.battle:getDB() | |
844 | + role:updateProperties({advInfo = self.advInfo, advTeam = self.advTeam}) | |
845 | + return true | |
846 | +end | |
847 | + | |
848 | +--使用技能 | |
849 | +function Adv:useSkill(skillId, target) | |
850 | + local skillLevel = nil | |
851 | + if skillId > 1000 then return end | |
852 | + for slot, heroId in pairs(self.advTeam.heros) do | |
853 | + if self.owner.heros[heroId] then | |
854 | + if csvdb["unitCsv"][self.owner.heros[heroId]:getSkinId()]["adv"] == skillId then | |
855 | + skillLevel = self.owner.heros[heroId]:getSkillLevel(4) | |
856 | + break | |
857 | + end | |
858 | + end | |
859 | + end | |
860 | + if not skillLevel then return end | |
861 | + local skillData = csvdb["adv_skillCsv"][skillId] | |
862 | + if self.advInfo.power < skillData.cost then return end | |
863 | + self.advInfo.power = self.advInfo.power - skillData.cost | |
864 | + if skillData.target:toArray(true, "=")[1] == 0 then | |
865 | + local enemy = self.battle:getEnemy(target.roomId, target.blockId) | |
866 | + if not enemy then return end | |
867 | + self.battle.player:releaseSkill(skillId, skillLevel, enemy) | |
868 | + else | |
869 | + self.battle.player:releaseSkill(skillId, skillLevel) | |
870 | + end | |
871 | + | |
872 | + self:afterRound() | |
873 | + self.battle:getDB() | |
874 | + role:updateProperties({advInfo = self.advInfo, advTeam = self.advTeam}) | |
875 | + return true | |
876 | +end | |
877 | + | |
878 | +--敌人死亡 | |
879 | +function Adv:enemyDead(roomId, blockId) | |
880 | + local block = self.rooms[roomId].blocks[blockId] | |
881 | + --死了以后掉东西 | |
882 | + if block.event and (block.event.etype == AdvEventType.BOSS or block.event.etype == AdvEventType.Monster) then --处理死亡 | |
883 | + local item = block.event.item | |
884 | + if not item then | |
885 | + if block.event.etype == AdvEventType.BOSS then | |
886 | + item = {1, 1} --todo 钥匙 | |
887 | + else | |
888 | + local monsterData = csvdb["event_monsterCsv"][block.event.id] | |
889 | + local dropData = csvdb["event_dropCsv"][monsterData.dropid] | |
890 | + item = dropData["range"]:randWeight(true) | |
891 | + end | |
892 | + end | |
893 | + table.clear(block.event) | |
894 | + block.event.etype = AdvEventType.Drop | |
895 | + block.event.item = item | |
896 | + end | |
897 | + self:backBlockChange(roomId, blockId) | |
898 | +end | |
899 | + | |
900 | +--cType 0 or nil 值 1 百分比 | |
901 | +function Adv:changePower(value, cType) | |
902 | + cType = cType or 0 | |
903 | + if cType == 0 then | |
904 | + self.advInfo.power = self.advInfo.power + value | |
905 | + elseif cType == 1 then | |
906 | + self.advInfo.power = self.advInfo.power + self.advInfo.power * value | |
907 | + end | |
908 | + self.advInfo.power = math.floor(math.max(0, self.advInfo.power)) | |
909 | +end | |
910 | + | |
911 | +function Adv:pushBackEvent(btype, params) | |
912 | + table.insert(self.backEvents, {btype = btype, params = params}) | |
913 | +end | |
914 | + | |
915 | +function Adv:backReward(items) | |
916 | + self:pushBackEvent(AdvBackEventType.Reward, {items = items}) | |
917 | +end | |
918 | +-- if is player enemyId is nil | |
919 | +--isMax 是否是改变血量上限 | |
920 | +function Adv:backHpChange(enemyId, change, isMax) | |
921 | + self:pushBackEvent(AdvBackEventType.HpChange, {enemyId = enemyId, change = change, isMax = isMax}) | |
922 | +end | |
923 | +-- if is player enemyId is nil | |
924 | +function Adv:backAtkChange(enemyId, change) | |
925 | + self:pushBackEvent(AdvBackEventType.AtkChange, {enemyId = enemyId, change = change}) | |
926 | +end | |
927 | +-- if is player enemyId is nil | |
928 | +function Adv:backBuff(enemyId, buffId, isDel) | |
929 | + self:pushBackEvent(AdvBackEventType.Buff, {enemyId = enemyId, buffId = buffId, isDel = isDel}) | |
930 | +end | |
931 | +-- if is player enemyId is nil | |
932 | +function Adv:backSkill(enemyId, skillId, receiver) | |
933 | + self:pushBackEvent(AdvBackEventType.Skill, {enemyId = enemyId, buffId = skillId, receiver = receiver}) | |
934 | +end | |
935 | + | |
936 | +function Adv:backNext() | |
937 | + self:pushBackEvent(AdvBackEventType.Next, {}) | |
938 | +end | |
939 | + | |
940 | +function Adv:backEnd(score) | |
941 | + self:pushBackEvent(AdvBackEventType.End, {score = score}) | |
942 | +end | |
943 | + | |
944 | +function Adv:backBlockChange(roomId, blockId) | |
945 | + self:pushBackEvent(AdvBackEventType.BlockChange, {roomId = roomId, blockId = blockId}) | |
946 | +end | |
947 | + | |
948 | +function Adv:backAtk(enemyId, receiver) | |
949 | + self:pushBackEvent(AdvBackEventType.Atk, {enemyId = enemyId, receiver = receiver}) | |
950 | +end | |
951 | + | |
952 | +function Adv:popBackEvents() | |
953 | + local events = self.backEvents | |
954 | + self.backEvents = {} | |
955 | + return events | |
956 | +end | |
957 | + | |
958 | +--回合事件处理 | |
959 | +function Adv:afterRound() | |
960 | + if self.battle then | |
961 | + self.battle:afterRound() | |
962 | + end | |
963 | +end | |
964 | + | |
965 | +return Adv | |
0 | 966 | \ No newline at end of file | ... | ... |
... | ... | @@ -0,0 +1,136 @@ |
1 | +local Player, Enemy = require "adv.advPlayer" | |
2 | +local Buff = require "adv.AdvBuff" | |
3 | +local AdvBattle = class("Battle") | |
4 | +function Battle:ctor(adv) | |
5 | + self.adv = adv | |
6 | + self.player = nil --玩家 | |
7 | + self.enemys = {} --怪 | |
8 | + self:initPlayer() | |
9 | + self:initEnemys() | |
10 | + self:initAfter() | |
11 | +end | |
12 | + | |
13 | +function Battle:initAfter() | |
14 | + self.player:initAfter(self.adv.advTeam.player) | |
15 | + for _, enemy in pairs(self.enemys) do | |
16 | + enemy:initAfter(self.adv.rooms[enemy.roomId].blocks[enemy.blockId].event.enemy) | |
17 | + end | |
18 | +end | |
19 | + | |
20 | +function Battle:initPlayer() | |
21 | + if not next(self.adv.advTeam.heros) then return end | |
22 | + if not self.adv.advTeam.player then | |
23 | + local hp = 0 | |
24 | + local player = {} | |
25 | + player.passives = {} | |
26 | + for slot, heroId in pairs(self.adv.advTeam.heros) do | |
27 | + if self.adv.owner.heros[heroId] then | |
28 | + hp = hp + self.adv.owner.heros[heroId]:getProperty("battleV") | |
29 | + local advSkillId = csvdb["unitCsv"][self.adv.owner.heros[heroId]:getSkinId()]["adv"] | |
30 | + if advSkillId > 1000 then | |
31 | + table.insert(player.passives, {id = advSkillId, level = self.adv.owner.heros[heroId]:getSkillLevel(4)}) | |
32 | + end | |
33 | + end | |
34 | + end | |
35 | + player.hp = hp | |
36 | + player.atk = player.hp * 0.1 --todo 系数是临时的 | |
37 | + player.miss = 0 | |
38 | + player.hit = 100 | |
39 | + self.adv.advTeam.player = player | |
40 | + end | |
41 | + self.player = Player.new(self, self.adv.advTeam.player) | |
42 | +end | |
43 | + | |
44 | +function Battle:initEnemys() | |
45 | + for _, room in pairs(self.adv.rooms) do | |
46 | + for _, block in pairs(room.blocks) do | |
47 | + self:addEnemy(room, block) | |
48 | + end | |
49 | + end | |
50 | +end | |
51 | + | |
52 | +function Battle:addEnemy(room, block) | |
53 | + if block.event and (block.event.etype == AdvEventType.BOSS or block.event.etype == AdvEventType.Monster) then | |
54 | + if not block.event.enemy then | |
55 | + local enemyCsv = csvdb["event_monsterCsv"][block.event.id] | |
56 | + local enemy = {} | |
57 | + enemy.hp = enemyCsv.hp + enemyCsv.levelhp * self.adv.advInfo.level | |
58 | + enemy.atk = enemyCsv.atk + enemyCsv.levelatk * self.adv.advInfo.level | |
59 | + enemy.hit = enemyCsv.hit + enemyCsv.levelhit * self.adv.advInfo.level | |
60 | + enemy.miss = enemyCsv.miss + enemyCsv.levelmiss * self.adv.advInfo.level | |
61 | + enemy.passives = {} | |
62 | + for _, id in ipairs(enemyCsv.passive:toArray(true, "=")) do | |
63 | + table.insert(enemy.passives, {id = id}) | |
64 | + end | |
65 | + block.event.enemy = enemy | |
66 | + table.insert(self.enemys, Enemy.new(self, block.event.mId or 999, block.event.id, room.roomId, block.blockId, not block.isOpen, block.event.enemy)) | |
67 | + end | |
68 | + end | |
69 | +end | |
70 | + | |
71 | +function Battle:getEnemy(roomId, blockId) | |
72 | + for _, enemy in ipairs(self.enemys) do | |
73 | + if enemy.roomId == roomId and enemy.blockId = blockId then | |
74 | + return enemy | |
75 | + end | |
76 | + end | |
77 | +end | |
78 | + | |
79 | +function Battle:getEnemyById(id) | |
80 | + for _, enemy in ipairs(self.enemys) do | |
81 | + if enemy.id == id then | |
82 | + return enemy | |
83 | + end | |
84 | + end | |
85 | +end | |
86 | +--普通攻击 | |
87 | +function Battle:playerAtk(roomId, blockId) | |
88 | + local enemy = self:getEnemy(roomId, blockId) | |
89 | + if enemy then | |
90 | + enemy:hurt(self.player:getHurtValue(), self.player, {hurtType = 1}) | |
91 | + --是否无法反击 | |
92 | + if not enemy:hadBuff(Buff.CANT_BACK_ATK) then | |
93 | + self.player:hurt(enemy:getHurtValue(), enemy, {hurtType = 1}) | |
94 | + end | |
95 | + end | |
96 | +end | |
97 | +--触发全员被动技能 | |
98 | +function Battle:triggerPassive(condType, params) | |
99 | + | |
100 | +end | |
101 | + | |
102 | +--回合 | |
103 | +function Battle:afterRound() | |
104 | + self.player:afterRound() | |
105 | + table.sort(self.enemys, function(e1, e2) | |
106 | + return e1.id < e2.id | |
107 | + end) | |
108 | + for _, enemy in ipairs(self.enemys) do | |
109 | + enemy:afterRound() | |
110 | + end | |
111 | + self.player:clearRound() | |
112 | + for _, enemy in ipairs(self.enemys) do | |
113 | + enemy:clearRound() | |
114 | + end | |
115 | + for i = #self.enemys, 1, -1 do | |
116 | + if self.enemys[i].isDead then | |
117 | + self.adv:enemyDead(self.enemys[i].roomId, self.enemys[i].blockId) | |
118 | + self.enemys[i]:clear() | |
119 | + table.remove(self.enemys, i) | |
120 | + end | |
121 | + end | |
122 | + if self.player.isDead then | |
123 | + self.adv:over(-1) | |
124 | + end | |
125 | +end | |
126 | + | |
127 | +--写入数据 | |
128 | +function Battle:getDB() | |
129 | + self.adv.advTeam.player = self.player:getDB() | |
130 | + for _, enemy in ipairs(self.enemys) do | |
131 | + local block = self.adv.rooms[enemy.roomId].blocks[enemy.blockId] | |
132 | + block.event.enemy = enemy:getDB() | |
133 | + end | |
134 | +end | |
135 | + | |
136 | +return AdvBattle | |
0 | 137 | \ No newline at end of file | ... | ... |
... | ... | @@ -0,0 +1,294 @@ |
1 | + | |
2 | +local Buff = class("Buff") | |
3 | + | |
4 | +Buff.HP_CHANGE = 1 --生命变化(每回合生效) | |
5 | +Buff.HP_MAX_CHANGE = 2 --生命上限变化(状态) | |
6 | +Buff.ATK_CHANGE = 3 --攻击变化(状态) | |
7 | +Buff.IMMNUE_ATK = 4 -- 免疫普通攻击 | |
8 | +Buff.BACK_HURT = 5 -- 伤害反弹 | |
9 | +Buff.HURT_CHANGE = 6 -- 伤害变化 | |
10 | +Buff.INJURED_CHANGE = 7 -- 受伤变化 | |
11 | +Buff.HURT_TRANSFER = 8 -- 侍宠(转移自己受到的伤害) | |
12 | +Buff.HURT_ABSORB = 9 -- 舍身(吸收他人受到的伤害) | |
13 | +Buff.CANT_BACK_ATK = 10 -- 无法反击 | |
14 | +Buff.IMMNUE_BUFF = 11 -- 免疫buff | |
15 | +Buff.CLEAR_BUFF = 12 -- 清除buff | |
16 | +Buff.CANT_SKILL = 13 -- 禁止技能 | |
17 | +Buff.OPEN_BLOCK = 14 -- 翻开格子(每回合) | |
18 | +Buff.POWER_CHANGE = 15 -- 体力变化(每回合) | |
19 | +Buff.HIT_CHANGE = 16 -- 命中变化(状态) | |
20 | +Buff.MISS_CHANGE = 17 -- 闪避变化(状态) | |
21 | + | |
22 | +--角色一些属性的变化 | |
23 | +local function commonAttr(_Buff, attrName) | |
24 | + _Buff._init = function(self, data) --初始化变化值 | |
25 | + self.owner:reSetAttr(attrName) | |
26 | + end | |
27 | + _Buff._effectValue = function(self) | |
28 | + return self.buffData.effectValue1, self.buffData.effectValue2 | |
29 | + end | |
30 | + _Buff._endBuff = function(self, data) | |
31 | + self.owner:reSetAttr(attrName) | |
32 | + end | |
33 | +end | |
34 | + | |
35 | +local BuffFactory = { | |
36 | + [Buff.HP_CHANGE] = function(_Buff) | |
37 | + _Buff._init = function(self, data) --初始化变化值 | |
38 | + self._changeV = 0 | |
39 | + if self.buffData.effectValue1 == 0 then --固定值 | |
40 | + self._changeV = self.buffData.effectValue2 | |
41 | + elseif self.buffData.effectValue1 == 1 then | |
42 | + local baseOwner = self.buffData.effectValue4 == 1 and self.owner or self.release | |
43 | + local attrs = {[0] = "hp", [1] = "hpMax", [2] = "atk"} | |
44 | + self._changeV = baseOwner[attrs[self.buffData.effectValue3]] * self.buffData.effectValue2 | |
45 | + end | |
46 | + if self._changeV < 0 then | |
47 | + self._changeV = -self.release:getHurtValue(-self._changeV) | |
48 | + end | |
49 | + end | |
50 | + _Buff._initDB = function(self, data) | |
51 | + self._changeV = data.cv | |
52 | + end | |
53 | + _Buff._afterRount = function(self) | |
54 | + if self._changeV > 0 then | |
55 | + self.owner:recover(self._changeV, self.release) | |
56 | + elseif self._changeV < 0 then | |
57 | + self.owner:hurt(-self._changeV, self.release, {hurtType = 2}) | |
58 | + end | |
59 | + end | |
60 | + _Buff._getDB = function(self) | |
61 | + return {cv = self._changeV} | |
62 | + end | |
63 | + end, | |
64 | + | |
65 | + [Buff.HP_MAX_CHANGE] = function(_Buff) | |
66 | + _Buff._init = function(self, data) --初始化变化值 | |
67 | + self._changeV = 0 | |
68 | + if self.buffData.effectValue1 == 0 then --固定值 | |
69 | + self._changeV = self.buffData.effectValue2 | |
70 | + elseif self.buffData.effectValue1 == 1 then | |
71 | + local baseOwner = self.buffData.effectValue4 == 1 and self.owner or self.release | |
72 | + local attrs = {[0] = "hp", [1] = "hpMax", [2] = "atk"} | |
73 | + self._changeV = baseOwner[attrs[self.buffData.effectValue3]] * self.buffData.effectValue2 | |
74 | + end | |
75 | + local old = self.owner.hpMax | |
76 | + self.owner.hpMax = math.max(1, self.owner.hpMax + self._changeV) | |
77 | + self._changeV = self.owner.hpMax - old | |
78 | + if self._changeV > 0 then | |
79 | + self.owner:recover(self._changeV, self.release) | |
80 | + elseif self._changeV < 0 then | |
81 | + self.owner:hurt(self.release:getHurtValue(-self._changeV), self.release, {hurtType = 2}) | |
82 | + self.owner.hp = math.min(self.owner.hpMax, self.owner.hp) | |
83 | + end | |
84 | + end | |
85 | + _Buff._initDB = function(self, data) | |
86 | + self._changeV = data.cv | |
87 | + end | |
88 | + _Buff._endBuff = function(self, data) | |
89 | + if self._changeV then | |
90 | + self.owner.hpMax = math.max(1, self.owner.hpMax - self._changeV) | |
91 | + self.owner.hp = math.min(self.owner.hpMax, self.owner.hp) | |
92 | + end | |
93 | + end | |
94 | + _Buff._getDB = function(self) | |
95 | + return {cv = self._changeV} | |
96 | + end | |
97 | + end, | |
98 | + [Buff.ATK_CHANGE] = function(_Buff) | |
99 | + commonAttr(_Buff, "atk") | |
100 | + end, | |
101 | + | |
102 | + [Buff.HIT_CHANGE] = function(_Buff) | |
103 | + commonAttr(_Buff, "hit") | |
104 | + end, | |
105 | + | |
106 | + [Buff.MISS_CHANGE] = function(_Buff) | |
107 | + commonAttr(_Buff, "miss") | |
108 | + end, | |
109 | + | |
110 | + [Buff.BACK_HURT] = function(_Buff) | |
111 | + _Buff._effectValue = function(self) | |
112 | + return self.buffData.effectValue1, self.buffData.effectValue2, self.buffData.effectValue3 | |
113 | + end | |
114 | + end, | |
115 | + | |
116 | + [Buff.HURT_CHANGE] = function(_Buff) | |
117 | + _Buff._effectValue = function(self) | |
118 | + return self.buffData.effectValue1, self.buffData.effectValue2 | |
119 | + end | |
120 | + end, | |
121 | + | |
122 | + [Buff.INJURED_CHANGE] = function(_Buff) | |
123 | + _Buff._effectValue = function(self) | |
124 | + return self.buffData.effectValue1, self.buffData.effectValue2 | |
125 | + end | |
126 | + end, | |
127 | + | |
128 | + [Buff.HURT_TRANSFER] = function(_Buff) | |
129 | + _Buff._effectValue = function(self) | |
130 | + return self.buffData.effectValue1, self.buffData.effectValue2 | |
131 | + end | |
132 | + end, | |
133 | + | |
134 | + [Buff.HURT_ABSORB] = function(_Buff) | |
135 | + _Buff._effectValue = function(self) | |
136 | + return self.buffData.effectValue1, self.buffData.effectValue2 | |
137 | + end | |
138 | + end, | |
139 | + | |
140 | + [Buff.IMMNUE_BUFF] = function(_Buff) | |
141 | + _Buff._init = function(self, data) | |
142 | + self.count = self.buffData.effectValue3 | |
143 | + end | |
144 | + _Buff._effectValue = function(self) | |
145 | + return self.buffData.effectValue1, self.buffData.effectValue2 | |
146 | + end | |
147 | + end, | |
148 | + | |
149 | + [Buff.CLEAR_BUFF] = function(_Buff) | |
150 | + _Buff._init = function(self, data) | |
151 | + self.count = self.buffData.effectValue3 | |
152 | + self:_afterRount() -- 挂上就清除一下子 | |
153 | + end | |
154 | + _Buff._afterRount = function(self) | |
155 | + local cType, aim = self:effectValue() | |
156 | + for _, buff in ipairs(self.buffs) do | |
157 | + if not buff.isDel and ((cType == 0 and buff.id == aim) or (cType == 1 and buff:getGroup() == aim)) then | |
158 | + buff.isDel = true | |
159 | + self:decCount() | |
160 | + end | |
161 | + end | |
162 | + end | |
163 | + _Buff._effectValue = function(self) | |
164 | + return self.buffData.effectValue1, self.buffData.effectValue2 | |
165 | + end | |
166 | + end, | |
167 | + | |
168 | + [Buff.OPEN_BLOCK] = function(_Buff) | |
169 | + _Buff._afterRount = function(self) | |
170 | + self.owner.battle.adv:openBlockRand(self.buffData.effectValue1) | |
171 | + end | |
172 | + end, | |
173 | + | |
174 | + [Buff.POWER_CHANGE] = function(_Buff) | |
175 | + _Buff._afterRount = function(self) | |
176 | + self.owner.battle.adv:changePower(self.buffData.effectValue2, self.buffData.effectValue1) | |
177 | + end | |
178 | + end | |
179 | +} | |
180 | + | |
181 | + | |
182 | +function Buff.create(owner, release, data) | |
183 | + local buff = Buff.new(owner, data.id) | |
184 | + buff:initNew(release, data) | |
185 | + return buff | |
186 | +end | |
187 | + | |
188 | +function Buff.load(owner, data) | |
189 | + local buff = Buff.new(owner, data.id) | |
190 | + buff:initByDB(data) | |
191 | + return buff | |
192 | +end | |
193 | + | |
194 | +function Buff:ctor(owner, id) | |
195 | + self.owner = owner | |
196 | + self.id = id | |
197 | + self.buffData = csvdb["adv_buffCsv"][self.id] | |
198 | + self.isDel = false | |
199 | + self.duration = 0 --剩余的回合 | |
200 | + self.count = -1 -- 可生效的次数 -1 无次数限制 | |
201 | + | |
202 | + if BuffFactory[self.buffData.type] then | |
203 | + BuffFactory[self.buffData.type](self) | |
204 | + end | |
205 | +end | |
206 | + | |
207 | +function Buff:initByDB(data) | |
208 | + if data.rele then | |
209 | + if data.rele == 0 then | |
210 | + self.release = self.owner.battle.player | |
211 | + else | |
212 | + self.release = self.owner.battle:getEnemyById(data.rele) | |
213 | + end | |
214 | + end | |
215 | + self.duration = data.dur | |
216 | + if data.count then | |
217 | + self.count = data.count | |
218 | + end | |
219 | + | |
220 | + if self._initDB then | |
221 | + self:_initDB(data) | |
222 | + end | |
223 | +end | |
224 | + | |
225 | +function Buff:initNew(release, data) | |
226 | + self.release = release | |
227 | + self.duration = self.buffData.duration | |
228 | + if self._init then | |
229 | + self:_init(data) | |
230 | + end | |
231 | +end | |
232 | + | |
233 | +function Buff:afterRound() | |
234 | + if self.isDel or self.owner.isDead then return end | |
235 | + | |
236 | + if self._afterRount then | |
237 | + self:_afterRount() | |
238 | + end | |
239 | + | |
240 | + if self.buffData.duration ~= 0 then | |
241 | + self.duration = self.duration - 1 | |
242 | + if self.duration <= 0 then | |
243 | + self.isDel = true | |
244 | + end | |
245 | + end | |
246 | +end | |
247 | + | |
248 | +function Buff:effectValue() | |
249 | + if self._effectValue then | |
250 | + return self:_effectValue() | |
251 | + end | |
252 | +end | |
253 | +--删除buff 时调用 | |
254 | +function Buff:endBuff() | |
255 | + if self._endBuff then | |
256 | + self:_endBuff() | |
257 | + end | |
258 | +end | |
259 | + | |
260 | +function Buff:getType() | |
261 | + return self.buffData.type | |
262 | +end | |
263 | + | |
264 | +function Buff:decCount() | |
265 | + if self.count == -1 then return end | |
266 | + self.count = self.count - 1 | |
267 | + if self.count <= 0 then | |
268 | + self.isDel = true | |
269 | + end | |
270 | +end | |
271 | + | |
272 | +function Buff:getGroup() | |
273 | + return self.buffData.group | |
274 | +end | |
275 | + | |
276 | +function Buff:getDB() | |
277 | + local db = {} | |
278 | + if self._getDB then | |
279 | + db = self:_getDB() | |
280 | + end | |
281 | + db.id = self.id | |
282 | + if self.release and not self.release.isDead then | |
283 | + db.rele = self.release.id or 0 --释放者的id (0 为玩家) (不存在 则释放者不存在或者已经死亡) | |
284 | + end | |
285 | + if self.buffData.duration ~= 0 then | |
286 | + db.dur = self.duration | |
287 | + end | |
288 | + if self.count ~= -1 then | |
289 | + db.count = self.count | |
290 | + end | |
291 | + return db | |
292 | +end | |
293 | + | |
294 | +return Buff | |
0 | 295 | \ No newline at end of file | ... | ... |
... | ... | @@ -0,0 +1,102 @@ |
1 | +local Passive = class("Passive") | |
2 | + | |
3 | +-- 每回合触发的使用 afterRound | |
4 | +-- 其他触发的使用 triggerPassive | |
5 | + | |
6 | +Passive.BORN_ONCE = 1 -- 自身出生(翻开所在格子)后M回合触发(1次) | |
7 | +Passive.BORN_PRE = 2 --自身出生(翻开所在格子)后每N回合触发1次 | |
8 | +Passive.HURT_PERCENT_SELF = 3 --自身,每损失N%生命值,触发1次 | |
9 | +Passive.HURT_PERCENT_TEAM = 4 --队友,每损失N%生命值,触发1次 | |
10 | +Passive.HP_LOW_SELF = 5 --自身生命值<N%时,每回合触发 | |
11 | +Passive.HP_LOW_TEAM = 6 --敌人生命值<N%时,每回合触发 | |
12 | +Passive.HP_UP_SELF = 7 --自身生命值>N%时,每回合触发 | |
13 | +Passive.HP_UP_TEAM = 8 --敌人生命值>N%时,每回合触发 | |
14 | +Passive.SELF_ATK = 9 --自身攻击N次后,触发1次 | |
15 | +Passive.SELF_HURT = 10 --自身受击N次后,触发1次 | |
16 | +Passive.TEAM_ATK = 11 --队友攻击N次后,触发1次 | |
17 | +Passive.TEAM_HURT = 12 --队友受击N次后,触发1次 | |
18 | +Passive.MONSTER_COUNT_UP = 13 --场上存在N个以上怪物,每回合触发 | |
19 | +Passive.MONSTER_COUNT_LOW = 14 --场上存在N个以下怪物,每回合触发 | |
20 | +Passive.SELF_DEAD = 15 --自身死亡后,触发1次 | |
21 | +Passive.TEAM_DEAD = 16 --队友死亡后,触发1次 | |
22 | +Passive.TARGET_SKILL = 17 --目标每使用N次技能,触发1次 | |
23 | +Passive.TEAM_SKILL = 18 --队友每使用N次技能,触发1次 | |
24 | +Passive.ROOM_SHOW = 19 --自身所在房间被展示时,触发1次 | |
25 | + | |
26 | +-- 不同的开启条件 | |
27 | +local PassiveFactory = { | |
28 | + [] | |
29 | +} | |
30 | + | |
31 | +function Passive:ctor(owner, data) | |
32 | + self.owner = owner | |
33 | + self.id = data.id | |
34 | + self.level = data.level or 1 | |
35 | + self.passiveData = csvdb["adv_skill_passiveCsv"][self.id][self.level] | |
36 | + self.isDel = false | |
37 | + self.round = data.round or 0 --触发剩余回合数 | |
38 | + self.count = data.count or 0 --触发剩余次数 | |
39 | + if PassiveFactory[self.passiveData.condition] then | |
40 | + PassiveFactory[self.passiveData.condition](self) | |
41 | + end | |
42 | +end | |
43 | + | |
44 | +function Passive:getCondType() | |
45 | + return self.passiveData.condition, self.passiveData.value | |
46 | +end | |
47 | + | |
48 | +function Passive:effect() | |
49 | + if self._effect then | |
50 | + self:_effect() | |
51 | + end | |
52 | + --次数为 -1 一局只能触发一次,触发过后删掉就可以 | |
53 | + if self.count == -1 then | |
54 | + self.isDel = true | |
55 | + end | |
56 | + if self.count > 0 then | |
57 | + self.count = self.count - 1 | |
58 | + self.round = self.passiveData.space | |
59 | + end | |
60 | +end | |
61 | + | |
62 | +function Passive:afterRound() | |
63 | + if self.isDel or self.owner.isDead then return end | |
64 | + if self._afterRound then | |
65 | + self:_afterRound() --有的触发自己检测在这里检查 | |
66 | + end | |
67 | + if self.round > 0 then --回合触发的 | |
68 | + self.round = self.round - 1 | |
69 | + if self.round == 0 then | |
70 | + self:effect() | |
71 | + end | |
72 | + end | |
73 | +end | |
74 | + | |
75 | +-- 正在触发中 | |
76 | +function Passive:isActive( ) | |
77 | + return self.count > 0 or self.round > 0 | |
78 | +end | |
79 | + | |
80 | +function Passive:trigger(condType, params) --触发检查 | |
81 | + if self:getCondType() ~= condType then return end | |
82 | + if self:isActive() then return end | |
83 | + | |
84 | + self.round = self.passiveData.delay --首次 | |
85 | + self.count = self.passiveData.count --次数 | |
86 | + -- 没有延迟就直接触发 | |
87 | + if self.round == 0 then | |
88 | + self:effect() | |
89 | + end | |
90 | +end | |
91 | + | |
92 | +function Passive:getDB() | |
93 | + local db = {} | |
94 | + if self._getDB then | |
95 | + db = self:_getDB() | |
96 | + end | |
97 | + db.id = self.id | |
98 | + db.level = self.level | |
99 | + db.round = self.round | |
100 | + db.count = self.count | |
101 | +end | |
102 | +return Passive | |
0 | 103 | \ No newline at end of file | ... | ... |
... | ... | @@ -0,0 +1,388 @@ |
1 | +-- 角色 | |
2 | +local Buff = require "adv.AdvBuff" | |
3 | +local Passive = require "adv.AdvPassive" | |
4 | + | |
5 | +local BaseObject = class("BaseObject") | |
6 | +function BaseObject:ctor(battle) | |
7 | + self.battle = battle | |
8 | + self.hpMax = 0 | |
9 | + self.hp = 0 | |
10 | + self.atk = 0 | |
11 | + self.aType = 0 --攻击类型 | |
12 | + self.lock = nil | |
13 | + self.passives = {} --固有技能 | |
14 | + self.buffs = {} --buff | |
15 | + self.isDead = false | |
16 | +end | |
17 | +--初始化角色 | |
18 | +function BaseObject:initData(data) | |
19 | + self.hpMax = data.hpMax or data.hp | |
20 | + self.hp = data.hp | |
21 | + --可变化的值 | |
22 | + self.atk = data.atk | |
23 | + self.miss = data.miss | |
24 | + self.hit = data.hit | |
25 | + --基础值记录 | |
26 | + self._atk = data._atk or self.atk | |
27 | + self._miss = data._miss or self.miss | |
28 | + self._hit = data._hit or self.hit | |
29 | +end | |
30 | +-- 角色初始化完以后才是 技能和被动技能 方便初始化 buff 的 释放对象 | |
31 | +function BaseObject:initAfter(data) | |
32 | + for _, passive in ipairs(data.passives or {}) do | |
33 | + table.insert(self.passives, Passive.load(self, passive)) | |
34 | + end | |
35 | + for _, buff in ipairs(data.buffs or {}) do | |
36 | + table.insert(self.buffs, Buff.load(self, buff)) | |
37 | + end | |
38 | +end | |
39 | + | |
40 | +function BaseObject:afterRound() | |
41 | + for _, passive in ipairs(self.passives) do | |
42 | + passive:afterRound(self) | |
43 | + end | |
44 | + for _, buff in ipairs(self.buffs) do | |
45 | + buff:afterRound(self) | |
46 | + end | |
47 | +end | |
48 | + | |
49 | +function BaseObject:clearRound() | |
50 | + for i = #self.passives, 1, -1 do | |
51 | + if self.passives[i].isDel then | |
52 | + self.passives[i]:endPassive() | |
53 | + table.remove(self.passives, i) | |
54 | + end | |
55 | + end | |
56 | + for i = #self.buffs, 1, -1 do | |
57 | + if self.buffs[i].isDel then | |
58 | + self.buffs[i]:endBuff() | |
59 | + table.remove(self.buffs, i) | |
60 | + end | |
61 | + end | |
62 | +end | |
63 | +function BaseObject:clear() | |
64 | + self.buffs = {} | |
65 | + self.passives = {} | |
66 | +end | |
67 | + | |
68 | +function BaseObject:addBuff(buffId, releaser) | |
69 | + local buffData = csvdb["adv_buffCsv"][buffId] | |
70 | + if not buffData then return end | |
71 | + for _, buff in ipairs(self.buffs) do | |
72 | + if not buff.isDel and (buff:getType() == CLEAR_BUFF or buff:getType() == IMMNUE_BUFF) then | |
73 | + local cType, aim = buff:effectValue() -- 0=buffid 1=buff组 | |
74 | + if (cType == 0 and buffId == aim) or (cType == 1 and buffData.group == aim) then -- buff 剔除 | |
75 | + buff:decCount() --减少次数 | |
76 | + return | |
77 | + end | |
78 | + end | |
79 | + end | |
80 | + table.insert(self.buffs, Buff.create(self, releaser, {id = buffId})) | |
81 | +end | |
82 | + | |
83 | +function BaseObject:hadBuff(bType) | |
84 | + for _, buff in ipairs(self.buffs) do | |
85 | + if not buff.isDel and buff:getType() == bType then | |
86 | + return true | |
87 | + end | |
88 | + end | |
89 | +end | |
90 | + | |
91 | +-- 通用的buff 效果汇总 -- 0 固定 1百分比 两种分类 | |
92 | +function BaseObject:getCommonBuffEffect(bType) | |
93 | + local effect, count = {[0] = 0, [1] = 0}, 0 | |
94 | + for _, buff in ipairs(self.buffs) do | |
95 | + if not buff.isDel and buff:getType() == bType then | |
96 | + local cType, value = buff:effectValue() | |
97 | + if cType then | |
98 | + change[cType] = change[cType] + value | |
99 | + count = count + 1 | |
100 | + end | |
101 | + end | |
102 | + end | |
103 | + return effect, count --效果 和生效的buff 个数 | |
104 | +end | |
105 | +--伤害反弹 | |
106 | +function BaseObject:getBackHurtBuff(isAtk) | |
107 | + local effect = {[0] = 0, [1] = 0} | |
108 | + for _, buff in ipairs(self.buffs) do | |
109 | + if not buff.isDel and buff:getType() == Buff.BACK_HURT then | |
110 | + local cType, value, aType = buff:effectValue() -- aType 0 全部 1 普通攻击 | |
111 | + if cType then | |
112 | + if aType == 0 or isAtk then | |
113 | + change[cType] = change[cType] + value | |
114 | + end | |
115 | + end | |
116 | + end | |
117 | + end | |
118 | + return effect | |
119 | +end | |
120 | + | |
121 | +--释放者伤害变化 | |
122 | +function BaseObject:getHurtChange() | |
123 | + local change = self:getCommonBuffEffect(Buff.HURT_CHANGE) | |
124 | + return change | |
125 | +end | |
126 | +--受伤者受伤变化 | |
127 | +function BaseObject:getInjuredChange() | |
128 | + local change = self:getCommonBuffEffect(Buff.INJURED_CHANGE) | |
129 | + return change | |
130 | +end | |
131 | +--重新计算属性 | |
132 | +function BaseObject:reSetAttr(field) | |
133 | + self[field] = self["_" .. field] --重置一下 | |
134 | + local fieldToBuff = {atk = Buff.IMMNUE_ATK, hit = Buff.HIT_CHANGE, miss = Buff.MISS_CHANGE} | |
135 | + local effect = self:getCommonBuffEffect(fieldToBuff[field]) | |
136 | + self[field] = (self[field] + effect[0]) * (1 + effect[1]) | |
137 | +end | |
138 | + | |
139 | +--计算打出伤害加成后的值 | |
140 | +function BaseObject:getHurtValue(value) | |
141 | + value = value or self.atk | |
142 | + local hurtChange = self:getHurtChange() | |
143 | + return math.max(0, (value + hurtChange[0]) * (1 + hurtChange[1])) | |
144 | +end | |
145 | +--计算自己伤害减免后的值 | |
146 | +function BaseObject:getInjuredValue(value) | |
147 | + local injuredChange = self:getInjuredChange() | |
148 | + return math.max(0, (value + injuredChange[0]) * (1 + injuredChange[1])) | |
149 | +end | |
150 | + | |
151 | +--最终伤害 = [ 敌方攻击 * (1+伤害增加百分比-伤害减少百分比)*(1+受伤增加百分比-受伤减少百分比)+(伤害增加固定值-伤害增加固定值+受伤增加固定值-受伤增加固定值)]*(1+侍宠百分比)-侍宠固定值 | |
152 | +-- params -- hurtType 1 普攻伤害 2 buff伤害 3 反弹伤害 | |
153 | +--进入这个方法之前计算好释放者加成的伤害 | |
154 | +function BaseObject:hurt(value, releaser, params) | |
155 | + params = params or {} | |
156 | + if params.hurtType and params.hurtType == 1 then | |
157 | + if self:hadBuff(Buff.IMMNUE_ATK) then return end --无视普通攻击 | |
158 | + | |
159 | + local hit = releaser.hit - self.miss --命中率 | |
160 | + if hit < math.randomInt(1, 100) then --miss | |
161 | + return | |
162 | + end | |
163 | + end | |
164 | + | |
165 | + value = self:getInjuredValue(value) --减伤计算 | |
166 | + if value == 0 then return end | |
167 | + | |
168 | + -- 舍身和恃宠 | |
169 | + local team = self:getTeam(1) | |
170 | + local transfer = {} | |
171 | + local absorb = {} | |
172 | + for _, one in ipairs(team) do | |
173 | + local change1, count1 = one:getCommonBuffEffect(Buff.INJURED_CHANGE) | |
174 | + local change2, count2 = one:getCommonBuffEffect(Buff.HURT_ABSORB) | |
175 | + if count1 > 0 then | |
176 | + table.insert(transfer, {one, change1, count1}) | |
177 | + end | |
178 | + if count2 > 0 then | |
179 | + table.insert(absorb, {one, change2, count2}) | |
180 | + end | |
181 | + end | |
182 | + if #absorb == 1 then --舍身优先级高 --舍身生效 | |
183 | + if absorb[1][1] ~= self then --舍身的人不是自己才有效 | |
184 | + local absorbV = (value - absorb[1][2][0]) * absorb[1][2][1] + absorb[1][2][0] --固定值先生效 | |
185 | + value = value - absorbV | |
186 | + absorb[1][1]:hurt(absorbV, releaser, params) | |
187 | + end | |
188 | + else | |
189 | + if #transfer == 1 and transfer[1][1] == self and #team > 1 then --侍宠 生效 | |
190 | + local transferValue = (value - transfer[1][2][0])* transfer[1][2][1] + transfer[1][2][0] --固定值先生效 | |
191 | + value = value - transferValue | |
192 | + local oneValue = transferValue / (#team - 1) | |
193 | + for _, one in ipairs(team) do | |
194 | + if one ~= self then | |
195 | + one:hurt(oneValue, releaser, params) | |
196 | + end | |
197 | + end | |
198 | + end | |
199 | + end | |
200 | + | |
201 | + value = math.max(0, value) | |
202 | + if value == 0 then return end | |
203 | + -- 反弹伤害 | |
204 | + if params.hurtType ~= 3 and releaser and not releaser.isDead then | |
205 | + local backEffect = self:getBackHurtBuff(params.hurtType == 1) | |
206 | + local backValue = math.max(0, value * backEffect[1] + backEffect[0]) | |
207 | + releaser:hurt(backValue, releaser, {hurtType = 3}) | |
208 | + end | |
209 | + | |
210 | + --受伤了~ | |
211 | + self.hp = math.max(0, self.hp - value) | |
212 | + if self.hp == 0 then | |
213 | + self.isDead = true | |
214 | + end | |
215 | +end | |
216 | +--恢复 | |
217 | +function BaseObject:recover(value, releaser, params) | |
218 | + params = params or {} | |
219 | + value = math.max(0, value) | |
220 | + self.hp = math.min(self.hpMax, self.hp + value) | |
221 | +end | |
222 | + | |
223 | +function BaseObject:releaseSkill(skillId, skillLevel, target) | |
224 | + skillLevel = skillLevel or 1 | |
225 | + local skillData = csvdb["adv_skillCsv"][skillId][skillLevel or 1] | |
226 | + local targetChoose = skillData.target:toArray(true, "=") | |
227 | + local targetNum = skillData.targetNum:toArray(true, "=") | |
228 | + --确定目标 | |
229 | + local targets = {} | |
230 | + if targetChoose[1] == 0 then --选定一个 | |
231 | + assert(target, "error " .. self.class.__cname .. " releaseSkill id: " .. skillId .." targetChoose==0 but no target") | |
232 | + table.insert(targets, target) | |
233 | + elseif targetChoose[1] == 1 then --全部 | |
234 | + if not targetChoose[2] or targetChoose[2] == 0 then | |
235 | + targets = self:getTeam(0) | |
236 | + else --指定 monsterId | |
237 | + local team = self:getTeam(0) | |
238 | + for _, one in pairs(team) do | |
239 | + if one.monsterId and one.monsterId == targetChoose[2] then | |
240 | + table.insert(targets, one) | |
241 | + end | |
242 | + end | |
243 | + end | |
244 | + elseif targetChoose[1] == 2 then -- 我方 | |
245 | + if targetChoose[2] == 1 then | |
246 | + table.insert(targets, self) | |
247 | + elseif targetChoose[2] == 2 then | |
248 | + targets = self:getTeam(1, true) | |
249 | + elseif targetChoose[2] == 3 then | |
250 | + targets = self:getTeam(1) | |
251 | + end | |
252 | + elseif targetChoose[1] == 3 then -- 敌方 | |
253 | + targets = self:getTeam(2) | |
254 | + end | |
255 | + | |
256 | + if targetChoose[1] ~= 0 then -- 不是指定一个的进行 排序 和 数量筛选 | |
257 | + local tempT = targets | |
258 | + local targets = {} | |
259 | + local function randNum(isSort) | |
260 | + if #tempT <= targetNum[2] then | |
261 | + targets = tempT | |
262 | + return | |
263 | + end | |
264 | + if isSort then | |
265 | + for i = 1, targetNum[2] do | |
266 | + table.insert(targets, tempT[i]) | |
267 | + end | |
268 | + else | |
269 | + for i = 1, targetNum[2] do | |
270 | + local idx = math.randomInt(1, #tempT) | |
271 | + table.insert(targets, tempT[idx]) | |
272 | + table.remove(tempT, idx) | |
273 | + end | |
274 | + end | |
275 | + end | |
276 | + if targetNum[1] == 0 then --任意排序 | |
277 | + randNum(false) | |
278 | + elseif targetNum[1] == 1 then --血量从低到高 | |
279 | + table.sort(tempT, function(o1, o2) | |
280 | + return o1.hp < o2.hp | |
281 | + end) | |
282 | + randNum(true) | |
283 | + elseif targetNum[1] == 2 then --血量从高到低 | |
284 | + table.sort(tempT, function(o1, o2) | |
285 | + return o1.hp > o2.hp | |
286 | + end) | |
287 | + randNum(true) | |
288 | + else | |
289 | + targets = tempT --all | |
290 | + end | |
291 | + end | |
292 | + -- 增加buff | |
293 | + for _, buffId in ipairs(skillData.selfbuff:toArray(true, "=")) do | |
294 | + self:addBuff(buffId, self) | |
295 | + end | |
296 | + | |
297 | + for _, buffId in ipairs(skillData.targetbuff:toArray(true, "=")) do | |
298 | + for _, target_ in ipairs(targets) do | |
299 | + target_:addBuff(buffId, self) | |
300 | + end | |
301 | + end | |
302 | +end | |
303 | + | |
304 | +--0 全部 1 我方 2 敌方 | |
305 | +function BaseObject:getTeam(nType, noSelf) | |
306 | + nType = nType or 0 | |
307 | + local team = {} | |
308 | + local function addPlayer() | |
309 | + if not noSelf or self.battle.player ~= self then | |
310 | + if not self.battle.player.isDead then | |
311 | + table.insert(team, self.battle.player) | |
312 | + end | |
313 | + end | |
314 | + end | |
315 | + local function addEnemy() | |
316 | + for _, enemy in pairs(self.battle.enemys) do | |
317 | + if not noSelf or enemy ~= self then | |
318 | + if not enemy.isDead and not enemy.lock then -- 已经翻开的 | |
319 | + table.insert(team, enemy) | |
320 | + end | |
321 | + end | |
322 | + end | |
323 | + end | |
324 | + if nType == 0 then | |
325 | + addPlayer() | |
326 | + addEnemy() | |
327 | + elseif nType == 1 then | |
328 | + if self.class == Player then --玩家 | |
329 | + addPlayer() | |
330 | + else | |
331 | + addEnemy() | |
332 | + end | |
333 | + elseif nType == 2 then | |
334 | + if self.class == Player then --玩家 | |
335 | + addEnemy() | |
336 | + else | |
337 | + addPlayer() | |
338 | + end | |
339 | + end | |
340 | + return team | |
341 | +end | |
342 | + | |
343 | +function BaseObject:getDB() | |
344 | + local db = {} | |
345 | + db.hpMax = self.hpMax | |
346 | + db.hp = self.hp | |
347 | + local baseAttr = {"atk", "miss", "hit"} | |
348 | + for _, field in pairs(baseAttr) do | |
349 | + db[field] = self[field] | |
350 | + db["_"..field] = self["_" .. field] | |
351 | + end | |
352 | + db.passives = {} | |
353 | + for _, passive in ipairs(self.passives) do | |
354 | + table.insert(db.passives, passive:getDB()) | |
355 | + end | |
356 | + db.buff = {} | |
357 | + for _, buff in ipairs(self.buffs) do | |
358 | + table.insert(db.buffs, buff:getDB()) | |
359 | + end | |
360 | + return db | |
361 | +end | |
362 | + | |
363 | +function BaseObject:triggerPassive(condType, params) | |
364 | + | |
365 | +end | |
366 | + | |
367 | +local Enemy = class("Enemy", BaseObject) | |
368 | +function Enemy:ctor(battle, monsterId, id, roomId, blockId, lock, enemy) | |
369 | + Enemy.super.ctor(self, battle) | |
370 | + self.id = id | |
371 | + self.monsterId = monsterId | |
372 | + self.roomId = roomId | |
373 | + self.blockId = blockId | |
374 | + self.lock = lock | |
375 | + self:initData(enemy) | |
376 | +end | |
377 | +function Enemy:unlock(id) | |
378 | + self.id = id | |
379 | + self.lock = nil | |
380 | +end | |
381 | + | |
382 | +local Player = class("Player", BaseObject) | |
383 | +function Player:ctor(battle, data) | |
384 | + Player.super.ctor(self, battle) | |
385 | + self:initData(data) | |
386 | +end | |
387 | + | |
388 | +return Player, Enemy | |
0 | 389 | \ No newline at end of file | ... | ... |
src/models/HeroPlugin.lua
... | ... | @@ -121,6 +121,12 @@ function HeroPlugin.bind(Hero) |
121 | 121 | return csvdb["skill_blockCsv"][unitData.block] |
122 | 122 | elseif idx == 2 then |
123 | 123 | return csvdb["skill_specialCsv"][unitData.special] |
124 | + elseif idx == 4 then --冒险技能 | |
125 | + if unitData.adv > 1000 then | |
126 | + return csvdb["adv_skill_passiveCsv"][unitData.adv] | |
127 | + else | |
128 | + return csvdb["adv_skillCsv"][unitData.adv] | |
129 | + end | |
124 | 130 | end |
125 | 131 | return {} |
126 | 132 | end | ... | ... |
src/models/Role.lua
... | ... | @@ -2,12 +2,10 @@ local Role = class("Role", require("shared.ModelBase")) |
2 | 2 | |
3 | 3 | local RolePlugin = import(".RolePlugin") |
4 | 4 | local RoleTask = import(".RoleTask") |
5 | -local RoleAdv = import(".RoleAdv") | |
6 | 5 | local RoleActivity = import(".RoleActivity") |
7 | 6 | local RoleChangeStruct = import(".RoleChangeStruct") |
8 | 7 | RolePlugin.bind(Role) |
9 | 8 | RoleTask.bind(Role) |
10 | -RoleAdv.bind(Role) | |
11 | 9 | RoleActivity.bind(Role) |
12 | 10 | RoleChangeStruct.bind(Role) |
13 | 11 | |
... | ... | @@ -15,6 +13,7 @@ function Role:ctor( properties ) |
15 | 13 | Role.super.ctor(self, properties) |
16 | 14 | self.ignoreHeartbeat = false |
17 | 15 | self.heros = {} |
16 | + self.advData = nil | |
18 | 17 | end |
19 | 18 | |
20 | 19 | Role.schema = { |
... | ... | @@ -39,7 +38,9 @@ Role.schema = { |
39 | 38 | |
40 | 39 | --冒险相关 |
41 | 40 | advPass = {"string", ""}, -- 通关记录 |
42 | - advInfo = {"table", {}}, -- 其他信息 | |
41 | + advItems = {"string", ""}, -- 冒险临时背包 | |
42 | + advInfo = {"table", {}}, -- 冒险关卡信息 | |
43 | + advTeam = {"table", {}}, -- 冒险玩家队伍信息 | |
43 | 44 | |
44 | 45 | } |
45 | 46 | |
... | ... | @@ -145,6 +146,7 @@ function Role:data() |
145 | 146 | loveStatus = self:getProperty("loveStatus"):toNumMap(), |
146 | 147 | advPass = self:getProperty("advPass"), |
147 | 148 | advInfo = self:getProperty("advInfo"), |
149 | + advItems = self:getProperty("advItems"):toNumMap(), | |
148 | 150 | } |
149 | 151 | end |
150 | 152 | ... | ... |
src/models/RoleAdv.lua deleted
... | ... | @@ -1,250 +0,0 @@ |
1 | - | |
2 | -local RoleAdv = {} | |
3 | - | |
4 | -function RoleAdv.bind(Role) | |
5 | - | |
6 | - | |
7 | - local function getIdByCr(c, r) | |
8 | - local crId = math.abs(r) + math.abs(c) * 100 | |
9 | - if c < 0 then | |
10 | - crId = crId + 10000 | |
11 | - end | |
12 | - if r < 0 then | |
13 | - crId = crId + 20000 | |
14 | - end | |
15 | - return crId | |
16 | - end | |
17 | - local function getCrById(crId) | |
18 | - local c = math.floor(crId % 10000 / 100) | |
19 | - local r = crId % 100 | |
20 | - local last = math.floor(crId / 10000) | |
21 | - if last == 3 then | |
22 | - c, r = -c, -r | |
23 | - elseif last == 1 then | |
24 | - c = -c | |
25 | - elseif last == 2 then | |
26 | - r = -r | |
27 | - end | |
28 | - return c, r | |
29 | - end | |
30 | - | |
31 | - --检查 是否满足层数限制条件 | |
32 | - local function checkIsIn(checkValue, checkType, checkRange) | |
33 | - if not checkValue then return end | |
34 | - if checkType == 1 then | |
35 | - local limits = checkRange:toNumMap() | |
36 | - for min, max in pairs(limits) do | |
37 | - if checkValue >= min and checkValue <= max then | |
38 | - return true | |
39 | - end | |
40 | - end | |
41 | - else | |
42 | - local limit = checkRange:toArray(true, "=") | |
43 | - for _, _l in ipairs(limit) do | |
44 | - if _l == checkValue then | |
45 | - return true | |
46 | - end | |
47 | - end | |
48 | - end | |
49 | - end | |
50 | - | |
51 | - --关卡事件库 | |
52 | - local function getEventLib(chapterId, level) | |
53 | - local chapter = math.floor(chapterId / 100) % 100 | |
54 | - | |
55 | - local libsToType = { | |
56 | - ["event_monsterCsv"] = {AdvEventType.Monster, AdvEventType.BOSS}, | |
57 | - ["event_chooseCsv"] = AdvEventType.Choose, | |
58 | - ["event_dropCsv"] = AdvEventType.Drop, | |
59 | - ["event_buildingCsv"] = AdvEventType.Build, | |
60 | - ["event_traderCsv"] = AdvEventType.Trader, | |
61 | - | |
62 | - } | |
63 | - local eventLib = {} | |
64 | - for lib, eventType in pairs(libsToType) do | |
65 | - if type(eventType) == "table" then | |
66 | - for _, temp in ipairs(eventType) do | |
67 | - eventLib[temp] = {} | |
68 | - end | |
69 | - else | |
70 | - eventLib[eventType] = {} | |
71 | - end | |
72 | - for id, data in pairs(csvdb[lib]) do | |
73 | - if data.levelchapter == chapter then | |
74 | - if checkIsIn(level, data.leveltype, data.levellimit) then | |
75 | - if type(eventType) == "table" then | |
76 | - eventLib[eventType[data.type]][id] = data | |
77 | - else | |
78 | - eventLib[eventType][id] = data | |
79 | - end | |
80 | - end | |
81 | - end | |
82 | - end | |
83 | - end | |
84 | - return eventLib | |
85 | - end | |
86 | - | |
87 | - -- 生成地图 是否可以生成地图上层判断 | |
88 | - function Role:randomAdvMap(chapterId, level) | |
89 | - local chapterData = csvdb["adv_chapterCsv"][chapterId] | |
90 | - if not chapterData then return end | |
91 | - if level > chapterData.limitlevel then return end | |
92 | - --随出地图 | |
93 | - local raw_pool = chapterData.mapid:toArray(true, "=") | |
94 | - local advInfo = self:getProperty("advInfo") | |
95 | - local lastMapId = advInfo.mapId --非同一层不连续随出同一张类似的地图 | |
96 | - local lastChapterId = advInfo.chapter | |
97 | - local pool = {} | |
98 | - for _, mapId in ipairs(raw_pool) do | |
99 | - local temp = csvdb["mapCsv"][mapId] | |
100 | - if temp and (lastChapterId == chapterId or lastMapId ~= mapId) then --非同一层不连续随出同一张类似的地图 | |
101 | - if checkIsIn(level, temp.leveltype, temp.levellimit) then | |
102 | - table.insert(pool, mapId) | |
103 | - end | |
104 | - end | |
105 | - end | |
106 | - if not next(pool) then return end | |
107 | - local mapId = pool[math.randomInt(1, #pool)] | |
108 | - --随出事件 | |
109 | - local mapData = csvdb["map_" .. csvdb["mapCsv"][mapId]["path"] .. "Csv"] | |
110 | - if not mapData then return end | |
111 | - | |
112 | - table.clear(advInfo) | |
113 | - advInfo.chapter = chapterId | |
114 | - advInfo.level = level | |
115 | - advInfo.mapId = mapId | |
116 | - advInfo.rooms = {} -- {[roomId] = {event = {}, open = {}, isPath = nil},} -- event 事件信息(具体信息查看randomEvent), open 是否解锁 isPath 是否是路径 | |
117 | - | |
118 | - --事件随机 | |
119 | - local eventLib = getEventLib(chapterId, level) | |
120 | - local monsterEvents = {} --处理钥匙掉落 | |
121 | - local haveBoss = false | |
122 | - local function randomEvent(roomId, blockId, eventType) | |
123 | - if advInfo.rooms[roomId]["event"][blockId] then return end --已经有事件了 不覆盖 | |
124 | - local event = {etype = eventType} | |
125 | - local randomFunc = { | |
126 | - [AdvEventType.In] = function() | |
127 | - advInfo.rooms[roomId]["open"][blockId] = 1 | |
128 | - end, | |
129 | - [AdvEventType.Out] = function() | |
130 | - end, | |
131 | - [AdvEventType.BOSS] = function() | |
132 | - if not next(eventLib[eventType]) or haveBoss then return false end | |
133 | - haveBoss = true | |
134 | - event.id = math.randWeight(eventLib[eventType], "showup") | |
135 | - end, | |
136 | - [AdvEventType.Choose] = function() | |
137 | - if not next(eventLib[eventType]) then return false end | |
138 | - event.id = math.randWeight(eventLib[eventType], "showup") | |
139 | - end, | |
140 | - [AdvEventType.Drop] = function() | |
141 | - if not next(eventLib[eventType]) then return false end | |
142 | - event.item = eventLib[eventType][math.randWeight(eventLib[eventType], "showup")]["range"]:randWeight(true) | |
143 | - end, | |
144 | - [AdvEventType.Monster] = function() | |
145 | - if not next(eventLib[eventType]) then return false end | |
146 | - event.id = math.randWeight(eventLib[eventType], "showup") | |
147 | - table.insert(monsterEvents, event) | |
148 | - end, | |
149 | - [AdvEventType.Trader] = function() | |
150 | - if not next(eventLib[eventType]) then return false end | |
151 | - event.id = math.randWeight(eventLib[eventType], "showup") | |
152 | - end, | |
153 | - [AdvEventType.Build] = function() | |
154 | - if not next(eventLib[eventType]) then return false end | |
155 | - event.id = math.randWeight(eventLib[eventType], "showup") | |
156 | - end, | |
157 | - } | |
158 | - | |
159 | - if randomFunc[eventType] then | |
160 | - if randomFunc[eventType]() ~= false then | |
161 | - advInfo.rooms[roomId]["event"][blockId] = event | |
162 | - end | |
163 | - end | |
164 | - end | |
165 | - | |
166 | - stagePool = {["global"] = {}} | |
167 | - for roomId, roomName in pairs(mapData["rooms"]) do | |
168 | - stagePool[roomId] = {} | |
169 | - advInfo.rooms[roomId] = {event = {}, open = {}} -- 事件, open | |
170 | - local roomData | |
171 | - if roomName == "path" then | |
172 | - advInfo.rooms[roomId].isPath = true | |
173 | - roomData = mapData["path"] | |
174 | - else | |
175 | - roomName = roomName:gsub("/", "_") | |
176 | - roomData = csvdb["room_" .. roomName .. "Csv"] | |
177 | - end | |
178 | - for blockId, stageType in pairs(roomData["blocks"]) do | |
179 | - if AdvSpecialStage[stageType] then | |
180 | - eventType = AdvEventType[AdvSpecialStage[stageType]] | |
181 | - randomEvent(roomId, blockId, eventType) | |
182 | - else | |
183 | - stagePool["global"][stageType] = stagePool["global"][stageType] or {} | |
184 | - stagePool[roomId][stageType] = stagePool[roomId][stageType] or {} | |
185 | - table.insert(stagePool["global"][stageType], {room = roomId, block = blockId}) | |
186 | - stagePool[roomId][stageType][blockId] = 1 | |
187 | - end | |
188 | - end | |
189 | - end | |
190 | - -- 全地图事件 优先级高 | |
191 | - for stageType, events in pairs(mapData["events"]) do | |
192 | - for _, event in ipairs(events) do | |
193 | - local lastCount = #stagePool["global"][stageType] | |
194 | - if lastCount <= 0 then break end | |
195 | - if math.randomFloat(0, 1) <= (event["rate"] or 1) then | |
196 | - local count = math.randomInt(math.min(lastCount, event["minc"]), math.min(lastCount, event["maxc"])) | |
197 | - for i = 1, count do | |
198 | - local idx = math.randomInt(1, lastCount) | |
199 | - local cur = stagePool["global"][stageType][idx] | |
200 | - randomEvent(cur["room"], cur["block"], event["event"]) | |
201 | - table.remove(stagePool["global"][stageType], idx) | |
202 | - lastCount = lastCount - 1 | |
203 | - stagePool[cur["room"]][stageType][cur["block"]] = nil | |
204 | - end | |
205 | - end | |
206 | - end | |
207 | - end | |
208 | - -- 随机单个房间的事件 | |
209 | - for roomId, roomName in pairs(mapData["rooms"]) do | |
210 | - local roomData | |
211 | - if roomName == "path" then | |
212 | - roomData = mapData["path"] | |
213 | - else | |
214 | - roomName = roomName:gsub("/", "_") | |
215 | - roomData = csvdb["room_" .. roomName .. "Csv"] | |
216 | - end | |
217 | - for stageType, events in pairs(roomData["events"]) do | |
218 | - local bpool = {} | |
219 | - if stagePool[roomId][stageType] then | |
220 | - for block, _ in pairs(stagePool[roomId][stageType]) do | |
221 | - table.insert(bpool, block) | |
222 | - end | |
223 | - end | |
224 | - for _, event in ipairs(events) do | |
225 | - if #bpool <= 0 then break end | |
226 | - if math.randomFloat(0, 1) <= (event["rate"] or 1) then | |
227 | - local count = math.randomInt(math.min(#bpool, event["minc"]), math.min(#bpool, event["maxc"])) | |
228 | - for i = 1, count do | |
229 | - local idx = math.randomInt(1, #bpool) | |
230 | - randomEvent(roomId, bpool[idx], event["event"]) | |
231 | - table.remove(bpool, idx) | |
232 | - end | |
233 | - end | |
234 | - end | |
235 | - end | |
236 | - end | |
237 | - if not haveBoss then | |
238 | - if not next(monsterEvents) then | |
239 | - print("这个地图没有钥匙!!! mapId : " .. mapId) | |
240 | - else | |
241 | - local event = monsterEvents[math.randomInt(1, #monsterEvents)] | |
242 | - event.item = {1, 1} --掉落钥匙 | |
243 | - end | |
244 | - end | |
245 | - self:updateProperty({field = "advInfo", value = advInfo}) | |
246 | - end | |
247 | - | |
248 | -end | |
249 | - | |
250 | -return RoleAdv | |
251 | 0 | \ No newline at end of file |
src/models/RolePlugin.lua
... | ... | @@ -65,7 +65,7 @@ function RolePlugin.bind(Role) |
65 | 65 | -- 发奖功能入口 award string id=count or {[id] = count} |
66 | 66 | function Role:award(gift, params) |
67 | 67 | local tgift = {} |
68 | - if type(award) == "string" then | |
68 | + if type(gift) == "string" then | |
69 | 69 | for _, one in pairs(gift:toTableArray(true)) do |
70 | 70 | tgift[one[1]] = (tgift[one[1]] or 0) + one[2] |
71 | 71 | end |
... | ... | @@ -201,6 +201,13 @@ function RolePlugin.bind(Role) |
201 | 201 | self.dailyData:load() |
202 | 202 | end |
203 | 203 | end |
204 | + | |
205 | + function Role:getAdvData() | |
206 | + if not self.advData then | |
207 | + self.advData = require("adv.Adv").new(self) | |
208 | + end | |
209 | + return self.advData | |
210 | + end | |
204 | 211 | end |
205 | 212 | |
206 | 213 | return RolePlugin |
207 | 214 | \ No newline at end of file | ... | ... |
src/shared/ModelBase.lua
... | ... | @@ -35,15 +35,16 @@ function ModelBase:ctor(properties) |
35 | 35 | self:setProperties(properties, true) --缺少的域将设置默认值 |
36 | 36 | end |
37 | 37 | |
38 | --- startCache 和 endCache 在恰当的时候配对使用 | |
38 | +-- startCache 和 endCache 在恰当的时候*配对使用* 嵌套使用多次增加引用计数 直到引用计数为0 写入 | |
39 | 39 | function ModelBase:startCache( ... ) |
40 | 40 | for _, field in ipairs({ ... }) do |
41 | 41 | if self.class.schema[field] then |
42 | - self.cacheFields[field] = true | |
42 | + self.cacheFields[field] = (self.cacheFields[field] or 0) + 1 | |
43 | 43 | end |
44 | 44 | end |
45 | 45 | end |
46 | 46 | |
47 | +--减少缓存引用计数 为时写入, 无参数 强制刷新所有缓存 | |
47 | 48 | function ModelBase:endCache( ... ) |
48 | 49 | args = { ... } |
49 | 50 | params = {} |
... | ... | @@ -66,8 +67,11 @@ function ModelBase:endCache( ... ) |
66 | 67 | else |
67 | 68 | for _, field in ipairs(args) do |
68 | 69 | if self.cacheFields[field] then |
69 | - self.cacheFields[field] = nil | |
70 | - doOneCache(field) | |
70 | + self.cacheFields[field] = self.cacheFields[field] - 1 | |
71 | + if self.cacheFields[field] <= 0 then | |
72 | + self.cacheFields[field] = nil | |
73 | + doOneCache(field) | |
74 | + end | |
71 | 75 | end |
72 | 76 | end |
73 | 77 | end | ... | ... |