Commit 23d89d1311fb747bc78ebbad220bc273a64b3262

Authored by zhouahaihai
1 parent 8dce6908

冒险 结构

src/GlobalVar.lua
... ... @@ -55,4 +55,24 @@ ItemId = {
55 55 Diamond = 3, -- 钻石
56 56 BreakCost = 4, -- 突破材料
57 57 HeroFC = {700, 701, 702, 703}, -- 通用角色碎片
  58 +}
  59 +
  60 +--客户端不需要知道这个
  61 +AdvSpecialStage = {
  62 + [1]= "In",
  63 + [2] = "Out",
  64 + [3] = "BOSS"
  65 +}
  66 +--客户端需要知道这个
  67 +AdvEventType = {
  68 + -- 特殊事件(地块决定)
  69 + In = -1, --入口
  70 + Out = -2, --出口
  71 + BOSS = -3, -- boss
  72 + -- 普通事件(随机)
  73 + Choose = 1, --选择点
  74 + Drop = 2, --物品掉落点
  75 + Monster = 3, -- 普通怪
  76 + Trader = 4, --商人
  77 + Build = 5, --建筑物
58 78 }
59 79 \ No newline at end of file
... ...
src/ProtocolCode.lua
... ... @@ -20,6 +20,9 @@ actionCodes = {
20 20 Role_updateProperties = 106,
21 21 Role_updateItems = 107,
22 22 Role_changeUpdate = 108,
  23 + Role_pipelining = 109,
  24 +
  25 + Adv_startAdvRpc = 151,
23 26  
24 27 Hero_loadInfos = 201,
25 28 Hero_updateProperty = 202,
... ... @@ -35,6 +38,7 @@ actionCodes = {
35 38 Hero_loveItemRpc = 212,
36 39 Hero_loveTaskRpc = 213,
37 40 Hero_changeSkinRpc = 214,
  41 +
38 42 }
39 43  
40 44 rpcResponseBegin = 10000
... ...
src/actions/AdvAction.lua 0 → 100644
... ... @@ -0,0 +1,35 @@
  1 +local ipairs = ipairs
  2 +local table = table
  3 +local math = math
  4 +local next = next
  5 +local string = string
  6 +local redisproxy = redisproxy
  7 +local MsgPack = MsgPack
  8 +local getRandomName = getRandomName
  9 +local mcast_util = mcast_util
  10 +local string_format = string.format
  11 +local tonumber = tonumber
  12 +local require = require
  13 +local table_insert = table.insert
  14 +local tconcat = table.concat
  15 +local table_unpack = table.unpack
  16 +
  17 +local _M = {}
  18 +
  19 +function _M.startAdvRpc( agent, data )
  20 + local role = agent.role
  21 + local msg = MsgPack.unpack(data)
  22 +
  23 + local advInfo = role:getProperty("advInfo")
  24 +
  25 + role:randomAdvMap(10101, 1) --测试
  26 +
  27 + SendPacket(actionCodes.Adv_startAdvRpc, '')
  28 + return true
  29 +end
  30 +
  31 +
  32 +
  33 +
  34 +
  35 +return _M
0 36 \ No newline at end of file
... ...
src/agent.lua
... ... @@ -46,17 +46,41 @@ function cancel_agent_timer()
46 46 end
47 47 ---- 定时器相关 }}}
48 48  
  49 +local _pipelinings = {} --可同时多个序列 栈的形式保证嵌套不出错
49 50 function SendPacket(actionCode, bin, client_fd)
50   - if #bin > 0 then bin = xxtea.encrypt(bin, XXTEA_KEY) end
51   -
  51 + client_fd = client_fd or agentInfo.client_fd
  52 +
52 53 local handlerName = actionHandlers[actionCode]
53 54 if string.sub(handlerName, -3, -1) == "Rpc" then
54 55 actionCode = actionCode + rpcResponseBegin
55 56 end
  57 + -- 查看是否是在 流水线操作中
  58 + if #_pipelinings > 0 then
  59 + local _curPipelining = _pipelinings[#_pipelinings]
  60 + _curPipelining[client_fd] = _curPipelining[client_fd] or {} --区分不同客户端
  61 + table.insert(_curPipelining[client_fd], {actionCode, bin})
  62 + else
  63 + if #bin > 0 then bin = xxtea.encrypt(bin, XXTEA_KEY) end
  64 + local head = string.pack("H", actionCode)
  65 + return socket.write(client_fd, netpack.pack(head .. bin))
  66 + end
  67 +end
56 68  
57   - local client_fd = client_fd or agentInfo.client_fd
58   - local head = string.pack("H", actionCode)
59   - return socket.write(client_fd, netpack.pack(head .. bin))
  69 +function SendPipelining(callback)
  70 + if type(callback) ~= "function" then return end
  71 + --push 当前队列
  72 + table.insert(_pipelinings, {})
  73 + -- 执行代码块 输出错误信息
  74 + local ok, err = pcall(callback)
  75 + --弹出当前队列
  76 + local curPipelining = table.remove(_pipelinings)
  77 + -- 查看是否有消息
  78 + if next(curPipelining) then
  79 + for client_fd, msg in pairs(curPipelining) do
  80 + SendPacket(actionCodes.Role_pipelining, MsgPack.pack(msg), client_fd)
  81 + end
  82 + end
  83 + if not ok then error(err) end
60 84 end
61 85  
62 86 function rpcAgent(roleId, funcName, ...)
... ...
src/models/Role.lua
... ... @@ -2,10 +2,12 @@ local Role = class("Role", require("shared.ModelBase"))
2 2  
3 3 local RolePlugin = import(".RolePlugin")
4 4 local RoleTask = import(".RoleTask")
  5 +local RoleAdv = import(".RoleAdv")
5 6 local RoleActivity = import(".RoleActivity")
6 7 local RoleChangeStruct = import(".RoleChangeStruct")
7 8 RolePlugin.bind(Role)
8 9 RoleTask.bind(Role)
  10 +RoleAdv.bind(Role)
9 11 RoleActivity.bind(Role)
10 12 RoleChangeStruct.bind(Role)
11 13  
... ... @@ -35,8 +37,9 @@ Role.schema = {
35 37 items = {"string", ""},
36 38 loveStatus = {"string", ""}, --统计角色的最高 好感度等级 类型相关 -- type=loveL type=loveL
37 39  
38   - advPass = {"string", ""}, -- 冒险 通关记录
39   - advInfo = {"table", {}}, -- 冒险 相关信息
  40 + --冒险相关
  41 + advPass = {"string", ""}, -- 通关记录
  42 + advInfo = {"table", {}}, -- 其他信息
40 43  
41 44 }
42 45  
... ... @@ -56,7 +59,7 @@ end
56 59  
57 60 function Role:updateProperty(params)
58 61 params = params or {}
59   - if not self.fields[params.field] then return end
  62 + if not self.schema[params.field] then return end
60 63 local oldValue = self:getProperty(params.field)
61 64 local ret = {key = params.field, oldValue = oldValue}
62 65 if params.value then
... ... @@ -86,13 +89,36 @@ function Role:notifyUpdateProperties(params)
86 89 SendPacket(actionCodes.Role_updateProperties, MsgPack.pack(params))
87 90 end
88 91  
89   --- 某些字段更新改变量 改变量的定义由字段自身决定 {{type = ""}, }
  92 +-- 某些字段 更新改变量 改变量的定义由字段自身决定 {{type = ""}, }
90 93 function Role:changeUpdates(params, notNotify)
91 94 local changeUpdateFunc = {
92 95 ["loveStatus"] = function(info)
93 96 self:setProperty("loveStatus", self:getProperty("loveStatus"):setv(info["field"], info["value"]))
94 97 return {type = "loveStatus", field = info["field"], value = info["value"]}
95 98 end,
  99 + --table 类型通用更新
  100 + ["tableCommon"] = function(fieldType, info)
  101 + if self.class.schema[fieldType][1] ~= "table" then
  102 + error("[ERROR:] need handler for changeUpdate, field : " .. fieldType)
  103 + return
  104 + end
  105 + --支持多深度单字段
  106 + local curValue = self:getProperty(fieldType)
  107 + if type(info["field"]) == "table" then
  108 + for _idx, _field in ipairs(info["field"]) do
  109 + if _idx < #info["field"] then
  110 + curValue[_field] = curValue[_field] or {}
  111 + curValue = curValue[_field]
  112 + else
  113 + curValue[_field] = info["value"]
  114 + end
  115 + end
  116 + else
  117 + curValue[info["field"]] = info["value"]
  118 + end
  119 + self:setProperty(fieldType)
  120 + return {type = fieldType, field = info["field"], value = info["value"]}
  121 + end,
96 122 }
97 123  
98 124 local updates = {}
... ... @@ -100,7 +126,7 @@ function Role:changeUpdates(params, notNotify)
100 126 if changeUpdateFunc[one["type"]] then
101 127 table.insert(updates, changeUpdateFunc[one["type"]](one))
102 128 else
103   - print("need handler for changeUpdate type : " .. params["type"])
  129 + table.insert(updates, changeUpdateFunc["tableCommon"](one["type"], one))
104 130 end
105 131 end
106 132 if not notNotify and next(updates) then
... ... @@ -117,6 +143,8 @@ function Role:data()
117 143 reDiamond = self:getProperty("reDiamond"),
118 144 items = self:getProperty("items"):toNumMap(),
119 145 loveStatus = self:getProperty("loveStatus"):toNumMap(),
  146 + advPass = self:getProperty("advPass"),
  147 + advInfo = self:getProperty("advInfo"),
120 148 }
121 149 end
122 150  
... ...
src/models/RoleAdv.lua 0 → 100644
... ... @@ -0,0 +1,250 @@
  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
0 251 \ No newline at end of file
... ...
src/utils/TableUtil.lua
... ... @@ -5,4 +5,10 @@ function table.arrayToMap(tab)
5 5 result[tab[i]] = tab[i + 1]
6 6 end
7 7 return result
  8 +end
  9 +
  10 +function table.clear(tab)
  11 + for k, _ in pairs(tab) do
  12 + tab[k] = nil
  13 + end
8 14 end
9 15 \ No newline at end of file
... ...