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
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.
-- 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.
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
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