How do I make this "hand to system" work?

INTRODUCTION
I am not sure when, but up until recently my Hand to System had been working fine. I have watched countless videos but they are almost always no use or very vague. In advance, I would like to personally thank anyone who is attempting to help me out with this.

HOW THE “HAND TO SYSTEM” WORKS

While holding the tool that needs to be given, the employee enters the customer’s name in the GUI located on the left side labeled, “HAND TO PLAYER”. After entering their name the employee presses enter on their keyboard.

The customer is then prompted with a GUI for them to confirm whether or not this is their order. Pressing yes gives the customer the tool and awards the employee one point. Pressing “I didn’t order this” does nothing and closes the GUI. Pressing no revokes a point from the employee and the tool is not given out.

THE ISSUE
Everything for the most part works. The tool is given to the customer and the point is awarded.

My Friend’s End

My End

However, on my end, it shows that my friend is not holding the tool. And after the tool is given my friend reports that the tool is broken. They are not able to activate the animation that comes with the tool nor are they able to add anything to the tool.

WHERE EVERYTHING IS AND THE SCRIPTS
Workspace:
This is the main part of the system where things like GUI for the customer and the script that displays the group rank and points is held.
this is in workspace

Script for Datastore:

local groupID = 8532453
local minimumRank = 11

game.ReplicatedStorage.GiveSystem.GiveItem.OnServerEvent:Connect(function(plr, customer, order)
	pcall(function()
		if customer ~= nil and order ~= nil then
			local gui = script.Parent.Receiver:Clone()
			gui.Employee.Value = plr.Name
			order.Parent = gui
			gui.Frame.Question.Text = "WOULD YOU LIKE TO RECEIVE "..order.Name.." FROM "..plr.Name.."?"
			gui.Parent = customer.PlayerGui
		end
	end)
end)

local array = {}

game.Players.PlayerAdded:Connect(function(player)
	local leaderstats = Instance.new("Folder",player)
	leaderstats.Name = "leaderstats"
	
	local rank = Instance.new("StringValue", leaderstats)
	rank.Name = "Rank"
	rank.Value = player:GetRoleInGroup(groupID)
	
	if player:GetRankInGroup(groupID) >= minimumRank then
		local points = Instance.new("IntValue", leaderstats)
		points.Name = "Points"
		points.Value = game:GetService("DataStoreService"):GetDataStore("Points"):GetAsync("user_"..player.userId)
		array[player.Name] = points.Value
	else
		local points = Instance.new("StringValue", leaderstats)
		points.Name = "Points"
		points.Value = "N/A"
	end
end)

game.ReplicatedStorage.GiveSystem.AddPoint.OnServerEvent:Connect(function(cus,p)
	plr = game.Players:FindFirstChild(p)
	if plr ~= nil and plr.leaderstats.Points.Value ~= "N/A" then
		plr.leaderstats.Points.Value = plr.leaderstats.Points.Value + 1
		array[plr.Name] = plr.leaderstats.Points.Value
	end
end)

game.ReplicatedStorage.GiveSystem.RevokePoint.OnServerEvent:Connect(function(cus,p)
	plr = game.Players:FindFirstChild(p)
	if plr ~= nil and plr.leaderstats.Points.Value ~= "N/A" then
		plr.leaderstats.Points.Value = plr.leaderstats.Points.Value - 1
		array[plr.Name] = plr.leaderstats.Points.Value
	end
end)

game.Players.PlayerRemoving:Connect(function(player)
	if array[player.Name] ~= nil then
		game:GetService("DataStoreService"):GetDataStore("Points"):UpdateAsync("user_"..player.userId, function(oldValue)
			local newValue = array[player.Name]
			local val = newValue
			return newValue
		end)
		wait()
		array[player.Name] = nil
	end
end)

Script for EventFire:

local frame = script.Parent
local gui = frame.Parent

frame:TweenPosition(UDim2.new(0.5, -200, 0.5, -75))
local employee = gui:WaitForChild("Employee")
local item = nil

for i,v in next, gui:GetChildren() do
	if v.ClassName == "Tool" then
		item = v
	end
end

function onYes()
	game.ReplicatedStorage.GiveSystem.AddPoint:FireServer(gui.Employee.Value)
	item.Parent = game.Players.LocalPlayer.Backpack
	frame:TweenPosition(UDim2.new(0.5, -200, 0, -121))
	wait(1)
	script.Parent:Destroy()
end

function onWrong()
	frame:TweenPosition(UDim2.new(0.5, -200, 0, -121))
	wait(1)
	script.Parent:Destroy()
end

function onNo()
	game.ReplicatedStorage.GiveSystem.RevokePoint:FireServer(gui.Employee.Value)
	frame:TweenPosition(UDim2.new(0.5, -200, 0, -121))
	wait(1)
	script.Parent:Destroy()
end

frame.Yes.MouseButton1Click:Connect(onYes)
frame.No.MouseButton1Click:Connect(onNo)
frame.NotMine.MouseButton1Click:Connect(onWrong)

ReplicatedStorage:
this is in replicated storage

StarterGui:
this is in starter GUI

Note: The LocalScript at the top is for something else and is not apart of this system. Everything that is apart of the system in StarterGui is located under "HandToPlayerGUI.

Script for HandTo:

local groupID = 8532453
local minimumStaffRank = 11

local giveFrame = script.Parent:WaitForChild("GiveFrame")
local giveTextBox = giveFrame:WaitForChild("GiveTextBox")

if game.Players.LocalPlayer:GetRankInGroup(groupID) < minimumStaffRank then
	script.Parent:Destroy()
	return
else
	giveFrame.Visible = true
end

giveTextBox.FocusLost:Connect(function(enterPressed)
	if enterPressed then
		local count = 0
		local plr = nil
		for i,v in next, game.Players:GetChildren() do
			if string.len(v.Name) >= string.len(giveTextBox.Text) then
				if string.lower(giveTextBox.Text) == string.lower(string.sub(v.Name,0,string.len(giveTextBox.Text))) then
					count = count + 1
					plr = v
				end
			end
		end
		giveTextBox.Text = "PLAYER NAME"
		if count == 1 and game.Players.LocalPlayer.Name ~= plr.Name then
			local item = nil
			for i,v in next, game.Players.LocalPlayer.Character:GetChildren() do
				if v.ClassName == "Tool" then
					item = v
				end
			end
			if item ~= nil then
				game.ReplicatedStorage.GiveSystem.GiveItem:FireServer(plr,item)
			end
			giveTextBox.Text = "PLAYER NAME"
		end
	end
end)

CLOSING STATEMENT
Again I would like to thank anyone who has spent any time in trying to figure this out, I truly appreciate it.

3 Likes

You should set the parent of the item on the server.

And, this is not related to the problem and not necessary, but instead of

local item = nil
for i,v in next, game.Players.LocalPlayer.Character:GetChildren() do
	if v.ClassName == "Tool" then
		item = v
	end
end

you could do

local item = game.Players.LocalPlayer.Character:FindFirstChildOfClass("Tool")
2 Likes

Just thought I’d pitch this in: Your remotes are extremely insecure! With your current system, you’ve given anyone in-game the authority to fire the RevokePoint or AddPoint event and pass in any employee who is currently in the server and change their leaderstats.

2 Likes

Hi, thanks for responding I really do appreciate it.
I did take your advice on using,

local item = game.Players.LocalPlayer.Character:FindFirstChildOfClass("Tool")

instead of what I had before.

Forgive me I am still learning the basics of scripting, I attempted to set the parent of the item server-sided by having this script in ServerScriptService:

game.ReplicatedStorage.GiveSystem.GiveItem.OnServerEvent:Connect(function(plr,item)
	local item = game.Players.LocalPlayer.Character:FindFirstChildOfClass("Tool")
	item.Parent = game.Players[plr.item].Backpack
end)

I have tested it and the same problem arises, but this is most likely due to my lack of knowledge in scripting. Is there something I should be doing differently?

If you only want the item to be given when the customer presses yes, you should probably do this in the function where you give the point.

game.ReplicatedStorage.GiveSystem.AddPoint.OnServerEvent:Connect(function(customer, employeeName)
	local employee = game.Players:FindFirstChild(employeeName)
	if not employee then
		return
	end
	local pointsValObj = employee.leaderstats.Points
	local currentPoints = pointsValObj.Value
	local item = employee.Character:FindFirstChildOfClass("Tool")
	if item and currentPoints ~= "N/A" then
		item.Parent = customer.Backpack
		local newPoints = currentPoints+1
		pointsValObj.Value = newPoints
		array[plr.Name] = newPoints
	end
end)

I used this code to replace what I originally had in ServerScriptService.

game.ReplicatedStorage.GiveSystem.AddPoint.OnServerEvent:Connect(function(customer, employeeName)
	local employee = plrs:FindFirstChild(employeeName)
	if not employee then
		return
	end
	local pointsValObj = employee.leaderstats.Points
	local currentPoints = pointsValObj.Value
	local item = employee.Character:FindFirstChildOfClass("Tool")
	if item and currentPoints ~= "N/A" then
		item.Parent = customer.Backpack
		local newPoints = currentPoints+1
		pointsValObj.Value = newPoints
		array[plr.Name] = newPoints
	end
end)

The same problem arises, and here is the output when I tested it.

My bad, I wrote plrs when it should have been game.Players. I’ve fixed that now.

1 Like

Thanks a ton, that fixed the issue with the output. Would you possibly mind checking this testing game out? It has the whole Hand to System in it along with a tool for testing, I feel like it should be working but there might have been some errors on my part because the tool keeps breaking.

https://www.roblox.com/games/6210307814/testing-place

I added a new remote event and a new local script. The gui clone isn’t sent from the server anymore. I moved the gui to the GiveSystem folder in ReplicatedStorage and made a local script that clones it on the client. That local script should handle what EventFire used to handle. Because ReplicatedStorage is a storage service, it felt like a more logical place to store the gui. I also added some checks on the server. The system seems to be working now. The item is now only removed from the sender if the receiver wants it, so that it won’t just disappear from the game.
testing place.rbxl (87.2 KB)

2 Likes

Thank you so much! The hand to system is working properly now. I was honestly stuck on this problem for the longest time and I am just beyond grateful for how much you have helped me.

1 Like