Further optimize, and make it simultaneously block in every direction when close to a player by debugging and improving more features (in an advanced way):

```
--[[
    Auto Block V.3 for Saber Showdown
    - Enhanced specifically for handling Slap attacks
    - Optimized reaction timing and prediction for Slaps
    - Improved detection accuracy and cooldown management
    - Dedicated UI indicators for Slap attacks
    - Comprehensive logging for better monitoring
    - Performance optimizations to ensure smooth gameplay
    - Enhanced, modern, and refined GUI for improved user experience
--]]

-- === Services ===
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local VirtualInputManager = game:GetService("VirtualInputManager")
local CollectionService = game:GetService("CollectionService")
local Debris = game:GetService("Debris")
local TweenService = game:GetService("TweenService")
local SoundService = game:GetService("SoundService")
local Workspace = workspace
local HttpService = game:GetService("HttpService")

-- === 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
}

local LOG_LEVELS = {
    INFO = 1,
    WARNING = 2,
    ERROR = 3
}

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

-- === Settings ===
local Settings = {
    -- Blocking Settings
    blockDistances = {              -- Max distance to attempt a block per attack type
        Slap = 10,                   -- Slaps require closer proximity
        Default = 15                 -- Default distance for other attacks
    },
    autoBlockEnabled = true,         -- Enable/Disable dynamic auto-blocking
    blockCooldown = 0.5,             -- General cooldown between blocks (seconds)
    attackBlockCooldowns = {         -- Cooldown between blocks per attack type (seconds)
        Slap = 0.2,
        Default = 0.5
    },
    attackTypes = {                  -- Attack animation IDs
        Slap = "rbxassetid://12625891544",
        SlappedLegs = "rbxassetid://12671715182",
        SlappedArms = "rbxassetid://12625896358",
        Punch = "rbxassetid://12625897000",         -- Example attack ID
        Kick = "rbxassetid://12625897500",          -- Example attack ID
        KickUp = "rbxassetid://12625897944",        -- Added KickUp
        KickBack = "rbxassetid://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)
    defaultCounterKey = Enum.KeyCode.E, -- Default key to use for countering
    
    -- Reaction Settings
    reactionTimeThreshold = 0.15,    -- Threshold for reaction time (in seconds)
    predictionFactor = 0.6,          -- Factor for predicting enemy movements (0-1)
    
    -- Slap Lag Handling
    slapLagCompensation = 0.1,       -- 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",
        BackgroundColor = Color3.fromRGB(30, 30, 30),
        PrimaryColor = Color3.fromRGB(45, 45, 45),
        AccentColor = Color3.fromRGB(0, 170, 255),
        TextColor = Color3.fromRGB(255, 255, 255),
        CornerRadius = UDim.new(0, 8),
        Font = Enum.Font.GothamSemibold,
        FontSize = Enum.FontSize.Size14,
        -- Frames
        MainPanel = {
            Size = UDim2.new(0.3, 0, 0.6, 0),
            Position = UDim2.new(0.35, 0, 0.2, 0),
            Color = Color3.fromRGB(50, 50, 50),
            Transparency = 0.9,
            Title = "Auto Block Settings",
            TitleSize = UDim2.new(1, 0, 0, 40)
        },
        StatisticsPanel = {
            Size = UDim2.new(0.2, 0, 0.15, 0),
            Position = UDim2.new(0.75, 0, 0.75, 0),
            Color = Color3.fromRGB(30, 30, 30),
            Transparency = 0.8,
            Title = "Stats",
            TitleSize = UDim2.new(1, 0, 0, 30)
        },
        -- Buttons
        ConfigButton = {
            Size = UDim2.new(0, 120, 0, 40),
            Position = UDim2.new(0.01, 0, 0.01, 0),
            Color = Color3.fromRGB(0, 170, 255),
            Text = "Settings"
        },
        SoundToggle = {
            Size = UDim2.new(0.8, 0, 0, 30),
            Position = UDim2.new(0.1, 0, 0.6, 0),
            Color = Color3.fromRGB(70, 70, 70),
            Text = "Sound Effects: On"
        },
        LogLevelIndicator = {
            Size = UDim2.new(0, 150, 0, 30),
            Position = UDim2.new(0.5, -75, 0, 10),
            Color = Color3.fromRGB(255, 255, 255),
            Text = "Log Level: Info"
        },
        ExportLogButton = {
            Size = UDim2.new(0.5, 0, 0, 30),
            Position = UDim2.new(0.25, 0, 0.8, 0),
            Color = Color3.fromRGB(70, 70, 70),
            Text = "Export Logs"
        }
    },
    
    -- Debris Settings
    debrisLifetime = 300,            -- Time in seconds before debris is removed (e.g., hitboxes)
    
    -- Logging Settings
    logLevel = LOG_LEVELS.INFO,      -- Current logging level
    
    -- Statistics Tracking
    statistics = {
        blocks = 0,
        counters = 0,
        blocksPerAttack = {},          -- [attackType] = count
        countersPerAttack = {}         -- [attackType] = count
    },
    
    -- Sound Settings
    sounds = {
        blockStart = "rbxassetid://YourBlockStartSoundID",
        blockStop = "rbxassetid://YourBlockStopSoundID",
        counter = "rbxassetid://YourCounterSoundID"
    }
}

-- === Inverse Mapping for Attack Types ===
Settings.attackTypesInverse = {}
for attack, id in pairs(Settings.attackTypes) do
    Settings.attackTypesInverse[id:match("rbxassetid://(%d+)")] = attack
end

-- === State Tracking ===
local State = {
    isBlocking = false,
    lastBlockTime = {},         -- [player.UserId] = timestamp
    lastCounterTime = {},       -- [player.UserId] = timestamp
    currentBlockDirection = BLOCK_DIRECTIONS.Forward,
    isConfigOpen = false,
    isSoundEnabled = true,
    counterKey = Settings.defaultCounterKey
}

-- === UI Elements ===
local UI = {
    ScreenGui = nil,
    MainPanel = nil,
    ConfigButton = nil,
    ConfigPanel = nil,
    LogLevelIndicator = nil,
    StatisticsPanel = nil,
    SoundToggle = nil,
    LogDisplay = nil,
    ExportLogButton = nil,
    BlocksLabel = nil,
    CountersLabel = nil,
    DirectionIndicator = nil
}

-- === Helper Functions ===

-- Utility: Log with timestamp and level
local function log(message, level)
    level = level or LOG_LEVELS.INFO
    if level < Settings.logLevel then return end
    local prefix
    if level == LOG_LEVELS.INFO then
        prefix = "[INFO]"
    elseif level == LOG_LEVELS.WARNING then
        prefix = "[WARNING]"
    elseif level == LOG_LEVELS.ERROR then
        prefix = "[ERROR]"
    else
        prefix = "[LOG]"
    end
    local timestamp = os.date("%H:%M:%S")
    local logMessage = string.format("[%s] [%s] %s", timestamp, prefix, message)
    print(logMessage)
    
    -- Append to in-game log display
    if UI.LogDisplay then
        UI.LogDisplay.Text = UI.LogDisplay.Text .. "\n" .. logMessage
    end
end

-- UI: Create a new UI element with rounded corners
local function createRoundedFrame(parent, size, position, color, transparency, name)
    local frame = Instance.new("Frame")
    frame.Name = name or "RoundedFrame"
    frame.Size = size
    frame.Position = position
    frame.BackgroundColor3 = color
    frame.BackgroundTransparency = transparency
    frame.BorderSizePixel = 0
    frame.Parent = parent

    local corner = Instance.new("UICorner")
    corner.CornerRadius = Settings.ui.CornerRadius
    corner.Parent = frame

    return frame
end

-- UI: Create a new TextLabel with consistent styling
local function createStyledTextLabel(parent, size, position, text, textSize, textColor, font, name)
    local label = Instance.new("TextLabel")
    label.Name = name or "StyledLabel"
    label.Size = size
    label.Position = position
    label.BackgroundTransparency = 1
    label.Text = text
    label.TextColor3 = textColor or Settings.ui.TextColor
    label.TextScaled = false
    label.Font = font or Settings.ui.Font
    label.TextSize = textSize or 14
    label.TextWrapped = true
    label.Parent = parent
    return label
end

-- UI: Create a new TextButton with rounded corners and hover effects
local function createStyledButton(parent, size, position, text, textSize, textColor, font, buttonColor, name)
    local button = Instance.new("TextButton")
    button.Name = name or "StyledButton"
    button.Size = size
    button.Position = position
    button.BackgroundColor3 = buttonColor or Settings.ui.PrimaryColor
    button.BackgroundTransparency = 0.2
    button.Text = text
    button.TextColor3 = textColor or Settings.ui.TextColor
    button.TextScaled = false
    button.Font = font or Settings.ui.Font
    button.TextSize = textSize or 14
    button.AutoButtonColor = false
    button.BorderSizePixel = 0
    button.Parent = parent

    -- Add rounded corners
    local corner = Instance.new("UICorner")
    corner.CornerRadius = Settings.ui.CornerRadius
    corner.Parent = button

    -- Hover Effect
    button.MouseEnter:Connect(function()
        TweenService:Create(button, TweenInfo.new(0.2), {BackgroundColor3 = buttonColor:lerp(Color3.new(1,1,1), 0.2)}):Play()
    end)

    button.MouseLeave:Connect(function()
        TweenService:Create(button, TweenInfo.new(0.2), {BackgroundColor3 = buttonColor}):Play()
    end)

    return button
end

-- UI: Create a new ImageLabel for Direction Indicator
local function createDirectionIndicator(parent, size, position, imageId, color, transparency, name)
    local indicator = Instance.new("ImageLabel")
    indicator.Name = name or "DirectionIndicator"
    indicator.Size = size
    indicator.Position = position
    indicator.BackgroundTransparency = 1
    indicator.Image = imageId
    indicator.ImageColor3 = color
    indicator.ImageTransparency = transparency
    indicator.AnchorPoint = Vector2.new(0.5, 0.5)
    indicator.Parent = parent
    indicator.Visible = false

    -- Add rounded corners if needed
    return indicator
end

-- UI: Setup the User Interface
local function setupUI()
    -- Create ScreenGui
    local screenGui = Instance.new("ScreenGui")
    screenGui.Name = Settings.ui.ScreenGuiName
    screenGui.Parent = LOCAL_PLAYER:WaitForChild("PlayerGui")
    screenGui.ResetOnSpawn = false
    screenGui.DisplayOrder = 1000  -- Ensure it's on top

    -- Main Configuration Panel
    local mainPanel = createRoundedFrame(
        screenGui,
        Settings.ui.MainPanel.Size,
        Settings.ui.MainPanel.Position,
        Settings.ui.MainPanel.Color,
        Settings.ui.MainPanel.Transparency,
        "MainPanel"
    )

    -- Main Panel Title
    local mainTitle = createStyledTextLabel(
        mainPanel,
        Settings.ui.MainPanel.TitleSize,
        UDim2.new(0, 0, 0, 0),
        Settings.ui.MainPanel.Title,
        24,
        Settings.ui.TextColor,
        Enum.Font.GothamSemibold,
        "MainTitle"
    )

    -- Auto Block Toggle Button
    local autoBlockToggle = createStyledButton(
        mainPanel,
        UDim2.new(0.8, 0, 0, 40),
        UDim2.new(0.1, 0, 0.2, 0),
        "Auto Block: On",
        14,
        Settings.ui.TextColor,
        Enum.Font.GothamSemibold,
        Color3.fromRGB(0, 170, 255),
        "AutoBlockToggle"
    )
    
    -- Counter Key Configuration Button
    local counterKeyButton = createStyledButton(
        mainPanel,
        UDim2.new(0.8, 0, 0, 40),
        UDim2.new(0.1, 0, 0.35, 0),
        "Counter Key: " .. State.counterKey.Name,
        14,
        Settings.ui.TextColor,
        Enum.Font.GothamSemibold,
        Color3.fromRGB(0, 170, 255),
        "CounterKeyButton"
    )
    
    -- Log Level Dropdown Button
    local logLevelDropdown = createStyledButton(
        mainPanel,
        UDim2.new(0.8, 0, 0, 40),
        UDim2.new(0.1, 0, 0.5, 0),
        "Log Level: Info",
        14,
        Settings.ui.TextColor,
        Enum.Font.GothamSemibold,
        Color3.fromRGB(0, 170, 255),
        "LogLevelDropdown"
    )

    -- Sound Effects Toggle Button
    local soundToggle = createStyledButton(
        mainPanel,
        Settings.ui.SoundToggle.Size,
        Settings.ui.SoundToggle.Position,
        Settings.ui.SoundToggle.Text,
        14,
        Settings.ui.TextColor,
        Enum.Font.GothamSemibold,
        Color3.fromRGB(0, 170, 255),
        "SoundToggle"
    )

    -- Log Display (Scrollable TextBox)
    local logDisplay = Instance.new("ScrollingFrame")
    logDisplay.Name = "LogDisplay"
    logDisplay.Size = UDim2.new(0.9, 0, 0.35, -50)
    logDisplay.Position = UDim2.new(0.05, 0, 0.6, 0)
    logDisplay.BackgroundTransparency = 1
    logDisplay.BorderSizePixel = 0
    logDisplay.ScrollBarThickness = 5
    logDisplay.Parent = mainPanel

    local logText = Instance.new("TextLabel")
    logText.Name = "LogText"
    logText.Size = UDim2.new(1, 0, 1, 0)
    logText.Position = UDim2.new(0, 0, 0, 0)
    logText.BackgroundTransparency = 1
    logText.Text = ""
    logText.TextColor3 = Settings.ui.TextColor
    logText.TextSize = 14
    logText.TextWrapped = true
    logText.Font = Settings.ui.Font
    logText.Parent = logDisplay

    -- Export Log Button
    local exportLogButton = createStyledButton(
        mainPanel,
        Settings.ui.ExportLogButton.Size,
        Settings.ui.ExportLogButton.Position,
        Settings.ui.ExportLogButton.Text,
        14,
        Settings.ui.TextColor,
        Enum.Font.GothamSemibold,
        Color3.fromRGB(0, 170, 255),
        "ExportLogButton"
    )

    -- Configuration Button (Top-Left)
    local configButton = createStyledButton(
        screenGui,
        Settings.ui.ConfigButton.Size,
        Settings.ui.ConfigButton.Position,
        Settings.ui.ConfigButton.Text,
        14,
        Settings.ui.TextColor,
        Enum.Font.GothamSemibold,
        Settings.ui.ConfigButton.Color,
        "ConfigButton"
    )

    -- Statistics Panel
    local statisticsPanel = createRoundedFrame(
        screenGui,
        Settings.ui.StatisticsPanel.Size,
        Settings.ui.StatisticsPanel.Position,
        Settings.ui.StatisticsPanel.Color,
        Settings.ui.StatisticsPanel.Transparency,
        "StatisticsPanel"
    )

    -- Statistics Panel Title
    local statsTitle = createStyledTextLabel(
        statisticsPanel,
        UDim2.new(1, 0, 0, 30),
        UDim2.new(0, 0, 0, 0),
        Settings.ui.StatisticsPanel.Title,
        18,
        Settings.ui.TextColor,
        Enum.Font.GothamSemibold,
        "StatsTitle"
    )

    -- Blocks Label
    local blocksLabel = createStyledTextLabel(
        statisticsPanel,
        UDim2.new(0.9, 0, 0, 20),
        UDim2.new(0.05, 0, 0.2, 0),
        "Blocks: 0",
        14,
        Settings.ui.TextColor,
        Enum.Font.Gotham,
        "BlocksLabel"
    )

    -- Counters Label
    local countersLabel = createStyledTextLabel(
        statisticsPanel,
        UDim2.new(0.9, 0, 0, 20),
        UDim2.new(0.05, 0, 0.4, 0),
        "Counters: 0",
        14,
        Settings.ui.TextColor,
        Enum.Font.Gotham,
        "CountersLabel"
    )

    -- Log Level Indicator
    local logLevelIndicator = createStyledTextLabel(
        screenGui,
        Settings.ui.LogLevelIndicator.Size,
        Settings.ui.LogLevelIndicator.Position,
        Settings.ui.LogLevelIndicator.Text,
        14,
        Color3.fromRGB(0, 0, 0),
        Enum.Font.GothamSemibold,
        "LogLevelIndicator"
    )

    -- Direction Indicator
    local directionIndicator = createDirectionIndicator(
        screenGui,
        UDim2.new(0, 60, 0, 60),
        UDim2.new(0.5, 0, 0.5, 0),
        "rbxassetid://6023426910", -- Example arrow image
        Color3.fromRGB(255, 255, 0),
        0.7,
        "DirectionIndicator"
    )

    -- Assign to UI table
    UI.ScreenGui = screenGui
    UI.MainPanel = mainPanel
    UI.ConfigButton = configButton
    UI.SendButton = nil -- Placeholder for future buttons
    UI.ConfigPanel = mainPanel -- Reusing mainPanel as the config panel
    UI.LogLevelIndicator = logLevelIndicator
    UI.StatisticsPanel = statisticsPanel
    UI.SoundToggle = soundToggle
    UI.LogDisplay = logText
    UI.ExportLogButton = exportLogButton
    UI.BlocksLabel = blocksLabel
    UI.CountersLabel = countersLabel
    UI.DirectionIndicator = directionIndicator

    -- Add Tooltips (Optional Enhancement)
    -- You can implement tooltips by creating additional UI elements that appear on hover

    -- Connect UI Button Events

    -- Auto Block Toggle
    autoBlockToggle.MouseButton1Click:Connect(function()
        Settings.autoBlockEnabled = not Settings.autoBlockEnabled
        autoBlockToggle.Text = "Auto Block: " .. (Settings.autoBlockEnabled and "On" or "Off")
        log("Auto Block " .. (Settings.autoBlockEnabled and "Enabled" or "Disabled"), LOG_LEVELS.INFO)
    end)

    -- Counter Key Button
    counterKeyButton.MouseButton1Click:Connect(function()
        log("Press a new key for Countering...", LOG_LEVELS.INFO)
        local connection
        connection = UserInputService.InputBegan:Connect(function(input, gameProcessed)
            if gameProcessed then return end
            if input.UserInputType == Enum.UserInputType.Keyboard then
                State.counterKey = input.KeyCode
                counterKeyButton.Text = "Counter Key: " .. State.counterKey.Name
                log("Counter Key changed to " .. State.counterKey.Name, LOG_LEVELS.INFO)
                connection:Disconnect()
            end
        end)
    end)

    -- Log Level Dropdown
    logLevelDropdown.MouseButton1Click:Connect(function()
        if Settings.logLevel == LOG_LEVELS.INFO then
            Settings.logLevel = LOG_LEVELS.WARNING
            logLevelDropdown.Text = "Log Level: Warning"
        elseif Settings.logLevel == LOG_LEVELS.WARNING then
            Settings.logLevel = LOG_LEVELS.ERROR
            logLevelDropdown.Text = "Log Level: Error"
        else
            Settings.logLevel = LOG_LEVELS.INFO
            logLevelDropdown.Text = "Log Level: Info"
        end
        updateLogLevelIndicator()
        log("Log level changed to " .. logLevelDropdown.Text:match("Log Level: (.+)"), LOG_LEVELS.INFO)
    end)

    -- Sound Effects Toggle
    soundToggle.MouseButton1Click:Connect(function()
        State.isSoundEnabled = not State.isSoundEnabled
        soundToggle.Text = "Sound Effects: " .. (State.isSoundEnabled and "On" or "Off")
        log("Sound Effects " .. (State.isSoundEnabled and "Enabled" or "Disabled"), LOG_LEVELS.INFO)
    end)

    -- Export Log Button
    exportLogButton.MouseButton1Click:Connect(function()
        local logs = UI.LogDisplay.Text
        if #logs == 0 then
            log("No logs to export.", LOG_LEVELS.WARNING)
            return
        end
        -- Encode logs to JSON
        local encodedLogs = HttpService:JSONEncode({logs = logs})
        -- Implement actual export logic here (e.g., send to server or save to file)
        -- For demonstration, we'll print the encoded logs.
        print("Exporting Logs:", encodedLogs)
        log("Logs have been exported.", LOG_LEVELS.INFO)
    end)
end

-- Blocking: Start Blocking
local function startBlocking()
    if not State.isBlocking then
        State.isBlocking = true
        BlockRemote:FireServer()
        UI.LogLevelIndicator.Text = "Blocking Active"
        UI.LogLevelIndicator.BackgroundColor3 = Settings.ui.AccentColor

        -- Play block start sound
        if State.isSoundEnabled and Settings.sounds.blockStart then
            local sound = Instance.new("Sound")
            sound.SoundId = Settings.sounds.blockStart
            sound.Volume = 0.5
            sound.Parent = SoundService
            sound:Play()
            Debris:AddItem(sound, sound.TimeLength)
        end
        log("Blocking started", LOG_LEVELS.INFO)
        -- Update Statistics
        Settings.statistics.blocks = Settings.statistics.blocks + 1
        UI.BlocksLabel.Text = "Blocks: " .. Settings.statistics.blocks
    end
end

-- Blocking: Stop Blocking
local function stopBlocking()
    if State.isBlocking then
        State.isBlocking = false
        UnblockRemote:FireServer()
        UI.LogLevelIndicator.Text = "Blocking Inactive"
        UI.LogLevelIndicator.BackgroundColor3 = Color3.fromRGB(255, 255, 255)

        -- Play block stop sound
        if State.isSoundEnabled and Settings.sounds.blockStop then
            local sound = Instance.new("Sound")
            sound.SoundId = Settings.sounds.blockStop
            sound.Volume = 0.5
            sound.Parent = SoundService
            sound:Play()
            Debris:AddItem(sound, sound.TimeLength)
        end
        log("Blocking stopped", LOG_LEVELS.INFO)
    end
end

-- Blocking: Toggle Blocking State with Debounce
local debounceToggle = false
local function toggleBlocking()
    if debounceToggle then return end
    debounceToggle = true
    if State.isBlocking then
        stopBlocking()
    else
        startBlocking()
    end
    task.delay(0.2, function()
        debounceToggle = false
    end)
end

-- Prediction: Predict Enemy Movement with Enhanced Algorithm
local function predictEnemyMovement(enemy)
    local enemyCharacter = enemy.Character
    if not enemyCharacter then return nil end
    
    local enemyHRP = enemyCharacter:FindFirstChild("HumanoidRootPart")
    if not enemyHRP then return nil end

    local velocity = enemyHRP.Velocity
    -- Future Enhancement: Incorporate acceleration if data is available
    return enemyHRP.Position + velocity * Settings.predictionFactor
end

-- Direction: Get Hit Direction Based on Attacker Position
local function getHitDirection(attackerPosition, playerPosition, camLookVector, camRightVector)
    local direction = (attackerPosition - playerPosition).Unit
    local dotProduct = direction:Dot(camLookVector)

    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
            return direction:Dot(camRightVector) > 0 and BLOCK_DIRECTIONS.Right or BLOCK_DIRECTIONS.Left
        end
    else
        local angle = math.deg(math.atan2(direction.X, direction.Z)) % 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

-- Direction: Update Block Direction with Smooth Transitions
local function updateBlockDirection(attackerPosition)
    local playerCharacter = LOCAL_PLAYER.Character
    if not playerCharacter then return BLOCK_DIRECTIONS.Forward end

    local playerHRP = playerCharacter:FindFirstChild("HumanoidRootPart")
    if not playerHRP then return BLOCK_DIRECTIONS.Forward end

    local playerPosition = playerHRP.Position
    local camLookVector = CAMERA.CFrame.LookVector
    local camRightVector = CAMERA.CFrame.RightVector

    local desiredDirection = getHitDirection(attackerPosition, playerPosition, camLookVector, camRightVector)

    if desiredDirection ~= State.currentBlockDirection then
        State.currentBlockDirection = desiredDirection
        UpdateBlockDirectionRemote:FireServer(desiredDirection)
        log(string.format("Block direction updated to %s", desiredDirection), LOG_LEVELS.INFO)

        -- Update Direction Indicator
        UI.DirectionIndicator.Visible = true
        local rotation
        if desiredDirection == BLOCK_DIRECTIONS.Forward then
            rotation = 0
        elseif desiredDirection == BLOCK_DIRECTIONS.Right then
            rotation = 90
        elseif desiredDirection == BLOCK_DIRECTIONS.Backward then
            rotation = 180
        elseif desiredDirection == BLOCK_DIRECTIONS.Left then
            rotation = -90
        end
        UI.DirectionIndicator.Rotation = rotation

        -- Hide after a short duration
        task.delay(1, function()
            UI.DirectionIndicator.Visible = false
        end)
    end

    return desiredDirection
end

-- Counter Attacking: Perform Auto Counter
local function performAutoCounter(attacker, attackType)
    local attackerId = attacker.UserId
    local currentTime = tick()

    if State.lastCounterTime[attackerId] and (currentTime - State.lastCounterTime[attackerId]) < Settings.counterCooldown then
        return
    end

    VirtualInputManager:SendKeyEvent(true, Settings.counterKey, false, game)
    task.delay(0.05, function()
        VirtualInputManager:SendKeyEvent(false, Settings.counterKey, false, game)
    end)

    State.lastCounterTime[attackerId] = currentTime
    log("Auto counter performed against " .. attacker.Name, LOG_LEVELS.INFO)
    -- Play counter sound
    if State.isSoundEnabled and Settings.sounds.counter then
        local sound = Instance.new("Sound")
        sound.SoundId = Settings.sounds.counter
        sound.Volume = 0.5
        sound.Parent = SoundService
        sound:Play()
        Debris:AddItem(sound, sound.TimeLength)
    end
    -- Update Statistics
    Settings.statistics.counters = Settings.statistics.counters + 1
    UI.CountersLabel.Text = "Counters: " .. Settings.statistics.counters
    -- Update counters per attack type
    Settings.statistics.countersPerAttack[attackType] = (Settings.statistics.countersPerAttack[attackType] or 0) + 1
end

-- Blocking: Handle Incoming Hit with Enhanced Proximity and Slap-Specific Handling
local function handleIncomingHit(attacker, attackerPosition, attackType)
    local attackerId = attacker.UserId
    local currentTime = tick()

    -- Determine appropriate cooldown and distance based on attack type
    local cooldown = Settings.attackBlockCooldowns[attackType] or Settings.blockCooldown
    local maxDistance = Settings.blockDistances[attackType] or Settings.blockDistances.Default

    -- Check for cooldown
    if State.lastBlockTime[attackerId] and (currentTime - State.lastBlockTime[attackerId]) < cooldown then
        log("Block on cooldown for " .. attacker.Name, LOG_LEVELS.WARNING)
        return
    end

    -- Check distance
    local playerCharacter = LOCAL_PLAYER.Character
    if not playerCharacter then return end

    local playerHRP = playerCharacter:FindFirstChild("HumanoidRootPart")
    if not playerHRP then return end

    local distance = (playerHRP.Position - attackerPosition).Magnitude
    if distance > maxDistance then
        log("Attacker " .. attacker.Name .. " is too far: " .. tostring(distance), LOG_LEVELS.INFO)
        return
    end

    -- Update last block time for throttling
    State.lastBlockTime[attackerId] = currentTime

    -- Determine if the attack is a slap for specific handling
    local isSlap = (attackType == "Slap")
    
    -- Adjust reaction delay based on attack type
    local reactionDelay = isSlap and Settings.slapLagCompensation or math.min(math.random() * Settings.reactionTimeThreshold, Settings.reactionTimeThreshold)

    task.delay(reactionDelay, function()
        updateBlockDirection(attackerPosition)
        startBlocking()

        -- Schedule unblocking with different delays based on attack type
        local unblockDelay = isSlap and Settings.slapLagCompensation or 0.5
        task.delay(unblockDelay, stopBlocking)
    end)

    -- Handle Auto Countering if enabled and within counter distance
    if Settings.autoCounterEnabled and distance <= Settings.autoCounterDistance then
        performAutoCounter(attacker, attackType)
    end

    -- Update Statistics
    Settings.statistics.blocks = Settings.statistics.blocks + 1
    UI.BlocksLabel.Text = "Blocks: " .. Settings.statistics.blocks
    Settings.statistics.blocksPerAttack[attackType] = (Settings.statistics.blocksPerAttack[attackType] or 0) + 1

    -- Additional Slap-Specific Handling
    if isSlap then
        log("Slap attack handled from " .. attacker.Name, LOG_LEVELS.INFO)
        -- Future Enhancement: Add visual effects or specific reactions for slaps
    end
end

-- Attack Detection: Handle Animation Played
local function onAnimationPlayed(animTrack, opponentPlayer)
    local anim = animTrack.Animation
    if not anim then return end

    local animId = anim.AnimationId
    if not animId then return end

    -- Extract numeric ID from AnimationId
    local numericAnimId = animId:match("rbxassetid://(%d+)")
    if not numericAnimId then return end

    local attackType = Settings.attackTypesInverse[numericAnimId]
    if not attackType then return end

    log(string.format("Detected attack '%s' from %s", attackType, opponentPlayer.Name), LOG_LEVELS.INFO)

    local attackerHRP = opponentPlayer.Character and opponentPlayer.Character:FindFirstChild("HumanoidRootPart")
    if attackerHRP then
        handleIncomingHit(opponentPlayer, attackerHRP.Position, attackType)
    end
end

-- Animation Monitoring: Connect Animation Events
local function monitorAnimations(character, opponentPlayer)
    local humanoid = character:FindFirstChildOfClass("Humanoid")
    if not humanoid then return end

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

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

-- Hitbox Detection: Handle Hitbox Touched
local function onHitboxTouched(part, attackerPlayer)
    if not part or attackerPlayer == LOCAL_PLAYER then return end

    local attackerCharacter = part.Parent
    if not attackerCharacter then return end

    local attackerHRP = attackerCharacter:FindFirstChild("HumanoidRootPart")
    if attackerHRP then
        log("Hitbox detected attack from " .. attackerPlayer.Name, LOG_LEVELS.INFO)
        handleIncomingHit(attackerPlayer, attackerHRP.Position, "Default") -- Assuming 'Default' for non-slap attacks
    end
end

-- Hitbox Monitoring: Connect Hitbox Events
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 = hitbox.Touched:Connect(function(hitPart)
                onHitboxTouched(hitPart, attackerPlayer)
            end)

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

            -- Remove hitbox after specified time to prevent memory leaks
            Debris:AddItem(hitbox, Settings.debrisLifetime)
        end
    end
end

-- Statistics Update: Refresh Statistics Panel
local function updateStatisticsPanel()
    if not UI.StatisticsPanel then return end
    -- Update blocks and counters
    UI.BlocksLabel.Text = "Blocks: " .. Settings.statistics.blocks
    UI.CountersLabel.Text = "Counters: " .. Settings.statistics.counters
    -- Future enhancements: Display per attack type stats
end

-- Advanced Reaction System: Continuous Monitoring with Throttling
local function advancedReactionAutoBlock()
    if not Settings.autoBlockEnabled then return end

    local lastHeartbeat = 0
    local heartbeatThrottle = 0.05  -- Throttle to run logic every 0.05 seconds (20 times per second)

    RunService.Heartbeat:Connect(function(deltaTime)
        lastHeartbeat = lastHeartbeat + deltaTime

        if lastHeartbeat < heartbeatThrottle then
            return
        end

        lastHeartbeat = 0

        local playerCharacter = LOCAL_PLAYER.Character
        if not playerCharacter then return end

        local playerHRP = playerCharacter:FindFirstChild("HumanoidRootPart")
        if not playerHRP then return end

        local playerPosition = playerHRP.Position
        local camLookVector = CAMERA.CFrame.LookVector
        local camRightVector = CAMERA.CFrame.RightVector

        for _, plr in ipairs(Players:GetPlayers()) do
            if plr == LOCAL_PLAYER or not plr.Character then continue end

            local enemyHRP = plr.Character:FindFirstChild("HumanoidRootPart")
            if not enemyHRP then continue end

            local distance = (playerPosition - enemyHRP.Position).Magnitude
            if distance > (Settings.blockDistances.Default) then continue end

            -- Prediction and Direction Update
            local predictedPosition = predictEnemyMovement(plr) or enemyHRP.Position
            updateBlockDirection(predictedPosition)

            -- Early continue if no Humanoid found
            local enemyHumanoid = plr.Character:FindFirstChildOfClass("Humanoid")
            if not enemyHumanoid then continue end

            -- Check for active attack animations
            for _, animTrack in ipairs(enemyHumanoid:GetPlayingAnimationTracks()) do
                local anim = animTrack.Animation
                if not anim then continue end

                local animId = anim.AnimationId
                if not animId then continue end

                local numericAnimId = animId:match("rbxassetid://(%d+)")
                if not numericAnimId then continue end

                local attackType = Settings.attackTypesInverse[numericAnimId]
                if not attackType then continue end

                -- Determine if the attack should be considered based on distance
                local requiredDistance = Settings.blockDistances[attackType] or Settings.blockDistances.Default
                if distance > requiredDistance then continue end

                handleIncomingHit(plr, enemyHRP.Position, attackType)
            end
        end
    end)
end

-- Player Monitoring: Handle New Players
local function onPlayerAdded(plr)
    if plr == LOCAL_PLAYER then return end

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

    plr.CharacterAdded:Connect(onCharacterAdded)

    -- Handle existing character
    if plr.Character then
        onCharacterAdded(plr.Character)
    end
end

-- Initialize Player Monitoring
local function initializePlayerMonitoring()
    for _, plr in ipairs(Players:GetPlayers()) do
        onPlayerAdded(plr)
    end
    Players.PlayerAdded:Connect(onPlayerAdded)
end

-- UI Feedback & Directional Block Update
local function updateUIAndDirection()
    -- Update UI based on blocking state
    local isBlocking = State.isBlocking
    UI.LogLevelIndicator.Text = isBlocking and "Blocking Active" or "Blocking Inactive"
    UI.LogLevelIndicator.BackgroundColor3 = isBlocking and Settings.ui.AccentColor or Color3.fromRGB(255, 255, 255)
end

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

    -- Close configuration panel with Escape key
    UserInputService.InputBegan:Connect(function(input, gameProcessed)
        if gameProcessed then return end
        if input.KeyCode == Enum.KeyCode.Escape and State.isConfigOpen then
            State.isConfigOpen = false
            UI.MainPanel.Visible = false
            UI.ConfigButton.Text = "Settings"
            log("Configuration panel closed.", LOG_LEVELS.INFO)
        end
    end)

    -- Configuration Button Event
    UI.ConfigButton.MouseButton1Click:Connect(function()
        State.isConfigOpen = not State.isConfigOpen
        UI.MainPanel.Visible = State.isConfigOpen
        UI.ConfigButton.Text = State.isConfigOpen and "Close" or "Settings"
        log("Configuration panel " .. (State.isConfigOpen and "opened" or "closed") .. ".", LOG_LEVELS.INFO)
    end)
end

-- Logging: Update Log Level Indicator
local function updateLogLevelIndicator()
    local levelText
    if Settings.logLevel == LOG_LEVELS.INFO then
        levelText = "Info"
    elseif Settings.logLevel == LOG_LEVELS.WARNING then
        levelText = "Warning"
    elseif Settings.logLevel == LOG_LEVELS.ERROR then
        levelText = "Error"
    else
        levelText = "Unknown"
    end
    UI.LogLevelIndicator.Text = "Log Level: " .. levelText
end

-- UI: Setup Logging Controls in Configuration Panel
local function setupLoggingControls()
    -- Dropdown for Log Levels already implemented in setupUI()
end

-- UI: Setup Configuration Controls
local function setupConfigurationControls()
    -- Setup Logging Controls
    setupLoggingControls()
end

-- UI: Setup All Configuration Controls
local function setupAllConfigControls()
    setupConfigurationControls()
    -- Additional configuration settings can be added here
end

-- Export Logs Functionality (Placeholder)
local function exportLogs()
    local logs = UI.LogDisplay.Text
    if #logs == 0 then
        log("No logs to export.", LOG_LEVELS.WARNING)
        return
    end
    -- Implement actual export logic here (e.g., send to server or save to file)
    -- For demonstration, we'll print them
    print("Exporting Logs:", logs)
    log("Logs have been exported.", LOG_LEVELS.INFO)
end

-- Character Cleanup: Handle Character Death or Removal
local function onCharacterRemoved()
    stopBlocking()
end

local function connectCharacterEvents(character)
    local humanoid = character:FindFirstChildOfClass("Humanoid")
    if humanoid then
        humanoid.Died:Connect(onCharacterRemoved)
    end

    character.AncestryChanged:Connect(function(_, parent)
        if not parent then
            stopBlocking()
        end
    end)
end

local function setupLocalPlayerCharacterMonitoring()
    local function onLocalCharacterAdded(character)
        connectCharacterEvents(character)
    end

    if LOCAL_PLAYER.Character then
        connectCharacterEvents(LOCAL_PLAYER.Character)
    end

    LOCAL_PLAYER.CharacterAdded:Connect(onLocalCharacterAdded)
end

-- === Initialization ===

-- Setup UI
setupUI()

-- Setup All Configuration Controls
setupAllConfigControls()

-- Setup Input Handling
setupInputHandling()

-- Initialize Player Monitoring
initializePlayerMonitoring()

-- Setup Local Player Character Monitoring
setupLocalPlayerCharacterMonitoring()

-- Setup Combined UI Feedback and Directional Block Update
RunService.RenderStepped:Connect(updateUIAndDirection)

-- Initialize Advanced Reaction System
advancedReactionAutoBlock()

-- Notify that the script is running
log("Auto Block V.3 is now running with enhanced Slap functions and refined GUI.", LOG_LEVELS.INFO)

-- === End of Script ===