Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local char = script.Parent
- local head = char:WaitForChild("Head")
- local torso = char:WaitForChild("Torso")
- local hum = char:WaitForChild("Humanoid")
- local destReachRange = 3
- local losRange = 128
- local hearRange = 48
- local ai_max_range = math.huge
- local attackRange = 2 --65
- local runSpeed = 16
- local patrolSpeed = 6
- local Orakel = require(game.ReplicatedStorage.Orakel.Main)
- local npcLib = Orakel.LoadModule("NpcLib")
- local pathLib = Orakel.LoadModule("PathLib")
- local map = workspace.Map
- local masterTable, mnt_index = pathLib.CollectNodes(map.Nodes)
- math.randomseed(os.time())
- local gyro = Instance.new("BodyGyro", script.Parent.Torso)
- gyro.D = 100
- gyro.P = 400
- gyro.MaxTorque = Vector3.new(0, 400000, 0)
- function rotateTowards(goal)
- if gyro ~= nil then
- gyro.CFrame = CFrame.new(torso.Position, goal) - torso.Position
- end
- end
- function shuffleTable(tab)
- local t = tab
- local rand = math.random
- assert( t, "shuffleTable() expected a table, got nil" )
- local iterations = #t
- local j
- for i = iterations, 2, -1 do
- j = rand(i)
- t[i], t[j] = t[j], t[i]
- end
- return t
- end
- function hasReachedDestination(dest)
- if (torso.Position - dest.Position).magnitude <= destReachRange then
- return true
- else
- return false
- end
- end
- function lineOfSight(a, b)
- local los = false
- local vis = npcLib.LineOfSight(a, b, losRange, _G.ignorelist)
- local behind = (b.CFrame:toObjectSpace(a.CFrame).p.Z < 0)
- if vis and not behind then
- los = true
- end
- return los
- end
- function attack()
- end
- function chooseNodeInArea(areanode)
- local validNodes = pathLib.GetNodesVisibleInRadius(areanode.Position, 32, true, workspace.Map.Nodes, masterTable)
- return validNodes[math.random(1,#validNodes)]
- end
- function chooseTarget()
- --[[
- local targets = {}
- --Find Player targets
- for _, plrInGame in pairs(game.Players:GetPlayers()) do
- local plr = plrInGame.Character
- if plr ~= nil then
- if plr.Humanoid.Health > 0 then
- local los = lineOfSight(head, plr.Head)
- if los then
- table.insert(targets, plr)
- else
- --[[if plr.EmittingSound.Value then
- local dist = (torso.Position - plr.Torso.Position).magnitude
- if dist <= hearRange then
- table.insert(targets, plr)
- end
- end]]
- --[[ end
- end
- end
- end
- if #targets > 1 then
- local nearest = targets[1]
- for t = 2, #targets do
- local old = (nearest.Torso.Position - torso.Position).magnitude
- local new = (targets[t].Torso.Position - torso.Position).magnitude
- if new < old then
- nearest = targets[t]
- end
- end
- elseif #targets == 1 then
- return targets[1]
- end
- ]]
- return nil
- end
- function pathFind(target, startPos, goalPos)
- local startID = pathLib.GetNearestNode(startPos, false, map.Nodes, masterTable)
- local goalID = pathLib.GetNearestNode(goalPos, false, map.Nodes, masterTable)
- local path = pathLib.AStar(masterTable, startID, goalID)
- for nodeNum, node in pairs(path) do
- local eta = npcLib.EstimatedPathTime(torso.Position, node.Position, hum.WalkSpeed)
- local timeWalked = 0
- while true do
- hum:MoveTo(node.Position)
- rotateTowards(node.Position)
- local act = wait(1/20)
- timeWalked = timeWalked + act
- local newTarget = chooseTarget()
- --Reached node, Move to next node
- if hasReachedDestination(node) then
- break
- end
- --Target changed!
- if newTarget ~= target and newTarget ~= nil then
- warn("-> Target changed from "..tostring(target).." to "..tostring(newTarget)..", aborting pathfind!")
- return false
- end
- --Timed out! Return false, acquire new path
- if timeWalked > eta then
- warn("-> Timed out!")
- return false
- end
- --Got line of sight on target, Stop finding the path and just walk there
- if target.Parent:FindFirstChild("Humanoid") then
- if npcLib.LineOfSight(head, target.Torso, losRange, _G.ignorelist) and (torso.Position - target.Torso.Position).magnitude <= 25 then
- warn("-> Got line of sight on target, Stop pathfinding")
- return false
- end
- end
- end
- end
- return true
- end
- warn("NPC loaded")
- while true do
- wait(1/30)
- local target-- = chooseTarget()
- if target == nil then
- --Area nodes are basically positions of rooms, each room will have one area node
- local areanodes = map.AreaNodes:GetChildren()
- areanodes = shuffleTable(areanodes)
- for node = 1, #areanodes do
- print("Patrolling area #"..node)
- local patrolLocation = chooseNodeInArea(areanodes[node])
- local success = pathFind(patrolLocation, torso.Position, patrolLocation.Position)
- if not success then
- warn("Pathfind was not a success")
- break
- else
- wait(math.random(3, 6))
- end
- end
- else
- end
- end
Add Comment
Please, Sign In to add comment