-
What do you want to achieve?
I recently made my server-sided grappling script client-sided since there is much less lag with the client-sided one. -
What is the issue?
The grappling and tweening works fine, but there is a bug within the script that seems to make my character freeze as shown here:
https://gyazo.com/d8ba3f31bfb128ade2257707018ed65e
If you need any information on how the grappling script actually works, you may refer to this post.
Summary
--//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
local leftHooked = false
local rightHooked = 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 = 0.05
--..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(2,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 TweenService = game:GetService("TweenService")
--//Locals
--..tweens tuff
local tweenInfo = TweenInfo.new(0.2, Enum.EasingStyle.Linear, Enum.EasingDirection.Out, 0, false, 0)
local tweenTable = {}
--//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 = 12
rope.Radius = 2
rope.LimitsEnabled = true
rope.Color = BrickColor.Black()
rope.Visible = true
rope.MaxLength = valuesFolder["MaxHookDistance"].Value
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 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 onServerEvent(array)
local character = player.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
rightHooked = 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
print("left hooked")
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()
character["Torso"].Ejector.Gas.Enabled = false
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)
spawn(function()
if hook:FindFirstChild("HookWeld") then
hook["HookWeld"]:Destroy()
else
print("Oop no weld. Moving on.")
end
end)
ropeTween1:Play()
ropeTween2:Play()
character["Torso"].rightgrapple.Reel:Play()
if character["Torso"].Ejector.Gas.Enabled then
if valuesFolder["LeftHooked"].Value then
print("left hooked")
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()
character["Torso"].Ejector.Gas.Enabled = false
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
print("Right hooked")
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()
character["Torso"].Ejector.Gas.Enabled = false
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)
spawn(function()
if hook:FindFirstChild("HookWeld") then
hook["HookWeld"]:Destroy()
else
print("Oop no weld. Moving on.")
end
end)
ropeTween1:Play()
ropeTween2:Play()
character["Torso"].leftgrapple.Reel:Play()
if character["Torso"].Ejector.Gas.Enabled then
if valuesFolder["RightHooked"].Value then
print("Right hooked")
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()
character["Torso"].Ejector.Gas.Enabled = false
end)
end
end
end
end
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)
if InputService:IsKeyDown(Enum.KeyCode.Space) and GasAmount > 0 then
if gasBoost == false then
gasBoost = true
Multiplier = 1.3
print("Gas! Gas! Gas!")
remotesFolder["Boost"]:FireServer(gasBoost)
GasAmount = GasAmount - 1
print(GasAmount)
UpdateBar()
elseif gasBoost == true then
gasBoost = false
Multiplier = 1
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
spawn(function()
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
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
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, 100*Multiplier, 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
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 then
if checkHookPlayerDistance() <= valuesFolder["MaxHookDistance"].Value then
if mouse.Target ~= nil then
-- we can eject hook and do other cool stuff
onServerEvent({"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 then
if checkHookPlayerDistance() <= valuesFolder["MaxHookDistance"].Value then
if mouse.Target ~= nil then
onServerEvent({"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
onServerEvent({"Retract", "Right"})
RightHook = false
end
elseif key.KeyCode == Enum.KeyCode.Q then
if valuesFolder["LeftHooked"].Value or valuesFolder["LeftEjected"].Value then
onServerEvent({"Retract", "Left"})
LeftHook = false
end
end
end
--//Events
InputService.InputBegan:Connect(onInputBegan)
InputService.InputEnded:Connect(onInputEnded)