Add more defaults for mcl_loot, fix random wear

This commit is contained in:
Wuzzy 2017-05-19 17:58:15 +02:00
parent 49bd956da8
commit 1cdc98e03b

View file

@ -7,24 +7,25 @@ Parameters:
* loot_definitions: Probabilities and information about the loot to select. Syntax: * loot_definitions: Probabilities and information about the loot to select. Syntax:
{ {
stacks_min = 1, -- Mamimum number of item stacks to get stacks_min = 1, -- Minimum number of item stacks to get. Default: 1
stacks_max = 3, -- Number of repetitions, maximum stacks_max = 3, -- Maximum number of item stacks to get. Default: 1
items = { -- Table of possible loot items. This function selects between stacks_min and stacks_max of these. items = { -- Table of possible loot items. This function selects between stacks_min and stacks_max of these.
{ {
itemstring = "example:item1", -- Which item to select itemstring = "example:item1", -- Which item to select
amount_min = 1, -- Minimum size of itemstack. Optional (default: 1) amount_min = 1, -- Minimum size of itemstack. Must not be larger than 6553. Optional (default: 1)
amount_max = 10, -- Maximum size of item stack. Must not exceed item definition's stack_max. Optional (default: 1) amount_max = 10, -- Maximum size of item stack. Must not be larger than item definition's stack_max or 6553. Optional (default: 1)
wear_min = 1, -- Minimum wear value. Must be at lest 1. Optional (default: no wear) wear_min = 1, -- Minimum wear value. Must be at least 1. Optional (default: no wear)
wear_max = 1, -- Maxiumum wear value. Must be at lest 1. Optional (default: no wear) wear_max = 1, -- Maxiumum wear value. Must be at least 1. Optional (default: no wear)
weight = 5, -- Likelihood of this item being selected weight = 5, -- Likelihood of this item being selected (see below). Optional (default: 1)
}, },
{ -- more tables like above, one table per item stack } { -- more tables like above, one table per item stack }
} }
} }
* pr: PseudoRandom object * pr: PseudoRandom object used for the randomness
How weight works: The probability of a single item stack being selected is weight/total_weight, with How weight works: The probability of a single item stack being selected is weight/total_weight, with
total_weight being the sum of all weight values in the items table. total_weight being the sum of all weight values in the items table. If you leave out the weight for
all items, the likelihood of each item being selected is equal.
Returns: Table of itemstrings Returns: Table of itemstrings
]] ]]
@ -33,9 +34,13 @@ function mcl_loot.get_loot(loot_definitions, pr)
local total_weight = 0 local total_weight = 0
for i=1, #loot_definitions.items do for i=1, #loot_definitions.items do
total_weight = total_weight + loot_definitions.items[i].weight total_weight = total_weight + (loot_definitions.items[i].weight or 1)
end end
local stacks_min = loot_definitions.stacks_min
local stacks_max = loot_definitions.stacks_max
if not stacks_min then stacks_min = 1 end
if not stacks_max then stacks_max = 1 end
local stacks = pr:next(loot_definitions.stacks_min, loot_definitions.stacks_max) local stacks = pr:next(loot_definitions.stacks_min, loot_definitions.stacks_max)
for s=1, stacks do for s=1, stacks do
local r = pr:next(1, total_weight) local r = pr:next(1, total_weight)
@ -43,7 +48,7 @@ function mcl_loot.get_loot(loot_definitions, pr)
local accumulated_weight = 0 local accumulated_weight = 0
local item local item
for i=1, #loot_definitions.items do for i=1, #loot_definitions.items do
accumulated_weight = accumulated_weight + loot_definitions.items[i].weight accumulated_weight = accumulated_weight + (loot_definitions.items[i].weight or 1)
if accumulated_weight >= r then if accumulated_weight >= r then
item = loot_definitions.items[i] item = loot_definitions.items[i]
break break
@ -55,10 +60,16 @@ function mcl_loot.get_loot(loot_definitions, pr)
itemstring = itemstring .. " " .. pr:next(item.amount_min, item.amount_max) itemstring = itemstring .. " " .. pr:next(item.amount_min, item.amount_max)
end end
if item.wear_min and item.wear_max then if item.wear_min and item.wear_max then
-- Sadly, PseudoRandom only allows very narrow ranges, so we set wear in steps of 10
local wear_min = math.floor(item.wear_min / 10)
local wear_max = math.floor(item.wear_max / 10)
local wear = pr:next(wear_min, wear_max) * 10
if not item.amount_min and not item.amount_max then if not item.amount_min and not item.amount_max then
itemstring = itemstring .. " 1" itemstring = itemstring .. " 1"
end end
itemstring = itemstring .. " " .. pr:next(item.wear_min, item.wear_max)
itemstring = itemstring .. " " .. tostring(wear)
end end
table.insert(items, itemstring) table.insert(items, itemstring)
else else
@ -74,7 +85,7 @@ Repeat mcl_loot.get_loot multiple times for various loot_definitions.
Useful for filling chests. Useful for filling chests.
* multi_loot_definitions: Table of loot_definitions (see mcl_loot.get_loot) * multi_loot_definitions: Table of loot_definitions (see mcl_loot.get_loot)
* pr: PseudoRandom object * pr: PseudoRandom object used for the randomness
Returns: Table of itemstrings ]] Returns: Table of itemstrings ]]
function mcl_loot.get_multi_loot(multi_loot_definitions, pr) function mcl_loot.get_multi_loot(multi_loot_definitions, pr)