How to make a VIP multiplier?

Hi everyone, I searched the web for answers, but I didn’t seem to find any. My question is: How to make a VIP x1.5 cash multiplier in a regular script? I know that I need to use the MarketPlaceService and UserOwnsGamePassAsync() but I don’t know how to get the local player since this would be a if statement (if player owns VIP then give x1.5 multiplier). How do I got about this? Do you have any helpful articles? I took a look at the one on Documentation - Roblox Creator Hub but it didn’t really help.

If all you need is to access the local player’s user id, you should use:

local PlayerID = game.Players.LocalPlayer.UserId

This only works in local scripts, for reasons I hope are obvious.
It’s worth noting that “game.Players.LocalPlayer” returns the Player class found in game.Players.

So do you think if I check that in a LocalScript and then pass it to a RemoteEvent it would be good? Thing is I don’t want hackers to be able to get it.

When you fire an event from the client to the server, the first argument on the server-side is always the player from which the RemoteEvent is fired from. In this case, you wouldn’t need to use game.Players.LocalPlayer because this information is always the first argument of the server-side function.

Take the following as an example:

function FunctionName (Player, Argument1, Argument2)
    -- Player does not need to passed as an argument in the client. Instead, the only arguments you pass in the client are Argument1 and Argument2.
end

If this remains confusing, I recommend this page.

I see what you mean. Here is what I came up with. Both the LocalScript and Script are located in ServerScriptService.
Local Script:

local Players = game:GetService("Players")
local player = Players.LocalPlayer
local id = 9086258

if game:GetService("MarketplaceService"):UserOwnsGamePassAsync(player, id) then
	game.ReplicatedStorage.VIPOwned:FireServer()
end

Script:

game.ReplicatedStorage.VIPOwned.OnServerEvent:Connect(function(player)
	player.Multiplier  = 1.5
	print(player.Name.." owns VIP.")
end)

A few things I think might be an issue here (although I’m not certain).

  1. The client cannot access ServerScriptService. Hence, the local script is best placed in StarterPlayerScripts or StarterCharacterScripts.
  2. It might be safer to check if a player owns a gamepass on the server. This is because I believe some exploiters are capable of modifying existing client-sided code. They could remove the if statement to bypass the gamepass restriction. However, they cannot modify server-side code.

You should not under any means have anything involving stuff such as gamepasses in the client. To get the localplayer you should use a PlayerAdded() event, the playerObject which is the first argument you put is essentially the localplayer.

Edit: If what you desire is client information you COULD in theory instead use a Remote Function and have it return the data the client needs when the client loads, which essentially you wouldn’t need a check in a localscript for such a thing, you could literally just do

--Client side
    local ReturnedValues = Network:InvokeServer("Get Your Data Here")
    print(ReturnedValues)
--Server Side 
Network.OnServerInvoke = function(playerObject, request)
       local data = "Just a string variable"
      return data
end)

Output: “Just a string variable”

1 Like

I don’t find there to be any reason why he can’t just perform the gamepass check on the server instead of the client.

Is there any reason why?

No, as I said you don’t need to have a check like this on the client. if however you need to change the client in anyway I would suggest either a Remote Function and return OR fireClient() but I personally would use a Remote Function as I can invoke it on the client, get the information on the server then return it to the client without having to go through the extra trouble of messing about the server side to fit in with the client information(As you can see the problem with firing client on PlayerAdded) and a extra event I find at that point is jumping through hoops while instead just using a Remote Function if something like this does require the client side at all.

So this should work right?

local id = 9086258

game.Players.PlayerAdded:Connect(function(player)
	if game:GetService("MarketplaceService"):UserOwnsGamePassAsync(player, id) then
		player.Multiplier.Value = 1.5
	end
end)

or do i need to do


game.Players.PlayerAdded:Connect(function(player)
	if game:GetService("MarketplaceService"):UserOwnsGamePassAsync(player, id) == true then
		player.Multiplier.Value = 1.5
	end
end)
2 Likes

Both work, the second one has dead code at the end of the if statement.

1 Like

Essentially yes but make sure it’s on the server side. Also no need to add true or false to anything what I tend to do instead is

if(not boolean) then
if(boolean) then

essentially the same deal just different context.

1 Like

Alright, but the output states this error: [14:43:49.017 - Unable to cast Instance to int64]

Edit: The error is on Line 4

The first argument needs to be the player userid. Which can be set by player.UserId instead of the player object

1 Like

So I need to do

local id = 9086258

game.Players.PlayerAdded:Connect(function(player)
	if game:GetService("MarketplaceService"):UserOwnsGamePassAsync(player.UserId, id) then
		player.Multiplier.Value = 1.5
	end
end)
1 Like

Try it and see then come back with the result

It is advisable to wrap your function in a pcall.
A pcall prevents a script from stopping when an error occurs.
This is recommended for web requests (HTTP requests or anything with Async at the end of the function name) because these requests can inexplicably generate errors due to data packet corruption.

This post is a bit complicated, but it’s here if you need more information about pcalls.

1 Like

Ah, it works, but now another problem come in, somehow regular players (that don’t own the gamepass) have a multiplier of 0, even with this script:

local id = 9086258

game.Players.PlayerAdded:Connect(function(player)
	if game:GetService("MarketplaceService"):UserOwnsGamePassAsync(player.UserId, id) then
		player.Multiplier.Value = 1.5
	else
		player.Multiplier.Value = 1
	end
end)

I suggest debugging that code. The console and prints are your friend. For example, print out every change in the value or if you want my opinion you should move what’s creating the values into 1 script. For me personally I only use 1 server script and rest modules but I’m not gonna get into that. I suggest trying to move everything involving a event such as PlayerAdded to one code entirely. It’s a very good practice as it minimizes server data usage, might not seem like much until you have a game of thousands of requests per minute where you’d take anything you can get.

Try setting the multiplier to 1 before the check:

local id = 9086258

game.Players.PlayerAdded:Connect(function(player)
    player.Multiplier.Value = 1
    if game:GetService("MarketplaceService"):UserOwnsGamePassAsync(player.UserId, id) then
	    player.Multiplier.Value = 1.5
    end
end)
1 Like