local RunService = game:GetService("RunService") local Workspace = game:GetService("Workspace") local Players = game:GetService("Players") -- 🛑 Place ID Verification if game.PlaceId ~= 18626211593 then warn("This script only runs in the verified place ID.") return end -- Delay start task.wait(3) -- Folder detection (accept singular or plural) local function getFolder(name) return Workspace:FindFirstChild(name) end local npcFolder = getFolder("NPC") or getFolder("NPCs") local entityFolder = getFolder("Entity") or getFolder("Entities") local folders = {} if npcFolder then table.insert(folders, {folder = npcFolder, type = "npc"}) end if entityFolder then table.insert(folders, {folder = entityFolder, type = "entity"}) end -- Tracking tables local highlights = {} local lastPositions = {} local hostiles = {} -- active hostile NPCs local hostileMemory = {} -- saved hostile records for session local pulseTimers = {} -- timers for non-hostile NPC pulsing -- 30Hz loop control local interval = 1 / 30 local lastUpdate = 0 local localPlayer = Players.LocalPlayer local function getChar() return localPlayer and localPlayer.Character or nil end -- Helper: build full path to NPC local function getFullPath(obj) local path = {} local current = obj while current and current.Parent do table.insert(path, 1, current.Name) current = current.Parent if current == Workspace then break end end return table.concat(path, ".") end -- Save NPC as hostile in session memory local function saveToSessionMemory(model) local path = getFullPath(model) local name = model.Name local id = path .. ":" .. name if not hostileMemory[id] then hostileMemory[id] = { name = name, path = path, time = os.time() } print("⚠ Hostile saved:", name, "at", path) end end -- Billboard for hostile NPCs local function createBillboard(model) if model:FindFirstChild("HostileBillboard") then return end local billboard = Instance.new("BillboardGui") billboard.Name = "HostileBillboard" billboard.Adornee = model:FindFirstChild("HumanoidRootPart") billboard.AlwaysOnTop = true billboard.Size = UDim2.new(0, 100, 0, 30) billboard.StudsOffset = Vector3.new(0, 4, 0) billboard.MaxDistance = 100 billboard.Parent = model local textLabel = Instance.new("TextLabel", billboard) textLabel.Size = UDim2.new(1, 0, 1, 0) textLabel.BackgroundTransparency = 1 textLabel.Text = ">HOSTILE<" textLabel.TextColor3 = Color3.fromRGB(255, 0, 0) textLabel.Font = Enum.Font.Nunito textLabel.TextScaled = true end -- Apply initial highlight local function applyHighlight(model, folderType) if highlights[model] then return end local hrp = model:FindFirstChild("HumanoidRootPart") if hrp then local hl = Instance.new("Highlight") hl.Adornee = model if folderType == "npc" then -- Initially green hl.FillColor = Color3.fromRGB(0, 255, 0) elseif folderType == "entity" then hl.FillColor = Color3.fromRGB(0, 100, 255) -- blue end hl.OutlineColor = Color3.fromRGB(255, 255, 255) hl.Parent = model highlights[model] = hl model.AncestryChanged:Connect(function(_, parent) if not parent and highlights[model] then highlights[model]:Destroy() highlights[model] = nil lastPositions[model] = nil hostiles[model] = nil pulseTimers[model] = nil end end) end end -- Cleanup destroyed NPCs/entities local function cleanupInvalid() for model, hl in pairs(highlights) do if not model.Parent then if hl then hl:Destroy() end highlights[model] = nil lastPositions[model] = nil hostiles[model] = nil pulseTimers[model] = nil end end end -- Pulse highlight for non-hostile NPCs local function pulseNonHostiles() for model, hl in pairs(highlights) do if model.Parent and not hostiles[model] and npcFolder and (model:IsDescendantOf(npcFolder) or (npcFolder and npcFolder.Name == "NPCs")) then if pulseTimers[model] == nil then pulseTimers[model] = os.clock() end local elapsed = os.clock() - pulseTimers[model] if elapsed >= 120 then -- every 2 minutes task.spawn(function() local originalColor = hl.FillColor hl.FillColor = Color3.fromRGB(0, 255, 0) task.wait(3) hl.FillColor = originalColor end) pulseTimers[model] = os.clock() end end end end -- Distance-based visibility for entities local function updateEntityVisibility() local char = getChar() local hrp = char and char:FindFirstChild("HumanoidRootPart") if not hrp then return end for model, hl in pairs(highlights) do if model.Parent and hl.FillColor == Color3.fromRGB(0, 100, 255) then local entHrp = model:FindFirstChild("HumanoidRootPart") if entHrp then local dist = (entHrp.Position - hrp.Position).Magnitude hl.Enabled = (dist >= 300 and dist <= 800) end end end end -- Main loop RunService.Heartbeat:Connect(function(dt) lastUpdate += dt if lastUpdate >= interval then for _, entry in ipairs(folders) do for _, model in ipairs(entry.folder:GetChildren()) do if model:IsA("Model") and model:FindFirstChild("HumanoidRootPart") then applyHighlight(model, entry.type) if entry.type == "npc" then local hrp = model.HumanoidRootPart local lastPos = lastPositions[model] local currentPos = hrp.Position local id = getFullPath(model) .. ":" .. model.Name if hostiles[model] or hostileMemory[id] then highlights[model].FillColor = Color3.fromRGB(255, 0, 0) hostiles[model] = true createBillboard(model) saveToSessionMemory(model) else if lastPos and (currentPos - lastPos).Magnitude > 0.05 then highlights[model].FillColor = Color3.fromRGB(255, 0, 0) hostiles[model] = true createBillboard(model) saveToSessionMemory(model) else highlights[model].FillColor = Color3.fromRGB(0, 255, 0) end end lastPositions[model] = currentPos end end end end pulseNonHostiles() updateEntityVisibility() cleanupInvalid() lastUpdate = 0 end end)