I need help with a script involving remote events

Hey, I’m currently working on creating a gamepass system similar to one Roblox Bedwars uses for kits. Currently, I have two gamepasses. One of them increases your JumpHeight and the other one increases your WalkSpeed. Similarly to Bedwars, there is a Gui that allows you to select which “kit,” in this case, gamepass you would like to use. So far, I have eight remote events in ReplicatedStorage which allow this system to work.

The problems:

  1. One issue is that players can select and use multiple gamepasses simultaneously, whereas they should only be able to utilize the perks of one gamepass at a time, similar to the setup in Bedwars. For instance, if a player chooses the speed gamepass option in the GUI, they should not be able to equip the jump boost gamepass unless they first unequip the speed gamepass. This is the intended behavior, but currently, players can use both gamepasses simultaneously if they have purchased them. (I have considered using BoolValues to check if one of the gamepasses is equipped, but I realize exploiters could likely change the values with ease)

  2. I am by no means a scripter, but I do have a decent amount of knowledge on it. Enough to be able to script most of the functionality in my games. I could be wrong, but eight remote events for one system seems like an excessive and likely unecessary amount. Is there a way to make this code a bit more efficient?

  3. Is this script vulnerable to exploits? Can an exploiter compromise this script with ease? If so, how do I make it more secure? I don’t know what exploiters are capable of as I have never exploited myself. Am I putting too much trust in the client?

I know this post is asking for a lot but even if you can’t help with all three of those things, just helping with one of them would be a major help.

Explorer:
Gui → StarterGui
SpeedScript (Server) → ServerScriptService
JumpScript (Server) → ServerScriptService
SpeedLocalScript (Client) → Gui
JumpLocalScript (Client) → Gui
Remotes → ReplicatedStorage

The script and Gui are prototypes. I am trying to get the basic coding for a much more complex system. (So don’t mind how poor quality the UI is)

I will show you the server sprint script and client sprint script. The scripts for jumping are exactly the same, just with different names for remotes and a few value changes. If you would also like to see the jump scripts or have any other questions, please ask.

Any help is much appreciated, thank you!

UI:

Speed script (Server)

--Variables
local eventFolder = game:GetService("ReplicatedStorage"):WaitForChild("GamepassEvents")

local speedEvent = game:GetService("ReplicatedStorage"):WaitForChild("GamepassEvents").SpeedGamepass
local speedAcceptEvent = game:GetService("ReplicatedStorage"):WaitForChild("GamepassEvents").SpeedAccepted
local speedDeclineEvent = game:GetService("ReplicatedStorage"):WaitForChild("GamepassEvents").SpeedDeclined
local unequipSpeed = game:GetService("ReplicatedStorage"):WaitForChild("GamepassEvents").UnequipSpeed

local id = 195581571

local normSpeed = 16
local speed = 32

--MarketplaceService

game:GetService("MarketplaceService").PromptGamePassPurchaseFinished:Connect(function(plr, ido, purchased)
	if purchased and ido == id then
		print("Player owns the gamepass")
	end
end)

game.Players.PlayerAdded:Connect(function(plr)
	plr.CharacterAdded:Connect(function(char)
		if game:GetService("MarketplaceService"):UserOwnsGamePassAsync(game.Players[char.Name].UserId, id) then
			print("Player owns the gamepass")
		end
	end)
end)

--Gamepass functionality

local function equipSpeed(player)
	--Confirm player has gamepass
	if game:GetService("MarketplaceService"):UserOwnsGamePassAsync(player.UserId, 195584369) then
		--Gives the player speed and makes changes to the UI on the client.
		player.Character.Humanoid.WalkSpeed = speed
		speedAcceptEvent:FireClient(player)
	else
		--Changes UI on the client. 
		speedDeclineEvent:FireClient(player)
	end
end

--Removes the speed
local function unEquipSpeed(player)
	player.Character.Humanoid.WalkSpeed = normSpeed
end

speedEvent.OnServerEvent:Connect(equipSpeed)
unequipSpeed.OnServerEvent:Connect(unEquipSpeed)

Speed script (Client)

--Variables
local eventFolder = game:GetService("ReplicatedStorage"):WaitForChild("GamepassEvents")

local speedEvent = game:GetService("ReplicatedStorage"):WaitForChild("GamepassEvents").SpeedGamepass
local speedAcceptEvent = game:GetService("ReplicatedStorage"):WaitForChild("GamepassEvents").SpeedAccepted
local speedDeclineEvent = game:GetService("ReplicatedStorage"):WaitForChild("GamepassEvents").SpeedDeclined
local unequipSpeed = game:GetService("ReplicatedStorage"):WaitForChild("GamepassEvents").UnequipSpeed

local jumpButton = script.Parent.Parent.JumpEquip

local button = script.Parent
local declineWarning = script.Parent.Parent.DeclineWarning
local mainGui = script.Parent.Parent

equipped = false

--Runs when the player presses the "Equip" button
button.MouseButton1Click:Connect(function()
	if equipped == false then
		equipped = true
		speedEvent:FireServer()
	else
		--Unequips and removes speed on the server
		button.Text = "Equip"
		unequipSpeed:FireServer()
		equipped = false
	end
		
end)

local function accepted()
	--Player has the gamepass
	button.Text = "Equipped"
	button.BackgroundColor = BrickColor.new(0.027451, 0.286275, 1)
	
end

local function declined()
	--Player doesn't have the gamepass
	button.BackgroundColor = BrickColor.new(1, 0, 0)
	--Warning label tells player they must purachase the gamepass
	declineWarning.Visible = true
	
end

speedAcceptEvent.OnClientEvent:Connect(accepted)
speedDeclineEvent.OnClientEvent:Connect(declined)

could you show what’s in the gui?

Absolutely!

Commissions - Roblox Studio 6_25_2023 10_34_40 PM

I think you can shorten your code by adding a variable to the player that will determine the buff the player has. And then from there, whichever buff the player has, the buff will be applied.

I haven’t thought of that approach.

So something like: local currentBuff = speed

I assume that would need to go on the server side. I would have to communicate that information to the client with another remote event though. That’s a good idea though. If no one else comes up with a more efficient way to do it, I’ll do that. Thank you for your input.

Hey Fractal, you should have a Remote that sends a request to the server saying what Kit they would like to equip. From the server, you should have a Data folder/profile to check if they can equip that kit

-- // Declarations

local replicatedStorage = game:GetService('ReplicatedStorage')
local remotes			= replicatedStorage:WaitForChild('Remotes', 1);
local kits				= {
	['speeder'] = {
		debuffs		= false,
		walkSpeed 	= 3.2, -- Doesn't skip leg day
		damageBoost = 1.2, -- Yes, they work out their arms.
		jumpBoost 	= 3.2 -- Jumps a bit more
	},
	['buffPerson'] = {
		debuffs 	= true, -- If this is set to true it means any value that below that is not damage will be a con for the player
		walkSpeed 	= 5.5, -- Negate 10 walkspeed from current WalkSpeed (slow down the player)
		damageBoost = 2.5, -- Give the player double damage and a half to account for slow speeds
		jumpBoost = 5.5 -- So buff that thier muscles are heavy
	}
}

-- // Connection / RemoteEvents


remotes.kitUsage.OnServerEvent:Connect(function(player, Kit)
	if typeof(Kit) == 'string' and kits[Kit] and player.Data.ownedKits:FindFirstChild(Kit) then -- Given kit is a string and is found in the kits table above, and we do own it
		player.Data.SelectedKit.String = Kit -- Set the new kit to the player
	end
end)

This is a way we could do it so that we give the selected kit to the player. Now save that to a dataStore so when they join the real match, they have that in their data.
Now, in the game we would do something like this:

-- // Declarations

local players = game:GetService('Players');
local kits				= {
	['speeder'] = {
		debuffs		= false,
		walkSpeed 	= 3.2, -- Doesn't skip leg day
		damageBoost = 1.2, -- Yes, they work out their arms.
		jumpBoost 	= 3.2 -- Jumps a bit more
	},
	['buffPerson'] = {
		debuffs 	= true, -- If this is set to true it means any value that below that is not damage will be a con for the player
		walkSpeed 	= 5.5, -- Negate 10 walkspeed from current WalkSpeed (slow down the player)
		damageBoost = 2.5, -- Give the player double damage and a half to account for slow speeds
		jumpBoost = 5.5 -- So buff that thier muscles are heavy
	}
}

-- // Character mainHandler

players.PlayerAdded:Connect(function(player)
	
	local data = Instance.new('Folder', player) -- New data folder 
	data.Name = 'Data'
	
	local selectedKit = Instance.new('StringValue', data) -- Kit holder
	selectedKit.Name = 'Kit'
	selectedKit.Value = 'buffPerson' -- Insert Data store data here
	
	local damageBooster = Instance.new('NumberValue', data) -- Damage holder
	damageBooster.Name = 'damageBooster'
	
	player.CharacterAppearanceLoaded:Connect(function(character) -- better CharacterAdded :yawn:
		local kit = kits[selectedKit.Value] -- what kit?
		if kit.debuffs then -- is this kit a debuff?
			character.Humanoid.WalkSpeed -= kit.walkSpeed
			character.Humanoid.JumpPower -= kit.jumpBoost
		else -- not a debuff
			character.Humanoid.WalkSpeed += kit.walkSpeed
			character.Humanoid.JumpPower += kit.jumpBoost
		end
		
		damageBooster.Value = kit.damageBoost -- damage boost
	end)
end)

~ Sincerely, Ihaveash0rtname
“Happy Scripting!”

2 Likes

Thank you so much! I will definitely do that. Thanks for putting in the time to write that for me!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.