From 46fac6f1866667f3ba878d4cc6c1f9df991b1d01 Mon Sep 17 00:00:00 2001 From: zhouahaihai Date: Mon, 14 Jan 2019 16:18:17 +0800 Subject: [PATCH] 酱料 --- src/GlobalVar.lua | 13 +++++++++++++ src/ProtocolCode.lua | 4 ++++ src/actions/AdvAction.lua | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- src/adv/Adv.lua | 965 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/adv/AdvBattle.lua | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/adv/AdvBuff.lua | 294 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/adv/AdvPassive.lua | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/adv/AdvPlayer.lua | 388 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/models/HeroPlugin.lua | 6 ++++++ src/models/Role.lua | 8 +++++--- src/models/RoleAdv.lua | 250 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- src/models/RolePlugin.lua | 9 ++++++++- src/shared/ModelBase.lua | 12 ++++++++---- 13 files changed, 1988 insertions(+), 261 deletions(-) create mode 100644 src/adv/Adv.lua create mode 100644 src/adv/AdvBattle.lua create mode 100644 src/adv/AdvBuff.lua create mode 100644 src/adv/AdvPassive.lua create mode 100644 src/adv/AdvPlayer.lua delete mode 100644 src/models/RoleAdv.lua diff --git a/src/GlobalVar.lua b/src/GlobalVar.lua index 1119856..4958f20 100644 --- a/src/GlobalVar.lua +++ b/src/GlobalVar.lua @@ -75,4 +75,17 @@ AdvEventType = { Monster = 3, -- 普通怪 Trader = 4, --商人 Build = 5, --建筑物 +} + +AdvBackEventType = { + Reward = 1 --奖励 + HpChange = 2 --血量改变 + AtkChange = 3 --攻击改变 + Buff = 4 --buff 改变 + Skill = 5 --释放技能 + Atk = 6 --攻击动作 + Next = 7 --进入下一层 + End = 8 -- 结束 + BlockChange = 9 -- 块改变 + } \ No newline at end of file diff --git a/src/ProtocolCode.lua b/src/ProtocolCode.lua index 3e62861..e111142 100644 --- a/src/ProtocolCode.lua +++ b/src/ProtocolCode.lua @@ -23,6 +23,10 @@ actionCodes = { Role_pipelining = 109, Adv_startAdvRpc = 151, + Adv_roleFormatRpc = 152, + Adv_clickBlockRpc = 153, + Adv_useItemRpc = 154, + Adv_useSkillRpc = 155, Hero_loadInfos = 201, Hero_updateProperty = 202, diff --git a/src/actions/AdvAction.lua b/src/actions/AdvAction.lua index 5869b67..714a1f5 100644 --- a/src/actions/AdvAction.lua +++ b/src/actions/AdvAction.lua @@ -16,18 +16,74 @@ local table_unpack = table.unpack local _M = {} +--开始一个新的关卡 function _M.startAdvRpc( agent, data ) local role = agent.role local msg = MsgPack.unpack(data) - + local chapterId = msg.chapterId + + --上一个关卡结束才可以开始新的关卡 local advInfo = role:getProperty("advInfo") + if next(advInfo) then return end + role:getAdvData():initByChapter(chapterId, 1) - role:randomAdvMap(10101, 1) --测试 - SendPacket(actionCodes.Adv_startAdvRpc, '') return true end +function _M.roleFormatRpc(agent , data) + local role = agent.role + local msg = MsgPack.unpack(data) + local advTeam = role:getProperty("advTeam") + for slot, heroId in ipairs(msg.heros) do + if not role.heros[heroId] then + return + end + end + table.clear(advTeam) + advTeam.heros = {} + for slot, heroId in ipairs(msg.heros) do + advTeam.heros[slot] = heroId + end + role:updateProperty({field = "advTeam", value = advTeam}) + SendPacket(actionCodes.Adv_roleFormatRpc, '') + return true +end + +-- 点击地块(解锁)(触发事件) +function _M.clickBlockRpc(agent, data) + local role = agent.role + local msg = MsgPack.unpack(data) + + local adv = role:getAdvData() + local status = adv:clickBlock(msg.roomId, msg.blockId, msg) + if not status then return end + SendPacket(actionCodes.Adv_clickBlockRpc, MsgPack.pack({events = adv:popBackEvents()})) + return true +end + +--use item 使用背包道具 +function _M.useItemRpc(agent, data) + local role = agent.role + local msg = MsgPack.unpack(data) + + local adv = role:getAdvData() + local status = adv:useItem(msg.itemId, msg.count, msg.target) -- target {roomId = 1, blockId = 1} 选择的目标 + if not status then return end + SendPacket(actionCodes.Adv_useItemRpc, MsgPack.pack({events = adv:popBackEvents()})) + return true +end + +--使用技能 +function _M.useSkillRpc(agent, data) + local role = agent.role + local msg = MsgPack.unpack(data) + local adv = role:getAdvData() + local status = adv:useSkill(msg.skillId, msg.target) -- target {roomId = 1, blockId = 1} 选择的目标 + if not status then return end + SendPacket(actionCodes.Adv_useSkillRpc, MsgPack.pack({events = adv:popBackEvents()})) + return true +end diff --git a/src/adv/Adv.lua b/src/adv/Adv.lua new file mode 100644 index 0000000..9e68115 --- /dev/null +++ b/src/adv/Adv.lua @@ -0,0 +1,965 @@ +local Passive = require "adv.AdvPassive" + +-- 工具函数 +local function getIdByCr(c, r) + local crId = math.abs(r) + math.abs(c) * 100 + if c < 0 then + crId = crId + 10000 + end + if r < 0 then + crId = crId + 20000 + end + return crId +end + +local function getCrById(crId) + local c = math.floor(crId % 10000 / 100) + local r = crId % 100 + local last = math.floor(crId / 10000) + if last == 3 then + c, r = -c, -r + elseif last == 1 then + c = -c + elseif last == 2 then + r = -r + end + return c, r +end + +-----------------------------随机地图----------------------------- +--检查 是否满足层数限制条件 +local function checkIsIn(checkValue, checkType, checkRange) + if not checkValue then return end + if checkType == 1 then + local limits = checkRange:toNumMap() + for min, max in pairs(limits) do + if checkValue >= min and checkValue <= max then + return true + end + end + else + local limit = checkRange:toArray(true, "=") + for _, _l in ipairs(limit) do + if _l == checkValue then + return true + end + end + end +end + +--关卡事件库 +local function getEventLib(chapterId, level, needEventType) + local chapter = math.floor(chapterId / 100) % 100 + + local libsToType = { + ["event_monsterCsv"] = {AdvEventType.Monster, AdvEventType.BOSS}, + ["event_chooseCsv"] = AdvEventType.Choose, + ["event_dropCsv"] = AdvEventType.Drop, + ["event_buildingCsv"] = AdvEventType.Build, + ["event_traderCsv"] = AdvEventType.Trader, + + } + local eventLib = {} + for lib, eventType in pairs(libsToType) do + if type(eventType) == "table" then + for _, temp in ipairs(eventType) do + eventLib[temp] = {} + end + else + eventLib[eventType] = {} + end + if not needEventType or eventLib[needEventType] then + for id, data in pairs(csvdb[lib]) do + if data.levelchapter == chapter then + if checkIsIn(level, data.leveltype, data.levellimit) then + if type(eventType) == "table" then + eventLib[eventType[data.type]][id] = data + else + eventLib[eventType][id] = data + end + end + end + end + if needEventType then + break + end + end + end + return eventLib +end + +-- 生成地图 是否可以生成地图上层判断 +local function randomAdvMap(role, chapterId, level, notNotify) + local chapterData = csvdb["adv_chapterCsv"][chapterId] + if not chapterData then return end + if level > chapterData.limitlevel then return end + --随出地图 + local raw_pool = chapterData.mapid:toArray(true, "=") + local advInfo = role:getProperty("advInfo") + local lastMapId = advInfo.mapId --非同一层不连续随出同一张类似的地图 + local lastChapterId = advInfo.chapter + local power = advInfo.power or 0 --体力 + local pool = {} + for _, mapId in ipairs(raw_pool) do + local temp = csvdb["mapCsv"][mapId] + if temp and (lastChapterId == chapterId or lastMapId ~= mapId) then --非同一层不连续随出同一张类似的地图 + if checkIsIn(level, temp.leveltype, temp.levellimit) then + table.insert(pool, mapId) + end + end + end + if not next(pool) then return end + local mapId = pool[math.randomInt(1, #pool)] + --随出事件 + local mapData = csvdb["map_" .. csvdb["mapCsv"][mapId]["path"] .. "Csv"] + if not mapData then return end + + + table.clear(advInfo) + advInfo.chapter = chapterId + advInfo.level = level + advInfo.mapId = mapId + advInfo.power = power + advInfo.enemyId = 1 --怪递增的索引 + advInfo.rooms = {} -- {[roomId] = {event = {}, open = {}},} -- event 事件信息(具体信息查看randomEvent), open 是否解锁 + + --事件随机 + local eventLib = getEventLib(chapterId, level) + local monsterEvents = {} --处理钥匙掉落 + local haveBoss = false + + local function randomEvent(roomId, blockId, eventType) + if advInfo.rooms[roomId]["event"][blockId] then return end --已经有事件了 不覆盖 + local event = {etype = eventType} + local randomFunc = {} + --入口 + randomFunc[AdvEventType.In] = function()end + --出口 + randomFunc[AdvEventType.Out] = function() end + + --boss + randomFunc[AdvEventType.BOSS] = function() + if not next(eventLib[eventType]) or haveBoss then return false end + haveBoss = true + event.id = math.randWeight(eventLib[eventType], "showup") + end + --怪物 + randomFunc[AdvEventType.Monster] = function() + if not next(eventLib[eventType]) then return false end + event.id = math.randWeight(eventLib[eventType], "showup") + table.insert(monsterEvents, event) + end + --选择点 + randomFunc[AdvEventType.Choose] = function() + if not next(eventLib[eventType]) then return false end + event.id = math.randWeight(eventLib[eventType], "showup") + end + --掉落点 + randomFunc[AdvEventType.Drop] = randomFunc[AdvEventType.Choose] + --交易所 + randomFunc[AdvEventType.Trader] = randomFunc[AdvEventType.Choose] + --建筑 + randomFunc[AdvEventType.Build] = randomFunc[AdvEventType.Choose] + + if randomFunc[eventType] then + if randomFunc[eventType]() ~= false then + advInfo.rooms[roomId]["event"][blockId] = event + end + end + end + + stagePool = {["global"] = {}} + for roomId, roomName in pairs(mapData["rooms"]) do + stagePool[roomId] = {} + advInfo.rooms[roomId] = {event = {}, open = {}} -- 事件, open open == 1 房间内地块全部开放 + local roomData + if roomName == "path" then + roomData = mapData["path"] + else + roomName = roomName:gsub("/", "_") + roomData = csvdb["room_" .. roomName .. "Csv"] + end + for blockId, stageType in pairs(roomData["blocks"]) do + if AdvSpecialStage[stageType] then + eventType = AdvEventType[AdvSpecialStage[stageType]] + randomEvent(roomId, blockId, eventType) + else + stagePool["global"][stageType] = stagePool["global"][stageType] or {} + stagePool[roomId][stageType] = stagePool[roomId][stageType] or {} + table.insert(stagePool["global"][stageType], {room = roomId, block = blockId}) + stagePool[roomId][stageType][blockId] = 1 + end + end + end + -- 全地图事件 优先级高 + for stageType, events in pairs(mapData["events"]) do + for _, event in ipairs(events) do + local lastCount = #stagePool["global"][stageType] + if lastCount <= 0 then break end + if math.randomFloat(0, 1) <= (event["rate"] or 1) then + local count = math.randomInt(math.min(lastCount, event["minc"]), math.min(lastCount, event["maxc"])) + for i = 1, count do + local idx = math.randomInt(1, lastCount) + local cur = stagePool["global"][stageType][idx] + randomEvent(cur["room"], cur["block"], event["event"]) + table.remove(stagePool["global"][stageType], idx) + lastCount = lastCount - 1 + stagePool[cur["room"]][stageType][cur["block"]] = nil + end + end + end + end + -- 随机单个房间的事件 + for roomId, roomName in pairs(mapData["rooms"]) do + local roomData + if roomName == "path" then + roomData = mapData["path"] + else + roomName = roomName:gsub("/", "_") + roomData = csvdb["room_" .. roomName .. "Csv"] + end + for stageType, events in pairs(roomData["events"]) do + local bpool = {} + if stagePool[roomId][stageType] then + for block, _ in pairs(stagePool[roomId][stageType]) do + table.insert(bpool, block) + end + end + for _, event in ipairs(events) do + if #bpool <= 0 then break end + if math.randomFloat(0, 1) <= (event["rate"] or 1) then + local count = math.randomInt(math.min(#bpool, event["minc"]), math.min(#bpool, event["maxc"])) + for i = 1, count do + local idx = math.randomInt(1, #bpool) + randomEvent(roomId, bpool[idx], event["event"]) + table.remove(bpool, idx) + end + end + end + end + end + if not haveBoss then + if not next(monsterEvents) then + print("这个地图没有钥匙!!! mapId : " .. mapId) + else + local event = monsterEvents[math.randomInt(1, #monsterEvents)] + event.item = {1, 1} --掉落钥匙 --todo + end + end +end + +--块类型 +local Block = class("Block") +function Block:ctor(blockId, event, isOpen) + self.blockId = blockId + self.col, self.row = getCrById(self.blockId) + self.isOpen = isOpen and true or false + self.event = event -- 拿到的是引用可以直接更新 +end +function Block:isBoss() + if not self.event then return end + return self.event["etype"] == AdvEventType.BOSS +end + +--事件有需要额外处理的部分 +function Block:open(adv, room) + --如果翻开有数据处理在这里处理 + local randomFunc = {} + --怪 + randomFunc[AdvEventType.Monster] = function() + self.event.mId = adv.advInfo.enemyId --给怪一个有序id 回合逻辑时使用 + adv.advInfo.enemyId = adv.advInfo.enemyId + 1 + local enemy = self.battle:getEnemy(room.roomId, self.blockId) + if enemy then + enemy:unlock(self.event.mId) + else + self.battle:addEnemy(room, self) + end + end + randomFunc[AdvEventType.BOSS] = randomFunc[AdvEventType.Monster] + --掉落 + randomFunc[AdvEventType.Drop] = function() + self.event.item = csvdb["event_dropCsv"][self.event.id]["range"]:randWeight(true) + end + --交易 + randomFunc[AdvEventType.Trader] = function() + local data = csvdb["event_traderCsv"][self.event.id] + self.event.shop = {} + self.event.status = "" --购买次数状态 1 就是购买过了 -- 购买id就是shop索引 + for i = 1, 10 do + local numS, rangeS = "num" .. i, "range" .. i + if data[numS] and data[rangeS] then + for j = 1, data[numS] do + table.insert(self.event.shop, data[rangeS]:randWeight(true)) + end + else + break + end + end + end + --建筑 + [AdvEventType.Build] = function() + local data = csvdb["event_buildingCsv"][self.event.id] + self.event.effect = data["range"]:randWeight(true) --随出建筑效果 + if self.event.effect[1] == 1 then --获得某道具 + local reward = csvdb["event_dropCsv"][self.event.effect[2]]["range"]:randWeight(true) + self.event.effect[2] = reward[1] + self.event.effect[3] = reward[2] + end + end + --抉择点 + [AdvEventType.Choose] = function() + local data = csvdb["event_chooseCsv"][self.event.id] + self.event.effect = {} + for i = 1, 2 do + self.event.effect[i] = data["button".. i .."effect"]:toArray(true, "=") + if self.event.effect[i][1] == 1 then --获得某道具 + local reward = csvdb["event_dropCsv"][self.event.effect[i][2]]["range"]:randWeight(true) + self.event.effect[i][2] = reward[1] + self.event.effect[i][3] = reward[2] + end + end + end + if self.event then -- 随机出具体的事件 + if randomFunc[self.event.etype] then + randomFunc[self.event.etype]() + end + end + self.isOpne = true +end + +local Room = class("Room") +function Room:ctor(adv, roomId, csvData, info, isPath) + self.roomId = roomId + self.col, self.row = getCrById(self.roomId) + self.isPath = isPath + self.isBossRoom = false -- boss房间 --击败boss 以后重置为false + self.info = info -- 拿到引用 方便更新advInfo + self.isShow = false + self.blocks = {} + + for blockId, _ in pairs(csvData["blocks"]) do + self.blocks[blockId] = Block.new(blockId, info.event[blockId], info.open == 1 or info.open[blockId]) + if not self.isPath and self.blocks[blockId]:isBoss() then + self.isBossRoom = true + end + if self.blocks[blockId].isOpen then + self.isShow = true + else + if self.blocks[blockId].event and self.blocks[blockId].event.etype == AdvEventType.In then -- 开放 + self.isShow = true + self.blocks[blockId].isOpen = true + self.info.open[blockId] = 1 + + --入口房间只会在这里首次展示开放 --触发固有技 + adv:triggerPassive(Passive.ROOM_SHOW, {roomId = self.roomId}) + end + end + end +end + +function Room:tranGToL(c, r) + return c - self.col, r - self.row +end + +function Room:tranLtoG(c, r) + return c + self.col, r + self.row +end + +function Room:getBByGPos(c, r) + local c, r = self:tranGToL(c, r) + return self.blocks[getIdByCr(c, r)] +end + +function Room:openBlock(block, adv) + if self.blocks[block.blockId] ~= block then return end + if block.isOpen == true then return end + block:open(adv, self) + local allOpen = true + if not self.isBossRoom then + for _, _block in pairs(self.blocks) do + if not _block.isOpen then + allOpen = false + break + end + end + end + + if allOpen then + self.info.open = 1 + else + self.info.open[block.blockId] = 1 + end + + if not self.isShow then + self.isShow = true + --首次展示房间 + adv:triggerPassive(Passive.ROOM_SHOW, {roomId = self.roomId}) + end +end + +function Room:clearBEvent(block) + if self.blocks[block.blockId] ~= block then return end + block.event = nil + self.info.event[block.blockId] = nil +end + + + +local Adv = class("Adv") +function Adv:ctor(owner) + assert(owner, "Adv instance must have owner(role)") + self.owner = owner + self.advInfo = self.owner:getProperty("advInfo") --这个变量置空使用 table.clear + self.advTeam = self.owner:getProperty("advTeam") --这个变量置空使用 table.clear + self:clear() + self.events = {} --发给客户端的事件组 +end + +-- 清空自己组织的数据 +function Adv:clear() + self.rooms = {} + self.cachePassiveEvent = {} -- 在battle 没有创建成功时 触发的被动技信息 + self.battle = nil -- 战斗逻辑 +end + +--关卡通关,非层 score < 0 失败 +function Adv:over(success) + local score = -1 + if success then + -- todo success 计算分数 + score = 1 + self.owner:updateProperty({field = "advPass", self.owner:getProperty("advPass"):setv(self.advInfo.chapter, score)}) + end + table.clear(self.advInfo) --清空advInfo + self.advTeam.player = nil --重置玩家的数据 + self:clear() + self:backEnd(score) +end + +function Adv:getMapInfo() + if not next(self.advInfo) then return end + return csvdb["mapCsv"][self.advInfo.mapId] +end + +function Adv:getMapData() + local mapInfo = self:getMapInfo() + if not mapInfo then return end + return csvdb["map_" .. self:getMapInfo()["path"] .. "Csv"] +end + +function Adv:initByInfo() + self:clear() + if not next(self.advInfo) then return end --未初始化的 advInfo + + local mapData = self:getMapData() + if not mapData then return end + + for roomId, roomName in pairs(mapData["rooms"]) do + if roomName == "path" then + self.rooms[roomId] = Room.new(self, roomId, mapData["path"], self.advInfo.rooms[roomId], true) + else + roomName = roomName:gsub("/", "_") + self.rooms[roomId] = Room.new(self, roomId, csvdb["room_" .. roomName .. "Csv"], self.advInfo.rooms[roomId], false) + end + end + self:initBattle() + return true +end + +function Adv:triggerPassive(condType, params) + if not self.battle then + table.insert(self.cachePassiveEvent, {condType, params}) + else + self.battle:triggerPassive(condType, params) + end +end + +function Adv:initBattle() + self.battle = require("adv.AdvBattle").new(self) + for _, passiveC in ipairs(self.cachePassiveEvent) do + self.battle:triggerPassive(passiveC[1], passiveC[2]) + end + self.cachePassiveEvent = {} +end + +-- 随机地图 +function Adv:initByChapter(chapterId, level, notNotify) + randomAdvMap(self.owner, chapterId, level, notNotify) + self:initByInfo() --初始化 + role:updateProperties({advInfo = self.advInfo, advTeam = self.advTeam}, notNotify) +end + +--获取,某个位置上的 room 和 block +function Adv:getRBByPos(c, r) + for roomId, room in pairs(self.rooms) do + local block = room:getBByGPos(c, r) + if block then + return room, block + end + end +end + +function Adv:getAroundBlocks(room, block) + local blocks = {} + local range = {1, -1} + local col, row = room:tranLtoG(block.col, block.row) + for _, add in ipairs(range) do + local rroom, rblock = self:getRBByPos(col + add, row) + if rroom then + table.insert(blocks, {rroom, rblock}) + end + end + for _, add in ipairs(range) do + local rroom, rblock = self:getRBByPos(col, row + add) + if rroom then + table.insert(blocks, {rroom, rblock}) + end + end + return blocks +end + +--随机一个空的位置生成怪, 如果没有就没有 +function Adv:addNewMonsterRand() + local pool = {} + for _, room in pairs(self.rooms) do + for _, block in pairs(self.blocks) do + if not block.event then + table.insert(pool, {room, block}) + end + end + end + if not next(pool) then return end + local idx = math.randomInt(1, #pool) + local room, block = pool[idx][1], pool[idx][2] + + local event = {mId = self.advInfo.enemyId} + self.advInfo.enemyId = self.advInfo.enemyId + 1 + + local eventLib = getEventLib(self.advInfo.chapter, self.advInfo.level, AdvEventType.Monster) + if not next(eventLib[AdvEventType.Monster]) then return false end + event.id = math.randWeight(eventLib[AdvEventType.Monster], "showup") + + block.event = event + room.info.event[block.blockId] = event + self.battle:addEnemy(room, block) + return room, block +end + +-- 随机翻开 num 个 以开放的房间的 地块 +function Adv:openBlockRand(num) + local pool = {} + for _, room in pairs(self.rooms) do + if room.isShow and not room.isPath then + for _, block in pairs(room.blocks) do + if not block.isOpen then + table.insert(pool, {room.roomId, block.blockId}) + end + end + end + end + if #pool <= num then + for _, temp in ipairs(pool) do + self:openBlock(temp[1], temp[2]) + end + else + for i = 1, num do + local idx = math.randomInt(1, #pool) + self:openBlock(pool[idx][1], pool[idx][2]) + table.remove(pool, idx) + end + end +end +-- 打开一个地块 +function Adv:openBlock(roomId, blockId) + local room = self.rooms[roomId] + local block = room.blocks[blockId] + room:openBlock(block, self) + self:backBlockChange(roomId, blockId) +end + +-- 在冒险中获得的物品都发放在冒险背包内 +function Adv:award(gift, params) + local tgift = {} + if type(gift) == "string" then + for _, one in pairs(gift:toTableArray(true)) do + tgift[one[1]] = (tgift[one[1]] or 0) + one[2] + end + else + tgift = gift + end + local items = self.owner:getProperty("advItems") + for itemId, count in pairs(tgift) do + local origin = items:getv(itemId, 0) + local nums = origin + count + if nums <= 0 then + items = items:delk(itemId) + nums = 0 + else + items = items:incrv(itemId, count) + end + end + self.owner:updateProperty({field = "advItems", value = items, notNotify = params.notNotify}) + return tgift +end + +-- 消耗物品 优先冒险背包 --check 只是检查够不够 +function Adv:cost(item, params, check) + local items = self.owner:getProperty("advItems") + local less = {} + local advCost = {} + for itemId, count in pairs(item) do + advCost[itemId] = - math.min(items:getv(itemId, 0), count) + if advCost[itemId] == 0 then + advCost[itemId] = nil + end + + local last = items:getv(itemId, 0) - count + if last < 0 then + less[itemId] = -last + end + + end + if next(less) and not self.owner:checkItemEnough(less) then return end --不够 + if check then return true end + self:award(advCost, params) + self.owner:costItems(less, params) + return true +end + +--事件点击处理 +local function clickOut(self, room, block, params) + if self:cost({[1] = 1}, {}) then --todo 钥匙id + if self.advInfo.level >= csvdb["adv_chapterCsv"][self.advInfo.chapter].limitlevel then --关卡结束 + self:over(true) + else + self:initByChapter(self.advInfo.chapter, self.advInfo.level + 1, true) + self:backNext() --下一关 + end + return true + end +end + +--战斗 普通攻击 +local function clickMonster(self, room, block, params) + self.battle:playerAtk(room.roomId, block.blockId) + return true +end + +local function clickChoose(self, room, block, params) + local choose = params.choose + local chooseData = csvdb["event_chooseCsv"][block.event.id] + if not chooseData or not chooseData["button".. choose .."cond"] then return end + + local cond = chooseData["button".. choose .."cond"]:toArray(true, "=") + local checkCond = { + -- 拥有道具 + [1] = function() + if self:cost({[cond[2]] = cond[3]}, {}, true) then + return true + end + end, + -- xx角色(todo 队长) + [2] = function() + for slot, heroId in pairs(self.advTeam.heros) do + if self.owner.heros[heroId] then + if self.owner.heros[heroId]:getProperty("type") == cond[2] then + return true + end + end + end + end, + --消灭所有怪 + [3] = function() + for _, room in pairs(self.rooms) do + for _, block in pairs(self.blocks) do + if block.event and (block.event.etype == AdvEventType.BOSS or block.event.etype == AdvEventType.Monster) then + return + end + end + end + return true + end, + --制定属性 > + [4] = function() + if (self.battle.player[AttsEnumEx[cond[2]]] or 0) > cond[3] then + return true + end + end, + } + assert(checkCond[cond[1]], "error cond, event_chooseCsv id :" .. block.event.id) + if not checkCond[cond[1]]() then return end + + local effect = block.event.effect[choose] + local doEffect = { + [1] = function() -- 获得某道具N个 + self:backReward(self:award({[effect[2]] = effect[3]}, {})) + end, + [2] = function() --获得冒险buff + self.battle.player:addBuff(effect[2]) + end, + [3] = function() --发现怪物 + local r, b = self:addNewMonsterRand() + self:backBlockChange(r.roomId, b.blockId) + end, + [4] = function() --无事发生 + end + } + assert(doEffect[effect[1]], "error effect, event_chooseCsv id :" .. block.event.id) + doEffect[effect[1]]() + room:clearBEvent(block) + return true +end + +local function clickDrop(self, room, block, params) + local reward = {} + if not block.event.item then return end + local reward = self:award({[block.event.item[1]] = block.event.item[2]}, {}) + room:clearBEvent(block) + self:backReward(reward) + return true +end + +local function clickTrader(self, room, block, params) + local buyId = params.id + local traderData = csvdb["event_traderCsv"][block.event.id] + if not traderData then return end -- 偷偷改表了 + + if not block.event.shop or not block.event.shop[buyId] then return end + if (block.event.status or ""):getv(buyId, 0) == 1 then return end -- 买过了 + + if not self:cost(traderData.type:toNumMap(), {}) then return end --不够 + + local reward = self:award({[block.event.shop[buyId][1]] = block.event.shop[buyId][2]}, {}) + block.event.status = block.event.status:setv(buyId, 1) + self:backReward(reward) + return true +end + +local function clickBuild(self, room, block, params) + local buildData = csvdb["event_buildingCsv"][block.event.id] + if not buildData then return end-- 偷偷改表了 + if not block.event.effect then return end -- 没有效果 气人不 + local effect = block.event.effect + --todo 效果生效 + local doEffect = { + [1] = function() -- 获得某道具N个 + self:backReward(self:award({[effect[2]] = effect[3]}, {})) + end, + [2] = function() --获得冒险buff + self.battle.player:addBuff(effect[2]) + end, + [3] = function() --发现怪物 + local r, b = self:addNewMonsterRand() + self:backBlockChange(r.roomId, b.blockId) + end, + [4] = function() --无事发生 + end + } + assert(doEffect[effect[1]], "error effect, event_buildingCsv id :" .. block.event.id) + if not self:cost({[buildData.type] = 1}, {}) then return end + doEffect[effect[1]]() + room:clearBEvent(block) + return true +end + +local eventCallFunc = { + [AdvEventType.Out] = clickOut, + [AdvEventType.BOSS] = clickMonster, + [AdvEventType.Monster] = clickMonster, + [AdvEventType.Choose] = clickChoose, + [AdvEventType.Drop] = clickDrop, + [AdvEventType.Trader] = clickTrader, + [AdvEventType.Build] = clickBuild, +} + +--点击处理 roomId, blockId +--params 某些事件需要的客户端传递的参数 +function Adv:clickBlock(roomId, blockId, params) + local room = self.rooms[roomId] + if not room then return end + local block = room.blocks[blockId] + if not block then return end + + local canOpen = false --如果未开放是否可以开放 + local hadMonster = false -- 周围是否有解锁的怪未击败 + for _, one in ipairs(self:getAroundBlocks(room, block)) do + local _room, _block = one[1], one[2] + if _block.isOpen then canOpen = true end + if _block.isOpen and _block.event and (_block.event.etype == AdvEventType.BOSS or _block.event.etype == AdvEventType.Monster) then + hadMonster = true + end + end + local status = false + if not block.isOpen then + if canOpen and not hadMonster then --开放 + room:openBlock(block, self) + status = true + end + else + --点了空地 + if not block.event then + return + end + --可点击的事件 + if not hadMonster and not room.isBossRoom then + if eventCallFunc[block.event.etype] then + status = eventCallFunc[block.event.etype](self, room, block, params) + end + end + end + if status and block.event.etype ~= AdvEventType.Out then --出去了就不计算回合了 + self:backBlockChange(roomId, blockId) + self:afterRound() + end + self.battle:getDB() + role:updateProperties({advInfo = self.advInfo, advTeam = self.advTeam}) + return status +end + +--使用道具产生效果 +function Adv:useItem(itemId, count, target) + count = count or 1 + local itemData = csvdb["adv_itemCsv"][itemId] + if not itemData then return end + --重置数量 + if itemData["function"] == 0 or itemData["function"] == 2 then count = 1 end + if not self:cost({[itemId] = count}, {}, true) then return true end + --消耗 + if itemData["function"] == 0 or itemData["function"] == 1 then + self:cost({[itemId] = count}, {}) + end + --生效 + if itemData.type == 1 or itemData.type == 0 then --技能 + self.battle.player:releaseSkill(itemData.effect, 1, target) + elseif itemData.type == 2 then --掉落 + local item = csvdb["event_dropCsv"][itemData.effect]["range"]:randWeight(true) + self:backReward(self:award({[item[1]] = item[2]}, {})) + else + return + end + + self:afterRound() + self.battle:getDB() + role:updateProperties({advInfo = self.advInfo, advTeam = self.advTeam}) + return true +end + +--使用技能 +function Adv:useSkill(skillId, target) + local skillLevel = nil + if skillId > 1000 then return end + for slot, heroId in pairs(self.advTeam.heros) do + if self.owner.heros[heroId] then + if csvdb["unitCsv"][self.owner.heros[heroId]:getSkinId()]["adv"] == skillId then + skillLevel = self.owner.heros[heroId]:getSkillLevel(4) + break + end + end + end + if not skillLevel then return end + local skillData = csvdb["adv_skillCsv"][skillId] + if self.advInfo.power < skillData.cost then return end + self.advInfo.power = self.advInfo.power - skillData.cost + if skillData.target:toArray(true, "=")[1] == 0 then + local enemy = self.battle:getEnemy(target.roomId, target.blockId) + if not enemy then return end + self.battle.player:releaseSkill(skillId, skillLevel, enemy) + else + self.battle.player:releaseSkill(skillId, skillLevel) + end + + self:afterRound() + self.battle:getDB() + role:updateProperties({advInfo = self.advInfo, advTeam = self.advTeam}) + return true +end + +--敌人死亡 +function Adv:enemyDead(roomId, blockId) + local block = self.rooms[roomId].blocks[blockId] + --死了以后掉东西 + if block.event and (block.event.etype == AdvEventType.BOSS or block.event.etype == AdvEventType.Monster) then --处理死亡 + local item = block.event.item + if not item then + if block.event.etype == AdvEventType.BOSS then + item = {1, 1} --todo 钥匙 + else + local monsterData = csvdb["event_monsterCsv"][block.event.id] + local dropData = csvdb["event_dropCsv"][monsterData.dropid] + item = dropData["range"]:randWeight(true) + end + end + table.clear(block.event) + block.event.etype = AdvEventType.Drop + block.event.item = item + end + self:backBlockChange(roomId, blockId) +end + +--cType 0 or nil 值 1 百分比 +function Adv:changePower(value, cType) + cType = cType or 0 + if cType == 0 then + self.advInfo.power = self.advInfo.power + value + elseif cType == 1 then + self.advInfo.power = self.advInfo.power + self.advInfo.power * value + end + self.advInfo.power = math.floor(math.max(0, self.advInfo.power)) +end + +function Adv:pushBackEvent(btype, params) + table.insert(self.backEvents, {btype = btype, params = params}) +end + +function Adv:backReward(items) + self:pushBackEvent(AdvBackEventType.Reward, {items = items}) +end +-- if is player enemyId is nil +--isMax 是否是改变血量上限 +function Adv:backHpChange(enemyId, change, isMax) + self:pushBackEvent(AdvBackEventType.HpChange, {enemyId = enemyId, change = change, isMax = isMax}) +end +-- if is player enemyId is nil +function Adv:backAtkChange(enemyId, change) + self:pushBackEvent(AdvBackEventType.AtkChange, {enemyId = enemyId, change = change}) +end +-- if is player enemyId is nil +function Adv:backBuff(enemyId, buffId, isDel) + self:pushBackEvent(AdvBackEventType.Buff, {enemyId = enemyId, buffId = buffId, isDel = isDel}) +end +-- if is player enemyId is nil +function Adv:backSkill(enemyId, skillId, receiver) + self:pushBackEvent(AdvBackEventType.Skill, {enemyId = enemyId, buffId = skillId, receiver = receiver}) +end + +function Adv:backNext() + self:pushBackEvent(AdvBackEventType.Next, {}) +end + +function Adv:backEnd(score) + self:pushBackEvent(AdvBackEventType.End, {score = score}) +end + +function Adv:backBlockChange(roomId, blockId) + self:pushBackEvent(AdvBackEventType.BlockChange, {roomId = roomId, blockId = blockId}) +end + +function Adv:backAtk(enemyId, receiver) + self:pushBackEvent(AdvBackEventType.Atk, {enemyId = enemyId, receiver = receiver}) +end + +function Adv:popBackEvents() + local events = self.backEvents + self.backEvents = {} + return events +end + +--回合事件处理 +function Adv:afterRound() + if self.battle then + self.battle:afterRound() + end +end + +return Adv \ No newline at end of file diff --git a/src/adv/AdvBattle.lua b/src/adv/AdvBattle.lua new file mode 100644 index 0000000..c37b6d7 --- /dev/null +++ b/src/adv/AdvBattle.lua @@ -0,0 +1,136 @@ +local Player, Enemy = require "adv.advPlayer" +local Buff = require "adv.AdvBuff" +local AdvBattle = class("Battle") +function Battle:ctor(adv) + self.adv = adv + self.player = nil --玩家 + self.enemys = {} --怪 + self:initPlayer() + self:initEnemys() + self:initAfter() +end + +function Battle:initAfter() + self.player:initAfter(self.adv.advTeam.player) + for _, enemy in pairs(self.enemys) do + enemy:initAfter(self.adv.rooms[enemy.roomId].blocks[enemy.blockId].event.enemy) + end +end + +function Battle:initPlayer() + if not next(self.adv.advTeam.heros) then return end + if not self.adv.advTeam.player then + local hp = 0 + local player = {} + player.passives = {} + for slot, heroId in pairs(self.adv.advTeam.heros) do + if self.adv.owner.heros[heroId] then + hp = hp + self.adv.owner.heros[heroId]:getProperty("battleV") + local advSkillId = csvdb["unitCsv"][self.adv.owner.heros[heroId]:getSkinId()]["adv"] + if advSkillId > 1000 then + table.insert(player.passives, {id = advSkillId, level = self.adv.owner.heros[heroId]:getSkillLevel(4)}) + end + end + end + player.hp = hp + player.atk = player.hp * 0.1 --todo 系数是临时的 + player.miss = 0 + player.hit = 100 + self.adv.advTeam.player = player + end + self.player = Player.new(self, self.adv.advTeam.player) +end + +function Battle:initEnemys() + for _, room in pairs(self.adv.rooms) do + for _, block in pairs(room.blocks) do + self:addEnemy(room, block) + end + end +end + +function Battle:addEnemy(room, block) + if block.event and (block.event.etype == AdvEventType.BOSS or block.event.etype == AdvEventType.Monster) then + if not block.event.enemy then + local enemyCsv = csvdb["event_monsterCsv"][block.event.id] + local enemy = {} + enemy.hp = enemyCsv.hp + enemyCsv.levelhp * self.adv.advInfo.level + enemy.atk = enemyCsv.atk + enemyCsv.levelatk * self.adv.advInfo.level + enemy.hit = enemyCsv.hit + enemyCsv.levelhit * self.adv.advInfo.level + enemy.miss = enemyCsv.miss + enemyCsv.levelmiss * self.adv.advInfo.level + enemy.passives = {} + for _, id in ipairs(enemyCsv.passive:toArray(true, "=")) do + table.insert(enemy.passives, {id = id}) + end + block.event.enemy = enemy + 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)) + end + end +end + +function Battle:getEnemy(roomId, blockId) + for _, enemy in ipairs(self.enemys) do + if enemy.roomId == roomId and enemy.blockId = blockId then + return enemy + end + end +end + +function Battle:getEnemyById(id) + for _, enemy in ipairs(self.enemys) do + if enemy.id == id then + return enemy + end + end +end +--普通攻击 +function Battle:playerAtk(roomId, blockId) + local enemy = self:getEnemy(roomId, blockId) + if enemy then + enemy:hurt(self.player:getHurtValue(), self.player, {hurtType = 1}) + --是否无法反击 + if not enemy:hadBuff(Buff.CANT_BACK_ATK) then + self.player:hurt(enemy:getHurtValue(), enemy, {hurtType = 1}) + end + end +end +--触发全员被动技能 +function Battle:triggerPassive(condType, params) + +end + +--回合 +function Battle:afterRound() + self.player:afterRound() + table.sort(self.enemys, function(e1, e2) + return e1.id < e2.id + end) + for _, enemy in ipairs(self.enemys) do + enemy:afterRound() + end + self.player:clearRound() + for _, enemy in ipairs(self.enemys) do + enemy:clearRound() + end + for i = #self.enemys, 1, -1 do + if self.enemys[i].isDead then + self.adv:enemyDead(self.enemys[i].roomId, self.enemys[i].blockId) + self.enemys[i]:clear() + table.remove(self.enemys, i) + end + end + if self.player.isDead then + self.adv:over(-1) + end +end + +--写入数据 +function Battle:getDB() + self.adv.advTeam.player = self.player:getDB() + for _, enemy in ipairs(self.enemys) do + local block = self.adv.rooms[enemy.roomId].blocks[enemy.blockId] + block.event.enemy = enemy:getDB() + end +end + +return AdvBattle \ No newline at end of file diff --git a/src/adv/AdvBuff.lua b/src/adv/AdvBuff.lua new file mode 100644 index 0000000..eae1a99 --- /dev/null +++ b/src/adv/AdvBuff.lua @@ -0,0 +1,294 @@ + +local Buff = class("Buff") + +Buff.HP_CHANGE = 1 --生命变化(每回合生效) +Buff.HP_MAX_CHANGE = 2 --生命上限变化(状态) +Buff.ATK_CHANGE = 3 --攻击变化(状态) +Buff.IMMNUE_ATK = 4 -- 免疫普通攻击 +Buff.BACK_HURT = 5 -- 伤害反弹 +Buff.HURT_CHANGE = 6 -- 伤害变化 +Buff.INJURED_CHANGE = 7 -- 受伤变化 +Buff.HURT_TRANSFER = 8 -- 侍宠(转移自己受到的伤害) +Buff.HURT_ABSORB = 9 -- 舍身(吸收他人受到的伤害) +Buff.CANT_BACK_ATK = 10 -- 无法反击 +Buff.IMMNUE_BUFF = 11 -- 免疫buff +Buff.CLEAR_BUFF = 12 -- 清除buff +Buff.CANT_SKILL = 13 -- 禁止技能 +Buff.OPEN_BLOCK = 14 -- 翻开格子(每回合) +Buff.POWER_CHANGE = 15 -- 体力变化(每回合) +Buff.HIT_CHANGE = 16 -- 命中变化(状态) +Buff.MISS_CHANGE = 17 -- 闪避变化(状态) + +--角色一些属性的变化 +local function commonAttr(_Buff, attrName) + _Buff._init = function(self, data) --初始化变化值 + self.owner:reSetAttr(attrName) + end + _Buff._effectValue = function(self) + return self.buffData.effectValue1, self.buffData.effectValue2 + end + _Buff._endBuff = function(self, data) + self.owner:reSetAttr(attrName) + end +end + +local BuffFactory = { + [Buff.HP_CHANGE] = function(_Buff) + _Buff._init = function(self, data) --初始化变化值 + self._changeV = 0 + if self.buffData.effectValue1 == 0 then --固定值 + self._changeV = self.buffData.effectValue2 + elseif self.buffData.effectValue1 == 1 then + local baseOwner = self.buffData.effectValue4 == 1 and self.owner or self.release + local attrs = {[0] = "hp", [1] = "hpMax", [2] = "atk"} + self._changeV = baseOwner[attrs[self.buffData.effectValue3]] * self.buffData.effectValue2 + end + if self._changeV < 0 then + self._changeV = -self.release:getHurtValue(-self._changeV) + end + end + _Buff._initDB = function(self, data) + self._changeV = data.cv + end + _Buff._afterRount = function(self) + if self._changeV > 0 then + self.owner:recover(self._changeV, self.release) + elseif self._changeV < 0 then + self.owner:hurt(-self._changeV, self.release, {hurtType = 2}) + end + end + _Buff._getDB = function(self) + return {cv = self._changeV} + end + end, + + [Buff.HP_MAX_CHANGE] = function(_Buff) + _Buff._init = function(self, data) --初始化变化值 + self._changeV = 0 + if self.buffData.effectValue1 == 0 then --固定值 + self._changeV = self.buffData.effectValue2 + elseif self.buffData.effectValue1 == 1 then + local baseOwner = self.buffData.effectValue4 == 1 and self.owner or self.release + local attrs = {[0] = "hp", [1] = "hpMax", [2] = "atk"} + self._changeV = baseOwner[attrs[self.buffData.effectValue3]] * self.buffData.effectValue2 + end + local old = self.owner.hpMax + self.owner.hpMax = math.max(1, self.owner.hpMax + self._changeV) + self._changeV = self.owner.hpMax - old + if self._changeV > 0 then + self.owner:recover(self._changeV, self.release) + elseif self._changeV < 0 then + self.owner:hurt(self.release:getHurtValue(-self._changeV), self.release, {hurtType = 2}) + self.owner.hp = math.min(self.owner.hpMax, self.owner.hp) + end + end + _Buff._initDB = function(self, data) + self._changeV = data.cv + end + _Buff._endBuff = function(self, data) + if self._changeV then + self.owner.hpMax = math.max(1, self.owner.hpMax - self._changeV) + self.owner.hp = math.min(self.owner.hpMax, self.owner.hp) + end + end + _Buff._getDB = function(self) + return {cv = self._changeV} + end + end, + [Buff.ATK_CHANGE] = function(_Buff) + commonAttr(_Buff, "atk") + end, + + [Buff.HIT_CHANGE] = function(_Buff) + commonAttr(_Buff, "hit") + end, + + [Buff.MISS_CHANGE] = function(_Buff) + commonAttr(_Buff, "miss") + end, + + [Buff.BACK_HURT] = function(_Buff) + _Buff._effectValue = function(self) + return self.buffData.effectValue1, self.buffData.effectValue2, self.buffData.effectValue3 + end + end, + + [Buff.HURT_CHANGE] = function(_Buff) + _Buff._effectValue = function(self) + return self.buffData.effectValue1, self.buffData.effectValue2 + end + end, + + [Buff.INJURED_CHANGE] = function(_Buff) + _Buff._effectValue = function(self) + return self.buffData.effectValue1, self.buffData.effectValue2 + end + end, + + [Buff.HURT_TRANSFER] = function(_Buff) + _Buff._effectValue = function(self) + return self.buffData.effectValue1, self.buffData.effectValue2 + end + end, + + [Buff.HURT_ABSORB] = function(_Buff) + _Buff._effectValue = function(self) + return self.buffData.effectValue1, self.buffData.effectValue2 + end + end, + + [Buff.IMMNUE_BUFF] = function(_Buff) + _Buff._init = function(self, data) + self.count = self.buffData.effectValue3 + end + _Buff._effectValue = function(self) + return self.buffData.effectValue1, self.buffData.effectValue2 + end + end, + + [Buff.CLEAR_BUFF] = function(_Buff) + _Buff._init = function(self, data) + self.count = self.buffData.effectValue3 + self:_afterRount() -- 挂上就清除一下子 + end + _Buff._afterRount = function(self) + local cType, aim = self:effectValue() + for _, buff in ipairs(self.buffs) do + if not buff.isDel and ((cType == 0 and buff.id == aim) or (cType == 1 and buff:getGroup() == aim)) then + buff.isDel = true + self:decCount() + end + end + end + _Buff._effectValue = function(self) + return self.buffData.effectValue1, self.buffData.effectValue2 + end + end, + + [Buff.OPEN_BLOCK] = function(_Buff) + _Buff._afterRount = function(self) + self.owner.battle.adv:openBlockRand(self.buffData.effectValue1) + end + end, + + [Buff.POWER_CHANGE] = function(_Buff) + _Buff._afterRount = function(self) + self.owner.battle.adv:changePower(self.buffData.effectValue2, self.buffData.effectValue1) + end + end +} + + +function Buff.create(owner, release, data) + local buff = Buff.new(owner, data.id) + buff:initNew(release, data) + return buff +end + +function Buff.load(owner, data) + local buff = Buff.new(owner, data.id) + buff:initByDB(data) + return buff +end + +function Buff:ctor(owner, id) + self.owner = owner + self.id = id + self.buffData = csvdb["adv_buffCsv"][self.id] + self.isDel = false + self.duration = 0 --剩余的回合 + self.count = -1 -- 可生效的次数 -1 无次数限制 + + if BuffFactory[self.buffData.type] then + BuffFactory[self.buffData.type](self) + end +end + +function Buff:initByDB(data) + if data.rele then + if data.rele == 0 then + self.release = self.owner.battle.player + else + self.release = self.owner.battle:getEnemyById(data.rele) + end + end + self.duration = data.dur + if data.count then + self.count = data.count + end + + if self._initDB then + self:_initDB(data) + end +end + +function Buff:initNew(release, data) + self.release = release + self.duration = self.buffData.duration + if self._init then + self:_init(data) + end +end + +function Buff:afterRound() + if self.isDel or self.owner.isDead then return end + + if self._afterRount then + self:_afterRount() + end + + if self.buffData.duration ~= 0 then + self.duration = self.duration - 1 + if self.duration <= 0 then + self.isDel = true + end + end +end + +function Buff:effectValue() + if self._effectValue then + return self:_effectValue() + end +end +--删除buff 时调用 +function Buff:endBuff() + if self._endBuff then + self:_endBuff() + end +end + +function Buff:getType() + return self.buffData.type +end + +function Buff:decCount() + if self.count == -1 then return end + self.count = self.count - 1 + if self.count <= 0 then + self.isDel = true + end +end + +function Buff:getGroup() + return self.buffData.group +end + +function Buff:getDB() + local db = {} + if self._getDB then + db = self:_getDB() + end + db.id = self.id + if self.release and not self.release.isDead then + db.rele = self.release.id or 0 --释放者的id (0 为玩家) (不存在 则释放者不存在或者已经死亡) + end + if self.buffData.duration ~= 0 then + db.dur = self.duration + end + if self.count ~= -1 then + db.count = self.count + end + return db +end + +return Buff \ No newline at end of file diff --git a/src/adv/AdvPassive.lua b/src/adv/AdvPassive.lua new file mode 100644 index 0000000..7cef59a --- /dev/null +++ b/src/adv/AdvPassive.lua @@ -0,0 +1,102 @@ +local Passive = class("Passive") + +-- 每回合触发的使用 afterRound +-- 其他触发的使用 triggerPassive + +Passive.BORN_ONCE = 1 -- 自身出生(翻开所在格子)后M回合触发(1次) +Passive.BORN_PRE = 2 --自身出生(翻开所在格子)后每N回合触发1次 +Passive.HURT_PERCENT_SELF = 3 --自身,每损失N%生命值,触发1次 +Passive.HURT_PERCENT_TEAM = 4 --队友,每损失N%生命值,触发1次 +Passive.HP_LOW_SELF = 5 --自身生命值N%时,每回合触发 +Passive.HP_UP_TEAM = 8 --敌人生命值>N%时,每回合触发 +Passive.SELF_ATK = 9 --自身攻击N次后,触发1次 +Passive.SELF_HURT = 10 --自身受击N次后,触发1次 +Passive.TEAM_ATK = 11 --队友攻击N次后,触发1次 +Passive.TEAM_HURT = 12 --队友受击N次后,触发1次 +Passive.MONSTER_COUNT_UP = 13 --场上存在N个以上怪物,每回合触发 +Passive.MONSTER_COUNT_LOW = 14 --场上存在N个以下怪物,每回合触发 +Passive.SELF_DEAD = 15 --自身死亡后,触发1次 +Passive.TEAM_DEAD = 16 --队友死亡后,触发1次 +Passive.TARGET_SKILL = 17 --目标每使用N次技能,触发1次 +Passive.TEAM_SKILL = 18 --队友每使用N次技能,触发1次 +Passive.ROOM_SHOW = 19 --自身所在房间被展示时,触发1次 + +-- 不同的开启条件 +local PassiveFactory = { + [] +} + +function Passive:ctor(owner, data) + self.owner = owner + self.id = data.id + self.level = data.level or 1 + self.passiveData = csvdb["adv_skill_passiveCsv"][self.id][self.level] + self.isDel = false + self.round = data.round or 0 --触发剩余回合数 + self.count = data.count or 0 --触发剩余次数 + if PassiveFactory[self.passiveData.condition] then + PassiveFactory[self.passiveData.condition](self) + end +end + +function Passive:getCondType() + return self.passiveData.condition, self.passiveData.value +end + +function Passive:effect() + if self._effect then + self:_effect() + end + --次数为 -1 一局只能触发一次,触发过后删掉就可以 + if self.count == -1 then + self.isDel = true + end + if self.count > 0 then + self.count = self.count - 1 + self.round = self.passiveData.space + end +end + +function Passive:afterRound() + if self.isDel or self.owner.isDead then return end + if self._afterRound then + self:_afterRound() --有的触发自己检测在这里检查 + end + if self.round > 0 then --回合触发的 + self.round = self.round - 1 + if self.round == 0 then + self:effect() + end + end +end + +-- 正在触发中 +function Passive:isActive( ) + return self.count > 0 or self.round > 0 +end + +function Passive:trigger(condType, params) --触发检查 + if self:getCondType() ~= condType then return end + if self:isActive() then return end + + self.round = self.passiveData.delay --首次 + self.count = self.passiveData.count --次数 + -- 没有延迟就直接触发 + if self.round == 0 then + self:effect() + end +end + +function Passive:getDB() + local db = {} + if self._getDB then + db = self:_getDB() + end + db.id = self.id + db.level = self.level + db.round = self.round + db.count = self.count +end +return Passive \ No newline at end of file diff --git a/src/adv/AdvPlayer.lua b/src/adv/AdvPlayer.lua new file mode 100644 index 0000000..1f54c3a --- /dev/null +++ b/src/adv/AdvPlayer.lua @@ -0,0 +1,388 @@ +-- 角色 +local Buff = require "adv.AdvBuff" +local Passive = require "adv.AdvPassive" + +local BaseObject = class("BaseObject") +function BaseObject:ctor(battle) + self.battle = battle + self.hpMax = 0 + self.hp = 0 + self.atk = 0 + self.aType = 0 --攻击类型 + self.lock = nil + self.passives = {} --固有技能 + self.buffs = {} --buff + self.isDead = false +end +--初始化角色 +function BaseObject:initData(data) + self.hpMax = data.hpMax or data.hp + self.hp = data.hp + --可变化的值 + self.atk = data.atk + self.miss = data.miss + self.hit = data.hit + --基础值记录 + self._atk = data._atk or self.atk + self._miss = data._miss or self.miss + self._hit = data._hit or self.hit +end +-- 角色初始化完以后才是 技能和被动技能 方便初始化 buff 的 释放对象 +function BaseObject:initAfter(data) + for _, passive in ipairs(data.passives or {}) do + table.insert(self.passives, Passive.load(self, passive)) + end + for _, buff in ipairs(data.buffs or {}) do + table.insert(self.buffs, Buff.load(self, buff)) + end +end + +function BaseObject:afterRound() + for _, passive in ipairs(self.passives) do + passive:afterRound(self) + end + for _, buff in ipairs(self.buffs) do + buff:afterRound(self) + end +end + +function BaseObject:clearRound() + for i = #self.passives, 1, -1 do + if self.passives[i].isDel then + self.passives[i]:endPassive() + table.remove(self.passives, i) + end + end + for i = #self.buffs, 1, -1 do + if self.buffs[i].isDel then + self.buffs[i]:endBuff() + table.remove(self.buffs, i) + end + end +end +function BaseObject:clear() + self.buffs = {} + self.passives = {} +end + +function BaseObject:addBuff(buffId, releaser) + local buffData = csvdb["adv_buffCsv"][buffId] + if not buffData then return end + for _, buff in ipairs(self.buffs) do + if not buff.isDel and (buff:getType() == CLEAR_BUFF or buff:getType() == IMMNUE_BUFF) then + local cType, aim = buff:effectValue() -- 0=buffid 1=buff组 + if (cType == 0 and buffId == aim) or (cType == 1 and buffData.group == aim) then -- buff 剔除 + buff:decCount() --减少次数 + return + end + end + end + table.insert(self.buffs, Buff.create(self, releaser, {id = buffId})) +end + +function BaseObject:hadBuff(bType) + for _, buff in ipairs(self.buffs) do + if not buff.isDel and buff:getType() == bType then + return true + end + end +end + +-- 通用的buff 效果汇总 -- 0 固定 1百分比 两种分类 +function BaseObject:getCommonBuffEffect(bType) + local effect, count = {[0] = 0, [1] = 0}, 0 + for _, buff in ipairs(self.buffs) do + if not buff.isDel and buff:getType() == bType then + local cType, value = buff:effectValue() + if cType then + change[cType] = change[cType] + value + count = count + 1 + end + end + end + return effect, count --效果 和生效的buff 个数 +end +--伤害反弹 +function BaseObject:getBackHurtBuff(isAtk) + local effect = {[0] = 0, [1] = 0} + for _, buff in ipairs(self.buffs) do + if not buff.isDel and buff:getType() == Buff.BACK_HURT then + local cType, value, aType = buff:effectValue() -- aType 0 全部 1 普通攻击 + if cType then + if aType == 0 or isAtk then + change[cType] = change[cType] + value + end + end + end + end + return effect +end + +--释放者伤害变化 +function BaseObject:getHurtChange() + local change = self:getCommonBuffEffect(Buff.HURT_CHANGE) + return change +end +--受伤者受伤变化 +function BaseObject:getInjuredChange() + local change = self:getCommonBuffEffect(Buff.INJURED_CHANGE) + return change +end +--重新计算属性 +function BaseObject:reSetAttr(field) + self[field] = self["_" .. field] --重置一下 + local fieldToBuff = {atk = Buff.IMMNUE_ATK, hit = Buff.HIT_CHANGE, miss = Buff.MISS_CHANGE} + local effect = self:getCommonBuffEffect(fieldToBuff[field]) + self[field] = (self[field] + effect[0]) * (1 + effect[1]) +end + +--计算打出伤害加成后的值 +function BaseObject:getHurtValue(value) + value = value or self.atk + local hurtChange = self:getHurtChange() + return math.max(0, (value + hurtChange[0]) * (1 + hurtChange[1])) +end +--计算自己伤害减免后的值 +function BaseObject:getInjuredValue(value) + local injuredChange = self:getInjuredChange() + return math.max(0, (value + injuredChange[0]) * (1 + injuredChange[1])) +end + +--最终伤害 = [ 敌方攻击 * (1+伤害增加百分比-伤害减少百分比)*(1+受伤增加百分比-受伤减少百分比)+(伤害增加固定值-伤害增加固定值+受伤增加固定值-受伤增加固定值)]*(1+侍宠百分比)-侍宠固定值 +-- params -- hurtType 1 普攻伤害 2 buff伤害 3 反弹伤害 +--进入这个方法之前计算好释放者加成的伤害 +function BaseObject:hurt(value, releaser, params) + params = params or {} + if params.hurtType and params.hurtType == 1 then + if self:hadBuff(Buff.IMMNUE_ATK) then return end --无视普通攻击 + + local hit = releaser.hit - self.miss --命中率 + if hit < math.randomInt(1, 100) then --miss + return + end + end + + value = self:getInjuredValue(value) --减伤计算 + if value == 0 then return end + + -- 舍身和恃宠 + local team = self:getTeam(1) + local transfer = {} + local absorb = {} + for _, one in ipairs(team) do + local change1, count1 = one:getCommonBuffEffect(Buff.INJURED_CHANGE) + local change2, count2 = one:getCommonBuffEffect(Buff.HURT_ABSORB) + if count1 > 0 then + table.insert(transfer, {one, change1, count1}) + end + if count2 > 0 then + table.insert(absorb, {one, change2, count2}) + end + end + if #absorb == 1 then --舍身优先级高 --舍身生效 + if absorb[1][1] ~= self then --舍身的人不是自己才有效 + local absorbV = (value - absorb[1][2][0]) * absorb[1][2][1] + absorb[1][2][0] --固定值先生效 + value = value - absorbV + absorb[1][1]:hurt(absorbV, releaser, params) + end + else + if #transfer == 1 and transfer[1][1] == self and #team > 1 then --侍宠 生效 + local transferValue = (value - transfer[1][2][0])* transfer[1][2][1] + transfer[1][2][0] --固定值先生效 + value = value - transferValue + local oneValue = transferValue / (#team - 1) + for _, one in ipairs(team) do + if one ~= self then + one:hurt(oneValue, releaser, params) + end + end + end + end + + value = math.max(0, value) + if value == 0 then return end + -- 反弹伤害 + if params.hurtType ~= 3 and releaser and not releaser.isDead then + local backEffect = self:getBackHurtBuff(params.hurtType == 1) + local backValue = math.max(0, value * backEffect[1] + backEffect[0]) + releaser:hurt(backValue, releaser, {hurtType = 3}) + end + + --受伤了~ + self.hp = math.max(0, self.hp - value) + if self.hp == 0 then + self.isDead = true + end +end +--恢复 +function BaseObject:recover(value, releaser, params) + params = params or {} + value = math.max(0, value) + self.hp = math.min(self.hpMax, self.hp + value) +end + +function BaseObject:releaseSkill(skillId, skillLevel, target) + skillLevel = skillLevel or 1 + local skillData = csvdb["adv_skillCsv"][skillId][skillLevel or 1] + local targetChoose = skillData.target:toArray(true, "=") + local targetNum = skillData.targetNum:toArray(true, "=") + --确定目标 + local targets = {} + if targetChoose[1] == 0 then --选定一个 + assert(target, "error " .. self.class.__cname .. " releaseSkill id: " .. skillId .." targetChoose==0 but no target") + table.insert(targets, target) + elseif targetChoose[1] == 1 then --全部 + if not targetChoose[2] or targetChoose[2] == 0 then + targets = self:getTeam(0) + else --指定 monsterId + local team = self:getTeam(0) + for _, one in pairs(team) do + if one.monsterId and one.monsterId == targetChoose[2] then + table.insert(targets, one) + end + end + end + elseif targetChoose[1] == 2 then -- 我方 + if targetChoose[2] == 1 then + table.insert(targets, self) + elseif targetChoose[2] == 2 then + targets = self:getTeam(1, true) + elseif targetChoose[2] == 3 then + targets = self:getTeam(1) + end + elseif targetChoose[1] == 3 then -- 敌方 + targets = self:getTeam(2) + end + + if targetChoose[1] ~= 0 then -- 不是指定一个的进行 排序 和 数量筛选 + local tempT = targets + local targets = {} + local function randNum(isSort) + if #tempT <= targetNum[2] then + targets = tempT + return + end + if isSort then + for i = 1, targetNum[2] do + table.insert(targets, tempT[i]) + end + else + for i = 1, targetNum[2] do + local idx = math.randomInt(1, #tempT) + table.insert(targets, tempT[idx]) + table.remove(tempT, idx) + end + end + end + if targetNum[1] == 0 then --任意排序 + randNum(false) + elseif targetNum[1] == 1 then --血量从低到高 + table.sort(tempT, function(o1, o2) + return o1.hp < o2.hp + end) + randNum(true) + elseif targetNum[1] == 2 then --血量从高到低 + table.sort(tempT, function(o1, o2) + return o1.hp > o2.hp + end) + randNum(true) + else + targets = tempT --all + end + end + -- 增加buff + for _, buffId in ipairs(skillData.selfbuff:toArray(true, "=")) do + self:addBuff(buffId, self) + end + + for _, buffId in ipairs(skillData.targetbuff:toArray(true, "=")) do + for _, target_ in ipairs(targets) do + target_:addBuff(buffId, self) + end + end +end + +--0 全部 1 我方 2 敌方 +function BaseObject:getTeam(nType, noSelf) + nType = nType or 0 + local team = {} + local function addPlayer() + if not noSelf or self.battle.player ~= self then + if not self.battle.player.isDead then + table.insert(team, self.battle.player) + end + end + end + local function addEnemy() + for _, enemy in pairs(self.battle.enemys) do + if not noSelf or enemy ~= self then + if not enemy.isDead and not enemy.lock then -- 已经翻开的 + table.insert(team, enemy) + end + end + end + end + if nType == 0 then + addPlayer() + addEnemy() + elseif nType == 1 then + if self.class == Player then --玩家 + addPlayer() + else + addEnemy() + end + elseif nType == 2 then + if self.class == Player then --玩家 + addEnemy() + else + addPlayer() + end + end + return team +end + +function BaseObject:getDB() + local db = {} + db.hpMax = self.hpMax + db.hp = self.hp + local baseAttr = {"atk", "miss", "hit"} + for _, field in pairs(baseAttr) do + db[field] = self[field] + db["_"..field] = self["_" .. field] + end + db.passives = {} + for _, passive in ipairs(self.passives) do + table.insert(db.passives, passive:getDB()) + end + db.buff = {} + for _, buff in ipairs(self.buffs) do + table.insert(db.buffs, buff:getDB()) + end + return db +end + +function BaseObject:triggerPassive(condType, params) + +end + +local Enemy = class("Enemy", BaseObject) +function Enemy:ctor(battle, monsterId, id, roomId, blockId, lock, enemy) + Enemy.super.ctor(self, battle) + self.id = id + self.monsterId = monsterId + self.roomId = roomId + self.blockId = blockId + self.lock = lock + self:initData(enemy) +end +function Enemy:unlock(id) + self.id = id + self.lock = nil +end + +local Player = class("Player", BaseObject) +function Player:ctor(battle, data) + Player.super.ctor(self, battle) + self:initData(data) +end + +return Player, Enemy \ No newline at end of file diff --git a/src/models/HeroPlugin.lua b/src/models/HeroPlugin.lua index 8b6785d..296002b 100644 --- a/src/models/HeroPlugin.lua +++ b/src/models/HeroPlugin.lua @@ -121,6 +121,12 @@ function HeroPlugin.bind(Hero) return csvdb["skill_blockCsv"][unitData.block] elseif idx == 2 then return csvdb["skill_specialCsv"][unitData.special] + elseif idx == 4 then --冒险技能 + if unitData.adv > 1000 then + return csvdb["adv_skill_passiveCsv"][unitData.adv] + else + return csvdb["adv_skillCsv"][unitData.adv] + end end return {} end diff --git a/src/models/Role.lua b/src/models/Role.lua index 72a5db8..fc82133 100644 --- a/src/models/Role.lua +++ b/src/models/Role.lua @@ -2,12 +2,10 @@ local Role = class("Role", require("shared.ModelBase")) local RolePlugin = import(".RolePlugin") local RoleTask = import(".RoleTask") -local RoleAdv = import(".RoleAdv") local RoleActivity = import(".RoleActivity") local RoleChangeStruct = import(".RoleChangeStruct") RolePlugin.bind(Role) RoleTask.bind(Role) -RoleAdv.bind(Role) RoleActivity.bind(Role) RoleChangeStruct.bind(Role) @@ -15,6 +13,7 @@ function Role:ctor( properties ) Role.super.ctor(self, properties) self.ignoreHeartbeat = false self.heros = {} + self.advData = nil end Role.schema = { @@ -39,7 +38,9 @@ Role.schema = { --冒险相关 advPass = {"string", ""}, -- 通关记录 - advInfo = {"table", {}}, -- 其他信息 + advItems = {"string", ""}, -- 冒险临时背包 + advInfo = {"table", {}}, -- 冒险关卡信息 + advTeam = {"table", {}}, -- 冒险玩家队伍信息 } @@ -145,6 +146,7 @@ function Role:data() loveStatus = self:getProperty("loveStatus"):toNumMap(), advPass = self:getProperty("advPass"), advInfo = self:getProperty("advInfo"), + advItems = self:getProperty("advItems"):toNumMap(), } end diff --git a/src/models/RoleAdv.lua b/src/models/RoleAdv.lua deleted file mode 100644 index 59f0674..0000000 --- a/src/models/RoleAdv.lua +++ /dev/null @@ -1,250 +0,0 @@ - -local RoleAdv = {} - -function RoleAdv.bind(Role) - - - local function getIdByCr(c, r) - local crId = math.abs(r) + math.abs(c) * 100 - if c < 0 then - crId = crId + 10000 - end - if r < 0 then - crId = crId + 20000 - end - return crId - end - local function getCrById(crId) - local c = math.floor(crId % 10000 / 100) - local r = crId % 100 - local last = math.floor(crId / 10000) - if last == 3 then - c, r = -c, -r - elseif last == 1 then - c = -c - elseif last == 2 then - r = -r - end - return c, r - end - - --检查 是否满足层数限制条件 - local function checkIsIn(checkValue, checkType, checkRange) - if not checkValue then return end - if checkType == 1 then - local limits = checkRange:toNumMap() - for min, max in pairs(limits) do - if checkValue >= min and checkValue <= max then - return true - end - end - else - local limit = checkRange:toArray(true, "=") - for _, _l in ipairs(limit) do - if _l == checkValue then - return true - end - end - end - end - - --关卡事件库 - local function getEventLib(chapterId, level) - local chapter = math.floor(chapterId / 100) % 100 - - local libsToType = { - ["event_monsterCsv"] = {AdvEventType.Monster, AdvEventType.BOSS}, - ["event_chooseCsv"] = AdvEventType.Choose, - ["event_dropCsv"] = AdvEventType.Drop, - ["event_buildingCsv"] = AdvEventType.Build, - ["event_traderCsv"] = AdvEventType.Trader, - - } - local eventLib = {} - for lib, eventType in pairs(libsToType) do - if type(eventType) == "table" then - for _, temp in ipairs(eventType) do - eventLib[temp] = {} - end - else - eventLib[eventType] = {} - end - for id, data in pairs(csvdb[lib]) do - if data.levelchapter == chapter then - if checkIsIn(level, data.leveltype, data.levellimit) then - if type(eventType) == "table" then - eventLib[eventType[data.type]][id] = data - else - eventLib[eventType][id] = data - end - end - end - end - end - return eventLib - end - - -- 生成地图 是否可以生成地图上层判断 - function Role:randomAdvMap(chapterId, level) - local chapterData = csvdb["adv_chapterCsv"][chapterId] - if not chapterData then return end - if level > chapterData.limitlevel then return end - --随出地图 - local raw_pool = chapterData.mapid:toArray(true, "=") - local advInfo = self:getProperty("advInfo") - local lastMapId = advInfo.mapId --非同一层不连续随出同一张类似的地图 - local lastChapterId = advInfo.chapter - local pool = {} - for _, mapId in ipairs(raw_pool) do - local temp = csvdb["mapCsv"][mapId] - if temp and (lastChapterId == chapterId or lastMapId ~= mapId) then --非同一层不连续随出同一张类似的地图 - if checkIsIn(level, temp.leveltype, temp.levellimit) then - table.insert(pool, mapId) - end - end - end - if not next(pool) then return end - local mapId = pool[math.randomInt(1, #pool)] - --随出事件 - local mapData = csvdb["map_" .. csvdb["mapCsv"][mapId]["path"] .. "Csv"] - if not mapData then return end - - table.clear(advInfo) - advInfo.chapter = chapterId - advInfo.level = level - advInfo.mapId = mapId - advInfo.rooms = {} -- {[roomId] = {event = {}, open = {}, isPath = nil},} -- event 事件信息(具体信息查看randomEvent), open 是否解锁 isPath 是否是路径 - - --事件随机 - local eventLib = getEventLib(chapterId, level) - local monsterEvents = {} --处理钥匙掉落 - local haveBoss = false - local function randomEvent(roomId, blockId, eventType) - if advInfo.rooms[roomId]["event"][blockId] then return end --已经有事件了 不覆盖 - local event = {etype = eventType} - local randomFunc = { - [AdvEventType.In] = function() - advInfo.rooms[roomId]["open"][blockId] = 1 - end, - [AdvEventType.Out] = function() - end, - [AdvEventType.BOSS] = function() - if not next(eventLib[eventType]) or haveBoss then return false end - haveBoss = true - event.id = math.randWeight(eventLib[eventType], "showup") - end, - [AdvEventType.Choose] = function() - if not next(eventLib[eventType]) then return false end - event.id = math.randWeight(eventLib[eventType], "showup") - end, - [AdvEventType.Drop] = function() - if not next(eventLib[eventType]) then return false end - event.item = eventLib[eventType][math.randWeight(eventLib[eventType], "showup")]["range"]:randWeight(true) - end, - [AdvEventType.Monster] = function() - if not next(eventLib[eventType]) then return false end - event.id = math.randWeight(eventLib[eventType], "showup") - table.insert(monsterEvents, event) - end, - [AdvEventType.Trader] = function() - if not next(eventLib[eventType]) then return false end - event.id = math.randWeight(eventLib[eventType], "showup") - end, - [AdvEventType.Build] = function() - if not next(eventLib[eventType]) then return false end - event.id = math.randWeight(eventLib[eventType], "showup") - end, - } - - if randomFunc[eventType] then - if randomFunc[eventType]() ~= false then - advInfo.rooms[roomId]["event"][blockId] = event - end - end - end - - stagePool = {["global"] = {}} - for roomId, roomName in pairs(mapData["rooms"]) do - stagePool[roomId] = {} - advInfo.rooms[roomId] = {event = {}, open = {}} -- 事件, open - local roomData - if roomName == "path" then - advInfo.rooms[roomId].isPath = true - roomData = mapData["path"] - else - roomName = roomName:gsub("/", "_") - roomData = csvdb["room_" .. roomName .. "Csv"] - end - for blockId, stageType in pairs(roomData["blocks"]) do - if AdvSpecialStage[stageType] then - eventType = AdvEventType[AdvSpecialStage[stageType]] - randomEvent(roomId, blockId, eventType) - else - stagePool["global"][stageType] = stagePool["global"][stageType] or {} - stagePool[roomId][stageType] = stagePool[roomId][stageType] or {} - table.insert(stagePool["global"][stageType], {room = roomId, block = blockId}) - stagePool[roomId][stageType][blockId] = 1 - end - end - end - -- 全地图事件 优先级高 - for stageType, events in pairs(mapData["events"]) do - for _, event in ipairs(events) do - local lastCount = #stagePool["global"][stageType] - if lastCount <= 0 then break end - if math.randomFloat(0, 1) <= (event["rate"] or 1) then - local count = math.randomInt(math.min(lastCount, event["minc"]), math.min(lastCount, event["maxc"])) - for i = 1, count do - local idx = math.randomInt(1, lastCount) - local cur = stagePool["global"][stageType][idx] - randomEvent(cur["room"], cur["block"], event["event"]) - table.remove(stagePool["global"][stageType], idx) - lastCount = lastCount - 1 - stagePool[cur["room"]][stageType][cur["block"]] = nil - end - end - end - end - -- 随机单个房间的事件 - for roomId, roomName in pairs(mapData["rooms"]) do - local roomData - if roomName == "path" then - roomData = mapData["path"] - else - roomName = roomName:gsub("/", "_") - roomData = csvdb["room_" .. roomName .. "Csv"] - end - for stageType, events in pairs(roomData["events"]) do - local bpool = {} - if stagePool[roomId][stageType] then - for block, _ in pairs(stagePool[roomId][stageType]) do - table.insert(bpool, block) - end - end - for _, event in ipairs(events) do - if #bpool <= 0 then break end - if math.randomFloat(0, 1) <= (event["rate"] or 1) then - local count = math.randomInt(math.min(#bpool, event["minc"]), math.min(#bpool, event["maxc"])) - for i = 1, count do - local idx = math.randomInt(1, #bpool) - randomEvent(roomId, bpool[idx], event["event"]) - table.remove(bpool, idx) - end - end - end - end - end - if not haveBoss then - if not next(monsterEvents) then - print("这个地图没有钥匙!!! mapId : " .. mapId) - else - local event = monsterEvents[math.randomInt(1, #monsterEvents)] - event.item = {1, 1} --掉落钥匙 - end - end - self:updateProperty({field = "advInfo", value = advInfo}) - end - -end - -return RoleAdv \ No newline at end of file diff --git a/src/models/RolePlugin.lua b/src/models/RolePlugin.lua index fc7fc7e..d5592a3 100644 --- a/src/models/RolePlugin.lua +++ b/src/models/RolePlugin.lua @@ -65,7 +65,7 @@ function RolePlugin.bind(Role) -- 发奖功能入口 award string id=count or {[id] = count} function Role:award(gift, params) local tgift = {} - if type(award) == "string" then + if type(gift) == "string" then for _, one in pairs(gift:toTableArray(true)) do tgift[one[1]] = (tgift[one[1]] or 0) + one[2] end @@ -201,6 +201,13 @@ function RolePlugin.bind(Role) self.dailyData:load() end end + + function Role:getAdvData() + if not self.advData then + self.advData = require("adv.Adv").new(self) + end + return self.advData + end end return RolePlugin \ No newline at end of file diff --git a/src/shared/ModelBase.lua b/src/shared/ModelBase.lua index aaaeacc..80ea8a0 100644 --- a/src/shared/ModelBase.lua +++ b/src/shared/ModelBase.lua @@ -35,15 +35,16 @@ function ModelBase:ctor(properties) self:setProperties(properties, true) --缺少的域将设置默认值 end --- startCache 和 endCache 在恰当的时候配对使用 +-- startCache 和 endCache 在恰当的时候*配对使用* 嵌套使用多次增加引用计数 直到引用计数为0 写入 function ModelBase:startCache( ... ) for _, field in ipairs({ ... }) do if self.class.schema[field] then - self.cacheFields[field] = true + self.cacheFields[field] = (self.cacheFields[field] or 0) + 1 end end end +--减少缓存引用计数 为时写入, 无参数 强制刷新所有缓存 function ModelBase:endCache( ... ) args = { ... } params = {} @@ -66,8 +67,11 @@ function ModelBase:endCache( ... ) else for _, field in ipairs(args) do if self.cacheFields[field] then - self.cacheFields[field] = nil - doOneCache(field) + self.cacheFields[field] = self.cacheFields[field] - 1 + if self.cacheFields[field] <= 0 then + self.cacheFields[field] = nil + doOneCache(field) + end end end end -- libgit2 0.21.2