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,4 +75,17 @@ AdvEventType = { | ||
75 | Monster = 3, -- 普通怪 | 75 | Monster = 3, -- 普通怪 |
76 | Trader = 4, --商人 | 76 | Trader = 4, --商人 |
77 | Build = 5, --建筑物 | 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 | \ No newline at end of file | 92 | \ No newline at end of file |
src/ProtocolCode.lua
@@ -23,6 +23,10 @@ actionCodes = { | @@ -23,6 +23,10 @@ actionCodes = { | ||
23 | Role_pipelining = 109, | 23 | Role_pipelining = 109, |
24 | 24 | ||
25 | Adv_startAdvRpc = 151, | 25 | Adv_startAdvRpc = 151, |
26 | + Adv_roleFormatRpc = 152, | ||
27 | + Adv_clickBlockRpc = 153, | ||
28 | + Adv_useItemRpc = 154, | ||
29 | + Adv_useSkillRpc = 155, | ||
26 | 30 | ||
27 | Hero_loadInfos = 201, | 31 | Hero_loadInfos = 201, |
28 | Hero_updateProperty = 202, | 32 | Hero_updateProperty = 202, |
src/actions/AdvAction.lua
@@ -16,18 +16,74 @@ local table_unpack = table.unpack | @@ -16,18 +16,74 @@ local table_unpack = table.unpack | ||
16 | 16 | ||
17 | local _M = {} | 17 | local _M = {} |
18 | 18 | ||
19 | +--开始一个新的关卡 | ||
19 | function _M.startAdvRpc( agent, data ) | 20 | function _M.startAdvRpc( agent, data ) |
20 | local role = agent.role | 21 | local role = agent.role |
21 | local msg = MsgPack.unpack(data) | 22 | local msg = MsgPack.unpack(data) |
22 | - | 23 | + local chapterId = msg.chapterId |
24 | + | ||
25 | + --上一个关卡结束才可以开始新的关卡 | ||
23 | local advInfo = role:getProperty("advInfo") | 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 | SendPacket(actionCodes.Adv_startAdvRpc, '') | 30 | SendPacket(actionCodes.Adv_startAdvRpc, '') |
28 | return true | 31 | return true |
29 | end | 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 @@ | @@ -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 | \ No newline at end of file | 966 | \ No newline at end of file |
@@ -0,0 +1,136 @@ | @@ -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 | \ No newline at end of file | 137 | \ No newline at end of file |
@@ -0,0 +1,294 @@ | @@ -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 | \ No newline at end of file | 295 | \ No newline at end of file |
@@ -0,0 +1,102 @@ | @@ -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 | \ No newline at end of file | 103 | \ No newline at end of file |
@@ -0,0 +1,388 @@ | @@ -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 | \ No newline at end of file | 389 | \ No newline at end of file |
src/models/HeroPlugin.lua
@@ -121,6 +121,12 @@ function HeroPlugin.bind(Hero) | @@ -121,6 +121,12 @@ function HeroPlugin.bind(Hero) | ||
121 | return csvdb["skill_blockCsv"][unitData.block] | 121 | return csvdb["skill_blockCsv"][unitData.block] |
122 | elseif idx == 2 then | 122 | elseif idx == 2 then |
123 | return csvdb["skill_specialCsv"][unitData.special] | 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 | end | 130 | end |
125 | return {} | 131 | return {} |
126 | end | 132 | end |
src/models/Role.lua
@@ -2,12 +2,10 @@ local Role = class("Role", require("shared.ModelBase")) | @@ -2,12 +2,10 @@ local Role = class("Role", require("shared.ModelBase")) | ||
2 | 2 | ||
3 | local RolePlugin = import(".RolePlugin") | 3 | local RolePlugin = import(".RolePlugin") |
4 | local RoleTask = import(".RoleTask") | 4 | local RoleTask = import(".RoleTask") |
5 | -local RoleAdv = import(".RoleAdv") | ||
6 | local RoleActivity = import(".RoleActivity") | 5 | local RoleActivity = import(".RoleActivity") |
7 | local RoleChangeStruct = import(".RoleChangeStruct") | 6 | local RoleChangeStruct = import(".RoleChangeStruct") |
8 | RolePlugin.bind(Role) | 7 | RolePlugin.bind(Role) |
9 | RoleTask.bind(Role) | 8 | RoleTask.bind(Role) |
10 | -RoleAdv.bind(Role) | ||
11 | RoleActivity.bind(Role) | 9 | RoleActivity.bind(Role) |
12 | RoleChangeStruct.bind(Role) | 10 | RoleChangeStruct.bind(Role) |
13 | 11 | ||
@@ -15,6 +13,7 @@ function Role:ctor( properties ) | @@ -15,6 +13,7 @@ function Role:ctor( properties ) | ||
15 | Role.super.ctor(self, properties) | 13 | Role.super.ctor(self, properties) |
16 | self.ignoreHeartbeat = false | 14 | self.ignoreHeartbeat = false |
17 | self.heros = {} | 15 | self.heros = {} |
16 | + self.advData = nil | ||
18 | end | 17 | end |
19 | 18 | ||
20 | Role.schema = { | 19 | Role.schema = { |
@@ -39,7 +38,9 @@ Role.schema = { | @@ -39,7 +38,9 @@ Role.schema = { | ||
39 | 38 | ||
40 | --冒险相关 | 39 | --冒险相关 |
41 | advPass = {"string", ""}, -- 通关记录 | 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,6 +146,7 @@ function Role:data() | ||
145 | loveStatus = self:getProperty("loveStatus"):toNumMap(), | 146 | loveStatus = self:getProperty("loveStatus"):toNumMap(), |
146 | advPass = self:getProperty("advPass"), | 147 | advPass = self:getProperty("advPass"), |
147 | advInfo = self:getProperty("advInfo"), | 148 | advInfo = self:getProperty("advInfo"), |
149 | + advItems = self:getProperty("advItems"):toNumMap(), | ||
148 | } | 150 | } |
149 | end | 151 | end |
150 | 152 |
src/models/RoleAdv.lua deleted
@@ -1,250 +0,0 @@ | @@ -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 | \ No newline at end of file | 0 | \ No newline at end of file |
src/models/RolePlugin.lua
@@ -65,7 +65,7 @@ function RolePlugin.bind(Role) | @@ -65,7 +65,7 @@ function RolePlugin.bind(Role) | ||
65 | -- 发奖功能入口 award string id=count or {[id] = count} | 65 | -- 发奖功能入口 award string id=count or {[id] = count} |
66 | function Role:award(gift, params) | 66 | function Role:award(gift, params) |
67 | local tgift = {} | 67 | local tgift = {} |
68 | - if type(award) == "string" then | 68 | + if type(gift) == "string" then |
69 | for _, one in pairs(gift:toTableArray(true)) do | 69 | for _, one in pairs(gift:toTableArray(true)) do |
70 | tgift[one[1]] = (tgift[one[1]] or 0) + one[2] | 70 | tgift[one[1]] = (tgift[one[1]] or 0) + one[2] |
71 | end | 71 | end |
@@ -201,6 +201,13 @@ function RolePlugin.bind(Role) | @@ -201,6 +201,13 @@ function RolePlugin.bind(Role) | ||
201 | self.dailyData:load() | 201 | self.dailyData:load() |
202 | end | 202 | end |
203 | end | 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 | end | 211 | end |
205 | 212 | ||
206 | return RolePlugin | 213 | return RolePlugin |
207 | \ No newline at end of file | 214 | \ No newline at end of file |
src/shared/ModelBase.lua
@@ -35,15 +35,16 @@ function ModelBase:ctor(properties) | @@ -35,15 +35,16 @@ function ModelBase:ctor(properties) | ||
35 | self:setProperties(properties, true) --缺少的域将设置默认值 | 35 | self:setProperties(properties, true) --缺少的域将设置默认值 |
36 | end | 36 | end |
37 | 37 | ||
38 | --- startCache 和 endCache 在恰当的时候配对使用 | 38 | +-- startCache 和 endCache 在恰当的时候*配对使用* 嵌套使用多次增加引用计数 直到引用计数为0 写入 |
39 | function ModelBase:startCache( ... ) | 39 | function ModelBase:startCache( ... ) |
40 | for _, field in ipairs({ ... }) do | 40 | for _, field in ipairs({ ... }) do |
41 | if self.class.schema[field] then | 41 | if self.class.schema[field] then |
42 | - self.cacheFields[field] = true | 42 | + self.cacheFields[field] = (self.cacheFields[field] or 0) + 1 |
43 | end | 43 | end |
44 | end | 44 | end |
45 | end | 45 | end |
46 | 46 | ||
47 | +--减少缓存引用计数 为时写入, 无参数 强制刷新所有缓存 | ||
47 | function ModelBase:endCache( ... ) | 48 | function ModelBase:endCache( ... ) |
48 | args = { ... } | 49 | args = { ... } |
49 | params = {} | 50 | params = {} |
@@ -66,8 +67,11 @@ function ModelBase:endCache( ... ) | @@ -66,8 +67,11 @@ function ModelBase:endCache( ... ) | ||
66 | else | 67 | else |
67 | for _, field in ipairs(args) do | 68 | for _, field in ipairs(args) do |
68 | if self.cacheFields[field] then | 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 | end | 75 | end |
72 | end | 76 | end |
73 | end | 77 | end |