Skip to main content

Pulse.Track

Pulse.Track handles the "apply on entry, remove on exit" pattern that comes up constantly in ESP and effect features. You register entities and their cleanup functions; the tracker handles when to call them.


The problem

Without a tracker, ESP code looks like:

local _active = {}

-- Apply on new entities
if not _active[titan] then
applyHighlight(titan)
_active[titan] = true
end

-- Remove dead ones
for titan in pairs(_active) do
if func.IsTitanDead(titan) then
removeHighlight(titan)
_active[titan] = nil
end
end

-- Remove all on disable
for titan in pairs(_active) do
removeHighlight(titan)
end
_active = {}

This boilerplate appears in every feature. Pulse.Track encapsulates it.


API

local tracker = Pulse.Track.new()

-- Mark an entity as tracked, with a cleanup function
tracker:apply(entity, function(e)
removeHighlight(e) -- called when entity is removed from the tracker
end)

tracker:remove(entity) -- remove one, run its cleanup
tracker:cleanup(predicateFn) -- remove all where predicate returns true
tracker:clear() -- remove everything, run all cleanups
tracker:has(entity) -- bool: is this entity tracked?
tracker:count() -- number of tracked entities
tracker:each(fn) -- call fn(entity) for every tracked entity

Complete ESP example

defineComponent('TitanESP', () => {
const enabled = signal(false)

const tracker = Pulse.Track.new()

function applyESP(titan: Model) {
const hb = titan.FindFirstChild('Hitboxes')
const nape = hb?.FindFirstChild('Nape') as BasePart | undefined
if (!nape) return
Pulse.Draw.highlight(nape, 'TitanESP', {
fill: Color3.fromRGB(255, 255, 0),
outline: Color3.fromRGB(255, 0, 0),
})
tracker.apply(titan, (t) => {
const h = t.FindFirstChild('Hitboxes')
if (h) Pulse.Draw.removeHighlight(h.FindFirstChild('Nape') as BasePart, 'TitanESP')
})
}

const loop = Pulse.Loop.new(1.0, () => {
tracker.cleanup(func.IsTitanDead)
for (const t of func.GetCachedTitans()) {
if (!tracker.has(t)) applyESP(t as Model)
}
})

on.signal(enabled, (v) => {
if (v) {
loop.start()
} else {
loop.stop()
tracker.clear()
}
})

return [toggle('Titan ESP').bind(enabled)]
})

Limitations

  • The cleanup function is called synchronously — don't yield inside it.
  • tracker:cleanup(fn) removes and cleans in one pass — efficient, but the predicate must not error.
  • Trackers don't auto-cleanup on component unmount. Always call tracker:clear() when disabling the feature.