Morwen's Loot Generator
Loot Table Generator[edit]
Description[edit]
The Loot Table Generator is a dynamic system for creating randomized loot items in Infinite Worlds. It generates a fresh table of items each turn based on your configuration, with full control over which properties (name, value, weight) are included in the output.
Configuration[edit]
Configuration Sections[edit]
Basic Settings[edit]
Controls the size of the generated table and which properties (name, value, weight) are included in each loot item.
loot_types[edit]
Defines the categories of items that can be generated, with probability weights determining their frequency. Weights must sum to 1.0.
rarities[edit]
Determines the distribution of rarity levels across generated items. Weights must sum to 1.0.
value_ranges[edit]
Sets the minimum and maximum gold value for each rarity level, used when value generation is enabled.
type_weights[edit]
Establishes the base weight range for each item type, used for encumbrance calculations when weight generation is enabled.
materials[edit]
Lists available materials for each item type. Material becomes a core property of the generated item and affects naming and weight.
keywords[edit]
Defines optional modifiers that can be applied to items. Can be simple (single probability) or complex (with probability and multiple values).
type_subtypes[edit]
Specifies the specific variants available within each loot type category, becoming the item's subtype property.
name_templates[edit]
Provides naming patterns for each type, supporting placeholders like {subtype}, {elemental}, {material}, and {effect} that are replaced during generation.
defaults[edit]
Fallback values used when no keyword of a specific type is selected during generation, ensuring all placeholders can be filled.
Full Configuration Example[edit]
# ===== BASIC SETTINGS =====
# Controls which properties are included in generated items
table_size: 10
include_name: true # Include name property in output
include_weight: false # Include weight property in output
include_value: false # Include value property in output
# ===== ITEM CATEGORIZATION =====
# Loot types with probability weights (must sum to 1.0)
loot_types:
weapon: 0.35
armor: 0.25
potion: 0.20
scroll: 0.15
gem: 0.05
# Rarities with probability weights (must sum to 1.0)
rarities:
common: 0.60
uncommon: 0.25
rare: 0.10
epic: 0.04
legendary: 0.01
# ===== VALUE SYSTEM =====
# Gold value ranges assigned by rarity
value_ranges:
common: [1, 50]
uncommon: [51, 200]
rare: [201, 500]
epic: [501, 1000]
legendary: [1001, 5000]
# Value multipliers for keywords
keyword_value_multipliers:
magical: 1.5
cursed: 0.8
blessed: 2.0
ancient: 1.8
elemental: 1.2
effect: 1.2
# ===== WEIGHT SYSTEM =====
# Base weight ranges by item type
type_weights:
weapon: [2, 8]
armor: [5, 20]
potion: [0.1, 2.0]
scroll: [0.1, 1.0]
gem: [0.1, 3.0]
# Weight multipliers for specific materials
material_weight_multipliers:
mithril: 0.7
steel: 1.2
iron: 1.5
wood: 0.8
bone: 0.6
# ===== MATERIAL PROPERTIES =====
# Materials available for each type (becomes item.material)
materials:
weapon: [iron, steel, silver, gold, mithril, wood, bone]
armor: [leather, iron, steel, silver, mithril, plate]
potion: [glass, crystal, clay, alchemical]
scroll: [parchment, paper, vellum, enchanted]
gem: [raw, cut, polished, flawless]
# ===== KEYWORD MODIFIERS =====
# Keywords that can be applied to items with their probabilities
keywords:
# Simple keywords (probability is the value)
magical: 0.30
cursed: 0.10
blessed: 0.05
ancient: 0.15
# Complex keywords (have probability and values)
elemental:
probability: 0.25
values: [fire, water, air, earth, lightning, ice]
effect:
probability: 0.15
values: [health, power, force, flying, stability]
# ===== ITEM VARIATION =====
# Subtypes for each loot type (becomes item.subtype)
type_subtypes:
weapon: [sword, axe, mace, dagger, spear, bow, staff]
armor: [helmet, chestplate, gauntlets, leggings, shield, boots]
potion: [health, mana, stamina, strength, defense, poison]
scroll: [fireball, heal, teleport, identify, protection, curse]
gem: [ruby, sapphire, emerald, diamond, amethyst, topaz]
# Name templates for each type
# Supports placeholders: {subtype}, {elemental}, {material}, {effect}
name_templates:
weapon:
- '{material} {subtype} of {elemental}'
- '{subtype} of {elemental}'
- '{subtype} of {effect}'
- '{material} {subtype}'
armor:
- '{material} {subtype} of {elemental}'
- '{subtype} of {effect}'
- '{subtype} of {elemental}'
- '{material} {subtype}'
potion:
- 'Potion of {elemental}'
- 'Potion of {effect}'
- '{elemental} Potion'
scroll:
- 'Scroll of {elemental}'
- 'Scroll of {effect}'
- '{elemental} Scroll'
gem:
- '{elemental} {material} Gem'
- '{material} Gem of {elemental}'
# ===== FALLBACKS =====
# Default values used when no keyword of that type is selected
defaults:
elemental: [power, mystery, ancients, stars]
material: [iron, steel, wooden, leather]
effect: [power, strength, dexterity]
Generation Script[edit]
# ===========================================
# LOOT TABLE GENERATOR
# Run this every turn to refresh loot_table
# ===========================================
$loot_table = list()
set $table_size = if($loot_config.contains('table_size'), $loot_config.table_size, 10)
for each $i in range($table_size)
set $total_type = 0
for each $t in $loot_config.loot_types.keys()
set $total_type = $total_type + $loot_config.loot_types.item($t)
set $rand = random() * $total_type
set $cumulative = 0
set $type = ''
for each $t in $loot_config.loot_types.keys()
if $type = ''
set $cumulative = $cumulative + $loot_config.loot_types.item($t)
if $rand < $cumulative
set $type = $t
set $subtypes = $loot_config.type_subtypes.item($type)
set $subtype = $subtypes.item(random_between(1, $subtypes.count()))
set $total_rarity = 0
for each $r in $loot_config.rarities.keys()
set $total_rarity = $total_rarity + $loot_config.rarities.item($r)
set $rand = random() * $total_rarity
set $cumulative = 0
set $rarity = ''
for each $r in $loot_config.rarities.keys()
if $rarity = ''
set $cumulative = $cumulative + $loot_config.rarities.item($r)
if $rand < $cumulative
set $rarity = $r
set $value_range = $loot_config.value_ranges.item($rarity)
set $value = random_between($value_range.item(1), $value_range.item(2))
set $keywords = list()
set $multiplier = 1.0
for each $kw in $loot_config.keywords.keys()
set $kc = $loot_config.keywords.item($kw)
set $prob = try($kc.item('probability'), $kc)
if random() < $prob
set $has_values = try($kc.contains('values'), false)
if $has_values
set $vals = $kc.item('values')
set $kw_val = $vals.item(random_between(1, $vals.count()))
$keywords.append($kw & ':' & $kw_val)
else
$keywords.append($kw)
if $loot_config.keyword_value_multipliers.contains($kw)
set $multiplier = $multiplier * $loot_config.keyword_value_multipliers.item($kw)
set $value = round($value * $multiplier)
set $elemental = ''
set $effect = ''
for each $kw in $keywords
set $p = $kw.split(':')
if $p.count() = 2
if $p.item(1) = 'elemental'
set $elemental = $p.item(2)
else if $p.item(1) = 'effect'
set $effect = $p.item(2)
if $elemental = ''
set $default_elementals = $loot_config.defaults.item('elemental')
set $elemental = $default_elementals.item(random_between(1, $default_elementals.count()))
if $effect = ''
set $default_effects = $loot_config.defaults.item('effect')
set $effect = $default_effects.item(random_between(1, $default_effects.count()))
set $material = ''
set $materials = $loot_config.materials.item($type)
if $materials
set $material = $materials.item(random_between(1, $materials.count()))
if $material = ''
set $default_materials = $loot_config.defaults.item('material')
set $material = $default_materials.item(random_between(1, $default_materials.count()))
set $templates = $loot_config.name_templates.item($type)
set $template = $templates.item(random_between(1, $templates.count()))
set $name = $template
set $name = $name.replace('{subtype}', $subtype)
set $name = $name.replace('{elemental}', $elemental)
set $name = $name.replace('{material}', $material)
set $name = $name.replace('{effect}', $effect)
set $name = $name.replace(' ', ' ').trim().title_case()
set $weight_range = $loot_config.type_weights.item($type)
set $weight = random_between($weight_range.item(1), $weight_range.item(2))
if $loot_config.material_weight_multipliers.contains($material)
set $weight = $weight * $loot_config.material_weight_multipliers.item($material)
set $item = record()
$item.item('id') = $i
if $loot_config.item('include_name') = true
$item.item('name') = $name
$item.item('type') = $type
$item.item('subtype') = $subtype
$item.item('rarity') = $rarity
$item.item('material') = $material
$item.item('keywords') = $keywords
if $loot_config.item('include_value') = true
$item.item('value') = $value
if $loot_config.item('include_weight') = true
$item.item('weight') = $weight.round(1)
$loot_table.append($item)Usage[edit]
Quick Start[edit]
1. Create a tracked item named Loot Config (API must be loot_config) with the configuration above
- Type: YAML
- Visibility: invisible to AI and player
2. Create an empty tracked item named Loot Table (API must be loot_table)
- Type: YAML
- Visibility: at least visible to the AI
- Not updateable by the AI
3. Add a trigger that runs the generation script at the start of each turn
4. Access loot via the `$loot_table` variable
Pulling Loot[edit]
# Pull a single random item
set $index = random_between(1, $loot_table.count())
set $loot = $loot_table.item($index)
# Add to player inventory
if not $player.inventory
$player.inventory = list()
end
$player.inventory.append($loot)Displaying Loot[edit]
# Show all loot names
<<$loot_table.format_each('{name}').join(', ')>>
# Show rare+ items
<<$loot_table.where(rarity = 'rare' or rarity = 'epic' or rarity = 'legendary').count()>> rare items
# Show a random item's details
<<$loot_table.item(random_between(1, $loot_table.count())).name>> (<<$loot_table.item(random_between(1, $loot_table.count())).rarity>>)Configuration Presets[edit]
Minimal[edit]
table_size: 5
include_name: false
include_weight: false
include_value: false
loot_types:
weapon: 0.5
armor: 0.5
rarities:
common: 0.8
uncommon: 0.2
value_ranges:
common: [1, 10]
uncommon: [11, 20]
type_weights:
weapon: [1, 5]
armor: [2, 8]
type_subtypes:
weapon: [sword, axe]
armor: [helmet, chestplate]
materials:
weapon: [iron, steel]
armor: [leather, iron]
keywords: {}
keyword_value_multipliers: {}
material_weight_multipliers: {}
name_templates:
weapon: ['{subtype}']
armor: ['{subtype}']
defaults:
elemental: [power]
material: [iron]
effect: [power]
Full RPG[edit]
table_size: 20
include_name: true
include_weight: true
include_value: true
loot_types:
weapon: 0.30
armor: 0.25
potion: 0.20
scroll: 0.15
gem: 0.10
rarities:
common: 0.55
uncommon: 0.25
rare: 0.15
epic: 0.04
legendary: 0.01
value_ranges:
common: [1, 100]
uncommon: [101, 500]
rare: [501, 2000]
epic: [2001, 5000]
legendary: [5001, 20000]
type_weights:
weapon: [3, 10]
armor: [8, 25]
potion: [0.5, 3.0]
scroll: [0.2, 2.0]
gem: [0.1, 5.0]
materials:
weapon: [iron, steel, silver, mithril, adamantium]
armor: [leather, iron, steel, mithril, plate]
potion: [glass, crystal, alchemical]
scroll: [parchment, vellum, enchanted]
gem: [raw, cut, polished, flawless]
keywords:
magical: 0.40
cursed: 0.15
blessed: 0.10
ancient: 0.20
elemental:
probability: 0.30
values: [fire, ice, lightning, holy, dark, nature]
effect:
probability: 0.25
values: [health, mana, strength, speed, protection, regeneration]
keyword_value_multipliers:
magical: 1.8
cursed: 0.7
blessed: 2.5
ancient: 2.0
elemental: 1.5
effect: 1.3
material_weight_multipliers:
mithril: 0.6
adamantium: 0.5
steel: 1.3
iron: 1.5
type_subtypes:
weapon: [sword, axe, mace, dagger, spear, bow, staff, wand]
armor: [helmet, chestplate, gauntlets, leggings, shield, boots, cloak]
potion: [health, mana, stamina, strength, defense, speed, poison, antidote]
scroll: [fireball, heal, teleport, identify, protection, curse, summon]
gem: [ruby, sapphire, emerald, diamond, amethyst, topaz, opal]
name_templates:
weapon:
- '{material} {subtype} of {elemental}'
- '{elemental} {material} {subtype}'
- '{subtype} of {effect}'
- 'Ancient {subtype}'
- '{material} {subtype}'
armor:
- '{material} {subtype} of {elemental}'
- '{elemental} {material} {subtype}'
- '{subtype} of {effect}'
- '{material} {subtype}'
potion:
- 'Potion of {elemental} {effect}'
- '{elemental} Potion of {effect}'
- '{effect} Potion'
- '{material} Potion'
scroll:
- 'Scroll of {elemental} {effect}'
- '{elemental} Scroll of {effect}'
- '{effect} Scroll'
gem:
- '{elemental} {material} Gem'
- '{material} Gem of {elemental}'
- 'Gem of {effect}'
defaults:
elemental: [power, mystery, ancients, stars, light]
material: [iron, steel, leather, cloth]
effect: [power, strength, dexterity, vitality, protection]
Customization Guide[edit]
Adding New Item Types[edit]
- Add to loot_types with probability weight
- Add to type_subtypes with possible subtypes
- Add to type_weights with weight range
- Add to materials with available materials
- Add to name_templates with naming patterns
Adding New Keywords[edit]
Simple keyword: Direct probability value
keywords:
new_keyword: 0.20
Complex keyword: With sub-values
keywords:
new_keyword:
probability: 0.20
values: [option1, option2, option3]
Adjusting Balance[edit]
- Modify value_ranges to change gold values by rarity
- Adjust keyword_value_multipliers to change keyword impact on value
- Change type_weights and material_weight_multipliers for encumbrance system
Notes[edit]
- All probability weights must sum to 1.0 within their category
- The loot table refreshes completely every turn the script runs
- Use //seed(42)// for testing with repeatable results
- For best performance, keep table_size under 50
- Material is a core property, not a keyword