Module:Iteminfo

From Terraria Wiki
Jump to navigation Jump to search
Lua.svg Documentation The documentation below is transcluded from Module:Iteminfo/doc. (edit | history)

This module 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.

It provides the functionality for {{iteminfo}}. Usually, that template should be called in articles instead of this module. It features additional utilities like output formatting and parameter aliases.

The module's code is currently synchronized with the Desktop version Desktop version 1.4.4.9 of Terraria.

Usage

All stats

{{#invoke:iteminfo|getInfo| id = <itemid> | prefix = <prefix for output varnames> }}

or

{{#invoke:iteminfo|getInfo| <itemid> | <prefix for output varnames> }}

id

Item ID, can be 1 through 5455. Please note that some IDs are unused or deprecated and thus invalid.

prefix (optional)

The prefix for the output variable, default is _iteminfo_. For example, the default variable name for value is _iteminfo_value. If you used prefix=my_, the variable name would be my_value. When you use this method, the module sets a number of DPL variables which you can then retrieve by using {{#dplvar:_iteminfo_value}}, for instance. This method is used in favor of Lua scripts due to DPL's better speed.

Single stat

{{#invoke:iteminfo|getStat| id = <itemid> | stat = <statname> }}

or

{{#invoke:iteminfo|getStat| <itemid> | <statname> }}

id

Item ID, can be 1 through 5455. Please note that some IDs are unused or deprecated and thus invalid.

stat (optional)

Stat name, see the table below for possible values.

If you are not sure if the ID you specified is valid, please check {{#invode:iteminfo|isValidId| <itemid> }}. It will be the 1 if it is valid, and 0 if the ID is invalid.

All return fields are listed below. Please note that not all of them are used – see note info of each row. And please also refer to these tModLoader and tConfig documentations.

Note: You can get the item name from the Item ID by using {{ItemNameFromId}}.

dplvar
(without prefix)
Default Value Example
(here: ID = 757)
Note
type 0 757 Item ID. If the ID specified as argument is valid, this value will be that number. Else, this value will be blank.
internalName TerraBlade Internal name of the item.
name Terra Blade English Name of the item.
DD2Summon If set, it means this item is a Tavernkeep's sentry-summoning weapon(Desktop, Console and Mobile versions).
ToolTip Currently always empty. Reserved for the future. You can use {{itemTooltip}} to retrieve tooltips.
material 1 If set, this item is a crafting material. You can also use {{#invoke:Recipes|exist|ingredient=<item name>}} to retrieve this info.
accessory If set, this is an accessory item.
alpha 0 0
ammo 0 0 AmmoID (used in field useAmmo) not only, e.g. 353, 154
autoReuse 1 If set, this item is capable of autoswing.
axe 0 0 Axe Power. 1 ≙ 5%, e.g. axe = 23 means Axe Power of this item is 115%.
backSlot -1 -1 Back slot ID. See Accessory IDs § Back.
bait 0 0 Bait power (in percent), e.g. bait = 50 means bait power of this item is 50%.
balloonSlot -1 -1 Balloon slot ID. See Armor IDs § Balloon.
bodySlot -1 -1 Body (waist) slot ID. See Armor IDs.
buffTime 0 0 Time the buff this item grants will be in effect in ticks (1 tick = 1/60 second and 1/3600 minute). For example, if buffTime = 14400, it means that the buff will be in effect for 240 seconds (14400/60 = 240) which is equal to 4 minutes (14400/3600 = 4).
buffType 0 0 Buff ID of the buff this item grants.
canBePlacedInVanityRegardlessOfConditions
cartTrack Is set for Minecart Tracks.
channel If set, means that the item can/needs be used continuously ("channeling cast", 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 Is set for items that are consumables (which means all items in Category:Consumable items). Note that this is distinct from the ingame concept "Consumable"! See Category:Consumable items for clarification. If this attribute is set to True, then one item from the stack is removed each time the item is used.
craftable 1 If set, this item is can be crafted. You can also use {{#invoke:Recipes|exist|result=<item name>}} to retrieve this info.
createTile -1 -1 Tile ID of the tile this item produces when placed. placeStyle is that tile's sub ID.
placeStyle 0 0
createWall -1 -1 Wall ID of the wall this item produces when placed.
crit 0 0 Critical strike chance (in percent) that is added to the base 4%, e.g. crit = 2 means crit chance of this item is 6%; crit = 4 means crit chance of this item is 8%.
damage -1 85 Base damage of the item.
defense 0 0 Defense this item grants.
dye 0 0 If non-zero, this is a dye item.
expert If set, this item will be displayed as Rarity level: Rainbow rarity.
faceSlot -1 -1 Face slot ID. See Accessory IDs § Face.
fishingPole 0 0 Fishing Power of the item (in percent), e.g. fishingPole = 27 means Fishing Power of this item is 27%.
flame Set for each kind of Torch and for Water, Peace, Platinum, and regular Candle. Interestingly, it is also set for Brand of the Inferno.
frontSlot -1 -1 Front slot ID. See Accessory IDs § Front.
glowMask -1 -1
hairDye -1 -1 0 for Hair Dye Remover and positive number for other Hair Dyes.
hammer 0 0 Hammer power (in percent), e.g. hammer = 90 means hammer power of this item is 90%.
handOffSlot -1 -1 Hand-off slot ID. See Accessory IDs § Hands off.
handOnSlot -1 -1 Hand-on slot ID. See Accessory IDs § Hands on.
headSlot -1 -1 Head slot ID. See Armor IDs.
healLife 0 0 Amount of Health Points this item restores when used.
healMana 0 0 Amount of Mana this item restores when used.
height 0 30 Height of the item sprite, in pixels.
holdStyle 0 0 How the item is held by the player when used or selected in the inventory. See Use Style IDs.
knockBack 0 6.5 Knockback value of the item.
legSlot -1 -1 Leg slot ID. See Armor IDs.
lifeRegen 0 0 Can only be 0 or 1. Is set to 1 for Band of Regeneration and Charm of Myths.
makeNPC 0 0 If non-zero, will spawn NPC when used. The value is the NPC ID of the spawned NPC.
mana 0 0 Amount of mana this item consumes upon use.
maxStack 1 1 Maximum stack limit.
mech If set, this is a mechanism item, which means that it shows wire and Actuators when held.
melee 1 If set, this item deals melee damage.
magic If set, this item deals magic damage.
ranged If set, this item deals ranged damage.
summon If set, this item deals summon damage.
thrown If set, this item deals thrown damage.
mountType -1 -1 Mount ID of the mount this item summons when used.
netID 0 757
neckSlot -1 -1 Neck slot ID. See Accessory IDs § Neck.
noMelee 1 Whether this item is allowed to deal damage with its sprite. Typically set to true for a ranged weapon, which would rely on its projectiles to deal damage, instead.
noUseGraphic Whether this item's sprite is drawn while it is in use. Thrown weapons like Dynamite uses this, because it is immediately tossed to the ground to create the illusion of being used.
noWet If set, 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 Is only set for Coins, Ale, Wire. Aside from Wire, these share the trait of not being able to be put in the ammo slot of the inventory, even though there are used as ammunition. Wire can be placed in that slot, though.
paint 0 0 Paint ID. If 0, then the item is not a paint item.
paintCoating 0 0 Coating ID. If 0, then the item is not a coating item.
pick 0 0 Pickaxe power (in percent), e.g. pick = 150 means pickaxe power of the item is 150%.
potion If set, no other items with this attribute may be used until the cooldown elapses. This applies to healing items and Mushrooms.
rare 0 8 Rarity of the item. Not valid if expert is set, as that makes the item have the Rarity level: Rainbow rarity.
rarity 0 0 "Internal rarity" of the item. Only valid and non-zero for Expert-exclusive items; see Treasure Bag § Internal rarity.
reuseDelay 0 0 The time in ticks (1 tick = 1/60 second and 1/3600 minute) before this item may be used again, commonly called "Use Delay". Currently only set for Clockwork Assault Rifle, Medusa Head, Last Prism, Sky Fracture, and Betsy's Wrath.
sacrifices 0 1 Required amount to research this item.
scale 1 1
sentry If set, this item is a sentry summon item.
shieldSlot -1 -1 Shield slot ID. See Accessory IDs § Shield.
shoeSlot -1 -1 Shoe slot ID. See Accessory IDs § Shoes.
shopCustomPrice -1 Purchase prices of the Old One's Army(Desktop, Console and Mobile versions) items, in Defender Medals.
shoot 0 985 If non-zero, this is the Projectile ID of the projectile fired by the item.
shootSpeed 0 12 Velocity of the projectile fired by the item, in pixels per tick.
stringColor The color type of Strings, only for String items.
tileBoost 0 0 Range bonus, e.g. tileBoost = 4 means range of this item is increased by 4. Also stated in the tooltip of the item as e.g. "+4 range".
tileWand -1 -1 Item ID of the block this block-placing wand places.
questItem Is only set for Quest Fish.
uniqueStack Is only set for Quest Fish. See Fishing#Fishing Quests for details regarding the special quality of these items.
useAmmo 0 0 Type of ammunition this 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 18 How long it takes the animation to play for the item, in ticks (1 tick = 1/60 second and 1/3600 minute). 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, use time of the item (that is displayed in the game and on the wiki) is useAnimation = -1.
UseSound Item_1 File name (without file extension, but it is usually .wav) of the sound effect that is played when this item is used. Note that the listed sound is only the base sound; it might be played with modified pitch and volume in-game.
useStyle 0 1 How the item is held by the player when used or selected in the inventory. See Use Style IDs.
useTime 100 18 Tool speed for tools, (internal) use time for others. How long it takes to use the item, in frames. While the item is in use, you cannot take other actions.
useTurn Whether the player will turn to face the direction the player is moving when the item is used. For example, a sword would make you face left or right, but a spear would not. Set this to useTurn = false prevents the player from switching directions while swinging a weapon.
value 0 1000000 Buy value, in Copper Coins. Sell value = buy value / 5. {{Coin}} helps formatting this value in order to display it properly.
vanity If set, this item is a vanity item.
waistSlot -1 -1 Waist slot ID. See Accessory IDs § Waist.
width 0 30 Width of the item sprite, in pixels.
wingSlot -1 -1 Wing slot ID. See Accessory IDs § Wings.

---Item info database
---luacache.get() is relative slow, therefore we load data from luacache only once per page.
local data = mw.loadData('Module:Iteminfo/loaddata')

local trim = mw.text.trim
local idSets = require('Module:Iteminfo/idSets')

local info = {
	version = data['_terrariaversion'],
	IDs = { -- min and max are both inclusive
		min = 1,
		max = 5455,
	},
}
info.IDs.isValidWithUnused = function(id)
	-- IDs marked as "unused" are still considered valid by this function
	return id ~= nil and type(id) == 'number' and id >= info.IDs.min and id <= info.IDs.max
end
info.IDs.isValid = function(id)
	-- IDs marked as "unused" are considered invalid by this function
	return info.IDs.isValidWithUnused(id) and idSets.getValue('Unused', id) ~= true
end

-- cache
local currentFrame

-- helper function
local getArg = function(key)
	local value = currentFrame.args[key]
	if not value then
		return nil
	end
	value = trim(value)
	if value == '' then
		return nil
	else
		return value
	end
end

-- credit: http://richard.warburton.it
-- this version is with trim.
local function explode(div,str) 
	if (div=='') then return false 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

local getStat = function(itemid, stat)
	return data[itemid][stat] or data[0][stat] or nil -- "or nil" will convert "false" to "nil"
end

local statname = {
	["acc"] = "accessory",
	["autoreuse"] = "autoReuse",
	["autoswing"] = "autoReuse",
	["auto"] = "autoReuse",
	["axe power"] = "axe",
	["axepower"] = "axe",
	["bait power"] = "bait",
	["baitpower"] = "bait",
	["body slot"] = "bodySlot",
	["bodyslot"] = "bodySlot",
	["buff duration"] = "buffTime",
	["buff id"] = "buffType",
	["buffduration"] = "buffTime",
	["buffid"] = "buffType",
	["bufftime"] = "buffTime",
	["bufftype"] = "buffType",
	["carttrack"] = "cartTrack",
	["createtile"] = "createTile",
	["createwall"] = "createWall",
	["critical"] = "crit",
	["dd2summon"] = "DD2Summon",
	["dmg"] = "damage",
	["fishing power"] = "fishingPole",
	["fishingpole"] = "fishingPole",
	["fishingpower"] = "fishingPole",
	["fishing"] = "fishingPole",
	["hair dye"] = "hairDye",
	["hairdye"] = "hairDye",
	["hammer power"] = "hammer",
	["hammerpower"] = "hammer",
	["head slot"] = "headSlot",
	["headslot"] = "headSlot",
	["heallife"] = "healLife",
	["healmana"] = "healMana",
	["holdstyle"] = "holdStyle",
	["id"] = "type",
	["internal name"] = "internalName",
	["internalname"] = "internalName",
	["item id"] = "type",
	["itemid"] = "type",
	["kb"] = "knockBack",
	["knockback"] = "knockBack",
	["leg slot"] = "legSlot",
	["legslot"] = "legSlot",
	["liferegen"] = "lifeRegen",
	["makenpc"] = "makeNPC",
	["maxstack"] = "maxStack",
	["mount id"] = "mountType",
	["mountid"] = "mountType",
	["mounttype"] = "mountType",
	["mount"] = "mountType",
	["nomelee"] = "noMelee",
	["notammo"] = "notAmmo",
	["nousegraphic"] = "noUseGraphic",
	["nowet"] = "noWet",
	["pick power"] = "pick",
	["pickpower"] = "pick",
	["pickaxe power"] = "pick",
	["pickaxepower"] = "pick",
	["pickaxe"] = "pick",
	["placestyle"] = "placeStyle",
	["projectileid"] = "shoot",
	["projectile id"] = "shoot",
	["questitem"] = "questItem",
	["range bonus"] = "tileBoost",
	["rangebonus"] = "tileBoost",
	["rarity"] = "rare",
	["reusedelay"] = "reuseDelay",
	["shootspeed"] = "shootSpeed",
	["sound"] = "UseSound",
	["sounduse"] = "UseSound",
	["stack"] = "maxStack",
	["stringcolor"] = "stringColor",
	["tile id"] = "createTile",
	["tile sub id"] = "placeStyle",
	["tile subid"] = "placeStyle",
	["tilesubid"] = "placeStyle",
	["tile wand"] = "tileWand",
	["tileboost"] = "tileBoost",
	["tileid"] = "createTile",
	["tilewand"] = "tileWand",
	["tile"] = "createTile",
	["tool speed"] = "useTime",
	["toolspeed"] = "useTime",
	["tooltip"] = "ToolTip",
	["uniquestack"] = "uniqueStack",
	["use delay"] = "reuseDelay",
	["use sound"] = "UseSound",
	["use style"] = "useStyle",
	["use time"] = "useAnimation",
	["useammo"] = "useAmmo",
	["useanimation"] = "useAnimation",
	["usedelay"] = "reuseDelay",
	["usesound"] = "UseSound",
	["usestyle"] = "useStyle",
	["usetime"] = "useAnimation",
	["useturn"] = "useTurn",
	["use"] = "useAnimation",
	["velocity"] = "shootSpeed",
	["wall id"] = "createWall",
	["wallid"] = "createWall",
	["wall"] = "createWall",
	["sell"] = "value",
	--non-native stats:
	["buy"] = "buyValue",
	["price"] = "buyValue",
	["buffname"] = "buffName",
	["buff name"] = "buffName",
	["buff"] = "buffName",
	["research"] = "sacrifices"
}

local proc = {}
proc.axe = function(value)
	return currentFrame:expandTemplate{ title = 'percent', args = { tostring((value or 0) * 5) .. '%' } }
end
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
proc.bait = function(value)
	return currentFrame:expandTemplate{ title = 'percent', args = { tostring(value) .. '%' } }
end
proc.fishingPole = proc.bait
proc.hammer = proc.bait
proc.pick = proc.bait
proc.buffTime = function(value)
	return currentFrame:expandTemplate{ title = 'duration', args = { (value or 0)/60 } }
end
proc.buffName = function(value, id)
	return currentFrame:expandTemplate{ title = 'GetBuffInfo', args = { getStat(id, 'buffType'), 'ename' } }
end
proc.crit = function(value, id)
	if getStat(id, 'damage') == -1 then
		return currentFrame:expandTemplate{ title = 'percent', args = { tostring(value) .. '%' } } -- no damage value
	else
		return currentFrame:expandTemplate{ title = 'percent', args = { tostring(value+4) .. '%' } }  -- has damage value
	end
end
proc.damagetype = function(value, id)
	if getStat(id, 'melee') then
		return currentFrame:expandTemplate{ title = 'l10n', args = { 'GetItemInfo', 'damagetype_melee' } }
	end
	if getStat(id, 'ranged') then
		return currentFrame:expandTemplate{ title = 'l10n', args = { 'GetItemInfo', 'damagetype_ranged' } }
	end
	if getStat(id, 'magic') then
		return currentFrame:expandTemplate{ title = 'l10n', args = { 'GetItemInfo', 'damagetype_magic' } }
	end
	if getStat(id, 'summon') then
		return currentFrame:expandTemplate{ title = 'l10n', args = { 'GetItemInfo', 'damagetype_summon' } }
	end
	if getStat(id, 'thrown') then
		return currentFrame:expandTemplate{ title = 'l10n', args = { 'GetItemInfo', 'damagetype_thrown' } }
	end
end
proc.rare = function(value)
	return currentFrame:expandTemplate{ title = 'rare', args = { (value or 0), cate=getArg('cate') or getArg('category') or getArg('cat') or 'no' } }
end
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
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 currentFrame:expandTemplate{ title = 'itemNameFromId', args = { value } }
end
proc.UseSound = function(value)
	local str = ''
	for _,v in pairs(explode(',', value)) do
		str = str .. currentFrame:expandTemplate{ title = 'sound', args = { '', v..'.wav' } }
	end
	return str
end
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
proc.buyValue = function(value, id)
	local t=getStat(id, 'shopCustomPrice')
	if t then
		return currentFrame:expandTemplate{ title = 'dm', args = { t } }
	else
		return currentFrame:expandTemplate{ title = 'coin', args = { tostring(getStat(id, 'value'))..'cc' } }
	end
end
proc.value = function(value)
	value = tonumber(value or 0)
	if value > 0 then
		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
	else
		return currentFrame:expandTemplate{ title = 'l10n', args = { 'GetItemInfo', 'noValue' } }
	end
end


---------------------------

local p = {
	-- info table for other modules
	info = info,
	
	-- info table data for templates
	v = function(frame)
		return info.version
	end,
	maxId = function(frame)
		return info.IDs.max
	end,
	isValidId = function(frame)
		currentFrame = 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: get all stats, return them as a table
	getItemInfo = function(itemid)
		if not data[itemid] then
			itemid = 0
		end
		local result = {['type'] = itemid}
		for k,v in pairs(data[0]) do
			result[k] = v
		end
		for k,v in pairs(data[itemid]) do
			result[k] = v
		end
		return result
	end,

	-- for templates: get all stats, set them in dplvars
	getInfo = function(frame)
		currentFrame = 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
			itemid = 0
		end
		
		local result = {['type'] = itemid}
		for k,v in pairs(data[0]) do
			result[k] = v
		end
		for k,v in pairs(data[itemid]) do
			result[k] = v
		end

		local args = {}
		local fields = {}
		for k,v in pairs(result) do
			args[#args + 1] = prefix .. k
			args[#args + 1] = v
			fields[#fields + 1] = k
		end
		
		args[#args + 1] = prefix .. '_fields'
		args[#args + 1] = table.concat(fields, '/')

		frame:callParserFunction{ name = '#dplvar:set', args = args }
	end,

	-- for other modules: get a single stat, return it directly
	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
			itemid = 0
		end
		if stat == 'type' then
			return itemid
		end
		return data[itemid][stat] or data[0][stat]
	end,

	-- for templates: get a single stat, return it directly
	getStat = function(frame)
		currentFrame = frame -- cache

		local itemid = tonumber(getArg('id')) or tonumber(getArg(1)) or 0
		local stat = getArg('stat') or getArg(2)
		stat = statname[stat] or stat

		if not stat then
			return
		end

		if not data[itemid] then
			itemid = 0
		end

		local result
		if stat == 'type' then
			return itemid
		end
		if stat == 'count' then
			-- this is deprecated, {{iteminfo/maxId}} should be used
			return info.IDs.max
		end
		result = getStat(itemid, stat) 
		if not getArg('raw') and proc[stat] then
			result = proc[stat](result, itemid)
		end

		if getArg('format') then
			result = frame:callParserFunction('formatnum', result)
		end

		return result
	end,
}

--alias
p.getinfo = p.getInfo
p.GetInfo = p.getInfo
p.getstat = p.getStat
p.GetStat = p.getStat

return p