Scp 096 beta classic version scp games and Scp monsters
Key RequiredUniversal

Scp 096 beta classic version scp games and Scp monsters

Universal ScriptDreadmakesmodeDreadmakesmode 570 views 1.2K executesUpdated Oct 2, 2026
5.0/ 5(1 votes)
10100% Positive
Lua Script•727 lines (27583 chars)
-- ═══════════════════════════════════════════════════════════════════════════════
-- SCP-096 SL - STRICT STATE MACHINE AI (SMART PATHFINDING, MULTI-TAB)
-- ═══════════════════════════════════════════════════════════════════════════════

if getgenv().SCP096_GUI then
    pcall(function() getgenv().SCP096_GUI:Destroy() end)
end
getgenv().SCP096_GUI = nil

local VirtualInputManager = game:GetService("VirtualInputManager")
local Players = game:GetService("Players")
local SoundService = game:GetService("SoundService")
local Workspace = game:GetService("Workspace")
local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ReplicatedFirst = game:GetService("ReplicatedFirst")
local PathfindingService = game:GetService("PathfindingService")
local Teams = game:GetService("Teams")
local LocalPlayer = Players.LocalPlayer

-- UI Library Setup
local Library = nil
local uiLoadSuccess = pcall(function()
    Library = loadstring(game:HttpGet("https://raw.githubusercontent.com/xHeptc/Kavo-UI-Library/main/source.lua"))()
end)

if not uiLoadSuccess or not Library then
    Library = {
        CreateLib = function()
            local ScreenGui = Instance.new("ScreenGui")
            ScreenGui.Name = "SCP096FallbackGUI"
            ScreenGui.Parent = LocalPlayer:WaitForChild("PlayerGui")
            getgenv().SCP096_GUI = ScreenGui

            local function createSection(frame)
                return {
                    NewToggle = function(self, text, desc, callback)
                        local toggle = Instance.new("TextButton")
                        toggle.Size = UDim2.new(1, 0, 0, 30)
                        toggle.Text = text .. " (off)"
                        toggle.BackgroundColor3 = Color3.fromRGB(50,50,50)
                        toggle.Parent = frame
                        local state = false
                        toggle.MouseButton1Click:Connect(function()
                            state = not state
                            toggle.Text = text .. (state and " (on)" or " (off)")
                            callback(state)
                        end)
                    end,
                    NewButton = function(self, text, desc, callback)
                        local btn = Instance.new("TextButton")
                        btn.Size = UDim2.new(1, 0, 0, 30)
                        btn.Text = text
                        btn.BackgroundColor3 = Color3.fromRGB(0,100,200)
                        btn.Parent = frame
                        btn.MouseButton1Click:Connect(callback)
                    end
                }
            end

            return {
                NewTab = function(self, name)
                    local frame = Instance.new("ScrollingFrame")
                    frame.Size = UDim2.new(0, 220, 0, 260)
                    frame.Position = UDim2.new(0, 10 + (#ScreenGui:GetChildren() * 230), 0, 100)
                    frame.BackgroundColor3 = Color3.fromRGB(30,30,30)
                    frame.Name = name
                    frame.Parent = ScreenGui
                    
                    local title = Instance.new("TextLabel")
                    title.Size = UDim2.new(1, 0, 0, 20)
                    title.Text = name
                    title.TextColor3 = Color3.new(1,1,1)
                    title.BackgroundTransparency = 1
                    title.Parent = frame

                    local listLayout = Instance.new("UIListLayout")
                    listLayout.Parent = frame
                    listLayout.SortOrder = Enum.SortOrder.LayoutOrder

                    return {
                        NewSection = function() return createSection(frame) end
                    }
                end
            }
        end
    }
end

local Window = Library.CreateLib("SCP-096 SL", "DarkTheme")
local TabControl = Window:NewTab("Control")
local TabTeleports = Window:NewTab("Teleports & Teams")
local TabNPCKill = Window:NewTab("NPC Loop Kill")

local SecControl = TabControl:NewSection("SCP-096 State Machine")
local SecTeleports = TabTeleports:NewSection("Utility")
local SecNPCKill = TabNPCKill:NewSection("Fast Loop Kill")

-- Configuration & State Definitions
local BUBBLE_RADIUS = 4.0 
local KILL_DISTANCE = 4.0
local RUN_START_DELAY = 1.2
local MIN_CHASE_DURATION = 4.0
local KILL_ANIMATION_DURATION = 4.0
local HEALTH_MAX = 3000
local CRITICAL_CHANCE = 10
local KILL_COOLDOWN = 1.0
local SUPER_FAR_DISTANCE = 300 

local RUN_TOOL = "096 - Run"
local IDLE_TOOL = "096 - Idle"
local KILL_TOOL = "096 - Kill"

local currentState = "IDLE"
local aiEnabled = false
local manualModeEnabled = false
local npcTestingEnabled = false
local showBubble = false
local fastNpcLoopKillEnabled = false

local currentTarget = nil
local stateStartTime = 0
local chaseStartTime = 0
local touchConnection = nil
local bubblePart = nil
local isKillingActive = false
local lastScanTime = 0
local lastKillEndTime = 0
local lastPathTime = 0

-- Smooth Pathfinding Variables
local lastTargetPos = nil
local currentWaypoints = nil
local currentWaypointIndex = 1

-- Emote & Notice Variables
local hasTriggeredNotice = false
local tPoseTrack = nil

-- Client-Side (FE bypass inside self) Audio Setup
local function createLocalSound(name, id)
    local sound = Instance.new("Sound")
    sound.Name = name
    sound.SoundId = id
    sound.Volume = 1.5
    sound.Looped = true
    sound.Parent = SoundService
    return sound
end

local IdleSound = createLocalSound("IdleSound", "rbxassetid://491877423")
local NoticeSound = createLocalSound("NoticeSound", "rbxassetid://491877470")
local ScreamingSound = createLocalSound("ScreamingSound", "rbxassetid://491877546")
NoticeSound.Looped = false

-- Audio Utils
local function getSoundParent()
    local char = LocalPlayer.Character
    if not char then return SoundService end
    return char:FindFirstChild("HumanoidRootPart") or char:FindFirstChild("Head") or SoundService
end

-- Synchronized Dual Kill Audio
local function playSyncKillAudioFE()
    local parent = getSoundParent()
    
    local sound1 = Instance.new("Sound")
    sound1.SoundId = "rbxassetid://531421188"
    sound1.Volume = 1.5
    sound1.Parent = parent
    
    local sound2 = Instance.new("Sound")
    sound2.SoundId = "rbxassetid://17878427121"
    sound2.Volume = 1.5
    sound2.Parent = parent
    
    sound1:Play()
    sound2:Play()
    
    sound1.Ended:Connect(function() sound1:Destroy() end)
    sound2.Ended:Connect(function() sound2:Destroy() end)
end

-- Input Utils
local function autoClickScreen()
    local char = LocalPlayer.Character
    if char then
        for _, tool in ipairs(char:GetChildren()) do
            if tool:IsA("Tool") then tool:Activate() end
        end
    end
    pcall(function()
        local cam = Workspace.CurrentCamera
        if cam then
            local center = cam.ViewportSize / 2
            VirtualInputManager:SendMouseButtonEvent(center.X, center.Y, 0, true, game, 0)
            task.wait(0.05)
            VirtualInputManager:SendMouseButtonEvent(center.X, center.Y, 0, false, game, 0)
        end
    end)
end

-- Tools & Animation Utils
local function getTool(name)
    local char = LocalPlayer.Character
    if char and char:FindFirstChild(name) then return char:FindFirstChild(name) end
    local backpack = LocalPlayer:FindFirstChild("Backpack")
    return backpack and backpack:FindFirstChild(name)
end

local function equipTool(name)
    local tool = getTool(name)
    local humanoid = LocalPlayer.Character and LocalPlayer.Character:FindFirstChildOfClass("Humanoid")
    if tool and humanoid and tool.Parent ~= LocalPlayer.Character then
        humanoid:EquipTool(tool)
    end
end

local function unequipAllToolsFast()
    local humanoid = LocalPlayer.Character and LocalPlayer.Character:FindFirstChildOfClass("Humanoid")
    if humanoid then humanoid:UnequipTools() end
end

local function isToolEquipped(name)
    local char = LocalPlayer.Character
    return char and char:FindFirstChild(name) ~= nil
end

-- T-Pose Emote Logic
local function playTPoseEmote()
    local character = LocalPlayer.Character
    local humanoid = character and character:FindFirstChildOfClass("Humanoid")
    if not humanoid then return end
    
    local animator = humanoid:FindFirstChildOfClass("Animator") or Instance.new("Animator", humanoid)
    local anim = Instance.new("Animation")
    anim.AnimationId = "rbxassetid://116099256350648"
    
    tPoseTrack = animator:LoadAnimation(anim)
    tPoseTrack.Priority = Enum.AnimationPriority.Action
    tPoseTrack:Play()
    
    if not IdleSound.IsPlaying then IdleSound:Play() end
end

local currentAnimTrack = nil
local function playKillAnimation()
    local character = LocalPlayer.Character
    local humanoid = character and character:FindFirstChildOfClass("Humanoid")
    if not humanoid then return nil end
    local animator = humanoid:FindFirstChildOfClass("Animator") or Instance.new("Animator", humanoid)
    local anim = Instance.new("Animation")
    -- Updated to new Classic SCP 096 Kill Animation
    anim.AnimationId = "rbxassetid://15172539171"
    
    local success, track = pcall(function() return animator:LoadAnimation(anim) end)
    if success and track then
        if currentAnimTrack then currentAnimTrack:Stop() end
        currentAnimTrack = track
        track.Priority = Enum.AnimationPriority.Action4
        track:Play(0.1, 1, 1.0)
        return track
    end
    return nil
end

local function calculateDamage()
    return math.random(1, 100) <= CRITICAL_CHANCE and (10^30 + 10^18) or 500
end

local function executeKillTarget(targetHum)
    if not targetHum or targetHum.Health <= 0 then return end
    local damage = calculateDamage()
    local shotgun = getTool("Shotgun")
    if shotgun and shotgun:FindFirstChild("Receiver") then
        shotgun.Receiver:FireServer("Damage", targetHum, damage)
    else
        targetHum.Health = 0
    end
end

-- State Transitions
local function transitionToIdle()
    currentState = "IDLE"
    currentTarget = nil
    isKillingActive = false
    unequipAllToolsFast()
    equipTool(IDLE_TOOL)
    lastKillEndTime = os.clock()
    
    if ScreamingSound.IsPlaying then ScreamingSound:Stop() end
    if not IdleSound.IsPlaying then IdleSound:Play() end
    
    -- Reset pathfinding smoothing variables
    lastTargetPos = nil
    currentWaypoints = nil
    
    task.spawn(function()
        task.wait(0.15)
        if currentState == "IDLE" then autoClickScreen() end
    end)
end

local function doTeleport()
    local block = Workspace:FindFirstChild("Block")
    if block then
        local parts = block:GetChildren()
        if parts[198] and LocalPlayer.Character then
            local targetPart = parts[198]
            local lookVector = targetPart.CFrame.LookVector
            LocalPlayer.Character:PivotTo(CFrame.new(targetPart.Position, targetPart.Position + lookVector))
        end
    end
    transitionToIdle()
end

local function transitionToRunStart(targetModel)
    if currentState ~= "IDLE" or not targetModel then return end
    if os.clock() - lastKillEndTime < KILL_COOLDOWN then return end
    
    currentState = "RUN_START"
    currentTarget = targetModel
    stateStartTime = os.clock()
    unequipAllToolsFast()
    equipTool(RUN_TOOL)
    
    IdleSound:Stop()
    if not ScreamingSound.IsPlaying then ScreamingSound:Play() end
    
    task.spawn(function()
        task.wait(0.15)
        if currentState == "RUN_START" or currentState == "CHASE" then
            autoClickScreen()
        end
    end)
end

local function transitionToChase()
    if currentState ~= "RUN_START" then return end
    currentState = "CHASE"
    chaseStartTime = os.clock()
end

local function transitionToKill(targetHumanoid)
    if currentState ~= "CHASE" or isKillingActive or not targetHumanoid then return end
    currentState = "KILL"
    isKillingActive = true
    unequipAllToolsFast()
    equipTool(KILL_TOOL)
    playSyncKillAudioFE()

    -- Mute Screaming audio during kill animation
    ScreamingSound.Volume = 0

    local track = playKillAnimation()
    local isPlayer = Players:GetPlayerFromCharacter(targetHumanoid.Parent) ~= nil

    task.spawn(function()
        local startTime = os.clock()
        
        if not isPlayer then
            if track then track:AdjustSpeed(10) end 
            local godModeTriggered = false
            
            while targetHumanoid and targetHumanoid.Parent and targetHumanoid.Health > 0 do
                executeKillTarget(targetHumanoid)
                
                if os.clock() - startTime > 2.0 and not godModeTriggered then
                    godModeTriggered = true
                    if track then track:Stop() end
                    local hum = LocalPlayer.Character and LocalPlayer.Character:FindFirstChildOfClass("Humanoid")
                    if hum then
                        for _, playingTrack in ipairs(hum:GetPlayingAnimationTracks()) do
                            playingTrack:Stop()
                        end
                    end
                end
                task.wait(0.1) 
            end
        else
            local animDuration = (track and track.Length > 0) and track.Length or KILL_ANIMATION_DURATION
            while (os.clock() - startTime < animDuration) do
                if targetHumanoid and targetHumanoid.Parent and targetHumanoid.Health > 0 then
                    executeKillTarget(targetHumanoid)
                end
                task.wait(0.15)
            end
        end
        
        if track then track:Stop() end
        
        -- Restore Screaming audio volume and go Idle, stopping chase
        ScreamingSound.Volume = 1.5
        transitionToIdle()
    end)
end

-- Invisible Kill Tool
local function giveCustomKillTool()
    local backpack = LocalPlayer:FindFirstChild("Backpack") or (LocalPlayer.Character and LocalPlayer.Character:FindFirstChild("Backpack"))
    if not backpack then return end

    local oldTool = backpack:FindFirstChild(KILL_TOOL) or (LocalPlayer.Character and LocalPlayer.Character:FindFirstChild(KILL_TOOL))
    if oldTool then oldTool:Destroy() end

    local killTool = Instance.new("Tool")
    killTool.Name = KILL_TOOL
    killTool.RequiresHandle = true
    killTool.CanBeDropped = false
    killTool.Parent = backpack

    local handle = Instance.new("Part")
    handle.Name = "Handle"
    handle.Size = Vector3.new(1, 1, 1)
    handle.Transparency = 1
    handle.CanCollide = false
    handle.Parent = killTool
end

-- Touch Detection (Includes Fixed Manual Touch Kill)
local function setupTouchListener()
    if touchConnection then touchConnection:Disconnect() end
    local char = LocalPlayer.Character
    if not char then return end
    local root = char:FindFirstChild("HumanoidRootPart") or char:FindFirstChild("Torso")
    if not root then return end

    touchConnection = root.Touched:Connect(function(hit)
        local hitModel = hit.Parent
        if not hitModel or hitModel == char then return end
        local pHum = hitModel:FindFirstChildOfClass("Humanoid")
        if not pHum or pHum.Health <= 0 then return end

        if manualModeEnabled and isToolEquipped(KILL_TOOL) and not isKillingActive then
            if os.clock() - lastKillEndTime < KILL_COOLDOWN then return end
            isKillingActive = true
            playSyncKillAudioFE()
            ScreamingSound.Volume = 0
            
            local track = playKillAnimation()
            local animDuration = (track and track.Length > 0) and track.Length or KILL_ANIMATION_DURATION

            task.spawn(function()
                local startTime = os.clock()
                while (os.clock() - startTime < animDuration) do
                    executeKillTarget(pHum)
                    task.wait(0.15)
                end
                if track then track:Stop() end
                isKillingActive = false
                lastKillEndTime = os.clock()
                ScreamingSound.Volume = 1.5
            end)
        elseif aiEnabled and currentState == "IDLE" then
            if os.clock() - lastKillEndTime < KILL_COOLDOWN then return end
            local isPlayer = Players:GetPlayerFromCharacter(hitModel) ~= nil
            if not npcTestingEnabled or not isPlayer then
                transitionToRunStart(hitModel)
            end
        end
    end)
end

-- Initialization & Respawn
LocalPlayer.CharacterAdded:Connect(function(newChar)
    task.wait(0.5)
    setupTouchListener()
    playTPoseEmote()
end)
if LocalPlayer.Character then 
    setupTouchListener() 
    playTPoseEmote()
end

-- UI: Tab 1 - Control
SecControl:NewButton("Get shotgun", "Teleport to shotgun and equip", function()
    if LocalPlayer.Character and LocalPlayer.Character:FindFirstChild("HumanoidRootPart") then
        LocalPlayer.Character:PivotTo(CFrame.new(-789.93, 3.0, 27.41))
        task.wait(0.1)
        VirtualInputManager:SendKeyEvent(true, Enum.KeyCode.E, false, game)
        task.wait(0.05)
        VirtualInputManager:SendKeyEvent(false, Enum.KeyCode.E, false, game)
    end
end)
SecControl:NewButton("Give custom 096 - Kill", "Creates invisible kill tool", giveCustomKillTool)
SecControl:NewToggle("Act like 096 (State Machine AI)", "Strict sequence AI", function(state)
    aiEnabled = state
    manualModeEnabled = false; npcTestingEnabled = false
    transitionToIdle()
    if state and not getTool(KILL_TOOL) then giveCustomKillTool() end
end)
SecControl:NewToggle("Manual Control", "Touch-kill only works when 096 - Kill is equipped", function(state)
    manualModeEnabled = state
    if state then aiEnabled = false; npcTestingEnabled = false; currentTarget = nil end
end)
SecControl:NewToggle("Show Bubble", "Display 4.0 stud detection bubble", function(state)
    showBubble = state
    if not state and bubblePart then bubblePart:Destroy(); bubblePart = nil end
end)

-- UI: Tab 2 - Teleports & Teams
SecTeleports:NewButton("FE Custom Team (Scp096Sl)", "Creates & joins team so you take gun damage", function()
    local team = Teams:FindFirstChild("Scp096Sl")
    if not team then
        team = Instance.new("Team")
        team.Name = "Scp096Sl"
        team.TeamColor = BrickColor.new("Really red")
        team.AutoAssignable = false
        team.Parent = Teams
    end
    LocalPlayer.Team = team
end)
SecTeleports:NewButton("FE Name Tag Remover", "Removes Billboard/SurfaceGuis and DisplayNames", function()
    local char = LocalPlayer.Character
    if not char then return end
    for _, v in ipairs(char:GetDescendants()) do
        if v:IsA("BillboardGui") or v:IsA("SurfaceGui") then
            v.Enabled = false; v:Destroy()
        end
    end
    local hum = char:FindFirstChildOfClass("Humanoid")
    if hum then hum.DisplayDistanceType = Enum.HumanoidDisplayDistanceType.None end
end)
SecTeleports:NewButton("Teleport to Place Manually", "Teleports to block 198, resets chases", doTeleport)

-- UI: Tab 3 - NPC Kill
SecNPCKill:NewToggle("Fast Loop Kill NPC", "Instantly loops shotgun damage on SCP 096SL without lag/sound", function(state)
    fastNpcLoopKillEnabled = state
end)

-- Background Loops
-- 1. Fast NPC Loop Kill
task.spawn(function()
    while task.wait() do
        if fastNpcLoopKillEnabled then
            local target = Workspace:FindFirstChild("SCP 096SL")
            if target then
                local tHum = target:FindFirstChildOfClass("Humanoid")
                if tHum and tHum.Health > 0 then
                    local shotgun = getTool("Shotgun")
                    if shotgun and shotgun:FindFirstChild("Receiver") then
                        shotgun.Receiver:FireServer("Damage", tHum, 10^30)
                    end
                end
            end
        end
    end
end)

-- 2. NPC Ignore & Fast Regen (God Mode)
task.spawn(function()
    while task.wait(0.1) do
        local char = LocalPlayer.Character
        if char then
            local hum = char:FindFirstChildOfClass("Humanoid")
            if hum then
                hum.MaxHealth = 3000
                if hum.Health < 3000 then hum.Health = 3000 end
            end
            
            -- Clear player tags so NPCs ignore the user
            local pTag = char:FindFirstChild("Player") or char:FindFirstChild("TargetTag")
            if pTag then pTag:Destroy() end
        end
    end
end)

-- Main State Machine Loop
RunService.RenderStepped:Connect(function()
    local char = LocalPlayer.Character
    local humanoid = char and char:FindFirstChildOfClass("Humanoid")
    local root = char and char:FindFirstChild("HumanoidRootPart")

    if showBubble then
        if not bubblePart then
            bubblePart = Instance.new("Part")
            bubblePart.Shape = Enum.PartType.Ball; bubblePart.Size = Vector3.new(BUBBLE_RADIUS*2, BUBBLE_RADIUS*2, BUBBLE_RADIUS*2)
            bubblePart.Transparency = 0.7; bubblePart.Anchored = true; bubblePart.CanCollide = false
            bubblePart.Material = Enum.Material.ForceField; bubblePart.BrickColor = BrickColor.new("Cyan")
            bubblePart.Parent = Workspace
            
            bubblePart.Touched:Connect(function(hit)
                if not aiEnabled or currentState ~= "IDLE" then return end
                local hitModel = hit.Parent
                if hitModel and hitModel ~= char then
                    local hum = hitModel:FindFirstChildOfClass("Humanoid")
                    if hum and hum.Health > 0 then
                        equipTool(RUN_TOOL)
                        autoClickScreen()
                        transitionToRunStart(hitModel)
                    end
                end
            end)
        end
        if root then bubblePart.Position = root.Position end
    end

    if not aiEnabled or not char or not humanoid or not root then return end

    -- Notice Trigger Detection
    if not hasTriggeredNotice and currentState == "IDLE" then
        for _, player in ipairs(Players:GetPlayers()) do
            if player ~= LocalPlayer then
                local pChar = player.Character
                local pRoot = pChar and (pChar:FindFirstChild("HumanoidRootPart") or pChar:FindFirstChild("Torso"))
                if pRoot and (root.Position - pRoot.Position).Magnitude <= 9 then
                    hasTriggeredNotice = true
                    if tPoseTrack then tPoseTrack:Stop() end
                    
                    IdleSound:Stop()
                    NoticeSound:Play()
                    
                    -- Reset Idle Animation by unequipping and equipping
                    unequipAllToolsFast()
                    task.wait(0.1)
                    equipTool(IDLE_TOOL)
                    
                    -- Play sound again after reset
                    IdleSound:Play()
                    break
                end
            end
        end
    end

    if currentState == "IDLE" then
        if not isToolEquipped(IDLE_TOOL) then unequipAllToolsFast(); equipTool(IDLE_TOOL) end
        if os.clock() - lastKillEndTime < KILL_COOLDOWN then return end
        
        if os.clock() - lastScanTime >= 0.2 then
            lastScanTime = os.clock()
            
            local specificTarget = Workspace:FindFirstChild("SCP 096SL")
            if specificTarget then
                local tRoot = specificTarget:FindFirstChild("HumanoidRootPart")
                local tHum = specificTarget:FindFirstChildOfClass("Humanoid")
                if tRoot and tHum and tHum.Health > 0 and (root.Position - tRoot.Position).Magnitude <= BUBBLE_RADIUS then
                    transitionToRunStart(specificTarget)
                    return
                end
            end

            for _, player in ipairs(Players:GetPlayers()) do
                if player ~= LocalPlayer then
                    local pChar = player.Character
                    local pRoot = pChar and (pChar:FindFirstChild("HumanoidRootPart") or pChar:FindFirstChild("Torso"))
                    local pHum = pChar and pChar:FindFirstChildOfClass("Humanoid")
                    if pRoot and pHum and pHum.Health > 0 and (root.Position - pRoot.Position).Magnitude <= BUBBLE_RADIUS then
                        transitionToRunStart(pChar)
                        return
                    end
                end
            end
        end

    elseif currentState == "RUN_START" then
        if not isToolEquipped(RUN_TOOL) then unequipAllToolsFast(); equipTool(RUN_TOOL) end
        if os.clock() - stateStartTime >= RUN_START_DELAY then transitionToChase() end

    elseif currentState == "CHASE" then
        if not currentTarget or not currentTarget.Parent then transitionToIdle(); return end
        local targetHum = currentTarget:FindFirstChildOfClass("Humanoid")
        local targetRoot = currentTarget:FindFirstChild("HumanoidRootPart") or currentTarget:FindFirstChild("Torso")

        if targetHum and targetHum.Health <= 0 then
            transitionToIdle()
            return
        end

        if not targetHum or not targetRoot then transitionToIdle(); return end
        if not isToolEquipped(RUN_TOOL) then unequipAllToolsFast(); equipTool(RUN_TOOL) end

        local distToTarget = (root.Position - targetRoot.Position).Magnitude
        
        if distToTarget > SUPER_FAR_DISTANCE then
            -- Target is too far, freeze movement but maintain state and run animation
            humanoid:MoveTo(root.Position) 
        else
            if os.clock() - lastPathTime >= 0.2 then
                lastPathTime = os.clock()
                local targetPos = targetRoot.Position
                
                if not lastTargetPos or (lastTargetPos - targetPos).Magnitude > 3.0 then
                    lastTargetPos = targetPos
                    -- Smart Pathfinding Config
                    local path = PathfindingService:CreatePath({
                        AgentRadius = 2.0, 
                        AgentHeight = 5.0, 
                        WaypointSpacing = 4.0,
                        AgentCanJump = true
                    })
                    path:ComputeAsync(root.Position, targetPos)
                    
                    if path.Status == Enum.PathStatus.Success then
                        currentWaypoints = path:GetWaypoints()
                        currentWaypointIndex = 2
                    else
                        -- Path blocked (doors closed, tall places), clear waypoints
                        currentWaypoints = nil
                    end
                end
            end

            if currentWaypoints and currentWaypointIndex <= #currentWaypoints then
                local targetWp = currentWaypoints[currentWaypointIndex].Position
                humanoid:MoveTo(targetWp)
                
                if (root.Position - Vector3.new(targetWp.X, root.Position.Y, targetWp.Z)).Magnitude < 3.5 then
                    currentWaypointIndex = currentWaypointIndex + 1
                end
            else
                -- Freeze if target is unreachable (behind door/tall place), but maintain run tool
                humanoid:MoveTo(root.Position)
            end
        end

        if distToTarget <= KILL_DISTANCE and (os.clock() - chaseStartTime) >= MIN_CHASE_DURATION then
            transitionToKill(targetHum)
        end

    elseif currentState == "KILL" then
        if currentTarget then
            local targetRoot = currentTarget:FindFirstChild("HumanoidRootPart") or currentTarget:FindFirstChild("Torso")
            if targetRoot then humanoid:MoveTo(targetRoot.Position) end
        end
    end
end)

Features & Information

Scp

Community Comments (1)

Dave83891Dave83891Oct 6, 2026

is this for the classic scp 096 or SL?

More Scripts for Universal Scripts