Nimble Pixie Merchant

    loot-table-advanced
    TypeScript icon, indicating that this package has built-in type declarations

    1.4.2 • Public • Published

    Loot Tables Advanced

    Loot Tables are lists of items, quantities, and probabilities, used to create random outcomes for games. This Loot Table specification is both simple and expressive, able to power anything from random card packs to monster spawns to crate drops.

    alt text

    Loot Tables

    Loot Tables have an ID, and a list of entries.

    Loot Table Item type

    The various Loot Table interfaces and functions take an optional generic type T that defaults to string. In your project, if you have an enum that defines valid item ids, you should supply that enum as your T parameter to preserve the typing throughout. The generic type V is used if you have a custom type for loot table ids.

    Loot Table Entry

    • ItemID or @TableID : T extends string
    • Min : number - minimum quantity to produce
    • Max : number - maximum quantity to produce
    • Step : int - quantity will be in increments of this amount, or NaN for non-integer decimal values
    • Group : int - entries may be grouped (see crate_1 example below)
    • Weight : int - the relative probability of for this entry
    • Transform : function - optional transform

    The optional transform function takes a number between 0.0 and 1.0 and should usually return a value between 0.0 and 1.0 as well. This can be used to do things like apply an easing function to the random number used to pick the value between Min and Max. The transformed value is not validated, so user beware. If you return a value below zero or above one, then you will get an output outside of your specified Min or Max.

    Stupid Simple Example

    This simple, one-item Loot Table will always produce "1 coin". The default value for all of the numeric properties is 1.

    ID Weight Min Max Step Group
    coin 1 1 1 1 1

    JavaScript

    const simple = [ { id: 'coin' } ];
    let loot = GetLoot(simple);

    TypeScript

    const simple: LootTable = [ { id: 'coin' } ]
    let loot = GetLoot(simple)

    Groups, nulls, and Quantities Example

    This more complex Loot Table has two Groups. One entry will be chosen per Group to produce. Entries with a null ID produce nothing. Group 1 has a total weight of 14, so Group 1 has a 10-in-14 chance of producing from the coin entry. If the coin entry is selected, it will produce 50, 75, or 100 units of coin, due to how Min, Max, and Step are specified. Group 2 has a total weight of 10, and since cloth and null both have a weight of 5, there's a 50/50 chance that Group 2 will produce nothing. If the cloth entry is selected, it will produce 40, 45, or 50 units of cloth. Overall, this Loot Table may produce nothing at all, some coin, some cloth, or some of both.

    ID Weight Min Max Step Group
    coin 10 50 100 25 1
    null 4 0 0 1 1
    cloth 5 40 50 5 2
    null 5 0 0 1 2

    The code examples show the use of the LootTableEntry helper function, which performs error checking on the inputs and returns a valid object.

    JavaScript

    const crate_1 = [
        LootTableEntry('coin', 10, 50, 100, 25, 1),
        LootTableEntry(null, 4, 1, 1, 1, 1),
        LootTableEntry('wood', 5, 40, 50, 5, 2),
        LootTableEntry(null, 5, 1, 1, 1, 2),
    ];
    let loot = GetLoot(crate_1);

    TypeScript

    const crate_1: LootTable = [
      LootTableEntry('coin', 10, 50, 100, 25, 1),
      LootTableEntry(null, 4, 1, 1, 1, 1),
      LootTableEntry('wood', 5, 40, 50, 5, 2),
      LootTableEntry(null, 5, 1, 1, 1, 2),
    ]
    let loot = GetLoot(crate_1)

    Nested Loot Tables

    A Loot Table Entry may specify an Item ID, as in the examples above, or an Entry may specify the ID of another Loot Table to generate items from. The only restriction is that Loot Table references may not create a circular reference. To differentiate Item ID from Loot Table ID, an @ character is used to prefix the Loot Table IDs.

    gems and treasure example

    gems

    ID Weight Min Max Step Group
    pearl 1 5 10 1 1
    garnet 1 3 12 1 1
    ruby 1 4 9 1 1
    sapphire 1 1 2 1 1

    treasure

    ID Weight Min Max Step Group
    @gems 1 0 2 1 1
    gold 1 15 20 1 2

    The treasure Loot Table will always give you 15 to 20 gold, and zero, one, or two results from the gems table.

    JavaScript

    const gems = [
        LootTableEntry('pearl', 1, 5, 10, 1, 1),
        LootTableEntry('garnet', 1, 3, 12, 1, 1),
        LootTableEntry('ruby', 1, 4, 9, 1, 1),
        LootTableEntry('sapphire', 1, 1, 2, 1, 1),
    ];
    const treasure = [
        LootTableEntry('@gems', 1, 0, 2, 1, 1),
        LootTableEntry('gold', 1, 15, 20, 1, 2),
    ];
    function ResolveHelper(id) {
        switch (id) {
            case 'gems':
                return gems;
            case 'treasure':
                return treasure;
        }
        return null;
    }
    let loot = GetLoot(treasure, 1, ResolveHelper);

    TypeScript

    const gems: LootTable = [
      LootTableEntry('pearl', 1, 5, 10, 1, 1),
      LootTableEntry('garnet', 1, 3, 12, 1, 1),
      LootTableEntry('ruby', 1, 4, 9, 1, 1),
      LootTableEntry('sapphire', 1, 1, 2, 1, 1),
    ]
    
    const treasure: LootTable = [
      LootTableEntry('@gems', 1, 0, 2, 1, 1),
      LootTableEntry('gold', 1, 15, 20, 1, 2),
    ]
    
    function ResolveHelper(id: string): LootTable | null {
      switch (id) {
        case 'gems':
          return gems
        case 'treasure':
          return treasure
      }
      return null
    }
    
    let loot = GetLoot(treasure, 1, ResolveHelper)

    Multiple Items Without Replacement

    To simulate something like, "draw two cards", where you can't get the same item twice, the Loot Table Advanced GetLoot allows the caller to specify a count. The count defaults to 1. Pass in a count of 2 or more, and the Loot Table will be processed multiple times, each time decrementing the Weight of the entry selected.

    ID Weight Min Max Step Group
    ace 1 1 1 1 1
    king 1 1 1 1 1
    queen 1 1 1 1 1
    jack 1 1 1 1 1

    GetLoot('cards',2) will get two distinct cards, since the Weight of each card in the table is 1. Within the one call, each time a random entry is selected, it's Weight is decremented, preventing it from being selected again. GetLoot('cards_chips') will yield between 10 and 50 chips, in multiples of 5, and 2 unique cards from the cards table.

    JavaScript

    const cards = [
        LootTableEntry('ace'),
        LootTableEntry('king'),
        LootTableEntry('queen'),
        LootTableEntry('jack'),
    ];
    const cards_chips = [
        LootTableEntry('chips', 1, 10, 50, 5, 1),
        LootTableEntry('@cards(2)', 1, 1, 1, 1, 2),
    ];
    let loot = GetLoot(cards_chips, 1, (id) => (id == 'cards' ? cards : null));

    TypeScript

    const cards: LootTable = [
      LootTableEntry('ace'),
      LootTableEntry('king'),
      LootTableEntry('queen'),
      LootTableEntry('jack'),
    ]
    const cards_chips: LootTable = [
      LootTableEntry('chips', 1, 10, 50, 5, 1),
      LootTableEntry('@cards(2)', 1, 1, 1, 1, 2),
    ]
    let loot = GetLoot(cards_chips, 1, (id) => (id == 'cards' ? cards : null))

    To reference another Loot Table, and specify a count, follow the @id with the count in parenthesis (n), for example: @cards(2)

    Summarize a Loot Table

    With nested loot tables, and data-driven design, it can be hard to tell what might a given loot table yield. To get a flattened summary of a loot table, with just the id, min, and max properties, but no nested references, there is a helper function called LootTableSummaryAsync.

    Call LootTableSummaryAsync to see what the possible yields are from a loot table. The concept of multiple draws without replacement is not taken into account. The summarization process basically combines groups by taking the smallest min and largest max of the group, then sums mins and maxes across groups.

    Install

    npm i loot-table-advanced

    DownloadsWeekly Downloads

    428

    Version

    1.4.2

    License

    MIT

    Unpacked Size

    27.5 kB

    Total Files

    5

    Last publish

    Collaborators

    • nimaimalle