Introduction
Tools are a pain to use, and it is an even bigger pain to have to duplicate them and change their appearance and a few bits of code to then realize there is a bug in all of them. You then fix the bug and copy and paste the new source from one tool to the other.
If only there was a simpler way to do all of this… That simpler way now exists, and I’ll show you how to use it.
How do I use it?
First, let’s require the module.
local item = require(script.Item) -- or wherever it is
Excellent, now we can use our item module!
Let’s now create an item and give it to the player when their character spawns.
local Players = game:GetService('Players')
local item = require(script.Item) -- or wherever it is
Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function()
wait(3)
local newItem = item.new()
newItem:SetParent(player.Backpack)
end)
end)
When we playtest, we get this error:
22:38:46.174 ServerScriptService.Script.Item:9: You must provide an object! - Server - Item:9
22:38:46.174 Stack Begin - Studio
22:38:46.174 Script 'ServerScriptService.Script.Item', Line 9 - Studio - Item:9
22:38:46.174 Script 'ServerScriptService.Script.Item.OOPWrapper', Line 33 - Studio - OOPWrapper:33
22:38:46.175 Script 'ServerScriptService.Script', Line 12 - Studio - Script:12
22:38:46.175 Stack End - Studio
We need to pass a Model as the first parameter to item.new()
. Otherwise, the item won’t have any appearance. We can achieve this via code, but you can do it directly in Studio if you want.
local Players = game:GetService('Players')
local item = require(script.Item) -- or wherever it is
local model = Instance.new("Model")
local part = Instance.new("Part")
part.Parent = model
model.PrimaryPart = part -- very important!
Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function()
wait(3)
local newItem = item.new(model)
newItem:SetParent(player.Backpack)
end)
end)
Now we get this error:
22:45:42.702 ServerScriptService.Script.Item:10: You must provide a Server Module! - Server - Item:10
22:45:42.702 Stack Begin - Studio
22:45:42.702 Script 'ServerScriptService.Script.Item', Line 10 - Studio - Item:10
22:45:42.702 Script 'ServerScriptService.Script.Item.OOPWrapper', Line 33 - Studio - OOPWrapper:33
22:45:42.702 Script 'ServerScriptService.Script', Line 31 - Studio - Script:31
22:45:42.703 Stack End - Studio
We need to create a server module and a client module for the tool to do stuff. Create two ModuleScripts inside of your script called ServerModule and ClientModule(you can name them anything you want)
In our ServerModule and our ClientModule, let’s put the boilerplate code for a class:
local module = {}
module.__index = module
function module.new(item)
local self = setmetatable({}, module)
return self
end
return module
Don’t forget to include them in the original script!
local Players = game:GetService('Players')
local item = require(script.Item) -- or wherever it is
local serverModule = script.ServerModule
local clientModule = script.ClientModule
local model = Instance.new("Model")
local part = Instance.new("Part")
part.Parent = model
Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function()
wait(3)
local newItem = item.new(model, serverModule, clientModule)
newItem:SetParent(player.Backpack)
end)
end)
Now if we playtest, we get this error:
22:54:47.990 ServerScriptService.Script.Item:25: Client module must be accessible from client! Make sure it isn't parented to ServerScriptService or ServerStorage. - Server - Item:25
22:54:47.991 Stack Begin - Studio
22:54:47.991 Script 'ServerScriptService.Script.Item', Line 25 - Studio - Item:25
22:54:47.991 Script 'ServerScriptService.Script.Item.OOPWrapper', Line 33 - Studio - OOPWrapper:33
22:54:47.991 Script 'ServerScriptService.Script', Line 35 - Studio - Script:35
22:54:47.991 Stack End - Studio
This is pretty self explanatory, the client module needs to be in a place where the client can access it. I’ll let you figure out how to fix the issue.
If you managed to fix the issue, you should now have a basic tool! It doesn’t do anything yet though.
Let’s make our tool change color every time we click with it equipped.
Set the server module code to this:
local module = {}
module.__index = module
function module.new(item)
local self = setmetatable({}, module)
self.OnClickEvent = Instance.new("RemoteEvent")
self.OnClickEvent.Parent = item:GetTool()
self.clickConnection = self.OnClickEvent.OnServerEvent:Connect(function()
item:GetObject().PrimaryPart.BrickColor = BrickColor.Random()
end)
return self
end
function module:Destroy()
self.clickConnection:Disconnect()
end
return module
and the client module code to this:
local player = game:GetService('Players').LocalPlayer
local mouse = player:GetMouse()
local module = {}
module.__index = module
function module.new(tool)
local self = setmetatable({}, module)
self.OnClickEvent = tool:WaitForChild('RemoteEvent')
self.clickConnection = mouse.Button1Down:Connect(function()
if tool.Parent:IsA('Model') then
self.OnClickEvent:FireServer()
end
end)
return self
end
function module:Destroy()
self.clickConnection:Disconnect()
end
return module
End result:
Of course you can do much more with this module, like swords, food, etc. For example, you can have your sword classes inherit one base sword class which is why this module is better than tools when it comes to scripting games with a load of weapons/other items.
If you would like to play with the place file, you can get it here: itemTest.rbxl (27.8 KB)
Documentation
Item Module.new(Model object, ModuleScript serverModule, ModuleScript clientModule, Boolean doNotAutoWeld) Creates an item.
The client module must be parented to places accessible from the client, meaning anywhere other than ServerScriptService and ServerStorage.
void Item:SetGrip(CFrame grip) Sets the item's grip.
void Item:SetParent(Instance parent) Sets the item's parent.
void Item:Destroy() Destroys the item.
Tool Item:GetTool() Returns the tool object associated to the item.
Model Item:GetObject() Returns the model object associated to the item.
Fin
This module is far from complete and the documentation is pretty poor, so if you see any bugs/things I should add, please reply/DM me! Have a nice day.