LootPlan is a lightweight portable ModuleScript I’ve created to solve any loot generation needs you may have. The module has example scripts, but most heavy documentation will be in this post.
The documentation is detailed to make sure nothing is missed, but you can probably get the jist of it by simply skimming over it, or looking at the code examples. The system is quite simple, with the module code only taking up ~150 lines.
Classes
There are two classes of LootPlan; “single” and “multi”.
Each class is fundamentally different in the way it handles loot.
To create a LootPlan, require the module and give it a variable, then use LootPlan.new(“class”)
local LootPlan = require(game.ReplicatedStorage.LootPlan)
local Test = LootPlan.newSingle()
“single” LootPlans
These LootPlans are great for any objects that can only have a single value. For example, you may want to create a mining game where different ores could spawn. Each rock could only have a single type of ore in it, so you would use a “single” LootPlan.
To use LootPlans, you must add loot. In this case, “Loot” is simply a name with a chance attached to it. Example code;
local LootPlan = require(game.ReplicatedStorage.LootPlan)
local OrePlan = LootPlan.newSingle()
-- The first argument is the name, the second is the chance
OrePlan:AddLoot("diamond", 0.01)
OrePlan:AddLoot("gold", 2)
OrePlan:AddLoot("iron", 10)
OrePlan:AddLoot("stone", 100)
To retrieve loot from the LootPlan, simply call “GetRandomLoot”. Optionally, you can set a luck multiplier using the first argument.
local OreType = OrePlan:GetRandomLoot(1) -- Argument is the luck multiplier
print(OreType)
How it works
Chance for “single” LootPlans is calculated relative to the total chance values of all loot.
In this example, the combined chance value is 112.01 (100+10+2+0.01)
That means the Iron ore has a true chance of 10/112.01 = 8.927%
The diamond ore has a true chance of 0.01/112.01 = 0.0089% (approx 1/11000)
You can find the true chance of loot quickly with the function OrePlan:GetTrueLootChance(name)
“multi” LootPlans
This class of LootPlan is ideal for scenarios where you need multiple items at once. For example after killing a mob in an MMO, they can often drop multiple items at a time. For this, you would use a “multi” LootPlan.
Unlike “single” LootPlans, this class returns a table of multiple items.
Like before, we create a plan and add loot to it;
local LootPlan = require(game.ReplicatedStorage.LootPlan)
local DropPlan = LootPlan.newMulti()
-- The arguments follow the same order as before (name, chance)
DropPlan:AddLoot("wizard hat", 0.1)
DropPlan:AddLoot("dagger", 2)
DropPlan:AddLoot("arrow", 10)
DropPlan:AddLoot("gold coin", 80)
Similar to the other class, you simply call “GetRandomLoot()” to retrieve random loot. However, instead of returning a single piece of loot, it returns a table of multiple loot.
-- First argument is the number of iterations, second argument is the luck multiplier
-- Both arguments are optional (default to 1)
local Drops = DropPlan:GetRandomLoot(1, 1)
for LootName,LootQuantity in pairs(Drops) do
print(LootName,"=",LootQuantity)
end
How it works
The difference of “multi” lootplans compared to “single” lootplans is the way the chance works. Instead of being based on the combined chance, it is simply a flat percentage out of 100. A item with a chance of 50 will have a 50% chance of appearing in the loot table, regardless of the chance of other items.
Other functions
LootPlans allow you to change/add/remove loot dynamically with low performance impact. This is useful for any scenario the chance needs to change quickly, such as changing ore chance based on depth.
ChangeLootChance
-- "single" LootPlan example
OrePlan:ChangeLootChance("iron", 20) -- (name, newChance)
-- "multi" LootPlan example
DropPlan:ChangeLootChance("arrow", 20) -- (name, newChance)
RemoveLoot
-- "single" LootPlan example
OrePlan:RemoveLoot("iron") -- (name)
-- "multi" LootPlan example
DropPlan:RemoveLoot("dagger") -- (name)
GetLootChance
-- Returns the current chance value of the loot
-- "single" LootPlan example
OrePlan:GetLootChance("diamond") -- returns 0.01 in our example
-- "multi" LootPlan example
DropPlan:GetLootChance("wizard hat") -- returns 0.1 in our example
GetTrueLootChance
-- This function only applies to "single" lootplans
-- Returns the true chance of the requested loot adjusted for the total loot value
OrePlan:GetTrueLootChance("iron") -- returns 8.927 from (10/(100+10+2+0.01))*100
AddLootFromTable
-- Adds loot from a table, helpful for convenience and compatibility
-- "single" LootPlan example
local OreChances = {
["diamond"] = 0.01;
["gold"] = 2;
["iron"] = 10;
["stone"] = 100;
}
OrePlan:AddLootFromTable(OreChances)
-- "multi" LootPlan example
local DropChances = {
["wizard hat"] = 0.1;
["dagger"] = 2;
["arrow"] = 10;
["gold coin"] = 80;
}
DropPlan:AddLootFromTable(DropChances)
Change Log
- Edit 1: Removed unnecessary quantity functionality from multi lootplans.
- Edit 2: Changed ‘rarity’ to ‘chance’ to make more logical sense
- Edit 3: Added “AddLootFromTable” function
- Edit 4: Added Luck multiplier functionality, provide when calling GetRandomLoot in the first argument for single lootplans and the second argument when using multi lootplans
- Edit 5: Added support for typed luau, meaning there is now proper auto fill for function names. This change required moving from
LootPlan.new("single")
toLootPlan.newSingle()