Humanoid NPC Control for Individual Players using :MoveTo() Function

  1. What do you want to achieve?
    Granting exclusive control of the NPC ‘Troop’ to a single player, determined by the ‘Test2’ StringValue with a value of ‘USA’. Right now, every player in the game can control the same NPC, which I do not want, as this can allow players to control other player’s troops.
  2. What is the issue?
    The Test2 StringValue’s Value changes to USA when I press this button, which I want.

This Local Script is in StarterCharacterScripts

local mouse = game.Players.LocalPlayer:GetMouse()
local db = false
local cooldown = 1
local selected = nil

mouse.Button1Down:Connect(function()
	if db == true then
		return
	end
	if selected ~= nil then
		game.ReplicatedStorage.Events.MoveEvent:FireServer(mouse.Hit.p, selected)
		selected = nil
		db = true
		wait(cooldown)
		db = false
	else
		--make sure its a dummy and not a player
		if mouse.Target.Parent:FindFirstChild("Humanoid") and not game.Players:FindFirstChild(mouse.Target.Name) then
			selected = mouse.Target.Parent
		end
	end
end)

This Server Script is inside of the R15 NPC named Troop in the workspace

local playersInControl = {}

game.ReplicatedStorage.Events.MoveEvent.OnServerEvent:Connect(function(plr, mousepos, selected)
	-- Check if the player is already in control of a character
	if playersInControl[plr] then
		return
	end

	if not playersInControl[plr] then
		local Dummy = selected
		local animid = "rbxassetid://11316621511"
		local hum = Dummy.Humanoid
		local ownerofTroops = Dummy:WaitForChild("OwnerofTroops")
		local anim = Instance.new("Animation")
		anim.AnimationId = animid

		local loadedanim = hum:LoadAnimation(anim)
		hum:MoveTo(mousepos)
		loadedanim:Play()
		hum.MoveToFinished:Wait()
		loadedanim:Stop()
	end
end)
  1. What solutions have you tried so far?
    Original scripts from this post
    This interests me, but if I run these scripts through the client, will it still allow two players to press and control the same NPC? I think the same issue will occur, since nothing in the scripts state that one player claims and controls the NPC named Troop.

I have tried a script which unanchors the HumanoidRootPart of the R15 NPC if the player’s Test2 Value is “USA”, but seems like the whole Server Script inside of the NPC named Troop doesn’t move if I anchor the HumanoidRootPart, so I ditched that idea. I turned to changing the transparency of a part inside of the HumanoidRootPart to visible if the player’s Test2 Value is USA, but then I realized these approaches won’t work because I would prefer other players not to control enemy troops. If statements, for example, “if player.Test2.Value == “USA” then” won’t work in the Server Script.

I’ve tried replacing the Original Server Script with these versions I tried to rewrite but they do not work.

local playersInControl = {}

game.ReplicatedStorage.Events.MoveEvent.OnServerEvent:Connect(function(plr, mousepos, selected)
	-- Check if the player is already in control of a character
	if playersInControl[plr] then
		return
	end

	-- Check if the selected character is already claimed by another player
	local ownerofTroops = selected:WaitForChild("OwnerofTroops")
	if ownerofTroops.Value ~= nil then
		return
	end

	-- Claim the character for the player
	playersInControl[plr] = true
	ownerofTroops.Value = plr

	local Dummy = selected
	local animid = "rbxassetid://11316621511"
	local hum = Dummy.Humanoid
	local anim = Instance.new("Animation")
	anim.AnimationId = animid

	local loadedanim = hum:LoadAnimation(anim)
	hum:MoveTo(mousepos)
	loadedanim:Play()
	hum.MoveToFinished:Wait()
	loadedanim:Stop()

	-- Release the character from the player's control
	playersInControl[plr] = nil
	ownerofTroops.Value = nil
end)

Note that I did create two StringValues inside of the Troop NPC Model in Workspace, one named OwnerofTroops, and the other named Owner01, which changes them to Test and Test2, also setting Test2’s Value to “USA”, so I could test out if the scripts would work if a player had their Test2 Value at “USA” after I press the “Test Button” TextButton in the first image. The original values are “No One”, so I could check if No one owned the NPC Troop or if USA did.

game.ReplicatedStorage.Events.MoveEvent.OnServerEvent:Connect(function(plr, mousepos, selected)
	local Dummy = selected
	local animid = "rbxassetid://11316621511"
	local hum = Dummy.Humanoid
	local ownerofTroops = Dummy:WaitForChild("OwnerofTroops")
	local anim = Instance.new("Animation")
	anim.AnimationId = animid
	local StringValue1 = script.Parent.Test2

	local loadedanim = hum:LoadAnimation(anim)
	hum:MoveTo(mousepos)
	loadedanim:Play()
	hum.MoveToFinished:Wait()
	loadedanim:Stop()

	(StringValue1.Value ~= "No One") and hum:MoveTo(mousepos) or print("OwnerofTroops value is No One")
end)

How should I approach this? Does this have anything to do with NetworkOwnership? How do games with controllable NPCS, for example, soldiers, move the player’s owned soldiers? The issue is coming from the scripts themselves. I tried changing them up but they won’t work for me when I mess with them. How do I restrict control of an NPC, named ‘Troop’, to a single player, based on the ‘Test2’ StringValue inside of the player. The possibility of utilizing NetworkOwnership interests me but I do not know if this has anything to do with it, I only encountered issues with that when I anchor the HumanoidRootPart, which is something unrelated. I have attempted to modify the scripts but no If statements seem to work, which is what I’m doing when I’m modifying them. Is it possible to modify the :MoveTo() function in a server script to only allow control for one specific player, or is cloning the ‘Troop’ NPC and disabling the scripts for other players a solution that seems realistic? Thanks for your insights!

Instead of using an actual NPC with a Humanoid, I will use MeshParts that move to where the mouse clicks, instead of having an actual Humanoid move to where the mouse clicks, so I can easily define who owns the MeshParts/Troops and those who can’t move the MeshParts/Troops.

This Post