Intro
I’m making this tutorial because I noticed there aren’t many inventory/item related tutorials on the devforum, and I really want to change that
What we are making
We are going to create a Items module to store all of our item information, a LootTables module to store all of our loot tables, and a ItemService module that uses both of the first two modules to get random items
we are creating the Items module separate from the LootTables module so we have the option to make multiple loot tables
Tutorial
Firstly, if we want to make loot tables, we are going to need some loot!
We can store all of our item information in Modules
Items Module
-- Module named Items in ReplicatedStorage
-- you can create as many items as you want, and give the items any value's you want
-- make sure to keep it as an array (linear and no missing indexes, e.g 1, 2, 3, 4, etc)
-- PRACTICE: try adding one or more items of your own
local Items = {
[1] = {
Name = "Iron",
Description = "Used to make iron equipment",
},
[2] = {
Name = "Iron Sword",
Description = "Watch out it's sharp",
},
[3] = {
Name = "Coal",
Description = "Used as a fuel source",
}
}
return Items
now to create a loot table, we can also use Modules for this
Loot Table Module
-- Module named LootTables in ReplicatedStorage
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Items = require(ReplicatedStorage.Items) -- get the Items module
--[[
Weight must be in order from greatest to least
The higher the weight, the more likely it is to be choosen
(relative to other items in loottable)
--]]
-- PRACTICE: if you created one of your own item(s) in the item module, add it here
local LootTables = {
["LootTableA"] = {
{Item = Items[3], Weight = 125}, -- coal, has the highest weight (most common)
{Item = Items[1], Weight = 80}, -- iron sword
{Item = Items[2], Weight = 45} -- iron, with the lowest weight (the rarest)
},
["LootTableB"] = {
{Item = Items[1], Weight = 500}, -- iron sword, and weight is way higher than others, so really common
{Item = Items[3], Weight = 75},
{Item = Items[2], Weight = 35}
}
}
return LootTables
so now that we’ve create both of those information modules, we can create a module to get random items from the loot tables we’ve just created
ItemService Module
-- Module named ItemService in ServerScriptService
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local LootTables = require(ReplicatedStorage.LootTables)
local ItemService = {LootTables = LootTables}
-- gets the total weight, used to generate a random number
local function getTotalWeightOfLootTable(lootTable)
local weight = 0
for _, v in ipairs(lootTable) do
weight = weight + v.Weight
end
return weight
end
function ItemService:GetRandomItemFromLootTable(lootTable)
local totalWeight = getTotalWeightOfLootTable(lootTable)
local randomNumber = math.random(totalWeight)
--[[
loops through the lootTable, if an item is less or equal to the weight of the current entry
it will return the item, otherwise it will subtract the weight and continue the process
until an item is returned
--]]
for _, entry in ipairs(lootTable) do
if randomNumber <= entry.Weight then -- weight is less than random number so returns item
return entry.Item
else -- no item, subtracts the weight from randomNumber
randomNumber = randomNumber - entry.Weight
end
end
end
return ItemService
that’s it, we created a loot table system, and now we can get random items as shown below
local ServerScriptService = game:GetService("ServerScriptService")
local ItemService = require(ServerScriptService.ItemService)
local lootTableA = ItemService.LootTables.LootTableA
local randomItem = ItemService:GetRandomItemFromLootTable(lootTableA)
print(randomItem.Name)
this is my first tutorial, so feel free to let me know how I can improve this post, and I will do so, depending on how this tutorial is received I will possibly add more to this tutorial
Update #1
Using indexes for loot tables may be bothersome or confusing, so in this first update we will make a function that can get an item by it’s name instead of index
we need to edit the Items module
creating a new table that that has an items name as the key and value as the item, is better than looping through the entire Items table and checking the name as we only have to iterate through a table once
local Items = {
[1] = {
Name = "Iron Sword",
Description = "Watch out it's sharp",
},
[2] = {
Name = "Iron",
Description = "Used to make iron equipment",
},
}
local ItemsByName = {}
for i, item in ipairs(Items) do
ItemsByName[item.Name] = item
end
function Items:GetItemByName(itemName)
return ItemsByName[itemName]
end
return Items
now in our LootTables module we can do
["LootTableA"] = {
{Item = Items:GetItemByName("Iron"), Weight = 2},
{Item = Items:GetItemByName("Coal"), Weight = 1},
{Item = Items:GetItemByName("Iron Sword"), Weight = 1}
}
it’s a lot easier to read to me, but this step is optional and opinion based
File: LootTablePlace.rbxl (19.5 KB)