I’m making a game that is a round-based game and I want to make a part that when a player touch, (s)he will receive coins or any other leaderstats. I made a server-sided part for this but it always making a mess where players are receiving multiple of coins
How my game works:
I have a script that pick a random map from a folder inside the ServerStorage and at the end there will be reward for completing that map. The win pad (part giving coins) is inside a model
Solution I Tried
I tried adding LocalScript inside the StarterGui since that is client-sided. Here’s the script:
local part = game.Workspace:WaitForChild("Map1", "Map2", "Map3").End -- end is the part that will gives the reward
canGet = true
local function onTouch(otherPart)
local humanoid = otherPart.Parent:FindFirstChild('Humanoid')
if humanoid then
local player = game.Players:FindFirstChild(otherPart.Parent.Name)
if player and canGet then
canGet = false
player.leaderstats.Wins.Value = player.leaderstats.Wins.Value + 1 -- leaderstats 1
player.leaderstats.Gems.Value = player.leaderstats.Gems.Value + 5 -- leaderstats 2
part:Destroy()
end
end
end
part.Touched:Connect(onTouch)
part.Touched:Connect(function(hit)
if hit.Parent:FindFirstChild("Humanoid") then
hit.Parent:BreakJoints()
end
end)
you need to fire the server to change the players leaderstats because if the client changes it and you try to purchase something with a server script the server wont see the change in currency values
Instead of having these on the client, transfer them over to a ServerScript and use a RemoteEvent since ClientSided values don’t show nor save on the Server.
local part = game.Workspace:WaitForChild("Map1", "Map2", "Map3").End -- end is the part that will gives the reward
canGet = true
local function onTouch(otherPart)
local humanoid = otherPart.Parent:FindFirstChild('Humanoid')
if humanoid then
local player = game.Players:FindFirstChild(otherPart.Parent.Name)
if player and canGet then
canGet = false
game.ReplicatedStorage.RemoteEvent:FireAllClients()
part:Destroy()
end
end
end
part.Touched:Connect(onTouch)
part.Touched:Connect(function(hit)
if hit.Parent:FindFirstChild("Humanoid") then
hit.Parent:BreakJoints()
end
end)
Then there will be a script inside ServerScriptStorage?:
local part = game.Workspace:WaitForChild("Map1", "Map2", "Map3").End -- end is the part that will gives the reward
canGet = true
local function onTouch(otherPart)
local humanoid = otherPart.Parent:FindFirstChild('Humanoid')
if humanoid then
local player = game.Players:FindFirstChild(otherPart.Parent.Name)
if player and canGet then
canGet = false
game.ReplicatedStorage.RemoteEvent:FireAllClients()
part:Destroy()
end
end
end
part.Touched:Connect(onTouch)
part.Touched:Connect(function(hit)
if hit.Parent:FindFirstChild("Humanoid") then
hit.Parent:BreakJoints()
end
end)
As it turns out Map1.End only works because :WaitForChild is only 1 time, example Instance:WaitForChild("Instance", 0.5 --The first one is the child we are looking and the second one is a cooldown)
I prefer using Players:GetPlayerFromCharacter() instead of :FindFirstChild()
I would prefer making a table like this:
local Players = game:GetService("Players")
local MapTable = {
Map1 = workspace.Map1,
Map2 = workspace.Map2,
Map3 = workspace.Map3,
}
for i,v in pairs(MapTable) do
v.End.Touched:Connect(function(Hit)
local IsPlayer = Players:GetPlayerFromCharacter(Hit.Parent)
if IsPlayer then
print("This is a player!")
else
print("This is not a player!")
end
end)
end
Gonna type it step by step to be cleared since I can’t process this on my brain. Please correct if I’m wrong
Add Script or LocalScript in the StarterPlayer - StarterCharacterScripts (Which script???)
Type this:
local Players = game:GetService("Players")
local MapTable = {
Map1 = workspace.Parts
}
for i,v in pairs(MapTable) do
v.End.Touched:Connect(function(Hit)
local IsPlayer = Players:GetPlayerFromCharacter(Hit.Parent)
if IsPlayer then
print("This is a player!")
else
print("This is not a player!")
end
end)
end
This’ll tag the end part of the 1st map, do the same for any other maps you have, just replace the Map1 with whatever its named.
Next, I don’t see the reason for making a client sided part to then have to send to the server, it’s useless. So, insert a Script in ServerScriptStorage and type out the following (read first so you’re not just copying code)
local collectionService = game:GetService("CollectionService")
local endParts = collectionService:GetTagged("endPart")
--so what we're doing is getting the parts that are tagged with endPart. GetTagged returns a table of the objects that are tagged with "endPart".
for _, part in pairs(endParts) do
--this means for each end part, we run this code
local debounce = false
part.Touched:Connect(function(hitPart)
if debounce then return end
debounce = true
--script is placed on a cooldown
local plr = game.Players:GetPlayerFromCharacter(hitPart.Parent)
if plr then
--found player
plr:FindFirstChild("leaderstats").Wins.Value += 1
plr:FindFirstChild("leaderstats").Gems.Value += 5
wait(3)
debounce = false
end
end)
end
Now, if you want to add another EndPart, you just need to tag it. Simple!