Unsolved Combat system network ownership problem

I have a combat system in Roblox inspired by TSB, However I’m struggling with network ownership issues, particularly when combining knockback with ragdoll. Here’s the problem:

  1. Knockback (short pushes with each punch using linear velocity) and ragdoll require transferring the enemy’s network ownership to the attacking player to work correctly.

  2. For Ragdolling, I apply the network ownership of the enemy’s torso to the attacking player right before the final punch. This works fine because the ownership naturally returns to normal when the enemy gets up most likely because of humanoid state.

  3. However, for knockback on regular punches, I face a dilemma:

  • If I apply network ownership before each punch and unapply it after, The ragdoll stops working because the ragdoll is initiated after the last punch in a combo.
  • If I don’t unapply network ownership, The enemy’s character would not function properly because of network ownership…
  1. I need a way to temporarily apply network ownership for each knockback and also the ragdoll and then unapply it after.

In essence, I’m looking for a method to apply network ownership before each knockback (including ragdoll initiation), execute the knockback/ragdoll effects and then unapply the network ownership immediately after - all while ensuring that these operations don’t interfere with each other.

(local script combat client):

local function executePunchSequence(isPunchHold)
	if currentPunchPosition >= 5 then
		currentPunchPosition = 1
		return
	end

	-- Set up animation and markers
	currentTrack = punchAnimationTracks[currentPunchPosition]
	local markerConnections = {}
	currentTrack:Play() -- this is just the punch animation

	-- Set up hitbox
	task.spawn(function()
		hitboxSet()
		hitboxDeploy()
	end)

	-- Handle hit detection
	task.spawn(function()
		hitDetection(function(hitPlayers)

			for enemyCharacter, _ in hitPlayers do -- for every player hit
				if not enemyCharacter then continue end

				hitPlayer = true
				
				-- Handle blocking
				if handleBlocking(enemyCharacter) then
					return -- Stop further logic if enemy blocking
				else

					-- Handle ragdoll
					task.spawn(function()
						if currentPunchPosition and currentPunchPosition >= 4 then
							if not enemyCharacter then return end
							isLastHit = true
							print("changing humanoidstate into ragdoll")
							ragdoll(enemyCharacter, enemyHumanoid)
						end
					end)

					-- Set up animation markers
					if enemyTorso and differenceDirection then
						table.insert(markerConnections, currentTrack:GetMarkerReachedSignal("prepunch"):Connect(function() -- this doesn't matter
							print("prepunch is reached")
							hitKnockback(torso, differenceDirection, true) -- push for player

							
						end))

						table.insert(markerConnections, currentTrack:GetMarkerReachedSignal("punch"):Connect(function()
							print("punch is reached")
							-- Check blocking again at the moment of impact
							applyNetworkRemote:InvokeServer(enemyPlayer, enemyTorso)

							hitKnockback(enemyTorso, differenceDirection, false, isLastHit) -- pushes the enemy and isLastHit checks if LastHit is true, if it is, isLastHit becomes true and sends to the function for a strong knockback.
							--unapplyNetworkRemote:InvokeServer(enemyPlayer, enemyTorso) -- here is the unapply network ownership i have no idea how to use

						end))
					end
				end
			end
		end)
	end)

	currentTrack.Stopped:Wait()-- dont mind all this, just for performance
	for _, connection in ipairs(markerConnections) do 
		connection:Disconnect()
	end
	currentPunchPosition += 1
	hitPlayer = false

end

Video:


In the video you can see that when the player punches the enemy once without ragdolling the enemy’s network ownership for the player stays without getting removed, But when the ragdoll happens, The network ownership returns.

Note: I use the client for the knockback and ragdoll for performance benefits.

6 Likes

Can show how you’re using theSetNetworkOwnerShip() method?

i just set the enemy’s torso network ownership to the player and then to himself using remote functions:

local function applyNetwork(player, enemyPlayer, enemyTorso)
	local character = player.Character
	local torso = character:FindFirstChild("Torso")
	if enemyTorso and torso then
		enemyTorso:SetNetworkOwner(player)
	end
	return
end
applyNetworkRemote.OnServerInvoke = applyNetwork -- connect the remote with function

local function revertNetwork(player, enemyPlayer, enemyTorso)
	if enemyTorso and enemyPlayer then
		enemyTorso:SetNetworkOwner(enemyPlayer)
	end
	return
end
unapplyNetworkRemote.OnServerInvoke = revertNetwork -- connect the remote with function

Where did you apply the unapplyNetworkRemote RemoteFunction.

i don’t, its commented out because if i do use it after each knockback the ragdoll stops working

Try using the remotefunction when you disabled ragdoll

When the enemy ragdolls and then gets up it naturally returns the network ownership, the problem is that i need to set the enemy’s network ownership to the player before the knockback and remove it after, the last hit(ragdoll) also requires to set the network ownership but i don’t know why the network ownership is removed before the ragdoll happens

are you applying knockback via the client or server? you could just avoid having to manipulate network ownership by applying knockback on the server.

the knockback is applied in the client for performance benefits

2 Likes

I can’t help you but I want to learn. What is the point of using Network ownership in this situation?

Do you give ownership to server so that the client doesn’t override status effects?

Why not just add an if statement to check if they’re ragdolled then?

On another note: You shouldn’t be dealing knockback from a client script because of how unsafe it is (unless I am misinterpreting the script?) and also having remotes that set the character’s network ownership, because of how any exploiter could just use it to pretty much break the game.
I’d suggest having some sort of server middleman script that does that for the client instead of giving it the total power to ‘possess’ other players.

Normally, if you want smooth knockback, you’d send a client event to the player who is being knocked back to inflict the knockback on themselves rather.

EDIT: Dealing knockback on the client isn’t thaaaat much of a bad idea, but you should still consider having a serverscript register the hits and then apply the network ownership rather than the client doing it by themselves.

What i want exactly is to check if the hit is not the last hit which ragdolls and unapply/unset the network ownership for after each hit, But the problem is that if i unapply it immediately or delay it the enemy returns to where he was from when the network ownership was applied.

i have 2 questions regarding the stuff you talked about earlier:

  1. Can’t a hacker exploit the remote event sent to the middle man script itself?

  2. A local script runs on each client, So what do you mean by sending a client event to the enemy client to execute knockback or ragdoll on himself?

i will say, in TSB network ownership isn’t given on punches, and i don’t believe in ragdoll either. you can tell this because you can punch a person as they dash, and the knockback doesn’t happen until after they finish their dash (which the dash is client sided). then they get stunned a few seconds after which allows for them to annoying escape combos. the reason i don’t believe networkownership is changed on ragdoll is because a lot of the mechanics rely on raycasting to determine the player’s condition (ragdolled in air, landed, knockedback, etc).

networkownership only really changes on grabbing moves as you still can maneuver your character even when another player is welded to you.

I understand that TSB doesn’t rely on network ownership, But in this case the knockback and ragdoll I’m using don’t work without it on the client, And I’m still trying to figure it out.

How does TSB handle this? Is there a way to handle knockback and ragdoll on the client without network ownership?

ragdolls kind of have to be on the client partly as humanoidstates will be set, and setting humanoidstates have to be done on the client.

im not certain what type of body movers they use for knockback. most likely linearvelocity or bodyvelocity as it locks you into that velocity whilst its active.

for ragdoll, i assume they have a value on the client or they fire an event that tells the client to set their humanoidstate to ragdoll while creating joints for the ragdoll rig on the server.

I’m doing exactly this, but the knockback and ragdoll don’t work without transferring the enemy’s network ownership to the player attacking and then transferring it back to him after, the problem is when I transfer it back it just returns the player to where he was before transferring the network ownership.

there are a couple of issues with the method you’re describing to me

  1. if you give ownership to another player for a short time then return it, it may be that the player controlling the other player cannot replicate the position fast enough for the other player to see it. this is why they return to their original position when you return networkownership

  2. constantly swapping networkownership for every punch will cause overlap if multiple people are m1’ing a person causing extremely bad physics calculations on the attacked player

  3. if you constantly swap networkownership there may be an issue regaining ownership of your character causing very delayed inputs.

i get what you’re attempting to do but i do not think it is a very efficient way to go about making a knockback system, roblox has many bodymovers and velocity functions at your disposal to make a knockback system without issues.