Why self isn't worked when I tried get HumanoidRootPart or another parts?

I seem to have written everything correctly, but the code gives an error, here it is:

–Script–
local BrutezAI = require(script.Parent.BrutezAI)
local brutezScript = script
local brutezAI = BrutezAI.new(brutezScript.Parent)

–ModuleScript–
local BrutezAI = {}
BrutezAI .__index = BrutezAI

function BrutezAI.new(Brutez)
local self = setmetatable({}, BrutezAI)
self.brutez = Brutez
self.radius = 10 – Radius for door opening. Set this according to your needs.
return self
end

local humanoidRootPart = self.brutez:FindFirstChild(‘HumanoidRootPart’) – returns an error that does not find HumanoidRootPart.
if not humanoidRootPart or not target:FindFirstChild(‘HumanoidRootPart’) then
return false
end

Firstly, I’d recommend to encapsulate your code in ```.
And secondly, what is the error that is being printed? As FindFirstChild does not print an error if it finds nothing, but just returns nil. Is it about not being able to call FindFirstChld on nil or something along these lines?

Here’s an error: Workspace.John Doe…BrutezAI:59: attempt to index nil with ‘FindFirstChild’

Where are the following lines in your code being ran, inside the same ModuleScript?

local humanoidRootPart = self.brutez:FindFirstChild(‘HumanoidRootPart’) – returns an error that does not find HumanoidRootPart.
if not humanoidRootPart or not target:FindFirstChild(‘HumanoidRootPart’) then
    return false
end

I don’t see this question. But here is:

local hit = self:RayCast(humanoidRootPart.Position, target.HumanoidRootPart.Position - humanoidRootPart.Position, 500, {self.brutez})

if hit and hit.Parent and hit.Parent.ClassName=="Model"and hit.Parent:FindFirstChild(“Torso”) and hit.Parent.Torso.Transparency <= 0.6 and hit.Parent:FindFirstChild(“Head”) then
return true
else
return false
end In Module Script

What I am trying to figure out here is are you running the last 4 lines of your first code in the ModuleScript or in the Script?

Is it?

while true do

local nearestTarget = brutezAI:FindNearestTarget()
if nearestTarget then
BrutezAI:navigateToTarget(nearestTarget)
– Perform actions on nearest target
end
wait()
end
That’s an ordinary script.

I will briefly explain.
The error: “attempt to index nil with FindFirstChild” basically means you are trying to use the method FindFirstChild on a nil object, which means that your self.brutez is nil when calling on it. I can not tell where the last 4 lines are being executed as I see you have 2 parts of your code, Script and ModuleScript, and that’d be useful to know in order to solve the problem.

But self.brutez is a JohnDoe that means brutez is determined.
I used print, and this is determined (not nil)

Can you send the entire ModuleScript code and the Script?

local BrutezAI = {}
BrutezAI .__index = BrutezAI

function BrutezAI.new(Brutez)
local self = setmetatable({}, BrutezAI)
self.brutez = Brutez
self.radius = 10 – Radius for door opening. Set this according to your needs.
return self
end

function BrutezAI:RayCast(Position, Direction, MaxDistance, IgnoreList)
return game:GetService(“Workspace”):FindPartOnRayWithIgnoreList(Ray.new(Position,Direction.unit*(MaxDistance or 999.999)), IgnoreList or {});
end;

function BrutezAI:checkOpenDoor()
local closeDoors = {}
for _, object in ipairs(game.Workspace:GetChildren()) do
if object:IsA(‘Model’) and object:FindFirstChild(‘Door’) then
local humanoidRootPart = self.brutez:FindFirstChild(‘HumanoidRootPart’)
if humanoidRootPart then
if (object.Door.Position - humanoidRootPart.Position).Magnitude <= self.radius then
table.insert(closeDoors, object)
end
end
end
end
for _, door in ipairs(closeDoors) do
if typeof(door.DoorOpenEvent) == “Instance” and door.DoorOpenEvent:IsA(“BindableEvent”) then
door.DoorOpenEvent:Fire()
end
end
end

function BrutezAI:FindNearestTarget()
local closestTarget = nil
local closestDistance = math.huge
local brutezHumanoidRootPart = self.brutez:FindFirstChild(‘HumanoidRootPart’)
if not brutezHumanoidRootPart then
return nil
end
for _, target in ipairs(workspace:GetChildren()) do
– Check if the target is a player and is alive
if target:IsA(‘Model’) and target:FindFirstChild(‘Humanoid’) and target.Humanoid.Health > 0 then
local targetHumanoidRootPart = target:FindFirstChild(‘HumanoidRootPart’)
if targetHumanoidRootPart then
local distance = (targetHumanoidRootPart.Position - brutezHumanoidRootPart.Position).Magnitude
if distance < closestDistance then
closestDistance = distance
closestTarget = target
end
end
end
end
return closestTarget
end

function BrutezAI:canSeeTarget(target)
local humanoidRootPart = self.brutez:FindFirstChild(‘HumanoidRootPart’)

if not humanoidRootPart or not target:FindFirstChild(‘HumanoidRootPart’) then
return false
end

local hit = self:RayCast(humanoidRootPart.Position, target.HumanoidRootPart.Position - humanoidRootPart.Position, 500, {self.brutez})

if hit and hit.Parent and hit.Parent.ClassName=="Model"and hit.Parent:FindFirstChild(“Torso”) and hit.Parent.Torso.Transparency <= 0.6 and hit.Parent:FindFirstChild(“Head”) then
return true
else
return false
end
end

function BrutezAI:navigateToTarget(target)
if self:canSeeTarget(target) then
self.brutez.Humanoid:MoveTo(target.HumanoidRootPart.Position, target)
else
if not self.pathing then
spawn(function()
self.pathing = true
local Path = game:GetService(“PathfindingService”):CreatePath({
AgentRadius = 2,
AgentHeight = 2,
AgentCanJump = true,
AgentCanClimb = true
})

  		Path:ComputeAsync(self.brutez.HumanoidRootPart.Position, target.HumanoidRootPart.Position)
  		local waypoints = Path:GetWaypoints()

  		for _, waypoint in ipairs(waypoints) do
  			if not self:canSeeTarget(target) then
  				local pathTimer = 0
  				repeat wait(0)
  					self.brutez.Humanoid:MoveTo(waypoint.Position)
  					pathTimer = pathTimer + 1
  					if pathTimer > 15 or self:canSeeTarget(target) then
  						break
  					end
  				until (self.brutez.HumanoidRootPart.Position - waypoint.Position).Magnitude < 8 or pathTimer > 15 or self:canSeeTarget(target)
  				if pathTimer > 15 or self:canSeeTarget(target) then
  					break
  				end
  			end
  		end
  		self.pathing = false
  	end)
  end

end
end

– Brutez main loop and other logic…

return BrutezAI

local BrutezAI = require(script.Parent.BrutezAI)
local brutezScript = script
local brutezAI = BrutezAI.new(brutezScript.Parent)
while true do

local nearestTarget = brutezAI:FindNearestTarget()
if nearestTarget then
BrutezAI:navigateToTarget(nearestTarget)
– Perform actions on nearest target
end

BrutezAI:checkOpenDoor()

wait() – Important. Make sure the while loop doesn’t run indefinitely.
end

Can you use encapsulate the code inside ``` so I can read it better?

What is encapsulate?hhhhhhhhhhhhhh

So just surround your code with ``` so it formats better

local brutezScript = script
local brutezAI = BrutezAI.new(brutezScript.Parent)
while true do

local nearestTarget = brutezAI:FindNearestTarget()
if nearestTarget then
BrutezAI:navigateToTarget(nearestTarget)
– Perform actions on nearest target
end

BrutezAI:checkOpenDoor()

wait() – Important. Make sure the while loop doesn’t run indefinitely.
end```
BrutezAI	.__index = BrutezAI

function BrutezAI.new(Brutez)
	local self = setmetatable({}, BrutezAI)
	self.brutez = Brutez
	self.radius = 10 -- Radius for door opening. Set this according to your needs.
	return self
end

function BrutezAI:RayCast(Position, Direction, MaxDistance, IgnoreList)
	return game:GetService("Workspace"):FindPartOnRayWithIgnoreList(Ray.new(Position,Direction.unit*(MaxDistance or 999.999)), IgnoreList or {});
end;

function BrutezAI:checkOpenDoor()
	local closeDoors = {}
	for _, object in ipairs(game.Workspace:GetChildren()) do
		if object:IsA('Model') and object:FindFirstChild('Door') then 
			local humanoidRootPart = self.brutez:FindFirstChild('HumanoidRootPart')
			if humanoidRootPart then
				if (object.Door.Position - humanoidRootPart.Position).Magnitude <= self.radius then
					table.insert(closeDoors, object)
				end
			end
		end
	end
	for _, door in ipairs(closeDoors) do
		if typeof(door.DoorOpenEvent) == "Instance" and door.DoorOpenEvent:IsA("BindableEvent") then
			door.DoorOpenEvent:Fire()
		end
	end
end

function BrutezAI:FindNearestTarget()
	local closestTarget = nil
	local closestDistance = math.huge
	local brutezHumanoidRootPart = self.brutez:FindFirstChild('HumanoidRootPart')
	if not brutezHumanoidRootPart then
		return nil
	end
	for _, target in ipairs(workspace:GetChildren()) do
		-- Check if the target is a player and is alive
		if target:IsA('Model') and target:FindFirstChild('Humanoid') and target.Humanoid.Health > 0 then
			local targetHumanoidRootPart = target:FindFirstChild('HumanoidRootPart')
			if targetHumanoidRootPart then
				local distance = (targetHumanoidRootPart.Position - brutezHumanoidRootPart.Position).Magnitude
				if distance < closestDistance then
					closestDistance = distance
					closestTarget = target
				end
			end
		end
	end
	return closestTarget
end


function BrutezAI:canSeeTarget(target)
	local humanoidRootPart = self.brutez:FindFirstChild('HumanoidRootPart')

	if not humanoidRootPart or not target:FindFirstChild('HumanoidRootPart') then
		return false
	end

	local hit = self:RayCast(humanoidRootPart.Position, target.HumanoidRootPart.Position - humanoidRootPart.Position, 500, {self.brutez})

	if hit and hit.Parent and hit.Parent.ClassName=="Model"and hit.Parent:FindFirstChild("Torso") and hit.Parent.Torso.Transparency <= 0.6 and hit.Parent:FindFirstChild("Head") then
		return true
	else
		return false
	end
end

function BrutezAI:navigateToTarget(target)
	if self:canSeeTarget(target) then
		self.brutez.Humanoid:MoveTo(target.HumanoidRootPart.Position, target)
	else
		if not self.pathing then
			spawn(function()
				self.pathing = true
				local Path = game:GetService("PathfindingService"):CreatePath({
					AgentRadius = 2,
					AgentHeight = 2,
					AgentCanJump = true, 
					AgentCanClimb = true
				})

				Path:ComputeAsync(self.brutez.HumanoidRootPart.Position, target.HumanoidRootPart.Position)
				local waypoints = Path:GetWaypoints()

				for _, waypoint in ipairs(waypoints) do
					if not self:canSeeTarget(target) then
						local pathTimer = 0
						repeat wait(0)
							self.brutez.Humanoid:MoveTo(waypoint.Position)
							pathTimer = pathTimer + 1
							if pathTimer > 15 or self:canSeeTarget(target) then
								break
							end
						until (self.brutez.HumanoidRootPart.Position - waypoint.Position).Magnitude < 8 or pathTimer > 15 or self:canSeeTarget(target)
						if pathTimer > 15 or self:canSeeTarget(target) then
							break
						end
					end
				end
				self.pathing = false
			end)
		end
	end
end

-- Brutez main loop and other logic...

return BrutezAI```

Where is the Script located?

Script is in JohnDoe and ModuleScript is in JohnDoe.
Screenshot_18

Can you try printing out

print(self.brutez)

In line 58?
And tell me what it prints out when testing

More precisely, in line 59. Outputs nil
.