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 Flowerpot = oo.class() Flowerpot.OpType_GetAllFlowerpotInfo = 1 --获取花盆信息 Flowerpot.OpType_Flowerpot = 2 --种植 Flowerpot.OpType_Shovel = 3 --铲除 Flowerpot.OpType_Fertilize = 4 --施肥 function Flowerpot:Init() end --花盆展示信息 function Flowerpot:Show( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SFlowerpotShow", c2sData.data )) local data = {} --先刷新一遍所有花盆信息 self:RefreshFlowerpot( player ) data.flowerpotInfo = self:GetAllFlowerpot( player ) s2cData.cmd = pb.enum("MsgType","CMD_S2C_FlowerpotShow") s2cData.data = assert(pb.encode("S2CFlowerpotShow", data)) end --花盆种植 function Flowerpot:Plant( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SFlowerpotPlant", c2sData.data )) local data = {} local flowerpotId = c2sData.data.flowerpotId local goodsType = c2sData.data.goodsType local goodsId = c2sData.data.goodsId if not flowerpotId or not goodsType or not goodsId then s2cData.code = errorInfo.ErrorCode.ErrRequestParam else --背包是否有相应的物品 可能种子或植物 local isExistFlowerpot = self:PutHouse( player , flowerpotId , nil ) local isExistGoods = player:IsBuyGoods( goodsType , goodsId ) log.info(string.format("玩家 %d 花盆 准备种植 花盆ID %d 种子ID %d 是否存在花盆 %s 是否存在种子 %s", player.userId , flowerpotId , goodsId , isExistFlowerpot , isExistGoods)) if isExistFlowerpot and isExistGoods then --播下种子或植物 self:StartPlant( player , flowerpotId , goodsType , goodsId ) else s2cData.code = errorInfo.ErrorCode.NoExistFlowerpotOrSeed end end data.flowerpotInfo = self:GetAllFlowerpot( player ) s2cData.cmd = pb.enum("MsgType","CMD_S2C_FlowerpotPlant") s2cData.data = assert(pb.encode("S2CFlowerpotPlant", data)) end --花盆铲除 function Flowerpot:Shovel( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SFlowerpotShovel", c2sData.data )) local data = {} local flowerpotId = c2sData.data.flowerpotId if not flowerpotId then s2cData.code = errorInfo.ErrorCode.ErrRequestParam else data.flowerpotInfo = {} for k, v in pairs( player.gameData.flowerpot ) do --找到指定花盆ID并且没有被种植 if dataType.GoodsType_Flowerpot == v.type and flowerpotId == v.id then if self:IsGrowUp( v.flowerpotInfo ) then v.flowerpotInfo.status = dataType.FlowerpotStatus_Empty --成长植物,铲除后就是空盆,植物消失 elseif self:IsRipe( v.flowerpotInfo ) then v.flowerpotInfo.status = dataType.FlowerpotStatus_Empty --成熟植物,铲除后就是空盆 skynet.server.bag:AddGoods( player , dataType.GoodsType_Plant , v.flowerpotInfo.plantId , 1 ) --植物放背包 if dataType.GoodsType_Seed == v.flowerpotInfo.plantType then skynet.server.dailyTask:Modify( player , 18 , 1) skynet.server.achieveTask:Modify( player , 18 , 1 ) end end --铲除后还原 v.flowerpotInfo.plantId = 0 v.flowerpotInfo.nextStatusTime = 0 v.flowerpotInfo.startPlantTime = 0 --后面加的 break end end end data.flowerpotInfo = self:GetAllFlowerpot( player ) s2cData.cmd = pb.enum("MsgType","CMD_S2C_FlowerpotShovel") s2cData.data = assert(pb.encode("S2CFlowerpotShovel", data)) end --花盆施肥 function Flowerpot:Fertilize( player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SFlowerpotFertilize", c2sData.data )) local data = {} local flowerpotId = c2sData.data.flowerpotId if not flowerpotId then s2cData.code = errorInfo.ErrorCode.ErrRequestParam else data.flowerpotInfo = {} local cfgSValue = skynet.server.gameConfig.SValue if not player:MoneyChange( dataType.MoneyType_Volute , -cfgSValue.plantGrowupCost ) then s2cData.code = errorInfo.ErrorCode.NoEnoughMoney else log.info(string.format("玩家 %d 花盆 施肥 花盆ID %d " , player.userId , flowerpotId)) for k, v in pairs( player.gameData.flowerpot ) do --找到指定花盆ID并且没有被种植 if dataType.GoodsType_Flowerpot == v.type and flowerpotId == v.id then if dataType.FlowerpotStatus_Seed == v.flowerpotInfo.status or dataType.FlowerpotStatus_Sprout == v.flowerpotInfo.status then --计算扣除时间,以免重新登录进来会以种植时间算状态 local reduceTime = 0 local curCfgPlant = skynet.server.gameConfig:GetCurPlantCfg( v.flowerpotInfo.plantId ) local growTime = skynet.server.gameConfig.SValue.plantGrowTimeRatio if dataType.FlowerpotStatus_Seed == v.flowerpotInfo.status then --种子 reduceTime = ( curCfgPlant.coin * growTime[1]) * 60 --((出售价格 * 系数) = 分钟数) * 60秒 = 所需要的秒数 reduceTime = reduceTime + ( curCfgPlant.coin * growTime[2]) * 60 elseif dataType.FlowerpotStatus_Sprout == v.flowerpotInfo.status then --发芽 --reduceTime = ( curCfgPlant.coin * growTime[1]) * 60 reduceTime = reduceTime + ( curCfgPlant.coin * growTime[2]) * 60 end v.flowerpotInfo.startPlantTime = v.flowerpotInfo.startPlantTime - reduceTime --种子和发芽切换到花苞状态 v.flowerpotInfo.status = dataType.FlowerpotStatus_Bud v.flowerpotInfo.nextStatusTime = self:GetNextStatusTime( v.flowerpotInfo.plantId , dataType.FlowerpotStatus_Sprout) elseif dataType.FlowerpotStatus_Bud == v.flowerpotInfo.status then self:ModifyRipeFlowerpot( player , v) end break end end end end data.flowerpotInfo = self:GetAllFlowerpot( player ) s2cData.cmd = pb.enum("MsgType","CMD_S2C_FlowerpotFertilize") s2cData.data = assert(pb.encode("S2CFlowerpotFertilize", data)) end --刷新花盆 function Flowerpot:RefreshFlowerpot( player ) for k, v in pairs( player.gameData.flowerpot ) do if dataType.GoodsType_Flowerpot == v.type and 0 ~= v.flowerpotInfo.startPlantTime then v.flowerpotInfo.status , v.flowerpotInfo.nextStatusTime = self:GetStatusAndTime( v.flowerpotInfo.plantId , v.flowerpotInfo.startPlantTime) --直接成熟 if dataType.FlowerpotStatus_Ripe == v.flowerpotInfo.status then self:ModifyRipeFlowerpot( player , v) end end end end --获取当前状态和时间 function Flowerpot:GetStatusAndTime( plantId , startPlantTime ) if 0 == startPlantTime then return dataType.FlowerpotStatus_Empty , 0 end local growTime = skynet.server.gameConfig.SValue.plantGrowTimeRatio local curCfgPlant = skynet.server.gameConfig:GetCurCfg( "Plant" , plantId ) local moneyCount = curCfgPlant.coin local allTime = 0 --当前状态是种子 local status = dataType.FlowerpotStatus_Seed local nextStatusTime = startPlantTime + ( moneyCount * growTime[ 1 ]) * 60 for i = 1, 3, 1 do allTime = allTime + ( moneyCount * growTime[ i ]) * 60 if skynet.GetTime() >= startPlantTime + allTime then if 1 == i then --发芽 status = dataType.FlowerpotStatus_Sprout nextStatusTime = startPlantTime + allTime + ( moneyCount * growTime[ 2 ]) * 60 elseif 2 == i then --花苞 status = dataType.FlowerpotStatus_Bud nextStatusTime = startPlantTime + allTime + ( moneyCount * growTime[ 3 ]) * 60 elseif 3 == i then --成熟 status = dataType.FlowerpotStatus_Ripe nextStatusTime = 0 end end end return status , nextStatusTime end --获取下一个状态的时间 function Flowerpot:GetNextStatusTime( plantId , status ) local growTime = skynet.server.gameConfig.SValue.plantGrowTimeRatio local nextStatusTime = 0 local curCfgPlant = skynet.server.gameConfig:GetCurPlantCfg( plantId ) if dataType.FlowerpotStatus_Seed == status then --种子 nextStatusTime = skynet.GetTime() + ( curCfgPlant.coin * growTime[1]) * 60 --((出售价格 * 系数) = 分钟数) * 60秒 = 所需要的秒数 elseif dataType.FlowerpotStatus_Sprout == status then --发芽 nextStatusTime = skynet.GetTime() + ( curCfgPlant.coin * growTime[2]) * 60 elseif dataType.FlowerpotStatus_Bud == status then --花苞 nextStatusTime = skynet.GetTime() + ( curCfgPlant.coin * growTime[3]) * 60 end return nextStatusTime end --是否空盆 function Flowerpot:IsEmpty( flowerpotInfo ) if flowerpotInfo.status == dataType.FlowerpotStatus_Empty then return true end return false end --是否成长阶段 function Flowerpot:IsGrowUp( flowerpotInfo ) if flowerpotInfo.status >= dataType.FlowerpotStatus_Seed and flowerpotInfo.status <= dataType.FlowerpotStatus_Bud then return true end return false end --是否成熟 function Flowerpot:IsRipe( flowerpotInfo ) if flowerpotInfo.status == dataType.FlowerpotStatus_Ripe then return true end return false end --生成植物 function Flowerpot:GeneratePlant( seedId ) local data = {} local cfgSeed = skynet.server.gameConfig.Seed local cfgPlant = skynet.server.gameConfig.Plant --仅有植物类型的配置 local cfgOnlyPlant = {} for k, v in pairs(cfgPlant) do if dataType.PlantType_Flower == v.type and 125 ~= v.id then --流泉枫不能通过奇异种子种出 table.insert( cfgOnlyPlant , v ) end end --检查是否为奇异种子 local isSpecialSeed = false for k, v in pairs( cfgSeed ) do if seedId == v.id and 0 == v.ripeId then isSpecialSeed = true break end end if isSpecialSeed then --奇异种子 --奇异种子概率(花卉45%、果蔬45%,其他特有植物10%)暂时没做,全部生成果蔬 local minIndex = 1 local maxIndex = #cfgOnlyPlant local randIndex = math.random( minIndex , maxIndex ) if cfgOnlyPlant[ randIndex ] then log.info(string.format("奇异种子成功获取植物 %d 随机值索引 %d 索引范围( 1 - %d )" , cfgOnlyPlant[ randIndex ].id , randIndex, maxIndex)) return cfgOnlyPlant[ randIndex ].id end else --普通种子 --稀有概率5%、罕见概率15%、普通概率80% local count={} for i = 1, 3, 1 do count[i] = 0 end for k1, v1 in pairs( cfgSeed ) do if seedId == v1.id then for k2, v2 in pairs( cfgPlant ) do if v1.shopType == v2.shopType and v1.ripeId == v2.subType then table.insert( data , { plantId = v2.id , quality = v2.quality , shopType = v2.shopType }) if skynet.server.shop.FlowerpotLevel_Common == v2.quality then count[1] = count[1] +1 elseif skynet.server.shop.FlowerpotLevel_Special == v2.quality then count[2] = count[2] +1 elseif skynet.server.shop.FlowerpotLevel_Rare == v2.quality then count[3] = count[3] +1 end end end end end --每种总概率 / 每种总数量 local common = math.floor(8000 / count[1]) local special = math.floor(1500 / count[2]) local rare = math.floor(500 / count[3]) --设置概率 for k, v in pairs( data ) do if skynet.server.shop.FlowerpotLevel_Common == v.quality then data[ k ].ratio = common log.info(string.format("植物 %d 稀有度 %d 概率值 %d", v.plantId , v.quality, v.ratio )) elseif skynet.server.shop.FlowerpotLevel_Special == v.quality then data[ k ].ratio = special log.info(string.format("植物 %d 稀有度 %d 概率值 %d", v.plantId , v.quality, v.ratio )) elseif skynet.server.shop.FlowerpotLevel_Rare == v.quality then data[ k ].ratio = rare log.info(string.format("植物 %d 稀有度 %d 概率值 %d", v.plantId , v.quality, v.ratio )) end end --随机 local rand = math.random(1,10000) local ratio = 0 for k, v in pairs( data ) do if 3 == v.shopType then log.info(string.format("特殊种子成功获取植物 %d 随机值 %d 当前概率值 %d" , v.plantId , rand, ratio)) return v.plantId else ratio = ratio + v.ratio if rand <= ratio then log.info(string.format("普通种子成功获取植物 %d 随机值 %d 当前概率值 %d" , v.plantId , rand, ratio)) return v.plantId end end end end return 1 end --种到花盆 function Flowerpot:StartPlant( player , flowerpotId , goodsType , seedId ) local flowerpotInfo = {} for k, v in pairs( player.gameData.flowerpot ) do --找到指定花盆ID并且没有被种植 if flowerpotId == v.id and dataType.FlowerpotStatus_Empty == v.flowerpotInfo.status then if dataType.GoodsType_Seed == goodsType then --播下种子 v.flowerpotInfo.plantId = self:GeneratePlant( seedId ) v.flowerpotInfo.startPlantTime = skynet.GetTime() v.flowerpotInfo.status , v.flowerpotInfo.nextStatusTime = self:GetStatusAndTime( v.flowerpotInfo.plantId , v.flowerpotInfo.startPlantTime ) --种出水生植物就+1 local cfgGoods = skynet.server.gameConfig:GetPlantCfg( v.flowerpotInfo.plantId ) if dataType.PlantType_AquaticPlant == cfgGoods.type then skynet.server.levelTask:Modify( player , 53 , 1 ) end for k, v in pairs( skynet.server.gameConfig.Seed ) do --只有植物小铺才能完成 if seedId == v.id and skynet.server.shop.FlowerpotShopType_Plant == v.shopType then skynet.server.levelTask:Modify( player , 46 , 1 ) break end end log.info(string.format("玩家 %d 花盆 开始种植种子 花盆ID %d 花盆状态 %d 植物ID %d 种植时间 %d 下一状态时间 %d", player.userId , flowerpotId , v.flowerpotInfo.status , v.flowerpotInfo.plantId , v.flowerpotInfo.startPlantTime , v.flowerpotInfo.nextStatusTime )) elseif dataType.GoodsType_Plant == goodsType then --种下植物 v.flowerpotInfo.status = dataType.FlowerpotStatus_Ripe v.flowerpotInfo.plantId = seedId v.flowerpotInfo.nextStatusTime = 0 log.info(string.format("玩家 %d 花盆 开始种植植物 花盆ID %d 花盆状态 %d 植物ID %d ", player.userId , flowerpotId , v.flowerpotInfo.status , v.flowerpotInfo.plantId )) end v.flowerpotInfo.plantType = goodsType --记录下种植类型 table.insert( flowerpotInfo , v ) --删除种子或者植物buy skynet.server.bag:RemoveGoods( player , goodsType , seedId , 1) break end end return flowerpotInfo end --花盆放置房间 function Flowerpot:PutHouse( player , flowerpotId , furnitureInfo ) local isExistFlowerpot = false for k1, v1 in pairs( player.gameData.flowerpot ) do --花盆已经存在,找到对应的花盆 if flowerpotId == v1.id then isExistFlowerpot = true local houseId = player.gameData.curHouseID local schemeId = player.gameData.house[ houseId ].curSchemeId --找一下是否有该房间和方案的位置信息 local isExistNowPos = false for k2, v2 in pairs( v1.nowPos) do if houseId == v2.houseId and schemeId == v2.schemeId then isExistNowPos = true break end end --没有该房间和方案的位置信息,就初始化个位置信息 if not isExistNowPos then --初始化花盆 if nil == furnitureInfo then table.insert( v1.nowPos , { houseId = houseId , schemeId = schemeId , x = 10000, y = 10000 , isPutInFurniture = false } ) else local nowPos = furnitureInfo.nowPos table.insert( v1.nowPos , { houseId = houseId , schemeId = schemeId , x = nowPos.x , y = nowPos.y , isPutInFurniture = furnitureInfo.isPutInFurniture } ) end end break end end if not isExistFlowerpot then --花盆列表中没有花盆,看背包有不朋,有就就初始化一个 local flowerpotType = dataType.GoodsType_Flowerpot if player:IsBuyGoods( flowerpotType , flowerpotId ) then --获取当前房间数据 local houseId = player.gameData.curHouseID local schemeId = player.gameData.house[ houseId ].curSchemeId --初始化花盆 if nil == furnitureInfo then furnitureInfo = {} furnitureInfo.nowPos = {} table.insert( furnitureInfo.nowPos , { houseId = houseId , schemeId = schemeId , x = 10000, y = 10000 , isPutInFurniture = false } ) else local nowPos = furnitureInfo.nowPos furnitureInfo.nowPos = {} table.insert( furnitureInfo.nowPos , { houseId = houseId , schemeId = schemeId , x = nowPos.x , y = nowPos.y , isPutInFurniture = furnitureInfo.isPutInFurniture} ) end furnitureInfo.type = flowerpotType furnitureInfo.id = flowerpotId furnitureInfo.rotateType = 0 furnitureInfo.isPutInFurniture = false furnitureInfo.clickType = 1 furnitureInfo.flowerpotInfo = {} furnitureInfo.flowerpotInfo.status = dataType.FlowerpotStatus_Empty furnitureInfo.flowerpotInfo.plantId = 0 furnitureInfo.flowerpotInfo.nextStatusTime = 0 furnitureInfo.flowerpotInfo.startPlantTime = 0 --开始种植时间 table.insert( player.gameData.flowerpot , furnitureInfo ) isExistFlowerpot = true end end return isExistFlowerpot end --花盆放置背包 function Flowerpot:PutBag( player , furnitureInfo ) local flowerpotId = furnitureInfo.id --在花盆列表中检查是否有花盆 for k, v in pairs( player.gameData.flowerpot ) do if flowerpotId == v.id then if self:IsRipe( v.flowerpotInfo ) then skynet.server.bag:AddGoods( player , dataType.GoodsType_Plant , v.flowerpotInfo.plantId , 1 ) --成熟盆植物放背包 --只有种子才能完成该任务 if dataType.GoodsType_Seed == v.flowerpotInfo.plantType then skynet.server.dailyTask:Modify( player , 18 , 1) skynet.server.achieveTask:Modify( player , 18 , 1 ) end end v.flowerpotInfo.plantId = 0 v.flowerpotInfo.status = dataType.FlowerpotStatus_Empty v.flowerpotInfo.nextStatusTime = 0 v.flowerpotInfo.startPlantTime = 0 furnitureInfo.flowerpotInfo= {} furnitureInfo.flowerpotInfo.plantId = 0 furnitureInfo.flowerpotInfo.status = dataType.FlowerpotStatus_Empty furnitureInfo.flowerpotInfo.nextStatusTime = 0 local houseId = player.gameData.curHouseID local schemeId = player.gameData.house[ houseId ].curSchemeId for k1, v1 in pairs( v.nowPos ) do if houseId == v1.houseId and schemeId == v1.schemeId then table.remove( v.nowPos , k1) break end end log.info(string.format("玩家 %d 花盆 %d 放置背包 ", player.userId , flowerpotId )) return true end end return false end --获取当前房间当前方案所有花盆信息 function Flowerpot:GetFlowerpot( player , flowerpotInfo ) local houseId = player.gameData.curHouseID local schemeId = player.gameData.house[ houseId ].curSchemeId local furnitureInfo = nil local isExist = false for k, v in pairs( flowerpotInfo.nowPos ) do --当前房间和当前方案下的花盆位置 if houseId == v.houseId and schemeId == v.schemeId then furnitureInfo = {} --将当前花盆的基本信息拷贝过来 for k, v in pairs( flowerpotInfo ) do furnitureInfo[ k ] = v end furnitureInfo.furnitureInfo = nil --这个值不传客户端去 furnitureInfo.nowPos = {} furnitureInfo.nowPos.x = v.x furnitureInfo.nowPos.y = v.y furnitureInfo.isPutInFurniture = v.isPutInFurniture or false break end end --log.info("GetFlowerpot" ,houseId ,schemeId, skynet.server.common:TableToString(furnitureInfo)) return furnitureInfo end --获取当前房间当前方案所有花盆信息 function Flowerpot:GetAllFlowerpot( player ) local flowerpotInfo = {} for k, v in pairs( player.gameData.flowerpot ) do local temp = self:GetFlowerpot( player , v ) if temp then table.insert( flowerpotInfo , temp ) --log.info("GetAllFlowerpot" , skynet.server.common:TableToString(temp)) log.info(string.format("玩家 %d 花盆 获取花盆信息 花盆ID %d 状态 %d 植物ID %d 种植时间 %s 下一状态时间 %s " , player.userId , temp.id , temp.flowerpotInfo.status , temp.flowerpotInfo.plantId , skynet.server.common:GetStrTime(temp.flowerpotInfo.startPlantTime) , skynet.server.common:GetStrTime(temp.flowerpotInfo.nextStatusTime) )) end end return flowerpotInfo end --更新当前房间当前方案花盆位置 function Flowerpot:UpdateFlowerpotPos( player , houseId , schemeId , flowerpotId , x , y , isPutInFurniture ) for k1, v1 in pairs( player.gameData.flowerpot ) do if flowerpotId == v1.id then for k2, v2 in pairs( v1.nowPos ) do if houseId == v2.houseId and schemeId == v2.schemeId then v2.x = x v2.y = y v2.isPutInFurniture = isPutInFurniture --log.info(string.format("玩家 %d 花盆 更新花盆位置 花盆ID %d 房间ID %d 方案ID %d 坐标( %f , %f ) 是否在其它家具上 %s" , player.basicInfo.userID , flowerpotId ,houseId , schemeId , x , y , isPutInFurniture )) return true end end end end return false end --修改花盆为成熟盆 function Flowerpot:ModifyRipeFlowerpot( player , v ) --种出水生植物就+1 local cfgGoods = skynet.server.gameConfig:GetPlantCfg( v.flowerpotInfo.plantId ) if dataType.PlantType_AquaticPlant == cfgGoods.type then player.gameData.aquaticPlantCount = player.gameData.aquaticPlantCount + 1 end player.gameData.plantCount = player.gameData.plantCount + 1 v.flowerpotInfo.status = dataType.FlowerpotStatus_Ripe v.flowerpotInfo.nextStatusTime = 0 --成熟后,没有下一个状态 v.flowerpotInfo.startPlantTime = 0 skynet.server.illustration:Add( player , dataType.GoodsType_Plant , v.flowerpotInfo.plantId ) skynet.server.levelTask:Modify( player , dataType.GeneralTaskType_HarvestPlant , 1 ) skynet.server.passCheck:Modify( player , 8 , 1 ) end --检查是否存在花盆位置 function Flowerpot:CheckExistFlowerpot( player ) for k, v in pairs( player.gameData.flowerpot ) do if not self:IsEmpty( v.flowerpotInfo ) then --如果有成熟盆,就要新的方案中显示花盆 local houseId = player.gameData.curHouseID local schemeId = player.gameData.house[ houseId ].curSchemeId --找一下是否有该房间和方案的位置信息 local isExistNowPos = false for k2, v2 in pairs( v.nowPos ) do if houseId == v2.houseId and schemeId == v2.schemeId then isExistNowPos = true break end end --没有该房间和方案的位置信息,就初始化个位置信息 if not isExistNowPos then --初始化花盆 log.info(string.format("玩家 %d 花盆 初始花盆位置 花盆ID %d 房间ID %d 方案ID " , player.basicInfo.userID , v.id , houseId , schemeId )) table.insert( v.nowPos , { houseId = houseId , schemeId = schemeId , x = 10000, y = 10000 , isBag = false } ) end end end end skynet.server.flowerpot = Flowerpot return Flowerpot