How can I create a grapple hook like in Just Cause?

Hello!
I am trying to make a grappling hook like the one Rico Rodriguez has in the game Just Cause 4. Currently, I’m just trying to make a RopeConstraint that attaches to the character’s right forearm to the player’s mouse.hit. For some reason, it’s not doing anything. It’s not even giving me an error in the Output.

Here’s what I have so far:

local character = player.Character
local arm = character.RightLowerArm
local mouse = player:GetMouse()


mouse.Button2Up:Connect(function()
	local rope = Instance.new("RopeConstraint")	
	local at0 = Instance.new("Attachment")
	local at1 = Instance.new("Attachment")
	rope.Parent = character
	rope.Thickness = 0.05
	rope.Attachment0 = at0
	rope.Attachment1 = at1
	rope.Length = 10
	at0.Position = arm.Position
	at1.Position = mouse.hit.p
	print(mouse.hit.p)
end)

The LocalScript is under StarterCharacterScripts.

Thank you for your help!

4 Likes

Maybe this thread would help you out. Be sure to use the search feature

Well, the thing with this is it does look a like what I’m going for, but it doesn’t answer my question. I’m not very advanced in scripting, and don’t know where to look in the open-source place to find an example or whatever. I also don’t want to just blatantly copy something, I’m trying to make it myself.

Not sure if constraints are the best thing here but if you’re using them I’d suggest a rod constraint. Instead of creating a new one everytime, just change the one attachment each time. Set the rod length to the magnitude of attachment1.WorldPosition - attachment0.WorldPosition, and I guess you could try tweening its length to 0? Not sure how this would work with network ownership.

https://gyazo.com/1a61b6fd1e7189c8230c002916c44e3b

4 Likes

Honestly now that I think about it you should tween the humanoidrootpart and use the rod purely for aesthetics

Sorry for the late response!
I had the same idea, and your RodConstraint idea is also something I will try out, but I still don’t know what’s making my script not work.

What does the output say? Where is the script located?

Just noticed its in startcharacterscripts, try printing when the button2 is fired to see if the issue is there

The functions works, because I get the print on mouse.hit.p in the output.

You need to parent the attachments to something

I tried this. Notice under my epic note the changes I made.

local character = player.Character
local arm = character.RightLowerArm
local mouse = player:GetMouse()


mouse.Button2Up:Connect(function()
	local rope = Instance.new("RopeConstraint")	
	local at0 = Instance.new("Attachment")
	local at1 = Instance.new("Attachment")
	--Epic note
	rope.Parent = workspace.Terrain
	at0.Parent = workspace.Terrain
	at1.Parent = workspace.Terrain
	rope.Thickness = 0.05
	rope.Attachment0 = at0
	rope.Attachment1 = at1
	rope.Length = 10
	at0.Position = arm.Position
	at1.Position = mouse.hit.p
	print(mouse.hit.p)
end)

Still nothing.

Attachments need to be parented to a part

I FIGURED IT OUT!
But now I have a whole new problem:
https://gyazo.com/1f1663f3aa254c0a48b013e02ddf49dc
(Ignore the red laser)

Also, I might have to go sleep in a bit so if I suddenly stop responding you know why.

I think you’re using attachments wrong, the “position” value is local to the part they are inside, so if its 0,1,0, it will appear one stud above the origin of the part. What you would want to do is make a attachment inside the arm of the character, then put the second attachment inside the part that you hit and set its world position to the place where it hit.

Great, that works perfectly, but it suspends the character so it can’t move. How do I fix that?

If you want to move the character closer you can either;

A). Tween the characters root part toward the objective

B). Tween the length of the rod

C). Add a align position to the player or legacy body mover

I’d do A

Okay, so I edited the script for it, and now this is happening.
https://gyazo.com/a08adb8e6997f6884c81ed355c31e1d1
Basically the character is getting separated from its root part.

Script
local player = game.Players.LocalPlayer
local character = player.Character
local arm = character.RightLowerArm
local mouse = player:GetMouse()
local deployed = false

--Tween Materials
local ts = game:GetService("TweenService")
local rootPart = character.HumanoidRootPart

mouse.Button2Up:Connect(function()
	if deployed == false then
		deployed = true
		local rope = Instance.new("RopeConstraint")	
		local at0 = Instance.new("Attachment")
		local at1 = Instance.new("Attachment")
		rope.Parent = workspace
		rope.Visible = true
		at0.Parent = arm
		at1.Parent = mouse.target
		rope.Thickness = 0.05
		rope.Attachment0 = at0
		rope.Attachment1 = at1
		rope.Length = .1
		at0.WorldPosition = arm.Position
		at1.WorldPosition = mouse.hit.p
		print(mouse.target)
		print(mouse.hit.p)
		
		local tweenInfo = TweenInfo.new(rope.CurrentDistance / 50, Enum.EasingStyle.Linear, Enum.EasingDirection.Out, 0, false, 0)
		local tweenProperties = {Position = at1.WorldPosition}
		local tween = ts:Create(rootPart,tweenInfo,tweenProperties)
		tween:Play()
		wait(rope.CurrentDistance / 50)	
		deployed = false
		rope:Destroy()
		at0:Destroy()
		at1:Destroy()
	end
end)

Try {CFrame = CFrame.new(at1.WorldPosition), thats how it works.