Gameplay Ability Firing Weapon

I am making a Multiplayer FPS Shooter and I am trying to figure out a good practice for shooting and damage.

Currently I am using a Gameplay Ability to check if there is a round in the chamber, check fire mode (safe, semi, full auto) and then shoot a line trace however I would think that this could be very bandwidth heavy especially if its multiple automatic weapons. (nothing like a mini gun)

I have read a couple different ways to do this but I am unsure what the best a better way for bandwidth and to prevent cheating.

  1. Have the client shoot and have the server check if the client can hit the location - Wouldn’t this be the same as having the server just do the trace in the first place? I am not sure how I would validate if the client could hit the location by the server (I would need to do something like this so the client isn’t hitting people on the other side of the map or behind some kind of object that they can’t shoot through)

  2. I could have a start firing tag or bool and a end firing tag or bool. Set the firing rate based off the weapon so the server will fire a line trace ever X.XX time.

If you have a better method please let me know.

Lastly the final issue is that when I currently shoot one round it shoots 2 line traces and causes damage twice. I have read “servers authoritative proxy (copy of your character) needs to have the ability too. So server applies the ability and replicates it to you and all simulated copies of you”. How would I stop this from happening twice in the gameplay ability?

You have to split your logic up into “Proxy Events”.

Client (Autonomous) presses fire, checks if it can shoot (ammo, other), Fires a local shot.
Local shot handles all the local hit fx.

RPC the Server (Authority) to shoot.
Checks if it can shoot (ammo, other), Fires a local shot.

Multicast for sims (Simulated) to shoot.
MC executes logic on Sim proxies only.
Get Local Role == Simulated Proxy -> Branch [true]: Event Sim Shoot

Event Sim Shoot (data): uses the same values the server used to shoot, so it get the same trajectory on shot.


Clients can pass simple vectors to the server to validate shot.

For Hitscan you’d pass the trace start/end vectors. Server can then compare the start and end points against its own calculations. If distance for each is within margin (few cm radius) use the clients values, otherwise use the servers.

This is solid for single fire. For Burst and Auto firing you only validate the first bullet, then the servers calcs are used for all others.

e.g. Burst firing typically does 3 shots in a loop. Client would pass the first shots values.
Server would scrutinize the first shot, make decision on which values to use, then fire the next two with no regard to what the client did.

Same applies to automatic firing. First shot checked, remaining are not. Server uses its values for all proceeding shots.

For projectiles you pass muzzle location and the final Velocity vector. Compare these.

We only compare the first because they are the only ones that are “truly” aimed. You want that shot to hit where the client was aiming. The remaining shots are chaotic recoil applied mess.

Very informative, I have seen a lot of your answers to people’s questions, and it has helped me a lot! Thanks for the reply. Not too sure how to implement this in GAS but I’ll keep looking!

1 Like

I wouldn’t suggest using GAS until you have a project that really requires it. GAS is great, but for 95% of the games I see/play they don’t require it, or really help. I find that it’s extremely heavy.

Here’s the general layout from a prototype build.

Client inputs FIRE, Run a macro to check if you can fire.
Macro: Has a weapon equipped, Weapon has ammo, Not jumping or underwater etc.
If “Can Fire”: Call Client Fire Weapon in the weapon class.


Client Fire Weapon does its own check if it can fire the weapon.
Macro: Has a weapon equipped, Weapon has ammo, Not jumping or underwater etc.
If “Can Fire”: Switch on Firing mode: Call specific function… single, burst, auto

Single Fire Example: SemiAuto Firing → Single Autonomous Firing

Function calculates the trajectory velocity, recoil data etc then requests the projectile from pool passing muzzle location and velocity.

Function returns Client Fire Data struct which is passed to the Server RPC.


Server RPC is an event in the character class which mirrors the client process in step 1.

The character is the owner of the weapon, thus the full authority. So we initiate the action of firing on the character. Let it jump the hoops just like the client would.


Srv Fire Weapon (Weapon Class)
Determines firing mode

Srv SemiAutoFiring → Single Authoritative Firing

The Srv Projectile Trajectory function handles the anti-cheat shot comparison logic.

Rough outline of things to check. Buffer checks on recoil application and mouse coord checks aren’t necessary for prototyping. 3rd party AC can handle those.

After the projectile is requested from pool we call a Multicast.

The branch only allows for execution on simulated proxies.


Single Simulated Firing

Main process here is requesting a projectile from the obj pool. Then playing Audio, muzzle flash etc.


Everything in this process is broke down to a proxy level.
Each proxy has its own projectile class.
Clients and Sims utilize the same bullet pool, while server has its own specialized bullet pool.

1 Like

Is the “Projectile Trajectory” where you get the launch conditions i.e. start point, velocity etc. and everything else and the “request projectile” where you actually spawn and “fire” the projectile? I am using something similar to a line trace with a simulated “bullet drop” ricochet and penetration. So I will have less steps and trying to see where I should tie it in at.

Yes, Projectile Trajectory does all the vector math. The Aim velocity is what is applied to the projectile movement components velocity.

Request Projectile is the Object Pool call.

Forgot to mention that penetration is 100% handled server side.

If you let a client determine it locally it may not matchup with the servers. Have the server make the determination and multicast the data needed to simulate the effect on each client.

Demo