universal damage tracker (FIXED LAG)
Key RequiredUniversal

universal damage tracker (FIXED LAG)

Universal Scriptkoboldpawskoboldpaws 852 views 256 executesUpdated Feb 12, 2026
5.0/ 5(3 votes)
30100% Positive
Lua Script•555 lines (13884 chars)
local v2 = Vector2.new
local v3 = Vector3.new
local rgb = Color3.fromRGB
local sin = math.sin
local abs = math.abs
local floor = math.floor
local random = math.random
local insert = table.insert
local remove = table.remove

local rs = game:GetService("RunService")
local plrs = game:GetService("Players")
local uis = game:GetService("UserInputService")
local lp = plrs.LocalPlayer
local cam = workspace.CurrentCamera

local enabled = true
local movingmode = false
local hudoffset = v2(0, 0)
local dragstart = nil
local indicators = {}
local healthcache = {}
local recenthits = {}
local kills = 0
local deaths = 0
local dmghistory = {}
local totaldamage = 0

local gridsize = 20

local lastentityscan = 0
local lastplayerscan = 0
local lastraycast = 0
local lastdpsclean = 0
local entityscanrate = 3
local playerscannrate = 1
local raycastrate = 0.05
local dpscleanrate = 0.5

local cacheddps = 0

local raycastparams = RaycastParams.new()
raycastparams.FilterType = Enum.RaycastFilterType.Exclude

local draw = Drawing

local panel = draw.new("Square")
panel.Size = v2(220, 120)
panel.Color = rgb(18, 18, 22)
panel.Filled = true
panel.Transparency = 0.25
panel.Visible = true

local accent = draw.new("Line")
accent.Thickness = 2
accent.Color = rgb(88, 255, 196)
accent.Transparency = 1
accent.Visible = true

local dpsnum = draw.new("Text")
dpsnum.Text = "0"
dpsnum.Size = 36
dpsnum.Color = rgb(255, 92, 92)
dpsnum.Font = 3
dpsnum.Outline = false
dpsnum.Visible = true

local dpslabel = draw.new("Text")
dpslabel.Text = "dps"
dpslabel.Size = 11
dpslabel.Color = rgb(140, 140, 145)
dpslabel.Font = 3
dpslabel.Outline = false
dpslabel.Visible = true

local totalnum = draw.new("Text")
totalnum.Text = "0"
totalnum.Size = 20
totalnum.Color = rgb(220, 220, 225)
totalnum.Font = 3
totalnum.Outline = false
totalnum.Visible = true

local totallabel = draw.new("Text")
totallabel.Text = "total"
totallabel.Size = 11
totallabel.Color = rgb(140, 140, 145)
totallabel.Font = 3
totallabel.Outline = false
totallabel.Visible = true

local kdnum = draw.new("Text")
kdnum.Text = "0.00"
kdnum.Size = 20
kdnum.Color = rgb(88, 255, 196)
kdnum.Font = 3
kdnum.Outline = false
kdnum.Visible = true

local kdlabel = draw.new("Text")
kdlabel.Text = "k/d"
kdlabel.Size = 11
kdlabel.Color = rgb(140, 140, 145)
kdlabel.Font = 3
kdlabel.Outline = false
kdlabel.Visible = true

local ratiotext = draw.new("Text")
ratiotext.Text = "0 / 0"
ratiotext.Size = 11
ratiotext.Color = rgb(160, 160, 165)
ratiotext.Font = 3
ratiotext.Outline = false
ratiotext.Visible = true

local combobg = draw.new("Square")
combobg.Size = v2(140, 50)
combobg.Color = rgb(22, 22, 26)
combobg.Filled = true
combobg.Transparency = 0.3
combobg.Visible = false

local combonum = draw.new("Text")
combonum.Text = "0"
combonum.Size = 28
combonum.Color = rgb(255, 208, 92)
combonum.Font = 3
combonum.Outline = false
combonum.Center = true
combonum.Visible = false

local combolabel = draw.new("Text")
combolabel.Text = "combo"
combolabel.Size = 11
combolabel.Color = rgb(200, 165, 75)
combolabel.Font = 3
combolabel.Outline = false
combolabel.Center = true
combolabel.Visible = false

local dragoutline = draw.new("Square")
dragoutline.Size = v2(220, 120)
dragoutline.Color = rgb(88, 255, 196)
dragoutline.Filled = false
dragoutline.Transparency = 0.8
dragoutline.Thickness = 2
dragoutline.Visible = false

local combo = 0
local lastcombo = 0

local function snaptogrid(val)
    return floor(val / gridsize) * gridsize
end

local function makeindicator(pos, dmg, crit)
    local ind = {
        pos = pos,
        dmg = dmg,
        time = 0,
        max = 1.2,
        crit = crit,
        vel = v3(random(-2, 2), random(5, 8), random(-2, 2))
    }

    local txt = draw.new("Text")
    txt.Text = tostring(floor(dmg))
    txt.Size = crit and 26 or 19
    txt.Color = crit and rgb(255, 235, 120) or rgb(255, 100, 100)
    txt.Font = 3
    txt.Outline = false
    txt.Center = true
    txt.Visible = true

    ind.txt = txt
    insert(indicators, ind)
end

local function updateindicators(dt)
    for i = #indicators, 1, -1 do
        local ind = indicators[i]
        ind.time = ind.time + dt

        ind.pos = ind.pos + ind.vel * dt
        ind.vel = ind.vel + v3(0, -15 * dt, 0)

        local sp, vis = cam:WorldToViewportPoint(ind.pos)

        if vis then
            ind.txt.Position = v2(sp.X, sp.Y)
            ind.txt.Transparency = 1 - (ind.time / ind.max)
            ind.txt.Size = (ind.crit and 26 or 19) * (1 + ind.time * 0.4)
            ind.txt.Visible = true
        else
            ind.txt.Visible = false
        end

        if ind.time >= ind.max then
            ind.txt:Remove()
            remove(indicators, i)
        end
    end
end

local function getdps()
    local total = 0
    for i = 1, #dmghistory do
        total = total + dmghistory[i].d
    end
    return total
end

local function cleandmghistory()
    local now = tick()
    while dmghistory[1] and (now - dmghistory[1].t > 1) do
        remove(dmghistory, 1)
    end
end

local function performraycast()
    if lp.Character then
        raycastparams.FilterDescendantsInstances = {lp.Character}
    end

    local mouse = lp:GetMouse()
    local origin = cam.CFrame.Position
    local mousepos = mouse.Hit.Position
    local dir = (mousepos - origin).Unit * 1000

    local result = workspace:Raycast(origin, dir, raycastparams)

    if result then
        local part = result.Instance
        local char = part:FindFirstAncestorOfClass("Model")

        if char and char ~= lp.Character then
            local hum = char:FindFirstChildOfClass("Humanoid")

            if hum and hum.Health > 0 then
                if not char.Name:match("[Rr]agdoll") then
                    recenthits[char] = tick()
                    return char
                end
            end
        end
    end

    return nil
end

local function setuptracking(entity)
    if entity == lp.Character then return end
    if healthcache[entity] then return end

    local h = entity:FindFirstChildOfClass("Humanoid")
    if not h then return end

    healthcache[entity] = {last = h.Health}

    h.HealthChanged:Connect(function(newhealth)
        local cache = healthcache[entity]
        if not cache then return end

        local dmg = cache.last - newhealth

        if dmg > 0 then
            local now = tick()

            if recenthits[entity] and (now - recenthits[entity]) < 0.6 then
                local root = entity:FindFirstChild("HumanoidRootPart")
                    or entity:FindFirstChild("Head")
                    or entity:FindFirstChild("Torso")
                    or entity:FindFirstChild("UpperTorso")

                if root then
                    local crit = dmg > 35
                    makeindicator(root.Position + v3(0, 4, 0), dmg, crit)

                    combo = combo + 1
                    lastcombo = now
                    totaldamage = totaldamage + dmg

                    insert(dmghistory, {d = dmg, t = now})
                end

                if newhealth <= 0 then
                    kills = kills + 1
                end

                recenthits[entity] = nil
            end
        end

        cache.last = newhealth
    end)
end

local function trackplayers()
    for _, p in ipairs(plrs:GetPlayers()) do
        if p ~= lp and p.Character then
            setuptracking(p.Character)
        end
    end
end

local function scannpcs()
    local playerchars = {}
    for _, p in ipairs(plrs:GetPlayers()) do
        if p.Character then
            playerchars[p.Character] = true
        end
    end

    local function checknpcs(container)
        if not container then return end
        for _, obj in ipairs(container:GetChildren()) do
            if obj:IsA("Model") and not playerchars[obj] then
                local hum = obj:FindFirstChildOfClass("Humanoid")
                if hum and hum.Health > 0 then
                    setuptracking(obj)
                end
            end
        end
    end

    checknpcs(workspace:FindFirstChild("NPCs"))
    checknpcs(workspace:FindFirstChild("Enemies"))
    checknpcs(workspace:FindFirstChild("Mobs"))
end

local function updateui()
    local ss = cam.ViewportSize

    local px, py

    if movingmode and dragstart then
        local mouse = uis:GetMouseLocation()
        px = snaptogrid(mouse.X - dragstart.X)
        py = snaptogrid(mouse.Y - dragstart.Y)

        px = math.clamp(px, 0, ss.X - 220)
        py = math.clamp(py, 0, ss.Y - 120)
    else
        px = ss.X - 240 + hudoffset.X
        py = 20 + hudoffset.Y
    end

    panel.Position = v2(px, py)
    accent.From = v2(px, py + 35)
    accent.To = v2(px + 220, py + 35)

    dpsnum.Position = v2(px + 13, py - 1)
    dpslabel.Position = v2(px + 12, py + 42)

    totalnum.Position = v2(px + 12, py + 68)
    totallabel.Position = v2(px + 12, py + 92)

    kdnum.Position = v2(px + 125, py + 68)
    kdlabel.Position = v2(px + 125, py + 92)

    ratiotext.Position = v2(px + 125, py + 46)

    if movingmode then
        dragoutline.Position = v2(px, py)
        dragoutline.Visible = true
    else
        dragoutline.Visible = false
    end

    local cx = ss.X / 2 - 70
    local cy = 70

    combobg.Position = v2(cx, cy)
    combonum.Position = v2(cx + 70, cy + 6)
    combolabel.Position = v2(cx + 70, cy + 32)
end

local function updatehud()
    updateui()

    if not enabled then
        panel.Visible = false
        accent.Visible = false
        dpsnum.Visible = false
        dpslabel.Visible = false
        totalnum.Visible = false
        totallabel.Visible = false
        kdnum.Visible = false
        kdlabel.Visible = false
        ratiotext.Visible = false
        combobg.Visible = false
        combonum.Visible = false
        combolabel.Visible = false
        return
    end

    panel.Visible = true
    accent.Visible = true
    dpsnum.Visible = true
    dpslabel.Visible = true
    totalnum.Visible = true
    totallabel.Visible = true
    kdnum.Visible = true
    kdlabel.Visible = true
    ratiotext.Visible = true

    dpsnum.Text = tostring(floor(cacheddps))
    totalnum.Text = tostring(floor(totaldamage))

    local kd = deaths > 0 and (kills / deaths) or kills
    kdnum.Text = string.format("%.2f", kd)
    kdnum.Color = kd > 2 and rgb(88, 255, 196) or kd > 1 and rgb(255, 208, 92) or rgb(255, 92, 92)

    ratiotext.Text = string.format("%d / %d", kills, deaths)

    if combo > 0 then
        combobg.Visible = true
        combonum.Visible = true
        combolabel.Visible = true

        combonum.Text = tostring(combo)

        local p = abs(sin(tick() * 5))
        combonum.Color = rgb(255, 208 + p * 47, 92)
    else
        combobg.Visible = false
        combonum.Visible = false
        combolabel.Visible = false
    end
end

local function checkcombo()
    if combo > 0 and tick() - lastcombo > 2.5 then
        combo = 0
    end
end

if lp.Character then
    local hum = lp.Character:FindFirstChild("Humanoid")
    if hum then
        hum.Died:Connect(function()
            deaths = deaths + 1
        end)
    end
end

lp.CharacterAdded:Connect(function(char)
    char:WaitForChild("Humanoid").Died:Connect(function()
        deaths = deaths + 1
    end)
end)

plrs.PlayerAdded:Connect(function(p)
    p.CharacterAdded:Connect(function(char)
        task.wait(0.5)
        setuptracking(char)
    end)
end)

uis.InputBegan:Connect(function(inp, gp)
    if gp then return end

    if inp.KeyCode == Enum.KeyCode.F5 then
        enabled = not enabled
    end

    if inp.KeyCode == Enum.KeyCode.F6 then
        movingmode = not movingmode

        if movingmode then
            local mouse = uis:GetMouseLocation()
            local ss = cam.ViewportSize
            local currentx = ss.X - 240 + hudoffset.X
            local currenty = 20 + hudoffset.Y

            dragstart = v2(mouse.X - currentx, mouse.Y - currenty)
        else
            if dragstart then
                local mouse = uis:GetMouseLocation()
                local ss = cam.ViewportSize

                local newx = snaptogrid(mouse.X - dragstart.X)
                local newy = snaptogrid(mouse.Y - dragstart.Y)

                newx = math.clamp(newx, 0, ss.X - 220)
                newy = math.clamp(newy, 0, ss.Y - 120)

                hudoffset = v2(newx - (ss.X - 240), newy - 20)
                dragstart = nil
            end
        end
    end
end)

rs.Heartbeat:Connect(function(dt)
    local now = tick()
    local mousedown = uis:IsMouseButtonPressed(Enum.UserInputType.MouseButton1)

    if mousedown and (now - lastraycast) >= raycastrate then
        performraycast()
        lastraycast = now
    end

    if now - lastplayerscan >= playerscannrate then
        trackplayers()
        lastplayerscan = now
    end

    if now - lastentityscan >= entityscanrate then
        scannpcs()
        lastentityscan = now
    end

    if now - lastdpsclean >= dpscleanrate then
        cleandmghistory()
        cacheddps = getdps()
        lastdpsclean = now
    end

    checkcombo()
end)

rs.RenderStepped:Connect(function(dt)
    updateindicators(dt)
    updatehud()
end)

task.spawn(function()
    local playerchars = {}
    for _, p in ipairs(plrs:GetPlayers()) do
        if p.Character then
            playerchars[p.Character] = true
        end
    end

    local descendants = workspace:GetDescendants()
    local chunk = 50

    for i = 1, #descendants, chunk do
        for j = i, math.min(i + chunk - 1, #descendants) do
            local obj = descendants[j]
            if obj:IsA("Model") and not playerchars[obj] then
                local hum = obj:FindFirstChildOfClass("Humanoid")
                if hum and hum.Health > 0 then
                    setuptracking(obj)
                end
            end
        end
        task.wait()
    end

    lastentityscan = tick()
end)

print("click f5 to toggle f6 to move")

Features & Information

tracks dps, total damage, and kd. only works with games using the normal roblox humanoid health
#tracker#damage#universal#kd#ratio

Community Comments (2)

dada

dwa

More Scripts for Universal Scripts