LootPlan is a lightweight portable ModuleScript I’ve created to solve your loot generation needs. The module has example scripts, but most of the documentation will be in this post.
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
local LootPlan = require(game.ReplicatedStorage.LootPlan)
local Single = LootPlan.newSingle()
local Multi = LootPlan.newMulti()
“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 *weight*.
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 loot in “single” LootPlans is calculated based on the weight of the loot relative to the combined weight of all of the other 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)
Why?
Using the relative weight to calculate chance instead of using static chance allows you to add loot with arbitrary weight values without having to worry if they add up to 100.
“multi” LootPlans
This class of LootPlan is ideal for scenarios where you want multiple items to drop 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.
The difference between this and “single” plans is that this returns a table of multiple items instead of just one when GetRandomLoot is called.
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 containing multiple loot.
-- First argument is the luck multiplier, second argument is the number of iterations to run
-- 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
Chance for “multi” plans works differently than weight in “single” plans. Instead of being calculated based on the combined weight, the chance is simply a flat percentage out of 100. An 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.
Change Loot Chance
-- "single" LootPlan example
OrePlan:ChangeLootWeight("iron", 20) -- (name, newWeight)
-- "multi" LootPlan example
DropPlan:ChangeLootChance("arrow", 20) -- (name, newChance)
Remove Loot
-- "single" LootPlan example
OrePlan:RemoveLoot("iron") -- (name)
-- "multi" LootPlan example
DropPlan:RemoveLoot("dagger") -- (name)
Get Loot Chance
-- Returns the current chance value of the loot
-- "single" LootPlan example
OrePlan:GetLootChance("diamond") -- returns 0.0089 in our example
-- "multi" LootPlan example
DropPlan:GetLootChance("wizard hat") -- returns 0.1 in our example
Add Loot From Table
-- Adds loot from a table, helpful for convenience and compatibility
-- "single" LootPlan example
local OreWeights = {
["diamond"] = 0.01;
["gold"] = 2;
["iron"] = 10;
["stone"] = 100;
}
OrePlan:AddLootFromTable(OreWeights)
-- "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()
- Edit 6: Changed “chance” for single plans to “weight” to align better with how the calculations work under the hood.