Module:Iteminfo

From Terraria Wiki
Jump to navigation Jump to search
Important.svg
CAUTION: Terraria Wiki code is complex!!!
If you want to use this code on another wiki, wiki.gg staff are not able to assist you.
Please consider picking a different wiki to adapt code from, or making your own templates!
Remember that content on a wiki is more important than fancy formatting.
Lua.svg Documentation The documentation below is transcluded from Module:Iteminfo/doc. (edit | history)

This module provides the functionality of the {{iteminfo}} template. It is used to dynamically and reliably obtain an item's stats. It takes its data directly from the source code, facilitating display of stats without having to change them in case of updates. However, this also makes the module unsuitable for content that is intended to be static, such as the History section.

This module relies entirely on the database Module:Iteminfo/data. The database is currently synchronized with the Desktop version Desktop version 1.4.5.4 of Terraria.

Usage

Wikitext

The module can be called from wikitext with the functions listed below.

getInfo

{{#invoke:Iteminfo| getInfo | id = <item ID> | prefix = <variable name prefix> | stat = <stat(s) to fetch> }}

Retrieves all information about the given item (ID 1 through 6144; though note that some IDs are unused or deprecated and thus invalid – check isValidId) and stores it as dplvars. This function merely fills the variables; it does not produce any output itself. Access the information via the variables. They are named _iteminfo_<stat>, so to display e.g. the damage stat of the item (see full list of stats below), use {{#dplvar:_iteminfo_damage}} after invoking this function.

The default variable prefix is _iteminfo_. It can be changed to a custom value using the prefix parameter.

By default, this function fetches the values of all stats for the item. The optional stat parameter can be used to limit this to one stat or multiple stats (separated with a slash (/)).

In addition, this function sets another variable called _fields (_iteminfo__fields with the default prefix). It contains the names of all stats in a random order, separated with slashes. If the stat parameter is used, then it only contains the stat names specified in that parameter.

Examples
Code Result
{{#invoke:Iteminfo|getInfo|id=757}}
* damage = {{#dplvar:_iteminfo_damage}}
* knockBack = {{#dplvar:_iteminfo_knockBack}}
  • damage = 85
  • knockBack = 6.5
{{#invoke:Iteminfo|getInfo|id=757|prefix=mycustomprefix_}}
* damage = {{#dplvar:mycustomprefix_damage}}
* knockBack = {{#dplvar:mycustomprefix_knockBack}}
  • damage = 85
  • knockBack = 6.5
{{#invoke:Iteminfo|getInfo|id=757|prefix=myprefix2_|stat=damage/knockBack}}
* damage = {{#dplvar:myprefix2_damage}}
* knockBack = {{#dplvar:myprefix2_knockBack}}
* rare = {{#dplvar:myprefix2_rare}}
  • damage = 85
  • knockBack = 6.5
  • rare =
{{#invoke:Iteminfo|getInfo|id=757}}
{{#dplvar:_iteminfo__fields}}

knockBack/axe/stringColor/magic/pick/accessory/shieldSlot/shopCustomPrice/createWall/holdStyle/autoReuse/defense/hairDye/craftable/vanity/maxStack/crit/noUseGraphic/beardSlot/scale/makeNPC/placeStyle/uniqueStack/voiceSlot/prefix/notAmmo/UseSound/sacrifices/armorPenetration/paint/legSlot/alpha/bodySlot/wingSlot/buffTime/buffType/manaIncrease/mech/glowMask/lifeRegen/paintCoating/tileWand/material/frontSlot/handOffSlot/noWet/handOnSlot/useTurn/potion/shootSpeed/useStyle/value/shoeSlot/width/expert/shoot/backSlot/healLife/cartTrack/headSlot/useTime/ranged/flame/healMana/consumable/name/sentry/height/tileBoost/useAnimation/reuseDelay/questItem/rare/bait/dye/rarity/hasVanityEffects/isAShopItem/shopSpecialCurrency/mountType/useAmmo/noMelee/shootsEveryUse/ammo/balloonSlot/internalName/damage/melee/type/neckSlot/createTile/faceSlot/hammer/waistSlot/fishingPole/summon/mana/chlorophyteExtractinatorConsumable/channel/tooltipContext/bonusTagDamage/DD2Summon/buy

Also see {{item stats table}} for a convenient table of an item's stats.

getStat

{{#invoke:Iteminfo| getStat | id = <item ID> | stat = <stat> | raw = y/yes | cate/category/cat = y/yes | format = y/yes }}

Displays the value of a single stat of the given item (ID 1 through 6144; though note that some IDs are unused or deprecated and thus invalid – check isValidId).

By default the value is processed to make it useful for wiki purposes. For instance, with |stat=buffTime the value is formatted using {{duration}}. Using |raw=yes disables this processing and returns the value exactly as it exists in the source code. That can be useful for further calculations, for example.

The processing of rarity stats (|stat=rare) consists of transcluding {{rare}}. By default that template is transcluded with |category=no, which can be overridden by passing |category=yes in this module.

The format parameter causes the result of this function to be wrapped in the magic word {{formatnum:}} (even if |raw=yes is used).

This function is generally only intended to be called from the {{iteminfo}} template.

v

{{#invoke:Iteminfo| v }}

Displays the Terraria version with which the database is currently synchronized.

Examples
Code Result
{{#invoke:Iteminfo|v}} 1.4.5.4

maxId

{{#invoke:Iteminfo| maxId }}

Displays the largest existing item ID. This function is generally only intended to be called from the {{iteminfo/maxId}} template.

Examples
Code Result
{{#invoke:Iteminfo|maxId}} 6144
{{itemNameFromId|{{#invoke:Iteminfo|maxId}}}} Music Box (Skeletron)

isValidId

{{#invoke:Iteminfo| isValidId | <item ID> | includeUnused = y/yes }}

Displays 1 if the provided item ID is valid and 0 if it is not valid. An item ID is considered valid by this function if it is within the bounds of existing item IDs (1 through 6144) and is not marked as unused. With |includeUnused=yes, item IDs marked as unused are also considered valid.

  • Examples
    Code Result
    {{#invoke:Iteminfo|isValidId|42}} 1
    {{#invoke:Iteminfo|isValidId|8000}} 0
    {{#invoke:Iteminfo|isValidId|2772}} 0
    {{#invoke:Iteminfo|isValidId|2772|includeUnused=yes}} 1

    researchableItems

    {{#invoke:Iteminfo| researchableItems }}

    Displays the count of items that can be researched in Journey Mode.

    Examples
    Code Result
    {{#invoke:Iteminfo|researchableItems}} 6087

    Other modules

    The module can be called from another module with the functions listed below.

    getItemInfo

    require('Module:Iteminfo').getItemInfo(<item ID>)

    Returns a table with all stats of the given item. Note that the item ID argument must be an integer, not a string.

    Examples
    Code Variable result
    local iteminfo = require('Module:Iteminfo')
    local result = iteminfo.getItemInfo(757)
    
    {
        ["DD2Summon"] = false,
        ["UseSound"] = "Item_1",
        ["accessory"] = false,
        ["active"] = true,
        ["alpha"] = 0,
        ["ammo"] = 0,
        ["autoReuse"] = true,
        ["axe"] = 0,
        -- ...
    	-- (rest omitted for brevity)
    }
    

    getItemStat

    require('Module:Iteminfo').getItemStat(<item ID>, '<stat>')

    Returns the value of a single stat of the given item. Note that the item ID argument must be an integer, not a string. No processing is done by this function; the value is returned exactly as it exists in the source code.

    Examples
    Code Variable result
    local iteminfo = require('Module:Iteminfo')
    local result = iteminfo.getItemStat(757, 'damage')
    
    85
    
    local iteminfo = require('Module:Iteminfo')
    local result = iteminfo.getItemStat(757, 'knockBack')
    
    6.5
    

    info.version

    require('Module:Iteminfo').info.version

    Returns the Terraria version with which the database is currently synchronized. Note that this is a simple string, not a function.

    Examples
    Code Variable result
    local iteminfo = require('Module:Iteminfo')
    local result = iteminfo.info.version
    
    '1.4.4.9'
    

    info.IDs.min

    require('Module:Iteminfo').info.IDs.min

    Returns the lowest valid item ID. Note that this is a simple integer, not a function.

    Examples
    Code Variable result
    local iteminfo = require('Module:Iteminfo')
    local result = iteminfo.info.IDs.min
    
    1
    

    info.IDs.max

    require('Module:Iteminfo').info.IDs.max

    Returns the largest valid item ID. Note that this is a simple integer, not a function.

    Examples
    Code Variable result
    local iteminfo = require('Module:Iteminfo')
    local result = iteminfo.info.IDs.max
    
    5455
    

    info.IDs.isValid

    require('Module:Iteminfo').info.IDs.isValid(<item ID>)

    Confirms whether or not the provided item ID is valid. Note that the item ID argument must be an integer, not a string.

    An item ID is considered valid by this function if it is within the bounds of existing item IDs (1 through 6144) and is not marked as unused. Use the alternative version of this function, info.IDs.isValidWithUnused, to consider item IDs valid that are marked as unused.

    Examples
    Code Variable result
    local iteminfo = require('Module:Iteminfo')
    local result = iteminfo.info.IDs.isValid(42)
    
    true
    
    local iteminfo = require('Module:Iteminfo')
    local result = iteminfo.info.IDs.isValid(42000)
    
    false
    
    local iteminfo = require('Module:Iteminfo')
    local result = iteminfo.info.IDs.isValid(2772)
    
    false
    
    local iteminfo = require('Module:Iteminfo')
    local result = iteminfo.info.IDs.isValidWithUnused(2772)
    
    true
    

    Stats

    All available stats are listed below. Please note that not all of them are used – see the "Notes" column of each row.

    Stat Default value Example value Notes
    type 0 42 Item ID. This will be identical to the item ID specified in the module invocation, so long as that ID is valid. Otherwise, this value will be blank.
    internalName None AntlionClaw Internal item name.
    name Terra Blade English item name.
    You can also use {{itemNameFromId|<item ID>}} to retrieve this info.
    ToolTip This value is currently always empty. It is reserved for the future.
    Use {{itemTooltip}} to retrieve tooltips.
    accessory 1 If set, then the item is an accessory.
    alpha 0 30
    ammo 0 40 Ammo ID (used in the field useAmmo). (not only, e.g. 353, 154)
    autoReuse 1 If set, then the item is capable of autoswing.
    axe 0 14 Axe power, 1 ≙ 5%. For example, a value of 23 means that the item's axe power is 115%.
    backSlot -1 24 Back slot ID.
    bait 0 20 Bait power, in percent. For example, a value of 50 means that the item's bait power is 50%.
    balloonSlot -1 9 Balloon slot ID.
    beardSlot -1 2 Beard slot ID.
    bodySlot -1 68 Body (waist) slot ID.
    buffTime 0 36000 Time that the buff granted by the item will be in effect, in ticks[1]. For example, a value of 14400 means that the buff will be in effect for 14400 ticks, which is equal to 240 seconds (14400/60 = 240) or 4 minutes (14400/3600 = 4).
    buffType 0 104 Buff ID of the buff granted by the item.
    cartTrack 1 If set, then the item is a Minecart Track (including Pressure Plate Track and Booster Track).
    channel 1 If set, then the item can/needs to be used continuously ("channeling cast"); this is different from autoswing, though! Is set for flails and yoyos, chainsaws and drills, Magic Missile and its upgrades, Dirt Rod, Piranha Gun, Chlorophyte Jackhammer, Laser Machinegun, Charged Blaster Cannon, Flying Knife, Medusa Head, Arkhalis, Portal Gun, Vortex Beater, Phantasm, The Grand Design, Last Prism, Sleepy Octopod, Ghastly Glaive, Phantom Phoenix, Sky Dragon's Fury. Is also set for certain pet/light pet/mount-summoning items, since they will continuously be in effect.
    consumable 1 If set, then the item is consumable, which means that it can (but not necessarily must) be used in a manner that causes it to leave the player's inventory. One item is removed from the stack each time the item is used. Crucially, this stat is distinct from the tooltip label "Consumable" that is displayed in-game.
    craftable 1 If set, then the item can be crafted.
    You can also use {{recipes/exist|result=<item name>}} to retrieve this info.
    createTile -1 104 Tile ID of the tile that the item produces when placed. placeStyle is that tile's sub ID.
    placeStyle 0 24
    createWall -1 253 Wall ID of the wall that the item produces when placed.
    crit 0 10 Critical strike chance that is added to the base 4%, in percent. For example, a value of 2 means that the item's critical strike chance is 6%; a value of 4 means that the item's critical strike chance is 8%.
    damage -1 53 Damage.
    DD2Summon 1 If set, then the item is one of the Tavernkeep's sentry-summoning weapons.
    defense 0 13 Defense.
    dye 0 1 If non-zero, then the item is a dye.
    expert 1 If set, then the item's rarity is displayed as Rainbow (Rarity level: Expert) in-game.
    faceSlot -1 19 Face slot ID.
    fishingPole 0 35 Fishing Power, in percent. For example, a value of 27 means that the item's Fishing Power is 27%.
    flame 1 Is set for each kind of Torch and for Water, Peace, Platinum, Shadow, and regular Candles. Interestingly, it is also set for the Brand of the Inferno and Nightglow.
    frontSlot -1 3 Front slot ID.
    glowMask -1 238
    hairDye -1 1 Is set to 0 for the Hair Dye Remover and 1 for other Hair Dyes.
    hammer 0 45 Hammer power, in percent. For example, a value of 90 means that the item's hammer power is 90%.
    handOffSlot -1 7 Hand-off slot ID.
    handOnSlot -1 12 Hand-on slot ID.
    hasVanityEffects 1 Is set for Music Boxes, strings, Golf Balls, Critter Shampoo, Rainbow Cursor, Moon Charm and Neptune's Shell as well as their upgrades, Yoraiz0r's Scowl, Leinfors' Luxury Shampoo, Angel Halo, Fake Unicorn Horn, Hellfire Treads, Royal Scepter, Terraspark Boots, Inner Tube, Bundle of Horseshoe Balloons, and Radio Thing.
    headSlot -1 219 Head slot ID.
    healLife 0 100 Number of health points restored by the item when used.
    healMana 0 50 Number of mana points restored by the item when used.
    height 0 40 Height of the item sprite, in pixels.
    holdStyle 0 2 How the item is held by the player when used or selected in the inventory. See Use Style IDs.
    knockBack 0 3.5 Knockback.
    legSlot -1 205 Leg slot ID.
    lifeRegen 0 2 Is set for the Band of Regeneration and Charm of Myths.
    makeNPC 0 616 If non-zero, then this value is the NPC ID of the NPC spawned by the item when used. For example, a value of 46 means that the item will spawn a Bunny NPC when used.
    mana 0 5 Number of mana points consumed by the item upon use.
    material 1 If set, then the item is a crafting material.
    You can also use {{recipes/exist|ingredient=<item name>}} to retrieve this info.
    maxStack 9999 9999 Maximum stack limit.
    mech 1 If set, then the item is a mechanism, which means that it shows wire and Actuators when held.
    melee 1 If set, then the item deals melee damage.
    magic 1 If set, then the item deals magic damage.
    ranged 1 If set, then the item deals ranged damage.
    summon 1 If set, then the item deals summon damage.
    mountType -1 6 Mount ID of the mount summoned by the item when used.
    netID
    neckSlot -1 8 Neck slot ID.
    noMelee 1 If set, then the item is not allowed to deal damage with its sprite. Typically set for ranged weapons, which rely on their projectiles to deal damage, instead.
    noUseGraphic 1 If set, then the item's sprite is drawn while it is in use. Is set for thrown weapons like Dynamite, because they are immediately tossed to the ground to create the illusion of being used.
    noWet 1 If set, then the item cannot be held/placed underwater: Unicorn on a Stick, every kind of Candle, and every kind of Torch (without Cursed and Ichor Torch). However, is also set for timers which can be placed underwater.
    notAmmo 1 Is only set for coins, Sand Blocks, and Ale. Aside from Ale, these share the trait of not being able to be placed in the ammo slots of the inventory, even though they are used as ammunition. Ale can be placed in those slots, though.
    paint 0 7 If non-zero, then this value is the item's paint ID.
    paintCoating 0 2 If non-zero, then this value is the item's coating ID.
    pick 0 65 Pickaxe power, in percent. For example, a value of 150 means that the item's pickaxe power is 150%.
    potion 1 If set, then no other items with this attribute may be used until the cooldown elapses. Is set for healing items.
    questItem 1 Is set for quest fish.
    rare 0 3 Rarity of the item. Not valid if expert is set, as that makes the item have the Rainbow (Rarity level: Expert) rarity.
    rarity 0 3 "Internal" rarity of the item. Only valid and non-zero for Expert-exclusive items; see Treasure Bag § Internal rarity.
    reuseDelay 0 5 Use delay, i.e. time in ticks[1] before the item may be used again. Is set for Clockwork Assault Rifle, Medusa Head, Last Prism, Sky Fracture, Betsy's Wrath, and various summon weapons.
    sacrifices 0 100 Required number to research the item.
    scale 1 0.85
    sentry 1 If set, then the item is a sentry-summoning weapon.
    shieldSlot -1 4 Shield slot ID.
    shoeSlot -1 16 Shoe slot ID.
    shopCustomPrice 60 Purchase price, in Defender Medals. Is only set for items which are purchased with Defender Medals.
    shoot 0 377 If non-zero, then this value is the projectile ID of the projectile fired by the item.
    shootSpeed 0 14 Velocity of the projectile fired by the item, in pixels per tick[1]. For example, a value of 6 means that the projectile initially moves at 31 mph (22.5 tiles/second). Note that this is merely the initial velocity of the projectile upon spawning; it may change afterwards depending on the projectile's behavior (such as the Demon Scythe, which speeds up).
    shootsEveryUse 1 Is set for certain projectile melee weapons.
    stringColor 13 String ID.
    tileBoost 0 -1 Range bonus, in tiles. For example, a value of 4 means that the item's range is increased by 4 tiles. It is also stated in the tooltip of the item as, e.g., "+4 range".
    tileWand -1 1124 Item ID of the block placed by the item, for block-placing wands.
    uniqueStack 1 Is set for quest fish. See Fishing § Fishing quests for details regarding the special quality of these items.
    useAmmo 0 97 Type of ammunition the item uses. 23 for Gel, 40 for Arrow, 71 for Coin, 75 for Fallen Star, 97 for Bullet, 169 for Sand, 283 for Dart, 771 for Rocket, 780 for Solution, 931 for Flare, 949 for Snowball, 1261 for Stynger Bolt, 1783 for Candy Corn, 1785 for Jack 'O Lantern, 1836 for Stake, 3108 for Nail.
    useAnimation 100 12 How long it takes the animation to play for the item, in ticks[1]. An interesting quirk is that if the useTime is lower than the useAnimation, it will be activated one or more times per use (e.g. Golden Shower). If the item is an auto-swinging sword, then the use time of the item (that is displayed in the game and on the wiki) is useAnimation - 1.
    UseSound Item_95 File name of the sound effect that is played when the item is used. May also be a comma-separated list, if the item has multiple sounds. File extensions are not included but are usually .wav. Note that the listed sound is only the base sound; it might be played with modified pitch and volume in-game.
    useStyle 0 5 How the item is held by the player when used or selected in the inventory. See Use Style IDs.
    useTime 100 15 Tool speed for tools, (internal) use time for other items. How long it takes to use the item, in ticks[1]. While the item is in use, the player cannot take any other actions.
    useTurn 1 If set, then the player will turn to face the direction they are moving in when the item is used. If this stat is not set, then the player cannot switch directions while the item is in use. For example, the player can switch directions while using a pickaxe (useTurn set), but not while using a spear (useTurn not set).
    value 0 500000 Purchase price, in Copper Coins. Note that this stat may be set even if the item cannot be purchased with coins (i.e. with Defender Medals instead). It may also be set if the item cannot be purchased at all. There is no dedicated stat for the sell value of an item, as it is always equal to 1/5 (20%) of its purchase price (value), rounded down (though never rounding down to less than 1).
    vanity 1 If set, then the item is a vanity item.
    waistSlot -1 16 Waist slot ID.
    width 0 40 Width of the item sprite, in pixels.
    wingSlot -1 39 Wing slot ID.

    See also

    Footnotes

    1. 1.0 1.1 1.2 1.3 1.4 A tick is a time unit countable by the software. Most of Terraria's updating logic happens every tick. A tick has the length of 1/60th of a second, hence there are 60 ticks in a second and 3600 ticks in a minute.

    --------------------------------------------------------------------------------
    --
    -- =============================================================================
    --
    -- Module:Iteminfo
    --
    -- Retrieval of various statistics about items
    --
    -- =============================================================================
    --
    -- Code annotations:
    -- This module is documented according to LuaCATS (Lua Comment and Type System).
    -- LuaCATS comments are prefixed with three dashes (---) and use Markdown syntax.
    -- For a full list of annotations, see the following link:
    -- https://luals.github.io/wiki/annotations/
    --
    --------------------------------------------------------------------------------
    
    
    local trim = mw.text.trim
    local idSets = require('Module:Iteminfo/idSets')
    local itemNames = require('Module:ItemNames').getData
    local percent = require('Module:Percent').format
    
    ---A cached version of the current frame, the interface to the parser.
    local currentFrame
    
    ---Item stats database. The database is cached; see [[Module:Iteminfo/datacache]]
    ---for details about what this means.
    ---@type {[integer]: boolean|string|number, ['_generated'|'_terrariaversion']: string}
    local data = mw.loadData('Module:Iteminfo/loaddata')
    
    ---Meta information about the item stats database.
    local info = { IDs = {} }
    
    ---Terraria version that the database is synchronized with.
    ---@type string
    info.version = data['_terrariaversion']
    
    ---Lowest valid item ID.
    info.IDs.min = 1
    
    ---Highest valid item ID.
    info.IDs.max = 6144
    
    ---Check if the given `id` is a valid item ID. IDs marked as "unused" are
    ---still considered *valid* by this function.
    ---@param id integer
    ---@return boolean
    info.IDs.isValidWithUnused = function(id)
    	return id ~= nil and type(id) == 'number' and id >= info.IDs.min and id <= info.IDs.max
    end
    
    ---Check if the given `id` is a valid item ID. IDs marked as "unused" are
    ---considered *invalid* by this function.
    ---@param id integer
    ---@return boolean
    info.IDs.isValid = function(id)
    	return info.IDs.isValidWithUnused(id) and idSets.getValue('Unused', id) ~= true
    end
    
    ---Return a trimmed version of the value of the template parameter with the specified `key`.
    ---Return `nil` if the parameter is empty or unset.
    ---@param key string|integer
    ---@return string?
    local function getArg(key)
    	local value = currentFrame.args[key]
    	if not value then
    		return nil
    	end
    	value = trim(value)
    	if value == '' then
    		return nil
    	end
    	return value
    end
    
    ---Split the `str` on each `div` in it and return the result as a table. Original
    ---version credit: http://richard.warburton.it. This version trims each substring.
    ---@param div string
    ---@param str string
    ---@return string[]? strExploded Is `nil` if `div` is an empty string
    local function explode(div, str)
    	if (div=='') then return nil end
    	local pos,arr = 0,{}
    	-- for each divider found
    	for st,sp in function() return string.find(str,div,pos,true) end do
    		arr[#arr+1] = trim(string.sub(str,pos,st-1)) -- Attach chars left of current divider
    		pos = sp+1 -- Jump past current divider
    	end
    	arr[#arr+1] = trim(string.sub(str,pos)) -- Attach chars right of last divider
    	return arr
    end
    
    ---Retrieve the value of the `stat` for the given `itemid` from the database.
    ---@param itemid integer
    ---@param stat string
    ---@return string|number|true|nil
    local function getStat(itemid, stat)
    	return data[itemid][stat] or data[0][stat] or nil -- "or nil" will convert "false" to "nil"
    end
    
    ---Aliases for stat names. They are case-sensitive.
    local statnameAliases = {
    	-- accessory
    	['acc'] = 'accessory',
    
    	-- autoReuse
    	['autoreuse'] = 'autoReuse',
    	['autoswing'] = 'autoReuse',
    	['auto'] = 'autoReuse',
    
    	-- axe
    	['axe power'] = 'axe',
    	['axepower'] = 'axe',
    
    	-- bait
    	['bait power'] = 'bait',
    	['baitpower'] = 'bait',
    
    	-- bodySlot
    	['body slot'] = 'bodySlot',
    	['bodyslot'] = 'bodySlot',
    
    	-- buffTime
    	['buff duration'] = 'buffTime',
    	['buffduration'] = 'buffTime',
    	['bufftime'] = 'buffTime',
    
    	-- buffType
    	['buff id'] = 'buffType',
    	['buffid'] = 'buffType',
    	['bufftype'] = 'buffType',
    
    	-- cartTrack
    	['carttrack'] = 'cartTrack',
    
    	-- createTile
    	['createtile'] = 'createTile',
    	['tile id'] = 'createTile',
    	['tileid'] = 'createTile',
    	['tile'] = 'createTile',
    
    	-- createWall
    	['createwall'] = 'createWall',
    	['wall id'] = 'createWall',
    	['wallid'] = 'createWall',
    	['wall'] = 'createWall',
    
    	-- crit
    	['critical'] = 'crit',
    
    	-- damage
    	['dmg'] = 'damage',
    
    	-- DD2Summon
    	['dd2summon'] = 'DD2Summon',
    
    	-- fishingPole
    	['fishing power'] = 'fishingPole',
    	['fishingpole'] = 'fishingPole',
    	['fishingpower'] = 'fishingPole',
    	['fishing'] = 'fishingPole',
    
    	-- hairDye
    	['hair dye'] = 'hairDye',
    	['hairdye'] = 'hairDye',
    
    	-- hammer
    	['hammer power'] = 'hammer',
    	['hammerpower'] = 'hammer',
    
    	-- headSlot
    	['head slot'] = 'headSlot',
    	['headslot'] = 'headSlot',
    
    	-- healLife
    	['heallife'] = 'healLife',
    
    	-- healMana
    	['healmana'] = 'healMana',
    
    	-- holdStyle
    	['holdstyle'] = 'holdStyle',
    
    	-- internalName
    	['internal name'] = 'internalName',
    	['internalname'] = 'internalName',
    
    	-- knockBack
    	['kb'] = 'knockBack',
    	['knockback'] = 'knockBack',
    
    	-- legSlot
    	['leg slot'] = 'legSlot',
    	['legslot'] = 'legSlot',
    
    	-- lifeRegen
    	['liferegen'] = 'lifeRegen',
    
    	-- makeNPC
    	['makenpc'] = 'makeNPC',
    
    	-- maxStack
    	['maxstack'] = 'maxStack',
    	['stack'] = 'maxStack',
    
    	-- mountType
    	['mount id'] = 'mountType',
    	['mountid'] = 'mountType',
    	['mounttype'] = 'mountType',
    	['mount'] = 'mountType',
    
    	-- noMelee
    	['nomelee'] = 'noMelee',
    
    	-- notAmmo
    	['notammo'] = 'notAmmo',
    
    	-- noUseGraphic
    	['nousegraphic'] = 'noUseGraphic',
    
    	-- noWet
    	['nowet'] = 'noWet',
    
    	-- pick
    	['pick power'] = 'pick',
    	['pickpower'] = 'pick',
    	['pickaxe power'] = 'pick',
    	['pickaxepower'] = 'pick',
    	['pickaxe'] = 'pick',
    
    	-- placeStyle
    	['placestyle'] = 'placeStyle',
    	['tile sub id'] = 'placeStyle',
    	['tile subid'] = 'placeStyle',
    	['tilesubid'] = 'placeStyle',
    
    	-- questItem
    	['questitem'] = 'questItem',
    
    	-- rare
    	['rarity'] = 'rare',
    
    	-- reuseDelay
    	['reusedelay'] = 'reuseDelay',
    	['use delay'] = 'reuseDelay',
    	['usedelay'] = 'reuseDelay',
    
    	-- sacrifices
    	['research'] = 'sacrifices',
    
    	-- shoot
    	['projectileid'] = 'shoot',
    	['projectile id'] = 'shoot',
    
    	-- shootSpeed
    	['shootspeed'] = 'shootSpeed',
    	['velocity'] = 'shootSpeed',
    
    	-- stringColor
    	['stringcolor'] = 'stringColor',
    
    	-- tileBoost
    	['range bonus'] = 'tileBoost',
    	['rangebonus'] = 'tileBoost',
    	['tileboost'] = 'tileBoost',
    
    	-- tileWand
    	['tile wand'] = 'tileWand',
    	['tilewand'] = 'tileWand',
    
    	-- ToolTip
    	['tooltip'] = 'ToolTip',
    
    	-- type
    	['id'] = 'type',
    	['item id'] = 'type',
    	['itemid'] = 'type',
    
    	-- uniqueStack
    	['uniquestack'] = 'uniqueStack',
    
    	-- useAmmo
    	['useammo'] = 'useAmmo',
    
    	-- useAnimation
    	['use time'] = 'useAnimation',
    	['useanimation'] = 'useAnimation',
    	['usetime'] = 'useAnimation',
    	['use'] = 'useAnimation',
    
    	-- UseSound
    	['sound'] = 'UseSound',
    	['sounduse'] = 'UseSound',
    	['use sound'] = 'UseSound',
    	['usesound'] = 'UseSound',
    
    	-- useStyle
    	['use style'] = 'useStyle',
    	['usestyle'] = 'useStyle',
    
    	-- useTime
    	['tool speed'] = 'useTime',
    	['toolspeed'] = 'useTime',
    
    	-- useTurn
    	['useturn'] = 'useTurn',
    
    	-- value
    	['sell'] = 'value',
    
    	-- buffName (custom stat, not from the database)
    	['buff name'] = 'buffName',
    	['buffname'] = 'buffName',
    	['buff'] = 'buffName',
    
    	-- buyValue (custom stat, not from the database)
    	['buy'] = 'buyValue',
    	['price'] = 'buyValue',
    }
    
    ---Functions for processing stat values. Each stat is a key in this table and the
    ---value is the function for processing the corresponding values of that stat.
    ---Some stats share processing functions, like hammer power and pickaxe power.
    ---@type table<string, function>
    local proc = {}
    
    ---Format with `{{percent}}` where 1==5% (axe power).
    proc.axe = function(value)
    	return percent((value or 0) * 5 / 100)
    end
    
    ---Consider -1 as invalid/default, and simply return any other value unchanged.
    proc.bodySlot = function(value)
    	return (value == -1) and "" or value
    end
    proc.createTile = proc.bodySlot
    proc.createWall = proc.bodySlot
    proc.damage = proc.bodySlot
    proc.hairDye = proc.bodySlot
    proc.headSlot = proc.bodySlot
    proc.legSlot = proc.bodySlot
    proc.mountType = proc.bodySlot
    proc.tileWand = proc.bodySlot
    
    ---Format with `{{percent}}` where 1==1%.
    proc.bait = function(value)
    	return percent(value / 100)
    end
    proc.fishingPole = proc.bait
    proc.hammer = proc.bait
    proc.pick = proc.bait
    
    ---Format a duration in ticks with `{{duration}}`.
    proc.buffTime = function(value)
    	return currentFrame:expandTemplate{ title = 'duration', args = { (value or 0)/60 } }
    end
    
    ---Fetch the English buff name stat of the item.
    proc.buffName = function(value, itemid)
    	return currentFrame:expandTemplate{ title = 'GetBuffInfo', args = { getStat(itemid, 'buffType'), 'ename' } }
    end
    
    ---Format a critical strike chance value with `{{percent}}`.
    proc.crit = function(value, itemid)
    	if getStat(itemid, 'damage') == -1 then
    		-- item does no damage, so the `crit` stat is the crit chance directly
    		return percent(value / 100)
    	else
    		-- item does do damage, so the stat is the crit chance added to the default 4%
    		return percent((value + 4) / 100)
    	end
    end
    
    ---Determine the damage type of the item and translate it.
    proc.damagetype = function(value, itemid)
    	if getStat(itemid, 'melee') then
    		return currentFrame:expandTemplate{ title = 'l10n', args = { 'GetItemInfo', 'damagetype_melee' } }
    	end
    	if getStat(itemid, 'ranged') then
    		return currentFrame:expandTemplate{ title = 'l10n', args = { 'GetItemInfo', 'damagetype_ranged' } }
    	end
    	if getStat(itemid, 'magic') then
    		return currentFrame:expandTemplate{ title = 'l10n', args = { 'GetItemInfo', 'damagetype_magic' } }
    	end
    	if getStat(itemid, 'summon') then
    		return currentFrame:expandTemplate{ title = 'l10n', args = { 'GetItemInfo', 'damagetype_summon' } }
    	end
    	if getStat(itemid, 'thrown') then
    		return currentFrame:expandTemplate{ title = 'l10n', args = { 'GetItemInfo', 'damagetype_thrown' } }
    	end
    end
    
    ---Format a rarity level with `{{rare}}`.
    proc.rare = function(value)
    	local cate = getArg('cate') or getArg('category') or getArg('cat') or 'no'
    	return currentFrame:expandTemplate{ title = 'rare', args = { (value or 0), cate=cate } }
    end
    
    ---Add a sign to the tile range number and append a translated "range" text.
    proc.tileBoost = function(value)
    	if value ~= 0 then
    		if value > 0 then
    			value = '+' .. tostring(value)
    		else
    			value = tostring(value)
    		end
    		return currentFrame:expandTemplate{ title = 'l10n', args = { 'GetItemInfo', 'tileBoost', ['$tiles$'] = value } }
    	end
    end
    
    ---Return the translated name of some ammo groups, or the English name of a
    ---single ammo item otherwise.
    proc.useAmmo = function(value)
    	if value == 40 or value == 71 or value == 97 or value == 283 or value == 771 or value == 931 then
    		return currentFrame:expandTemplate{ title = 'l10n', args = { 'GetItemInfo', 'ammo' .. tostring(value) } }
    	end
    	return itemNames('itemNameFromId', value)
    end
    
    ---Format with `{{sound}}`.
    proc.UseSound = function(value)
    	local sounds = {}
    	for _, v in pairs(explode(',', value)) do
    		sounds[#sounds+1] = currentFrame:expandTemplate{ title = 'sound', args = { '', v .. '.wav' } }
    	end
    	return table.concat(sounds)
    end
    
    ---Return the translated name of a use style.
    proc.useStyle = function(value)
    	if value == 0 then
    		return
    	end
    	if value >= 1 and value <= 5 then
    		return currentFrame:expandTemplate{ title = 'l10n', args = { 'GetItemInfo', 'usestyle' .. tostring(value) } }
    	end
    	return value
    end
    
    ---Format the item's buy price with `{{coin}}` or `{{dm}}`.
    proc.buyValue = function(value, itemid)
    	local dmValue = getStat(itemid, 'shopCustomPrice')
    	if dmValue then
    		return currentFrame:expandTemplate{ title = 'dm', args = { dmValue } }
    	else
    		return currentFrame:expandTemplate{ title = 'coin', args = { tostring(getStat(itemid, 'value')) .. 'cc' } }
    	end
    end
    
    ---Format a sell value (buy price divided by 5) with `{{coin}}`.
    proc.value = function(value)
    	value = tonumber(value or 0)
    	if value <= 0 then
    		return currentFrame:expandTemplate{ title = 'l10n', args = { 'GetItemInfo', 'noValue' } }
    	end
    	if value < 5 then
    		-- items with value<5 have a sell value of 1, not 0 (contrary to regular rounding)
    		return currentFrame:expandTemplate{ title = 'coin', args = { '1cc' } }
    	else
    		return currentFrame:expandTemplate{ title = 'coin', args = { tostring(math.floor(value/5)) .. 'cc' } }
    	end
    end
    
    --------------------------------------------------------------------------------
    ---Main return object
    local p = {}
    
    ---For other modules: meta information about the item stats database.
    p.info = info
    
    ---For templates: return the Terraria version that the item stats database is
    ---currently synchronized with.
    ---@param frame table Interface to the parser (`mw.frame`)
    ---@return string
    p.v = function(frame)
    	return info.version
    end
    
    ---For templates: return the highest valid item ID.
    ---@param frame table Interface to the parser (`mw.frame`)
    ---@return integer
    p.maxId = function(frame)
    	return info.IDs.max
    end
    
    ---For templates: return count of items that can be researched
    ---@param frame table Interface to the parser (`mw.frame`)
    ---@return integer
    p.researchableItems = function(frame)
    	local researchableItems = 0
    	-- find all items that can be researched (sacrifices!=0)
    	for itemId = info.IDs.min, info.IDs.max do
    		local itemStats = p.getItemInfo(itemId)
    		if itemStats['sacrifices'] ~= 0 then
    			researchableItems = researchableItems + 1
    		end
    	end
    	return researchableItems
    end
    
    ---For templates: check if a given ID is a valid item ID.
    ---@param frame table Interface to the parser (`mw.frame`)
    ---@return integer isValid 1 if valid, 0 if invalid
    p.isValidId = function(frame)
    	currentFrame = frame  -- global frame cache
    	if getArg('includeUnused') then
    		return info.IDs.isValidWithUnused(tonumber(getArg(1)) or 0) and 1 or 0
    	end
    	return info.IDs.isValid(tonumber(getArg(1)) or 0) and 1 or 0
    end
    
    ---For other modules: return a table with all stats of the given item.
    ---@param itemid integer
    ---@return table
    p.getItemInfo = function(itemid)
    	if not data[itemid] then
    		-- no data found for the given ID, fall back to the default stats
    		itemid = 0
    	end
    	local result = {['type'] = itemid}
    	-- copy the default stats to `result`
    	for k, v in pairs(data[0]) do
    		result[k] = v
    	end
    	-- overwrite the default stats with the given item's stats where needed
    	for k, v in pairs(data[itemid]) do
    		result[k] = v
    	end
    	return result
    end
    
    ---For templates: store all stats of the given item as dplvars.
    ---@param frame table Interface to the parser (`mw.frame`)
    p.getInfo = function(frame)
    	currentFrame = frame  -- global frame cache
    
    	local itemid = tonumber(getArg('id')) or tonumber(getArg(1)) or 0
    	local prefix = getArg('prefix') or getArg(2) or '_iteminfo_'
    
    	if not data[itemid] then
    		-- no data found for the given ID, fall back to the default stats
    		itemid = 0
    	end
    
    	local result = {['type'] = itemid}
    	-- copy the default stats to `result`
    	for k, v in pairs(data[0]) do
    		result[k] = v
    	end
    	-- overwrite the default stats with the given item's stats where needed
    	for k, v in pairs(data[itemid]) do
    		result[k] = v
    	end
    
    	---Arguments for the `{{#dplvar:set}}` parser function.
    	local args = {}
    
    	local fieldsArg = getArg('stat') or getArg(3)
    	local fields = {}
    	if fieldsArg then
    		fields = explode('/', fieldsArg)  --[[@as string[] ]]
    	end
    
    	if fieldsArg then
    		for _, v in ipairs(fields) do
    			args[#args + 1] = prefix .. v  -- dplvar key
    			args[#args + 1] = result[statnameAliases[v] or v]  -- dplvar value
    		end
    	else
    		for k, v in pairs(result) do
    			args[#args + 1] = prefix .. k  -- dplvar key
    			args[#args + 1] = v  -- dplvar value
    			fields[#fields + 1] = k
    		end
    	end
    	args[#args + 1] = prefix .. '_fields'
    	args[#args + 1] = table.concat(fields, '/')
    
    	frame:callParserFunction{ name = '#dplvar:set', args = args }
    end
    -- aliases
    p.getinfo = p.getInfo
    p.GetInfo = p.getInfo
    
    ---For other modules: return a single stat of the given item.
    ---@param itemid integer
    ---@param stat string
    ---@return boolean|string|number
    p.getItemStat = function(itemid, stat)
    	if stat == 'count' then
    		-- this is deprecated, p.info.IDs.max should be used directly
    		return info.IDs.max
    	end
    	if not data[itemid] then
    		-- no data found for the given ID, fall back to the default stats
    		itemid = 0
    	end
    	if stat == 'type' then
    		return itemid
    	end
    	return data[itemid][stat] or data[0][stat]
    end
    
    ---For `{{iteminfo}}`: return a single stat of the given item.
    ---@param frame table Interface to the parser (`mw.frame`)
    ---@return string|number|true|nil
    p.getStat = function(frame)
    	currentFrame = frame  -- global frame cache
    
    	local itemid = tonumber(getArg('id')) or tonumber(getArg(1)) or 0
    	local stat = getArg('stat') or getArg(2)
    	if stat == 'sell' and getArg('raw') then
    		-- {{iteminfo|...|sell|raw=yes}} would return the item's raw `value`
    		-- stat, which generally represents the item's buy price, not its sell
    		-- value, so this is forbidden to avoid a counter-intuitive and
    		-- confusing output; also see
    		-- [[Template talk:GetItemInfo#Issue about raw price info display]]
    		return
    	end
    	stat = statnameAliases[stat] or stat
    
    	if not stat then
    		return
    	end
    
    	if not data[itemid] then
    		-- no data found for the given ID, fall back to the default stats
    		itemid = 0
    	end
    
    	if stat == 'type' then
    		return itemid
    	end
    	if stat == 'count' then
    		-- this is deprecated, {{iteminfo/maxId}} should be used
    		return info.IDs.max
    	end
    
    	local result = getStat(itemid, stat)
    	if not getArg('raw') and proc[stat] then
    		-- perform processing of the stat value, unless "|raw=y" is used
    		result = proc[stat](result, itemid)
    	end
    
    	if getArg('format') then
    		result = frame:callParserFunction('formatnum', result)
    	end
    
    	return result
    end
    -- aliases
    p.getstat = p.getStat
    p.GetStat = p.getStat
    
    return p