How do I approach making a Class/Loadout System?

I’m currently working on a game and it needs a class system where player can customize loadout of each class with some tools and weapons available only in specific class, and some available for every class. Tools also should be stored in single folder. I would like to know a good approach to achieve this. Resources like Youtube videos, Devforum posts, code blocks and just ideas will be appreciated.

Ok, so, there are several approaches. There’s a good chance you’ll rather use a different approach to me, and idk how much code experience you have, but you may be able to take inspiration. Behold:

  • Classes: Lua code classes, essentially making my own data-types like Vector3
    • CharacterClass: Contains code which most character classes will use, to avoid repetition of code. May contain methods (lua-code-class functions) like :addTool
--Table to store variables and methods/functions
local CharacterClass = {}

--If a table is linked to this table, and something cant find something in the other table, check this table
--So, if a linked table ('object') tries to find addTool, it will get addTool from here
--This is how we avoid repeating code, by searching if the code exists somewhere else
CharacterClass.__index = CharacterClass

--Function to add a tool. In this example, tool isnt a model or a tool-instance
--It is a table of data (an 'object') containing the tool stats and containing the model of the tool
function CharacterClass:addTool(tool)
	--stuff
	--Maybe update the player's inventory
	--Maybe check if the tool is allowed, already added, not unlocked etc
end

--Return this table, so something else can use it
return CharacterClass
    • Tool: Contains code most tools will need, and default stats which most tools may have
      • Potion: You may have various potions. This can contain code most potions will have. ‘Linked’ to Tools, so if you need a function in Tools, you can access it
      • Weapons: Contains functions most weapons will need. ‘Linked’ to Tools, so if you need a function in Tools, you can access it
  • CharacterClasses: Contains the actual character classes. You can loop through this when creating the buttons to select a class.
    • Bomber: Contains default stats for the Bomber class, maybe even an imageId for an image representing the class
local SS = game:GetService('ServerStorage')

local Classes = SS.Classes

--Default stats for Bomber
local Bomber = {
	id = 'Bomber',
	maxHealth = 100,
	maxStamina = 100,
	icon = 'rbxassetid://0000000'
}

--Tools which will already be assigned to the Bomber
local DefaultTools = {
	require(SS.Tools.Bomb)
}

--One way of limiting tools to classes is to set the allowed tools of a class directly
local AllowedTools = {}

--'Link' the Bomber table/code class to the CharacterClass table/code clas
--This way, if we make a new Bomber called 'bomber', we can call 'bomber:addTool(tool)'
--Even though the Bomber table does not contain :addTool
setmetatable(Bomber, require(Classes.CharacterClass))

--If a specific player's bomber tries to access a variable/method from their bomber
--If it doesnt exist, check the Bomber class for the method/variable
Bomber.__index = Bomber

--Make a new bomber 'object' which can be assigned to a player
--Contains its tools and stats
--Changing the stats of a player's bomber wont change the default stats new bombers get
function Bomber.new()
	--Make a new table/object {}
	--'Link' it to Bomber;
	--It now has a copy of all the stats
	--It now has access to any methods/functions made in this script
	--Since Bomber is also linked to CharacterClass, bomber can also access :addTool()
	local bomber = setmetatable({}, Bomber)
	
	--Give the default tools to the bomber
	bomber.tools = table.clone(DefaultTools)
	
	--Return the new bomber. Another script can assign this to a player
	return bomber
end

return Bomber
    • Hunter: Character class similar to bomber
    • SussyImpasta: Character class similar to Bomber but with extra sus
  • Tools: List of tools. Inside each tool script is the tool model/tool instance, depending on how you wish to design your tools. You can also store effects and sounds in here, which can get cloned to the tool when it is used
    • Bomb: DATA ABOUT BOMB TOOL! STORES BOMB STATS! HAS BOMB MODEL!
local SS = game:GetService('ServerStorage')

local Classes = SS.Classes

--BOMB STATS
local Bomb = {
	id = 'Bomb',
	damage = 100,
	
	--One way of limiting weapons to classes is to set the class type in the weapon
	characterClass = 'Bomber'
}

--LINK BOMB TO WEAPON CLASS
--NOW BOMB CAN ACCESS METHODS DEFINED IN Weapon
setmetatable(Bomb, require(Classes.Tool.Weapon))

--NEW BOMB TOOL/OBJECT
function Bomb.new()
	--LINK NEW TABLE TO Bomb TO CREATE bomb OBJECT
	--HAS ACCESS TO Bomb STATS, METHODS, Weapon METHODS AND Tool METHODS
	local bomb = setmetatable({}, Bomb)
	
	--ASSIGN PHYSICAL BOMB TO OBJECT
	bomb.tool = script.BombModel:Clone()
	
	return bomb
end

--A script may access the bomb from an Inventory table and call bomb:equip(player.Character)
function Bomb:equip(character)
	self.tool.Parent = character
end

--It is best to make more methods here which define how the tool behaves, instead of adding a script to
--every bomb with the same code.

return Bomb
    • Bow: Stats and methods for bow, similar to bomb
    • StaffOfSussness: Tired of being sus? Make others sus!
    • HealthPotion: Linked to Potions instead of Weapons. Contains stats and methods for the HealthPotion tool

There are different ways to restrict tools to each class. You can add a variable called characterClass into each tool and set it to which class the tool is for. You can then have the characterClass loop through all tools, check if the classes match, and add the tool to a list of accepted tools. Or you can directly add each tool to a table inside each class. Or use your own approach.

You can loop through these classes with a script to generate the UI buttons your player needs to select a class and tools.

You’ll need remote events in ReplicatedStorage, in the UI and/or in tools to send signals to the server indicating you want to select a character/tool/use a tool

You may need remote functions in ReplicatedStorage to get certain data about the player or an item/class from the server

You’ll need to disable CharacterAutoLoads in Players since players will be selecting a class before they spawn

You’ll need a custom spawn script in ServerStorage

You’ll need to manually clone the class-selection guis into each player’s PlayerGui as I don’t think guis from StarterGui load on the client until your character loads

Whether or not this approach is something you wish to use, you can probably take inspiration from it to create something at your level of expertise.

In a similar way, I’d also create code-classes called User (containing useful stuff like :getData, :getChar, :getHum, :save etc) and Data (stores, loads and saves user data)

Now, why did I bother writing so much? Ok maybe I have an addiction to making classes… Help… Please…

1 Like

separating each class into its own module same as weapons is overcomplicated in my opinion. i expected a method to make class and loadout system itself with feature to restrict certain weapons from each class.

what i do is have a settings file that stores all the classes data (module script)

this has the key being the class’ name and the value being its data

for example:

return {
    assault = { 
        guns = {"M4", "Glock"},
        speed = 16,
        health = 100
    }
}

you can change that to be whatever you need

then on the server side you would have a way to select a class, simply adding the tools (guns) to the player’s backpack and editing/adding anything else you need

for the gun scripts just put them inside the tool itself and store them in server storage, they wont run until inside the player’s backpack
(or you can have a component system like Knit)

the client side could have a gui to select a class that fires a remote event to the server

now for customization, your settings file is now your default loadouts if no data is saved

on the server (and client) you will store a copy of this table somewhere for each person (on the client just for the local player) then to edit that, you just edit the values inside the saved table

saving that to a datastore when they leave (if you want loadouts to save) and loading it when they join

when selecting a loadout, just have the server check its copy of the table to make sure they actually have that loadout and its not a fake request