The AI basically roams around the room/area until it finds a player.
But sometimes, on a random occasion, the AI just doesn’t roam around and does not recalculate it’s path.
I’ve been debugging for 2 hours and I can’t seem to find the problem with the code..
function MisprintTemplate.new(misprint: Model, paths: {BasePart})
local self = setmetatable({}, MisprintTemplate)
self._trove = Trove.new()
self._path_trove = self._trove:Add(Trove.new())
self._pathfinder = self._trove:Add(SimplePath.new(misprint, {
AgentCanJump = false,
AgentClimb = false,
}))
self._model = self._trove:Add(misprint)
self._instance_paths = paths
self._lastTick = os.clock()
self._last_attack_tick = os.clock()
self._roaming = false
self._on_aggro = false
self._attacking = false
self._hitbox_size = vector.create(7, 7, 7)
self._range = 10
self._max_angle = 120
self._loop_check = 5
self._aggro_distance = 40
self._hit_cooldown = 1.25
self._attack_distance = 15
self._hitbox_check_cooldown = 0.025
self._updateDelay = 0.25 + math.random() * 0.25
self._default_walkspeed = self._model:GetAttribute("WalkSpeed") or 16
self._damage = self._model:GetAttribute("Damage") or 1
self._run_speed = self._model:GetAttribute("RunSpeed") or 24
--> Init misprint in workspace
self._model.Parent = LoadedMisprints
self._model:PivotTo(self._instance_paths[math.random(1, #self._instance_paths)].CFrame)
return self
end
function MisprintTemplate.ChangeWalkSpeed(self: Misprint, walkspeed: number)
local humanoid = self._model:FindFirstChildOfClass("Humanoid")
if humanoid then
humanoid.WalkSpeed = walkspeed
end
end
function MisprintTemplate.GetNearestPlayer(self: Misprint)
local character, dist = SimplePath.GetNearestCharacter(self._model:GetPivot().Position)
if character and dist <= self._attack_distance and os.clock() - self._last_attack_tick >= self._hit_cooldown then
self:Attack()
self._last_attack_tick = os.clock()
end
if character and dist <= self._aggro_distance then
self._path_trove:Destroy()
-- Set states
self._roaming = false
self._on_aggro = true
self._attacking = false
-- Stop any current path
if self._pathfinder.Status == SimplePath.StatusType.Active then
self._pathfinder:Stop()
end
self._model:SetAttribute("State", GlobalStates.Chase)
self:ChangeWalkSpeed(self._run_speed)
self._pathfinder:Run(character.PrimaryPart)
else
-- No player close, go back to roaming
if not self._roaming then
self._on_aggro = false
self._attacking = false
if self._pathfinder.Status == SimplePath.StatusType.Active then
self._pathfinder:Stop()
end
end
end
end
function MisprintTemplate.Roam(self: Misprint)
if self._roaming == false and self._on_aggro == false and self._attacking == false then
self._roaming = true
self._pathfinder:Run(self._instance_paths[math.random(1, #self._instance_paths)])
self._model:SetAttribute("State", GlobalStates.Walk)
self:ChangeWalkSpeed(self._default_walkspeed)
local reached : RBXScriptSignal
local errored : RBXScriptSignal
local blocked : RBXScriptSignal
reached = self._path_trove:Add(self._pathfinder.Reached:Connect(function()
self._roaming = false
self._path_trove:Destroy()
--self._path_trove:Remove(reached)
end))
errored = self._path_trove:Add(self._pathfinder.Error:Connect(function()
--self._path_trove:Remove(reached)
--self._path_trove:Remove(errored)
--if blocked then self._path_trove:Remove(blocked) end
self._roaming = false
self._path_trove:Destroy()
print("ERROR!")
end))
blocked = self._path_trove:Add(self._pathfinder.Blocked:Connect(function()
self._roaming = false
self._path_trove:Destroy()
--self._path_trove:Remove(reached)
--self._path_trove:Remove(errored)
--self._path_trove:Remove(blocked)
end))
end
end
function MisprintTemplate.Attack(self: Misprint)
self._trove:AddPromise(Promise.new(function(resolve, reject, onCancel)
local targets = {}
for i = 1, self._loop_check do
local target = Magnitude:GetTarget(self._model, self._hitbox_size, self._range, self._max_angle)
if target and not table.find(targets, target) then
table.insert(targets, target)
end
task.wait(self._hitbox_check_cooldown)
end
resolve(targets)
end)):andThen(function(targets: {Model?})
for _, target in targets do
if not target then continue end
target:SetAttribute("Hearts", target:GetAttribute("Hearts") - self._damage)
end
end)
end
function MisprintTemplate.Update(self: Misprint)
if (os.clock() - self._lastTick) >= self._updateDelay then
self._lastTick = os.clock()
self:GetNearestPlayer()
print(`Roaming: {self._roaming}, Attacking: {self._attacking}, Aggro: {self._on_aggro}`)
-- Only roam if not chasing
if not self._on_aggro then
self:Roam()
end
end
end
function MisprintTemplate.Destroy(self: Misprint)
self._trove:Destroy()
end
return MisprintTemplate