[SOLVED] Section of Code prevents Ai from targeting ALL Players, how to fix?

So basically I am making a “Weeping Angel” System. I have already constructed the code and interpreted the usage of the System. However, as I was testing the Ai with a few of my friends I have noticed that the Ai primarily targets the first Player that has joined the game. So this prevents other Players from being hunted or killed. If the a Player does manage to die from the Ai, the the Ai will swap and target the next person that looks away from its presence. The Ai targets 1 Player per Death.

does this section of code prevent the Ai targeting ALL Players?

-- Ai Control
function GetTarget()
    local TargetReturn
    local KillDistance = 2
    local DetectionDistance = 10000000
    for _, Target in pairs(workspace:GetChildren()) do
        if Target ~= NPC.Parent and Target.Name ~= NPC.Parent and Target:FindFirstChild("Humanoid") ~= nil and Target:FindFirstChild("HumanoidRootPart") ~= nil then
            if (Target:FindFirstChild("HumanoidRootPart").Position - NPC.HumanoidRootPart.Position).Magnitude < DetectionDistance then
                TargetReturn = Target
                if (Target:FindFirstChild("HumanoidRootPart").Position - NPC.HumanoidRootPart.Position).Magnitude < KillDistance then
                    Kill(Target:FindFirstChild("Humanoid"))
                end
            end
        end
    end
    return TargetReturn
end
1 Like

It’ll be beneficial if the Ai would intend to choose the closest Player.

Hello! You can create a system like this to target the closest player.

-- Ai Control
function GetTarget()
	local TargetReturn
	local KillDistance = 2
	local DetectionDistance = 10000000 -- if you don't want a detection distance you can also set this to math.huge
	local closestDistance = math.huge -- basically just a very huge number (it's a good idea to originally set this to the DetectionDistance variable since it is the farthest possible distance )
	for _, Target in pairs(workspace:GetChildren()) do
		if Target ~= NPC.Parent and Target.Name ~= NPC.Parent and Target:FindFirstChild("Humanoid") ~= nil and Target:FindFirstChild("HumanoidRootPart") ~= nil then
			local magniutde = (Target:FindFirstChild("HumanoidRootPart").Position - NPC.HumanoidRootPart.Position).Magnitude -- make this a variable since you use this many times
			if magniutde < DetectionDistance and magniutde < closestDistance then
				TargetReturn = Target	
			end
		end
	end
	if (TargetReturn:FindFirstChild("HumanoidRootPart").Position - NPC.HumanoidRootPart.Position).Magnitude < KillDistance then -- move this to the outside of the loop because so it can scan all the other players before instantly attacking a player that meets the criteria
		Kill(TargetReturn:FindFirstChild("Humanoid"))
	end
	return TargetReturn
end

Let me know if you have any questions or problems regarding this system.

so the system would look like this?

-- Ai Control
function GetTarget()
	local TargetReturn
	local KillDistance = 2
	local DetectionDistance = math.huge
	local ClosestDistance = math.huge -- basically just a very huge number (it's a good idea to originally set this to the DetectionDistance variable since it is the farthest possible distance )
	for _, Target in pairs(workspace:GetChildren()) do
		if Target ~= NPC.Parent and Target.Name ~= NPC.Parent and Target:FindFirstChild("Humanoid") ~= nil and Target:FindFirstChild("HumanoidRootPart") ~= nil then
			local Magniutde = (Target:FindFirstChild("HumanoidRootPart").Position - NPC.HumanoidRootPart.Position).Magnitude -- make this a variable since you use this many times
			if Magniutde < DetectionDistance and Magniutde < ClosestDistance then
				TargetReturn = Target	
			end
		end
	end
	if (TargetReturn:FindFirstChild("HumanoidRootPart").Position - NPC.HumanoidRootPart.Position).Magnitude < KillDistance then -- move this to the outside of the loop because so it can scan all the other players before instantly attacking a player that meets the criteria
		Kill(TargetReturn:FindFirstChild("Humanoid"))
	end
	return TargetReturn
end

It looks right, but I didn’t test the script. You can test it in studio, though, using the test feature to control multiple characters. I also forgot to mention that in this line:

if ...  Target:FindFirstChild("Humanoid") ~= nil and Target:FindFirstChild("HumanoidRootPart") ~= nil then -- (first part of statement doesn't apply, which is why there is an ellipses)

you don’t need to check if it is not equal to nil, all you need to do is just check if it exists in general which is why “~= nil” isn’t required. So you can have this instead:

if ...  Target:FindFirstChild("Humanoid") and Target:FindFirstChild("HumanoidRootPart") then

Also, you really only need one of these conditions to find a character, but both are find too.

if Target ~= Target:FindFirstChild("Humanoid") and Target:FindFirstChild("HumanoidRootPart") then```

Yeah that’s good, it should be working when you test it. Let me know if there are any errors.
What’s this condition for though

is this part needed?

Max characters

It doesn’t really do anything. It is asking if the character is the same object as it’s humanoid, which shouldn’t ever be true.

also I found this Error every time I leave the testing Server

Error > 02:09:22.888 Workspace.AI.Mr. Twigs.Ai:57: attempt to index nil with 'FindFirstChild' - Server

which I also forgot to mention but here’s the entire system

----------------------------------------------------------------------------- Ai
-- Services
local TweenService = game:GetService("TweenService")
local PathfindingService = game:GetService("PathfindingService")

-- Players
local Players = game:GetService("Players")

-- NPC
local NPC = script.Parent
local NPCHumanoid = script.Parent:WaitForChild("NPC")
local NPCTorso = script.Parent:WaitForChild("Torso")

-- Distance Setup
local Distance 
local ClosestPlayer, ClosestDistance = nil, math.huge -- Entire Map

local FadeTime = 3.5; -- In TweenInfo; Fade Time

-- Touch Kill Control
function Kill(Humanoid)
	Humanoid.Health = 0
	script.Parent.HumanoidRootPart.Jumpscare:Play()
end

script.Parent.Parent["Mr. Twigs"].HumanoidRootPart.Anchored = true
-- Gui Control
task.wait(45)
script.Parent.Parent["Mr. Twigs"].HumanoidRootPart.Anchored = false
-- script.Parent.HumanoidRootPart.Snap:Play()
-- Getting the PlayerGui.
for _, Player in game:GetService("Players"):GetPlayers() do
	if Player:FindFirstChildOfClass("PlayerGui") then
		local NoticeGui = Player:FindFirstChild("PlayerGui"):FindFirstChild("NoticeGui")
		local NotcieText = NoticeGui:FindFirstChild("NoticeText")
		NoticeGui.Alert:Play()
		NotcieText.Visible = true 
		task.wait(FadeTime)
		TweenService:Create(NotcieText, TweenInfo.new(1.5), {TextTransparency = 1}):Play() TweenService:Create(NotcieText, TweenInfo.new(1.5), {TextStrokeTransparency = 1}):Play()
	end
end

-- Ai Control
function GetTarget()
	local TargetReturn
	local KillDistance = 2
	local DetectionDistance = math.huge
	local ClosestDistance = math.huge 
	for _, Target in pairs(workspace:GetChildren()) do
		if Target ~= Target:FindFirstChild("Humanoid") and Target:FindFirstChild("HumanoidRootPart") then
			local Magniutde = (Target:FindFirstChild("HumanoidRootPart").Position - NPC.HumanoidRootPart.Position).Magnitude
			if Magniutde < DetectionDistance and Magniutde < ClosestDistance then
				TargetReturn = Target	
			end
		end
	end
	if (TargetReturn:FindFirstChild("HumanoidRootPart").Position - NPC.HumanoidRootPart.Position).Magnitude < KillDistance then
		Kill(TargetReturn:FindFirstChild("Humanoid"))
	end
	return TargetReturn
end

-- If Player has turned away 
function CanSeeTarget(Target)	
	if NPC.Head.Orientation.Y > Target:FindFirstChild("Head").Orientation.Y - 90 and NPC.Head.Orientation.Y < Target:FindFirstChild("Head").Orientation.Y + 90 then
		return true
	end
end

-- Movement Detection Control
spawn(function()
	while task.wait() do
		if CanWander then
			local RandomPosition = math.random(-100, 100)
			local PositionToMove = NPC.HumanoidRootPart.Position + Vector3.new(RandomPosition, 0, RandomPosition)
			NPC.NPC:MoveTo(PositionToMove)
			NPC.NPC.MoveToFinished:Wait()
		end
	end
end)

while task.wait() do
	local MainTarget = GetTarget()
	if MainTarget then
		CanWander = false
		if CanSeeTarget(MainTarget) then
			NPC.NPC.WalkSpeed = 25 -- Chase Speed
			NPC.NPC:MoveTo(MainTarget:FindFirstChild("HumanoidRootPart").Position)
		else
			NPC.NPC.WalkSpeed = 16 -- Patrol Speed
		end
	else
		CanWander = true
	end
end

@tnt_Dante

Max characters lol

You forgot to include the first part of the if statement. In total it should be this:

if Target ~= NPC.Parent and Target.Name ~= NPC.Parent and Target:FindFirstChild("Humanoid") then

I think it was scanning the bot. You can replace line 57 for this.

are you sure line (57)?

Max character

Yes, that is what it is saying in the error message.

I don’t think I understand line (57) is
end

Oh. I mean this line

if Target ~= Target:FindFirstChild("Humanoid") and Target:FindFirstChild("HumanoidRootPart") then

It should work now.

(character limit )

Error > 02:26:13.730 Workspace.AI.Mr. Twigs.Ai:53: attempt to index nil with 'FindFirstChild' - Server 02:26:13.730 Stack Begin - Studio 02:26:13.730 Script 'Workspace.AI.Mr. Twigs.Ai', Line 53 - function GetTarget - Studio 02:26:13.730 Script 'Workspace.AI.Mr. Twigs.Ai', Line 79 - Studio 02:26:13.730 Stack End - Studio