Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

how to make a "Click to attach Rope" tool? [closed]

Asked by 6 years ago

i was wondering if anyone knew how to make a tool that attaches a rope constraint to a Humanoid root part?

Locked by User#24403

This question has been locked to preserve its current state and prevent spam and unwanted comments and answers.

Why was this question closed?

1 answer

Log in to vote
5
Answered by 6 years ago
Edited 6 years ago

Question

i was wondering if anyone knew how to make a tool that attaches a rope constraint to a Humanoid root part?

Well here is how we do it.

(This is going to be a lengthy post because I wanted to elaborate on everything.) pls accept took forever

First we want to insert a tool into StarterPack so any players that join get the tool. Then we can name the tool to anything we want. In my case I named it to "AttachTo". (In my demonstration I am not using a handle so we can disable the "RequiresHandle" property so the .Activated signal fires without a handle in the tool. ) Now that we have a tool we need it to work when the player activates it. First we will use a LocalScript because we need to be able to index the target of the players mouse to see what they clicked on. I named my local script "AttachToHandler_Client" because it handles the clientside for our AttachTo tool.

The client side

Now that we have our localscript ready for editing, we need to be-able to send our mouse's target to the server. We can use remote events for this which seem complex but are pretty easily. You can learn more about remote events here aswell as here

We can get reference to our player on the client via the LocalPlayer property of the Player Service. To get a service we use game:GetService(serviceName) and it returns the service. So we can get reference to our players by defining a variable for the player's service and indexing LocalPlayer.

1local players = game:GetService("Players")
2local client = players.LocalPlayer

Now that we have reference to our player we can get reference to our mouse. We can use the :GetMouse method of a player instance. (This can only be called on the client). We will set a variable so we can easily index the properties of the mouse such as MouseTarget which is the instance the mouse is pointing at. (Sometimes nil if they are pointing at the sky)

1local mouse = client:GetMouse()

After that we should define our tool; our tool will be the parent of the script since we put the script inside the tool, and connect a function to the Activated signal for our tool. We do this so everytime the tool is activated it fires the function. (We connect signals with the :Connect method and pass a function)

1local tool = script.Parent
2 
3local function sendMouseTargetToServer()
4 
5end
6 
7tool.Activated:Connect(sendMouseTargetToServer)

We have defined our framework now to make it send the mouse's target to the server using a remote event. We will want to insert a "RemoteEvent" instance into our tool and name it "SendMouseTarget".

Now we can define the variable for our remote event and fire it when the function is called.

1local tool = script.Parent
2local sendMouseTargetEvent = tool:WaitForChild("SendMouseTarget")
3 
4local function sendMouseTargetToServer()
5    sendMouseTargetEvent:FireServer(mouse.Target)
6end
7 
8tool.Activated:Connect(sendMouseTargetToServer)

We have finished the client side.

The server side

We will insert a "ServerScript" instance into our tool. I named it based off how we named our local script. I named mine "AttachToHandler_Server" because it handles the serverside.

We will need reference to the HumanoidRootPart from the serverside (we are doing this serverside so we don't have players trying to pass other people's HumanoidRootParts through or another instance.) We know the parent of the tool will be the player's backpack. We can then index the player from there, and then the character. With reference to the character we can index the character's HumanoidRootPart. (Also the character property of a player instance doesn't exist instantly so we have to yield until it exists if it doesn't already yet. player.Character or player.CharacterAdded:Wait())

1local tool = script.Parent
2 
3local backpack = tool.Parent
4local player = backpack.Parent
5 
6local character = player.Character or player.CharacterAdded:Wait()
7local root = character:WaitForChild("HumanoidRootPart")

We will want to be able to receive the mousetarget so we will connect a function to the OnServerEvent signal of our remote event after we define our remote.

1local sendMouseTarget = tool:WaitForChild("SendMouseTarget")
2 
3local function receiveMouseTarget(player, target)
4 
5end
6 
7sendMouseTarget.OnServerEvent:Connect(receiveMouseTarget)

Now we have our function's frame ready, we can start our other functions such as the function we will use to create attachments for the rope we are creating. We will pass a part through our makeAttachment and a position of where to place the attachment. Now we create the attachment with Instance.new and set its position to our passed position, and the parent to our passed part. Then we return the attachment so we can use it.

1local function makeAttachment(part, pos)
2    local attachment = Instance.new("Attachment")
3    local pos = pos or Vector3.new()
4 
5    attachment.Position = pos
6    attachment.Parent = part
7 
8    return attachment
9end

Next we make a function for connecting the rope to our root and the mouse target. We will create two attachments, the distance between the two parts passed, and the new rope we are creating to connect with the attachments.

We set the Attachment0 property of newRope to our attachment0 property and do the same for the Attachment1 property but use attachment1

Next we set the rope to visible so we can see it, and then we set the length to the distance between the part0 and part1 so they don't try to teleport inside eachother.

Finally we set the parent to one of the parts, in my case I just set it to part0

01local function connectWithRopeConstraint(part0, part1)
02    local newRope = Instance.new("RopeConstraint")
03    local dist = (part0.Position - part1.Position).Magnitude
04 
05    local attachment0 = makeAttachment(part0)
06    local attachment1 = makeAttachment(part1)
07 
08    newRope.Attachment0 = attachment0
09    newRope.Attachment1 = attachment1
10 
11    newRope.Visible = true
12    newRope.Length = dist
13 
14    newRope.Parent = part0
15end

Now we go back to our receiveMouseTarget function since we have our rope function done. We want to check if the target exists so we don't try to index a nil value. Then we want to check if its a userdata so players don't try passing a table with a :IsA method and running unwanted code on the server. Once we know the target exists we check if its a basepart and if so continue and pass it in our connectWithRopeConstraint function with the root variable we have.

01local sendMouseTarget = tool:WaitForChild("SendMouseTarget")
02 
03local function receiveMouseTarget(player, target)
04    if type(target) == "userdata" and target then
05        if target:IsA("BasePart") then
06            connectWithRopeConstraint(root, target)
07        end
08    end
09end
10 
11sendMouseTarget.OnServerEvent:Connect(receiveMouseTarget)

You may notice the player can spam the tool and potentially crash the server with an auto clicker.

We can add a debounce variable somewhere at the top and handle it in our receiveMouseTarget function.

01local canUseMouseTargetReceived = true
02 
03-- rest of code
04 
05local function receiveMouseTarget(player, target)
06    if canUseMouseTargetReceived then
07        canUseMouseTargetReceived = false
08 
09        if type(target) == "userdata" and target then
10            if target:IsA("BasePart") then
11                connectWithRopeConstraint(root, target)
12            end
13        end
14 
15        wait(1)
16        canUseMouseTargetReceived = true
17    end
18end

The player can now only add a rope every 1 second. We are now finished.

The final code

Client

01local players = game:GetService("Players")
02 
03local client = players.LocalPlayer
04local mouse = client:GetMouse()
05local character = client.Character or client.CharacterAdded:Wait()
06 
07local tool = script.Parent
08local sendMouseTargetEvent = tool:WaitForChild("SendMouseTarget")
09 
10local function sendMouseTargetToServer()
11    sendMouseTargetEvent:FireServer(mouse.Target)
12end
13 
14tool.Activated:Connect(sendMouseTargetToServer)

Server

01local tool = script.Parent
02 
03local backpack = tool.Parent
04local player = backpack.Parent
05 
06local character = player.Character or player.CharacterAdded:Wait()
07local root = character:WaitForChild("HumanoidRootPart")
08 
09local sendMouseTarget = tool:WaitForChild("SendMouseTarget")
10local canUseMouseTargetReceived = true
11 
12local function makeAttachment(part, pos)
13    local attachment = Instance.new("Attachment")
14    local pos = pos or Vector3.new()
15 
View all 54 lines...

Extra

Uncopylocked place with all the sourcecode. Here

0
Guys is my post epic EpicMetatableMoment 1444 — 6y
1
I counted 1,434 words and 9,744 characters. Good job. Zafirua 1348 — 6y
0
Thanks Zafiura. I wanted to make sure they understood how the code worked aswell how to implement it before they used it. EpicMetatableMoment 1444 — 6y
0
Didn't have to write an essay.. lol good job Nickelz 37 — 6y
Ad