CCCPaste

Knuckles Auto-Counter outcome memories

local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local ContextActionService = game:GetService("ContextActionService")
local ReplicatedStorage = game:GetService("ReplicatedStorage"):WaitForChild("ReplicatedStorage", 5) or game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")
local CollectionService = game:GetService("CollectionService")
local RunService = game:GetService("RunService")
local pcall = pcall

local TouchEnabled = UserInputService.TouchEnabled

local player = Players.LocalPlayer
local playerGui = player:WaitForChild("PlayerGui", 5)

-- Wait for character and handle respawns
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid", 5)
local rootPart = character:WaitForChild("HumanoidRootPart", 5)

player.CharacterAdded:Connect(function(newChar)
    character = newChar
    humanoid = newChar:WaitForChild("Humanoid", 5)
    rootPart = newChar:WaitForChild("HumanoidRootPart", 5)
end)

-- Create or get RemoteEvent with safety
local counterRemote
pcall(function()
    counterRemote = ReplicatedStorage:WaitForChild("CounterAttack", 3)
    if not counterRemote then
        counterRemote = Instance.new("RemoteEvent")
        counterRemote.Name = "CounterAttack"
        counterRemote.Parent = ReplicatedStorage
    end
end)

-- Config: Move-specific ranges
local DETECTION_RANGES = {
    ChargeGrab = 15,
    MeleeSwing = 8,
    GodsTrickery = 12,
    Default = 10
}

-- Known attack keywords
local ATTACK_KEYWORDS = {"attack", "swing", "charge", "grab", "punch", "slash", "trick", "hit", "strike", "melee", "god"}

local COOLDOWN = 2
local isBlocking = false
local lastCounter = 0
local frameCounter = 0  -- For throttling

-- Per-enemy debounce
local enemyDebounce = {}

-- Auto-Tag Common Executioners (shallower recursion for Delta perf)
local possibleEnemyNames = {"_2011X", "Fleetway", "V1", "Chaos", "Executioner", "Killer"}
local function findAndTagEnemies(parent, depth)
    if depth > 3 then return end  -- Limit depth
    pcall(function()
        for _, obj in ipairs(parent:GetChildren()) do
            if obj:IsA("Model") and table.find(possibleEnemyNames, obj.Name) and obj:FindFirstChild("Humanoid") and not CollectionService:HasTag(obj, "EnemyAttacker") then
                CollectionService:AddTag(obj, "EnemyAttacker")
            end
            findAndTagEnemies(obj, depth + 1)
        end
    end)
end

local function autoTagEnemies()
    pcall(findAndTagEnemies, workspace, 0)
end
autoTagEnemies()
task.spawn(function()
    while task.wait(10) do  -- Slower poll for Delta
        autoTagEnemies()
    end
end)

-- GUI Setup (Delta-safe)
local screenGui = Instance.new("ScreenGui")
screenGui.Name = "KnucklesCounterGUI"
screenGui.ResetOnSpawn = false
screenGui.Parent = playerGui

local mainFrame = Instance.new("Frame")
mainFrame.Size = UDim2.new(0, 220, 0, 120)
mainFrame.Position = UDim2.new(0, 10, 0, 10)
mainFrame.BackgroundColor3 = Color3.new(0, 0, 0)
mainFrame.BackgroundTransparency = 0.5
mainFrame.BorderSizePixel = 2
mainFrame.BorderColor3 = Color3.new(1, 0, 0)
mainFrame.Parent = screenGui

local titleLabel = Instance.new("TextLabel")
titleLabel.Size = UDim2.new(1, 0, 0.3, 0)
titleLabel.BackgroundTransparency = 1
titleLabel.Text = "Knuckles Auto-Counter"
titleLabel.TextColor3 = Color3.new(1, 0, 0)
titleLabel.TextScaled = true
titleLabel.Font = Enum.Font.SourceSansBold
titleLabel.Parent = mainFrame

local statusLabel = Instance.new("TextLabel")
statusLabel.Size = UDim2.new(1, 0, 0.3, 0)
statusLabel.Position = UDim2.new(0, 0, 0.3, 0)
statusLabel.BackgroundTransparency = 1
statusLabel.Text = TouchEnabled and "Tap Button to Toggle Block" or "Hold E to Block"
statusLabel.TextColor3 = Color3.new(1, 1, 1)
statusLabel.TextScaled = true
statusLabel.Font = Enum.Font.SourceSansItalic
statusLabel.Parent = mainFrame

local instructLabel = Instance.new("TextLabel")
instructLabel.Size = UDim2.new(1, 0, 0.2, 0)
instructLabel.Position = UDim2.new(0, 0, 0.6, 0)
instructLabel.BackgroundTransparency = 1
instructLabel.Text = "Auto-tags & detects attacks!"
instructLabel.TextColor3 = Color3.new(0, 1, 0)
instructLabel.TextScaled = true
instructLabel.Font = Enum.Font.SourceSans
instructLabel.Parent = mainFrame

-- Toggle Button (Mobile)
local toggleButton = Instance.new("TextButton")
toggleButton.Size = UDim2.new(0.9, 0, 0.2, 0)
toggleButton.Position = UDim2.new(0.05, 0, 0.8, 0)
toggleButton.BackgroundColor3 = Color3.new(1, 0, 0)
toggleButton.Text = "Toggle Block (Off)"
toggleButton.TextColor3 = Color3.new(1, 1, 1)
toggleButton.TextScaled = true
toggleButton.Font = Enum.Font.SourceSansBold
toggleButton.Visible = TouchEnabled
toggleButton.Parent = mainFrame

local function setBlocking(state)
    isBlocking = state
    if humanoid then
        humanoid.WalkSpeed = state and 8 or 16
    end
    toggleButton.Text = "Toggle Block (" .. (state and "On" or "Off") .. ")"
    toggleButton.BackgroundColor3 = state and Color3.new(0, 1, 0) or Color3.new(1, 0, 0)
    updateStatusGUI()
end

toggleButton.MouseButton1Click:Connect(function()
    setBlocking(not isBlocking)
end)

-- Input: Use ContextActionService for better Delta support
local blockAction = "BlockAction"
ContextActionService:BindAction(blockAction, function(actionName, inputState, inputObj)
    if actionName == blockAction then
        if inputState == Enum.UserInputState.Begin then
            setBlocking(true)
        elseif inputState == Enum.UserInputState.End then
            setBlocking(false)
        end
        return Enum.ContextActionResult.Sink
    end
end, false, Enum.KeyCode.E)
if TouchEnabled then
    ContextActionService:BindAction(blockAction, function() end, true, Enum.KeyCode.ButtonA)  -- Fallback for mobile
end

-- Update GUI (throttled)
local function updateStatusGUI()
    if not statusLabel then return end
    local baseText = isBlocking and "Blocking... Scanning attacks!" or (TouchEnabled and "Tap Button to Toggle Block" or "Hold E to Block")
    statusLabel.Text = baseText
    
    local cooldownLeft = COOLDOWN - (tick() - lastCounter)
    if cooldownLeft > 0 then
        statusLabel.Text = baseText .. "\nCooldown: " .. string.format("%.1f", cooldownLeft) .. "s"
        statusLabel.TextColor3 = Color3.new(1, 1, 0)
    else
        statusLabel.TextColor3 = isBlocking and Color3.new(0, 1, 0) or Color3.new(1, 1, 1)
    end
end

-- Punch effect (non-blocking)
local function playPunchEffect(moveType)
    pcall(function()
        local punchSound = Instance.new("Sound")
        punchSound.SoundId = "rbxassetid://156894510"
        punchSound.Volume = 1
        if rootPart then punchSound.Parent = rootPart end
        punchSound:Play()
        game:GetService("Debris"):AddItem(punchSound, 5)
        
        local camera = workspace.CurrentCamera
        local originalFOV = camera.FieldOfView
        local shake = TweenService:Create(camera, TweenInfo.new(0.1, Enum.EasingStyle.Linear, Enum.EasingDirection.Out, 5, true), {FieldOfView = originalFOV + math.random(-5, 5)})
        shake:Play()
        task.spawn(function()
            shake.Completed:Wait()
            camera.FieldOfView = originalFOV
        end)
        
        local flash = TweenService:Create(mainFrame, TweenInfo.new(0.2), {BackgroundTransparency = 0.2})
        flash:Play()
        task.spawn(function()
            flash.Completed:Wait()
            TweenService:Create(mainFrame, TweenInfo.new(0.2), {BackgroundTransparency = 0.5}):Play()
        end)
    end)
end

-- Infer move type
local function inferMoveType(name)
    if not name then return "Default" end
    name = name:lower()
    if name:find("charge") or name:find("grab") then return "ChargeGrab"
    elseif name:find("melee") or name:find("swing") or name:find("punch") or name:find("slash") then return "MeleeSwing"
    elseif name:find("god") or name:find("trick") then return "GodsTrickery"
    end
    return "Default"
end

-- Is attack
local function isAttackName(name)
    if not name then return false end
    name = name:lower()
    for _, keyword in ipairs(ATTACK_KEYWORDS) do
        if name:find(keyword) then return true end
    end
    return false
end

-- Connections cache
local animConnections = {}
local soundConnections = {}

-- Connect to enemy
local function connectEnemyDetection(enemy)
    if animConnections[enemy] then return end
    local hum = enemy:FindFirstChild("Humanoid")
    if not hum then return end
    
    pcall(function()
        local animConn = hum.AnimationPlayed:Connect(function(track)
            if track.IsPlaying and track.Animation and isAttackName(track.Animation.Name) then
                local moveType = inferMoveType(track.Animation.Name)
                performCounterIfInRange(enemy, moveType)
            end
        end)
        animConnections[enemy] = animConn
        
        local root = enemy:FindFirstChild("HumanoidRootPart") or enemy
        local soundConn = root.ChildAdded:Connect(function(child)
            if child:IsA("Sound") and child.IsPlaying and isAttackName(child.Name) then
                local moveType = inferMoveType(child.Name)
                performCounterIfInRange(enemy, moveType)
            end
        end)
        soundConnections[enemy] = soundConn
    end)
end

-- Shared counter logic with debounce
local function performCounterIfInRange(enemy, moveType)
    if not isBlocking or tick() - lastCounter < COOLDOWN then return end
    local now = tick()
    if enemyDebounce[enemy] and now - enemyDebounce[enemy] < 0.5 then return end  -- Per-enemy debounce
    enemyDebounce[enemy] = now
    
    local enemyRoot = enemy:FindFirstChild("HumanoidRootPart")
    if enemyRoot and rootPart then
        local distance = (rootPart.Position - enemyRoot.Position).Magnitude
        local range = DETECTION_RANGES[moveType] or DETECTION_RANGES.Default
        if distance <= range then
            pcall(function()
                counterRemote:FireServer(enemy.Name, moveType)  -- Send name instead of instance for safety
                playPunchEffect(moveType)
                lastCounter = now
                updateStatusGUI()
            end)
        end
    end
end

-- Main Detection Loop (throttled)
RunService.Heartbeat:Connect(function()
    frameCounter = frameCounter + 1
    if frameCounter % 2 ~= 0 then return end  -- Every 2nd frame
    updateStatusGUI()
    
    if not isBlocking then return end
    
    local myPos = rootPart and rootPart.Position
    if not myPos then return end
    
    pcall(function()
        for _, enemy in ipairs(CollectionService:GetTagged("EnemyAttacker")) do
            if enemy and enemy:FindFirstChild("HumanoidRootPart") and enemy:FindFirstChild("Humanoid") and enemy.Humanoid.Health > 0 then
                connectEnemyDetection(enemy)
                
                -- Proactive checks
                local hum = enemy.Humanoid
                for _, track in ipairs(hum:GetPlayingAnimationTracks()) do
                    if track.IsPlaying and track.Animation and isAttackName(track.Animation.Name) then
                        local moveType = inferMoveType(track.Animation.Name)
                        performCounterIfInRange(enemy, moveType)
                    end
                end
                
                local root = enemy:FindFirstChild("HumanoidRootPart") or enemy
                for _, child in ipairs(root:GetChildren()) do
                    if child:IsA("Sound") and child.IsPlaying and isAttackName(child.Name) then
                        local moveType = inferMoveType(child.Name)
                        performCounterIfInRange(enemy, moveType)
                    end
                end
            end
        end
    end)
end)

-- Cleanup
CollectionService:GetInstanceRemovedSignal("EnemyAttacker"):Connect(function(enemy)
    if animConnections[enemy] then
        animConnections[enemy]:Disconnect()
        animConnections[enemy] = nil
    end
    if soundConnections[enemy] then
        soundConnections[enemy]:Disconnect()
        soundConnections[enemy] = nil
    end
    enemyDebounce[enemy] = nil
end)