Ammo being controlled by all players

Hello Everyone,

I’ve been trying to set up my own weapon framework (with fastcast) for guns. Everything works as I want it to when playing solo.

When I try it out in multiplayer, for some reason the ammo is updated universally for all players. So when one players shoots a bullet out of the clip of 10, everyone else has 9 bullets left in their ammo clip.

No errors or anything. I think I am messing up on something in one of the functions.

Framework Server ModuleScript:

local FastCast = require(game.ServerScriptService.FastCastRedux)

local Caster = FastCast.new()

local CastParams = RaycastParams.new()
CastParams.IgnoreWater = true
FastCast.VisualizeCasts = true

local Behavior = FastCast.newBehavior()
Behavior.RaycastParams = CastParams
Behavior.AutoIgnoreContainer = false

local GunFramework = {}

GunFramework.__index = GunFramework

function GunFramework.new(player, Config) -- I feel like it is in here
	local self = setmetatable({}, GunFramework)
	
	self.Player = player
	self.Gun = Config
	
	print(self.GunWithStats)
	
	self.Reloading = false
	self.Shooting = false
	
	return self
end


function GunFramework:Fire(origin, mousePosition, player, tool)
	CastParams.FilterDescendantsInstances = {player.Character}
	
	print("ELLO")
	print(self.Gun.AmmoInClip)
	
	if self.Gun.AmmoInClip > 0 and not self.Gun.Reloading then
		self.Gun.Shooting = true
		
		self.Gun.AmmoInClip -= 1
		
		local direction = (mousePosition - origin).Unit


		Caster:Fire(origin, direction, 1000, Behavior)
	else
		
		return false
		
	end
	
	self.Gun.Shooting = false
	
	return true

	
end

Server Input Script:

local FireEvent = game.ReplicatedStorage.Events.Fire
local ReloadEvent = game.ReplicatedStorage.Events.Reload
local Framework = require(game.ServerScriptService.GunFramework)
local GunConfig = {
	["FiveSeven"] = {
		["Name"] = "FiveSeven",
		["Class"] = "Pistol",
		["Damage"] = 25,
		["MaxAmmoInClip"] = 10,
		["Range"] = 75,
		["ReloadTime"] = 2,
		["TimeBetweenShots"] = 0.1,
		["TotalAmmo"] = 40,
		["AmmoInClip"] = 10
	}
}

local player = script.Parent.Parent.Parent

local Gun = Framework.new(player, GunConfig)


--I dont think it's in here
FireEvent.OnServerInvoke = function(player, mousePosition, origin, tool) 
	
	local Fire = Gun:Fire(origin, mousePosition, player, tool)
	
	if Fire then
		return true
	else
		return false
	end
	
end

Thanks,

Ultan

It seems like they are all sharing the GunConfig table. Maybe try adding a deepCopy function to copy that table when calling your new function.

local function deepCopy(original)
  local copy = {}
  for k, v in pairs(original) do
    if type(v) == "table" then
      v = deepCopy(v)
    end
    copy[k] = v
  end
  return copy
end

Then in your Server input script do:

local Gun = Framework.new(player, deepCopy(GunConfig))

I just tried that, it doesn’t seem to work. Is it maybe because I use a remote function instead of a remote event?

The problem is that you’re creating a new instance of your GunFramework class for each player. The GunFramework class has a Gun property that is shared between all players. This is because you’re passing in a single table (GunConfig) as the second argument to the GunFramework.new function. If you change GunConfig in one instance of GunFramework then it will change in all instances of GunFramework.
So, when you call Gun:Fire it is decrementing the AmmoInClip property in the GunConfig table.
The solution is to create a new GunConfig table for each player. You could do this by cloning it:
local Gun = Framework.new(player, DeepClone(GunConfig))