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!