I have done this before and i’ll tell you exactly how I did it:
Hierarchy:
GunService
→ GunController
→ GunComponents
→ -> Firing Component
→ -> Effect Component
→ GunDefenitions
→ -> Ak-47
→ -> Glock
So GunService is a service module wich just creates GunController and stores them:
local gunService = {}
gunService.gunControllers = {}
function gunService:createGun(gunName)
local gunConfiguration = require(gunDefenitions[gunName)
local gunController = gunControllerModule.new(gunConfiguration)
gunController:initialize()
table.insert(gunService.gunControllers, gunController)
return gunController
end
return gunService
Ok so we pass a gunName, this name hooks up to our gunDefenitions. A gunDefenition tells the gun what components to use, fire rate, auto/ semi, etc.
So what happens in the gunController? Well I used an OOP method that loads components and hooks then up with signals
local gunController = {}
gunController.__index = gunController
function gunController.new(gunConfiguration)
local self = setmetatable({}, gunController)
self.configuration = gunConfiguration
self.components = {}
self.events = {
["preFire"] = signal.new(),
["fire"] = signal.new()
end
function gunController:shoot()
local preFire = self.events.preFire
local fire = self.events.fire
local shotContext = {
["cancelled"] = false
}
preFire:Fire(shotContext)
if shotContext.cancelled == true then return end
fire:Fire()
end
local function gunController:loadComponents()
local components = self.configuration.components
for _, componentScript in components do
local requiredComponent = require(component)
local componentObject = requiredComponent.new(self)
componentObject:initialize()
table.insert(self.components, componentObject)
end
end
function gunController:initialize()
self:loadComponents()
end
return gunController
ok so this constructs our gunController and loads our modules.
We have prefire so components like ammoComponent can cancel the shot if for example you are out of ammo. After that the fire signal is fired and your firingComponent can create a projectile or raycast.
But what is a component? Well again its an OOP object:
local firingComponent = {}
firingComponent.__index = firingComponent
function firingComponent.new(gunController)
local self = setmetatable({}, firingComponent)
self.gunController = gunController
return self
end
function firingComponent:initialize()
local fire = self.gunController.events.fire
fire:Connect(function()
print("Fired!")
end
end
return firingComponent
I can share you an a file of an example that works if you like.
Ok all of this code was rushed on mobile without autocomplete but I hope it gives you a sketch on a possible structure.
You can then create a gunController in your toolObject and fire it when the mouse is pressed down.