Further enhance this script, and add an advanced dynamic further consistent slap blocking system:

```
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local VirtualInputManager = game:GetService("VirtualInputManager")
local TweenService = game:GetService("TweenService")
local StarterGui = game:GetService("StarterGui")

local LightsaberRemotes = ReplicatedStorage:WaitForChild("LightsaberRemotes")
local BlockRemote = LightsaberRemotes:WaitForChild("Block")
local UnblockRemote = LightsaberRemotes:WaitForChild("Unblock")

-- Settings
local Settings = {
    BlockDistance = 20,
    AutoCounterEnabled = true,
    AutoSlapDistance = 10,
    ReactionTimeThreshold = 0.15,
    BlockDuration = 0.3,
    Cooldown = 1.0,
    SlapAnimations = {
        ["Slap"] = 12625891544,
        ["SlappedLegs"] = 12671715182,
        ["SlappedArms"] = 12625896358,
        ["SlappedHead"] = 12625897000,
        ["DoubleSlap"] = 12625897500
    }
}

local lastBlockTime = 0
local isBlocking = false

-- Create GUI for visual feedback
local screenGui = Instance.new("ScreenGui")
screenGui.Name = "AntiSlapIndicator"
screenGui.Parent = Players.LocalPlayer:WaitForChild("PlayerGui")

local blockIndicator = Instance.new("Frame")
blockIndicator.Size = UDim2.new(0, 100, 0, 50)
blockIndicator.Position = UDim2.new(0.5, -50, 0, 10)
blockIndicator.BackgroundColor3 = Color3.new(1, 0, 0)
blockIndicator.Visible = false
blockIndicator.Parent = screenGui

local blockText = Instance.new("TextLabel")
blockText.Size = UDim2.new(1, 0, 1, 0)
blockText.BackgroundTransparency = 1
blockText.Text = "Blocking"
blockText.TextColor3 = Color3.new(1, 1, 1)
blockText.TextScaled = true
blockText.Parent = blockIndicator

-- Tween for smooth appearance/disappearance
local tweenInfo = TweenInfo.new(0.2, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
local showTween = TweenService:Create(blockIndicator, tweenInfo, {BackgroundColor3 = Color3.new(1, 0, 0), Visible = true})
local hideTween = TweenService:Create(blockIndicator, tweenInfo, {BackgroundColor3 = Color3.new(1, 0, 0), Visible = false})

local function showBlockIndicator()
    if not blockIndicator.Visible then
        blockIndicator.Visible = true
        showTween:Play()
    end
end

local function hideBlockIndicator()
    if blockIndicator.Visible then
        hideTween:Play()
        task.delay(tweenInfo.Time, function()
            blockIndicator.Visible = false
        end)
    end
end

local function getClosestPlayers()
    local players = {}
    local localPlayer = Players.LocalPlayer
    local localCharacter = localPlayer.Character

    if localCharacter and localCharacter:FindFirstChild("HumanoidRootPart") then
        local localPosition = localCharacter.HumanoidRootPart.Position

        for _, player in ipairs(Players:GetPlayers()) do
            if player ~= localPlayer and player.Character and player.Character:FindFirstChild("HumanoidRootPart") then
                local playerPosition = player.Character.HumanoidRootPart.Position
                local distance = (playerPosition - localPosition).Magnitude

                if distance <= Settings.BlockDistance then
                    table.insert(players, {Player = player, Distance = distance})
                end
            end
        end
    end

    table.sort(players, function(a, b) return a.Distance < b.Distance end)
    return players
end

local function handleSlapAnimation(opponent, animTrack)
    local localPlayer = Players.LocalPlayer
    local character = localPlayer.Character
    if not character then return end

    local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
    if not humanoidRootPart then return end

    local opponentRootPart = opponent.Character and opponent.Character:FindFirstChild("HumanoidRootPart")
    if not opponentRootPart then return end

    local distance = (humanoidRootPart.Position - opponentRootPart.Position).Magnitude

    if distance <= Settings.BlockDistance and not isBlocking then
        local currentTime = tick()
        local timeSinceLastBlock = currentTime - lastBlockTime

        if timeSinceLastBlock >= Settings.Cooldown then
            isBlocking = true
            lastBlockTime = currentTime
            BlockRemote:FireServer()

            showBlockIndicator()
            print("Blocking initiated against:", opponent.Name)

            task.delay(Settings.BlockDuration, function()
                if isBlocking then
                    UnblockRemote:FireServer()
                    isBlocking = false
                    hideBlockIndicator()
                    print("Blocking ended.")
                end
            end)

            if Settings.AutoCounterEnabled and distance <= Settings.AutoSlapDistance then
                task.delay(Settings.BlockDuration * 0.5, function()
                    VirtualInputManager:SendKeyEvent(true, Enum.KeyCode.E, false, game)
                    task.wait(0.1)
                    VirtualInputManager:SendKeyEvent(false, Enum.KeyCode.E, false, game)
                    print("Automatic counter-slap performed.")
                end)
            end
        else
            print("Block on cooldown. Time left:", Settings.Cooldown - timeSinceLastBlock)
        end
    end
end

local function onOpponentAnimationPlayed(opponent, animTrack)
    for animName, animId in pairs(Settings.SlapAnimations) do
        if animTrack.Animation and animTrack.Animation.AnimationId == "rbxassetid://" .. animId then
            print("Detected slap animation:", animName, "from:", opponent.Name)
            handleSlapAnimation(opponent, animTrack)
            break
        end
    end
end

local function onCharacterAdded(character)
    local humanoid = character:WaitForChild("Humanoid")
    local opponent = Players:GetPlayerFromCharacter(character)

    if not opponent or opponent == Players.LocalPlayer then return end

    humanoid.AnimationPlayed:Connect(function(animTrack)
        onOpponentAnimationPlayed(opponent, animTrack)
    end)
end

local function setupPlayer(player)
    if player.Character then
        onCharacterAdded(player.Character)
    end
    player.CharacterAdded:Connect(onCharacterAdded)
end

for _, player in ipairs(Players:GetPlayers()) do
    setupPlayer(player)
end

Players.PlayerAdded:Connect(setupPlayer)

RunService.Heartbeat:Connect(function()
    local closestPlayers = getClosestPlayers()
    -- Additional logic for prioritizing or handling multiple close players can be added here
end)

-- You can add more features or GUI elements as needed
```

Reference Script (REFERENCE ONLY (THE ONLY VALID ANIM ID'S AND REMOTES ARE HERE):

```
local animIDs = {
    ["RightSwing"] = 12625839385,
    ["OverheadSwing"] = 12625841878,
    ["LeftSwing"] = 12625843823,
    ["BackLeftSwing"] = 12625846167,
    ["FrontRightSwing"] = 12625848489,
    ["BackRightSwing"] = 12625851115,
    ["FrontLeftSwing"] = 12625853257,
    ["RightBlock"] = 12625856098,
    ["LeftBlock"] = 12625858434,
    ["FrontLeftBlock"] = 12625860439,
    ["FrontRightBlock"] = 12625862519,
    ["FrontBlock"] = 12625864413,
    ["BackLeftBlock"] = 12625866538,
    ["BackRightBlock"] = 12625868684,
    ["Grab"] = 12625870437,
    ["Slap"] = 12625891544,
    ["SlappedLegs"] = 12671715182,
    ["SlappedArms"] = 12625896358,
    ["KickUp"] = 12625897944,
    ["KickBack"] = 12625899752,
    ["LeftRoll"] = 12625901874,
    ["RightRoll"] = 12625904322,
    ["Aerial"] = 12625908201,
    ["Idle"] = 13956175510,
    ["Throw"] = 12626569448,
    ["ForcePush"] = 12645928786,
    ["CrouchWalkRight"] = 12699256551,
    ["CrouchWalkLeft"] = 12699989478,
    ["CrouchWalkBack"] = 12699390244,
    ["CrouchWalkForward"] = 12699464592,
    ["FrontRoll"] = 12708915962,
    ["RightCrouchRoll"] = 12713661639,
    ["LeftCrouchRoll"] = 12713663289,
    ["Kata"] = 12735531097,
    ["Choking"] = 12814275189,
    ["Choke"] = 12815930160,
}

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UserInputService = game:GetService("UserInputService")
local VirtualInputManager = game:GetService("VirtualInputManager")

local LightsaberRemotes = ReplicatedStorage:WaitForChild("LightsaberRemotes")
local BlockRemote = LightsaberRemotes:WaitForChild("Block")
local UnblockRemote = LightsaberRemotes:WaitForChild("Unblock")

local ESP_COLOR = Color3.new(1, 0, 0)
local OUTLINE_THICKNESS = 3

local Rayfield = loadstring(game:HttpGet('https://raw.githubusercontent.com/shlexware/Rayfield/main/source'))()

local Window = Rayfield:CreateWindow({
    Name = "Saber Showdown GUI",
    LoadingTitle = "Saber Showdown Auto Block",
    LoadingSubtitle = "Created By xenon9012",
})

local ESPTab = Window:CreateTab("ESP Settings", 4483362458)
local AutoBlockTab = Window:CreateTab("Auto Block", 4483362458)
local AutoCounterTab = Window:CreateTab("Auto Counter", 4483362458)
local creditsTab = Window:CreateTab("Credits", 4483362458)

local Section = ESPTab:CreateSection("ESP Config")

local espEnabled = true
local autoBlockEnabled = true
local autoCounterEnabled = true
local autoHalfSwingEnabled = true
local autoFastSwingEnabled = true
local espOutlineColor = Color3.new(1, 1, 1)
local espNameColor = Color3.new(1, 0, 0)
local espDistance = 100
local blockDistance = 20
local autoSlapDistance = 10
local rainbowESPEnabled = false
local highlightThickness = 0.5
local slapTimerEnabled = true
local slapTimerColor = Color3.new(0, 1, 0)
local autoHalfSwingDelay = 0.3
local autoFastSwingDelay = 0.15
local autoHalfSwingEnabled = false
local autoFastSwingEnabled = false
local autoHalfSwingDelay = 0.3
local autoFastSwingDelay = 0.15
local swingCooldown = 0.1 -- Cooldown between swings
local lastSwingTime = 0

local autoBlockMode = "Smart" -- "Always", "Smart", or "Reactive"
local autoBlockReactionTime = 0.1 -- in seconds
local autoBlockDuration = 0.5 -- in seconds
local autoBlockCooldown = 0.2 -- in seconds
local lastBlockTime = 0

local function updateESPColors()
    for _, player in ipairs(Players:GetPlayers()) do
        if player ~= Players.LocalPlayer and player.Character then
            local espObjects = player.Character:FindFirstChild("ESPObjects")
            if espObjects then
                local highlight = espObjects:FindFirstChild("Highlight")
                local nameESP = espObjects:FindFirstChild("NameESP")
                if highlight then
                    highlight.OutlineColor = espOutlineColor
                    highlight.OutlineTransparency = 1 - highlightThickness
                end
                if nameESP then
                    nameESP.Color = espNameColor
                end
            end
        end
    end
end

local Toggle = ESPTab:CreateToggle({
    Name = "Enable ESP",
    CurrentValue = espEnabled,
    Flag = "ESPToggle",
    Callback = function(Value)
        espEnabled = Value
    end,
})

local RainbowToggle = ESPTab:CreateToggle({
    Name = "Rainbow Outline ESP",
    CurrentValue = rainbowESPEnabled,
    Flag = "RainbowESPToggle",
    Callback = function(Value)
        rainbowESPEnabled = Value
    end,
})

local SlapTimerToggle = ESPTab:CreateToggle({
    Name = "Enable Slap Timer",
    CurrentValue = slapTimerEnabled,
    Flag = "SlapTimerToggle",
    Callback = function(Value)
        slapTimerEnabled = Value
    end,
})

local ColorPicker1 = ESPTab:CreateColorPicker({
    Name = "ESP Outline Color",
    Color = espOutlineColor,
    Flag = "ESPOutlineColor",
    Callback = function(Value)
        espOutlineColor = Value
        updateESPColors()
    end,
})

local ColorPicker2 = ESPTab:CreateColorPicker({
    Name = "ESP Name Color",
    Color = espNameColor,
    Flag = "ESPNameColor",
    Callback = function(Value)
        espNameColor = Value
        updateESPColors()
    end,
})

local Slider1 = ESPTab:CreateSlider({
    Name = "ESP Distance",
    Range = {0, 500},
    Increment = 10,
    Suffix = "studs",
    CurrentValue = espDistance,
    Flag = "ESPDistance",
    Callback = function(Value)
        espDistance = Value
    end,
})

local Slider3 = ESPTab:CreateSlider({
    Name = "Highlight Thickness",
    Range = {0, 1},
    Increment = 0.1,
    Suffix = "",
    CurrentValue = highlightThickness,
    Flag = "HighlightThickness",
    Callback = function(Value)
        highlightThickness = Value
        updateESPColors()
    end,
})

local SlapTimerColorPicker = ESPTab:CreateColorPicker({
    Name = "Slap Timer Color",
    Color = slapTimerColor,
    Flag = "SlapTimerColor",
    Callback = function(Value)
        slapTimerColor = Value
    end,
})

local Toggle2 = AutoBlockTab:CreateToggle({
    Name = "Enable Auto Block",
    CurrentValue = autoBlockEnabled,
    Flag = "AutoBlockToggle",
    Callback = function(Value)
        autoBlockEnabled = Value
    end,
})

local Slider2 = AutoBlockTab:CreateSlider({
    Name = "Block Distance",
    Range = {0, 100},
    Increment = 1,
    Suffix = "studs",
    CurrentValue = blockDistance,
    Flag = "BlockDistance",
    Callback = function(Value)
        blockDistance = Value
    end,
})

-- Add these new toggles and sliders to the AutoBlockTab
local AutoBlockModeDropdown = AutoBlockTab:CreateDropdown({
    Name = "Auto Block Mode",
    Options = {"Always", "Smart", "Reactive"},
    CurrentOption = autoBlockMode,
    Flag = "AutoBlockMode",
    Callback = function(Option)
        autoBlockMode = Option
    end,
})

local AutoBlockReactionTimeSlider = AutoBlockTab:CreateSlider({
    Name = "Block Reaction Time",
    Range = {0, 0.5},
    Increment = 0.01,
    Suffix = "seconds",
    CurrentValue = autoBlockReactionTime,
    Flag = "AutoBlockReactionTime",
    Callback = function(Value)
        autoBlockReactionTime = Value
    end,
})

local AutoBlockDurationSlider = AutoBlockTab:CreateSlider({
    Name = "Block Duration",
    Range = {0.1, 2},
    Increment = 0.1,
    Suffix = "seconds",
    CurrentValue = autoBlockDuration,
    Flag = "AutoBlockDuration",
    Callback = function(Value)
        autoBlockDuration = Value
    end,
})

local AutoBlockCooldownSlider = AutoBlockTab:CreateSlider({
    Name = "Block Cooldown",
    Range = {0, 1},
    Increment = 0.1,
    Suffix = "seconds",
    CurrentValue = autoBlockCooldown,
    Flag = "AutoBlockCooldown",
    Callback = function(Value)
        autoBlockCooldown = Value
    end,
})

local AutoCounterToggle = AutoCounterTab:CreateToggle({
    Name = "Enable Auto Slap",
    CurrentValue = autoCounterEnabled,
    Flag = "AutoCounterToggle",
    Callback = function(Value)
        autoCounterEnabled = Value
    end,
})

local AutoHalfSwingToggle = AutoCounterTab:CreateToggle({
    Name = "Auto Half Swing",
    CurrentValue = autoHalfSwingEnabled,
    Flag = "AutoHalfSwingToggle",
    Callback = function(Value)
        autoHalfSwingEnabled = Value
    end,
})

local AutoHalfSwingSlider = AutoCounterTab:CreateSlider({
    Name = "Auto Half Swing Delay",
    Range = {0.1, 1},
    Increment = 0.05,
    Suffix = "secs",
    CurrentValue = autoHalfSwingDelay,
    Flag = "AutoHalfSwingDelay",
    Callback = function(Value)
        autoHalfSwingDelay = Value
    end,
})

local AutoFastSwingToggle = AutoCounterTab:CreateToggle({
    Name = "Auto Fast Swing",
    CurrentValue = autoFastSwingEnabled,
    Flag = "AutoFastSwingToggle",
    Callback = function(Value)
        autoFastSwingEnabled = Value
    end,
})

local AutoFastSwingSlider = AutoCounterTab:CreateSlider({
    Name = "Auto Fast Swing Delay",
    Range = {0.05, 0.5},
    Increment = 0.05,
    Suffix = "secs",
    CurrentValue = autoFastSwingDelay,
    Flag = "AutoFastSwingDelay",
    Callback = function(Value)
        autoFastSwingDelay = Value
    end,
})

local SwingCooldownSlider = AutoCounterTab:CreateSlider({
    Name = "Swing Cooldown",
    Range = {0, 0.5},
    Increment = 0.01,
    Suffix = "secs",
    CurrentValue = swingCooldown,
    Flag = "SwingCooldown",
    Callback = function(Value)
        swingCooldown = Value
    end,
})

local AutoSlapDistanceSlider = AutoCounterTab:CreateSlider({
    Name = "Auto Slap Distance",
    Range = {0, 50},
    Increment = 1,
    Suffix = "studs",
    CurrentValue = autoSlapDistance,
    Flag = "AutoSlapDistance",
    Callback = function(Value)
        autoSlapDistance = Value
    end,
})

local function createPlayerESP(player)
    local espFolder = Instance.new("Folder")
    espFolder.Name = "ESPObjects"
    espFolder.Parent = player.Character

    local highlight = Instance.new("Highlight")
    highlight.FillColor = Color3.new(1, 0, 0)
    highlight.OutlineColor = espOutlineColor
    highlight.FillTransparency = 1
    highlight.OutlineTransparency = 1 - highlightThickness
    highlight.Adornee = player.Character
    highlight.Parent = espFolder

    local nameESP = Drawing.new("Text")
    nameESP.Visible = false
    nameESP.Center = true
    nameESP.Outline = true
    nameESP.Font = 2
    nameESP.Size = 13
    nameESP.Color = espNameColor

    local healthBar = Drawing.new("Line")
    healthBar.Visible = false
    healthBar.Thickness = 2
    healthBar.Color = Color3.new(0, 1, 0)

    local slapTimerESP = Drawing.new("Text")
    slapTimerESP.Visible = false
    slapTimerESP.Center = true
    slapTimerESP.Outline = true
    slapTimerESP.Font = 2
    slapTimerESP.Size = 13
    slapTimerESP.Color = slapTimerColor

    RunService.RenderStepped:Connect(function()
        if player.Character and player.Character:FindFirstChild("HumanoidRootPart") and player.Character:FindFirstChild("Humanoid") then
            local rootPart = player.Character.HumanoidRootPart
            local humanoid = player.Character.Humanoid
            local vector, onScreen = workspace.CurrentCamera:WorldToViewportPoint(rootPart.Position)
            local distance = (rootPart.Position - workspace.CurrentCamera.CFrame.Position).Magnitude
            
            if onScreen and distance <= espDistance and espEnabled then
                nameESP.Text = string.format("%s [%.1f]", player.Name, distance)
                nameESP.Position = Vector2.new(vector.X, vector.Y - 40)
                nameESP.Visible = true

                local healthPercentage = humanoid.Health / humanoid.MaxHealth
                healthBar.From = Vector2.new(vector.X + 50, vector.Y - 20)
                healthBar.To = Vector2.new(vector.X + 50, vector.Y - 20 + 40 * healthPercentage)
                healthBar.Color = Color3.new(1 - healthPercentage, healthPercentage, 0)
                healthBar.Visible = true

                highlight.Enabled = true

                if rainbowESPEnabled then
                    local hue = (tick() % 5) / 5
                    local rainbowColor = Color3.fromHSV(hue, 1, 1)
                    highlight.OutlineColor = rainbowColor
                    nameESP.Color = rainbowColor
                else
                    highlight.OutlineColor = espOutlineColor
                    nameESP.Color = espNameColor
                end
                highlight.OutlineTransparency = 1 - highlightThickness

                if slapTimerEnabled then
                    slapTimerESP.Position = Vector2.new(vector.X, vector.Y + 20)
                    slapTimerESP.Visible = true
                else
                    slapTimerESP.Visible = false
                end
            else
                nameESP.Visible = false
                healthBar.Visible = false
                highlight.Enabled = false
                slapTimerESP.Visible = false
            end
        else
            nameESP.Visible = false
            healthBar.Visible = false
            highlight.Enabled = false
            slapTimerESP.Visible = false
        end
    end)

    return {nameESP, healthBar, highlight, slapTimerESP}
end

local function getClosestPlayer()
    local closestPlayer = nil
    local shortestDistance = math.huge
    local localPlayer = Players.LocalPlayer
    local localCharacter = localPlayer.Character

    if localCharacter then
        local localPosition = localCharacter.PrimaryPart.Position

        for _, player in ipairs(Players:GetPlayers()) do
            if player ~= localPlayer and player.Character and player.Character:FindFirstChild("HumanoidRootPart") then
                local playerPosition = player.Character.PrimaryPart.Position
                local distance = (playerPosition - localPosition).Magnitude

                if distance < shortestDistance then
                    closestPlayer = player
                    shortestDistance = distance
                end
            end
        end
    end

    return closestPlayer
end

local function performSwing()
    local currentTime = tick()
    if currentTime - lastSwingTime >= swingCooldown then
        mouse1click()
        lastSwingTime = currentTime
    end
end

local function onCharacterAdded(character)
    local humanoid = character:WaitForChild("Humanoid")
    local player = Players:GetPlayerFromCharacter(character)
    
    local espObjects = createPlayerESP(player)
    local slapTimerESP = espObjects[4]
    local canSlap = true
    local blockEndTime = 0
    
    humanoid.AnimationPlayed:Connect(function(animTrack)
        for animName, animId in pairs(animIDs) do
            if animTrack.Animation.AnimationId == "rbxassetid://" .. animId then
                print(player.Name .. " used animation: " .. animName)
                
                if animName == "Slap" and slapTimerEnabled then
                    canSlap = false
                    local startTime = tick()
                    
                    task.spawn(function()
                        while tick() - startTime < 3 and slapTimerEnabled do
                            local timeLeft = math.ceil(3 - (tick() - startTime))
                            slapTimerESP.Text = string.format("%d cannot slap", timeLeft)
                            slapTimerESP.Color = slapTimerColor
                            slapTimerESP.Visible = true
                            task.wait(0.1)
                        end
                        
                        canSlap = true
                        slapTimerESP.Text = "Can slap"
                        slapTimerESP.Color = Color3.new(1, 0, 0)
                        slapTimerESP.Visible = true
                    end)
                end
                
                if animName == "Slap" then
                    local localPlayer = Players.LocalPlayer
                    local localCharacter = localPlayer.Character
                    if localCharacter then
                        local localPosition = localCharacter.PrimaryPart.Position
                        local playerPosition = player.Character.PrimaryPart.Position
                        local distance = (playerPosition - localPosition).Magnitude
                        
                        if distance < blockDistance then 
                            BlockRemote:FireServer()
                            
                            -- Block for the duration of the slap animation
                            task.wait(animTrack.Length)
                            
                            UnblockRemote:FireServer()
                            
                            -- Auto Counter Slap if enabled
                            if autoCounterEnabled and distance < autoSlapDistance then
                                VirtualInputManager:SendKeyEvent(true, Enum.KeyCode.E, false, game)
                                task.wait(0.1)
                                VirtualInputManager:SendKeyEvent(false, Enum.KeyCode.E, false, game)
                            end
                        end
                    end
                end
                
                -- Auto Half Swing or Fast Swing
                if animName:find("Swing") and player == Players.LocalPlayer then
                    if autoHalfSwingEnabled then
                        task.spawn(function()
                            task.wait(autoHalfSwingDelay)
                            performSwing()
                        end)
                    end
                    if autoFastSwingEnabled then
                        task.spawn(function()
                            for i = 1, 3 do -- Perform multiple fast swings
                                task.wait(autoFastSwingDelay)
                                performSwing()
                            end
                        end)
                    end
                end
                
                break
            end
        end
    end)
end

local function advancedAutoBlock(player, animTrack)
    local localPlayer = Players.LocalPlayer
    local localCharacter = localPlayer.Character
    if not localCharacter then return end

    local localPosition = localCharacter.PrimaryPart.Position
    local playerPosition = player.Character.PrimaryPart.Position
    local distance = (playerPosition - localPosition).Magnitude

    if distance > blockDistance then return end

    local currentTime = tick()
    if currentTime - lastBlockTime < autoBlockCooldown then return end

    local shouldBlock = false

    if autoBlockMode == "Always" then
        shouldBlock = true
    elseif autoBlockMode == "Smart" then
        local playerFacing = player.Character.PrimaryPart.CFrame.LookVector
        local toLocal = (localPosition - playerPosition).Unit
        local dotProduct = playerFacing:Dot(toLocal)
        shouldBlock = dotProduct > 0.5 -- Block if the player is facing towards us
    elseif autoBlockMode == "Reactive" then
        -- Only block for specific animations
        local reactiveAnims = {"Slap", "RightSwing", "LeftSwing", "OverheadSwing"}
        for _, animName in ipairs(reactiveAnims) do
            if animTrack.Animation.AnimationId == "rbxassetid://" .. animIDs[animName] then
                shouldBlock = true
                break
            end
        end
    end

    if shouldBlock then
        task.spawn(function()
            task.wait(autoBlockReactionTime)
            if autoBlockEnabled then
                BlockRemote:FireServer()
                lastBlockTime = currentTime
                task.wait(autoBlockDuration)
                UnblockRemote:FireServer()
            end
        end)
    end
end

local function counterSlap()
    VirtualInputManager:SendKeyEvent(true, Enum.KeyCode.E, false, game)
    task.wait(0.1)
    VirtualInputManager:SendKeyEvent(false, Enum.KeyCode.E, false, game)
end

local function monitorClosestPlayer()
    RunService.Heartbeat:Connect(function()
        local closestPlayer = getClosestPlayer()
        if closestPlayer and closestPlayer.Character then
            local humanoid = closestPlayer.Character:FindFirstChild("Humanoid")
            if humanoid then
                for _, track in pairs(humanoid:GetPlayingAnimationTracks()) do
                    for animName, animId in pairs(animIDs) do
                        if track.Animation.AnimationId == "rbxassetid://" .. animId and animName == "Slap" then
                            handleSlapAnimation(closestPlayer, track, nil)
                            break
                        end
                    end
                end
            end
        end
    end)
end

local function handleSlapAnimation(player, animTrack, slapTimerESP)
    if slapTimerEnabled then
        updateSlapTimer(slapTimerESP)
    end

    advancedAutoBlock(player, animTrack)

    local localPlayer = Players.LocalPlayer
    local localCharacter = localPlayer.Character
    if localCharacter then
        local localPosition = localCharacter.PrimaryPart.Position
        local playerPosition = player.Character.PrimaryPart.Position
        local distance = (playerPosition - localPosition).Magnitude
        
        if distance < blockDistance and autoBlockEnabled then 
            -- Block immediately when slap animation starts
            BlockRemote:FireServer()
            
            -- Maintain block for slightly longer than the slap animation
            task.spawn(function()
                task.wait(animTrack.Length + 0.2)
                UnblockRemote:FireServer()
            end)
            
            -- Auto Counter Slap if enabled
            if autoCounterEnabled and distance < autoSlapDistance then
                task.spawn(function()
                    task.wait(animTrack.Length / 2)  -- Wait for half of the slap animation
                    counterSlap()
                end)
            end
        end
    end
end

local function updateSlapTimer(slapTimerESP)
    local canSlap = false
    local startTime = tick()
    
    task.spawn(function()
        while tick() - startTime < 3 and slapTimerEnabled do
            local timeLeft = math.ceil(3 - (tick() - startTime))
            slapTimerESP.Text = string.format("%d cannot slap", timeLeft)
            slapTimerESP.Color = slapTimerColor
            slapTimerESP.Visible = true
            task.wait(0.1)
        end
        
        canSlap = true
        slapTimerESP.Text = "Can slap"
        slapTimerESP.Color = Color3.new(1, 0, 0)
        slapTimerESP.Visible = true
    end)
end

local function counterSlap()
    VirtualInputManager:SendKeyEvent(true, Enum.KeyCode.E, false, game)
    task.wait(0.1)
    VirtualInputManager:SendKeyEvent(false, Enum.KeyCode.E, false, game)
end

local function handleSwingAnimation(animTrack)
    if autoHalfSwingEnabled then
        task.spawn(function()
            task.wait(autoHalfSwingDelay)
            performSwing()
        end)
    end
    if autoFastSwingEnabled then
        task.spawn(function()
            for i = 1, 3 do
                task.wait(autoFastSwingDelay)
                performSwing()
            end
        end)
    end
end

RunService.RenderStepped:Connect(function()
    local closestPlayer = getClosestPlayer()
    if closestPlayer and closestPlayer.Character then
        local humanoid = closestPlayer.Character:FindFirstChild("Humanoid")
        if humanoid and tick() > blockEndTime then
            local localPlayer = Players.LocalPlayer
            local localCharacter = localPlayer.Character
            if localCharacter then
                local localPosition = localCharacter.PrimaryPart.Position
                local playerPosition = closestPlayer.Character.PrimaryPart.Position
                local distance = (playerPosition - localPosition).Magnitude
                
                if distance < autoSlapDistance then
                    VirtualInputManager:SendKeyEvent(true, Enum.KeyCode.E, false, game)
                    task.wait(0.1)
                    VirtualInputManager:SendKeyEvent(false, Enum.KeyCode.E, false, game)
                end
            end
        end
    end
end)

for _, player in ipairs(Players:GetPlayers()) do
    if player ~= Players.LocalPlayer then
        if player.Character then
            onCharacterAdded(player.Character)
        end
        player.CharacterAdded:Connect(onCharacterAdded)
    end
end

Players.PlayerAdded:Connect(function(player)
    if player ~= Players.LocalPlayer then
        player.CharacterAdded:Connect(onCharacterAdded)
    end
end)

local creditsSection = creditsTab:CreateSection("Credits")

local creditsText = {
    "Created by xenon90 on discord",
    "If any other comissions are needed then feel free to contact me",
    "Most of my scripts are free that i make due to it being for experience",
}

for _, text in ipairs(creditsText) do
    creditsTab:CreateLabel(text)
end

monitorClosestPlayer()