Модуль:Iteminfo

Материал из Terraria Wiki
Перейти к навигации Перейти к поиску
Important.svg
ВНИМАНИЕ: код шаблонов на Terraria Wiki очень сложный!!!
Если вы хотите использовать этот код на другой вики, сотрудники wiki.gg не смогут вам помочь.
Пожалуйста, рассмотрите вариант использования кода с других вики или создайте свои шаблоны с нуля!
Помните что наполнение вики важнее чем красивый код.
Lua.svg Документация Документация, указанная ниже, находится на странице «Модуль:Iteminfo/док». (править | история)

Этот модуль используется для получения динамических и достоверных характеристик предметов. Он берёт данные напрямую из исходного кода, упрощая отображение характеристик без необходимости их изменения при последующих обновлениях игры.

Он также используется для работы шаблона {{iteminfo}}. Как правило, в статьях вместо модуля должен использоваться именно этот шаблон. В нём содержатся дополнительные утилиты, такие как форматирование вывода и алиасов параметров.

Код модуля на данный момент синхронизирован с версией Terraria 1.4.4.9(Издания для ПК, консолей и мобильных устройств).

Использование

Все характеристики

{{#invoke:iteminfo|getInfo| id = <id предмета> | prefix = <префикс имён переменных для вывода> }}

или

{{#invoke:iteminfo|getInfo| <id предмета> | <префикс имён переменных для вывода> }}

id

ID предмета, должно быть в диапазоне от 1 до 6144. Обратите внимание, что следующие ID устарели и, следовательно, недействительны: от 2772 до 2775, от 2777 до 2780, от 2782 до 2785, 2881, 3273, от 3340 до 3346, от 3462 до 3465, 3750, от 3847 до 3851, 3861 и 3862.

prefix (необязательный)

Префикс для выходной переменной, по умолчанию это _iteminfo_. Например, имя переменной значения по умолчанию это _iteminfo_value. Если используете prefix=my_, то имя переменной должно быть my_value. При использовании этого метода модуль задаёт количество переменных DPL, которые затем, например, можно будет получить при помощи {{#dplvar:_iteminfo_value}}. Этот метод предпочтительно использовать для Lua-скриптов в силу быстроты DPL.

Одна характеристика

{{#invoke:iteminfo|getStat| id = <id предмета> | stat = <название характеристики> }}

или

{{#invoke:iteminfo|getStat| <id предмета> | <название характеристики> }}

id

ID предмета, должно быть в диапазоне от 1 до 6144. Обратите внимание, что следующие ID устарели и, следовательно, недействительны: от 2772 до 2775, от 2777 до 2780, от 2782 до 2785, 2881, 3273, от 3340 до 3346, от 3462 до 3465, 3750, от 3847 до 3851, 3861 и 3862.

stat (необязательный)

Название характеристики, см. таблицу ниже для возможных значений.


Если вы не уверены, что указанный вами ID корректен, проверьте его через {{#dplvar:_iteminfo_type}}. ID отобразится, если оно корректно, иначе значение будет пустым.

Все поля вывода перечислены ниже. Обратите внимание, что не все из них используются; см. примечание к каждой строке. И, пожалуйста, также обращайтесь к документациям по tModLoader и tConfig.

Примечание: Вы можете получить название предмета из идентификатора при помощи {{ItemNameFromId}}.

dplvar
(без префикса)
Значение по умолчанию Пример
(здесь: ID = 757)
Примечание
type 0 757 ID предмета. Если ID как аргумент задан корректно, то значение будет выведено числом. Иначе значение будет пустым.
internalName TerraBlade Внутреннее название предмета.
name Terra Blade Название предмета на английском языке.
lname Переведённое название предмета.
DD2Summon Если имеется, то это значит, что это призывающее стражей оружие от трактирщика(Издания для ПК, консолей и мобильных устройств).
ToolTip На данный момент всегда пусто. Сохранено для использования в будущем. Можете использовать {{itemTooltip}} для вывода подсказок.
material 1 Если имеется, то этот предмет — материал. Вы также можете использовать {{#invoke:Recipes|exist|ingredient=<название предмета>}}, чтобы отобразить эту информацию.
accessory Если имеется, то этот предмет — аксессуар.
alpha 0 0
ammo 0 0 ID боеприпаса (используется в поле useAmmo) и не только, например 353, 154
autoReuse 1 Если имеется, то у этого предмета есть автовзмах.
axe 0 0 Мощность топора. 1 ≙ 5%, например, axe = 23 означает, что мощность топора у этого предмета равна 115%.
backSlot -1 -1 ID ячейки со спины. См. «Идентификаторы брони» § «Аксессуары».
bait 0 0 Качество наживки (в процентах), например, bait = 50 означает, что качество наживки у этого предмета равно 50%.
balloonSlot -1 -1 ID ячейки шарика. См. «Идентификаторы брони» § «Аксессуары».
bodySlot -1 -1 ID ячейки тела (груди). См. «Идентификаторы брони».
buffTime 0 0 Время действия бафа, который дает этот предмет, в тиках (1 тик = 1/60 секунды и 1/3600 минуты). Например, если buffTime = 14400, то это означает, что баф будет действовать в течение 240 секунд (14400/60 = 240), что равняется четырём минутам (14400/3600 = 4).
buffType 0 0 ID бафа, накладываемого этим предметом.
canBePlacedInVanityRegardlessOfConditions
cartTrack Задаётся для рельс.
channel Если имеется, то это означает, что предмет можно/нужно использовать постоянно (здесь имеется в виду не автовзмах, а именно возможность удерживания предмета!). Задаётся для кистеней и йо-йо, бензопил и буров, волшебной ракеты и её аналогов, жезла земли, пираньевой пушки, хлорофитового отбойного молотка, лазерного пулемёта, заряжаемой бластер-пушки, летающего ножа, головы Медузы, Архалиса, портальной пушки, «Вихревого загонщика», «Фантома», «Высшего замысла», последней призмы, сонного осьмижезла, жуткой глефы, «Призрачного феникса», «Ярости небесного дракона». Также задаётся для некоторых предметов, призывающих питомцев/освещающих питомцев/средства передвижения, так как они действуют постоянно.
consumable Задаётся для предметов, которые расходуются (все они перечислены в категории «Расходуемые предметы»). Обратите внимание, что они отличаются от внутриигрового понятия слова «расходуемые»! См. для ясности категорию «Расходуемые предметы» . Если данный атрибут имеет значение True, то один предмет из стопки будет удалён при использовании.
craftable 1 Если имеется, то этот предмет может быть создан. Вы также можете использовать {{#invoke:Recipes|exist|result=<название предмета>}}, чтобы отобразить эту информацию.
createTile -1 -1 ID тайла этого предмета, который создаётся при размещении. placeStyle — это подкатегория ID тайла.
placeStyle 0 0
createWall -1 -1 ID стены этого предмета, который создаётся при размещении.
crit 0 0 Шанс критического удара (в процентах), который добавляется к основному шансу в 4%, например, crit = 2 означает, что шанс критического удара этого предмета равен 6%; crit = 4 означает, что шанс критического удара этого предмета равен 8%.
damage -1 85 Базовый урон предмета.
defense 0 0 Уровень защиты, который даёт этот предмет.
dye 0 0 Если значение не равно нулю, то этот предмет — краситель.
expert Если имеется, то этот предмет будет отображаться с уровнем редкости Класс редкости: Радужный.
faceSlot -1 -1 ID ячейки на лице. См. «Идентификаторы брони» § «Аксессуары».
fishingPole 0 0 Навык рыбной ловли предмета (в процентах), например, fishingPole = 27 означает, что навык рыбной ловли этого предмета равен 27%.
flame Задаётся для каждого вида факела, а также для водяной, мирной, платиновой и обычной свечи. Что интересно, оно также задаётся для адского меча.
frontSlot -1 -1 ID ячейки спереди. См. «Идентификаторы брони» § «Аксессуары».
glowMask -1 -1
hairDye -1 -1 Значение равное нулю задаётся для смывателя краски для волос, а положительные числа — для красок для волос.
hammer 0 0 Мощность молота (в процентах), например, hammer = 90 означает, что мощность молота предмета равна 90%.
handOffSlot -1 -1 ID ячейки свободной руки. См. «Идентификаторы брони» § «Аксессуары».
handOnSlot -1 -1 ID ячейки занятой руки. См. «Идентификаторы брони» § «Аксессуары».
headSlot -1 -1 ID ячейки головы. См. Идентификаторы брони.
healLife 0 0 Количество очков здоровья, которое восстанавливает предмет при использовании.
healMana 0 0 Количество очков маны, которое восстанавливает предмет при использовании.
holdStyle 0 0 Может быть только в виде значения от 0 до 3. Значение 1 задаётся для каждого вида факела, а также для водяной, мирной, платиновой и обычной свечи, липкой светящейся палочки, прыгучей светящейся палочки, светящейся палочки спелеолога и обычной светящейся палочки, эля, единорога на палке, сигнальной ракетницы, зефира на палочке, таинства туманности. Значение 2 задаётся для дыхательной трубки, зонтика. Значение 3 задаётся для магической арфы.
knockBack 0 6.5 Значение отбрасывания предмета.
legSlot -1 -1 ID ячейки ноги. См. Идентификаторы брони.
lifeRegen 0 0 Может быть только в виде 0 или 1. Значение 1 задаётся для браслета восстановления и амулета мифов.
makeNPC 0 0 Если значение не равно нулю, то это означает, что предмет используется для призыва существ (NPC). Значение соответствует ID существа, которое призывается.
mana 0 0 Количество маны, которое предмет потребляет при использовании.
maxStack 1 9999 Максимальное количество в стопке.
mech Если имеется, то этот предмет является механизмом, что также означает, что он отображает провода и актуаторы, если находится в руке.
melee 1 Если имеется, то этот предмет наносит урон в ближнем бою.
magic Если имеется, то этот предмет наносит магический урон.
ranged Если имеется, то этот предмет наносит урон в дальнем бою.
summon Если имеется, то этот предмет наносит урон от призванного существа.
thrown Если имеется, то этот предмет наносит урон при броске.
mountType -1 -1 ID средства передвижения, которое призывает этот предмет при использовании.
netID 0
neckSlot -1 -1 ID ячейки на шее. См. «Идентификаторы брони» § «Аксессуары».
noMelee 1 Разрешено ли этому предмету наносить урон своим спрайтом. Обычно ставится значение true для оружия дальнего боя, которое вместо этого будет полагаться на свои снаряды для нанесения урона.
noUseGraphic Отрисовывается ли спрайт этого элемента, когда он используется. Используется в таком метательном оружии, как динамит, потому что его тут же бросают на землю, чтобы создать иллюзию того, что его используют.
noWet Если имеется, то предмет нельзя держать в руках/размещать под водой: единорог на палке, каждый вид свечи и каждый вид факела (кроме проклятого и ихорного). Тем не менее, он также задаётся для таймеров, которые могут размещаться под водой.
notAmmo Задаётся только для монет, эля, проводов. Помимо проводов, их объединяет ещё то, что их нельзя размещать в ячейку боеприпасов инвентаря, даже если они используются как боеприпасы. Однако в эту ячейку можно разместить провода.
paint 0 0 Если значение не равно нулю, то этот предмет — краска. Это значение является чем-то вроде «ID краски», которое находится в диапазоне от 1 (красная краска) до 30 (негативная краска).
pick 0 0 Мощность кирки (в процентах), например, pick = 150 означает, что мощность кирки предмета равна 150%.
potion Если имеется, никакие другие предметы с этим атрибутом нельзя использовать до тех пор, пока не истечёт время восстановления. Оно используется для лечащих предметов и грибов.
rare 0 8 Редкость предмета. Значение будет некорректно, если задано expert, поскольку это означает, что предмет имеет редкость уровня Класс редкости: Радужный.
reuseDelay 0 0 Время в тиках (1 тик = 1/60 секунды и 1/3600 минуты) до тех пор, пока предмет можно будет использовать снова, обычно называемое «задержкой использования». На данный момент задаётся только для заводной штурмовой винтовки, головы Медузы, последней призмы, «Рассекателя небес» и проклятия Бетси.
sacrifices 0 1 Необходимое количество предметов для исследования.
scale 1 1
sentry Если имеется, то этот предмет является призывающим стражей.
shieldSlot -1 -1 ID ячейки щита. См. «Идентификаторы брони» § «Аксессуары».
shoeSlot -1 -1 ID ячейки обуви. См. «Идентификаторы брони» § «Аксессуары».
shopCustomPrice -1 Стоимость предметов армии Древних(Издания для ПК, консолей и мобильных устройств), в медалях защитника.
shoot 0 985 Если значение не равно нулю, то это ID снаряда, выпускаемого предметом.
shootSpeed 0 12 Скорость снаряда, выпускаемого предметом.
stringColor Цвет верёвочки.
tileBoost 0 0 Бонус дальности, например, tileBoost = 4 означает, что дальность этого предмета увеличена до 4. Также упоминается в подсказках предмета как, например, «+4 к дальности».
tileWand -1 -1 ID предмета блока, который размещает палочка.
questItem Задаётся только для квестовых рыб.
uniqueStack Задаётся только для квестовых рыб. См. Рыбалка#Задания рыбака для более подробной информации о качестве этих предметов.
useAmmo 0 0 Тип боеприпасов, которые используются этим предметом. 23 для геля, 40 для стрелы, 71 для монеты, 75 для упавшей звезды, 97 для пули, 169 для песка, 283 для дротика, 771 для ракеты, 780 для раствора, 931 для сигнальной ракеты, 949 для снежка, 1261 для болта «Стингера», 1783 для кэнди-корна, 1785 для светильника Джека, 1836 для кола, 3108 для гвоздя.
useAnimation 100 18 Как долго проигрывается анимация предмета, в тиках (1 тик = 1/60 секунды и 1/3600 минуты). Интересная особенность заключается в том, что если значение useTime ниже, чем у useAnimation, то она будет проигрываться один или несколько раз за использование (как, например, «Золотой дождь»). Если предмет является мечом с автовзмахом, то время использования предмета (которое отображается в игре и на вики) будет задано как useAnimation = -1.
UseSound Item_1 Название файла (без расширения файла, чем обычно является .wav) звукового эффекта, который воспроизводится этим предметом при использовании. Обратите внимание, что указанный звук является только основным; он может быть проигран с изменённой высотой тона и громкостью в игре.
useStyle 0 1 1 = общий взмах/бросок, 2 = поедание/использование, 3 = колотый удар, 4 = держание, 5 = убирание. Также см. список tConfig.
useTime 100 18 Скорость инструмента, (внутреннее) время использования для других. Сколько времени нужно для использования предмета, в кадрах. Пока предмет находится в состоянии использования, вы не можете выполнять другие действия.
useTurn Будет ли игрок поворачиваться лицом в направлении своего движения при использовании предмета. Например, меч поворачивает вас лицом влево или вправо, а вот копьё — нет. Если задать значение как useTurn = false, то это позволит игроку не поворачиваться в сторону своего движения при использовании.
value 0 1000000 Значение стоимости, в медных монетах. Стоимость продажи = стоимость покупки / 5. Шаблон {{Coin}} помогает с форматированием этого значения для корректного отображения.
vanity Если имеется, то этот предмет — предмет стиля.
waistSlot -1 -1 ID ячейки туловища. См. «Идентификаторы брони» § «Аксессуары».
wingSlot -1 -1 ID ячейки крыльев. См. «Идентификаторы брони» § «Аксессуары».

--------------------------------------------------------------------------------
--
-- =============================================================================
--
-- 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