In the game Power Simulator (game link: Power Simulator - Roblox) you are able to buy a VIP pass that grants a series of advantages in the game. Usually in most games, a pricey gamepass would be used and once purchased will forever grant that player that VIP pass. But in Power Simulator, this is time based (VIP lasting for 3 hours for example). Seeing as this is bought numerous times, it is a developer product.
I plan on using a similar system but I have no idea where to start and which coding methods I should use to achieve this. May I have some guidance on this?
Well, as you said, you’d approach this by making use of devproducts; as far as making it last a certain amount of time goes, I’d personally go about this by setting up a function you can invoke which checks the amount of time that’s elapsed (using either a cached os.time, current ostime, & os.difftime or by making use of a cached os.date & uncached os.date).
Upon the purchase of the devproduct, I’d
cache the time of purchase.
enable whatever ‘VIP’ features the player should then have access to.
check the time difference between when they bought it & the current time
When the player joins the server
In set intervals, for all online players, across the lifetime of each game server
When the player leaves the server (somewhat redundant)
I see, so let’s say, every 1 minute, check to see if a dev product is active, I would save this in a datastore, with the key being the vip and the value being the amount of time elapsed? I’m pretty sure there would he problems when players begin to stack them.
Finally got around to writing some mock code to show the gist of it. I’m not sure if this shows the best approach to take nor if there is a library that may make achieving the intended behavior easier (I’ll have to look, if there isn’t one I’ll consider making one similar to LuaDate but for roblox).
I used LuaDoc-esque comments to explain function behavior & --> to signify what the output would look like as a result of that function’s execution
local vip = {
data = {}
}
local secondsPer = {
sec = 1,
min = 60,
hour = 3600,
day = 86400,
week = 604800,
month = 2629800,
year = 31557600,
}
--- dummyPurchase ( playerName, _debugCurrentTimeOverride )
--- An dummy example of what the purchasing function should look like
--@param playerName name of the purchaser
--@param _debugCurrentTimeOverride debug override that lets you set the time of the mock purchase
--
--@return nil
function vip:dummyPurchase(playerName, _debugCurrentTimeOverride)
local hoursToGrant = 3 -- Number of hours to add per purchase
local currentTime = _debugCurrentTimeOverride or os.time()
local pdata = (
self.data[playerName]
or
{ -- Default data
tOfInitialPurchase = nil,
hoursRemaining = 0,
}
)
if (not pdata.tOfInitialPurchase) or self:hasExpired(pdata, currentTime) then
-- Purchased for the first time or after expiration of last purchase
pdata.tOfInitialPurchase = os.time()
pdata.hoursRemaining = hoursToGrant
print('new purchase/expired')
else
-- Purchased while a VIP
pdata.hoursRemaining = pdata.hoursRemaining + hoursToGrant
print('purchased while vip')
end
self.data[playerName] = pdata
end
--- hasExpired ( pdata, currentTime )
--@param pdata A table describing a player's vip
--@param time Any number; intepreted as seconds since Epoch
--
--@return bool, number Whether the player's vip has expired, hours until it expires
function vip:hasExpired(pdata, time)
local difference = (pdata.tOfInitialPurchase+(pdata.hoursRemaining*secondsPer.hour) - time)
return difference < 0, difference/secondsPer.hour
end
-- Mock purchase
vip:dummyPurchase('test') --> new purchase
print(
-- Check if the player's VIP has expired
vip:hasExpired(vip.data.test, os.time())
) --> false 3
vip:dummyPurchase('test') --> purchased while vip
print(
-- Check if the player's VIP has expired
vip:hasExpired(vip.data.test, os.time())
) --> false 6
-- Emulate a purchase a day after their last
vip:dummyPurchase('test', os.time()+secondsPer.day) --> new purchase/expired