HomeServer/Server/AllServer/GameServer/Activity/ActivityPuzzle.lua
2024-11-20 15:41:37 +08:00

468 lines
21 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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