Diner.lua 11.5 KB
local Diner = class("Diner", require("shared.ModelBase"))

function Diner:ctor(properties)
	Diner.super.ctor(self, properties)
end

Diner.schema = {
	buildL 	= {"string", ""},			-- 家具等级 1=1 2=1 3=1
	order 	= {"string", "[]"},			-- 特殊订单
	sells 	= {"string", "[]"},			-- 贩卖位置
	dishTree	= {"string", "1=1 101=1 201=1"},		-- 料理天赋
	skillTree	= {"string", ""},		-- 支援天赋
	popular = {"number",0},          	-- 累计人气
	expedite = {"number",1},         	--每日加速次数
	gfood = {"table", {}},			-- 愿望食材 {{id = 123, st = 1232144},}
	task = {"table", {}}, -- 任务刷新 {et =  消失时间  id = 任务id, refuse = 0}
	entrustB = {"table", {}}, -- 委托完成过的记录 {id = 1} 
	entrust = {"table", {}}, -- 委托 {id, id, id}
	customer = {"table", {}}, -- 解锁的顾客 {id = 1}  -- 1 (已解锁) 0(达成条件 可解锁 服务器用)
	comboStatus = {"table", {}}, -- 组合领取奖励状态 {id = -1} --有表示已经领取奖励
}

function Diner:rankResetData(notify)
	self:updateProperty({field = "popular", value = 0, notNotify = not notify})
end

function Diner:refreshDailyData(notify)

	-- 委托
	local entrust = self:getProperty("entrust")
	local entrustB = self:getProperty("entrustB")
	local had = {}
	local pool = {}
	local change = false
	for i = 1, 3 do
		if not entrust[i] then
			if not next(pool) then
				for id, data in pairs(csvdb["diner_missionCsv"]) do
					local show = true
					if data.show ~= "" then
						-- 不填=默认刷出,1=达成前置任务,2=通关关卡
						local showC = data.show:toArray(true, "=")
						if showC[1] == 2 then
							if not self.owner:checkHangPass(showC[2]) then
								show = false
							end
						elseif showC[1] == 1 then
							if not entrustB[showC[2]] then
								show = false
							end
						end
					end
					if show then
						table.insert(pool, {id, data.chance})
					end
				end
			end

			if #pool > 0 then
				local idx = math.randWeight(pool, 2)
				entrust[i] = pool[idx][1]
				change = true
				table.remove(pool, idx)
			end
			if not next(pool) then
				break
			end
		else
			had[entrust[i]] = 1
		end
	end

	if self.owner:getProperty("funcGuide"):getv(51,0) == 0 or (not self.owner:checkOverGuide(27) and self.owner:checkOverGuide(25)) then
		entrust[1] = 1001
		entrust[2] = 1
	elseif not self.owner:checkOverGuide(29,4) and self.owner:checkOverGuide(29) then
		local temp = entrust[1]
		entrust[1] = 1
		entrust[2] = temp
	end

	self:updateProperty({field = "entrust", value = entrust, notNotify = not notify})

	-- 每日加速次数
	self:updateProperty({field = "expedite", value = 1, notNotify = not notify})
	-- 特殊订单
	local orders = json.decode(self:getProperty("order"))
	local hadTask = {}
	local needCount = globalCsv.diner_task_count
	for idx, temp in pairs(orders) do
		if temp.lock ~= 0 then
			hadTask[temp.id] = 1
			needCount = needCount - 1
		end
	end

	if needCount <= 0 then return end

	-- 等级由订单板等级决定
	local taskLevel = self:getProperty("buildL"):getv(5, 1)
	local taskData = csvdb["diner_questCsv"][taskLevel]
	if not taskData then return end
	local pool = {}
	local dishTree = self:getProperty("dishTree")
	for id, temp in pairs(taskData) do
		local unlock = true
		for _, front in ipairs(temp.front:toArray(true, "=")) do
			if dishTree:getv(front, 0) == 0 then
				unlock = false
				break
			end
		end
		if not hadTask[id] and unlock then
			table.insert(pool, temp)
		end
	end
	local needCount = math.min(#pool, needCount) -- 需要的任务个数

	for idx = 1, globalCsv.diner_task_count do
		local order = orders[idx]
		if not order or order.lock == 0 then
			if needCount > 0 then
				local index = math.randWeight(pool, "chance")
				local data = pool[index]
				orders[idx] = {lv = taskLevel, id = data.id, n = 0, lock = 0, status = 0}
				needCount = needCount - 1
				table.remove(pool, index)
			end
		end
	end

	self:updateProperty({field = "order", value = json.encode(orders), notNotify = not notify})
end

function Diner:updateProperty(params)
	params = params or {}
	if not self.schema[params.field] then
		return
	end
	local oldValue = self:getProperty(params.field)
	if params.value then
		self:setProperty(params.field, params.value)
	elseif params.delta then
		self:incrProperty(params.field, params.delta)
	else
		return
	end
	local newValue = self:getProperty(params.field)
	if not params.notNotify then
		self:notifyUpdateProperty(params.field, newValue, oldValue)
	end
end

function Diner:notifyUpdateProperty(field, newValue, oldValue)
	local datas = {
		key = field,
		newValue = newValue,
		oldValue = oldValue,
	}
	SendPacket(actionCodes.Diner_updateProperty, MsgPack.pack(datas))
end

function Diner:checkDinerTask(typ, count, param1, param2, notNotify)
	local orders = json.decode(self:getProperty("order"))
	local dirty = false
	for k, order in ipairs(orders) do
		local taskSet = csvdb["diner_questCsv"][order.lv]
		if taskSet and taskSet[order.id] then
			local data = taskSet[order.id]
			if data.type == typ and data.condition1 == param1 and order.status == 1 then
				orders[k].n = orders[k].n + count
				dirty = true
			end
		end
	end
	if dirty then
		self:updateProperty({field = "order", value = json.encode(orders), notNotify = notNotify})
	end
	return dirty
end

function Diner:calSellReward(sell, delta, dishData)
	local reward = sell.reward or ""
	local popular = 0
	if delta <= 0 then
		return reward, popular
	end
	local addReward = {}
	for key, value in pairs(dishData.item_normal:toNumMap()) do
		addReward[key] = (addReward[key] or 0) + value * delta
	end

	popular = dishData.famous_normal * delta

	local upValue = {}
	-- 建筑加成
	for buildType = 1, 6 do
		local level = self:getProperty("buildL"):getv(buildType, 1)
		local buildData = csvdb["diner_buildingCsv"][buildType][level]
		if buildData.gold_up > 0 then
			upValue[ItemId.Gold] = (upValue[ItemId.Gold] or 0) + buildData.gold_up
		end
		if buildData.item_up > 0 then
			upValue[ItemId.DinerCoin] = (upValue[ItemId.DinerCoin] or 0) + buildData.gold_up
		end
		if buildData and buildData.famous_up > 0 then
			upValue[-1] = (upValue[-1] or 0) + buildData.famous_up
		end
	end

	-- 收集加成
	local collectCount = 0
	for _id , status in pairs(self:getProperty("customer")) do
		if status == 1 then
			collectCount = collectCount + 1
		end
	end
	local collectAdd = 0
	for _, collectData in ipairs(csvdb["diner_customer_collectCsv"]) do
		if collectData.num <= collectCount then
			collectAdd = collectData.bonus
		else
			break
		end
	end
	upValue[-1] = (upValue[-1] or 0) + collectAdd

	for id, count in pairs(addReward) do
		addReward[id] = math.floor(count * (1 + (upValue[id] or 0) / 100))
		reward = reward:incrv(id, addReward[id])
	end
	popular = math.floor(popular * (1 + (upValue[-1] or 0) / 100))

	return reward, popular
end

function Diner:updateSell(slot, calOnly)
	local sells = json.decode(self:getProperty("sells"))
	local sell = sells[slot]
	if not sell or sell.count <= 0 then
		return
	end
	local dishData = csvdb["diner_dishCsv"][sell.dish][sell.level]

	local deltaTime = 0
	local deltaCount = 0
	local timePass = skynet.timex() - sell.time
	local sellTime = dishData.sell_time

	deltaCount = math.floor(timePass / sellTime)
	if deltaCount < sell.count then
		deltaTime = math.floor(timePass - sellTime * deltaCount)
	end
	deltaCount = math.min(deltaCount, sell.count)
	local lastCount = sell.count - deltaCount
	local reward, popular = self:calSellReward(sell, deltaCount, dishData)

	if not calOnly and deltaCount > 0 then
		sells[slot].time = skynet.timex() - deltaTime
		sells[slot].count = lastCount
		sells[slot].level = self:getProperty("dishTree"):getv(sell.dish, 1)
		sells[slot].reward = reward
		sells[slot].popular = (sells[slot].popular or 0) + popular
		self:setProperty("sells", json.encode(sells))
		self:checkDinerTask(DinerTask.SellDish, deltaCount, sell.dish)
		self:checkDinerTask(DinerTask.SellDishType, deltaCount, math.ceil(sell.dish / 100))
		self:checkDinerTask(DinerTask.SellDishRare, deltaCount, dishData.rarity)
		self.owner:checkTaskEnter("FoodSell", {count = deltaCount})
	end
	return {
		deltaCount = deltaCount,
		deltaTime = deltaTime,
		lastCount = lastCount,
		reward = reward,
	}
end

function Diner:expediteSell(slot)
	local sells = json.decode(self:getProperty("sells"))
	local sell = sells[slot]
	if not sell or sell.count <= 0 then
		return
	end
	local dishData = csvdb["diner_dishCsv"][sell.dish][sell.level]
	local expediteCount = 0
	local expediteTime = globalCsv.diner_sell_expediteTime
	local sellTime = dishData.sell_time
	expediteCount = math.floor(expediteTime / sellTime)
	expediteCount = math.min(expediteCount, sell.count)
	local lastCount = sell.count - expediteCount
	local reward, popular = self:calSellReward(sell, expediteCount, dishData)
	local deltaTime = math.floor(expediteTime - sellTime * expediteCount)
	if expediteCount > 0 then
		sells[slot].time = sell.time - deltaTime
		sells[slot].count = lastCount
		self:setProperty("sells", json.encode(sells))
		self:checkDinerTask(DinerTask.SellDish, expediteCount, sell.dish)
		self:checkDinerTask(DinerTask.SellDishType, expediteCount, math.ceil(sell.dish / 100))
		self:checkDinerTask(DinerTask.SellDishRare, expediteCount, dishData.rarity)
		self.owner:checkTaskEnter("FoodSell", {count = expediteCount})
	end
	return {
		expediteCount = expediteCount,
		lastCount = lastCount,
		reward = reward,
		popular = popular,
		deltaTime = deltaTime,
	}
end

function Diner:getMaxSlots()
	local slotCount = globalCsv.diner_sell_slots_init

	for _, carbonId in ipairs(globalCsv.diner_sell_slots_unlock) do
		if self.owner:checkHangPass(carbonId) then
			slotCount = slotCount + 1
		end
	end

	return slotCount
end

function Diner:getMaxDishs()
	local dishCount = globalCsv.diner_sell_dish_init

	-- local buildingCsv = csvdb["diner_buildingCsv"]
	-- for id, level in pairs(self:getProperty("buildL"):toNumMap()) do
	-- 	if buildingCsv[id][level].storage > 0 then
	-- 		dishCount = dishCount + buildingCsv[id][level].storage
	-- 	end
	-- end
	return dishCount
end

function Diner:popularAdd(popular)
	if popular ~= 0 then
		self:updateProperty({field = "popular", delta = popular})
		local dbKey = self.owner:getCurDinerRankKey()
		local roleId = self.owner:getProperty("id")
		-- 更新排行榜
		local curPopular = self:getProperty("popular")
		self.owner:checkTaskEnter("DinerPopular", {count = curPopular})
		redisproxy:pipelining(function (red)
			red:zadd(dbKey, curPopular, roleId)	--更新分数
			red:hset(RANK_DINER_INFO, roleId,  MsgPack.pack({
				lv = self:getProperty("buildL"):getv(1, 1),
				name = self.owner:getProperty("name"),
				headId = self.owner:getProperty("headId")
			}))
		end)
	end
end

function Diner:getPopularRank()
	local dbKey = self.owner:getCurDinerRankKey()
	local list = {}
	local ids = redisproxy:zrevrange(dbKey, 0 , 99, "WITHSCORES")
	local redret = {}
	if ids and next(ids) then
		redret = redisproxy:pipelining(function (red)
			for i = 1, #ids, 2 do
				local roleId = ids[i]
				local score = ids[i + 1]
				list[#list + 1] = {score = tonumber(score), roleId = tonumber(roleId)}
				red:hget(RANK_DINER_INFO, roleId)
			end
		end)
	end
	for i = 1, #redret do
		local player = MsgPack.unpack(redret[i])
		list[i].player = player
	end
	local rank = redisproxy:ZREVRANK(dbKey, self.owner:getProperty("id"))
	if not rank then
		rank = -1
	else
		rank = rank + 1
	end
	return {list = list, rank = rank}
end

function Diner:data()
	local properties = {
		"buildL", 
		"order", 
		"sells", 
		"dishTree", 
		"skillTree",
		"popular",
		"expedite",
		"gfood", 
		"task",
		"entrust",
		"customer",
		"comboStatus",
	}
	local data = self:getProperties(properties)
	return data
end

return Diner