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 activity = require "Activity" local json =require "json" local taskListEvent = require "TaskListEvent" local ActivityPuzzle = oo.class() ActivityPuzzle.ActivityType = dataType.ActivityType_Puzzle --当前盲盒矩阵模板 ActivityPuzzle.BoxInfosModel = {} function ActivityPuzzle:Init() --对当前盲盒矩阵初始化 for i = 1, 16 do self.BoxInfosModel[i] ={ blindBoxId = i, blindBoxState = 1 } end end --拼图任务事件注册 local function onEventFired(player , taskId , count) local activityId = skynet.server.activity:GetActivityInfo(player, ActivityPuzzle.ActivityType) --活动是否开启 if not player:IsUnlockSystem( dataType.UnlockSystem_ActivityPuzzle) or activityId == 0 then return end local cfgPuzzleTask = skynet.server.gameConfig:GetPlayerAllCfg(player, "JigsawPuzzleTask") local task = {} for k, v in pairs(cfgPuzzleTask) do if v.puzzleId == activityId then table.insert(task,v) end end --存在配置 if task == nil or not next(task) then return end --防止数据为空报错 if player.gameData.activity[ActivityPuzzle.ActivityType] == nil or next(player.gameData.activity[ActivityPuzzle.ActivityType]) == nil or player.gameData.activity[ActivityPuzzle.ActivityType].curData == nil or next(player.gameData.activity[ActivityPuzzle.ActivityType].curData) == nil then skynet.server.activityPuzzle:InitData(player) end --触发完成任务 local finishIds = taskListEvent:Condition(player , taskId , count , player.gameData.activity[ActivityPuzzle.ActivityType].curData.puzzleTask , task) --后续处理逻辑 红点逻辑此处处理 if next(finishIds) then skynet.server.msgTips:Add(player, 112) end end function ActivityPuzzle:LoginInitData(player) -- 检查应该初始还是结束活动 local activityId, startTime, endTime , id = activity:GetActivityInfo(player, self.ActivityType) if activityId == 0 and player.gameData.activity[self.ActivityType] ~= nil and next(player.gameData.activity[self.ActivityType]) ~= nil then --如果活动结束玩家身上还有未使用的拼图碎片则清空 if not player.gameData.activity[self.ActivityType].isClear then skynet.server.msgTips:Reset(player, 110) skynet.server.msgTips:Reset(player, 111) skynet.server.msgTips:Reset(player, 112) skynet.server.bag:RemoveGoods(player, dataType.GoodsType_Prop, 31, skynet.server.bag:GetGoodsCount(player, dataType.GoodsType_Prop, 31)) player.gameData.activity[self.ActivityType].isClear = true end end if id == 0 then return end if player:IsUnlockSystem( dataType.UnlockSystem_ActivityPuzzle ) then if player.gameData.activity[self.ActivityType] == nil or next(player.gameData.activity[self.ActivityType]) == nil or player.gameData.activity[self.ActivityType].curData == nil or next(player.gameData.activity[self.ActivityType].curData) == nil then self:InitData(player) else if player.gameData.activity[self.ActivityType].curId ~= id then self:InitData(player) else skynet.server.msgTips:Reset(player, 110) skynet.server.msgTips:Reset(player, 111) skynet.server.msgTips:Reset(player, 112) self:CheckRedHot( player ) end end end end function ActivityPuzzle:InitData(player) local activityId, startTime, endTime , id = skynet.server.activity:GetActivityInfo(player, self.ActivityType) if player.gameData.activity[self.ActivityType] == nil or player.gameData.activity[self.ActivityType].curData == nil then player.gameData.activity[self.ActivityType] = {} player.gameData.activity[self.ActivityType].curId = 0 player.gameData.activity[self.ActivityType].isClear = false player.gameData.activity[self.ActivityType].activedata = {} player.gameData.activity[self.ActivityType].curData = {} end if activityId == 0 then return end player.gameData.activity[self.ActivityType].curId = id player.gameData.activity[self.ActivityType].isClear = false player.gameData.activity[self.ActivityType].activedata = {} player.gameData.activity[self.ActivityType].curData = {} local puzzleData = player.gameData.activity[self.ActivityType].curData -- 玩家对应配置 puzzleData.puzzleId = activityId -- 本次活动id puzzleData.curLevelId = 1 -- 当前关卡id puzzleData.jigsawProgressStates = {1,1,1} --拼图进度进度奖励状态 1未解锁 2解锁未领取 3 已领取 puzzleData.fourDirRewardState = 1 --四向拼图奖励状态1未解锁 2解锁未领取 3 已领取 puzzleData.coreRewardState = 1 --中心拼图奖励状态1未解锁 2解锁未领取 3 已领取 puzzleData.JigsawPosInfos = {} --当前已经有拼图的位置 puzzleData.jigsawBlindBoxInfos = skynet.server.common:DeepCopy(self.BoxInfosModel) --当前盲盒矩阵信息 puzzleData.remainingUniversal = 2 --剩余万能碎片数量 puzzleData.remainingRandom = 14 --剩余随机碎片数量 puzzleData.puzzleTask = {} --拼图任务集合 puzzleData.stateLock = 1 --活动状态锁 1:正常 2:上锁 在活动展示接口如果为上锁状态说明有异常操作需要回溯 puzzleData.lastedBoxInfo = { boxId = 0,blindBoxContent = 0 } --最近一次解锁的盲盒id,碎片类型 用于回溯开盒操作 local cfgPuzzleTask = skynet.server.gameConfig:GetPlayerAllCfg(player, "JigsawPuzzleTask") for k, v in pairs(cfgPuzzleTask) do -- 任务数据 id , 任务类型 , 进度 , 状态 if v.puzzleId == activityId then puzzleData.puzzleTask[v.id] = { id = v.id, taskType = v.taskType, value = 0, status = dataType.TaskStatus_UnFinish } end end end -- 拼图 展示 function ActivityPuzzle:Show(player, c2sData, s2cData) c2sData.data = assert(pb.decode("C2SActivityJigsawShow", c2sData.data)) local data = {} local puzzleData = player.gameData.activity[self.ActivityType].curData -- 判断一下是否需要初始化玩家数据 if puzzleData == nil or next(puzzleData) == nil then self:InitData(player) puzzleData = player.gameData.activity[self.ActivityType].curData end -- 玩家拼图的相关信息 data.curLevelId = puzzleData.curLevelId data.jigsawProgressStates = {} data.fourDirRewardState = puzzleData.fourDirRewardState data.coreRewardState = puzzleData.coreRewardState data.JigsawPosInfos = {} --活动安全锁进行判断,如果需要回溯执行以下逻辑 if puzzleData.stateLock == 2 then puzzleData.jigsawBlindBoxInfos[puzzleData.lastedBoxInfo.boxId].blindBoxState = 1 if puzzleData.lastedBoxInfo.blindBoxContent == 1 then puzzleData.remainingRandom = puzzleData.remainingRandom + 1 elseif puzzleData.lastedBoxInfo.blindBoxContent == 2 then puzzleData.remainingUniversal = puzzleData.remainingUniversal + 1 end puzzleData.stateLock = 1 end for k, v in pairs(puzzleData.jigsawProgressStates) do table.insert(data.jigsawProgressStates, v) end for k, v in pairs(puzzleData.JigsawPosInfos) do table.insert(data.JigsawPosInfos, v) end s2cData.cmd = pb.enum("MsgType", "CMD_S2C_ActivityJigsawShow") s2cData.data = assert(pb.encode("S2CActivityJigsawShow", data)) end --领取拼图进度奖励 function ActivityPuzzle:GetPuzzleReward(player, c2sData, s2cData) c2sData.data = assert(pb.decode("C2SActivityJigsawRewardGet", c2sData.data)) local data = {} local cfgJigsawPuzzle = skynet.server.gameConfig:GetPlayerAllCfg(player, "JigsawPuzzle") local puzzleData = player.gameData.activity[self.ActivityType].curData data.rewardId = -1 data.levelIdOrFinisType = c2sData.data.levelIdOrFinisType --奖励类型 1拼图完成奖励 2四向拼图奖励或者中心拼图奖励 if c2sData.data.rewardType == 1 then --关卡id或者拼图完成奖励的类型(1四向或2中心) if c2sData.data.levelIdOrFinisType and puzzleData.jigsawProgressStates[c2sData.data.levelIdOrFinisType]==2 then for i, v in pairs(cfgJigsawPuzzle) do if v.activityId == puzzleData.puzzleId and c2sData.data.levelIdOrFinisType == v.levelID then data.rewardId = v.puzzleReward data.levelIdOrFinisType = v.levelID break end end --发放奖励 if data.rewardId ~= -1 then local eventId = pb.enum("EnumMoneyChangeEventID","EventID_129") player:GiveReward( data.rewardId , eventId , 1) --更新奖励获取情况 puzzleData.jigsawProgressStates[c2sData.data.levelIdOrFinisType]=3 --清除红点逻辑 skynet.server.msgTips:Reduce(player, 110) else s2cData.code = errorInfo.ErrorCode.OPFailed end end elseif c2sData.data.rewardType == 2 then if c2sData.data.levelIdOrFinisType == 1 and puzzleData.fourDirRewardState == 1 then --此处处理当关卡最后一块拼图完成时领取上一关卡的奖励问题 if next(puzzleData.JigsawPosInfos)~= nil then puzzleData.fourDirRewardState = 2 for i, v in pairs(cfgJigsawPuzzle) do if v.activityId == puzzleData.puzzleId and puzzleData.curLevelId == v.levelID then data.rewardId = v.aroundPuzzleReward break end end else for i, v in pairs(cfgJigsawPuzzle) do if v.activityId == puzzleData.puzzleId and puzzleData.curLevelId - 1 == v.levelID then data.rewardId = v.aroundPuzzleReward break end end end elseif c2sData.data.levelIdOrFinisType == 2 and puzzleData.coreRewardState ==1 then if next(puzzleData.JigsawPosInfos) ~= nil then puzzleData.coreRewardState = 2 for i, v in pairs(cfgJigsawPuzzle) do if v.activityId == puzzleData.puzzleId and puzzleData.curLevelId == v.levelID then data.rewardId = v.midPuzzleReward break end end else for i, v in pairs(cfgJigsawPuzzle) do if v.activityId == puzzleData.puzzleId and puzzleData.curLevelId - 1 == v.levelID then data.rewardId = v.midPuzzleReward break end end end end if data.rewardId ~= -1 then local eventId = pb.enum("EnumMoneyChangeEventID","EventID_129") player:GiveReward( data.rewardId , eventId , 1) else s2cData.code = errorInfo.ErrorCode.OPFailed end end data.rewardType = c2sData.data.rewardType s2cData.cmd = pb.enum("MsgType", "CMD_S2C_ActivityJigsawRewardGet") s2cData.data = assert(pb.encode("S2CActivityJigsawRewardGet", data)) end --盲盒展示 function ActivityPuzzle:BoxShow(player, c2sData, s2cData) c2sData.data = assert(pb.decode("C2SActivityJigsawBlindBoxShow", c2sData.data)) local data = {} data.jigsawBlindBoxInfos = {} data.jigsawBlindBoxInfos = player.gameData.activity[self.ActivityType].curData.jigsawBlindBoxInfos s2cData.cmd = pb.enum("MsgType", "CMD_S2C_ActivityJigsawBlindBoxShow") s2cData.data = assert(pb.encode("S2CActivityJigsawBlindBoxShow", data)) end --开盲盒 function ActivityPuzzle:OpenBox(player, c2sData, s2cData) c2sData.data = assert(pb.decode("C2SActivityJigsawBlindBoxOpen", c2sData.data)) local puzzleData = player.gameData.activity[self.ActivityType].curData local data = {} if puzzleData.stateLock == 2 then s2cData.code=errorInfo.ErrorCode.OPFailed else if not c2sData.data.blindBoxId or puzzleData.jigsawBlindBoxInfos[c2sData.data.blindBoxId].blindBoxState == nil or puzzleData.jigsawBlindBoxInfos[c2sData.data.blindBoxId].blindBoxState == 2 then s2cData.code=errorInfo.ErrorCode.InvaildOpForCurActivityStatus else --将对应盲盒状态设置成已开启 此处暂不做验证 puzzleData.jigsawBlindBoxInfos[c2sData.data.blindBoxId].blindBoxState=2 data.blindBoxContent = 1 --随机发放1个尚未获得的碎片 if puzzleData.remainingUniversal>0 and puzzleData.remainingRandom>0 then if math.random(puzzleData.remainingUniversal + puzzleData.remainingRandom) > puzzleData.remainingRandom then data.blindBoxContent = 2 puzzleData.remainingUniversal = puzzleData.remainingUniversal - 1 else puzzleData.remainingRandom = puzzleData.remainingRandom - 1 end else if puzzleData.remainingUniversal == 0 then puzzleData.remainingRandom = puzzleData.remainingRandom - 1 else data.blindBoxContent = 2 puzzleData.remainingUniversal = puzzleData.remainingUniversal - 1 end end --加锁并记录操作,用于回溯状态 puzzleData.stateLock = 2 puzzleData.lastedBoxInfo.boxId = c2sData.data.blindBoxId puzzleData.lastedBoxInfo.blindBoxContent = data.blindBoxContent end end s2cData.cmd = pb.enum("MsgType", "CMD_S2C_ActivityJigsawBlindBoxOpen") s2cData.data = assert(pb.encode("S2CActivityJigsawBlindBoxOpen", data)) end --拼图任务展示 function ActivityPuzzle:TaskShow(player, c2sData, s2cData) c2sData.data = assert(pb.decode("C2SActivityJigsawTaskShow", c2sData.data)) local data = {} data.taskInfos = self:GetShowTaskData(player) s2cData.cmd = pb.enum("MsgType", "CMD_S2C_ActivityJigsawTaskShow") s2cData.data = assert(pb.encode("S2CActivityJigsawTaskShow", data)) end --拼图任务领取奖励 function ActivityPuzzle:TaskRewardGet(player, c2sData, s2cData) c2sData.data = assert(pb.decode("C2SActivityJigsawTaskRewardGet", c2sData.data)) local data = {} local puzzletask = player.gameData.activity[self.ActivityType].curData.puzzleTask[c2sData.data.taskId] if puzzletask and puzzletask.status == dataType.TaskStatus_Finish then local cfgPuzzleTask = skynet.server.gameConfig:GetPlayerCurCfg(player, "JigsawPuzzleTask", puzzletask.id) skynet.server.bag:AddGoods(player, dataType.GoodsType_Prop, 31, cfgPuzzleTask.puzzleFragmentReward) puzzletask.status = dataType.TaskStatus_Receive --清除红点逻辑 skynet.server.msgTips:Reduce(player, 112) self:BoxRedGotCheck(player) end data.taskId = c2sData.data.taskId s2cData.cmd = pb.enum("MsgType", "CMD_S2C_ActivityJigsawTaskRewardGet") s2cData.data = assert(pb.encode("S2CActivityJigsawTaskRewardGet", data)) end --解锁指定拼图块 function ActivityPuzzle:ClickPuzzle(player, c2sData, s2cData) c2sData.data = assert(pb.decode("C2SActivityJigsawOnClick", c2sData.data)) local puzzleData = player.gameData.activity[self.ActivityType].curData local data = {} if puzzleData.stateLock == 1 then s2cData.code=errorInfo.ErrorCode.OPFailed else --将前端传来的新解锁拼图坐标信息插入玩家拼图矩阵信息中 此处不做验证,如果需要的话再加上重复/合法性验证 table.insert(puzzleData.JigsawPosInfos,c2sData.data.jigsawPosInfo) --将解锁所需的拼图碎片减去 local cfgPuzzle = skynet.server.gameConfig:GetPlayerAllCfg(player, "JigsawPuzzle") local activityId = skynet.server.activity:GetActivityInfo(player, self.ActivityType) for k , v in pairs(cfgPuzzle) do if v.activityId == activityId and v.levelID == puzzleData.curLevelId then skynet.server.bag:RemoveGoods(player, dataType.GoodsType_Prop, 31, v.puzzleFragmentNum) break end end skynet.server.msgTips:ReduceAll(player, 111) --当前拼图是该关卡最后一块时的逻辑 if #puzzleData.JigsawPosInfos==16 and puzzleData.curLevelId ~=3 then puzzleData.jigsawProgressStates[puzzleData.curLevelId] =2 puzzleData.curLevelId =puzzleData.curLevelId + 1 puzzleData.fourDirRewardState = 1 puzzleData.coreRewardState = 1 puzzleData.JigsawPosInfos = {} puzzleData.remainingUniversal = 2 puzzleData.remainingRandom = 14 puzzleData.jigsawBlindBoxInfos = skynet.server.common:DeepCopy(self.BoxInfosModel) --红点逻辑 skynet.server.msgTips:Add(player, 110) elseif #puzzleData.JigsawPosInfos==16 and puzzleData.curLevelId ==3 then puzzleData.jigsawProgressStates[puzzleData.curLevelId] =2 puzzleData.fourDirRewardState = 1 puzzleData.coreRewardState = 1 --红点逻辑 skynet.server.msgTips:Add(player, 110) end --释放安全锁 puzzleData.stateLock = 1 self:BoxRedGotCheck(player) end s2cData.cmd = pb.enum("MsgType", "CMD_S2C_ActivityJigsawOnClick") s2cData.data = assert(pb.encode("S2CActivityJigsawOnClick", data)) end --拼图任务展示 数据处理 function ActivityPuzzle:GetShowTaskData(player) local data = {} local puzzletask = player.gameData.activity[self.ActivityType].curData.puzzleTask for k, v in pairs(puzzletask) do table.insert(data, { id = v.id, progress = v.value, status = v.status + 1 }) end -- 将完成的任务排到最后 local sortData = {} for k, v in pairs(data) do if dataType.TaskStatus_Finish == v.status -1 then table.insert(sortData, v) end end for k, v in pairs(data) do if dataType.TaskStatus_Receive ~= v.status -1 and dataType.TaskStatus_Finish ~= v.status -1 then table.insert(sortData, v) end end for k, v in pairs(data) do if dataType.TaskStatus_Receive == v.status -1 then table.insert(sortData, v) end end data = sortData return data end --红点检测 function ActivityPuzzle:CheckRedHot( player ) local puzzleData = player.gameData.activity[self.ActivityType].curData local activityId = skynet.server.activity:GetActivityInfo(player, self.ActivityType) local cfgPuzzle = skynet.server.gameConfig:GetPlayerAllCfg(player, "JigsawPuzzle") --拼图进度奖励红点 for k , v in pairs(puzzleData.jigsawProgressStates) do if v == 2 then skynet.server.msgTips:Add(player, 110) end end --盲盒按钮红点 for k , v in pairs(cfgPuzzle) do if v.activityId == activityId and puzzleData.curLevelId == v.levelID and skynet.server.bag:GetGoodsCount(player, dataType.GoodsType_Prop, 31) >= v.puzzleFragmentNum then if puzzleData.jigsawProgressStates[3] < 2 then skynet.server.msgTips:Add(player, 111) break end end end --活动任务红点 for k, v in pairs(player.gameData.activity[self.ActivityType].curData.puzzleTask) do if v.status == dataType.TaskStatus_Finish then skynet.server.msgTips:Add(player, 112) end end end function ActivityPuzzle:BoxRedGotCheck(player) local puzzleData = player.gameData.activity[self.ActivityType].curData local activityId = skynet.server.activity:GetActivityInfo(player, self.ActivityType) local cfgPuzzle = skynet.server.gameConfig:GetPlayerAllCfg(player, "JigsawPuzzle") --盲盒按钮红点 for k , v in pairs(cfgPuzzle) do if v.activityId == activityId and puzzleData.curLevelId == v.levelID and skynet.server.bag:GetGoodsCount(player, dataType.GoodsType_Prop, 31) >= v.puzzleFragmentNum then if puzzleData.jigsawProgressStates[3] < 2 then skynet.server.msgTips:Add(player, 111) break end end end end --注册拼图任务 taskListEvent:Register(onEventFired,"拼图任务") skynet.server.activityPuzzle = ActivityPuzzle return ActivityPuzzle