I have a script for a grappling hook which works fine for the most part. However, the character goes crazy as soon as they begin being dragged by the Spring (which acts as the rope between the gun and the hook) as they are in a Physics state. It would be nice if this didn’t happen. As for the second half of the title, I speculate this could be done with AlignOrientation, but I would like some guidance on how to implement this as I’m not too good with the forces in Roblox.
The main script for the grappling hook (a ModuleScript called by a LocalScript and server Script):
local runserv = game:GetService("RunService")
local players = game:GetService("Players")
local tweenserv = game:GetService("TweenService")
local tool = script.Parent
local base = tool:WaitForChild("base")
local spring = base.spring
local hook = tool:WaitForChild("hook")
local hookweld = hook.hookweld
local hookref = tool:WaitForChild("hookref")
local msg = script:WaitForChild("msg")
local active = script:WaitForChild("gamingrn")
--client only vars
local player = nil
local mouse = nil
local curtween = nil
local grapplegun = {}
local function togglegrapplestate(active)
local humanoid = player.Character and player.Character:FindFirstChild("Humanoid")
if humanoid then
wait()
if active then
humanoid:SetStateEnabled(Enum.HumanoidStateType.Running, false)
humanoid:ChangeState(Enum.HumanoidStateType.Physics)
else
humanoid:SetStateEnabled(Enum.HumanoidStateType.Running, true)
humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
end
end
end
local function clientinit()
player = players.LocalPlayer
mouse = player:GetMouse()
--prevent player from hitting themself
mouse.TargetFilter = player.Character
tool.Activated:Connect(function()
if not grapplegun.IsActivated() and mouse.Target then
msg:FireServer(true, mouse.Hit.Position)
togglegrapplestate(true)
end
end)
tool.Deactivated:Connect(function()
msg:FireServer(false)
togglegrapplestate(false)
end)
tool.Unequipped:Connect(function()
msg:FireServer(false)
togglegrapplestate(false)
end)
end
local function serverinit()
msg.OnServerEvent:Connect(function(player, _activated, targetpos)
active.Value = _activated
if grapplegun.IsActivated() then
grapplegun:Fire(targetpos)
else
grapplegun:Reset()
end
end)
end
local function init()
if runserv:IsClient() then
print("client")
clientinit()
elseif runserv:IsServer() then
print("server")
serverinit()
end
end
function grapplegun.IsActivated()
return active.Value
end
function grapplegun:Fire(targetpos)
local initpos = hookref.Position
--distance from gun 2 mouse
local distance = (targetpos - initpos).Magnitude
hookweld.Enabled = false
hook.Anchored = true
wait()
local hookInfo = TweenInfo.new(distance/500, Enum.EasingStyle.Linear)
local hookTween = tweenserv:Create(hook, hookInfo, {Position = targetpos})
--hook.Position = targetpos
hookTween:Play()
curtween = hookTween
hookTween.Completed:Connect(function()
spring.FreeLength = distance
local info = TweenInfo.new(distance/100, Enum.EasingStyle.Linear)
local tween = tweenserv:Create(spring, info, {FreeLength = 1})
tween:Play()
curtween = tween
end)
end
function grapplegun:Reset()
if curtween then
curtween:Cancel()
end
hook.CFrame = hookref.CFrame
hookweld.Enabled = true
hook.Anchored = false
spring.FreeLength = 1
end
init()
return grapplegun