Improve this roblox script, and make it block slaps consistently:

```
-- Super Advanced Auto Block Script for Saber Showdown
-- Optimized with Improved Performance, Reduced Redundancy, and Enhanced Readability

-- === Services ===
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local StarterGui = game:GetService("StarterGui")
local VirtualInputManager = game:GetService("VirtualInputManager")
local CollectionService = game:GetService("CollectionService")
local Debris = game:GetService("Debris")

-- === Constants ===
local LOCAL_PLAYER = Players.LocalPlayer
local CAMERA = workspace.CurrentCamera
local ATTACK_HITBOX_TAG = "AttackHitbox"
local BLOCK_DIRECTIONS = {Forward = 1, Right = 2, Backward = 3, Left = 4}

-- === Remotes ===
local LightsaberRemotes = ReplicatedStorage:WaitForChild("LightsaberRemotes")
local BlockRemote = LightsaberRemotes:WaitForChild("Block")
local UnblockRemote = LightsaberRemotes:WaitForChild("Unblock")
local UpdateManualBlockRemote = LightsaberRemotes:WaitForChild("UpdateManualBlock")
local UpdateBlockDirectionRemote = LightsaberRemotes:WaitForChild("UpdateBlockDirection")

-- === Settings ===
local Settings = {
    -- Blocking Settings
    blockDistance = 15,            -- Max distance to attempt a block
    autoBlockEnabled = true,       -- Enable/Disable dynamic auto-blocking
    blockCooldown = 0.5,           -- Cooldown between blocks (seconds)
    slapBlockCooldown = 0.2,       -- Cooldown between blocks specifically for slaps
    attackTypes = {                -- Attack animation IDs
        Slap = 12625891544,
        SlappedLegs = 12671715182,
        SlappedArms = 12625896358,
        Punch = 12625897000,       -- Example attack ID
        Kick = 12625897500,        -- Example attack ID
        KickUp = 12625897944,      -- Added KickUp
        KickBack = 12625899752      -- Added KickBack
    },
    
    -- Counter Attacking Settings
    autoCounterEnabled = true,     -- Enable/Disable auto counter attacks
    autoCounterDistance = 10,      -- Distance within which to auto counter
    counterCooldown = 1.5,         -- Cooldown between counters (seconds)
    counterKey = Enum.KeyCode.E,    -- Key to use for countering

    reactionTimeThreshold = 0.2,   -- Threshold for reaction time (in seconds)
    predictionFactor = 0.5,        -- Factor for predicting enemy movements (0-1)
    
    -- Slap Lag Handling
    slapLagCompensation = 0.2,     -- Additional delay to compensate for lag in slap attacks
    
    -- Aim-Lock Directional Block Settings
    aimLockEnabled = true,         -- Enable/Disable aim-lock directional blocking
    aimLockSmoothness = 0.1,       -- Smoothness factor for direction adjustment
    
    -- UI Settings
    ui = {
        ScreenGuiName = "AutoBlockUI",
        BlackBoxSize = UDim2.new(0.25, 0, 0.1, 0),
        BlackBoxPosition = UDim2.new(0, 0, 0.9, 0),
        BlackBoxColor = Color3.fromRGB(0, 0, 0),
        BlackBoxTransparency = 0.5,
        LoadingBarSize = UDim2.new(1, 0, 0.2, 0),
        LoadingBarPosition = UDim2.new(0, 0, -0.2, 0),
        LoadingBarColor = Color3.fromRGB(0, 255, 0),
        LoadingBarTransparency = 0.3,
        MessageBoxText = "Press 'Q' to toggle Auto Block",
        MessageBoxColor = Color3.fromRGB(255, 255, 255),
        MessageBoxTransparency = 1,
    }
}

-- === State Tracking ===
local State = {
    isBlocking = false,
    lastBlockTime = {},
    lastCounterTime = {},
    autoBlockEnabled = Settings.autoBlockEnabled,
    currentBlockDirection = BLOCK_DIRECTIONS.Forward
}

-- === UI Setup ===
local function setupUI()
    local screenGui = Instance.new("ScreenGui")
    screenGui.Name = Settings.ui.ScreenGuiName
    screenGui.Parent = LOCAL_PLAYER:WaitForChild("PlayerGui")
    screenGui.ResetOnSpawn = false
    
    -- Black Box Frame
    local blackBox = Instance.new("Frame")
    blackBox.Size = Settings.ui.BlackBoxSize
    blackBox.Position = Settings.ui.BlackBoxPosition
    blackBox.BackgroundColor3 = Settings.ui.BlackBoxColor
    blackBox.BackgroundTransparency = Settings.ui.BlackBoxTransparency
    blackBox.Parent = screenGui
    
    -- Loading Bar
    local loadingBar = Instance.new("Frame")
    loadingBar.Size = Settings.ui.LoadingBarSize
    loadingBar.Position = Settings.ui.LoadingBarPosition
    loadingBar.BackgroundColor3 = Settings.ui.LoadingBarColor
    loadingBar.BackgroundTransparency = Settings.ui.LoadingBarTransparency
    loadingBar.Parent = blackBox
    
    -- Message Box
    local messageBox = Instance.new("TextLabel")
    messageBox.Size = UDim2.new(1, 0, 1, 0)
    messageBox.Position = UDim2.new(0, 0, 0, 0)
    messageBox.BackgroundTransparency = Settings.ui.MessageBoxTransparency
    messageBox.TextColor3 = Settings.ui.MessageBoxColor
    messageBox.TextScaled = true
    messageBox.Text = Settings.ui.MessageBoxText
    messageBox.Parent = blackBox
    
    return {
        ScreenGui = screenGui,
        BlackBox = blackBox,
        LoadingBar = loadingBar,
        MessageBox = messageBox
    }
end

local UI = setupUI()

-- === Utility Functions ===

-- Start blocking if not already blocking
local function startBlocking()
    if not State.isBlocking then
        State.isBlocking = true
        BlockRemote:FireServer()
        print("[AutoBlock] Blocking started")
    end
end

-- Stop blocking if currently blocking
local function stopBlocking()
    if State.isBlocking then
        State.isBlocking = false
        UnblockRemote:FireServer()
        print("[AutoBlock] Blocking stopped")
    end
end

-- Toggle blocking state
local function toggleBlocking()
    if State.isBlocking then
        stopBlocking()
    else
        startBlocking()
    end
end

-- Predict enemy movement based on velocity
local function predictEnemyMovement(enemy)
    local enemyHRP = enemy.Character and enemy.Character:FindFirstChild("HumanoidRootPart")
    if not enemyHRP then return nil end

    local velocity = enemyHRP.Velocity
    return enemyHRP.Position + velocity * Settings.predictionFactor
end

-- Determine hit direction based on attacker's position and camera direction
local function getHitDirection(attackerPosition)
    local characterPosition = LOCAL_PLAYER.Character.HumanoidRootPart.Position
    local direction = (attackerPosition - characterPosition).Unit
    local camForward = CAMERA.CFrame.LookVector
    local dotProduct = direction:Dot(camForward)

    if Settings.aimLockEnabled then
        if dotProduct > math.cos(math.rad(45)) then
            return BLOCK_DIRECTIONS.Forward
        elseif dotProduct < -math.cos(math.rad(45)) then
            return BLOCK_DIRECTIONS.Backward
        else
            local rightDot = direction:Dot(CAMERA.CFrame.RightVector)
            return rightDot > 0 and BLOCK_DIRECTIONS.Right or BLOCK_DIRECTIONS.Left
        end
    else
        local angle = math.deg(math.atan2(direction.Z, direction.X))
        angle = (angle + 360) % 360  -- Normalize angle between 0-360

        if angle < 45 or angle >= 315 then
            return BLOCK_DIRECTIONS.Forward
        elseif angle < 135 then
            return BLOCK_DIRECTIONS.Right
        elseif angle < 225 then
            return BLOCK_DIRECTIONS.Backward
        else
            return BLOCK_DIRECTIONS.Left
        end
    end
end

-- Smoothly update block direction based on desired direction
local function getSmoothBlockDirection(attackerPosition)
    local desiredDirection = getHitDirection(attackerPosition)
    local currentDirection = State.currentBlockDirection

    -- Smooth transition
    local smoothness = Settings.aimLockSmoothness
    local newDirection = currentDirection + (desiredDirection - currentDirection) * smoothness

    -- Clamp to valid directions
    newDirection = math.clamp(newDirection, BLOCK_DIRECTIONS.Forward, BLOCK_DIRECTIONS.Left)

    -- Round to nearest integer direction
    newDirection = math.round(newDirection)

    -- Update only if direction has changed
    if newDirection ~= currentDirection then
        State.currentBlockDirection = newDirection
        UpdateBlockDirectionRemote:FireServer(newDirection)
    end

    return newDirection
end

-- Handle incoming hits with appropriate cooldowns and actions
local function handleIncomingHit(attacker, attackerPosition, isSlap)
    local currentTime = tick()

    -- Determine appropriate cooldown
    local cooldown = isSlap and Settings.slapBlockCooldown or Settings.blockCooldown

    -- Check for cooldown
    if State.lastBlockTime[attacker] and (currentTime - State.lastBlockTime[attacker]) < cooldown then
        return
    end

    -- Check distance
    local characterHRP = LOCAL_PLAYER.Character.HumanoidRootPart
    local distance = (characterHRP.Position - attackerPosition).Magnitude
    if distance > Settings.blockDistance then
        return
    end

    -- Determine reaction delay
    local reactionDelay = isSlap and 0 or math.random() * Settings.reactionTimeThreshold

    task.delay(reactionDelay, function()
        local predictedPos = predictEnemyMovement(attacker)
        local blockDirPos = predictedPos or attackerPosition
        local blockDirection = getSmoothBlockDirection(blockDirPos)

        startBlocking()
        State.lastBlockTime[attacker] = tick()

        -- Schedule unblocking with lag compensation
        local unblockDelay = isSlap and Settings.slapLagCompensation or 0.5
        task.delay(unblockDelay, stopBlocking)
    end)

    -- Handle Auto Countering
    if Settings.autoCounterEnabled and distance <= Settings.autoCounterDistance then
        if not State.lastCounterTime[attacker] or (currentTime - State.lastCounterTime[attacker]) >= Settings.counterCooldown then
            -- Simulate Counter Key Press
            VirtualInputManager:SendKeyEvent(true, Settings.counterKey, false, game)
            task.delay(0.05, function()
                VirtualInputManager:SendKeyEvent(false, Settings.counterKey, false, game)
            end)
            State.lastCounterTime[attacker] = currentTime
            print("[AutoBlock] Countered attack from " .. attacker.Name)
        end
    end
end

-- === Animation State Detection ===
local function onAnimationPlayed(animTrack, opponentPlayer)
    if not animTrack.Animation or not animTrack.Animation.AnimationId then return end

    for attackType, animId in pairs(Settings.attackTypes) do
        if animTrack.Animation.AnimationId == "rbxassetid://" .. tostring(animId) then
            print("[AutoBlock] Detected attack '" .. attackType .. "' from " .. opponentPlayer.Name)
            local attackerHRP = opponentPlayer.Character and opponentPlayer.Character:FindFirstChild("HumanoidRootPart")
            if attackerHRP then
                local isSlap = (attackType == "Slap")
                handleIncomingHit(opponentPlayer, attackerHRP.Position, isSlap)
            end
            break
        end
    end
end

local function monitorAnimations(character, opponentPlayer)
    local humanoid = character:WaitForChild("Humanoid")
    local connection

    connection = humanoid.AnimationPlayed:Connect(function(animTrack)
        onAnimationPlayed(animTrack, opponentPlayer)
    end)

    -- Cleanup connection when character is removed
    character.AncestryChanged:Connect(function(_, parent)
        if not parent and connection then
            connection:Disconnect()
        end
    end)
end

-- === Hitbox Detection ===
local function onHitboxTouched(hit, attackerPlayer)
    local attackerCharacter = hit.Parent
    if not attackerCharacter or attackerPlayer == LOCAL_PLAYER then return end

    local attackerHRP = attackerCharacter:FindFirstChild("HumanoidRootPart")
    if attackerHRP then
        print("[AutoBlock] Hitbox detected attack from " .. attackerPlayer.Name)
        handleIncomingHit(attackerPlayer, attackerHRP.Position, false)
    end
end

local function monitorHitboxes(character, attackerPlayer)
    local hitboxes = CollectionService:GetTagged(ATTACK_HITBOX_TAG)
    for _, hitbox in ipairs(hitboxes) do
        if hitbox:IsDescendantOf(character) then
            local connection
            connection = hitbox.Touched:Connect(function(hit)
                onHitboxTouched(hit, attackerPlayer)
            end)

            -- Optional: Disconnect hitbox after certain time to prevent memory leaks
            Debris:AddItem(hitbox, 300)  -- Example: Remove hitbox after 5 minutes
        end
    end
end

-- === Advanced Reaction-Based Auto-Block ===
local function advancedReactionAutoBlock()
    if not Settings.autoBlockEnabled then return end

    RunService.Heartbeat:Connect(function()
        for _, plr in ipairs(Players:GetPlayers()) do
            if plr ~= LOCAL_PLAYER and plr.Character and plr.Character:FindFirstChild("HumanoidRootPart") then
                local enemyHRP = plr.Character.HumanoidRootPart
                local distance = (LOCAL_PLAYER.Character.HumanoidRootPart.Position - enemyHRP.Position).Magnitude
                if distance <= Settings.blockDistance then
                    local predictedPosition = predictEnemyMovement(plr)
                    getSmoothBlockDirection(predictedPosition or enemyHRP.Position)

                    -- Check for active attack animations
                    local enemyHumanoid = plr.Character:FindFirstChild("Humanoid")
                    if enemyHumanoid then
                        for _, animTrack in ipairs(enemyHumanoid:GetPlayingAnimationTracks()) do
                            if animTrack.Animation and animTrack.Animation.AnimationId then
                                for attackType, animId in pairs(Settings.attackTypes) do
                                    if animTrack.Animation.AnimationId == "rbxassetid://" .. tostring(animId) then
                                        local isSlap = (attackType == "Slap")
                                        handleIncomingHit(plr, enemyHRP.Position, isSlap)
                                        break
                                    end
                                end
                            end
                        end
                    end
                end
            end
        end
    end)
end

-- === Player Monitoring ===
local function onPlayerAdded(plr)
    if plr == LOCAL_PLAYER then return end

    local function onCharacterAdded(character)
        monitorAnimations(character, plr)
        monitorHitboxes(character, plr)
    end

    if plr.Character then
        onCharacterAdded(plr.Character)
    end

    plr.CharacterAdded:Connect(onCharacterAdded)
end

-- Monitor existing players
for _, plr in ipairs(Players:GetPlayers()) do
    onPlayerAdded(plr)
end

-- Connect to future players
Players.PlayerAdded:Connect(onPlayerAdded)

-- === Manual Blocking Toggle ===
UserInputService.InputBegan:Connect(function(input, gameProcessed)
    if gameProcessed then return end
    if input.KeyCode == Enum.KeyCode.Q then
        toggleBlocking()
    end
end)

-- === Combined UI Feedback and Aim-Lock Directional Block Update ===
RunService.RenderStepped:Connect(function()
    -- Update UI
    if State.isBlocking then
        UI.MessageBox.Text = "Blocking Active"
        UI.LoadingBar.BackgroundColor3 = Color3.fromRGB(0, 255, 0)
    else
        UI.MessageBox.Text = Settings.ui.MessageBoxText
        UI.LoadingBar.BackgroundColor3 = Color3.fromRGB(255, 0, 0)
    end

    -- Update Block Direction based on Aim-Lock
    if Settings.aimLockEnabled and State.autoBlockEnabled and State.isBlocking then
        local mousePos = UserInputService:GetMouseLocation()
        local mouseRay = CAMERA:ScreenPointToRay(mousePos.X, mousePos.Y)
        local targetPosition = LOCAL_PLAYER.Character.HumanoidRootPart.Position + (mouseRay.Direction * 10)
        getSmoothBlockDirection(targetPosition)
    end
end)

-- === Cleanup on Character Death or Removal ===
local function onCharacterDied()
    stopBlocking()
end

local function connectCharacterEvents(character)
    local humanoid = character:WaitForChild("Humanoid")
    humanoid.Died:Connect(onCharacterDied)
    character.AncestryChanged:Connect(function(_, parent)
        if not parent then
            stopBlocking()
        end
    end)
end

-- Connect initial character events
if LOCAL_PLAYER.Character then
    connectCharacterEvents(LOCAL_PLAYER.Character)
end

-- Connect to future character spawns
LOCAL_PLAYER.CharacterAdded:Connect(connectCharacterEvents)

-- === Initialize Advanced Reaction System ===
advancedReactionAutoBlock()

-- Notify that the script is running
print("[AutoBlock] Advanced Auto Block Script is now running.")
```