I’m planning to create a FPS game that will have different spray spread in a cone shape depending on the gun’s stats. It is common for FPS games to have the spread of guns to be decreased drastically when aiming down. How can I do this without it being easily exploited? Most importantly does it matter?
Unless you want to add a significant delay to shooting, you can’t. The only way to secure the spread is by doing the calculations on the server, which creates more issues than it solves.
Any competitive FPS game has to do some calculations server side, or exploiting is going to be rampant to the point of unplayable. Good shooters try, wherever practical, to do the calculation on your client first, and just hope that the server agrees with the outcome when it does the same calculations moments later. The server has to have some tolerance for latency, so really what it’s doing is checking if what the shooter’s client came up with is close enough to be plausible. Most games just check to see if the positions of the players the shooter’s client used for the calcs are within whats reasonable on the server, based on player movement speeds, typical ping times etc.
If someone’s really laggy, or the players are moving very fast in opposite directions, the server may not validate the shot, in which case the shooter thinks he landed a hit, but it’s not confirmed by the death/damage to the opponent. You tune this sort of system by feel, making it loose enough to work for typical player pings 99% of the time, but not so generous that it validates obvious impossible shots.
That said, it’s not usually the spread of the shots that exploiters modify locally. If they’re serious about cheating, they use aimbots, which are very difficult to detect and to distinguish from really cracked players. It normally has to be detected with collection of lots of data and statistically analysis to see if someone went from garbage to goated overnight. And even then, it may be because they got a new mouse, better internet, discovered framerate unlocker, or multiple people with different skill levels are sharing the account.
I was specifically talking about the hit detection calculations (where the spread is applied). If you do the raycasts on the server, and you’re shooting at a moving target, you’ll basically have to lead your shots to hit anything.
Ideally, you should only have to lead your shots on a moving target to compensate for bullet travel time, not client-server ping time, this is true.
So what’s normally done is that you first do the raycasts on the client, then the client tells the server its account of the shooting (where each player was on the shooter’s client, where the shooter was aiming, where the bullet hit, etc.). The server then validates this result by checking if the results from the client are within the range of what that player should have seen based on their ping, the position updates the server has been sending them for other players, and their own top movement speed. The comparison is allows for some variability in ping, of course. The server doesn’t necessarily need to roll back its state of the world and re-do the actual raycasts, it just needs to make a call on whether or not the client’s hit detection results are plausible (vs only possible by exploiting). This setup is the standard “favor the shooter” method that most FPS games use, and it’s why getting shot just after taking cover is such a common complaint; this is the tradeoff that’s made because it feels worse to constantly miss shots that look like they should have hit (on your machine). There are different ways to implement this, some of which rely more on values from the client, and some which trust server estimation of what that client should have been seeing.
In the specific case of shotgun spread, the actual angle of the spread is also something the server calculations would take into account. But really, this would amount to the server just knowing the min/max limits of the spread, and checking that the hit is valid within those limits (i.e. it doesn’t require something like 180-degree spread to reproduce the hit).