How to fix this item shop?

Hey there!

I am have just completed my daily item shop and all the features of it, using this amazing tutorial by @rek_kie. It works great and I love it except for one thing. The video will explain:
https://www.wevideo.com/view/2159133106

Here is the serverscript:

local syncedtime = require(game.ServerStorage.SyncedTime)
local UpdateFunction = game.ReplicatedStorage.UpdateRemoteFunction
local updateTimerEvent = game.ReplicatedStorage:WaitForChild("ShopTimeUpdate")

syncedtime.init()

local function toHMS(s)
	return string.format("%02i:%02i:%02i", s/60^2, s/60%60, s%60)
end

local CommonItems = {
	"RthroAnim";
	"GreenParticleTrail";
	"CloudParticleTrail"; --
	"CheckMarkParticleTrail";
	"HeartParticleTrail";
	"QuestionMarkParticleTrail";
	"SunParticleTrail";
	"SpiderWebParticleTrail"
}

local UncommonItems = {
	"RobotAnim";
	"OldSchoolAnim"; --
	"StylishAnim";
	"BlueParticleTrail";
	"CrossMarkParticleTrail";
	"WaterParticleTrail";
	"ClubParticleTrail";
	"MoonParticleTrail"
}

local RareItems = {
	"ToyAnim";
	"BubblyAnim";
	"ElderAnim";
	"CartoonyAnim";
	"SuperHeroAnim";
	"MageAnim"; --
	"YellowParticleTrail";
	"TornadoParticleTrail"
}

local VeryRareItems = {
	"KnightAnim";
	"ZombieAnim"; --
	"AstronautAnim";
	"WerewolfAnim";
	"VampireAnim";
	"OrangeParticleTrail"; --
	"SpadeParticleTrail";
	"RockParticleTrail"
}

local EpicItems = {
	"PirateAnim";
	"NinjaAnim"; --
	"RedParticleTrail";
	"ExclaimationMarkParticleTrail";
	"DiamondParticleTrail";
	"FireParticleTrail"; --
	"CometParticleTrail";
	"MusicNoteParticleTrail"
}

local LegendaryItems = {
	"LevitationAnim";
	"PurpleParticleTrail";
	"StarParticleTrail";
	"LightningParticleTrail"; --
	"PresentParticleTrail";
	"CycloneParticleTrail"; --
	"SnowflakeParticleTrail"; --
	"ExplosionParticleTrail"
}

local weights = {
	Common = 100,
	Uncommon = 60,
	Rare = 32,
	VeryRare = 15,
	Epic = 5,
	Legendary = 1
}

function getAvailableItems(day, numberofitems)
	local rng = Random.new(day)
	local shopItems = {}
	
	local function shallowCopy(original)
		local copy = {}
		for key, value in pairs(original) do
			copy[key] = value
		end
		return copy
	end
	
	local function Generate()
		local shopitem = nil 
		local returnedRarity = nil

		
		local function GenerateWeightedItem()
			local rarity = nil
			local weightNumber = rng:NextNumber(0, 100)
			
			local weightitem = nil
			
			if weightNumber < weights.Legendary then
				print("Legendary")
				weightitem = LegendaryItems[rng:NextInteger(1, #LegendaryItems)]
				rarity = LegendaryItems
			elseif weightNumber < weights.Epic then
				print("Epic")
				weightitem = EpicItems[rng:NextInteger(1, #EpicItems)]
				rarity = EpicItems
			elseif weightNumber < weights.VeryRare then
				print("Very Rare")
				weightitem = VeryRareItems[rng:NextInteger(1, #VeryRareItems)]
				rarity = VeryRareItems
			elseif weightNumber < weights.Rare then
				print("Rare")
				weightitem = RareItems[rng:NextInteger(1, #RareItems)]
				rarity = RareItems
			elseif weightNumber < weights.Uncommon then
				print("Uncommon")
				weightitem = UncommonItems[rng:NextInteger(1, #UncommonItems)]
				rarity = UncommonItems
			elseif weightNumber < weights.Common then
				print("Common")
				weightitem = CommonItems[rng:NextInteger(1, #CommonItems)]
				rarity = CommonItems
			end
			
			return weightitem, rarity
		end
		
		shopitem, returnedRarity = GenerateWeightedItem()
		local itemtablecopy = shallowCopy(returnedRarity)
		
		for i, item in pairs(shopItems) do
			local duplicate = table.find(shopItems, shopitem)
			
			if duplicate then
				print("Respinning...")
				for number, v in pairs(itemtablecopy) do
					for i = 1,#shopItems do
						if v == shopItems[i] then
							table.remove(itemtablecopy, number)
						end
					end
				end
				repeat
					shopitem = itemtablecopy[rng:NextInteger(1, #itemtablecopy)]
				until shopitem ~= item
			end
		end
		table.insert(shopItems, shopitem)
	end
	
	repeat
		Generate()
	until #shopItems >= numberofitems
	
	return shopItems
end


local currentDay = nil
local currentShopItems = {}
local hourOffset = -3

local offset = (60 * 60 * hourOffset)

function UpdateShop()
	print("CAME THROUGH")
	return currentShopItems
end

UpdateFunction.OnServerInvoke = UpdateShop

while true do
	local day = math.floor((syncedtime.time() + offset) / (60 * 60 * 24))
	local t = (math.floor(syncedtime.time())) - offset
	local daypass = t % 86400
	local timeleft = 86400 - daypass
	local timeleftstring = toHMS(timeleft)
	
	local sentence = ("Time till shop resets: " .. timeleftstring)
	
	if day ~= currentDay then
		currentDay = day
		currentShopItems = getAvailableItems(day, 6)
		print("Today's Items: " .. table.concat(currentShopItems, ", "))
	end
	updateTimerEvent:FireAllClients(sentence)
	wait(1)
end

And here is the Local Script:

local player = game.Players.LocalPlayer
local UpdateFunction = game.ReplicatedStorage.UpdateRemoteFunction
local Items = require(game.ReplicatedStorage:WaitForChild("Items"))
boughtRequest = game.ReplicatedStorage:WaitForChild("BoughtRequest")

local WhatImage = "BuyImage"
local WhatPrice = "BuyPrice"
while true do
	wait(5)
	bought = boughtRequest:InvokeServer()
	local itemTable = UpdateFunction:InvokeServer()
	for i, button in ipairs(script.Parent.Items:GetChildren()) do
		if button.Buy.Value == false then
			local which = itemTable[i]
			button.Item.Value = which
			button.BackgroundColor3 = Items.Items[which].color
			button.Text = Items.Items[which].name
			button.IType.Value = Items.Items[which].class
			local image = script.Parent.ItemImages:FindFirstChild(WhatImage .. i)
			image.Image = "rbxassetid://" .. Items.Items[which].imageID
			if which == "GreenParticleTrail" then
				image.ImageColor3 = Color3.fromRGB(0, 255, 0)
			elseif which == "BlueParticleTrail" then
				image.ImageColor3 = Color3.fromRGB(0, 170, 255)
			elseif which == "YellowParticleTrail" then
				image.ImageColor3 = Color3.fromRGB(255, 255, 0)
			elseif which == "OrangeParticleTrail" then
				image.ImageColor3 = Color3.fromRGB(255, 170, 0)
			elseif which == "RedParticleTrail" then
				image.ImageColor3 = Color3.fromRGB(255, 0, 0)
			elseif which == "PurpleParticleTrail" then
				image.ImageColor3 = Color3.fromRGB(170, 0, 255)
			elseif which == "OldSchoolAnim" then
				image.ImageColor3 = Color3.fromRGB(170, 0, 255)
			end
			local price = script.Parent.ItemPrices:FindFirstChild(WhatPrice .. i)
			price.Text = "Price: " .. Items.Items[which].price .. " Points"

			for k, v in pairs(bought) do
				--change the button color and text depending on the item we purchased
				if button.Buy.Value == false then
					if button.Item.Value == v then
						if button.IType == "Trail" then
							button.Text = button.Text .. " (Owned)"
						elseif button.IType == "Anim" then
							button.Text = button.Text .. " (Owned)"
						else
							button.Text = button.Text .. " (Owned)"
						end
					end
				end
			end 
		end	
	end
end 

If this helps here is the time module

local monthStrMap = {
	Jan=1,
	Feb=2,
	Mar=3,
	Apr=4,
	May=5,
	Jun=6,
	Jul=7,
	Aug=8,
	Sep=9,
	Oct=10,
	Nov=11,
	Dec=12
}
local HttpService = game:GetService("HttpService")
local function RFC2616DateStringToUnixTimestamp(dateStr)
	local day, monthStr, year, hour, min, sec = dateStr:match(".*, (.*) (.*) (.*) (.*):(.*):(.*) .*")
	local month = monthStrMap[monthStr]
	local date = {
		day=day,
		month=month,
		year=year,
		hour=hour,
		min=min,
		sec=sec
	}
	
	return os.time(date)
end

local isInited = false
local originTime = nil
local responseTime = nil
local responseDelay = nil
local function inited()
	return isInited
end

local function init()
	if not isInited then
		local ok = pcall(function()
			local requestTime = tick()
			local response = HttpService:RequestAsync({Url="http://google.com"}) 
			local dateStr = response.Headers.date
			originTime = RFC2616DateStringToUnixTimestamp(dateStr)
			responseTime = tick()
			-- Estimate the response delay due to latency to be half the rtt time
			responseDelay = (responseTime-requestTime)/2
		end)
		if not ok then
			warn("Cannot get time from google.com. Make sure that http requests are enabled!")
			originTime = os.time()
			responseTime = tick()
			responseDelay = 0
		end
		
		isInited = true
	end
end

local function time()
	if not isInited then
		init()
	end
	
	return originTime + tick()-responseTime - responseDelay
end

return {
	inited=inited,
	init=init,
	time=time
}

I am not really sure how it is possible for the time and the actual updating to be at separate times, but maybe it has something to do with the serverscript with the

if day ~= currentDay then

But I don’t know, does anyone have any ideas?

This code seems semi complicated, but it is probably easy for some of you, but we shall see!

2 Likes

If you need me to explain anything at all just ask!

@Dev_Latte, I saw the request from my group to explain this, but, I believe that it is best explained by rek_kie himself in his tutorial… if you need me to explain other stuff for mine, I would be happy to, but I’ll wait till you can start posting, so you can tell me exactly what you need to know. And remember, all you need to read are 1.5k posts, and view 50 or 100 topics, I don’t remember that one. You can look it up.

offset is added to day, which is used to determine when items actually reset. It’s subtracted out for t, though, so the time being displayed won’t be offset in the same way; it’s offset in the opposite direction.

2 Likes

Sorry this might sound dumb but what should I change? I am a little uncertain sorry. :laughing:

day is having the offset added, so the items actually change three hours before (the hourOffset you chose is -3) midnight.* t is having offset subtracted, so the actual clock says the items change three hours after midnight.* You can change either one to be addition or subtraction, just make sure it’s the same for both. I would assume what you wanted here was addition, so it’d actually be offset that many hours, but it’d “work” with subtraction too; they just have to be the same.

*: It’s probably not midnight in your timezone but rather in UTC, which is why 5:00 is “three hours away from midnight.”

3 Likes

Thank you this has been a huge issue for me thanks!!