How to make a VIP multiplier?

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

Hey, I took what you did and what @ithacaTheEnby did, and put it in my leaderstats script, although now it claims that multiplier isn’t a part of Player

local ServerStorage = game:GetService("ServerStorage")
local DataStoreService = game:GetService("DataStoreService")
local myDataStore = DataStoreService:GetDataStore("myDataStore")

local VIPid = 9086258

game.Players.PlayerAdded:Connect(function(player)
	
	local character = player.Character
	
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player
	
	local Points = Instance.new("IntValue")
	Points.Name = "Points"
	Points.Parent = leaderstats
	
	local Wins = Instance.new("IntValue")
	Wins.Name = "Wins"
	Wins.Parent = leaderstats
	
	local Activations = Instance.new("IntValue")
	Activations.Name = "Activations"
	Activations.Parent = leaderstats
	
	local Deaths = Instance.new("IntValue")
	Deaths.Name = "Deaths"
	Deaths.Parent = leaderstats
	
	local Upgrades = Instance.new("Folder")
	Upgrades.Name = "Upgrades"
	Upgrades.Parent = player
	
	local SpeedLevel = Instance.new("IntValue")
	SpeedLevel.Name = "SpeedLevel"
	SpeedLevel.Parent = Upgrades

	local JumpLevel = Instance.new("IntValue")
	JumpLevel.Name = "JumpLevel"
	JumpLevel.Parent = Upgrades
	
	local maxSpeed = Instance.new("IntValue")
	maxSpeed.Name = "maxSpeed"
	maxSpeed.Parent = player
	
	local maxJump = Instance.new("IntValue")
	maxJump.Name = "maxJump"
	maxJump.Parent = player

	local CurrentSpeed = Instance.new("IntValue")
	CurrentSpeed.Name = "CurrentSpeed"
	CurrentSpeed.Parent = player
	
	local CurrentJump = Instance.new("IntValue")
	CurrentJump.Name = "CurrentJump"
	CurrentJump.Parent = player

	local Multiplier = Instance.new("NumberValue")
	Multiplier.Name = "Multiplier"
	Multiplier.Parent = player
	Multiplier.Value = 1
	if game:GetService("MarketplaceService"):UserOwnsGamePassAsync(player.UserId, VIPid) then
		player.Multiplier.Value = 1.5
	end

	-->> Data: Begining
	
	local playerUserId = "Player_"..player.UserId
	
	-->>Data: Load Data
	
	local data
	local success, errormessage	 = pcall(function()
		data = myDataStore:GetAsync(playerUserId)
	end)
	
	if success then
		if data then
			Points.Value = data.Points
			Wins.Value = data.Wins
			Activations.Value = data.Activations
			Deaths.Value = data.Deaths
			SpeedLevel.Value = data.SpeedLevel
			JumpLevel.Value = data.JumpLevel
			maxSpeed.Value = data.maxSpeed
			maxJump.Value = data.maxJump
			CurrentSpeed = data.CurrentSpeed
			CurrentJump = data.CurrentJump
			Multiplier = data.Multiplier
		end
	end
	
end)

-->> Data: Saving Stats

game.Players.PlayerRemoving:Connect(function(player)
	local playerUserId = "Player_"..player.UserId

	local data = {
		Points = player.leaderstats.Points.Value;
		Wins = player.leaderstats.Wins.Value;
		Activations = player.leaderstats.Activations.Value;
		Deaths = player.leaderstats.Deaths.Value;
		SpeedLevel = player.Upgrades.SpeedLevel.Value;
		JumpLevel = player.Upgrades.JumpLevel.Value;
		maxSpeed = player.maxSpeed.Value;
		maxJump = player.maxJump.Value;
		CurrentSpeed = player.Character.Humanoid.WalkSpeed;
		CurrentJump = player.Character.Humanoid.JumpPower;
		Multiplier = player.Multiplier.Value;
	}
	
	local success, errormessage = pcall(function()
		myDataStore:SetAsync(playerUserId, data)
	end)
		
	if success then
		print("Data succefully saved!")
	else
		print("Data saving error")
		warn(errormessage)
	end
	
end)

Edit: OMG sorry it was the wrong script… It was the old one, now it works well.

You don’t need to use player.Multiplier, try jjust using multiplier instead.

1 Like