local skynet = require "skynet" local oo = require "Class" local log = require "Log" local pb = require "pb" local dataType = require "DataType" local errorInfo = require "ErrorInfo" local PassCheck = oo.class() PassCheck.RewardType_Normal = 1 --普通奖励 PassCheck.RewardType_Pay = 2 --付费奖励 PassCheck.TaskType_Normal = 1 --常规任务 PassCheck.TaskType_LimitTime = 2 --限时任务 PassCheck.TaskType_Daily = 3 --每日任务 PassCheck.surplusTime = 100 --剩余时间 PassCheck.MaxShowItem = 4 --任务最大显示多少个 function PassCheck:Init() end --初始化数据 function PassCheck:CheckNew( player ) if not player:IsUnlockSystem( dataType.UnlockSystem_PassCheck ) then return end --根据开始和结束时间找到当期的任务 local curCfgPassCheck = self:GetCurPeriodCfg( player ) local passCheck = player.gameData.passCheck if curCfgPassCheck and curCfgPassCheck.id ~= passCheck.curId then --新的一期初始化数据 passCheck.curId = curCfgPassCheck.id --获取最新的通行证ID passCheck.rewards = {} passCheck.tasks = {} passCheck.score = 0 passCheck.isVip = false passCheck.infiniteRewardCount = 0 local cfgPassCheckClass = skynet.server.gameConfig.PassCheckClass --奖励配置 for k, v in pairs( cfgPassCheckClass ) do if curCfgPassCheck.id == v.passCheckId then table.insert( passCheck.rewards , { id = v.id , normalStatus = dataType.RewardStatus_NoGet , payStatus = dataType.RewardStatus_NoGet }) end end local tmpCfgPassCheckTask = self:GetRandTask( player , curCfgPassCheck ) for k, v in pairs( tmpCfgPassCheckTask ) do --任务类型(注意配置中用的是taskTime),任务种类,当前进度,是否完成 if self.TaskType_Normal == v.taskTime then --if v.id >=1 and v.id <= 18 then -- table.insert( passCheck.tasks , { id = v.id , type = v.taskTime , kind = v.taskType , progress = 0 , status = skynet.server.task.TaskStatus_AlreadyGet}) --else table.insert( passCheck.tasks , { id = v.id , type = v.taskTime , kind = v.taskType , progress = 0 , status = skynet.server.task.TaskStatus_NoComplete}) --end elseif self.TaskType_LimitTime == v.taskTime then --if v.id >=21 and v.id <= 39 then -- table.insert( passCheck.tasks , { id = v.id , type = v.taskTime , kind = v.taskType , progress = 0 , status = skynet.server.task.TaskStatus_OutOfTime , endTime = 0}) --else table.insert( passCheck.tasks , { id = v.id , type = v.taskTime , kind = v.taskType , progress = 0 , status = skynet.server.task.TaskStatus_NoComplete , endTime = 0}) --end elseif self.TaskType_Daily == v.taskTime then table.insert( passCheck.tasks , { id = v.id , type = v.taskTime , kind = v.taskType , progress = 0 , status = skynet.server.task.TaskStatus_NoComplete }) end end end end --通行证奖励显示 function PassCheck:RewardShow( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPassCheckRewardShow", c2sData.data )) local passCheck = player.gameData.passCheck local data = {} data.basicInfo = { score = passCheck.score , surplusTime = self.surplusTime , passCheckId = passCheck.curId } data.rewards = passCheck.rewards data.isVip = passCheck.isVip data.infiniteRewardCount = passCheck.infiniteRewardCount s2cData.cmd = pb.enum("MsgType","CMD_S2C_PassCheckRewardShow") s2cData.data = assert(pb.encode("S2CPassCheckRewardShow", data)) end --获得当前期配置 function PassCheck:GetCurPeriodCfg( player ) local curCfgPassCheck = nil local cfgPassCheck = skynet.server.gameConfig.PassCheck for k, v in pairs(cfgPassCheck) do local startTime = skynet.server.common:GetTime( v.startTime ) local endTime = skynet.server.common:GetTime( v.endTime ) if skynet.GetTime() >= startTime and skynet.GetTime() <= endTime then curCfgPassCheck = v --获取当前通行证ID break end end return curCfgPassCheck end --随机任务 function PassCheck:GetRandTask( player , curCfgPassCheck ) --打乱现有配置顺序 local cfgPassCheckTask = skynet.server.gameConfig.PassCheckTask --任务配置 local tmpCfgPassCheckTask = {} for k, v in pairs(cfgPassCheckTask) do --每日任务直接加入 if self.TaskType_Daily == v.taskTime then v.randValue = 0 table.insert(tmpCfgPassCheckTask , v) else --常规和限时任务部分任务才能加入 if self:IsJoinTask( curCfgPassCheck , v.taskTime , v.id ) then v.randValue = math.random(1,1000) table.insert(tmpCfgPassCheckTask , v) end end end --根据随机值进行排序 table.sort(tmpCfgPassCheckTask , function (a,b) if a.randValue >b.randValue then --降序 return end end) return tmpCfgPassCheckTask end --获取普通奖励信息 function PassCheck:GetNormalReward( player , rewardId ) local isGainReward = false local getRewardIds = {} --奖励的信息 local passCheck = player.gameData.passCheck local curCfgPassCheckClass = skynet.server.gameConfig:GetCurCfg("PassCheckClass" , rewardId ) local curCfgPassCheck = skynet.server.gameConfig:GetCurCfg("PassCheck" , passCheck.curId ) --获取当前奖励信息 local curReward = {} for k, v in pairs( passCheck.rewards ) do if rewardId == v.id then curReward = v break end end --非无限奖励领奖 if dataType.RewardStatus_CanGet == curReward.normalStatus then --普通奖励 for k, v in pairs( curCfgPassCheckClass.normalReward ) do table.insert( getRewardIds , v ) end curReward.normalStatus = dataType.RewardStatus_AlreadyGet isGainReward =true log.info(string.format("玩家 %d 通行证 普通奖励获取 奖励ID %d" , player.userId, rewardId)) end if passCheck.isVip and dataType.RewardStatus_CanGet == curReward.payStatus then --付费奖励 for k, v in pairs( curCfgPassCheckClass.payReward ) do table.insert( getRewardIds , v ) end curReward.payStatus = dataType.RewardStatus_AlreadyGet isGainReward =true log.info(string.format("玩家 %d 通行证 付费奖励获取 奖励ID %d", player.userId , rewardId)) end --发奖 for k, v in pairs( getRewardIds ) do player:GiveReward( v ) end return getRewardIds,isGainReward end --获取无限奖励信息 function PassCheck:GetInfiniteReward( player , rewardId , s2cData) local isGainReward = false local getRewardIds = {} --奖励的信息 local passCheck = player.gameData.passCheck local curCfgPassCheckClass = skynet.server.gameConfig:GetCurCfg("PassCheckClass" , rewardId ) local curCfgPassCheck = skynet.server.gameConfig:GetCurCfg("PassCheck" , passCheck.curId ) local data = {} if passCheck.infiniteRewardCount >= curCfgPassCheck.ultimateLimit then s2cData.code = errorInfo.ErrorCode.MaxLimit elseif not passCheck.isVip then return data,isGainReward else --获取当前奖励信息 local curReward = {} for k, v in pairs( passCheck.rewards ) do if rewardId == v.id then curReward = v break end end if dataType.RewardStatus_CanGet == curReward.normalStatus then --普通奖励 --发奖 local weight = curCfgPassCheckClass.ultimateRewardWeight local allWeight = 0 --计算权重总数 for k, v in pairs( weight ) do allWeight = allWeight + v end --在1和总权重进行随机 local rand = math.random(1 , allWeight) log.info(string.format("玩家 %d 通行证 随机值 %d 随机区间[ %d , %d ]" , player.userId , rand , 1, allWeight)) local curCount = 0 local weightIndex = 0 for k, v in pairs( weight ) do curCount = curCount + v if rand <= curCount then weightIndex = k break end end for k, v in pairs( curCfgPassCheckClass.ultimateReward ) do data = player:SelectOneReward( v , weightIndex) end passCheck.infiniteRewardCount = passCheck.infiniteRewardCount + 1 --无线领奖状态修改为已获取 if passCheck.infiniteRewardCount >= curCfgPassCheck.ultimateLimit then curReward.payStatus = dataType.RewardStatus_AlreadyGet end isGainReward = true log.info(string.format("玩家 %d 通行证 无限奖励获取 奖励索引 %d" , player.userId , weightIndex)) end return data,isGainReward end end --通行证奖励获取 function PassCheck:RewardGet( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPassCheckRewardGet", c2sData.data )) local rewardId = c2sData.data.rewardId local data = {} data.gainRewards = {} data.infiniteMoneys = {} if not rewardId then s2cData.code = errorInfo.ErrorCode.ErrRequestParam else local getRewardIds = {} --获取奖励的ID local passCheck = player.gameData.passCheck local getRewardIds = {} if 0 == rewardId % 31 then local rewardInfo,isGainReward = self:GetInfiniteReward( player , rewardId , s2cData ) if isGainReward then table.insert( data.infiniteMoneys ,rewardInfo ) end else data.gainRewards = self:GetNormalReward( player , rewardId ) --当前奖励信息 end for k, v in pairs( passCheck.rewards ) do if rewardId == v.id then data.reward = v break end end data.infiniteRewardCount = passCheck.infiniteRewardCount end self:CheckMsgTips( player ) s2cData.cmd = pb.enum("MsgType","CMD_S2C_PassCheckRewardGet") s2cData.data = assert(pb.encode("S2CPassCheckRewardGet", data)) end --通行证奖励一键获取 function PassCheck:RewardAllGet( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPassCheckRewardAllGet", c2sData.data )) local data = {} data.rewards = {} data.gainRewards = {} data.infiniteMoneys = {} local getRewardIds = {} --获取奖励的ID local passCheck = player.gameData.passCheck for k1, v1 in pairs( passCheck.rewards ) do if 0 == v1.id % 31 then local curCfgPassCheck = skynet.server.gameConfig:GetCurCfg("PassCheck" , passCheck.curId ) local gainCount = curCfgPassCheck.ultimateLimit - passCheck.infiniteRewardCount if gainCount > 0 then for i = 1, gainCount, 1 do local rewardInfo,isGainReward = self:GetInfiniteReward( player , v1.id , s2cData ) if isGainReward then table.insert( data.infiniteMoneys ,rewardInfo ) table.insert( data.rewards , v1 ) end end end else local gainRewards,isGainReward = self:GetNormalReward( player , v1.id ) --当前奖励信息 for k, v in pairs(gainRewards) do table.insert(data.gainRewards ,v) end if isGainReward then table.insert( data.rewards , v1 ) end end end self:CheckMsgTips( player ) data.infiniteRewardCount = passCheck.infiniteRewardCount s2cData.cmd = pb.enum("MsgType","CMD_S2C_PassCheckRewardAllGet") s2cData.data = assert(pb.encode("S2CPassCheckRewardAllGet", data)) end --通行证任务显示 function PassCheck:TaskShow( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPassCheckTaskShow", c2sData.data )) local taskType = c2sData.data.taskType local data = {} if not taskType then s2cData.code = errorInfo.ErrorCode.ErrRequestParam else local passCheck = player.gameData.passCheck data.taskType = taskType data.basicInfo = { score = passCheck.score , surplusTime = self.surplusTime } --获取任务信息 data.taskInfos = self:GetShowTaskData( player , taskType ) end s2cData.cmd = pb.enum("MsgType","CMD_S2C_PassCheckTaskShow") s2cData.data = assert(pb.encode("S2CPassCheckTaskShow", data)) end --通行证任务获取 function PassCheck:TaskGet( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SPassCheckTaskGet", c2sData.data )) local taskType = c2sData.data.taskType local taskId = c2sData.data.taskId local data = {} if not taskType or not taskId then s2cData.code = errorInfo.ErrorCode.ErrRequestParam else local passCheck = player.gameData.passCheck local curTask = self:GetTaskInfo( player , taskType , taskId ) if curTask.status == skynet.server.task.TaskStatus_AlreadyComplete then --已经完成才能领取 local curCfgPassCheckTask = skynet.server.gameConfig:GetCurCfg("PassCheckTask" , taskId ) local passCheck = player.gameData.passCheck passCheck.score = passCheck.score + curCfgPassCheckTask.taskPoint --领取了积分修改已经领取状态 curTask.status = skynet.server.task.TaskStatus_AlreadyGet --检查下普通和付费奖励是否能领取 self:CheckNormalReward( player ) self:CheckPayReward( player ) log.info(string.format("玩家 %d 通行证 任务完成领取积分 任务ID %d" , player.userId ,taskId)) else s2cData.code = errorInfo.ErrorCode.GetAwardFailed end data.taskType = taskType data.basicInfo = { score = passCheck.score , surplusTime = self.surplusTime } data.taskInfo = self:GetShowTaskData( player , taskType ) end self:CheckMsgTips( player ) s2cData.cmd = pb.enum("MsgType","CMD_S2C_PassCheckTaskGet") s2cData.data = assert(pb.encode("S2CPassCheckTaskGet", data)) end --通行证充值 function PassCheck:Pay( player , storeId ) local passCheck = player.gameData.passCheck passCheck.isVip = true --开起VIP --充值了,检查下玩家的是否能领取付费礼包 self:CheckPayReward( player ) end --通行证修改任务 function PassCheck:Modify( player , kind , count ) if not player:IsUnlockSystem( dataType.UnlockSystem_PassCheck ) then return end log.info(string.format("玩家 %d 通行证 任务修改 种类 %d 数量 %d" , player.userId , kind , count )) local maxProgress = 0 local passCheck = player.gameData.passCheck for k, v in pairs( passCheck.tasks ) do if (self.TaskType_Normal == v.type or self.TaskType_LimitTime == v.type) and kind == v.kind and skynet.server.task.TaskStatus_NoComplete == v.status and self:IsShowTask( player , v.type , v.id ) then --获取最大进度 maxProgress = skynet.server.gameConfig:GetCurCfg("PassCheckTask" , v.id ).taskNum v.progress = v.progress + count --检查是否完成任务 if v.progress >= maxProgress then v.status =skynet.server.task.TaskStatus_AlreadyComplete self:CheckMsgTips( player ) v.progress = maxProgress log.info(string.format("玩家 %d 通行证 任务种类 %d 任务ID %d 完成 " , player.userId , kind ,v.id)) end end end --每日任务统计 for k, v in pairs( passCheck.tasks ) do if self.TaskType_Daily == v.type and kind == v.kind then local curCfgPassCheckTask = skynet.server.gameConfig:GetCurCfg("PassCheckTask" , v.id ) if v.progress < curCfgPassCheckTask.limit then --每日任务直接更新积分 v.progress = v.progress + 1 passCheck.score = passCheck.score + curCfgPassCheckTask.taskPoint --检查下普通和付费奖励是否能领取 self:CheckNormalReward( player ) self:CheckPayReward( player ) log.info(string.format("玩家 %d 通行证 任务种类 %d 任务ID %d 完成 " , player.userId , kind ,v.id)) end end end end --检查能领取的普通奖励 function PassCheck:CheckNormalReward( player ) local passCheck = player.gameData.passCheck local rewardLevel = self:GetRewardLevel( player ) for k, v in pairs( passCheck.rewards ) do local curCfg = skynet.server.gameConfig:GetCurCfg("PassCheckClass" , v.id ) --检查可以领取的普通奖励 if curCfg.level <= rewardLevel and dataType.RewardStatus_NoGet == v.normalStatus then v.normalStatus = dataType.RewardStatus_CanGet elseif curCfg.level > rewardLevel then break end end end --检查能领取的付费奖励 function PassCheck:CheckPayReward( player ) local passCheck = player.gameData.passCheck if passCheck.isVip then local rewardLevel = self:GetRewardLevel( player ) --开通了VIP才给付费奖励 for k, v in pairs( passCheck.rewards ) do local curCfg = skynet.server.gameConfig:GetCurCfg("PassCheckClass" , v.id ) --无法领取的付费奖励状态都设为可领取 if curCfg.level <= rewardLevel and dataType.RewardStatus_NoGet == v.payStatus then v.payStatus = dataType.RewardStatus_CanGet elseif curCfg.level > rewardLevel then break end end end end --获取奖励等级 function PassCheck:GetRewardLevel( player ) local score = player.gameData.passCheck.score local level = 0 local cfgPassCheckClass = skynet.server.gameConfig.PassCheckClass --奖励配置 for k, v in pairs( cfgPassCheckClass ) do score = score - v.Integral if score < 0 then break end level = level + 1 end return level end --获取任务信息 function PassCheck:GetTaskInfo( player , taskType , taskId ) local passCheck = player.gameData.passCheck for k, v in pairs( passCheck.tasks ) do if taskType == v.type and taskId == v.id then return v end end return nil end --检查有不有消息提示 function PassCheck:CheckMsgTips( player ) local passCheck = player.gameData.passCheck skynet.server.msgTips:Reset( player , 24 ) for k, v in pairs( passCheck.rewards ) do if dataType.RewardStatus_CanGet == v.normalStatus or dataType.RewardStatus_CanGet == v.payStatus then skynet.server.msgTips:Add( player , 24 ) break end end skynet.server.msgTips:Reset( player , 25 ) for k, v in pairs( passCheck.tasks ) do if self.TaskType_Normal == v.type and skynet.server.task.TaskStatus_AlreadyComplete == v.status then skynet.server.msgTips:Add( player , 25 ) break end end skynet.server.msgTips:Reset( player , 26 ) for k, v in pairs( passCheck.tasks ) do if self.TaskType_LimitTime == v.type and skynet.server.task.TaskStatus_AlreadyComplete == v.status then skynet.server.msgTips:Add( player , 26 ) break end end skynet.server.msgTips:SendLastTips( player , 24) skynet.server.msgTips:SendLastTips( player , 25) skynet.server.msgTips:SendLastTips( player , 26) end --获取数量 function PassCheck:GetTaskData( player , taskType ) local data = {} local passCheck = player.gameData.passCheck local count = 0 for k, v in pairs( passCheck.tasks ) do if count >= self.MaxShowItem then break end --限时任务超过时间就改为过期状态 if self.TaskType_LimitTime == v.type and skynet.server.task.TaskStatus_OutOfTime ~= v.status and skynet.GetTime() >= v.endTime and 0 ~=v.endTime then v.status = skynet.server.task.TaskStatus_OutOfTime end --未完成和已完成才会显示 if skynet.server.task.TaskStatus_NoComplete == v.status or skynet.server.task.TaskStatus_AlreadyComplete == v.status then if (self.TaskType_Normal == taskType or self.TaskType_Daily == taskType) and taskType == v.type then --常规任务和每日任务 table.insert( data , { id = v.id , progress = v.progress , status = v.status , endTime = 0} ) count = count + 1 elseif self.TaskType_LimitTime == taskType and taskType == v.type then --限时任务有个截止时间 if 0 == v.endTime then local cfgCurPassCheckTask = skynet.server.gameConfig:GetCurCfg("PassCheckTask", v.id) local runTime = cfgCurPassCheckTask.timeNum * 86400 local endTime = skynet.GetTime() + runTime v.endTime = endTime end table.insert( data , { id = v.id , progress = v.progress , status = v.status , endTime = v.endTime }) count = count + 1 end end end return data,count end --获取显示的任务信息 function PassCheck:GetShowTaskData( player , taskType ) local data = {} local count = 0 --获取下任务数据 data,count = self:GetTaskData( player , taskType ) --如果找出来的数量小于指定数量 if count < self.MaxShowItem then local passCheck = player.gameData.passCheck local tmpCount = self.MaxShowItem - count --需要补足多少个任务 --找出能够恢复的任务 local allRandTask = {} for k, v in pairs( passCheck.tasks ) do if skynet.server.task.TaskStatus_AlreadyGet== v.status or skynet.server.task.TaskStatus_OutOfTime == v.status then local isAdd = true if 12 == v.kind then local cfgCount = #skynet.server.gameConfig.StyleList --设计奖励配置数量 local rewardsCount = #player.gameData.shop[ dataType.ShopType_Style ].gainRewards --已经获取的奖励数量 local count = cfgCount - rewardsCount local curCfgPassCheckTask = skynet.server.gameConfig:GetCurCfg( "PassCheckTask" , v.id ) if count < curCfgPassCheckTask.taskNum then --小于数量就不再添加 isAdd = false end end if isAdd then table.insert( allRandTask , { id = v.id }) end end end --随机指定数量 local randTask = skynet.server.shop:GetNoRepeatGoods( tmpCount , allRandTask ) for k1, v1 in pairs( randTask ) do for k2, v2 in pairs( passCheck.tasks ) do if v1 == v2.id then --任务重置 v2.status = skynet.server.task.TaskStatus_NoComplete v2.progress = 0 --限时任务需要多重置个截止时间 if self.TaskType_LimitTime == taskType and taskType == v2.type then v2.endTime = 0 end end end end --再获取下任务数据 data,count = self:GetTaskData( player , taskType ) end return data end --是否显示中的任务 function PassCheck:IsShowTask( player , taskType , taskId ) local allTask = self:GetShowTaskData( player , taskType ) for k, v in pairs(allTask) do if taskId == v.id then return true end end return false end --是否加入任务 function PassCheck:IsJoinTask( curCfgPassCheck , taskType , taskId ) if self.TaskType_Normal == taskType then for k, v in pairs( curCfgPassCheck.normalTask ) do if taskId == v then return true end end elseif self.TaskType_LimitTime == taskType then for k, v in pairs( curCfgPassCheck.limitTask ) do if taskId == v then return true end end end return false end skynet.server.passCheck = PassCheck return PassCheck