local ipairs = ipairs local table = table local math = math local next = next local string = string local redisproxy = redisproxy local MsgPack = MsgPack local getRandomName = getRandomName local mcast_util = mcast_util local string_format = string.format local tonumber = tonumber local require = require local table_insert = table.insert local tconcat = table.concat local table_unpack = table.unpack local _M = {} local function checkReward(role) local hangInfo = role:getProperty("hangInfo") if not hangInfo.carbonId or not hangInfo.coinTime or not hangInfo.itemTime then return false end local carbonData = csvdb["idle_battleCsv"][hangInfo.carbonId] local expCarbonData = csvdb["idle_battleCsv"][hangInfo.expCarbonId] local nowCoinTime = math.min(skynet.timex(), hangInfo.endCoinTime or 0) local nowItemTime = math.min(skynet.timex(), hangInfo.endItemTime or 0) -- 此次挂机,其中翻倍时长占多少 local doubleTime = role.activity:getActHangDoubleTime(hangInfo.coinTime, nowCoinTime) local normalTime = nowCoinTime - hangInfo.coinTime - doubleTime local coinCount = math.max(0, math.floor((normalTime) / globalCsv.idle_money_produce_cd)) local coinDoubleCount = math.max(0, math.floor((doubleTime) / globalCsv.idle_money_produce_cd)) * 2 hangInfo.coinTime = nowCoinTime normalTime = nowItemTime - hangInfo.itemTime local itemCount = math.max(0, math.floor((normalTime) / globalCsv.idle_item_produce_cd)) hangInfo.itemTime = nowItemTime local items = role:getProperty("hangBag") coinCount = coinCount + coinDoubleCount items[ItemId.Gold] = math.floor((items[ItemId.Gold] or 0) + coinCount * expCarbonData.money) items[ItemId.Exp] = math.floor((items[ItemId.Exp] or 0) + coinCount * expCarbonData.exp) items[ItemId.PlayerExp] = math.floor((items[ItemId.PlayerExp] or 0) + coinCount * expCarbonData.playerExp) local pool = {} for _, temp in pairs(carbonData.item:toArray()) do table.insert(pool, temp:toArray(true, "=")) end local curFC = 0 local curIC = 0 for id, count in pairs(items) do if id ~= ItemId.Gold and id ~= ItemId.Exp and id ~= ItemId.PlayerExp then curFC = curFC + math.ceil(count / globalCsv.idle_field_limit) curIC = curIC + count end end -- 特权卡挂机额外栏位 local privExtraCnt = role.storeData:getHangSlotExtraCount() local selfFC = role:getProperty("hangBagLimit") + privExtraCnt local selfIC = selfFC * globalCsv.idle_field_limit local function randomItem() if curIC >= selfIC then return end local tempPool = clone(pool) while #tempPool > 0 do local idx = math.randWeight(tempPool, 3) local cur = clone(pool[idx]) if cur[1] ~= 0 then -- 轮空 id if cur[1] == ItemId.BreakCost and doubleTime > 0 then cur[2] = cur[2] * 2 end if (items[cur[1]] and math.ceil((items[cur[1]] + cur[2]) / globalCsv.idle_field_limit) > math.ceil(items[cur[1]] / globalCsv.idle_field_limit)) or not items[cur[1]] then --要占用新栏位的情况 local addFC if not items[cur[1]] then addFC = math.ceil(cur[2] / globalCsv.idle_field_limit) else local frontC = items[cur[1]] % globalCsv.idle_field_limit if frontC == 0 then frontC = globalCsv.idle_field_limit end addFC = math.ceil((cur[2] - (globalCsv.idle_field_limit - frontC)) / globalCsv.idle_field_limit) end if curFC + addFC <= selfFC then curFC = curFC + addFC items[cur[1]] = (items[cur[1]] or 0) + cur[2] break else --加不了,换别的东西 table.remove(tempPool, idx) end else items[cur[1]] = items[cur[1]] + cur[2] break end else break end end curIC = curIC + 1 end for i = 1, itemCount do randomItem() end if coinCount > 0 or itemCount > 0 then return true end return false end --开始一个新的关卡 function _M.startRpc( agent, data ) local role = agent.role local msg = MsgPack.unpack(data) local carbonId = msg.carbonId local carbonData = csvdb["idle_battleCsv"][carbonId] if not carbonData then return 1 end if math.floor(carbonId / 10000) ~= 1 then if not role:isFuncUnlock(FuncUnlock.DifficultHang) then return end end for _, preCarbonId in ipairs(carbonData.prepose:toArray(true, "=")) do if not role:checkHangPass(preCarbonId) then return 2 end end if checkReward(role) then role:updateProperty({field = "hangBag", value = role:getProperty("hangBag")}) end local hangInfo = role:getProperty("hangInfo") local isNew = not hangInfo.carbonId hangInfo.carbonId = carbonId hangInfo.expCarbonId = isNew and carbonId or hangInfo.expCarbonId local nowTime = skynet.timex() if isNew then hangInfo.coinTime = nowTime hangInfo.itemTime = nowTime hangInfo.endCoinTime = nowTime + globalCsv.idle_producetime_max hangInfo.endItemTime = nowTime + globalCsv.idle_producetime_max else hangInfo.coinTime = math.min(nowTime, hangInfo.endCoinTime) hangInfo.itemTime = math.min(nowTime, hangInfo.endItemTime) end if not role:checkHangPass(carbonId) then hangInfo.bossTime = nowTime + carbonData.idle_time else hangInfo.bossTime = nil end role:updateProperty({field = "hangInfo", value = hangInfo}) -- 指定当前引导的步骤 if carbonId == 10101 then role:saveGuide(5,11) elseif carbonId == 10102 then role:saveGuide(8,2) elseif carbonId == 10103 then role:saveGuide(9,2) elseif carbonId == 10220 then role:saveGuide(22,1) end role:mylog("hang_action", {desc = "startHang", int1 = carbonId}) SendPacket(actionCodes.Hang_startRpc, '') return true end -- 每隔1分钟检查一次 function _M.checkRpc(agent, data) local role = agent.role -- local msg = MsgPack.unpack(data) if checkReward(role) then role:updateProperty({field = "hangBag", value = role:getProperty("hangBag")}) role:updateProperty({field = "hangInfo", value = role:getProperty("hangInfo")}) end SendPacket(actionCodes.Hang_checkRpc, MsgPack.pack({})) return true end local _BattleKey = nil function _M.startBattleRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) local carbonId = msg.carbonId local curData = csvdb["idle_battleCsv"][carbonId] if not curData then return 1 end local hangInfo = role:getProperty("hangInfo") or {} if curData.main ~= 1 then if carbonId ~= hangInfo.carbonId then return 2 end end if role:checkHangPass(carbonId) then return 3 end _BattleKey = tostring(math.random()) role:checkTaskEnter("HangBattle", {id = carbonId}) SendPacket(actionCodes.Hang_startBattleRpc, MsgPack.pack({key = _BattleKey})) return true end function _M.endBattleRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) local hangInfo = role:getProperty("hangInfo") or {} if not msg.key or msg.key ~= _BattleKey then SendPacket(actionCodes.Hang_endBattleRpc, MsgPack.pack({errorCode = 1})) return true end local carbonId = msg.carbonId local isWin = msg.starNum and msg.starNum > 0 local carbonData = csvdb["idle_battleCsv"][carbonId] if not carbonData then return 2 end if carbonData.main ~= 1 then if carbonId ~= hangInfo.carbonId then return 3 end end if role:checkHangPass(carbonId) then return 4 end local reward, change if isWin then --win role:hangFinish(carbonId) if carbonData.main ~= 1 then hangInfo.bossTime = nil end -- reward reward = {} reward[ItemId.Gold] = carbonData.money_clear reward[ItemId.Exp] = carbonData.exp_clear reward[ItemId.PlayerExp] = carbonData.playerExp_clear for itemId, count in pairs(carbonData.item_clear:toNumMap()) do reward[itemId] = count end reward, change = role:award(reward, {log = {desc = "hangBattle", int1 = carbonId}}) role:checkTaskEnter("HangPass", {id = carbonId}) -- 引导 if carbonId == 10101 then role:finishGuide(5) elseif carbonId == 10102 then role:finishGuide(8) role:saveGuide(9, 2) elseif carbonId == 10103 then role:finishGuide(9) elseif carbonId == 20101 then role:finishGuide(22) end for _, guideData in pairs(csvdb["guide_unlockCsv"]) do if guideData.type == 3 and guideData.carbonId == carbonId then role:saveGuide(guideData.guideId,1,true) break end end end local nextCarbonId = role:getNextCarbonId(carbonId) -- 设置挂机关卡 if isWin and (hangInfo.carbonId or 0) < nextCarbonId then hangInfo.expCarbonId = nextCarbonId local cfg = csvdb["idle_battleCsv"][nextCarbonId] if cfg then hangInfo.bossTime = skynet.timex() + cfg.idle_time end end role:updateProperty({field = "hangInfo", value = hangInfo}) role:checkBattle("hang", { id = carbonId, isWin = isWin, info = msg.info, reward = reward, }) local team = role:getProperty("pvpTC") role:mylog("hang_action", {desc = "hangBattle", short1 = msg.starNum > 0 and 1 or 0, int1 = carbonId, int2 = role:getProperty("hangTBV"), cint1 = role:getHerosCamp(team.heros)}) SendPacket(actionCodes.Hang_endBattleRpc, MsgPack.pack({ starNum = msg.starNum, reward = reward, change = change, })) return true end local function checkLeader(heros, leader) if not leader then return end for slot, heroId in pairs(heros) do if heroId == leader then return true end end end function _M.roleFormatRpc(agent , data) local role = agent.role local msg = MsgPack.unpack(data) local hangTeam = role:getProperty("hangTeam") for slot, heroId in pairs(msg.heros) do if not role.heros[heroId] then return 1 end end local supports = {} for slot, support in pairs(msg.supports or {}) do if slot ~= 1 and slot ~= 2 then return 2 end local level = role.dinerData:getProperty("dishTree"):getv(support, 0) if level <= 0 then return 3 end supports[slot] = support end if not checkLeader(msg.heros, msg.leader) then return 4 end table.clear(hangTeam) hangTeam.heros = {} for slot, heroId in pairs(msg.heros) do hangTeam.heros[slot] = heroId end hangTeam.leader = msg.leader hangTeam.supports = supports role:saveHangTeam(hangTeam) role:saveGuide(5,8) SendPacket(actionCodes.Hang_roleFormatRpc, '') return true end function _M.getRewardRpc(agent , data) local role = agent.role checkReward(role) local items = role:getProperty("hangBag") if not next(items) then return end local reward, change = role:award(items, {log = {desc = "hangReward"}}) table.clear(items) local hangInfo = role:getProperty("hangInfo") local nowTime = skynet.timex() hangInfo.endItemTime = nowTime + globalCsv.idle_producetime_max hangInfo.endCoinTime = nowTime + globalCsv.idle_producetime_max hangInfo.coinTime = nowTime hangInfo.itemTime = nowTime role:updateProperty({field = "hangBag", value = items}) role:updateProperty({field = "hangInfo", value = hangInfo}) role:checkTaskEnter("HangGet", {reward = reward}) if reward[ItemId.Gold] then role:checkTaskEnter("HangGetGold", {count = reward[ItemId.Gold]}) end role:log("residence_reward", { mission_threadid = math.floor(hangInfo.carbonId / 10000), --大关卡ID mission_id = hangInfo.carbonId, --关卡ID mission_type = 100, --关卡类型,见关卡类型枚举表 residence_reward_type = 0, --领取奖励方式,快速(超前领取)记录为1,正常领取记录为0 residence_time = 0, --挂机或排名时长 residence_reward = reward, --获得奖励,建议使用json格式记录。示例:{ "XX": "1", "XXX": "3"} }) SendPacket(actionCodes.Hang_getRewardRpc, MsgPack.pack({ reward = reward, change = change })) return true end function _M.quickRpc(agent , data) local role = agent.role local hangInfo = role:getProperty("hangInfo") if not hangInfo.carbonId then return end local carbonData = csvdb["idle_battleCsv"][hangInfo.carbonId] local expCarbonData = csvdb["idle_battleCsv"][hangInfo.expCarbonId] local curCount = role.dailyData:getProperty("hangQC") + 1 local costs = globalCsv.idle_quickproduce_cost:toArray(true, "=") if not costs[curCount] then return end if costs[curCount] > 0 then if not role:checkItemEnough({[ItemId.Diamond] = costs[curCount]}) then return end role:costItems({[ItemId.Diamond] = costs[curCount]}, {log = {desc = "quickHang", int1 = hangInfo.carbonId}}) end role.dailyData:updateProperty({field = "hangQC", value = curCount}) local time = globalCsv.idle_quickproduce_time local reward = {} local coinCount = math.floor(time / globalCsv.idle_money_produce_cd) local itemCount = math.floor(time / globalCsv.idle_item_produce_cd) reward[ItemId.Gold] = math.floor((reward[ItemId.Gold] or 0) + coinCount * expCarbonData.money) reward[ItemId.Exp] = math.floor((reward[ItemId.Exp] or 0) + coinCount * expCarbonData.exp) reward[ItemId.PlayerExp] = math.floor((reward[ItemId.PlayerExp] or 0) + coinCount * expCarbonData.playerExp) local pool = {} for _, temp in pairs(carbonData.item:toArray()) do table.insert(pool, temp:toArray(true, "=")) end for i = 1, itemCount do local cur = pool[math.randWeight(pool, 3)] reward[cur[1]] = (reward[cur[1]] or 0) + cur[2] end local doubleCoef = role.activity:isOpen("DoubleDrop") and 2 or 1 -- 特权卡获取加速获得额外道具 local coef = role.storeData:getProduceItemSpeedCoef() if coef > 1 or doubleCoef > 1 then for k, cnt in pairs(reward) do reward[k] = math.floor(cnt * coef * doubleCoef) end end local change reward, change = role:award(reward, {log = {desc = "quickHang", int1 = hangInfo.carbonId}}) if reward[ItemId.Gold] then role:checkTaskEnter("HangGetGold", {count = reward[ItemId.Gold]}) end role:checkTaskEnter("HangQuick") role:log("residence_reward", { mission_threadid = math.floor(hangInfo.carbonId / 10000), --大关卡ID mission_id = hangInfo.carbonId, --关卡ID mission_type = 100, --关卡类型,见关卡类型枚举表 residence_reward_type = 1, --领取奖励方式,快速(超前领取)记录为1,正常领取记录为0 residence_time = time, --挂机或排名时长 residence_reward = reward, --获得奖励,建议使用json格式记录。示例:{ "XX": "1", "XXX": "3"} }) SendPacket(actionCodes.Hang_quickRpc, MsgPack.pack({ reward = reward, change = change })) return true end function _M.bonusFormatRpc(agent , data) local role = agent.role local msg = MsgPack.unpack(data) local bTeam = role:getProperty("bTeam") for slot, heroId in pairs(msg.heros) do if not role.heros[heroId] then return end end local supports = {} for slot, support in pairs(msg.supports) do if slot ~= 1 and slot ~= 2 then return end local level = role.dinerData:getProperty("dishTree"):getv(support, 0) if level <= 0 then return end supports[slot] = support end if not checkLeader(msg.heros, msg.leader) then return end table.clear(bTeam) bTeam.heros = {} for slot, heroId in pairs(msg.heros) do bTeam.heros[slot] = heroId end bTeam.leader = msg.leader bTeam.supports = supports role:updateProperty({field = "bTeam", value = bTeam}) SendPacket(actionCodes.Hang_bonusFormatRpc, '') return true end function _M.buyBonusCountRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) local count = msg.count local btype = msg.type if not TimeReset["DailyBattle" .. btype] then return end local open, actId = role.activity:isOpen("BonusDouble") local actData = csvdb["activity_ctrlCsv"][actId] local coef = 1 if open and actData then coef= tonumber(actData.condition2) end local bonusC = role.dailyData:getProperty("bonusC") bonusC[btype] = bonusC[btype] or {c = 0, b = 0} local lastCount = globalCsv.bonus_daily_buy_count * coef - bonusC[btype]["b"] if math.illegalNum(count, 1, lastCount) then return 1 end if not role:checkItemEnough({[ItemId.Diamond] = globalCsv.bonus_buy_cost * count}) then return 2 end role:costItems({[ItemId.Diamond] = globalCsv.bonus_buy_cost * count}, {log = {desc = "buyBonusCount", int1 = btype, int2 = count}}) bonusC[btype]["b"] = bonusC[btype]["b"] + count bonusC[btype]["c"] = bonusC[btype]["c"] - count role.dailyData:updateProperty({field = "bonusC", value = bonusC}) SendPacket(actionCodes.Hang_buyBonusCountRpc, '') return true end function _M.startBonusBattleRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) local id = msg.id local open, actId = role.activity:isOpen("BonusDouble") if not role:isFuncUnlock(FuncUnlock.BonusBattle) then return 1 end local bonusData = csvdb["bonus_battleCsv"][id] if not open then if not role:isTimeResetOpen(TimeReset["DailyBattle" .. bonusData.type]) then return 2 end end if not bonusData then return 3 end if not role:checkHangPass(bonusData.unlock) then return 4 end if not next(role:getProperty("bTeam")) then return 5 end local bonusC = role.dailyData:getProperty("bonusC") bonusC[bonusData.type] = bonusC[bonusData.type] or {c = 0, b = 0} local actData = csvdb["activity_ctrlCsv"][actId] local coef = 1 if open and actData then coef = tonumber(actData.condition2) end if globalCsv.bonus_daily_count * coef - bonusC[bonusData.type]["c"] <= 0 then return 7 end role.__bonusBattleCache = { key = tostring(math.random()), id = id, } SendPacket(actionCodes.Hang_startBonusBattleRpc, MsgPack.pack({key = role.__bonusBattleCache.key})) return true end function _M.endBonusBattleRpc(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 local open, actId = role.activity:isOpen("BonusDouble") local actData = csvdb["activity_ctrlCsv"][actId] local coef = 1 if open and actData then coef = tonumber(actData.condition2) end if role.__bonusBattleCache.id ~= id or role.__bonusBattleCache.key ~= key then SendPacket(actionCodes.Hang_endBonusBattleRpc, MsgPack.pack({errorCode = 1})) return true end local bonusData = csvdb["bonus_battleCsv"][id] local reward, change if starNum and starNum > 0 then -- 胜利扣除次数 local bonusC = role.dailyData:getProperty("bonusC") bonusC[bonusData.type] = bonusC[bonusData.type] or {c = 0, b = 0} if globalCsv.bonus_daily_count * coef - bonusC[bonusData.type]["c"] <= 0 then return 3 end bonusC[bonusData.type]["c"] = bonusC[bonusData.type]["c"] + 1 role.dailyData:updateProperty({field = "bonusC", value = bonusC}) reward = bonusData.reward:toNumMap() local chance = bonusData.chance:randWeight(true) if chance[1] ~= 0 then reward[chance[1]] = (reward[chance[1]] or 0) + chance[2] end for k, v in pairs(reward) do reward[k] = v * (coef > 1 and actData.condition or 1) end reward, change = role:award(reward, {log = {desc = "bonusBattle", int1 = id}}) role:checkTaskEnter("BonusPass", {id = id}) end role:checkBattle("bonus", { id = id, isWin = starNum and starNum > 0, info = msg.info, reward = reward, }) role:mylog("hang_action", {desc = "bonusBattle", short1 = msg.starNum > 0 and 1 or 0, int1 = id}) SendPacket(actionCodes.Hang_endBonusBattleRpc, 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) local id = msg.id local carbonData = csvdb["idle_battleCsv"][id] if not carbonData or carbonData.item_clear_special == "" then return 1 end local hangGift = role:getProperty("hangGift") if hangGift[id] then return 2 end local reward, change = role:award(carbonData.item_clear_special, {log = {desc = "hangGift", int1 = id}}) role:changeUpdates({{type = "hangGift", field = id, value = 1}}) role:mylog("hang_action", {desc = "hangGift", int1 = id}) SendPacket(actionCodes.Hang_hangGiftRpc, MsgPack.pack({reward = reward, change = change})) return true end function _M.bagFieldRpc(agent, data) local role = agent.role local curBL = role:getProperty("hangBagLimit") local costD = globalCsv.idle_field_cost[curBL - globalCsv.idle_field_origin] if not costD then return 1 end if costD ~= 0 and not role:checkItemEnough({[ItemId.Diamond] = costD}) then return 2 end role:updateProperty({field = "hangBagLimit", value = curBL + 1}) role:costItems({[ItemId.Diamond] = costD}, {log = {desc = "bagField"}}) SendPacket(actionCodes.Hang_bagFieldRpc, '') return true end function _M.chatLineRpc(agent, data) local role = agent.role local msg = MsgPack.unpack(data) local id = msg.id local idleData = csvdb["idle_battleCsv"][id] if not idleData or idleData.chatline == 0 then return end local chatline = role:getProperty("chatline") if chatline[id] then return end if not role:checkHangPass(id) then return end chatline[id] = skynet.timex() role:updateProperty({field = "chatline", value = chatline}) local reward, change = role:award(idleData.chatline_reward, {log = {desc = "chatline", int1 = id}}) SendPacket(actionCodes.Hang_chatLineRpc, MsgPack.pack({reward = reward, change = change})) return true end return _M