
What we're building: corner box ESP with health bars and name tags.
What you’ll learn
1
Project setup
Import modules and set up the render loop.
2
Bounding box
Calculate screen-space bounding boxes from collision data.
3
Box rendering
Draw outlined boxes with corner accents.
4
Health bars
Animated health bars with gradient colors and damage indicators.
5
Name tags & visibility
Player names with text shadows and visibility-based coloring.
Step 1 - Project setup
Every ESP starts the same way: import what you need, hook into the render event, and grab the local player.getPlayers({ skipLocal: true }) returns all player pawns except
your own. We skip dead players early with m_iHealth <= 0.Step 2 - Bounding box calculation
The naïve approach is to hardcode a height offset (origin.z + 72),
but that breaks for crouching players and non-standard models.
Instead, we use the entity’s collision bounds - m_pCollision
gives us the real mins/maxs of the hitbox.
We project all 8 corners of the 3D box to screen space and find
the tightest 2D rectangle that contains them:
worldToScreen returns
success: false and we bail out - drawing a partial box looks worse
than drawing nothing.
Let’s plug it in:
Step 3 - Box rendering
A singleRender.rect looks flat. For a polished look we’ll draw
three layers - dark outer outline, colored main box, and dark inner
outline - plus animated corner accents.
Basic triple-outline box
Corner accents
Corner-style ESP draws short lines at each corner instead of a full rectangle. We’ll animate their length with a sine wave for a subtle pulsing effect:Step 4 - Health bars
A health bar sits to the left of the bounding box. We’ll add:- A dark background with outline
- A color-gradient fill (green → red)
- Smooth animation when health changes
- A white “damage indicator” showing where health used to be
Per-player state
To animate smoothly, we need to remember each player’s previous health value between frames:Drawing the bar
Math.lerp with frameTime * 10 creates an exponential decay
animation - the bar moves fast at first then slows down as it
approaches the target value.
Step 5 - Name tags & visibility
Eye position helper
For accurate visibility checks we need the player’s eye position, not just their feet. The view offset is stored as aCNetworkViewOffsetVector - a packed struct that comes back as raw
bytes. We read the floats manually:
m_vecViewOffset is a CNetworkViewOffsetVector with 16 bytes of
padding, then three CNetworkedQuantizedFloat structs at offsets
0x10, 0x18, 0x20. Each starts with a float we can read
directly.Visibility-aware box color
Instead of a static red box, we’ll smoothly transition between green (visible) and red (hidden):Color.red() in the box and corner
accent drawing with boxColor.
Name tags with shadow
UseRender.calcTextSize to measure the text and center it above
the box. A text shadow (same text drawn 1px offset in black) makes
names readable against any background:
Final result
Here’s everything put together - a complete, working ESP script:Next steps
Now that you have a working ESP, try extending it:- Weapon name - read
enemy.m_hActiveWeaponand display the weapon class below the box - Distance - show distance in meters between you and each player
- Snaplines - draw lines from the bottom of your screen to each enemy
- Team filtering - compare
m_iTeamNumto only draw enemies, not teammates