Why your shots don't count: how anti-lead works in Steam GunZ
In Steam GunZ your PC does not decide whether you hit someone. The victim's PC does, after it rewinds itself into the past by one round trip. That one design choice explains most of the shots that land on your screen and then do nothing.
In short
- When you fire, the game sends only the direction of your shot, once, with no resend. It does not say who you hit.
- The victim's game receives it, moves its own character back in time by about one round trip (≈ your ping), checks the shot against that old position, applies its own damage and then tells everyone.
- That rewind is an estimate built from two separately measured numbers. When ping moves (jitter, spikes, route changes), the estimate is off by tens of milliseconds. On a strafing target, 40 ms is about 28 units: half a body width.
- Result: roughly 1 in 10 to 1 in 5 on-target shots register nothing in recorded matches; credit can be lost one way only; relayed players are exposed twice; and the victim's frame rate is your hit registration.
- The 27 October update added Floating Combat Text computed on your PC. It now shows damage numbers the victim never accepts: about 1 in 5 on-target shots in a test game.
- Proposal: let the attacker decide hits (what the shooter saw is what counts), sent reliably, and have the victim and server check each claim within strict limits instead of re-deciding it.
1. How a shot travels today
Most shooters avoid trusting any single player's PC with a hit. Steam GunZ is peer-to-peer for combat, and it puts the decision on the victim's side. Step by step:
- A fires. The game sends a small message holding a timestamp, the muzzle position and the aim direction. It contains no target and no damage. It is sent once to each player, with no acknowledgement or retransmission.
- B receives it about half a round trip later. By then B has kept moving. If B judged the ray against where it is now, almost every shot at a moving player would miss.
- So B rewinds itself. B's game keeps a short history of its own positions and looks up where it was at an estimated "moment A fired". In practice the rewind is about one full round trip:
collision_time = shot_time − clock_offset(A→B) − RTT_last_pingIn recorded matches the measured rewind fits
1.13 × RTT + 14 ms(r = 0.87). In steady conditions the lab reconstruction gives exactly1.00 × RTT. - B tests each pellet, applies the damage to itself and broadcasts the result: one damage report per connecting pellet, plus its new HP/AP. Only when that report reaches A does A get the credit.
Note what "anti-lead" means here. There is no anti-lead message and no server check. The room's anti-lead setting changes how the victim treats the ray it receives; the decision itself always happens on the victim's PC.
2. Six ways a good shot disappears
1The rewind is an estimate, and it drifts when ping moves
The rewind combines two numbers measured at different times: a clock offset (how far A's clock is from B's, learned slowly from position updates) and the last ping (one completed ping exchange). When the connection is steady, the two agree and the error is a fraction of a millisecond. When ping changes (jitter, a spike, a route change, one direction getting slower), they describe different moments. Roughly:
That error is a time. Multiply by the target's speed to get the distance by which B tests the wrong pose. At GunZ strafe speed (700 units/s), 40 ms of error puts the victim's hitbox about 28 units off, against a body capsule 60 units wide. A dash or wall-run is faster and changes direction, which makes it worse.
The lab measured this directly: with only 15 ms of random jitter in each direction, about 19% of shots at a strafing target ended with a different pellet count on the victim's side than on the shooter's. That held at every base ping from 50 to 320 ms. With direction changes it was 57%. A perfectly steady 800 ms connection, by contrast, stays almost aligned. Changing ping hurts more than high ping.
2Your hit needs their downlink
Your shot is one unacknowledged datagram per player. If it is dropped on the way to the victim, the victim never tests it. On your screen that is identical to a miss: no error, no retry, no record.
3Credit is a second, independent gamble
Even when the victim accepts the hit and loses HP, the damage report has to make the return trip, also without resend. In a paired 1v1 recorded from both PCs at 12 ms ping, 12 of 1,960 damage reports (134 damage) never reached the attacker in one direction, and 0 were lost in the other. The victim lost the HP. The attacker's scoreboard never saw it.
4Relayed players are exposed twice
When two PCs cannot reach each other directly (strict NAT, some ISPs), their messages go through a relay. Then both the shot and the damage report make two hops instead of one. That doubles the chances to lose either, adds latency (so the rewind is longer and less precise) and adds the relay's own jitter to issue 1.
5The victim's frame rate is your hit registration
The victim's position history is recorded once per frame of the victim's game, and the shot is only processed on the victim's next frame. In recorded rooms those samples were about 12 ms apart in a 4-player duel and 23 ms apart in a 23-player room. A victim with a low or unstable frame rate has a coarser history to rewind through, so your accuracy is judged against interpolated guesses. Nothing on your side can fix that.
6The victim is the one being trusted
Because the victim decides and reports its own damage, a modified client could simply decline to apply or report hits. To everyone else that looks exactly like network loss (issues 2 and 3), so it is very hard to prove. The current model already trusts players' PCs. It trusts the one with the strongest reason to lie.
3. What the reconstruction lab shows
To separate the timing effect from network loss, frame rate and walls, the timing, clock estimation, position history and hit test were rebuilt as an isolated model and fed controlled networks and movements. It does not run the game and no live players were involved. The shotgun spread is shared by both sides, so every difference below comes from where the victim thinks it was.
- 2,943,000 shot events, 11,772,000 comparisons: base ping 0–350 ms in 10 ms steps × jitter 0–45 ms in 5 ms steps, six movement patterns, two aim points, two assumptions about what the shooter sees.
- Stationary targets: 0 pellet disagreements in 1,962,000 comparisons, under the same timing errors. The error only matters when the target moves.
| Base ping | Jitter (SD, each way) | Strafe: different pellet count | Direction changes: different count | Timing error (P95) |
|---|---|---|---|---|
| Any (0–320 ms) | 0 ms | 0–1% | 1–6% | < 0.1 ms |
| 50 ms | 15 ms | 18.8% | 59.8% | 39 ms |
| 150 ms | 15 ms | 18.7% | 56.7% | 41 ms |
| 280 ms | 15 ms | 18.3% | 56.5% | 40 ms |
| 320 ms | 15 ms | 18.9% | 56.2% | 42 ms |
| 320 ms | 30 ms | 28.0% | 69.8% | 77 ms |
| 320 ms | 45 ms | 34.9% | 75.4% | 122 ms |

See it in 3D. Fire any recorded lab shot with real GunZ models, watch the ray travel and the victim rewind, and compare all 12 pellets as the shooter saw them and as the victim judged them.
Open the 3D lab4. The 27 October update makes it visible
The 27 October Steam update added Floating Combat Text: damage numbers above the target. Those numbers are worked out on the attacker's PC from what the attacker sees. The damage that counts is still decided by the victim. After the update, damage reports are still sent only by victims, and HP drops still line up with the victim's own report 99.5% of the time.
So the game now shows two answers to the same question. In a test game after the update, about 1 in 5 on-target shots showed a number on the shooter's screen that the victim never accepted. Players are not imagining the gap any more; the game draws it for them.
5. The fix: attacker-decided hits
The proposal is to move hit decisions 100% to the attacker, the "favor the shooter" model, and turn the victim and the server from deciders into checkers.
How it works
- Decide on the attacker's PC. When A fires, A's game tests the 12 pellets against the target poses it is drawing at that moment, the same calculation Floating Combat Text already does. There is no estimate: A knows exactly what it rendered.
- Send a claim, not just a ray. The message carries the shot id, the time, the ray, the target, the hit part per pellet, and the timestamp of the target snapshot A was drawing.
- Deliver it reliably. Claims are acknowledged and resent until received (or relayed through the match server), with the shot id preventing double counting. A lost datagram no longer erases a hit, and the damage report no longer has to come back for you to get credit.
- Check instead of re-decide. The victim (and, where possible, the server) accepts a claim if the shot was really announced, it starts where A plausibly was, the claimed target pose is within a tolerance of the victim's own recorded history at that time, and the claim's age is within a cap (see below). Inside those limits the claim counts as made.
What it fixes
- Issue 1 (estimate drift): the exact pose comes from the shooter's screen. Jitter only matters at the edge of the tolerance, not for every shot.
- Issues 2–4 (lost shots, lost credit, double exposure on relays): reliable claims survive a dropped datagram, and credit no longer depends on a return trip.
- Issue 5 (victim frame rate): the test runs against the attacker's own render, so the victim's frame rate only affects the plausibility check, which has tolerance built in.
- The Floating Combat Text matches the damage you are credited with, because they are the same calculation.
6. The honest costs, and how to bound them
Attacker-side hits are not free. These are the real costs and how to bound each one.
Cost 1 · Trusting the attacker's PC
A modified client could claim hits it never made, for example shots through walls or impossible aim. This is the main risk. It is bounded by checks that require no trust:
- The shot must exist. Claims reference a shot announced at fire time; no announced shot, no damage.
- Geometry must agree. The ray must start near A's broadcast position, and the claimed target pose must lie within a tolerance of the victim's own history (for example about 30–60 units, scaled by measured jitter).
- Physics must agree. Fire rate, pellet count and damage per weapon are capped. Line of sight can be checked against the map geometry the clients already load.
- Statistics catch the rest. Explicit claims can be logged and audited: accuracy versus ping, headshot ratios, claims at the edge of tolerance. Today a refused hit is indistinguishable from packet loss. Under this model every disputed hit is a signed, logged claim.
Aimbots and wallhacks are not made worse: they already aim the real ray in either model. The new risk is specifically fabricated hits, which the checks above are designed to reject.
Cost 2 · "I was already behind cover"
With shooter-favoured hits, the victim can be hit a moment after reaching cover on their own screen, because the shooter saw them in the open. This is the deliberate trade every shooter-favoured game makes. Bound it with a rewind cap (for example 200–250 ms): claims older than the cap fall back to today's victim-side check, so a very high-ping attacker cannot reach back arbitrarily far. Cross-region players lose some advantage. Everyone else gets consistent hits.
Cost 3 · More simultaneous kills
Two players who shoot each other within the same round trip can both land their hits. That is consistent with what both saw, and fairer than one of them losing a hit to a dropped message.
Cost 4 · Engineering and roll-out
It is a protocol change, so every client must update together, which a Steam build controls anyway. To de-risk it: first run attacker-side verdicts in shadow mode next to today's system and log disagreements; tune the tolerances and the cap on real data; then switch the room's anti-lead setting over once the numbers hold.
Why it is still the better trade
Today's model already trusts players' PCs, and it trusts them in the way that is hardest to check: a missing hit leaves no evidence. The attacker-side model trusts the player who actually saw the shot, makes every hit an explicit claim that can be verified, and puts hard limits on how far that trust goes. Consistency improves for everyone, and cheating becomes more detectable, not less.
7. What this analysis does not prove
- The lab is a controlled reconstruction of the timing and hit-test logic with synthetic movement and networks. It shows a mechanism and its size; it does not measure how often each condition happens in live Steam matches.
- How the shooter's own screen lags the target is modelled with two explicit assumptions. Exact outcomes depend on that choice; the overall pattern does not.
- The replay measurements come from a limited set of matches. The rewind fit (
1.13 × RTT + 14 ms) is a strong correlation, not a published constant. - Walls, real per-part hitboxes, armour and the full damage pipeline are outside the lab. Part of the 10–20% figure from recorded matches comes from those.