Module:ItemInfo

-- local p = {}

local getArgs = require('Module:Arguments').getArgs local loader = require('Module:Loader')

local yesno, color, statname, rarity, ability, slot = loader.require('Yesno', 'Color', 'Statname', 'RarityTier', 'Ability', 'Inventory slot')

local statData = mw.loadData('Module:Statname/Data')

local PAGENAME = mw.title.getCurrentTitle.text

local DATA_MODULES = { -- ['Item'] = 'Item', ['Weapon'] = 'Weapon/Data', ['Armor Piece'] = 'Armor/Data', ['Armor'] = 'Armor/Data', } local TEMPLATES = { ['Item'] = 'ItemInfo', ['Weapon'] = 'WeaponInfo', ['Armor Piece'] = 'ArmorPieceInfo', ['Armor'] = 'ArmorInfo', }

local VED_BUTTONS = 'V[ E]D ' -- View/Edit/Discuss buttons local NOT_USING_DATA_MODULE_BUTTON = '\'\'\'!\'\'\' ' -- shown if the template does not use data from a data Module (by using ) local NOT_USING_DATA_MODULE_MESSAGE = ' \nIt is recommended to use data located at Module:%s for this template. If it is not already present in the Module, you can add the following code to the data Module: %s \n\n:\'\'See Template:%s for more info on how to use the data Module.\'\'\n  ' -- message shown if the template does not use data from a data Module

local ARMORPIECEPREFIXES = { -- prefixes/names for each armor piece ({...aliases, key = key in data table}) {'helmet', 'head', key = 'head'}, {'chestplate', 'chest', key = 'chest'}, {'leggings', 'legs', key = 'legs'}, {'boots', key = 'boots'}, } local MAXABILITIES = 2 -- maximum abilities that can be on an item local ABILITYTYPES = { -- abilities/bonuses ({type = type in Module:Ability, key = key in data table, prefix = prefix to be used when converting template arguments into a data table}) {type = 'ability', key = 'ia', prefix = 'ability'}, {type = 'piece', key = 'pcb', prefix = 'piece_bonus'}, {type = 'full_set', key = 'fsb', prefix = 'full_set_bonus'}, {type = 'tiered_armor', key = 'tab', prefix = 'tiered_armor_bonus'}, } local ABILITYPROPERTIES = { {name = 'Soulflow Cost', key = 'soulflow_cost', color = 'dark_aqua'}, {name = 'Mana Cost', key = 'cost', color = 'dark_aqua'}, {name = 'Health Cost', key = 'health_cost', color = 'red'}, {name = 'Coin Cost', key = 'coin_cost', color = 'gold'}, {name = 'Cooldown', key = 'cd', color = 'green'}, {name = 'Cooldown', key = 'cooldownAlt', color = 'dark_gray'}, {name = 'Max Souls', key = 'max_souls', color = 'light_purple'}, -- not in game {name = 'Armor Pieces Required', key = 'required_pieces', color = 'gray'}, {name = 'Upgraded By', key = 'upgraded_by', color = 'green'}, }

local BLANK_CELL = ''

-- converts template arguments into a table following those in Module:Weapon/Data/Module:Armor/Data local function convertItemArguments(args) local data = { exists = yesno(args.exist or args.exists, true), -- if armor piece exists type = args.type, -- "type" of item/set to be displayed in top labelText = args.labelText, name = args.name, slots = args.slot or args.slots, rarity = args.rarity, stats = {}, specialEffect = args.specialEffect or args.special_effects or args.special_effect or args.effects or args.effect, }

-- stats for k, v in pairs(statData) do -- item stats data.stats[v.shortcode] = args[v.shortcode] -- or nil end

-- abilities for i = 1, MAXABILITIES, 1 do		local suffix = i ~= 1 and tostring(i) or '' -- suffix for template arguments ("ability_name", "ability_name2")

for _, abilityType in ipairs(ABILITYTYPES) do if args[abilityType.prefix .. '_name' .. suffix] then data[abilityType.key .. suffix] = { name = args[abilityType.prefix .. '_name' .. suffix], secret = yesno(args[abilityType.prefix .. '_secret' .. suffix]), activation = args[abilityType.prefix .. '_activation' .. suffix], req = args[abilityType.prefix .. '_requirement' .. suffix] or args[abilityType.prefix .. '_req' .. suffix], desc = args[abilityType.prefix .. '_desc' .. suffix] or args[abilityType.prefix .. '_description' .. suffix], }

for _, property in ipairs(ABILITYPROPERTIES) do data[abilityType.key .. suffix][property.key] = args[abilityType.prefix .. '_' .. property.key .. suffix] end end end end

return data end

-- converts template arguments into a table following the format of Module:Armor/Data, using convertItemArguments(...) local function convertArmorArguments(args) local armorData = { head = {}, chest = {}, legs = {}, boots = {}, total = convertItemArguments(args), type = args.type, name = args.name, rarity = args.rarity, }

for _, pieceAliases in ipairs(ARMORPIECEPREFIXES) do -- creates a table for each armor piece with all template arguments prefixed by " _" for __, piece in ipairs(pieceAliases) do			for k, v in pairs(args) do if k:find('^' .. piece) then armorData[pieceAliases.key][k:gsub(piece .. '_', '')] = v				end end end end

for _, piece in ipairs(ARMORPIECEPREFIXES) do -- converts each armor piece table to a usable data table armorData[piece.key] = convertItemArguments(armorData[piece.key]) end

return armorData end

local function getSlots(name, default) local slotsList = {}

if type(name) == 'table' then for _, slotName in ipairs(name) do			table.insert(slotsList, slot.slot{slotName}) end else return slot.slot{name or default} end return table.concat(slotsList, ' ') end

local function getStats(statsTable) -- makes a bulleted list of the item's stats (not sorted due to using pairs(...)) if not statsTable then return end

local statsList = {}

for k, v in pairs(statsTable) do		table.insert(statsList, ('*%s: +%s'):format(statname.stat(k), tostring(v))) end return table.concat(statsList, '\n') end

local function getTotalStats(data) local statsTable = {} for _, piece in ipairs(ARMORPIECEPREFIXES) do		for k, v in pairs(data[piece.key] and data[piece.key].stats or {}) do			statsTable[k] = (statsTable[k] and statsTable[k] + (tonumber(v) or 0)) or (tonumber(v) or 0) end end for k, v in pairs(data.total and data.total.stats or {}) do		statsTable[k] = v	end

return getStats(statsTable) end

local function getEffects(data) if not data then return end local effectsList = {data.specialEffect} for _, abilityType in ipairs(ABILITYTYPES) do -- appends abilities to effectsList for i = 1, MAXABILITIES, 1 do			local suffix = i > 1 and tostring(i) or ''

if data[abilityType.key .. suffix] then local itemAbility = data[abilityType.key .. suffix]

local abilityString = { (ability._ability('%s', itemAbility.secret, abilityType.type) .. ' %s%s %s'):format(						itemAbility.name,						itemAbility.activation and () or ,						itemAbility.req and (' (Requires ' .. itemAbility.req .. ')') or ,						itemAbility.desc or 					) }

for _, property in ipairs(ABILITYPROPERTIES) do					if itemAbility[property.key] then table.insert(abilityString, (' ' .. color.makeColor('dark_gray', '%s:') .. ' %s'):format( property.name, color.makeColor(property.color, itemAbility[property.key]) ))					end end

table.insert(effectsList, table.concat(abilityString)) end end end

return table.concat(effectsList, ' ') end

local function notUsingDataModuleWarning(convertedTable, itemName, itemType) local tb = mw.dumpObject(convertedTable) :gsub('table#%d+ ', '') :gsub('%["', )		:gsub('"%]', ) :gsub(' ', '	') .. ','	return NOT_USING_DATA_MODULE_BUTTON:format(DATA_MODULES[itemType], itemName:lower:gsub('%s', '-')), NOT_USING_DATA_MODULE_MESSAGE:format(itemName:lower:gsub('%s', '-'), DATA_MODULES[itemType], table.concat{'["' .. itemName:lower .. '"] = ', mw.text.nowiki(tb)}, TEMPLATES[itemType]) end

-- For single items function p.itemInfo(frame) local args = getArgs(frame) local type = args.itemtype return mw.getCurrentFrame:preprocess(p._itemInfo(type, args)) end

function p._itemInfo(itemType, args) local data local usingDataModule = true if args[1] or args.item or args.weapon then local dataModule = mw.loadData('Module:' .. DATA_MODULES[itemType or 'Item']) data = dataModule[(args[1] or PAGENAME):lower] if not data then error(('item name %q not found in Module:%s'):format((args[1] or PAGENAME):lower, DATA_MODULES[itemType or 'Item'])) end else data = convertItemArguments(args) usingDataModule = false end

local name = data.name or args[1] or PAGENAME local slots = getSlots(data.slot or data.slots, name) local stats = getStats(data.stats) local effects = getEffects(data) local notUsingDataModuleButton, notUsingDataModuleMessage = ,  if not usingDataModule then notUsingDataModuleButton, notUsingDataModuleMessage = notUsingDataModuleWarning(data, name, itemType) end

local wikitable = mw.html.create('table'):addClass('wikitable'):css('overflow', 'auto'):css('border-width', '2px 2px 2px 2px !important'):css('vertical-align', 'text-top'):css('max-width', '20em') wikitable:tag('tr'):css('border-width', '2px'):css('min-width', '150px') :tag('th'):attr('colspan', '2'):wikitext(notUsingDataModuleButton .. (data.type or itemType or 'Item') .. VED_BUTTONS:format(DATA_MODULES[itemType], DATA_MODULES[itemType])):done :done :tag('tr') :tag('td'):addClass('ct'):wikitext(slots):done -- slot :tag('td'):wikitext(('%s \n%s'):format(rarity._link(data.rarity or 'c', name), stats or '')):done -- name, stats :done

if effects ~= '' then wikitable:tag('tr'):css('border-width', '2px') :tag('th'):attr('colspan', '2'):wikitext('Effects'):done :done :tag('tr') :tag('td'):attr('colspan', '2'):wikitext(effects):done -- effects :done end

wikitable:done return table.concat{notUsingDataModuleMessage, tostring(wikitable)} end

-- For Armor Sets function p.armorInfo(frame) local args = getArgs(frame)

return mw.getCurrentFrame:preprocess(p._armorInfo(args)) end

function p._armorInfo(args) local data local usingDataModule = true if args[1] or args.armor then local dataModule = mw.loadData('Module:Armor/Data') data = dataModule[args[1]:lower or PAGENAME:lower] if not data then error(('armor name %q not found in Module:Armor/Data'):format((args[1] or PAGENAME):lower)) end else data = convertArmorArguments(args) usingDataModule = false end

local armorName = data.name or args[1] or PAGENAME local pieces = { head = usingDataModule and data.head or (data.head and data.head.exists) or false, chest = usingDataModule and data.chest or (data.chest and data.chest.exists) or false, legs = usingDataModule and data.legs or (data.legs and data.legs.exists) or false, boots = usingDataModule and data.boots or (data.boots and data.boots.exists) or false, }	local names = { head = (data.head and data.head.name) or armorName:gsub('Armor', (data.head and data.head.label) or 'Helmet'), chest = (data.chest and data.chest.name) or armorName:gsub('Armor', (data.chest and data.chest.label) or 'Chestplate'), legs = (data.legs and data.legs.name) or armorName:gsub('Armor', (data.legs and data.legs.label) or 'Leggings'), boots = (data.boots and data.boots.name) or armorName:gsub('Armor', (data.boots and data.boots.label) or 'Boots'), }	local slots = { head = getSlots(data.head and (data.head.slot or data.head.slots), names.head), chest = getSlots(data.chest and (data.chest.slot or data.chest.slots), names.chest), legs = getSlots(data.legs and (data.legs.slot or data.legs.slots), names.legs), boots = getSlots(data.boots and (data.boots.slot or data.boots.slots), names.boots), }	local stats = { head = getStats(data.head and data.head.stats), chest = getStats(data.chest and data.chest.stats), legs = getStats(data.legs and data.legs.stats), boots = getStats(data.boots and data.boots.stats), total = getTotalStats(data) }	local effects = { head = getEffects(data.head), chest = getEffects(data.chest), legs = getEffects(data.legs), boots = getEffects(data.boots), total = getEffects(data.total) }	local notUsingDataModuleButton, notUsingDataModuleMessage = ,  if not usingDataModule then notUsingDataModuleButton, notUsingDataModuleMessage = notUsingDataModuleWarning(data, armorName, 'Armor') end

local wikitable = mw.html.create('table'):addClass('wikitable'):css('overflow', 'auto'):css('border-width', '2px 2px 2px 2px !important'):css('vertical-align', 'text-top'):css('max-width', '40em') wikitable:tag('tr') :tag('th'):attr('colspan', '4'):css('border-width', '2px'):wikitext(notUsingDataModuleButton .. (data.type or 'Armor Set') .. VED_BUTTONS:format('Armor/Data', 'Armor/Data')):done :done :tag('tr') :tag('th'):attr('colspan', '2'):css('border-width', '2px'):css('min-width', '150px'):wikitext(data.head and data.head.label or 'Helmet'):done :tag('th'):attr('colspan', '2'):css('border-width', '2px'):css('min-width', '150px'):wikitext(data.chest and data.chest.label or 'Chestplate'):done :done :tag('tr') :tag('td'):addClass('ct'):wikitext(pieces.head and slots.head or BLANK_CELL):done -- slots :tag('td'):wikitext(pieces.head and ('%s \n%s\n%s'):format(data.head.labelText or rarity._link(data.head.rarity or data.rarity or 'c', names.head), stats.head or , effects.head or ) or BLANK_CELL):done -- name, stats, piece effects :tag('td'):addClass('ct'):wikitext(pieces.chest and slots.chest or BLANK_CELL):done :tag('td'):wikitext(pieces.chest and ('%s \n%s\n%s'):format(data.chest.labelText or rarity._link(data.chest.rarity or data.rarity or 'c', names.chest), stats.chest or , effects.chest or ) or BLANK_CELL):done :done :tag('tr') :tag('th'):attr('colspan', '2'):css('border-width', '2px'):wikitext(data.legs and data.legs.label or 'Leggings'):done :tag('th'):attr('colspan', '2'):css('border-width', '2px'):wikitext(data.boots and data.boots.label or 'Boots'):done :done :tag('tr') :tag('td'):addClass('ct'):wikitext(pieces.legs and slots.legs or BLANK_CELL):done :tag('td'):wikitext(pieces.legs and ('%s \n%s\n%s'):format(data.legs.labelText or rarity._link(data.legs.rarity or data.rarity or 'c', names.legs), stats.legs or , effects.legs or ) or BLANK_CELL):done :tag('td'):addClass('ct'):wikitext(pieces.boots and slots.boots or BLANK_CELL):done :tag('td'):wikitext(pieces.boots and ('%s \n%s\n%s'):format(data.boots.labelText or rarity._link(data.boots.rarity or data.rarity or 'c', names.boots), stats.boots or , effects.boots or ) or BLANK_CELL):done :done :tag('tr') :tag('th'):attr('colspan', '4'):css('border-width', '2px'):wikitext('Total'):done :done :tag('tr') :tag('td'):attr('colspan', '4'):wikitext(('%s\n%s'):format(data.total and data.total.labelText or rarity._link(data.rarity or 'c', armorName), stats.total or '')):done -- armor name, total stats :done if effects.total ~= '' then wikitable:tag('tr') :tag('th'):attr('colspan', '4'):css('border-width', '2px'):wikitext('Effects'):done :done :tag('tr') :tag('td'):attr('colspan', '4'):wikitext(effects.total) -- total effects :done end

wikitable:done

return table.concat{notUsingDataModuleMessage, tostring(wikitable)} end

return p