-
What do you want to achieve? Keep it simple and clear!
I’m trying to make an NPC system with moods/needs such as hunger, thirst, cleanliness etc… The NPC will walk to the part/object that’ll fulfill that need and then if all needs are fine they’ll just walk around randomly -
What is the issue? Include screenshots / videos if possible!
No idea on where to start, and pathfinding seems to be broken for me. I haven’t had to use pathfinding until now and it’s like there’s nothing about it. -
What solutions have you tried so far? Did you look for solutions on the Developer Hub?
I’ve tried to make it, but it the NPC keeps going in a straight line and not to the destination. I even tried a script right off the developer hub and it still didn’t work. Also checked YT and dev forums / other sites and found nothing.
The main module will start everything up, so it’ll make the moods with the moods module and then will go to the pathfinding module.
main prisoner module
local prisonerHandler = {}
local moods = require(script.moodInterface)
local pathfinding = require(script.pathfinding)
task.spawn(function()
for _, prisoner in pairs(workspace.PrisonOperator_Main.TestingPlot.Prisoners:GetChildren()) do
local hrp:Part = prisoner:FindFirstChild("HumanoidRootPart")
hrp:SetNetworkOwner(nil)
moods:CreateMoods(prisoner)
wait(0.25)
pathfinding:Start(prisoner)
end
end)
return prisonerHandler
pathfinding submodule
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local path:Path = PathfindingService:CreatePath({
Costs = {
Water = 20
}
})
local TEST_DESTINATION = Vector3.new(workspace.PrisonOperator_Main.TestingPlot.Showers.ShowerA.Position)
local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local function followPath(destination, character, humanoid)
-- Compute the path
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Get the path waypoints
waypoints = path:GetWaypoints()
for i, waypoint:PathWaypoint in pairs(waypoints) do
local part = Instance.new("Part")
part.Shape = Enum.PartType.Ball
part.Color = Color3.fromRGB(255,0,0)
part.Anchored = true
part.Transparency = 0.5
part.CanCollide = false
part.Position = waypoint.Position
part.Parent = workspace.Waypoints
character.Humanoid.WalkSpeed = character:GetAttribute("WalkSpeed")
character.Humanoid:MoveTo(waypoint.Position)
character.Humanoid.MoveToFinished:Wait()
game.Debris:AddItem(part, 2)
end
-- Detect if path becomes blocked
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- Check if the obstacle is further down the path
if blockedWaypointIndex >= nextWaypointIndex then
-- Stop detecting path blockage until path is re-computed
blockedConnection:Disconnect()
-- Call function to re-compute new path
followPath(destination)
end
end)
-- Detect when movement to next waypoint is complete
if not reachedConnection then
reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
-- Increase waypoint index and move to next waypoint
nextWaypointIndex += 1
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
reachedConnection:Disconnect()
blockedConnection:Disconnect()
end
end)
end
-- Initially move to second waypoint (first waypoint is path start; skip it)
nextWaypointIndex = 2
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
warn("Path not computed!", errorMessage)
end
end
local pathfinding = {}
function pathfinding:Start(prisoner:Model)
followPath(TEST_DESTINATION, prisoner, prisoner:FindFirstChildOfClass("Humanoid"))
end
return pathfinding
mood module
local ServerStorage = game:GetService("ServerStorage")
local ScriptAssets = ServerStorage.ScriptAssets
local moodModule = {}
function moodModule:StartMoodDecay(Character:Model, moodInterface)
task.spawn(function()
while true do
wait(0.25) -- change to 5 later
local moodsFolder = Character:FindFirstChild("Moods")
for _, mood:IntValue in pairs(moodsFolder:GetChildren()) do
if mood.Name ~= "Happiness" then
if mood.Value > 0 then
mood.Value -= math.random(1,5)
else
mood.Value = 0
end
end
end
moodModule:LoadMoodInterface(moodInterface, moodsFolder)
end
end)
end
function moodModule:CreateMoods(Character:Model)
if Character:FindFirstChildOfClass("Humanoid") ~= nil then
local moodInterface = ScriptAssets.MoodInterface:Clone()
local moodsFolder = ScriptAssets.Moods:Clone()
moodsFolder.Parent = Character
moodInterface.Parent = Character:FindFirstChild("HumanoidRootPart")
moodModule:StartMoodDecay(Character, moodInterface)
end
end
function moodModule:LoadMoodInterface(moodInterface:BillboardGui, moodsFolder:Configuration)
moodInterface.Frame.BladderLabel.Text = moodsFolder.Bladder.Value
moodInterface.Frame.CleanLabel.Text = moodsFolder.Cleanliness.Value
end
return moodModule
mb if something is wrong, it’s my first time posting, i’ll try to respond as fast as possible if you have any questions