Commit 46fac6f1866667f3ba878d4cc6c1f9df991b1d01

Authored by zhouahaihai
1 parent 23d89d13

酱料

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
... ... @@ -23,6 +23,10 @@ actionCodes = {
23 23 Role_pipelining = 109,
24 24  
25 25 Adv_startAdvRpc = 151,
  26 + Adv_roleFormatRpc = 152,
  27 + Adv_clickBlockRpc = 153,
  28 + Adv_useItemRpc = 154,
  29 + Adv_useSkillRpc = 155,
26 30  
27 31 Hero_loadInfos = 201,
28 32 Hero_updateProperty = 202,
... ...
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  
... ...
src/adv/Adv.lua 0 → 100644
... ... @@ -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
... ...
src/adv/AdvBattle.lua 0 → 100644
... ... @@ -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
... ...
src/adv/AdvBuff.lua 0 → 100644
... ... @@ -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
... ...
src/adv/AdvPassive.lua 0 → 100644
... ... @@ -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
... ...
src/adv/AdvPlayer.lua 0 → 100644
... ... @@ -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(&quot;Role&quot;, require(&quot;shared.ModelBase&quot;))
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
... ...