A shooter where the server has the final word
Weapons configured in one table and checked at startup; hitscan bullets and shotgun pellets from a shared seed; auto, semi and burst fire; tactical and empty reloads; recoil and bloom; headshots, falloff and armour; kills, assists and a killfeed; and server-side checks on every shot (fire rate, gun position, spread, silent aim, lag-compensated hit boxes, walls) with strikes.
For: Roblox developers building shooters, combat games and PvP modes.
See it work: real output from the shipped code
A 3-player fight through Combat:Fire()
Every row is a shot a client sent, checked by Validator on the server with the example config: pings of 60-120 ms, targets moving, hits checked against where each target really was when the shot was fired. Kills / deaths after the fight: Ava 2/0 · Ben 0/1 · Cy 0/1.
| Shot at | Shooter → target | Weapon | Ping | Server verdict | Target HP |
|---|---|---|---|---|---|
| 0.20s | Ava → Ben | Vanguard AR | 80 ms | Hit 26 | 74 |
| 0.29s | Ava → Ben | Vanguard AR | 90 ms | Hit 26 | 48 |
| 0.33s | Cy → Ava | Wasp SMG | 120 ms | Hit 18.5 | 81.5 |
| 0.38s | Ava → Ben | Vanguard AR | 80 ms | Hit 46.8 | 1.2 |
| 0.47s | Ava → Ben | Vanguard AR | 80 ms | Hit 26 | 0 |
| 0.40s | Cy → Ava | Wasp SMG | 120 ms | Hit 18.5 | 63 |
| 0.90s | Ava → Cy | Bulldog Shotgun | 60 ms | Hit 16.4 | 83.6 |
| 1.75s | Ava → Cy | Ridgeback Pistol | 60 ms | Hit 46 | 37.6 |
| 1.80s | Cy → Ava | Wasp SMG | 120 ms | Hit 18.8 | 44.2 |
| 1.95s | Ava → Cy | Ridgeback Pistol | 60 ms | Hit 23 | 14.6 |
| 2.12s | Ava → Cy | Ridgeback Pistol | 60 ms | Hit 46 | 0 |
Exploit attempts and the server's answer
The same server, a fresh target, and the shots a cheat client would send. A refused shot uses no ammo and adds strikes; a dropped hit does no damage.
| What the client sent | Result |
|---|---|
| Legit shot, 50 ms ping | Hit 26 |
| Rapid fire (20 ms after the last shot) | Refused: rate |
| No-spread (cone 0 on a hip-fire weapon) | Refused: spread |
| Silent aim (hit claimed on a player 30 studs off the ray) | Hit dropped |
| Shooting from 25 studs away (teleported gun) | Refused: origin |
| Replayed old shot (0.9 s old) | Refused: time |
| Legit shot, 250 ms ping (lag-compensated) | Hit 26 |
The example's 6 weapons, from Damage.shotsToKill
Shots to kill a 100 HP player (body / head at 10 studs, body at 50 and 120 studs) and time to kill with every shot landing. Change any number in the config and these change with it.
| Weapon | Mode | RPM | Mag | 10 st | 50 st | 120 st | TTK |
|---|---|---|---|---|---|---|---|
| Vanguard AR | auto | 720 | 30 | 4 / 3 | 4 | 5 | 0.25s |
| Lynx Burst | burst | 900 | 24 | 4 / 2 | 4 | 4 | 0.433s |
| Wasp SMG | auto | 900 | 32 | 5 / 4 | 7 | 9 | 0.267s |
| Bulldog Shotgun | semi | 75 | 6 ×8 | 2 / 1 | 4 | 4 | 0.8s |
| Kestrel Marksman | semi | 48 | 5 | 2 / 1 | 2 | 2 | 1.25s |
| Ridgeback Pistol | semi | 420 | 12 | 5 / 3 | 5 | 7 | 0.571s |
What's inside
| Module | Runs on | What it does | Lines |
|---|---|---|---|
| Combat | Server | The server side of a shooter. | 243 |
| Validator | Server | The server's anti-exploit checks for every shot a client sends. | 191 |
| WeaponConfig | Shared | Every weapon's numbers in one table, checked at startup so a typo never reaches players. | 236 |
| Damage (free) | Shared | Range falloff, headshot and limb multipliers, and armour, as plain functions you can test. | 94 |
| Spread | Shared | Seeded bullet spread and bloom that the client and the server compute identically. | 81 |
| FireControl | Shared | Fire rate, semi-auto, full-auto and burst timing in one small state machine. | 90 |
| Ammo | Shared | Magazine + reserve with timed reloads (tactical vs empty, a chambered round, cancel). | 147 |
| Recoil | Client | A learnable recoil pattern with recovery, as camera offsets in degrees (client side). | 62 |
| History | Server | Where every character was over the last second, for lag-compensated hit checks. | 90 |
| Killfeed | Shared | Kill entries with headshots, assists, multi-kills and streaks, ready for any UI. | 119 |
| World | Server | The bridge between the combat rules and your place (raycasts, characters, teams, history). | 122 |
| Signal (free) | Shared | A tiny event object so your UI, HUD and game modes can react to hits, kills and reloads. | 49 |
| Example script | Type | Put it in |
|---|---|---|
| SalvowickConfig | ModuleScript | ReplicatedStorage |
| SalvowickServer | Script | ServerScriptService |
| SalvowickClient | LocalScript | StarterPlayer > StarterPlayerScripts |
Tested like real software
45 automated tests run in a real Luau VM against a Roblox engine mock, on luau-web 1.4.0 (Luau compiled to WebAssembly). They ship in the zip: cd tests && npm install && node run.mjs.
| Spec | Passing | For example |
|---|---|---|
| config | 7/7 | the example config passes every check (6 weapons, slots 1-6) … |
| damage | 6/6 | body zones for R6 and R15 parts … |
| demo | 1/1 | demo: a scripted fight, the exploit table and the weapon table |
| example | 2/2 | example config: every loadout weapon exists and every combat setting is present … |
| spread | 11/11 | the same seed gives the same pellets (client and server agree) … |
| validator | 14/14 | a legit shot 150 ms behind the server lands on the lag-compensated target … |
| world | 4/4 | World: Cast finds the player behind the ray and clear() sees walls … |
Install in 5 minutes
- Drag
Salvowick.rbxmxonto ReplicatedStorage in Roblox Studio. - Drag
SalvowickExamples.rbxmxin and move the three scripts to the services above. - Turn on Studio access to API services and press Play.
INSTALL.mdwalks through an example place step by step.
FAQ
Is this allowed on Roblox?
Yes. It's ordinary Luau using Roblox's own services (DataStoreService, MarketplaceService, Players). Nothing bypasses Roblox rules.
Why not a free model from the Toolbox?
Free models are a fine start. Salvowick ships its tests (45 of them, run in a real Luau VM), validates every remote argument, and is original code with a clear licence.
Do I need Rojo?
No. Drag the .rbxmx files into Roblox Studio. A Rojo project file is included if you use it.
Can I use it in a game I sell or a client's game?
Yes: unlimited experiences, commercial or not, for you or your clients. You can't resell or share the code itself.
Is CyberMax affiliated with Roblox?
No. Roblox and Roblox Studio are trademarks of Roblox Corporation, named only to describe compatibility.