Hey everyone, i’m currently working on a grip and carry system and it is designed to allow players to interact with other players who are in a “knocked” state.
The knocked state is triggered when a player’s health drops to zero, at which point they are prevented from dying by setting their health to a minimum of 1. In this state, knocked players are immobilized and are eligible to be carried (“C”) or gripped (“B”) by other nearby players. This system involves two scripts: a ServerScript and a LocalScript.
The ServerScript handles setting a player’s knocked state, handling health restrictions, and listening for the B and C key presses to perform grip or carry actions. The LocalScript complements this by playing animations and sounds on the client side.
The issue here is that the B and C keys, which trigger the grip and carry actions, aren’t working as expected. Despite proximity checks and event setups. I dont know if this is an event handling problem or what exactly.
I’ll post both scripts down below for further clarity… Thanks everyone…
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local FX = ReplicatedStorage:WaitForChild("FX")
local Sounds = ReplicatedStorage:WaitForChild("Sounds")
local Animations = ReplicatedStorage:WaitForChild("Animations")
local UserInputService = game:GetService("UserInputService")
local MIN_HEALTH_THRESHOLD = 1
local KNOCKED_DURATION = 50
local GRIP_KEY = Enum.KeyCode.B
local CARRY_KEY = Enum.KeyCode.C
local PROXIMITY_RADIUS = 10
local GripEvent = ReplicatedStorage.Events:WaitForChild("GripEvent")
local CarryEvent = ReplicatedStorage.Events:WaitForChild("CarryEvent")
local DropEvent = ReplicatedStorage.Events:WaitForChild("DropEvent")
local function stopAllActions(character)
local humanoid = character:FindFirstChild("Humanoid")
if humanoid then
humanoid.PlatformStand = true
humanoid.WalkSpeed = 0
humanoid.JumpPower = 0
print("Stopping all actions for", character.Name)
end
end
local function restoreNormalState(character)
local humanoid = character:FindFirstChild("Humanoid")
if humanoid then
humanoid.PlatformStand = false
humanoid.WalkSpeed = 16
humanoid.JumpPower = 50
print("Restoring normal state for", character.Name)
end
end
local function applyKnockedState(character)
if character:FindFirstChild("IsKnocked") and character.IsKnocked.Value == true then
return
end
local humanoid = character:FindFirstChild("Humanoid")
if not humanoid then return end
humanoid.Health = MIN_HEALTH_THRESHOLD
print(character.Name, "health set to", MIN_HEALTH_THRESHOLD)
stopAllActions(character)
character:SetPrimaryPartCFrame(character.HumanoidRootPart.CFrame * CFrame.new(0, -2, 0))
character:FindFirstChild("IsKnocked").Value = true
Sounds.Splurge:Play()
print("Player is knocked:", character.Name)
wait(KNOCKED_DURATION)
restoreNormalState(character)
character:FindFirstChild("IsKnocked").Value = false
print("Knocked state ended for:", character.Name)
end
local function isPlayerCloseEnough(player, victim)
local playerHRP = player.Character and player.Character:FindFirstChild("HumanoidRootPart")
local victimHRP = victim:FindFirstChild("HumanoidRootPart")
if playerHRP and victimHRP then
local distance = (playerHRP.Position - victimHRP.Position).Magnitude
print("Distance between player and victim:", distance)
return distance <= PROXIMITY_RADIUS
end
return false
end
local function preventDeath(humanoid)
humanoid.HealthChanged:Connect(function()
if humanoid.Health < MIN_HEALTH_THRESHOLD then
humanoid.Health = MIN_HEALTH_THRESHOLD
end
end)
end
local function onKeyPress(player, key)
print("Key pressed:", key)
local character = player.Character
if not character then return end
local humanoid = character:FindFirstChild("Humanoid")
if not humanoid then return end
local victim = nil
local isKnocked = false
for _, otherCharacter in pairs(workspace:GetChildren()) do
if otherCharacter:FindFirstChild("Humanoid") then
if otherCharacter:FindFirstChild("IsKnocked") and otherCharacter.IsKnocked.Value then
victim = otherCharacter
isKnocked = true
break
end
end
end
if victim and isKnocked and isPlayerCloseEnough(player, victim) then
if key == CARRY_KEY then
local carryAnimation = Animations.Carry:Clone()
local victimAnimation = Animations.BeingCarried:Clone()
humanoid:LoadAnimation(carryAnimation):Play()
victim:FindFirstChild("Humanoid"):LoadAnimation(victimAnimation):Play()
Sounds.Splurge2:Play()
local carryWeld = Instance.new("WeldConstraint")
carryWeld.Parent = victim.HumanoidRootPart
carryWeld.Part0 = character.HumanoidRootPart
carryWeld.Part1 = victim.HumanoidRootPart
victim:FindFirstChild("IsCarrying").Value = true
character:FindFirstChild("IsCarrying").Value = true
CarryEvent:FireClient(player, victim)
elseif key == GRIP_KEY then
local gripAnimation = Animations.Grip:Clone()
local victimAnimation = Animations.BeingGripped:Clone()
humanoid:LoadAnimation(gripAnimation):Play()
victim:FindFirstChild("Humanoid"):LoadAnimation(victimAnimation):Play()
Sounds.Hit:Play()
local gripWeld = Instance.new("WeldConstraint")
gripWeld.Parent = victim.HumanoidRootPart
gripWeld.Part0 = character.HumanoidRootPart
gripWeld.Part1 = victim.HumanoidRootPart
victim:FindFirstChild("IsGripped").Value = true
character:FindFirstChild("IsGripping").Value = true
GripEvent:FireClient(player, victim)
victim.Humanoid.Health = 0
end
else
print("Player is not close enough to interact with victim.")
end
end
Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function(character)
local isKnockedValue = Instance.new("BoolValue")
isKnockedValue.Name = "IsKnocked"
isKnockedValue.Value = false
isKnockedValue.Parent = character
local isCarryingValue = Instance.new("BoolValue")
isCarryingValue.Name = "IsCarrying"
isCarryingValue.Value = false
isCarryingValue.Parent = character
local isGrippedValue = Instance.new("BoolValue")
isGrippedValue.Name = "IsGripped"
isGrippedValue.Value = false
isGrippedValue.Parent = character
local humanoid = character:WaitForChild("Humanoid")
preventDeath(humanoid)
humanoid.HealthChanged:Connect(function()
if humanoid.Health <= 0 then
print(character.Name, "health reached 0, applying knocked state.")
applyKnockedState(character)
end
end)
UserInputService.InputBegan:Connect(function(input, isProcessed)
if isProcessed then return end
if input.UserInputType == Enum.UserInputType.Keyboard then
onKeyPress(player, input.KeyCode)
end
end)
end)
end)
Local Script
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Animations = ReplicatedStorage:WaitForChild("Animations")
local Sounds = ReplicatedStorage:WaitForChild("Sounds")
local GripEvent = ReplicatedStorage.Events:WaitForChild("GripEvent")
local CarryEvent = ReplicatedStorage.Events:WaitForChild("CarryEvent")
local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")
local UserInputService = game:GetService("UserInputService")
local function playGripAnimation(victim)
local gripAnimation = Animations.Grip:Clone()
local victimAnimation = Animations.BeingGripped:Clone()
Humanoid:LoadAnimation(gripAnimation):Play()
victim:FindFirstChild("Humanoid"):LoadAnimation(victimAnimation):Play()
Sounds.Hit:Play() -- Grip sound effect
end
local function playCarryAnimation(victim)
local carryAnimation = Animations.Carry:Clone()
local victimAnimation = Animations.BeingCarried:Clone()
Humanoid:LoadAnimation(carryAnimation):Play()
victim:FindFirstChild("Humanoid"):LoadAnimation(victimAnimation):Play()
Sounds.Splurge2:Play() -- Carry sound effect
end
GripEvent.OnClientEvent:Connect(function(player, victim)
if player == Player then
playGripAnimation(victim)
end
end)
CarryEvent.OnClientEvent:Connect(function(player, victim)
if player == Player then
playCarryAnimation(victim)
end
end)
UserInputService.InputBegan:Connect(function(input, isProcessed)
if isProcessed then return end
if input.UserInputType == Enum.UserInputType.Keyboard then
if input.KeyCode == Enum.KeyCode.B then
local victim = nil
for _, otherCharacter in pairs(workspace:GetChildren()) do
if otherCharacter:FindFirstChild("Humanoid") and otherCharacter:FindFirstChild("IsKnocked") and otherCharacter.IsKnocked.Value then
victim = otherCharacter
break
end
end
if victim then
GripEvent:FireServer(victim)
end
end
if input.KeyCode == Enum.KeyCode.C then
local victim = nil
for _, otherCharacter in pairs(workspace:GetChildren()) do
if otherCharacter:FindFirstChild("Humanoid") and otherCharacter:FindFirstChild("IsKnocked") and otherCharacter.IsKnocked.Value then
victim = otherCharacter
break
end
end
if victim then
CarryEvent:FireServer(victim)
end
end
end
end)
For one, you cannot use UserInputService or any client-based service on the server. The server doesn’t have any user input, it’s the server! Only clients can listen to user input directly. You have the right idea in mind, but your execution is slightly off.
Another thing is that you’re firing to the person doing the gripping or the carrying to play the animation on the victim on the client which won’t really work as well as you think it might because that animation might not replicate, the behavior will be pretty weird since you’re welding two network owners to each other, so they’ll be fighting over that network ownership and causing other unusual behavior.
I suggest finding a different solution that doesn’t use welds, maybe use RigidityEnabled with AlignPosition to mimic the behavior of a weld without the network ownership features.
Thank you so much, that worked exactly as i wanted it to, had to move all input detection (UserInputService) to the client script as you stated, and i’m still working through welding issues trying to get it right.
On a side note, i dont know if you accept friend requests on discord, i’d love to occasionally learn from someone as knowledgeable as you, this has helped me a lot!