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
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.
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)
Sorry, the clues were hard to find