Hello, I’m looking for alternate ideas, or confirmation on if my current way of doing tools is correct
what I’m currently doing is creating a tool object (gun in my example) on the server and then telling the client to do the same
Equpping:
server tool Equipped > create tool object > fire client > create tool object
-- on server
local serverGun = ServerGun.new()
-- client
local clientGun = ClientGun.new()
Dequipping:
server tool destroyed > fire client > client tool destroyed
-- on server
serverGun:Destroy()
-- client
clientGun:Destroy()
working example I made while messing around with fastcast (isn’t the neatest code)
Server Gun
-- Services
local Players = game:GetService("Players")
-- Modules
local Quire = require(game:GetService("ReplicatedStorage"):WaitForChild("Shared").Quire)
local Weld = Quire("Weld")
local Maid = Quire("Maid")
local FastCast = Quire("FastCast")
local Network = Quire("Network")
local replicateProjectileEvent = Network("replicateProjectileRemoteEvent", "RemoteEvent")
local ServerGunModule = {}
ServerGunModule.__index = ServerGunModule
function ServerGunModule.new(player, character, humanoid, weaponInfo)
local self = setmetatable({
Player = player,
Character = character,
Model = weaponInfo.Model:Clone(),
WeaponInfo = weaponInfo,
Caster = FastCast.new(),
Debounce = tick(),
Maid = Maid.new()
}, ServerGunModule)
self:Weld()
local connection = self.Caster.RayHit:Connect(function(hit, hitPos, norm, mat, bullet)
if not hit then return end
local enemyChar = hit.Parent
local enemyHumanoid = enemyChar:FindFirstChild("Humanoid")
if enemyHumanoid and enemyChar ~= character then
enemyHumanoid.Health = enemyHumanoid.Health - weaponInfo.BulletDamage
end
end)
self.Maid:GiveTask(function()
connection:Disconnect()
end)
return self, self.Model
end
function ServerGunModule:Shoot() -- runs when client fires server to shoot
if (tick() - self.Debounce) < self.WeaponInfo.Cooldown then return end
self.Debounce = tick()
local origin = self.Model.Barrel.Position
local direction = self.Character.PrimaryPart.CFrame.LookVector * 999
local velocity = self.WeaponInfo.BulletVelocity
self.Caster:Fire(origin, direction, velocity)
replicateProjectileEvent:FireAllClients(self.Player, origin, direction, velocity, self.WeaponInfo)
end
function ServerGunModule:Weld()
local model = self.Model
local modelPrimary = model.PrimaryPart
local characterHand = self.Character.RightHand
model.Parent = self.Character
modelPrimary.CFrame = characterHand.CFrame
Weld(modelPrimary, characterHand)
self.Maid:GiveTask(model)
end
function ServerGunModule:Destroy()
self.Maid:Destroy()
end
return ServerGunModule
Client Gun
-- Services
local UserInputService = game:GetService("UserInputService")
-- Modules
local Quire = require(game:GetService("ReplicatedStorage"):WaitForChild("Shared").Quire)
local Animations = Quire("Animations")
local ClientProjectileHandler = Quire("ClientProjectileHandler")
local Maid = Quire("Maid")
local Network = Quire("Network")
-- Remotes
local shootEvent = Network("ShootRemoteEvent", "RemoteEvent")
local ClientGunModule = {}
ClientGunModule.__index = ClientGunModule
function ClientGunModule.new(weaponInfo, character, humanoid, weaponModel)
local self = setmetatable({
Character = character,
Humanoid = humanoid,
Maid = Maid.new(),
WeaponInfo = weaponInfo,
Debounce = tick(),
Model = weaponModel,
Animations = {}
}, ClientGunModule)
self:HoldAnimation(true)
self.Maid:GiveTask(
UserInputService.InputBegan:Connect(function(input, proc)
if input.UserInputType == Enum.UserInputType.MouseButton1 and not proc then
self:Shoot()
end
end)
)
return self
end
function ClientGunModule:Shoot()
if (tick() - self.Debounce) < self.WeaponInfo.Cooldown then return end
self.Debounce = tick()
shootEvent:FireServer()
local origin = self.Model.Barrel.Position
local direction = self.Character.PrimaryPart.CFrame.LookVector * 999
local velocity = self.WeaponInfo.BulletVelocity
local newBullet = self.WeaponInfo.Bullet:Clone()
newBullet.Parent = workspace
ClientProjectileHandler.Fire(origin, direction, velocity, newBullet)
end
function ClientGunModule:HoldAnimation(play)
local holdAnim = Animations["Hold"]
local isPlaying = holdAnim.IsPlaying
if play and not isPlaying then
holdAnim:Play()
elseif not play and isPlaying then
holdAnim:Stop()
end
end
function ClientGunModule:Destroy()
self.Maid:Destroy()
end
return ClientGunModule
I didn’t show 100% of the code (remotes etc) , but this is likely enough to understand what I’m doing
the only other idea I currently have is to have one local and one script and put it inside a character when they need to equip a tool
is there better alternatives to my method?