Multiplayer bullet spread

Let me layout what’s going on.
a client shoots
client already sends bullets flying through the game to make it feel responsive.
server registers bullets (UDP) and simulates trajectory.
server simulates collision, hits enemy or not.

Now I want to add accuracy to certain guns. (trajectory offset)
The bullet spread obviously should be the same on the server and client.
But the server can’t accept whatever spread the client has sent. This can be hacked to disable spread.

Sorry if I’m being unclear. I’m having a hard time explaining :stuck_out_tongue:

You’re correct. The server should decide the spread/direction of each bullet, but doing so would incur a lot of delay. The client can’t generate those itself because that’d be easily hackable. A simple solution would be to have the server decide on a random seed assigned to each player/entity. When the player shoots, you calculate the next value on both the server and the client and use that as the spread angle/radius/whatever. Essentially, the server decides ahead of time what the future spreads will be with the seed. If the client hacks it, it’d only affect the player’s view of the world making it seem like the bullets have no spread, but the server still does the correct spread calculations.

EDIT: It’s important that you do not “desync” the seeds used for spread calculations. If you use UDP, you must be careful to sort packets that arrive out of order, and the delay of the messages must not cause order changes.

Example if you use a shared seed between all players:

Server’s view:

  • Player 1 shoots (10 ping) with seed 1
  • Player 2 shoots (100 ping) with seed 2

Player 2’s view:

  • I shoot with seed 1
  • Player 2 shoots with seed 2

So you should try to use 1 seed per player to avoid relativistic problems (lolz) and make sure that shooting packets are reordered when received by the server/client.

You may be tempted to avoid all this reordering and seed synchronization by having the client send the next seed, but this will cause the spread to be hackable again as the client can brute-force a good seed with close to zero spread and send that. You could try to verify that the seeds are sequential, but then you get problems with legitimate but lagging players looking like cheaters due to the ordering and delay of their packets.

I see what you mean, the only think I couldn’t wrap my head around was how to fix the UDP thing.
As some packets will not arrive the seed would be desynced.

Do it like Counter-Strike: The same weapon always has the same spread/spray pattern.
So you only need to send when the player hits the “shoot” button and when it releases it.
Makes your game alot more interesting for pro-gamers moving the mouse in inverse spread patterns.

That actually seems like a good solution.

some most games totally ignore this issue. they just let the client see a totally different “random” behaviour. it may happen too fast to be noticed.

random seed is a good idea. the only number to sync is the position inside the random sequence. which if hacked, would only branch for a sync-cylcle which may not be noticed either.

a fixed pattern may be learned and exploited by crazy people.

i love it when people go about such small features. sometimes they turn out to be not as simple and plain and affect perception big time.

I do not see what the problem is with gathering the indication that the player is requesting to shoot, then doing calculations on the server to generate the bullets. As per each shoot request comes another. As per a modded amount of shoot requests comes delays in the gun from the server side. So that isn’t a problem. You never have to send any packets back.

Because there should be an accuracy factor to the gun. The client should show what the server will know or already knows. Else it can lead to false view.

Another question:
Should the angle to the mouse from the player be sent when starting to shoot? Cause I believe it can be modified. angle = angle - generatedDeviation();
If it isn’t sent the gun would shoot to the point the player was aiming at in the past depending on latency.

Oh right, you want a bullet trail or whatever.
Alongside what I said, you can always send data back per request.

I guess I can’t send angle anyways, cause i will only send a start and stop shooting packet. And obviously player’s can rotate while shooting so. Perhaps I’ll send a set rotation packet for every bullet, pretty much forcing onto the rotation data the server has which could be in the past.

I wanna mention that players who lag in super network intensive games such as FPS or MOBAS like LoL or Dota should suffer the ugliness.

@SuperMario: You should be able to derive the location (and direction) of the muzzle using the transform of the player on the server side, thus not needing to send the information.

Why are you suggesting people should make a shit games because the players may not have access to the best hardware or network connections? Networks are not perfect, even on LAN (let alone over the internet and through firewalls) there are occasional hiccups.

I didn’t say that whatsoever. Go try to start flame with someone who doesn’t monitor intense use of minimalist CPU/GPU and Internet. I know what I am talking about when I say don’t play where 125+ ping is on you; its stupid. Get better internet or find a game with a closer server. It’s their problem not yours. Having the game being ugly is the least you can get and players can’t aim anyways, and that isn’t even your fault. You will always see it in video games and can’t be taken out. And to go off of, “players can’t aim anyways” I always find doing nothing aesthetically helps lagging people, as you have better sense of where that player is.

I can agree with this. The “net code” should be optimized for all players having roughly the same ping. If a player has a higher ping than other players, they must be the ones that are suffer the consequences from their bad connection. Example: Lagging player shoots first, non-lagging player shoots second, server sees second player’s message arrive first, but first player’s timestamp is lower. Yes, it sucks to “punish” people who are stuck on bad connections, but the alternatives are worse.

In some games, lagging player will have certain advantages when it comes to being offensive. Run around a corner and you technically see the enemy first before they see you (they haven’t seen you come around the corner yet). This leads to an incentive for people to introduce artificial delays on their packets to gain an advantage. Secondly, it’s fair to say that 1 lagging player can easily ruin the fun for everyone else on a server, so it’s a good idea to discourage that. Everyone’s happier if they just play with people that have the same ping as them.

You’re right, this could be a problem. The client does “know” what the next random spread will be if it calculates it from the seed prematurely, which technically could allow it to compensate between each shot. There really isn’t a perfect solution here simply because the client cannot be trusted. A seed-based spread pattern will keep the spread patterns synchronized between the server and the client, but also tell the client what the spread is going to be in the future. Most likely, the most unhackable solution is to simply let the client and the server calculate different spread values and show different bullets. Then again, if the player has an aimbot hack any kind of spread or recoil probably won’t matter anyway. IMO, the best anti-hacking system is a solid vote-kick/ban command. =P

This information is from the past though, and rotation (since it’s 2d) is almost always changing as the gun aims to your mouse location.
I might just show a different spread on the client. I’ve heard that AAA titles’ collision detection is random and isn’t what the client shows. However it will account for lag compensation.

Yes, sorry I assumed that you would have a history of that information, up to a certain time in the past.

OOOh now it’s 2d >.>
Much, much easier to do and I don’t even think you have to worry.

Technically, bullets aren’t actually glowing brightly when flying in the air unless they are tracer rounds, so rendered bullets don’t really need to be that correct if you are aiming for realism.

Another option, if you want spreads to be varied, is to pre-calculate a set of different spreads for the weapon and hard-code them into the game, so that the client/server only need to tell each other the identifier of the specific spread from the set, rather than calculating anything.