local ReplicatedStorage = game:GetService("ReplicatedStorage") local Players = game:GetService("Players") local Workspace = game:GetService("Workspace") local AbilityEvent = ReplicatedStorage.Remotes.AbilityEvent local LocalPlayer = Players.LocalPlayer local ATTACKS = { ["rbxassetid://80666205436772"] = "Warrior Zombie Lunge", ["rbxassetid://85966009904121"] = "Warrior Zombie M1", ["rbxassetid://101311358142810"] = "Scripter M1", ["rbxassetid://70486957731291"] = "Scripter Move 1", ["rbxassetid://120438552410980"] = "Scripter Move 2", ["rbxassetid://71294736489876"] = "Default Zombie Attack", ["rbxassetid://99251628957425"] = "Crosswalker Slam", ["rbxassetid://130471571956863"] = "Frostborne M1", ["rbxassetid://119457368102139"] = "Frostborne M2", ["rbxassetid://131301950844942"] = "Ellernate M1", ["rbxassetid://101792283397169"] = "Ellernate Move 1", ["rbxassetid://137865611397955"] = "Ellernate Move 4", ["rbxassetid://120005408192265"] = "Ellernate Slash", } local PARRY_COOLDOWN = 0.3 local MAX_PARRY_DISTANCE = 16 local PARRY_DELAY = 0.12 -- slight delay (adjust this) local lastParry = 0 local connected = {} local function canParry() return (tick() - lastParry) >= PARRY_COOLDOWN end local function isInRange(character) local myRoot = LocalPlayer.Character and LocalPlayer.Character:FindFirstChild("HumanoidRootPart") local theirRoot = character and character:FindFirstChild("HumanoidRootPart") if not myRoot or not theirRoot then return false end return (myRoot.Position - theirRoot.Position).Magnitude <= MAX_PARRY_DISTANCE end local function onAttackDetected(animationId, character) if not ATTACKS[animationId] then return end if not canParry() then return end if not isInRange(character) then return end print("[Warrior Auto-Parry] Detected:", ATTACKS[animationId]) lastParry = tick() -- Slight delay before firing the ability task.delay(PARRY_DELAY, function() AbilityEvent:FireServer("Q_Ability") end) end local function setupZombie(character) if connected[character] then return end connected[character] = true local humanoid = character:FindFirstChildOfClass("Humanoid") or character:WaitForChild("Humanoid", 3) if not humanoid then return end humanoid.AnimationPlayed:Connect(function(track) local animId = tostring(track.Animation.AnimationId) onAttackDetected(animId, character) end) humanoid.Died:Connect(function() connected[character] = nil end) character.AncestryChanged:Connect(function(_, parent) if not parent then connected[character] = nil end end) end local function scanExisting() for _, obj in ipairs(Workspace:GetDescendants()) do if obj:IsA("Model") and obj:FindFirstChildOfClass("Humanoid") then local isPlayer = Players:GetPlayerFromCharacter(obj) if not isPlayer then setupZombie(obj) end end end end Workspace.DescendantAdded:Connect(function(obj) if obj:IsA("Model") and obj:FindFirstChildOfClass("Humanoid") then local isPlayer = Players:GetPlayerFromCharacter(obj) if not isPlayer then task.defer(setupZombie, obj) end end end) scanExisting() task.spawn(function() while true do task.wait(4) scanExisting() end end)