diff --git a/src/GlobalVar.lua b/src/GlobalVar.lua index 9612328..dc2f9d4 100644 --- a/src/GlobalVar.lua +++ b/src/GlobalVar.lua @@ -16,6 +16,12 @@ TIME_ZONE = math.floor(os.difftime(START_RESET_TIME_BASE, os.time(os.date("!*t", START_RESET_TIME = START_RESET_TIME_BASE - TIME_ZONE * 3600 +function weekday(now) + local day = math.ceil((now - START_RESET_TIME) % 604800 / 86400) + if day == 0 then day = 1 end + return day +end + STRUCT_VERSION = 3 -- 数据结构版本 MAX_ROLE_NUM = 1000000 @@ -155,6 +161,11 @@ TimeReset = { DrawType1 = 17, -- 变异 抽卡加成 DrawType2 = 18, -- 通常 抽卡加成 DrawType3 = 19, -- 魔法 抽卡加成 + WorkBattle1 = 22, -- 夜间玩法 1 + WorkBattle2 = 23, -- 夜间玩法 2 + WorkBattle3 = 24, -- 夜间玩法 3 + WorkBattle4 = 25, -- 夜间玩法 4 + WorkBattle5 = 26, -- 夜间玩法 5 } -- TimeReset 索引数组 diff --git a/src/ProtocolCode.lua b/src/ProtocolCode.lua index 41edaee..746b7ef 100644 --- a/src/ProtocolCode.lua +++ b/src/ProtocolCode.lua @@ -121,6 +121,10 @@ actionCodes = { Hang_bagFieldRpc = 263, Hang_chatLineRpc = 264, Hang_selectTeamRpc = 265, + Hang_startWorkBattleRpc = 266, + Hang_endWorkBattleRpc = 267, + Hang_workBattleInfoRpc = 268, + Hang_getWorkRewardRpc = 269, Diner_updateProperty = 300, Diner_addSellRpc = 301, diff --git a/src/RedisKeys.lua b/src/RedisKeys.lua index 068340a..0b7711a 100644 --- a/src/RedisKeys.lua +++ b/src/RedisKeys.lua @@ -62,7 +62,7 @@ FRIEND_ENERGY = "role:%d:energy" -- set 送给我活动能量的好友 FRIEND_RECOMMEND = "friend:recommend" -- sort set 登录排序 获取推荐好友 CHAT_OFFLINE = "chat:offline:%d" --消息离线缓存 - +WORK_BATTLE_COUNT = "global:workbattle" -- 世界次数统计 -- FRIEND_DINER_LIKE_KEY = "role:%d:diner:like" -- list -- UNION_SET = "global:union" diff --git a/src/actions/HangAction.lua b/src/actions/HangAction.lua index 5700d7a..b0dc185 100644 --- a/src/actions/HangAction.lua +++ b/src/actions/HangAction.lua @@ -750,6 +750,260 @@ function _M.endBonusBattleRpc(agent, data) return true end + + +local function workWinReward(role, bonusData, rewardType, count, sweep) + count = count or 1 + local reward, change = {} + if rewardType == 2 or rewardType == 4 then + for k, v in pairs(bonusData.perfect_reward:toNumMap()) do + reward[k] = (reward[k] or 0) + v + end + end + + if rewardType == 3 then + reward = bonusData.reward:toNumMap() + for itemId, c in pairs(reward) do + reward[itemId] = c * count + end + for i = 1, count do + local chance = bonusData.chance:randWeight(true) + if chance[1] ~= 0 then + reward[chance[1]] = (reward[chance[1]] or 0) + chance[2] + end + end + end + if sweep then + -- local bnousReward = role:getBnousSweep() + -- for key, value in pairs(bnousReward) do + -- reward[key] = (reward[key] or 0) + value * count + -- end + end + + reward, change = role:award(reward, {log = {desc = "workBattle", int1 = bonusData.id}}) + -- role:checkTaskEnter("BonusPass", {id = bonusData.id, count = count}) + return reward, change +end + +function _M.workBattleInfoRpc(agent, data) + local role = agent.role + local msg = MsgPack.unpack(data) + local workMainCsv = csvdb["work_mainCsv"][msg.type] + if not workMainCsv then return 1 end + if not role:isTimeResetOpen(TimeReset["WorkBattle" .. msg.type]) then return 2 end + SendPacket(actionCodes.Hang_workBattleInfoRpc, MsgPack.pack({count = tonum(redisproxy:hget(WORK_BATTLE_COUNT, role:getTimeResetRound(TimeReset["WorkBattle" .. msg.type]) * 10 + msg.type))})) + return true +end + + +function _M.getWorkRewardRpc(agent, data) + local role = agent.role + local msg = MsgPack.unpack(data) + local workMainCsv = csvdb["work_mainCsv"][msg.type] + if not workMainCsv then return 1 end + if not role:isTimeResetOpen(TimeReset["WorkBattle" .. msg.type]) then return 2 end + local count = tonum(redisproxy:hget(WORK_BATTLE_COUNT, role:getTimeResetRound(TimeReset["WorkBattle" .. msg.type]) * 10 + msg.type)) + if count < workMainCsv.target_num then return 3 end + local workBattle = role:getProperty("workBattle") + if workBattle[msg.type] ~= 1 then + return 4 + end + workBattle[msg.type] = -1 + role:updateProperty({field = "workBattle", value = workBattle}) + local reward, change = role:award(workMainCsv.phase_award, {log = {desc = "workReward"}}) + SendPacket(actionCodes.Hang_getWorkRewardRpc, MsgPack.pack({reward = reward, change = change})) + return true +end + +function _M.startWorkBattleRpc(agent, data) + local role = agent.role + local msg = MsgPack.unpack(data) + local id = msg.id + local count = msg.count or 1 + + if not role:isFuncUnlock(FuncUnlock.BonusBattle) then return 1 end + + local bonusData = csvdb["work_battleCsv"][id] + + if not bonusData then return 3 end + + if not role:isTimeResetOpen(TimeReset["WorkBattle" .. bonusData.type]) then return 2 end + + local ticketId = csvdb["work_mainCsv"][bonusData.type].ticket + local workStar = role:getProperty("workStar") + + if bonusData.unlock ~= 0 and (not workStar[bonusData.unlock] or workStar[bonusData.unlock] == 0) then return 4 end + local workBattle = role:getProperty("workBattle") + workBattle[bonusData.type] = workBattle[bonusData.type] or 0 + local needCount = count - (workBattle[bonusData.type] == 0 and 1 or 0) + if needCount ~= 0 and not role:checkItemEnough({[ticketId] = needCount}) then return 11 end + + if workStar[id] and workStar[id] >= (1 << #bonusData.sweep_condition:toTableArray(true)) - 1 then + if workBattle[bonusData.type] == 0 then + workBattle[bonusData.type] = 1 + role:updateProperty({field = "workBattle", value = workBattle}) + end + if needCount > 0 then + role:costItems({[ticketId] = needCount}, {log = {desc = "workBattle", int1 = id}}) + end + redisproxy:hincrby(WORK_BATTLE_COUNT, role:getTimeResetRound(TimeReset["WorkBattle" .. bonusData.type]) * 10 + bonusData.type, count) + local reward, change = workWinReward(role, bonusData, 3, count, true) + SendPacket(actionCodes.Hang_startWorkBattleRpc, MsgPack.pack({reward = reward, change = change})) + else + local bTeam = role:getTeamFormatByType(TeamSystemType.BonusBattle) + if not next(bTeam) then return 5 end + role.__bonusBattleCache = { + key = tostring(math.random()), + id = id, + } + SendPacket(actionCodes.Hang_startWorkBattleRpc, MsgPack.pack({key = role.__bonusBattleCache.key})) + end + + return true +end + +function _M.endWorkBattleRpc(agent, data) + local role = agent.role + local msg = MsgPack.unpack(data) + local id = msg.id + local key = msg.key + local starNum = msg.starNum + if not role.__bonusBattleCache then return 1 end + + + if role.__bonusBattleCache.id ~= id or role.__bonusBattleCache.key ~= key then + SendPacket(actionCodes.Hang_endWorkBattleRpc, MsgPack.pack({errorCode = 1})) + return true + end + role.__bonusBattleCache = nil + + -- 防作弊 + if not role:checkBattleCheat("work", { + id = id, + isWin = starNum and starNum > 0, + info = msg.info + }) then + SendPacket(actionCodes.Hang_endWorkBattleRpc, MsgPack.pack({errorCode = 1})) + return true + end + + local bonusData = csvdb["work_battleCsv"][id] + local ticketId = csvdb["work_mainCsv"][bonusData.type].ticket + local reward, change = {} + + local workStar = role:getProperty("workStar") + local oldStar = workStar[id] or 0 + local curStar = 0 + if starNum and starNum > 0 then + -- 胜利扣除次数 + + local bTeam = role:getTeamFormatByType(TeamSystemType.BonusBattle) + local herosInfo = role:getTeamHerosInfo(bTeam).heros + + local check = {} + -- 1 通关 + check[1] = function(_) + return true + end + -- 2 阵亡人数 <= N + check[2] = function(_, cond) + return msg.info.dead and msg.info.dead <= cond + end + -- 3 全员存活 + check[3] = function(_) + return msg.info.dead and msg.info.dead == 0 + end + -- 4 指定种族 >= N + check[4] = function(_, cond) + local count = 0 + for _, one in pairs(herosInfo) do + local heroData = csvdb["unitCsv"][one.type] + if heroData.camp == cond then + count = count + 1 + end + end + return count >= cond + end + -- 5 指定职业 >= N + check[5] = function(_, cond) + local count = 0 + for _, one in pairs(herosInfo) do + local heroData = csvdb["unitCsv"][one.type] + if heroData.job == cond then + count = count + 1 + end + end + return count >= cond + end + -- 6 含有指定角色 + check[6] = function(_, cond) + for _, one in pairs(herosInfo) do + if one.type == cond then + return true + end + end + return false + end + -- 7 通关耗时 <= X 秒 msg.info.atime + check[7] = function(_, cond) + return msg.info.atime and msg.info.atime <= cond + end + curStar = 0 + local sweepConds = bonusData.sweep_condition:toTableArray(true) + for i, cond in ipairs(sweepConds) do + if check[cond[1]] and check[cond[1]](table.unpack(cond)) then + curStar = curStar + (1 << (i - 1)) + end + end + local status + local rewardType = 0 + if curStar >= (1 << #sweepConds) - 1 then -- 满星 + rewardType = 2 + if oldStar == 0 then --通关 + rewardType = 4 + end + elseif oldStar == 0 then --通关 + rewardType = 1 + end + + if rewardType ~= 0 then + local workBattle = role:getProperty("workBattle") + workBattle[bonusData.type] = workBattle[bonusData.type] or 0 + local needCount = 1 - (workBattle[bonusData.type] == 0 and 1 or 0) + if workBattle[1] == 0 then + workBattle[1] = 1 + role:updateProperty({field = "workBattle", value = workBattle}) + end + if needCount > 0 then + role:costItems({[ticketId] = needCount}, {log = {desc = "workBattle", int1 = id}}) + end + redisproxy:hincrby(WORK_BATTLE_COUNT, role:getTimeResetRound(TimeReset["WorkBattle" .. bonusData.type]) * 10 + bonusData.type, 1) + reward, change = workWinReward(role, bonusData, rewardType) + end + else + curStar = oldStar + end + if curStar ~= oldStar then + workStar[id] = curStar + role:updateProperty({field = "workStar", value = workStar}) + end + + role:checkBattle("work", { + id = id, + isWin = starNum and starNum > 0, + info = msg.info, + reward = reward, + }) + role:mylog("hang_action", {desc = "workBattle", short1 = msg.starNum > 0 and 1 or 0, int1 = id}) + + SendPacket(actionCodes.Hang_endWorkBattleRpc, MsgPack.pack({ + starNum = starNum, + reward = reward, + change = change + })) + return true +end + function _M.hangGiftRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) diff --git a/src/actions/RoleAction.lua b/src/actions/RoleAction.lua index 00b1d52..62c85db 100644 --- a/src/actions/RoleAction.lua +++ b/src/actions/RoleAction.lua @@ -161,6 +161,9 @@ function _M.loginRpc( agent, data ) role:getAdvData(true) -- 清掉不合格的数据 role:advEndlessSeasonCheck(true) -- 冒险赛季更新检查 role:checkSeaportTrade() -- 检查海港贸易季活动 + if not next(role:getProperty("workBattle")) then + role:setProperty("workBattle", {round = math.floor((now - START_RESET_TIME) / 604800)}) + end -- 跨天登陆事件 local resetMode = role:updateTimeReset(now) @@ -936,7 +939,15 @@ function _M.taskActiveRpc(agent, data) return end - local reward, change = role:award(taskData.reward, {log = {desc = "taskActive", int1 = taskType, int2 = taskId}}) + local needReward = taskData.reward:toNumMap() + if taskData.reward_2 ~= 0 then + local day = weekday(skynet.timex()) + local workMainCsv = csvdb["work_mainCsv"][day] + if workMainCsv then + needReward[workMainCsv.ticket] = taskData.reward_2 + end + end + local reward, change = role:award(needReward, {log = {desc = "taskActive", int1 = taskType, int2 = taskId}}) role:changeUpdates({ { type = roleField[taskType], field = {"at", taskId}, value = -1 } }) diff --git a/src/models/Role.lua b/src/models/Role.lua index f3f2508..ddc1d99 100644 --- a/src/models/Role.lua +++ b/src/models/Role.lua @@ -119,6 +119,8 @@ Role.schema = { towerTeams = {"table", {}}, -- 四个电波塔的队伍 bonusStar = {"table", {}}, -- 奖励关卡 通关星星 {[id] = 1} 三个二进制位 表示三个星 从低到高 (1 << 0) (1 << 1) (1 << 2) 满星 (1 << 3) - 1 + workStar = {"table", {}}, -- 夜间玩法 通关星星 {[id] = 1} 三个二进制位 表示三个星 从低到高 (1 << 0) (1 << 1) (1 << 2) 满星 (1 << 3) - 1 + workBattle = {"table", {}}, -- 夜间玩法记录 {[1] = 1, [2] = 1, [3] = 1, [4] = 1, round = 10} -- 第N天打了多少次 round 轮次 --引导相关 newerGuide = {"string","1=1"}, -- 新手引导 master=slave @@ -378,6 +380,8 @@ function Role:data() towerTeams = self:getProperty("towerTeams"), bonusStar = self:getProperty("bonusStar"), + workStar = self:getProperty("workStar"), + workBattle = self:getProperty("workBattle"), newerGuide = self:getProperty("newerGuide"), funcGuide = self:getProperty("funcGuide"), diff --git a/src/models/RoleBattle.lua b/src/models/RoleBattle.lua index 7374ed5..84ddcd3 100644 --- a/src/models/RoleBattle.lua +++ b/src/models/RoleBattle.lua @@ -17,6 +17,7 @@ local BattleType = { pvpc = 500, pvph = 501, act_battle = 502, + work = 301, } RoleBattle.bind = function (Role) @@ -127,6 +128,18 @@ function Role:checkBattleCheat(battleType, params) -- local carbonData = csvdb["bonus_battleCsv"][params.id] -- enemyServer = packBattleEnemyCommon(carbonData) end + cheat["work"] = function() + local team = self:getTeamBattleInfo(self:getTeamFormatByType(TeamSystemType.BonusBattle)) + for slot, hero in pairs(team.heros) do + local temp = {} + for arr, _ in pairs(checkCheatAttrs) do + temp[arr] = hero[arr] + end + selfTeamServer[hero.type] = temp + end + -- local carbonData = csvdb["bonus_battleCsv"][params.id] + -- enemyServer = packBattleEnemyCommon(carbonData) + end cheat["pvpc"] = function() if not params.format then return end local team = self:getTeamBattleInfo(params.format) diff --git a/src/models/RoleLog.lua b/src/models/RoleLog.lua index 2e8a5b0..3abbfb6 100644 --- a/src/models/RoleLog.lua +++ b/src/models/RoleLog.lua @@ -72,6 +72,8 @@ local ItemReason = { towerBattle = 310, -- 电波塔战斗 advOver = 311, -- 冒险结算 advUnlock = 312, -- 拾荒解锁 + workBattle = 313, -- workBattle夜间打工 + workReward = 314, -- workBattle夜间打工 阶段奖励 dinerFinishTask = 401, -- 餐厅完成任务 storybookReward = 402, -- 剧情奖励 diff --git a/src/models/RoleTimeReset.lua b/src/models/RoleTimeReset.lua index 7b9119e..05c82ff 100644 --- a/src/models/RoleTimeReset.lua +++ b/src/models/RoleTimeReset.lua @@ -33,6 +33,38 @@ ResetFunc["CrossDay"] = function(self, notify, response, now) self:checkReturner() end + -- 检查 夜间打工 + local workBattle = role:getProperty("workBattle") + local need = {} + for i = 1, 5 do + if workBattle[i] == 1 then + need[#need + 1] = workBattle.round * 10 + i + end + end + local change = false + if next(need) then + local ret = redisproxy:hmget(WORK_BATTLE_COUNT, table.unpack(need)) + for idx, v in ipairs(need) do + local ctype = v % 10 + local ccount = tonum(ret[idx]) + local workMainCsv = csvdb["work_mainCsv"][ctype] + if ccount >= workMainCsv.target_num then + self:sendMail(workMainCsv.email, nil, workMainCsv.phase_award) + end + workBattle[ctype] = -1 + end + change = true + end + local newRound = math.floor((now - START_RESET_TIME) / 604800) + if newRound ~= workBattle.round then + workBattle = {round = newRound} + change = true + end + if change then + self:setProperty("workBattle", workBattle) + response.workBattle = workBattle + end + response.dTask = {} response.advSup = self:getProperty("advSup") self:log("onLogin") -- libgit2 0.21.2