What's the best way to handle weapon's stats?

Sorry if I’m posting in the wrong category, idk which to post in

I’m curious on how other devs out there handle the stats of their weapons.

We all know the traditional way of storing values inside a Configuration will no longer works, the client can just simply change the values which opened a big door towards exploiters, so, what’re your approaches?

Let me explain mine first. I’m really concerned on the way that I did it, I think it neither can be exploited nor it is inconsistent.

I have a large module script that includes all weapons’ stats, it’s a big table. When player joins, it fired to the client as a reference. Stats like taking damage can be done from server, just simply find the corresponding weapon’s stats’ damage then deal it! However some stats such as Fire rate, reload time can’t be fetched from server every single time when they fire a gun, players with high ping will suffer a lot. Here raises my first question:
Can exploiters change those values that’re stored inside a Local Script?

Alright, let’s move on. I used to have a variable CurrentWeapon that stores the players’ equipped weapon. It’s fetched from the server. When a player equips a weapon, the client will check that weapon for it’s corresponding stats base on the variable CurrentWeapon. I found this inconsistent, because a player can only own one weapon at the time, even if they have 2 different weapons in backpack, they will share the same stat base on CurrentWeapon. I know I can use a table instead, but I have to do more stuff like indexing them, like what if player switches their order in backpack? I also tried to find a tool’s stats according to the tool name but everything is done in client, so if an exploiter changes the tool name, so do the stats.

So, I’ve switched to another solution. My long term goal is to completely deprecate the CurrentWeapon value, no matter on client or server. Right now whenever a player equips a weapon, it will use a Remote Function to fetch weapon’s data (and welding the tool to player because I don’t use tool handles). Is this a good way? My major concern is on the latency, I also have a custom “EquipTime” which is an amount of time that the tool have to wait before it’s able to shoot (mostly less than a second) and it’s also stored in the Weapon stats table. Now I have to do something with tick() and subtraction in order to make sure the draw time complete on time. This also solves the problems I’ve mentioned above, including tool name changing, multiple tools etc.

I don’t really need a solution or improvements to my current system right now (but feel free to give any suggestions to it!), but I’m really curious on how other devs handle it. Hope I’ll see any new/ innovative/ consistent solutions that ya’ll have!

7 Likes

Any important information such as the Weapon’s damage that will be dealt when the player shoots should be put inside the ServerStorage. The Client should never have access to important information.

What I would do is have a module script of each weapon’s information such as its damage within an Array inside the server storage and have the server take any stats from there.

Now let’s say you wanted to display the Weapon Stats on the Client’s interface, I would make a similar module script with all the needed information inside an array and put it Client Sided BUT you only use this from the client. The Server will use the one you put in the ServerStorage.

Moving on to the CurrentWeapon variable, you should never trust the client doing any Checks, have the server do that using a remote event then compare the stats on the server by making a reference to the Module Script which should be inside the ServerStorage. You should also not refer to the weapon that is currently equipped from the client, let the server check what the player is currently equipping.

4 Likes

I only skimmed through the OP but if you’re going to store the exact copy of a data module in ServerStorage and ReplicatedStorage, you might as well only use the one in ReplicatedStorage.

The return values of ModuleScripts are not shared between the server and the client (mainly because it’s not possible), so if you make a module which returns a stats table and modify the table on the client, it won’t affect the server (as long as you obviously handle the damage calculations on the server).

2 Likes

Yes, you can also use one Module script in the ReplicatedStorage like @Amiaa16 said, depending on what you need. If the info you need is the same or similar then I suggest using the ReplicatedStorage.

If it’s completely different you could still add the information you need all in one module and perhaps create another array within the same module but I like to have everything organised if you get what I mean.

Just always do the important calculations on the server as said above.

A while ago I came up with a way to use it on the client side but I don’t know if it works

When a player tries to exploit what he does is read the outgoing data of the client and modify it, but if one encrypts the information with its own code, I doubt very much that by exploiting it, it will only be necessary to make sure to decrypt the information on the server side.

like for example you want to save the damage done by the weapon let’s say it has 25 damage but you encrypt it and let’s say it looks like this jghfd7 the client will be sending letters and the player won’t know what they mean or what function they have

I don’t know if this works and I haven’t had time to try it but it wouldn’t be a bad idea to try

Luck

Translated with google translator

Yes, this is what I’ve been doing too.

This is also similar to what I’ve been doing, the stats (aka the big table) is being fetched by client from server, the only thing that client references is stats such as fire rate, reload time, etc. This brought me up to the question of whether client can change these read-only values which are stored inside the table initially.

Oh, anything on the client can be changed but it’s not really a problem since you said they are “read-only”. Unless you’re using them to make calculations of how many times the gun can fire per second that’s where the mistake is cause they can easily be changed.

If you are, make use of a table or even a value within the player to act as a kind of debounce. I’d prefer a table as that gives you more options. Basically what you do is have a table on the server and have each Player’s Name/UserId as an index and put another table (within the player index) with the booleans you need such as CanFire = true and you change it to false with a cooldown if you get what I mean. You get the cooldown from your module I guess.

1 Like

I suppose Roblox scripts are? I’m not sure

No that’s not what I thought you meant. I thought you were using them for display or something. Yes they can change them, they can modify any client scripts. They can modify anything within the client. If you are using that fire rate as a cooldown they can change it and turn a shot gun into a machine gun.

Do this :

--Table on server script
ExampleTbl = {
     [Headstackk] = {CanFire = true} --you can add more info in this
     [Player1] = {CanFire = false} --This guy is on cooldown
     --Get the cooldown time for the guns from your module and then you just change the Boolean to true after the wait(cooldown) 
}

--Example in pseudo
--Player clicks and sends an event to server
--On Server event - check if CanFire is true
ExampleTbl[plr.Name][CanFire] = false
wait(cooldown) --GetCooldown from your module depending on the gun 
ExampleTbl[plr.Name][CanFire] = true
1 Like