I’m currently making a grapple hook. This grapple was made with rope constraints and the shape was a bit plain, so I used spring constraints to create a pretty decent grapple hook. However, when I fired the hook using FastCast, I ran into an issue where the player would freeze while the hook was stuck in the ground. I would like the spring to just have its shape, or for the player to move while it’s being fired.
local module = require(game.ReplicatedStorage.FastCastRedux)
game.ReplicatedStorage.HookFireEvent.OnServerEvent:Connect(function(plr, position, value)
local caster = module.new()
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Blacklist
params.IgnoreWater = true
local cb = module.newBehavior()
cb.RaycastParams = params
cb.Acceleration = Vector3.new(0, -workspace.Gravity/1.5, 0)
cb.AutoIgnoreContainer = false
cb.MaxDistance = 200000
cb.CosmeticBulletContainer = workspace.Bullets
cb.CosmeticBulletTemplate = game.ReplicatedStorage.hook
module.VisualizeCasts = false
caster.LengthChanged:Connect(function(cast, lastpoint, direction, length, velocity, bullet)
if bullet then
local bul = bullet.Size.Z/2
local offset = CFrame.new(0, 0, -(length - bul))
bullet.CFrame = CFrame.lookAt(lastpoint, lastpoint + direction):ToWorldSpace(offset) * CFrame.Angles(0, math.rad(180), 0)
end
end)
params.FilterDescendantsInstances = {plr.Character}
cb.RaycastParams = params
local origin = plr.Character.Handle.Handle.Position
local direction = ((position + Vector3.new(0, 0.5, 0)) - origin).Unit
caster:Fire(origin, direction, 400, cb, plr)
local rope1 = Instance.new("RopeConstraint")
local visual = game.ReplicatedStorage.VisualSpring:Clone()
visual.Parent = game.ReplicatedStorage
visual.Coils = 8
visual.Radius = 1.5
local tween = game.TweenService:Create(
visual,
TweenInfo.new(1.25, Enum.EasingStyle.Exponential, Enum.EasingDirection.Out),
{Coils = 0, Radius = 0.15}
)
local brick = Instance.new("Part") --Creates the part where the Attachment will be held
brick.Size = Vector3.new(0.05,0.05,0.05)
brick.Parent = game.Workspace
brick.Transparency = 1
brick.CanCollide = false
brick.Anchored = true
brick.Position = position --Brick positioned on click
brick.Name = plr.Name.."attb"
local UA = Instance.new("Part")
UA.Size = Vector3.new(0.5,0.5,0.5) --Creates the Unanchored part that is attached to the other brick
UA.CustomPhysicalProperties = PhysicalProperties.new(100,0,0,0,0) --Make it the heaviest it can be to stop it from bugging out
UA.Parent = brick
UA.Shape = "Ball"
UA.Transparency = 1
UA.CanCollide = false
UA.Anchored = false
UA.Position = brick.Position --Put it inside the brick
local UAatt = Instance.new("Attachment") --Attachment the goes inside the ball
UAatt.Parent = UA
UAatt.WorldPosition = UA.Position
local Brickatt = Instance.new("Attachment") --Attachment that goes inside the brick
Brickatt.Parent = brick
Brickatt.WorldPosition = brick.Position
caster.LengthChanged:Connect(function(cast, lastpoint, direction, length, velocity, bullet)
if bullet then
brick.Position = bullet.Position
UA.Position = brick.Position
UAatt.WorldPosition = UA.Position
Brickatt.WorldPosition = brick.Position
end
end)
local BrUARope = Instance.new("RopeConstraint") --Creates a rope between the anchored brick and the unachored ball it in place
BrUARope.Parent = brick
BrUARope.Attachment0 = Brickatt
BrUARope.Attachment1 = UAatt
BrUARope.Length = 0.1
BrUARope.Thickness = 1
rope1.Thickness = 0
rope1.Color = BrickColor.new(0, 0, 0)
visual.Parent = plr.Character
visual.Attachment0 = plr.Character.HumanoidRootPart.RootAttachment
visual.Attachment1 = UAatt
visual.Coils = 4
visual.Radius = 1.5
tween:Play()
caster.RayHit:Connect(function(cast, result, velocity, bullet)
if bullet and result then
rope1.Attachment0 = plr.Character.Torso.BodyFrontAttachment
rope1.Attachment1 = UAatt
rope1.Parent = plr.Character
rope1.Name = "Rope"
rope1.Length = plr:DistanceFromCharacter(brick.Position) + 2
rope1.Visible = true
local hit = result.Instance
local char = hit.Parent
local hum = char:FindFirstChildWhichIsA("Humanoid")
if hum then
hum:TakeDamage(10)
end
bullet.CFrame *= CFrame.new(0, 0, .5)
bullet.Anchored = true
end
end)
end)
game.ReplicatedStorage.HookPullEvent.OnServerEvent:Connect(function(plr)
local rope1:RopeConstraint = plr.Character:FindFirstChild("Rope")
local visual:SpringConstraint = plr.Character:FindFirstChild("VisualSpring")
local accle = 0
local value = true
if rope1 and visual then
while value == true do
task.wait()
accle += 0.25
rope1.Length -= accle
if rope1.Length <= 1 then
rope1:Destroy()
visual:Destroy()
local ropedelete = game.Workspace:FindFirstChild(plr.Name.."attb") --Deletes everything
ropedelete:Destroy()
game.ReplicatedStorage.HookEvent:FireClient(plr)
if workspace.Bullets:FindFirstChild(plr.Name.."sBullet") then
workspace.Bullets:FindFirstChild(plr.Name.."sBullet"):Destroy()
end
value = false
else
end
end
end
end)
Main Script
repeat wait() until game.Players.LocalPlayer
local player = game.Players.LocalPlayer
local mouse = player:GetMouse()
local accle = 0
local rope1 = Instance.new("RopeConstraint")
local visual = game.ReplicatedStorage.VisualSpring:Clone()
visual.Parent = game.ReplicatedStorage
visual.Coils = 4
visual.Radius = 1
local tween = game.TweenService:Create(
visual,
TweenInfo.new(0.25, Enum.EasingStyle.Exponential, Enum.EasingDirection.Out),
{Coils = 0, Radius = 0.15}
)
local function onMouseClick(position)
if script.Value.Value == false then
script.Value.Value = true
game.ReplicatedStorage.HookFireEvent:FireServer(mouse.Hit.Position, script.Value.Value)
end
end
local function onMouseUp()
local pull = player.Character:WaitForChild("Humanoid").Animator:LoadAnimation(player.Character.Pull)
local pull2 = player.Character:WaitForChild("Humanoid").Animator:LoadAnimation(player.Character.Pull2)
pull:Play()
task.delay(pull.Length, function()
if script.Value.Value then
pull2:Play()
end
end)
while script.Value.Value do
task.wait()
accle += 0.25
rope1.Length -= accle
if rope1.Length <= 1 then
accle = 0
rope1.Parent = game.ReplicatedStorage
visual.Parent = game.ReplicatedStorage
local ropedelete = game.Workspace:FindFirstChild(player.Name.."attb") --Deletes everything
ropedelete:Destroy()
script.Value.Value = false
script.Parent.Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
else
script.Parent.Humanoid:ChangeState(Enum.HumanoidStateType.Physics)
end
end
pull2:Stop()
end
game.ReplicatedStorage.HookEvent.OnClientEvent:Connect(function()
script.Value.Value = false
script.Parent.Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
end)
mouse.Button1Down:Connect(function()
onMouseClick()
end)
mouse.Button1Up:Connect(function()
game.ReplicatedStorage.HookPullEvent:FireServer()
script.Parent.Humanoid:ChangeState(Enum.HumanoidStateType.Physics)
end)
Local script
Character