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 shop = require "Shop" local StyleShop = oo.class(shop) --(推送所有格子信息,单个格子status是未翻开,content必为) StyleShop.shopType = dataType.ShopType_Style StyleShop.GridStatus_NoOpen = 1 --未翻开 StyleShop.GridStatus_AlreadyOpen = 2 --已翻开 StyleShop.GridStatus_AlreadyGain = 3 --已领取 StyleShop.ResourceType_Init = 0 StyleShop.ResourceType_1 = 1 --卷发棒 StyleShop.ResourceType_2 = 2 --粉底刷 StyleShop.ResourceType_3 = 3 --梳子 StyleShop.ResourceType_4 = 4 --刷新 StyleShop.ResourceType_5 = 5 --剪刀 StyleShop.RestoreType_AD = 1 --广告 StyleShop.RestoreType_Volute = 2 --蜗壳币 --格子展示 function StyleShop:GridShow( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SStylingRoomMiniGameShow", c2sData.data )) local data = {} --检查下是否能恢复 self:CheckRestoreEnergy( player ) local cfgSValue = skynet.server.gameConfig:GetPlayerAllCfg( player , "SValue") local cfgStyleProps = skynet.server.gameConfig:GetPlayerAllCfg( player , "StyleProps") local curShop = player.gameData.shop[ self.shopType ] skynet.server.levelTask:Modify( player , 28 , 1 ) skynet.server.taskListEvent:Modify( player , 28 , 1 ) data.grids = self:GetClientAllGrid( player ) data.energy = curShop.energy data.money = curShop.money s2cData.cmd = pb.enum("MsgType","CMD_S2C_StylingRoomMiniGameShow") s2cData.data = assert(pb.encode("S2CStylingRoomMiniGameShow", data)) end --格子刷新 function StyleShop:GridRefresh( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SStylingRoomMiniGameRefresh", c2sData.data )) local data = {} local curShop = player.gameData.shop[ self.shopType ] local isExist = false for k, v in pairs( curShop.grids ) do if self.GridStatus_AlreadyOpen == v.status and self.ResourceType_4 == v.content then --找到对应的才会刷新 curShop.grids = self:GenerateGrid( player ) isExist = true break end end if not isExist then s2cData.code = errorInfo.ErrorCode.ErrRequestParam else data.grids = self:GetClientAllGrid( player ) log.debug(string.format("玩家 %d 造型间 刷新格子", player.userId )) end s2cData.cmd = pb.enum("MsgType","CMD_S2C_StylingRoomMiniGameRefresh") s2cData.data = assert(pb.encode("S2CStylingRoomMiniGameRefresh", data)) end --格子点击 function StyleShop:GridClick( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SStylingRoomMiniGameClick", c2sData.data )) local data = {} local id = c2sData.data.id id = id + 1 if not id or not self:IsVaildGrid( id ) then s2cData.code = errorInfo.ErrorCode.ErrRequestParam else local curShop = player.gameData.shop[ self.shopType ] local nowTime = skynet.GetTime() local isExist = false for k, v in pairs( curShop.grids ) do if id == v.id and self.GridStatus_NoOpen == v.status then --显示资源 local curEnergy = curShop.energy.energy --当前能量 if curEnergy <= 0 then s2cData.code = errorInfo.ErrorCode.NoEnoughMoney else local cfgSValue = skynet.server.gameConfig:GetPlayerAllCfg( player , "SValue") curShop.energy.energy = curShop.energy.energy - 1 --能量扣除 curShop.energy.nextRefillTime = nowTime + self:GetMaxCDTime( player ) v.status = self.GridStatus_AlreadyOpen isExist = true if v.content >= self.ResourceType_1 and v.content <=self.ResourceType_3 then skynet.server.taskListEvent:Modify( player , 14 , 1 ) end log.debug(string.format("玩家 %d 造型间 打开格子 %d 最新能量 %d 下一次刷新时间 %s", player.userId , id , curShop.energy.energy , skynet.server.common:GetStrTime( curShop.energy.nextRefillTime))) end elseif id == v.id and self.GridStatus_AlreadyOpen == v.status and ((v.content >= self.ResourceType_1 and v.content <= self.ResourceType_3) or v.content == self.ResourceType_5) then --搜集资源 v.status = self.GridStatus_AlreadyGain --根据资源类型进行搜集 if self.ResourceType_1 == v.content then curShop.money.resource1 = curShop.money.resource1 + 1 elseif self.ResourceType_2 == v.content then curShop.money.resource2 = curShop.money.resource2 + 1 elseif self.ResourceType_3 == v.content then curShop.money.resource3 = curShop.money.resource3 + 1 elseif self.ResourceType_5 == v.content then local cfgStyleProps = skynet.server.gameConfig:GetPlayerAllCfg( player , "StyleProps") local cfgSValue = skynet.server.gameConfig:GetPlayerAllCfg( player , "SValue") curShop.energy.energy = curShop.energy.energy + cfgStyleProps[ self.ResourceType_5 ].num --剪刀按配置中的数量增加 local maxEnergy = self:GetMaxRestoreEnergy( player ) if curShop.energy.energy > maxEnergy then --大于默认值就按最大值给 curShop.energy.energy = maxEnergy curShop.energy.nextRefillTime = 0 end end if v.content >= self.ResourceType_1 and v.content <=self.ResourceType_3 then skynet.server.levelTask:Modify( player , 54 , 1 ) skynet.server.taskListEvent:Modify( player , 54 , 1 ) end --主动推货币变化信息 local tmpData = {} tmpData.money = {} tmpData.money.resource1 = curShop.money.resource1 tmpData.money.resource2 = curShop.money.resource2 tmpData.money.resource3 = curShop.money.resource3 skynet.server.gameServer:SendMsgToUser( player.userId , "CMD_S2C_StylingRoomMiniGameRes" , tmpData ) isExist = true log.debug(string.format("玩家 %d 造型间 收集格子 %d 物品 物品类型 %d 最新资源 %d %d %d", player.userId , id , v.content , curShop.money.resource1 , curShop.money.resource2 , curShop.money.resource3 )) end end if not isExist then s2cData.code = errorInfo.ErrorCode.ErrRequestParam else data.grid = self:GetClientOneGrid( player , id ) data.energy = curShop.energy skynet.server.msgTips:Reduce(player , 74) end --检查下是否能恢复 self:CheckRestoreEnergy( player ) end s2cData.cmd = pb.enum("MsgType","CMD_S2C_StylingRoomMiniGameClick") s2cData.data = assert(pb.encode("S2CStylingRoomMiniGameClick", data)) end --恢复能量 function StyleShop:RestoreEnergy( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SStylingRoomMiniGameEnergyRefill", c2sData.data )) local data = {} local methodType = c2sData.data.methodType if not methodType then s2cData.code = errorInfo.ErrorCode.ErrRequestParam else local curShop = player.gameData.shop[ self.shopType ] local cfgStyleShop = skynet.server.gameConfig:GetPlayerAllCfg( player , "StyleShop") local cfgSValue = skynet.server.gameConfig:GetPlayerAllCfg( player , "SValue") local isSuc = false local useAcceleratorCoupon = false --玩家是不是使用加速券进行恢复 if methodType == dataType.AccelerateType_Volute then -- 消耗玩家蜗壳币 local eventId = pb.enum("EnumMoneyChangeEventID","EventID_9" ) local nowTime = skynet.GetTime() local time = 0 if skynet.server.luxuryCard:IsActivate( player ) then time = (cfgSValue.styleEnergy * cfgSValue.luxuryCardScissorsModulus - 1 - curShop.energy.energy) * cfgSValue.styleEnergyCdTime * cfgSValue.luxuryCardScissorsCdModulus + curShop.energy.nextRefillTime else time = (cfgSValue.styleEnergy - 1 - curShop.energy.energy) * cfgSValue.styleEnergyCdTime + curShop.energy.nextRefillTime end local needVolute = math.ceil((time - nowTime) / 60 / cfgSValue.timeExchangeVoluteCoin[2] * cfgSValue.timeExchangeVoluteCoin[1]) if -needVolute > 0 then s2cData.cmd = pb.enum("MsgType","CMD_S2C_StylingRoomMiniGameEnergyRefill") s2cData.code = errorInfo.ErrorCode.ErrRequestParam return end if player:MoneyChange( dataType.MoneyType_Volute , -needVolute , eventId) then --使用蜗壳币进行加速 修改相关数据 player.gameData.todayGain.speedUpUseCount = player.gameData.todayGain.speedUpUseCount + 1 if player.gameData.todayGain.speedUpUseCount == cfgSValue.triggerPlantPack[ 1 ] then skynet.server.store:TriggerPack(player , skynet.server.store.TriggerPack_SpeedUp) end isSuc = true else s2cData.code = errorInfo.ErrorCode.NoEnoughMoney end elseif methodType == dataType.AccelerateType_AccTicket and skynet.server.bag:GetGoodsCount(player, dataType.GoodsType_Prop, 6) > 0 then --消耗玩家一个加速券 skynet.server.bag:RemoveGoods(player , dataType.GoodsType_Prop, 6 , 1) useAcceleratorCoupon = true isSuc = true elseif methodType == dataType.AccelerateType_ADTicket and skynet.server.ad:CanWatch(player, "StylingRoomSciRefill") and skynet.server.ad:PayADTicket(player, "StylingRoomSciRefill") then isSuc = true elseif methodType == dataType.AccelerateType_WatchAD and skynet.server.ad:CanWatch(player, "StylingRoomSciRefill") then skynet.server.ad:Update(player, "StylingRoomSciRefill") isSuc = true end local maxEnergy = self:GetMaxRestoreEnergy( player ) --如果是看广告或者蜗壳币直接全部恢复 if isSuc and not useAcceleratorCoupon then --恢复能量 curShop.energy.energy = maxEnergy curShop.energy.nextRefillTime = 0 data.energy = curShop.energy log.debug(string.format("玩家 %d 造型间 恢复能量 恢复类型 %d ", player.userId , methodType )) elseif isSuc and useAcceleratorCoupon then --恢复能量 10/2 curShop.energy.energy = curShop.energy.energy + math.ceil(( cfgSValue.speedCouponTime * 60 ) / self:GetMaxCDTime( player )) data.energy = curShop.energy log.debug(string.format("玩家 %d 造型间 恢复能量 加速券恢复 ", player.userId)) end if curShop.energy.energy >= maxEnergy then skynet.server.msgTips:Reset( player , 74 ) skynet.server.msgTips:Add(player , 74) end end s2cData.cmd = pb.enum("MsgType","CMD_S2C_StylingRoomMiniGameEnergyRefill") s2cData.data = assert(pb.encode("S2CStylingRoomMiniGameEnergyRefill", data)) end --能量展示 function StyleShop:EnergyShow( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SStylingRoomMiniGameEnergyShow", c2sData.data )) local data = {} local curShop = player.gameData.shop[ self.shopType ] data.energy = curShop.energy s2cData.cmd = pb.enum("MsgType","CMD_S2C_StylingRoomMiniGameEnergyShow") s2cData.data = assert(pb.encode("S2CStylingRoomMiniGameEnergyShow", data)) end --造型间展示 function StyleShop:RoomShow( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SStylingDesignRoomShow", c2sData.data )) local data = {} self:CheckRestoreEnergy( player ) skynet.server.levelTask:Modify( player , 28 , 1 ) skynet.server.taskListEvent:Modify( player , 28 , 1 ) local curShop = player.gameData.shop[ self.shopType ] data.currentStyleId = curShop.curStyleId data.rewards = curShop.gainRewards data.money = curShop.money data.energy = curShop.energy s2cData.cmd = pb.enum("MsgType","CMD_S2C_StylingDesignRoomShow") s2cData.data = assert(pb.encode("S2CStylingDesignRoomShow", data)) end --造型间设计 function StyleShop:RoomAttempt( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SStylingDesignRoomAttempt", c2sData.data )) local data = {} local styleId = c2sData.data.styleId if not styleId then s2cData.code = errorInfo.ErrorCode.ErrRequestParam else local curCfgStyleList = skynet.server.gameConfig:GetPlayerCurCfg( player , "StyleList" , styleId ) local curShop = player.gameData.shop[ self.shopType ] local curStyleId = curShop.curStyleId local money = curShop.money if styleId ~= curStyleId then s2cData.code = errorInfo.ErrorCode.ErrRequestParam elseif money.resource1 < curCfgStyleList.res1 or money.resource2 < curCfgStyleList.res2 or money.resource3 < curCfgStyleList.res3 then s2cData.code = errorInfo.ErrorCode.NoEnoughMoney else money.resource1 = money.resource1 - curCfgStyleList.res1 money.resource2 = money.resource2 - curCfgStyleList.res2 money.resource3 = money.resource3 - curCfgStyleList.res3 curShop.curStyleId = self:GetStyleID( player ) data.currentStyleId = curShop.curStyleId data.money = curShop.money if 0 == styleId % 3 then --NPCTask id28的条件有错,应该是要完成StyleList中id为3、6、9、12、15的内容才生效,不是完成任一都生效 skynet.server.levelTask:Modify( player , 62 , 1 ) skynet.server.achieveTask:Modify( player , 62 , 1) skynet.server.npcTask:Modify( player , 62 , 1) skynet.server.taskListEvent:Modify( player , 62 , 1) end skynet.server.taskListEvent:Modify( player , 12 , 1 ) player:AddExpForType( 9 ) log.debug(string.format("玩家 %d 造型间 开始设计 造型ID %d 设计后最新造型ID", player.userId , styleId , curShop.curStyleId)) end end s2cData.cmd = pb.enum("MsgType","CMD_S2C_StylingDesignRoomAttempt") s2cData.data = assert(pb.encode("S2CStylingDesignRoomAttempt", data)) end --领取设计奖励 function StyleShop:RoomReward( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SStylingDesignRewardPrize", c2sData.data )) local data = {} local styleId = c2sData.data.styleId if not styleId or styleId <= 0 then s2cData.code = errorInfo.ErrorCode.ErrRequestParam else local isGain = false local curShop = player.gameData.shop[ self.shopType ] --先检查下领取过该奖励 for k, v in pairs( curShop.gainRewards ) do if styleId == v then isGain = true break end end if isGain then s2cData.code = errorInfo.ErrorCode.AlreadyGet elseif styleId > curShop.curStyleId then s2cData.code = errorInfo.ErrorCode.ErrRequestParam else table.insert( curShop.gainRewards , styleId) --发放奖励 local curCfgStyleList = skynet.server.gameConfig:GetPlayerCurCfg( player , "StyleList" , styleId ) local eventId = pb.enum("EnumMoneyChangeEventID","EventID_82") player:GiveRewardNpc( curCfgStyleList.reward , 5 , eventId) data.styleId = styleId end end s2cData.cmd = pb.enum("MsgType","CMD_S2C_StylingDesignRewardPrize") s2cData.data = assert(pb.encode("S2CStylingDesignRewardPrize", data)) end --检查下能不能恢复体力 function StyleShop:CheckRestoreEnergy( player ) local cfgSValue = skynet.server.gameConfig:GetPlayerAllCfg( player , "SValue") local curShop = player.gameData.shop[ self.shopType ] if not curShop then return end local nowTime = skynet.GetTime() local diffTime = nowTime - curShop.energy.nextRefillTime if 0 == curShop.energy.nextRefillTime or diffTime < 0 then return end local count = math.ceil(diffTime / self:GetMaxCDTime( player )) --计算恢复数量 curShop.energy.energy = curShop.energy.energy + count local maxEnergy = self:GetMaxRestoreEnergy( player ) if curShop.energy.energy >= maxEnergy then curShop.energy.energy = maxEnergy curShop.energy.nextRefillTime = 0 skynet.server.msgTips:Reset( player , 74 ) skynet.server.msgTips:Add(player , 74) else curShop.energy.nextRefillTime = nowTime + self:GetMaxCDTime( player ) --能量恢复时间 end log.debug(string.format("玩家 %d 造型间 检查恢复能量 时间差 %d 恢复时间 %d 秒 恢复数量 %d 最终数量 %d", player.userId , diffTime , self:GetMaxCDTime( player ) , count , curShop.energy.energy)) end --int stylePropsUpdateLimit 2 道具分配权重至多连续n次刷新到同一组 造型室优化 --int stylePropsUpdateRange 5 n次刷新中,3组道具分配权重需要分别被分配1次 --[[ 刷新机制设置保底规则: 玩家连续刷到同一材料分配的概率需≤2次 当玩家达到这个限制时,则下一次刷新则使用另外两组概率的其中一个 在五次刷新中,三组概率至少要分别被刷新1次 ]] --生成随机 function StyleShop:GenerateRand( player ) local cfgSValue = skynet.server.gameConfig:GetPlayerAllCfg( player , "SValue") local randValue = 0 --当前随机值 local randCount = 0 --当前随机值的数量 local curShop = player.gameData.shop[ self.shopType ] if not curShop.randHistoryList then curShop.randHistoryList = {} --随机历史记录 end --获取当前随机数量 local function GetRandCount( rand ) local count = 0 for k, v in pairs( curShop.randHistoryList ) do if rand == v then count = count + 1 end end return count end --随机历史记录数量超过5个,移除第一个 if #curShop.randHistoryList == cfgSValue.stylePropsUpdateRange then table.remove( curShop.randHistoryList, 1 ) end while true do randValue = math.random( 1, 3 ) --随机权重 local randCount = GetRandCount( randValue ) if randCount < cfgSValue.stylePropsUpdateLimit then table.insert( curShop.randHistoryList , randValue ) log.debug(string.format("玩家 %d 造型间 生成随机值 %d 当前随机值数量 %d 生成成功", player.userId, randValue, randCount)) break else log.debug(string.format("玩家 %d 造型间 生成随机值 %d 当前随机值数量 %d 生成失败", player.userId, randValue, randCount)) end end log.debug(string.format("玩家 %d 造型间 随机值历史记录 %d %d %d %d %d", player.userId, curShop.randHistoryList[1] or 0 , curShop.randHistoryList[2] or 0, curShop.randHistoryList[3] or 0, curShop.randHistoryList[4] or 0, curShop.randHistoryList[5] or 0)) return randValue end --生成格子 function StyleShop:GenerateGrid( player ) local cfgStyleProps = skynet.server.gameConfig:GetPlayerAllCfg( player , "StyleProps") local cfgSValue = skynet.server.gameConfig:GetPlayerAllCfg( player , "SValue") local rand = math.random( 1, 3 ) --随机权重 暂时没有需求 self:GenerateRand( player ) --获取三种道具的权重 local curWeight = {} curWeight[ self.ResourceType_1 ] = cfgStyleProps[ self.ResourceType_1 ].updateWeight[ rand ] curWeight[ self.ResourceType_2 ] = cfgStyleProps[ self.ResourceType_2 ].updateWeight[ rand ] curWeight[ self.ResourceType_3 ] = cfgStyleProps[ self.ResourceType_3 ].updateWeight[ rand ] local allWeightCount = curWeight[1] + curWeight[2] + curWeight[3] --计算总权重 local materialCount = cfgSValue.styleProbsUpdateNum local goodsCount = materialCount[1] + materialCount[ 2 ] --总共道具数量 local material = {} --材料 --根据权重随机16种材料 local sText = "" for i = 1, materialCount[ 1 ], 1 do rand = math.random(1,allWeightCount) local tmp = 0 local index = 0 --当前生成的材料 for j = self.ResourceType_1, self.ResourceType_3, 1 do tmp = tmp + curWeight[ j ] if rand <= tmp then index = j break end end sText = sText.." "..index table.insert( material , index) end --根据配置数量将刷新材料放进去 for i = 1, materialCount[ 2 ], 1 do table.insert( material , self.ResourceType_4 ) sText = sText.." " sText = sText..self.ResourceType_4 end --剪刀需要一定的概率刷出 local prob = cfgStyleProps[ 5 ].updateProbability * 100 rand = math.random(1,100) if rand <= prob then table.insert( material , self.ResourceType_5 ) sText = sText.." " sText = sText..self.ResourceType_5 goodsCount = goodsCount + 1 end log.debug(string.format("玩家 %d 造型间 生成道具信息 %s", player.userId , sText )) --默认42个格子 local grids = {} local tmpGrids = {} for i = 1, 42, 1 do grids[ i ] = {} grids[ i ].id = i grids[ i ].content = 0 grids[ i ].status = self.GridStatus_NoOpen table.insert( tmpGrids , {id = i}) end --生成17个格子位置 sText = "" local randGridsIndex = skynet.server.shop:GetNoRepeatGoods( goodsCount , tmpGrids ) for k, v in pairs( randGridsIndex ) do grids[ v ].content = material[ k ] sText = sText.." 格子ID "..v.." 道具ID "..grids[ k ].content end log.debug(string.format("玩家 %d 造型间 最终生成格子信息 %s", player.userId , sText )) return grids end --是否有效的格子 function StyleShop:IsVaildGrid( id ) if id < 1 or id > 42 then return false end return true end --获取单个格子 function StyleShop:GetClientOneGrid( player , id ) local curShop = player.gameData.shop[ self.shopType ] local data = {} local curGrid = curShop.grids[ id ] if self.GridStatus_AlreadyOpen == curGrid.status then --打开状态才发真实数据 data = { id = curGrid.id - 1, content = curGrid.content , status = curGrid.status } else --未打开状态内容填0 data = { id = curGrid.id - 1, content = 0 , status = curGrid.status } end return data end --获取所有格子 function StyleShop:GetClientAllGrid( player ) local curShop = player.gameData.shop[ self.shopType ] local data = {} for k, v in pairs( curShop.grids ) do if self.GridStatus_AlreadyOpen == v.status then --打开状态才发真实数据 table.insert( data , { id = v.id -1, content = v.content , status = v.status }) else --未打开状态内容填0 table.insert( data , { id = v.id -1, content = 0 , status = v.status }) end end return data end --获取当前的造型ID function StyleShop:GetStyleID( player ) local cfgStyleList = skynet.server.gameConfig:GetPlayerAllCfg( player , "StyleList") local cfgCount = #cfgStyleList local curShop = player.gameData.shop[ self.shopType ] curShop.curStyleId = curShop.curStyleId + 1 if curShop.curStyleId > cfgCount then curShop.curStyleId = cfgCount + 1 end return curShop.curStyleId end --获取最大恢复能量 function StyleShop:GetMaxRestoreEnergy( player ) local cfgSValue = skynet.server.gameConfig:GetPlayerAllCfg( player , "SValue") local maxEnergy = cfgSValue.styleEnergy if skynet.server.luxuryCard:IsActivate( player ) then maxEnergy = maxEnergy * cfgSValue.luxuryCardScissorsModulus end return maxEnergy end --获取最大的CD时间 function StyleShop:GetMaxCDTime( player ) local cfgSValue = skynet.server.gameConfig:GetPlayerAllCfg( player , "SValue") local cdTime = cfgSValue.styleEnergyCdTime * skynet.server.store:GetTimeCoefficient(player , 5 ) --造型室单个体力恢复时间 * 普通月卡的CD系数 if skynet.server.luxuryCard:IsActivate( player ) then --如果也开通了豪华月卡,再进行一个打折 cdTime = cdTime * cfgSValue.luxuryCardScissorsCdModulus end return math.ceil( cdTime ) end skynet.server.styleShop = StyleShop return StyleShop