You can write your topic however you want, but you need to answer these questions:
-
What do I want to achieve?
I am making a grapple hook system. When you press Q or E, you will grapple towards where ever your mouse is pointing. -
What is the issue? Include screenshots / videos if possible!
Whenever I “double-hook”, or press Q and E at the same time, the script breaks entirely and the player won’t be able to grapple.
As seen here:
https://gyazo.com/13ac5828518ca9a6d959d7c5d1aef82a
Client Script
--//Services
local InputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
--//Locals
local player = game.Players.LocalPlayer
local camera = workspace.CurrentCamera
local mouse = player:GetMouse()
local character = player.Character
local CameraShaker = require(game.ReplicatedStorage.CameraShaker)
local RightHook = false
local LeftHook = false
--.. gear stuff
local gearFolder = script.Parent.Parent
local valuesFolder = gearFolder:WaitForChild("Values")
local remotesFolder = gearFolder:WaitForChild("Remotes")
local animationFolder = gearFolder:WaitForChild("Animations")
local burstCooldown = 2
local Multiplier = 1
local gasBoost = false
local Blades = false
--..body movers
local bodyGyro = character.HumanoidRootPart:WaitForChild("BodyGyro")
local bodyVelocity = character.HumanoidRootPart:WaitForChild("BodyVelocity")
--..debounce
local debounce = false
local cooldown = (1/4)
--..camera stuff
local tiltAngle = 0
local canReload = true
local BladesAmount = valuesFolder.BladeAmount.Value
local GasAmount = valuesFolder.GasAmount.Value
local ODMGui = gearFolder.ODMGui:Clone()
ODMGui.Parent = player.PlayerGui
local gasBar = ODMGui.GasFrame.count
local function UpdateBar()
gasBar:TweenSize(UDim2.new(0.296, 0,GasAmount/-1526.71756, 0))
end
UpdateBar()
local Grapple = animationFolder["Grapple"]
local BladeChange = animationFolder["BladeChange"]
local RightOrbit = animationFolder["RightOrbit"]
local LeftOrbit = animationFolder["LeftOrbit"]
local VerticalSpin = animationFolder["VerticalSpin"]
local HorizontalSpin = animationFolder["HorizontalSpin"]
--..animation stuff
--local leftCycle = character.Humanoid:LoadAnimation(animationFolder["LeftCycle"])
--local rightCycle = character.Humanoid:LoadAnimation(animationFolder["RightCycle"])
--//Functions
local function lerpUnit(a ,b ,c)
return a + (b - a) * c
end
local function checkHookPlayerDistance()
return math.abs((character.HumanoidRootPart.CFrame.Position - mouse.Hit.Position).Magnitude)
end
local function returnHookDirection(side)
if valuesFolder[side.."Position"].Value == Vector3.new() then
return Vector3.new()
end
return (valuesFolder[side.."Position"].Value - character.HumanoidRootPart.CFrame.Position).Unit
end
local function onInputBegan(key, event)
if event then return end
if debounce then return end
--..scripting the right hook ejection key
if key.KeyCode == Enum.KeyCode.E and not debounce then
if checkHookPlayerDistance() <= valuesFolder["MaxHookDistance"].Value then
if mouse.Target ~= nil then
--.. we can eject hook and do other cool stuff
remotesFolder["Grapple"]:FireServer({"Eject", "Right", mouse.Hit.Position, mouse.Target})
debounce = true
RightHook = true
wait(cooldown)
debounce = false
GasAmount = GasAmount - 1
local track = character:WaitForChild("Humanoid"):LoadAnimation(Grapple)
track:Play()
for i,v in pairs (character.Humanoid:GetPlayingAnimationTracks())do
v:Stop()
end
track.Priority = Enum.AnimationPriority.Action
print(GasAmount)
UpdateBar()
end
end
elseif key.KeyCode == Enum.KeyCode.Q and not debounce then
if checkHookPlayerDistance() <= valuesFolder["MaxHookDistance"].Value then
if mouse.Target ~= nil then
--.. we can eject hook and do other cool stuff
remotesFolder["Grapple"]:FireServer({"Eject", "Left", mouse.Hit.Position, mouse.Target})
debounce = true
LeftHook = true
wait(cooldown)
debounce = false
GasAmount = GasAmount - 1
local track = character:WaitForChild("Humanoid"):LoadAnimation(Grapple)
track:Play()
for i,v in pairs (character.Humanoid:GetPlayingAnimationTracks())do
v:Stop()
end
track.Priority = Enum.AnimationPriority.Action
print(GasAmount)
UpdateBar()
end
end
end
end
local function onInputEnded(key, event)
if event then return end
if key.KeyCode == Enum.KeyCode.E then
if valuesFolder["RightHooked"].Value or valuesFolder["RightEjected"].Value then
remotesFolder["Grapple"]:FireServer({"Retract", "Right"})
RightHook = false
end
elseif key.KeyCode == Enum.KeyCode.Q then
if valuesFolder["LeftHooked"].Value or valuesFolder["LeftEjected"].Value then
remotesFolder["Grapple"]:FireServer({"Retract", "Left"})
LeftHook = false
end
end
end
--//Events
InputService.InputBegan:Connect(onInputBegan)
InputService.InputEnded:Connect(onInputEnded)
InputService.InputBegan:connect(function(input, isTyping)
if isTyping then return end
if input.KeyCode == Enum.KeyCode.R and canReload and BladesAmount > 0 and not Blades then
remotesFolder:WaitForChild("Reload"):FireServer()
canReload = false
Blades = true
for i,v in pairs (character.Humanoid:GetPlayingAnimationTracks())do
v:Stop()
end
local track = character:WaitForChild("Humanoid"):LoadAnimation(BladeChange)
track:Play()
track.Priority = Enum.AnimationPriority.Action
wait(1)
canReload = true
end
end)
InputService.InputBegan:connect(function(input, isTyping)
if isTyping then return end
if input.KeyCode == Enum.KeyCode.Space and GasAmount > 0 and LeftHook or RightHook then
gasBoost = true
Multiplier = 1.5
print("Gas! Gas! Gas!")
remotesFolder["Boost"]:FireServer(gasBoost)
GasAmount = GasAmount - 1
print(GasAmount)
UpdateBar()
end
end)
InputService.InputEnded:connect(function(input, isTyping)
if isTyping then return end
if input.KeyCode == Enum.KeyCode.Space then
gasBoost = false
Multiplier = 1
print("Stopped the gas function.")
remotesFolder["Boost"]:FireServer(gasBoost)
end
end)
InputService.InputBegan:connect(function(input, isTyping)
if isTyping then return end
if input.KeyCode == Enum.KeyCode.R and canReload and Blades then
remotesFolder:WaitForChild("ReturnBlade"):FireServer()
canReload = false
Blades = false
for i,v in pairs (character:WaitForChild("Humanoid"):GetPlayingAnimationTracks())do
v:Stop()
end
local track = character:WaitForChild("Humanoid"):LoadAnimation(BladeChange)
track:Play()
track.Priority = Enum.AnimationPriority.Action
wait(1)
canReload = true
end
end)
InputService.InputBegan:connect(function(input, isTyping)
local chance = math.random(1,2)
if isTyping then return end
if input.UserInputType == Enum.UserInputType.MouseButton1 and Blades then
if chance == 1 then
for i,v in pairs (character:WaitForChild("Humanoid"):GetPlayingAnimationTracks())do
v:Stop()
end
local track = character:WaitForChild("Humanoid"):LoadAnimation(VerticalSpin)
track:Play()
track.Priority = Enum.AnimationPriority.Action
remotesFolder["Attack"]:FireServer()
elseif chance == 2 then
for i,v in pairs (character:WaitForChild("Humanoid"):GetPlayingAnimationTracks())do
v:Stop()
end
local track = character:WaitForChild("Humanoid"):LoadAnimation(HorizontalSpin)
track:Play()
track.Priority = Enum.AnimationPriority.Action
remotesFolder["Attack"]:FireServer()
end
end
end)
InputService.InputBegan:connect(function(input, isTyping)
local DoneOnce = false
local briefCooldown = 0.3
if isTyping then return end
if input.KeyCode == Enum.KeyCode.W then
if not DoneOnce then
DoneOnce = true
wait(briefCooldown)
DoneOnce = false
return
else
if DoneOnce == true then
print("Burst!")
DoneOnce = false
end
end
end
end)
--//Loops
while true do
RunService.Heartbeat:Wait()
if valuesFolder["RightHooked"].Value or valuesFolder["LeftHooked"].Value then
character.Humanoid.AutoRotate = false
-- body gyro
bodyGyro.MaxTorque = lerpUnit(bodyGyro.MaxTorque, Vector3.new(150000 * Multiplier, 150000 * Multiplier, 150000 * Multiplier), 0.3)
bodyGyro.CFrame = CFrame.new(character.HumanoidRootPart.Position, valuesFolder["RightPosition"].Value + valuesFolder["LeftPosition"].Value)
-- body velocity
bodyVelocity.MaxForce = lerpUnit(bodyVelocity.MaxForce, Vector3.new(200000 * Multiplier, 200000 * Multiplier, 200000 * Multiplier), 0.1)
if InputService:IsKeyDown(Enum.KeyCode.A) then
for i,v in pairs (character.Humanoid:GetPlayingAnimationTracks())do
v:Stop()
end
local track = character:WaitForChild("Humanoid"):LoadAnimation(RightOrbit)
track:Play()
track.Priority = Enum.AnimationPriority.Movement
bodyVelocity.Velocity = lerpUnit(bodyVelocity.Velocity, (returnHookDirection("Right") + returnHookDirection("Left") + (-character.HumanoidRootPart.CFrame.RightVector)) * (valuesFolder["Magnitude"].Value - 30) * Multiplier, 0.08)
--bodyGyro.CFrame = CFrame.new(character.HumanoidRootPart.Position, valuesFolder["RightPosition"].Value + valuesFolder["LeftPosition"].Value) * CFrame.Angles(0, 0, math.rad(25))
elseif InputService:IsKeyDown(Enum.KeyCode.D) then
for i,v in pairs (character.Humanoid:GetPlayingAnimationTracks())do
v:Stop()
end
local track = character:WaitForChild("Humanoid"):LoadAnimation(LeftOrbit)
track:Play()
track.Priority = Enum.AnimationPriority.Movement
bodyVelocity.Velocity = lerpUnit(bodyVelocity.Velocity, (returnHookDirection("Right") + returnHookDirection("Left") + (character.HumanoidRootPart.CFrame.RightVector)) * (valuesFolder["Magnitude"].Value - 30) * Multiplier, 0.08)
--bodyGyro.CFrame = CFrame.new(character.HumanoidRootPart.Position, valuesFolder["RightPosition"].Value + valuesFolder["LeftPosition"].Value) * CFrame.Angles(0, 0, math.rad(-25))
else
bodyVelocity.Velocity = lerpUnit(bodyVelocity.Velocity, (returnHookDirection("Right") + returnHookDirection("Left")) * (valuesFolder["Magnitude"].Value * Multiplier), 0.2)
--bodyGyro.CFrame = CFrame.new(character.HumanoidRootPart.Position, valuesFolder["RightPosition"].Value + valuesFolder["LeftPosition"].Value) * CFrame.Angles(0, 0, math.rad(0))
end
camera.FieldOfView = lerpUnit(camera.FieldOfView, 85, 0.05)
else
-- reset values when we arent hooked
character.Humanoid.AutoRotate = true
bodyVelocity.MaxForce = lerpUnit(bodyVelocity.MaxForce, Vector3.new(), 0.2)
bodyGyro.MaxTorque = lerpUnit(bodyGyro.MaxTorque, Vector3.new(), 0.3)
camera.FieldOfView = lerpUnit(camera.FieldOfView, 70, 0.05)
end
end
--valuesFolder["Magnitude"].Value
Server Script
--//Services
local TweenService = game:GetService("TweenService")
--//Locals
--..tweens tuff
local tweenInfo = TweenInfo.new(0.2, Enum.EasingStyle.Linear, Enum.EasingDirection.Out, 0, false, 0)
local tweenTable = {}
local leftgrapple = false
local rightgrapple = false
local Blades = false
--.. gear stuff
local gearFolder = script.Parent.Parent
local valuesFolder = gearFolder:WaitForChild("Values")
local remotesFolder = gearFolder:WaitForChild("Remotes")
local Animations = gearFolder:WaitForChild("Animations")
--//Functions
local function createAttachment(_ancestor)
local attachment = Instance.new("Attachment")
attachment.Parent = _ancestor
attachment.Name = "RopeAttachment"
return attachment
end
local function createPseudoHook(_ancestor)
local hook = Instance.new("Part")
hook.Anchored = true
hook.Size = Vector3.new(0.1,0.1,0.1)
hook.CFrame = _ancestor.CFrame
hook.Parent = _ancestor
hook.Name = "PseudoHook"
return hook
end
--.. really and truly its a spring but it has the cool effect we want
local function createRope(_ancestor, attahcment0, attachment1)
local rope = Instance.new("SpringConstraint")
rope.Name = "Rope"
rope.Thickness = 0.1
rope.Coils = 6
rope.Radius = 2
rope.Color = BrickColor.Black()
rope.Visible = true
rope.Attachment0 = attahcment0
rope.Attachment1 = attachment1
rope.Parent = _ancestor
return rope
end
local function createWeld(part0, part1)
local weld = Instance.new("WeldConstraint")
weld.Part0 = part0
weld.Part1 = part1
weld.Parent = part1
weld.Name = "HookWeld"
end
local function onServerEvent(client, array)
local character = client.Character
if array[1] == "Eject" then
if array[2] == "Right" then
if valuesFolder["RightEjected"].Value then return end
if valuesFolder["RightHooked"].Value then return end
valuesFolder["RightEjected"].Value = true
character["Torso"].rightgrapple.Eject.Enabled = true
local hook = createPseudoHook(character["Torso"].rightgrapple)
local attachment = createAttachment(hook)
local rope = createRope(hook, hook.Parent["RopeAttachment"], attachment)
tweenTable.tweenHookCFrameRight = TweenService:Create(hook, tweenInfo, {CFrame = CFrame.new(array[3])})
tweenTable.tweenRopeRadiusRight = TweenService:Create(rope, tweenInfo, {Radius = 0})
tweenTable.tweenHookCFrameRight:Play()
tweenTable.tweenRopeRadiusRight:Play()
character["Torso"].rightgrapple.Grapple:Play()
tweenTable.tweenHookCFrameRight.Completed:Connect(function(state)
if state == Enum.PlaybackState.Completed then
valuesFolder["RightHooked"].Value = true
valuesFolder["RightEjected"].Value = false
valuesFolder["RightPosition"].Value = hook.Position
createWeld(array[4], hook)
character["Torso"].Ejector.Gas.Enabled = true
end
tweenTable.tweenHookCFrameRight = nil
tweenTable.tweenRopeRadiusRight = nil
end)
character["Torso"].rightgrapple.Eject.Enabled = false
elseif array[2] == "Left" then
if valuesFolder["LeftEjected"].Value then return end
if valuesFolder["LeftHooked"].Value then return end
valuesFolder["LeftEjected"].Value = true
character["Torso"].leftgrapple.Eject.Enabled = true
local hook = createPseudoHook(character["Torso"].leftgrapple)
local attachment = createAttachment(hook)
local rope = createRope(hook, hook.Parent["RopeAttachment"], attachment)
tweenTable.tweenHookCFrameLeft = TweenService:Create(hook, tweenInfo, {CFrame = CFrame.new(array[3])})
tweenTable.tweenRopeRadiusLeft = TweenService:Create(rope, tweenInfo, {Radius = 0})
tweenTable.tweenHookCFrameLeft:Play()
tweenTable.tweenRopeRadiusLeft:Play()
character["Torso"].leftgrapple.Grapple:Play()
tweenTable.tweenHookCFrameLeft.Completed:Connect(function(state)
if state == Enum.PlaybackState.Completed then
valuesFolder["LeftHooked"].Value = true
valuesFolder["LeftEjected"].Value = false
valuesFolder["LeftPosition"].Value = hook.Position
createWeld(array[4], hook)
character["Torso"].Ejector.Gas.Enabled = true
end
tweenTable.tweenHookCFrameLeft = nil
tweenTable.tweenRopeRadiusLeft = nil
end)
end
character["Torso"].leftgrapple.Eject.Enabled = false
elseif array[1] == "Retract" then
if array[2] == "Right" then
if valuesFolder["RightEjected"].Value then
tweenTable.tweenHookCFrameRight:Cancel()
local hook = character["Torso"].rightgrapple["PseudoHook"]
local ropeTween = TweenService:Create(hook["Rope"], tweenInfo, {Thickness = 0})
ropeTween:Play()
character["Torso"].rightgrapple.Reel:Play()
if character["Torso"].Ejector.Gas.Enabled then
if valuesFolder["LeftHooked"].Value then
return
else
character["Torso"].Ejector.Gas.Enabled = false
end
end
ropeTween.Completed:Connect(function()
valuesFolder["RightEjected"].Value = false
valuesFolder["RightPosition"].Value = Vector3.new()
wait(.1)
hook:Destroy()
end)
elseif valuesFolder["RightHooked"].Value then
local hook = character["Torso"].rightgrapple["PseudoHook"]
local ropeTween1 = TweenService:Create(hook["Rope"], tweenInfo, {Thickness = 0})
local ropeTween2 = TweenService:Create(hook["Rope"], tweenInfo, {Radius = 0.2})
wait(.1)
hook["HookWeld"]:Destroy()
ropeTween1:Play()
ropeTween2:Play()
character["Torso"].rightgrapple.Reel:Play()
if character["Torso"].Ejector.Gas.Enabled then
if valuesFolder["LeftHooked"].Value then
return
else
character["Torso"].Ejector.Gas.Enabled = false
end
end
ropeTween2.Completed:Connect(function()
valuesFolder["RightHooked"].Value = false
valuesFolder["RightPosition"].Value = Vector3.new()
wait(.1)
hook:Destroy()
end)
end
elseif array[2] == "Left" then
if valuesFolder["LeftEjected"].Value then
tweenTable.tweenHookCFrameLeft:Cancel()
local hook = character["Torso"].leftgrapple["PseudoHook"]
local ropeTween = TweenService:Create(hook["Rope"], tweenInfo, {Thickness = 0})
ropeTween:Play()
character["Torso"].leftgrapple.Reel:Play()
if character["Torso"].Ejector.Gas.Enabled then
if valuesFolder["RightHooked"].Value then
return
else
character["Torso"].Ejector.Gas.Enabled = false
end
end
ropeTween.Completed:Connect(function()
valuesFolder["LeftEjected"].Value = false
valuesFolder["LeftPosition"].Value = Vector3.new()
wait(.1)
hook:Destroy()
end)
elseif valuesFolder["LeftHooked"].Value then
local hook = character["Torso"].leftgrapple["PseudoHook"]
local ropeTween1 = TweenService:Create(hook["Rope"], tweenInfo, {Thickness = 0})
local ropeTween2 = TweenService:Create(hook["Rope"], tweenInfo, {Radius = 0.2})
wait(.1)
hook["HookWeld"]:Destroy()
ropeTween1:Play()
ropeTween2:Play()
character["Torso"].leftgrapple.Reel:Play()
if character["Torso"].Ejector.Gas.Enabled then
if valuesFolder["RightHooked"].Value then
return
else
character["Torso"].Ejector.Gas.Enabled = false
end
end
ropeTween2.Completed:Connect(function()
valuesFolder["LeftHooked"].Value = false
valuesFolder["LeftPosition"].Value = Vector3.new()
wait(.1)
hook:Destroy()
end)
end
end
end
end
--//Events
remotesFolder["Grapple"].OnServerEvent:Connect(onServerEvent)
remotesFolder["Attack"].OnServerEvent:Connect(function(player)
if Blades then
local LeftBlade = player.character["Left Arm"]:WaitForChild("Blade")
local RightBlade = player.character["Right Arm"]:WaitForChild("Blade")
local leftTrail = LeftBlade.Trail
local rightTrail = RightBlade.Trail
leftTrail.Enabled = true
rightTrail.Enabled = true
local a = Instance.new("Sound")
a.Parent = player.Character.Head
a.SoundId = "rbxassetid://4958430453"
a.Volume = 1
a:Play()
game.Debris:AddItem(a,1)
LeftBlade.Material = Enum.Material.Neon
RightBlade.Material = Enum.Material.Neon
local hitBox = LeftBlade or RightBlade
hitBox.Touched:connect(function(hit)
if hit.Parent:findFirstChild("Humanoid") and hit.Parent.Name ~= player.Name then
if not hit.Parent:findFirstChild("Nape") and not hit.Parent:findFirstChild("Ragdoller") then
hit.Parent.Humanoid:TakeDamage(25)
end
if hit.Name == "Nape" then
local hitv = Instance.new("ObjectValue")
hitv.Name = "HitRequest"
hitv.Value = player
hit.Parent:findFirstChildOfClass("Humanoid"):TakeDamage(2000)
end
end
end)
wait(1)
leftTrail.Enabled = false
rightTrail.Enabled = false
LeftBlade.Material = Enum.Material.Metal
RightBlade.Material = Enum.Material.Metal
end
end)
remotesFolder["GasBurst"].OnServerEvent:Connect(function(player, Side)
end)
remotesFolder["Boost"].OnServerEvent:Connect(function(player, Boost)
if Boost then
local char = player.Character
local sound = char.Torso.Body.Gas
sound:Play()
else
local char = player.Character
local sound = char.Torso.Body.Gas
sound:Stop()
end
end)
remotesFolder["Reload"].OnServerEvent:connect(function(player)
local character = player.Character
local LeftBlade = player.character["Left Arm"]:WaitForChild("Blade")
local RightBlade = player.character["Right Arm"]:WaitForChild("Blade")
valuesFolder.BladeAmount.Value = valuesFolder.BladeAmount.Value - 2
LeftBlade.Transparency = 0
RightBlade.Transparency = 0
local a = Instance.new("Sound")
a.SoundId = "http://www.roblox.com/asset/?id=130785405"
a.Volume = 1
a.Pitch = 2
a.MaxDistance = 50
a.Parent = player.Character.HumanoidRootPart
a:play()
game.Debris:AddItem(a,0.5)
Blades = true
end)
remotesFolder["ReturnBlade"].OnServerEvent:connect(function(player)
local character = player.Character
local LeftBlade = player.character["Left Arm"]:WaitForChild("Blade")
local RightBlade = player.character["Right Arm"]:WaitForChild("Blade")
valuesFolder.BladeAmount.Value = valuesFolder.BladeAmount.Value + 2
LeftBlade.Transparency = 1
RightBlade.Transparency = 1
local a = Instance.new("Sound")
a.SoundId = "http://www.roblox.com/asset/?id=211134014"
a.Volume = 1
a.Pitch = 2
a.MaxDistance = 50
a.Parent = player.Character.HumanoidRootPart
a:play()
game.Debris:AddItem(a,0.5)
Blades = false
end)