I am trying to create a GUI in the workspace that displays the amount of robux my game has earned in a certain time period. I’m trying to create a goal, so let’s say 100 robux earned in a day, and have it displayed on a wall with it increasing on its own; from 10/100 to 30/100 right after someone spends 20 robux.
Anyone know how I could do this? Scripting is a big weakness of mine so if there are any suggestions or solutions for this issue that would be great.
You could use a datastore and use os.time to keep track of the dates, and then store the daily goal and possibly update it game-wide whenever a player donates or buys a gamepass. Also, if you’re not looking to go as advanced, you could simply have a “server robux goal” in which you just have that goal for that server and that server only.
ROBLOX is planning to release “Universe Scripts and Global Services” in the final quarter of 2019, as seen on their developer roadmap. This would likely make it much easier to do stuff like this. I’m sure it’s somewhat possible, but you would likely have to use an offsite API which is not worth the trouble of getting. Unless I’m being a moron and forgetting that product purchase events fire throughout the whole game, I don’t think there’s any other way.
Edit: It seems as though they set its status to ‘deferred’, hopefully it will be soon, although it doesn’t seem like it will be coming in 2019.
It shouldn’t be difficult to update it game-wide. Just have a datastore key called “GameRobuxGoal” or something like that. Whenever players buy a dev product, update that value in the datastore. Then have all of your servers call GetAsync with that key every 5 minutes or so and then update the wall in that server.
For sure, the first thing you wanna do is get the DataStore you are gonna save all the data in, you will need this to call the saving/loading functions later.
local ds = game:GetService("DataStoreService"):GetDataStore("WeeklyGoals")
Now you should have a Process Receipt callback set up to handle DevProduct transactions, (you can find a code sample on what that should look like here) Inside of that callback you can get the cost of the DevProduct and add it to the datastore that tracks how much robux has been spent
local market = game:GetService("MarketplaceService")
local devProductId = --Enter the ID of the dev product you are selling here
--Gets a dictionary of all the info you could want about a Developer product
local productInfo = market:GetProductInfo(devProductId, Enum.InfoType.Product)
local productPrice = productInfo["PriceInRobux"] --Get the price of the product from the dictionary
--Now update the datastore to reflect how much robux has been spent
ds:IncrementAsync("RobuxSpent", productPrice)
Now that you have code that will store the amount of robux that has been spent by all the players you just need to make a seperate script that will update the wall in your game that will display this number this part is pretty straightforward
local iteration = 0
game:GetService("RunService").Heartbeat:Connect(function()
iteration = iteration + 1
--Heartbeat runs roughly 60 times per second i believe so this will make the code update the amount of robux spent every 5 minutes
if iteration >= 60*300 then
iteration = 0
local robuxSpent = ds:GetAsync("RobuxSpent")
--Here set the number on your wall to the robux spent value
end
end)
I have modified this code in order to have the robux total reset on a specific time period.
-- Define the DataStore
local DS = game:GetService("DataStoreService"):GetDataStore("WeeklyGoals")
local MPS = game:GetService("MarketplaceService")
-- Reset Data on Period
local IntervalCheck = coroutine.create(function()
while wait(300) do
local TimeNow = os.time()
local Data
pcall(function()
Data = DS:GetAsync("TimeReset")
end)
if Data ~= nil then
local LastReset = TimeNow - Data
if (LastReset / 3600) >= 24 then
DS:SetAsync("RobuxSpent",0)
DS:SetAsync("TimeReset",os.time())
end
else
DS:SetAsync("RobuxSpent",0)
DS:SetAsync("TimeReset",os.time())
end
end
end)
coroutine.resume(IntervalCheck)
-- Setup Receipt Processing
local function processReceipt(receiptInfo)
DS:IncrementAsync("RobuxSpent",receiptInfo.CurrencySpent)
end
MPS.ProcessReceipt = processReceipt
By the way, it’s better to use time compared to iterations.
local referenceTime = os.time()
RunService.Heartbeat:Connect(function()
if referenceTime - os.time() >= 60 * 5 then
referenceTime = os.time()
-- do stuff
end
end)
FYI: Using pcalls correctly instead of creating a new function every time can be a more efficient.
How can you do this? Like so:
local ds = game:GetService("DataStoreService"):GetDataStore("WeeklyGoals")
--Getting
local success, data = pcall(ds.GetAsync, ds, "key") --ds is there as the function is called with :
--data will act as the error message if it does error
--Setting
local success = pcall(ds.SetAsync, ds, "key", dataToSave)
Why pcall though? API errors with getting/setting the data could result in data loss or even your game braking.
You are miss understanding the concept of avoiding loops, of course if there is an Event for something use that instead of a loop but not in this case.
You basically want to avoid repeating something if it’s unnecessary, that doesn’t mean you should never use a while loop.
Any experience Scripter who knows what they are doing wouldn’t teach you to use RunService.HeartBeat for something that doesn’t required to be ran every frame let alone every 5 minutes.