Errors cannot be found and cannot be resolved in this script

local Self = script.Parent
local Settings = Self:FindFirstChild("Configurations")
local Mind = Self:FindFirstChild("Mind")

assert(Self:FindFirstChild("Humanoid") ~= nil)
assert(Settings ~= nil)
assert(Settings:FindFirstChild("MaximumDetectionDistance") ~= nil and Settings.MaximumDetectionDistance:IsA("NumberValue"))
assert(Settings:FindFirstChild("CanGiveUp") ~= nil and Settings.CanGiveUp:IsA("BoolValue"))
assert(Settings:FindFirstChild("CanRespawn") ~= nil and Settings.CanRespawn:IsA("BoolValue"))
assert(Settings:FindFirstChild("SpawnPoint") ~= nil and Settings.SpawnPoint:IsA("Vector3Value"))
assert(Settings:FindFirstChild("AutoDetectSpawnPoint") ~= nil and Settings.AutoDetectSpawnPoint:IsA("BoolValue"))
assert(Settings:FindFirstChild("FriendlyTeam") ~= nil and Settings.FriendlyTeam:IsA("BrickColorValue"))
assert(Settings:FindFirstChild("AttackDamage") ~= nil and Settings.AttackDamage:IsA("NumberValue"))
assert(Settings:FindFirstChild("AttackFrequency") ~= nil and Settings.AttackFrequency:IsA("NumberValue"))
assert(Settings:FindFirstChild("AttackRange") ~= nil and Settings.AttackRange:IsA("NumberValue"))
assert(Mind ~= nil)
assert(Mind:FindFirstChild("CurrentTargetHumanoid") ~= nil and Mind.CurrentTargetHumanoid:IsA("ObjectValue"))
assert(Self:FindFirstChild("Respawn") and Self.Respawn:IsA("BindableFunction"))
assert(Self:FindFirstChild("Died") and Self.Died:IsA("BindableEvent"))
assert(Self:FindFirstChild("Respawned") and Self.Died:IsA("BindableEvent"))
assert(Self:FindFirstChild("Attacked") and Self.Died:IsA("BindableEvent"))
assert(script:FindFirstChild("Attack") and script.Attack:IsA("Animation"))

local Info = {
	Players = game:GetService("Players"),
	PathfindingService = game:GetService("PathfindingService"),

	RecomputePathFrequency = 1, 
	RespawnWaitTime = 5, 
	JumpCheckFrequency = 1, 
}
local Data = {
	LastRecomputePath = 0,
	Recomputing = false, 
	PathCoords = {},
	IsDead = false,
	TimeOfDeath = 0,
	CurrentNode = nil,
	CurrentNodeIndex = 1,
	AutoRecompute = true,
	LastJumpCheck = 0,
	LastAttack = 0,

	BaseMonster = Self:Clone(),
	AttackTrack = nil,
}

local Monster = {}

function Monster:GetCFrame()
	local humanoidRootPart = Self:FindFirstChild("HumanoidRootPart")

	if humanoidRootPart ~= nil and humanoidRootPart:IsA("BasePart") then
		return humanoidRootPart.CFrame
	else
		return CFrame.new()
	end
end

function Monster:GetMaximumDetectionDistance()	
	local setting = Settings.MaximumDetectionDistance.Value

	if setting < 0 then
		return math.huge
	else
		return setting
	end
end

function Monster:SearchForTarget()
	local players = Info.Players:GetPlayers()
	local closestCharacter, closestCharacterDistance

	for i=1, #players do
		local player = players[i]

		if player.Neutral or player.TeamColor ~= Settings.FriendlyTeam.Value then
			local character = player.Character

			if character ~= nil and character:FindFirstChild("Humanoid") ~= nil and character.Humanoid:IsA("Humanoid") then
				local distance = player:DistanceFromCharacter(Monster:GetCFrame().Position)

				if distance < Monster:GetMaximumDetectionDistance() then
					if closestCharacter == nil then
						closestCharacter, closestCharacterDistance = character, distance
					else
						if closestCharacterDistance > distance then
							closestCharacter, closestCharacterDistance = character, distance
						end
					end
				end
			end
		end
	end
	if closestCharacter ~= nil then
		Mind.CurrentTargetHumanoid.Value = closestCharacter.Humanoid
	end
end

function Monster:TryRecomputePath()
	if Data.AutoRecompute or tick() - Data.LastRecomputePath > 1/Info.RecomputePathFrequency then
		Monster:RecomputePath()
	end
end

function Monster:GetTargetCFrame()
	local targetHumanoid = Mind.CurrentTargetHumanoid.Value

	if Monster:TargetIsValid() then
		return targetHumanoid.Torso.CFrame
	else
		return CFrame.new()
	end
end

function Monster:IsAlive()
	return Self.Humanoid.Health > 0 and Self.Humanoid.Torso ~= nil
end

function Monster:TargetIsValid()
	local targetHumanoid = Mind.CurrentTargetHumanoid.Value

	if targetHumanoid ~= nil and targetHumanoid:IsA("Humanoid") and targetHumanoid.Torso ~= nil and targetHumanoid.Torso:IsA("BasePart") then
		return true
	else
		return false
	end
end

function Monster:HasClearLineOfSight()
	local myPos, targetPos = Monster:GetCFrame().Position, Monster:GetTargetCFrame().Position

	local hit, pos = workspace:FindPartOnRayWithIgnoreList(
		Ray.new(
			myPos,
			targetPos - myPos
		),
		{
			Self,
			Mind.CurrentTargetHumanoid.Value.Parent
		}
	)	
	if hit == nil then
		return true
	else
		return false
	end
end

function Monster:RecomputePath()
	if not Data.Recomputing then
		if Monster:IsAlive() and Monster:TargetIsValid() then
			if Monster:HasClearLineOfSight() then
				Data.AutoRecompute = true
				Data.PathCoords = {
					Monster:GetCFrame().Position,
					Monster:GetTargetCFrame().Position
				}

				Data.LastRecomputePath = tick()
				Data.CurrentNode = nil
				Data.CurrentNodeIndex = 2 
			else
				Data.Recomputing = true 
				Data.AutoRecompute = false

				local path = Info.PathfindingService:FindPathAsync(
					Monster:GetCFrame().Position,
					Monster:GetTargetCFrame().Position,
					500
				)
				Data.PathCoords = path:GetPointCoordinates()			
				Data.Recomputing = false
				Data.LastRecomputePath = tick()
				Data.CurrentNode = nil
				Data.CurrentNodeIndex = 1
			end
		end
	end
end

function Monster:Update()
	Monster:ReevaluateTarget()
	Monster:SearchForTarget()
	Monster:TryRecomputePath()
	Monster:TravelPath()
end

function Monster:TravelPath()
	local closest, closestDistance, closestIndex
	local myP = Monster:GetCFrame().Position
	local skipCurrentNode = Data.CurrentNode ~= nil and (Data.CurrentNode - myP).magnitude < 3

	for i=Data.CurrentNodeIndex, #Data.PathCoords do
		local coord = Data.PathCoords[i]
		if not (skipCurrentNode and coord == Data.CurrentNode) then
			local distance = (coord - myP).magnitude

			if closest == nil then
				closest, closestDistance, closestIndex = coord, distance, i
			else
				if distance < closestDistance then
					closest, closestDistance, closestIndex = coord, distance, i
				else
					break
				end
			end
		end
	end

	if closest ~= nil then
		Data.CurrentNode = closest
		Data.CurrentNodeIndex = closestIndex

		local humanoid = Self:FindFirstChild("Humanoid")

		if humanoid ~= nil and humanoid:IsA("Humanoid") then
			humanoid:MoveTo(closest)
		end

		if Monster:IsAlive() and Monster:TargetIsValid() then
			Monster:TryJumpCheck()
			Monster:TryAttack()
		end

		if closestIndex == #Data.PathCoords then
			Data.AutoRecompute = true
		end
	end
end

function Monster:TryJumpCheck()
	if tick() - Data.LastJumpCheck > 1/Info.JumpCheckFrequency then
		Monster:JumpCheck()
	end
end

function Monster:TryAttack()
	if tick() - Data.LastAttack > 1/Settings.AttackFrequency.Value then
		Monster:Attack()
	end
end

function Monster:Attack()
	local myPos, targetPos = Monster:GetCFrame().Position, Monster:GetTargetCFrame().Position

	if (myPos - targetPos).magnitude <= Settings.AttackRange.Value then
		Mind.CurrentTargetHumanoid.Value:TakeDamage(Settings.AttackDamage.Value)
		Data.LastAttack = tick()
		Data.AttackTrack:Play()
	end
end

function Monster:JumpCheck()
	local myCFrame = Monster:GetCFrame()
	local checkVector = (Monster:GetTargetCFrame().Position - myCFrame.Position).unit*2

	local hit, pos = workspace:FindPartOnRay(
		Ray.new(
			myCFrame.Position + Vector3.new(0, 0, 0),
			checkVector
		),
		Self
	)

	if hit ~= nil and not hit:IsDescendantOf(Mind.CurrentTargetHumanoid.Value.Parent) then		
		local hit2, pos2 = workspace:FindPartOnRay(
			Ray.new(
				myCFrame.Position + Vector3.new(0, 0, 0),
				checkVector
			),
			Self
		)

		if hit2 == hit then
			if ((pos2 - pos)*Vector3.new(0,0,0)).magnitude < 0.1 then 
				Self.Humanoid.Jump = true
			end
		end
	end	
	Data.LastJumpCheck = tick()
end

function Monster:Connect()
	Mind.CurrentTargetHumanoid.Changed:connect(function(humanoid)
		if humanoid ~= nil then
			assert(humanoid:IsA("Humanoid"))

			Monster:RecomputePath()
		end
	end)	
	Self.Respawn.OnInvoke = function(point)
		Monster:Respawn(point)
	end
end

function Monster:Initialize()
	Monster:Connect()	
	if Settings.AutoDetectSpawnPoint.Value then
		Settings.SpawnPoint.Value = Monster:GetCFrame().Position
	end
end

function Monster:Respawn(point)
	local point = point or Settings.SpawnPoint.Value

	for index, obj in next, Data.BaseMonster:Clone():GetChildren() do
		if obj.Name == "Configurations" or obj.Name == "Mind" or obj.Name == "Respawned" or obj.Name == "Died" or obj.Name == "MonsterScript" or obj.Name == "Respawn" then
			obj:Destroy()
		else
			Self[obj.Name]:Destroy()
			obj.Parent = Self
		end
	end

	Monster:InitializeUnique()

	Self.Parent = workspace	
	Self.HumanoidRootPart.CFrame = CFrame.new(point)
	Settings.SpawnPoint.Value = point
	Self.Respawned:Fire()
end

function Monster:InitializeUnique()
	Data.AttackTrack = Self.Humanoid:LoadAnimation(script.Attack)
end

function Monster:ReevaluateTarget()
	local currentTarget = Mind.CurrentTargetHumanoid.Value

	if currentTarget ~= nil and currentTarget:IsA("Humanoid") then
		local character = currentTarget.Parent

		if character ~= nil then
			local player = Info.Players:GetPlayerFromCharacter(character)

			if player ~= nil then
				if not player.Neutral and player.TeamColor == Settings.FriendlyTeam.Value then
					Mind.CurrentTargetHumanoid.Value = nil
				end
			end
		end		
		if currentTarget == Mind.CurrentTargetHumanoid.Value then
			local torso = currentTarget.Torso

			if torso ~= nil and torso:IsA("BasePart") then
				if Settings.CanGiveUp.Value and (torso.Position - Monster:GetCFrame().Position).magnitude > Monster:GetMaximumDetectionDistance() then
					Mind.CurrentTargetHumanoid.Value = nil
				end
			end
		end
	end
end

Monster:Initialize()
Monster:InitializeUnique()

while true do
	if not Monster:IsAlive() then
		if Data.IsDead == false then
			Data.IsDead = true
			Data.TimeOfDeath = tick()
			Self.Died:Fire()
		end
		if Data.IsDead == true then
			if tick()-Data.TimeOfDeath > Info.RespawnWaitTime then
				Monster:Respawn()
			end
		end
	end	
	if Monster:IsAlive() then
		Monster:Update()
	end
	wait()
end
2 Likes

Could you please elaborate on that?

We still have no idea what you’re talking about.

Sorry for changing the content above don’t mind it again check the content above

We still don’t have any clue what the heck you are on about.

What is the issue? Should something be running which isn’t?

The picture of the error you posted says on line 117 that it couldn’t find the humanoid.

Line 117 is the Monster:IsAlive() function.

Which was called from line 359 at the top of the while true do loop.

The fix is to check if Humanoid exists as a child of Self, before attempting to check it’s HP.

1 Like

I think I know what the problem is, you need to make it so the humanoid has a :waitforchild for it, so it would be
Self:WaitForChild(“Humanoid”).Health > 0 and Self.Torso ~= nil

Edit: torso is not part of humanoid so that’s what also could of caused the problem (unless there is a value inside it)

3 Likes

Sorry, the clues were hard to find