From 0769908cc283656ae4ff4d46085558f1b1c32f0b Mon Sep 17 00:00:00 2001 From: zqj <582132116@qq.com> Date: Sat, 9 Oct 2021 19:15:13 +0800 Subject: [PATCH] feat: 常规世界boss --- src/ProtocolCode.lua | 6 ++++++ src/RedisKeys.lua | 1 + src/actions/ActivityAction.lua | 454 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/models/Activity.lua | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/models/RoleLog.lua | 5 +++++ 5 files changed, 524 insertions(+), 0 deletions(-) diff --git a/src/ProtocolCode.lua b/src/ProtocolCode.lua index 3937a2e..92875fc 100644 --- a/src/ProtocolCode.lua +++ b/src/ProtocolCode.lua @@ -270,6 +270,12 @@ actionCodes = { Activity_actNewUserTaskRpc = 674, Activity_buyBattleTicketRpc = 675, Activity_resetGachakonRpc = 676, --狩猎祭,重制扭蛋机 + Activity_startRegularWorldBossBattleRpc = 677, + Activity_endRegularWorldBossBattleRpc = 678, + Activity_regularWorldBossRewardRpc = 679, + Activity_buyWorldBossBattleTicketRpc = 680, + Activity_regularWorldBossMilestoneRpc = 681, + Radio_startQuestRpc = 700, Radio_finishQuestRpc = 701, diff --git a/src/RedisKeys.lua b/src/RedisKeys.lua index 9a57702..f0d4aca 100644 --- a/src/RedisKeys.lua +++ b/src/RedisKeys.lua @@ -22,6 +22,7 @@ RANK_COMMON = "rank:common:" RANK_TYPE = { ActBattleBoss = "act_battle_boss", ActCrisis = "crisis", + RegularWorldBoos = "regular_world_boss" } -- rank diff --git a/src/actions/ActivityAction.lua b/src/actions/ActivityAction.lua index 0664f6e..dea003f 100644 --- a/src/actions/ActivityAction.lua +++ b/src/actions/ActivityAction.lua @@ -918,6 +918,7 @@ function _M.battleRankRpc(agent, data) local actTypeToRank = { [role.activity.ActivityType.ChallengeLevel] = RANK_TYPE.ActBattleBoss, [role.activity.ActivityType.Crisis] = RANK_TYPE.ActCrisis, + [role.activity.ActivityType.RegularWorldBoos] = RANK_TYPE.RegularWorldBoos, } if not actTypeToRank[cfg.showType] then return end local rankInfo = role:getRankInfoCommon(actTypeToRank[cfg.showType]) @@ -1541,4 +1542,457 @@ function _M.buyBattleTicketRpc(agent, data) return true end + +-- 常规世界boss +function _M.startRegularWorldBossBattleRpc(agent, data) + local role = agent.role + local msg = MsgPack.unpack(data) + local actid = msg.actid + local id = msg.id + local count = msg.count + + local actCfg = csvdb["activity_battleCsv"][actid] + if not actCfg then return 2 end + + local battleCfg = actCfg[id] + if not battleCfg then return 3 end + + local actData = role.activity:getActData("RegularWorldBoos") or {} + + local preArr = battleCfg.prepose:toArray(true, "=") + for _, v in ipairs(preArr) do + local battleInfo = actData[v] + if not battleInfo then + return 4 + end + local star = battleInfo["star"] or 0 + if star <= 0 then + return 4 + end + end + -- check cost + local changeFlag = false + local ticket = actData["ticket"] + local num = 0 -- cost num + if battleCfg.type ~= "" then + role.activity:getRegularWorldBossTicket(actid) + num = battleCfg.type:toArray(true, "=")[3] + if count and count > 0 then + if battleCfg.rank ~= 0 then + local bi = actData[id] + if not bi then return 8 end + local star = bi["star"] or 0 + local maxP = bi["maxP"] or 0 + -- 世界boss + if battleCfg.worldBoss_award ~= 0 then + if maxP < 1 then + return 9 + end + else + if star < 1 then + return 9 + end + end + end + num = num * count + else + num = 0 + end + if ticket < num then + return 6 + end + changeFlag = true + end + -- 解锁活动剧情 + role:checkStoryStatus(false, 5, id) + + if not count then + role.__actBattleCache = { + key = tostring(math.random()), + actid = actid, + id = id, + format = msg.format, + } + SendPacket(actionCodes.Activity_startRegularWorldBossBattleRpc, MsgPack.pack({key = role.__actBattleCache.key})) + else + if count <= 0 then + return + end + + local bi = actData[id] + local star = bi["star"] or 0 + local award = battleCfg.item_clear:toNumMap() + + if battleCfg.rank ~= 0 then + if getStarCount(battleCfg, star) == 3 then + local aw = battleCfg.perfect_reward:toNumMap() + for k, v in pairs(aw) do + award[k] = (award[k] or 0) + v + end + end + end + for k, v in pairs(award) do + award[k] = v * count + end + local reward, change = role:award(award, {log = {desc = "actBattle", int1 = actid, int2 = count or 0}}) + + changeFlag = true + actData["ticket"] = ticket - num + + if battleCfg.rank ~= 0 then + if battleCfg.worldBoss_award ~= 0 and (bi["maxP"] or 0) > 0 then + bi["bossP"] = (bi["bossP"] or 0) + bi["maxP"] * count + end + + bi["sum"] = bi["sum"] + bi["top"] * count + actData[id] = bi + + local rankVal = 0 + if battleCfg.rank == 1 then + rankVal = bi["sum"] + elseif battleCfg.rank == 2 then + rankVal = bi["top"] + end + role:updateRankCommon(RANK_TYPE.RegularWorldBoos, rankVal) + end + role.activity:updateActData("RegularWorldBoos", actData) + + SendPacket(actionCodes.Activity_startRegularWorldBossBattleRpc, MsgPack.pack(role:packReward(reward, change))) + + return true + end + + return true +end + +function _M.endRegularWorldBossBattleRpc(agent, data) + local role = agent.role + local msg = MsgPack.unpack(data) + local actid = msg.actid + local id = msg.id + local key = msg.key + local isWin = msg.isWin + local heros = msg.heros + local support = msg.support + if not role.activity:isOpenById(actid, "RegularWorldBoos") then + SendPacket(actionCodes.Activity_endRegularWorldBossBattleRpc, MsgPack.pack({})) + return true + end + + if not role.__actBattleCache then return 2 end + + if role.__actBattleCache.id ~= id or role.__actBattleCache.key ~= key and role.__actBattleCache.actid ~= actid then + SendPacket(actionCodes.Activity_endRegularWorldBossBattleRpc, MsgPack.pack({errorCode = 1})) + end + + -- 防作弊 + if not role:checkBattleCheat("act_battle", { + id = id, + isWin = isWin, + info = msg.info, + format = role.__actBattleCache.format + }) then + SendPacket(actionCodes.Activity_endRegularWorldBossBattleRpc, MsgPack.pack({errorCode = 1})) + return true + end + role.__actBattleCache = nil + + local actCfg = csvdb["activity_battleCsv"][actid] + if not actCfg then return 3 end + + local battleCfg = actCfg[id] + if not battleCfg then return 4 end + + local actData = role.activity:getActData("RegularWorldBoos") or {} + + -- 总输出 + local dmg = 0 + for k, v in pairs(msg.info.damage) do + if k % 100 == 2 then + dmg = dmg + v + end + end + + local reward, change = {}, nil + + local battleInfo = actData[id] or {} + local curStar = 0 + if isWin then + local herosInfo = msg.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 + -- 8 总输出值 msg.info.atime + check[8] = function(_, cond) + return dmg >= cond + end + curStar = 0 + local sweepConds = battleCfg.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 + + role:checkTaskEnter("ActBattlePass", {chapterId = id}) + else + curStar = 0 + if battleCfg.rank ~= 0 then + curStar = 1 + end + end + local oldStarNum = getStarCount(battleCfg, battleInfo["star"] or 0) + local newStarNum = getStarCount(battleCfg, curStar) + if newStarNum > oldStarNum then + battleInfo["star"] = curStar + end + + if battleCfg.rank ~= 0 and isWin then + if battleCfg.type ~= "" then + -- 消耗门票 + role.activity:getRegularWorldBossTicket(actid) + local num = battleCfg.type:toArray(true, "=")[3] + actData["ticket"] = math.max(actData["ticket"] - num, 0) + end + + -- 更新排行榜 最高伤害 + battleInfo["top"] = math.max(battleInfo["top"] or 0, dmg) + battleInfo["sum"] = (battleInfo["sum"] or 0) + dmg + local rankVal = 0 + if battleCfg.rank == 1 then + rankVal = battleInfo["sum"] + elseif battleCfg.rank == 2 then + rankVal = battleInfo["top"] + end + if rankVal > 0 then + role:updateRankCommon(RANK_TYPE.RegularWorldBoos, rankVal) + end + end + + if (oldStarNum == 0 and newStarNum > 0) or battleCfg.rank ~= 0 then + reward = battleCfg.item_clear:toNumMap() + end + if (oldStarNum < 3 and newStarNum == 3) or (battleCfg.rank ~= 0 and newStarNum == 3) then + local aw = battleCfg.perfect_reward:toNumMap() + for k, v in pairs(aw) do + reward[k] = (reward[k] or 0) + v + end + end + + role:checkBattle("act_battle", { + cfg = battleCfg, + star = newStarNum, + isWin = isWin, + info = msg.info, + reward = reward, + heros = heros, + supports = support, + }) + + -- 解锁活动剧情 + if newStarNum >= 3 then + role:checkStoryStatus(false, 5, id) + end + + if battleCfg.worldBoss_award ~= 0 and msg.point then + battleInfo["bossP"] = (battleInfo["bossP"] or 0) + msg.point + battleInfo["maxP"] = math.max(msg.point, (battleInfo["maxP"] or 0)) + end + actData[id] = battleInfo + role.activity:updateActData("RegularWorldBoos", actData) + + reward, change = role:award(reward, {log = {desc = "actBattle", int1 = actid, int2 = newStarNum}}) + + SendPacket(actionCodes.Activity_endRegularWorldBossBattleRpc, MsgPack.pack({ + reward = reward, + change = change + })) + + return true +end + +function _M.regularWorldBossRewardRpc(agent, data) + local role = agent.role + local msg = MsgPack.unpack(data) + local actid = msg.actid + local id = msg.id + local index = msg.index + + if not role.activity:isOpenById(actid, "RegularWorldBoos") then return 1 end + + local actCfg = csvdb["activity_battleCsv"][actid] + if not actCfg then return 2 end + + local battleCfg = actCfg[id] + if not battleCfg then return 3 end + + if battleCfg.worldBoss_award == 0 then return 4 end + + actCfg = csvdb["activity_wordboss_awardCsv"][battleCfg.worldBoss_award] + if not actCfg then return 5 end + local awardCfg = actCfg[index] + if not awardCfg then return 6 end + + local totalAwardCnt = #actCfg + local preList = awardCfg.condition1:toArray(true, "=") + + local actData = role.activity:getActData("RegularWorldBoos") or {} + local battleInfo = actData[id] or {} + local bossPoint = battleInfo["bossP"] or 0 + if bossPoint < 1 then return 7 end + + local bossRecord = battleInfo["bossR"] or "" + local r = string.char(string.getbit(bossRecord, index)) + if r == "1" then + return 9 + end + local ok = false + if #preList == 0 then + ok = true + else + for _, i in ipairs(preList) do + local flag = string.char(string.getbit(bossRecord, i)) + if flag == "1" then + ok = true + break + end + end + end + if not ok then return 8 end + + battleInfo["bossR"] = string.setbit(bossRecord, index) + local allFinish = true + for i = 1, totalAwardCnt do + if string.char(string.getbit(battleInfo["bossR"], i)) == "0" then + allFinish = false + break + end + end + if allFinish then + battleInfo["bossR"] = "" + end + battleInfo["bossP"] = bossPoint - 1 + actData[id] = battleInfo + role.activity:updateActData("RegularWorldBoos", actData) + + local award = awardCfg.reward:toNumMap() + local reward, change = role:award(award, {log = {desc = "regularWorldBossReward", int1 = actid, int2 = index}}) + SendPacket(actionCodes.Activity_regularWorldBossRewardRpc, MsgPack.pack(role:packReward(reward, change))) + return true +end + +function _M.buyWorldBossBattleTicketRpc(agent, data) + local role = agent.role + local msg = MsgPack.unpack(data) + local actid = msg.actid + local id = msg.id + local count = msg.count + if not role.activity:isOpenById(actid, "RegularWorldBoos") then return 1 end + role.activity:getRegularWorldBossTicket(actid) + local actData = role.activity:getActData("RegularWorldBoos") or {} + local battleInfo = actData[id] or {} + --["activity_scrofa_tickets"] = { 10, 20, 30, 40, 50, 100, 150, 200, 200, 200 } + --TODO + local limit = #(globalCsv.activity_scrofa_tickets) + local curCount = actData["buyC"] or 0 + if count <= 0 or curCount + count > limit then + return 2 + end + local cost = globalCsv.activity_scrofa_tickets[curCount + 1] + if not role:checkItemEnough({[ItemId.Jade] = cost}) then return 3 end + role:costItems({[ItemId.Jade] = cost}, {log = {desc = "buyRegularWorldBossTicket", int1 = actid, int2 = count, long1 = curCount}}) + actData["ticket"] = (actData["ticket"] or 0) + 1 + actData["buyC"] = curCount + count + + role.activity:updateActData("RegularWorldBoos", actData) + SendPacket(actionCodes.Activity_buyWorldBossBattleTicketRpc, "") + return true +end + +function _M.regularWorldBossMilestoneRpc(agent, data) + local role = agent.role + local msg = MsgPack.unpack(data) + local actid = msg.actid + local id = msg.id + local index = msg.index + + if not role.activity:isOpenById(actid, "RegularWorldBoos") then return 1 end + + local actCfg = csvdb["activity_mileageCsv"][actid] + if not actCfg then return 3 end + + local mileCfg = actCfg[index] + if not mileCfg then return 4 end + + local actData = role.activity:getActData("RegularWorldBoos") or {} + local battleInfo = actData[id] or {} + local val = 0 + if mileCfg.type == 1 then + val = battleInfo["sum"] or 0 + elseif mileCfg.type == 2 then + val = battleInfo["top"] or 0 + end + + local record = battleInfo["r"] or "" + local flag = string.char(string.getbit(record, index)) + if flag == "1" then return 5 end + if mileCfg.condition > val then return 6 end + + battleInfo["r"] = string.setbit(record, index) + actData[id] = battleInfo + role.activity:updateActData("RegularWorldBoos", actData) + + local award = mileCfg.reward:toNumMap() + local reward, change = role:award(award, {log = {desc = "regularWorldBossMilestone", int1 = actid, int2 = index}}) + SendPacket(actionCodes.Activity_regularWorldBossMilestoneRpc, MsgPack.pack(role:packReward(reward, change))) + + return true +end + return _M diff --git a/src/models/Activity.lua b/src/models/Activity.lua index d95c7b1..ba3d926 100644 --- a/src/models/Activity.lua +++ b/src/models/Activity.lua @@ -40,6 +40,8 @@ Activity.ActivityType = { BattleCommandTask = 38, -- 战令任务活动 NewUserTask = 41, -- 新用户任务 + + RegularWorldBoos = 42, -- 常规世界boos } local function checkActivityType(activityType) @@ -93,6 +95,7 @@ Activity.schema = { act34 = {"table", {}}, -- 战令记录{unlock = 1, freeR = "", payR = "", lvl = 10, sum = 100} act36 = {"table", {}}, -- 每日活跃签到 {0=day, 1=1,2=1,3=1} + act42 = {"table", {}}, -- reset20 = {"number", 1}, -- 重置扭蛋机 } @@ -123,6 +126,7 @@ function Activity:data() act34 = self:getProperty("act34"), act36 = self:getProperty("act36"), + act42 = self:getProperty("act42"), reset20 = self:getProperty("reset20") } @@ -836,6 +840,21 @@ activityFunc[Activity.ActivityType.ChallengeLevel] = { end, } +--RegularWorldBoos +activityFunc[Activity.ActivityType.RegularWorldBoos] = { + ["init"] = function(self, actType, isCrossDay, notify, actId) + self:getRegularWorldBossTicket(actId) + end, + ["login"] = function(self, actType, actId) + self:getRegularWorldBossTicket(actId) + end, + ["crossDay"] = function(self, actType, notify) + local actData = self:getActData(actType) + actData["buyC"] = 0 + self:updateActData(actType, actData, not notify) + end, +} + function Activity:onLoginActivity(actId) local actData = csvdb["activity_ctrlCsv"][actId] if not actData then return end @@ -1056,6 +1075,45 @@ function Activity:getBattleTicket(actId) end end +--常规世界boss计算门票 +function Activity:getRegularWorldBossTicket(actId) + local role = self.owner + local createTs = role:getProperty("ctime") + local actCfg = csvdb["activity_ctrlCsv"][actId] + if not actCfg then return 0 end + + local actStartTime = 0 + local openTimes = actCfg.time:toArray(false, "=") + actStartTime = toUnixtime(openTimes[1]..string_format("%02x", RESET_TIME)) + local actData = self:getActData("RegularWorldBoos") or {} + local startTs = actData["ts"] or math.max(actStartTime, createTs) + local timeNow = skynet.timex() + local modify = false + local arr = actCfg.condition2:toArray(true, "=") + + local ticketId, init, limit, duration = arr[1] or 0, arr[2] or 0, arr[3] or 0, arr[4] or 10000 + + local count = actData["ticket"] or init + if count >= limit then + actData["ts"] = timeNow + self:updateActData("RegularWorldBoos", actData) + return + end + local add = math.max(math.floor((timeNow - startTs) / (duration * 60)), 0) + + local newCount= math.min(count + add, limit) + if newCount ~= count or newCount >= limit then + modify = true + end + add = newCount - count + + if modify or not next(actData) then + actData["ticket"] = newCount + actData["ts"] = newCount >= limit and timeNow or (startTs + add * duration * 60) + self:updateActData("RegularWorldBoos", actData) + end +end + activityFunc[Activity.ActivityType.ActShopGoods] = { ["init"] = function(self, actType, isCrossDay, notify, actId) end, diff --git a/src/models/RoleLog.lua b/src/models/RoleLog.lua index b613a7d..ceb1a33 100644 --- a/src/models/RoleLog.lua +++ b/src/models/RoleLog.lua @@ -70,6 +70,9 @@ local ItemReason = { buyDiamondCardReward = 154, --购买钻石额外赠送奖励 firstMonthCardReward = 155, --首次订阅月卡奖励 firstSMonthCardReward = 156, --首次订阅特刊奖励 + regularWorldBossReward = 157, -- 常规世界boss + regularWorldBossMilestone = 157, -- 常规世界boss伤害里程碑 + advHang = 301, -- 拾荒挂机 hangBattle = 302, -- 挂机战斗 @@ -115,6 +118,8 @@ local ItemReason = { battleCommandTask = 1011, -- 将军令任务 newUserTask = 1012, -- 新玩家任务 buyActivityBattleTicket = 1013, -- 购买门票 + buyRegularWorldBossTicket = 1014, -- 购买门票 + -- 餐厅 greenHourse = 1101, -- 食材获得 -- libgit2 0.21.2