~/docs/paintball/configuration/anti-cheat-integration
paintball docs›
Paintball
Anti Cheat Integration
-- 3 code blocks · 2 min read
Var-PaintBall is a non-lethal combat gamemode. During a match, players legitimately have behaviour that most anti-cheats flag as cheating :
- No combat damage : players don't take real health damage (elimination is kevlar-based).
- Infinite / high ammo : the paintball weapon is given large ammo counts.
To prevent false-positive bans during a match, Var-PaintBall exposes two server-side events that fire when a player enters and leaves a live match. You hook these from your own resource to whitelist players in your anti-cheat — and un-whitelist them the moment the match is over.
The script has no hard dependency on any anti-cheat. These are generic hooks, they work with WaveShield, FiveGuard, or any system that exposes a per-player bypass.
How it works
All authority stays server-side. The client never decides who is whitelisted, so a cheater cannot self-whitelist by replaying a client event.
| Event | Args | Fires when |
|---|---|---|
var-paintball:server:match:playerJoined |
src (number), matchId (number) |
The player is placed into a live match. |
var-paintball:server:match:playerLeft |
src (number) |
Match end, death/elimination, kick, leave, or disconnect mid-match. |
The two events are strictly paired : every playerJoined is followed by exactly one playerLeft, covering every exit path (match finished, player eliminated, kicked, left the lobby, or dropped from the server mid-match). This guarantees a bypass is always revoked.
Setup
Create a small server file in your own resource (do not edit Var-PaintBall), and listen to the two events.
WaveShield
-- server.lua (in your own resource)
AddEventHandler("var-paintball:server:match:playerJoined", function(src)
exports["WaveShield"]:toggleBypass(src, true)
end)
AddEventHandler("var-paintball:server:match:playerLeft", function(src)
exports["WaveShield"]:toggleBypass(src, false)
end)
That's it. Players are whitelisted for the duration of the match and re-protected the instant it ends.
Any other anti-cheat
The pattern is identical — swap the export for your anti-cheat's whitelist/bypass call:
AddEventHandler("var-paintball:server:match:playerJoined", function(src)
-- enable your anti-cheat bypass for `src`
end)
AddEventHandler("var-paintball:server:match:playerLeft", function(src)
-- disable your anti-cheat bypass for `src`
end)
Optional : safety-net auto-expire
If your anti-cheat supports a timed bypass, you can add one on join as a fallback. If a playerLeft is ever missed (e.g. an anti-cheat resource restart), the bypass still expires on its own instead of staying open.
AddEventHandler("var-paintball:server:match:playerJoined", function(src)
exports["WaveShield"]:toggleBypass(src, true)
exports["WaveShield"]:tempBypass(src, 1800) -- auto-expires after 30 min
end)
Set the auto-expire duration longer than your longest possible match, otherwise a long match could lose its bypass mid-game. The paired
playerLefthandler remains the primary way the bypass is revoked,tempBypassis only a fallback.
FAQ
Do I have to edit the Var-PaintBall files ? No. The hooks are built in. All your integration lives in your own resource.
What if a player disconnects in the middle of a match ? playerLeft still fires for them, so any bypass is revoked. (Most anti-cheats also clear per-player state on disconnect anyway.)
Can a cheater abuse the bypass outside a match ? No. The events fire only when the server places a player into a real match and removes them. The client has no control over this.
Which anti-cheats are supported ? Any of them, the hooks are generic. WaveShield is shown above because it ships ready-made toggleBypass / tempBypass exports.