The only thing here I believe I have experience to talk about on is how you should differentiate between gun types, and to do that I would use OOP (Object Oriented Programming).
local Gun = {}
Gun.__index = Gun
function Gun.new(GunModel,GunInfo)
local self = setmetatable({},Gun)
self.model = GunModel
self.bulletspawn = self.model.BulletSpawn -- arbitrary part at the tip of the gun
self.shooting = false
self.reloading = false
self.reloadtime = GunInfo.ReloadTime
self.class = GunInfo.Class
self.bulletfireoptions = GunInfo.BulletFireOptions -- maybe an array like {5, 1} if the gun is automatic and single shot, {1} if it's single shot only, etc.
self.ammo = GunInfo.AmmoPerMag
self.ammopermag = GunInfo.AmmoPerMag
self.storedammo = GunInfo.StoredAmmo
return self
end
function Gun:CancelReload()
-- optional (for sprinting or clicking while mid-reload)
end
function Gun:Reload()
task.wait(self.reloadtime)
local temp = self.ammo
self.ammo = self.ammopermag
self.storedammo -= (self.ammopermag - temp)
end
function Gun:Shoot()
if self.reloading then
self:CancelReload()
return
end
if self.ammo > 0 then
-- can shoot
-- depends on how you wanna do it, a raycast maybe (from self.bulletspawn to wherever mouse.Hit.p was?)
elseif self.ammo <= 0 and self.storedammo > 0 then
self:Reload()
else
-- player has no ammo ? possibly switch to secondary for them or display a ui
end
end
This is a very broad pseudocode example of how it might be made via OOP. I haven’t exactly made a gun framework myself, but I would take a similar approach to where it’s scalable with multiple gun types all running on one OOP module.
Again, keep in mind I’ve never made an actual gun framework for scalability before. There could be better practices, I just found this tutorial here which seems to have a lot of content packed into it.