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