Documentation for this module may be created at Module:Mods/infobox/doc
--- '''Mods/infobox''' builds the infobox on mod pages and adds the
-- appropriate category pages.<br />
--
-- @module Mods
-- @alias p
-- @author [[User:FINNER|FINNER]]
-- @attribution [[User:Cephalon Scientia|Cephalon Scientia]]
-- @attribution [[User:Trajos|Trajos]]
-- @image
-- @require [[Module:Version]]
-- @require [[Module:Polarity]]
-- @require [[Module:Tooltips]]
-- @require [[Module:DropTables]]
-- @require [[Module:Vendors]]
-- @require [[Module:Baro]]
-- @require [[Module:InfoboxBuilder]]
-- @require [[Module:Mods/data]]
-- @require [[Module:DropTables/data]]
-- @release stable
-- <nowiki>
local Version = require([[Module:Version]])
local Polarity = require([[Module:Polarity]])
local Tooltip = require([[Module:Tooltips]])
local DropTable = require([[Module:DropTables]])
local Vendor = require([[Module:Vendors]])
local Baro = require([[Module:Baro]])
local InfoboxBuilder = require([[Module:InfoboxBuilder]])
local Lang = mw.language.new('en') -- Using for number formatting
local ModData = mw.loadData([[Module:Mods/data]])
local DropData = mw.loadData([[Module:DropTables/data]])
local function makeMTooltip(modTable)
local str = {}
for _, modIndex in ipairs(modTable) do
table.insert(str, Tooltip.full(modIndex, 'Mods'))
end
return table.concat(str, '<br />')
end
-- For calculating Endo cost to max a mod
-- Note that there exist additional displayed rarities (e.g. Peculiar, Requiem)
-- that share one of the below 4 values
local RARITY_EMUM = {
Common = 1,
Uncommon = 2,
Rare = 3,
Legendary = 4,
}
-- Trading tax of mod in Credits
local TAX_MAP = {
Common = 2000,
Uncommon = 4000,
Rare = 8000,
Legendary = 1000000,
}
-- Mapping internal icon text to file links as stored on the wiki
local ICON_TEXT_MAP = {
['<DT_IMPACT>'] = '[[File:Impact_b.png|x16px|class=dark-invert]]',
['<DT_PUNCTURE>'] = '[[File:Puncture_b.png|x16px|class=dark-invert]]',
['<DT_SLASH>'] = '[[File:Slash_b.png|x16px|class=dark-invert]]',
['<DT_FIRE>'] = '[[File:Heat_b.png|x16px|class=dark-invert]]',
['<DT_FREEZE>'] = '[[File:Cold_b.png|x16px|class=dark-invert]]',
['<DT_ELECTRICITY>'] = '[[File:Electricity_b.png|x16px|class=dark-invert]]',
['<DT_POISON>'] = '[[File:Toxin_b.png|x16px|class=dark-invert]]',
['<DT_EXPLOSION>'] = '[[File:Blast_b.png|x16px|class=dark-invert]]',
['<DT_RADIATION>'] = '[[File:Radiation_b.png|x16px|class=dark-invert]]',
['<DT_GAS>'] = '[[File:Gas_b.png|x16px|class=dark-invert]]',
['<DT_MAGNETIC>'] = '[[File:Magnetic_b.png|x16px|class=dark-invert]]',
['<DT_VIRAL>'] = '[[File:Viral_b.png|x16px|class=dark-invert]]',
['<DT_CORROSIVE>'] = '[[File:Corrosive_b.png|x16px|class=dark-invert]]',
['<DT_RADIANT>'] = '[[File:VoidTearIcon_b.png|x16px|class=dark-invert]]',
['<DT_SENTIENT>'] = '[[File:Tau_b.png|x16px|class=dark-invert]]',
['<AMMO_MUTATION>'] = '[[File:AmmoMutation.png|x16px|class=dark-invert]]',
['<LINE_SEPARATOR>'] = '<hr />',
['<ENERGY>'] = '[[File:IconEnergy.gif|x16px]]',
['<SHIELD>'] = '[[File:IconShield.png|x16px]]',
['<SECONDARY_FIRE>'] = '<SECONDARY_FIRE>'
}
return {
buildInfobox = function(frame)
local args = frame.args;
local name = mw.text.decode(args['Name']);
local modData = ModData.Mods[name];
assert(modData ~= nil, ('p.buildInfobox(frame): mod with name "%s" does not exist in [[Module:Mods/data]]'):format(name))
local formattedModDesc = modData.Description
local damageTypeName = formattedModDesc:match('<[A-Z_]+>') -- Matching strings in the form of "<DT_TYPE>"
if (damageTypeName ~= nil) then
formattedModDesc = formattedModDesc:gsub(damageTypeName, ICON_TEXT_MAP[damageTypeName])
-- Matching a second different icon text like in the case of Rending Strike mod
if (formattedModDesc:match('<[A-Z_]+>') ~= nil) then
damageTypeName = formattedModDesc:match('<[A-Z_]+>')
formattedModDesc = formattedModDesc:gsub(damageTypeName, ICON_TEXT_MAP[damageTypeName])
end
end
local incompatibilityTags = {}
for _, tag in ipairs(modData.IncompatibilityTags or {}) do
table.insert(incompatibilityTags, tag)
end
incompatibilityTags = table.concat(incompatibilityTags, ', ')
local compatibilityTags = {}
for _, tag in ipairs(modData.CompatibilityTags or {}) do
table.insert(compatibilityTags, tag)
end
compatibilityTags = table.concat(compatibilityTags, ', ')
-- TODO: Some reason this snippet does not output a non-empty string when modData.IncompatibilityTags is not nil nor empty
-- while the above loop + table.concat works. Determine if this is an upstream issue with table.concat's implementation.
-- local incompatibilityTags = table.concat(modData.IncompatibilityTags, ', ')
local Infobox = InfoboxBuilder('WARFRAME Wiki:L10n/general.json', 'WARFRAME Wiki:L10n/meta.json')
:tag('title')
:tag('default')
:tag('b'):wikitext(name..'[[Category:Mods]]'):done()
:done()
:done()
:tag('image'):attr('source', 'Image')
:tag('default')
:tag('gallery'):wikitext((modData.Image and modData.Image..'|Full' or '')..'\n'..(modData.Icon and modData.Icon..'|Icon' or '')):done()
:done()
:done()
:group()
:caption('Tradeable', modData.Tradable and '[[File:TradableIcon.png|x32px|class=icon dark-invert]] [[Trading|{{text|green|Tradeable}}]][[Category:Tradeable Mods]]' or '{{text|red|Untradeable}}[[Category:Untradeable Mods]]')
:caption('Exilus', modData.IsExilus and '[[:Category:Exilus Mods|{{text|green|EXILUS}}]][[Category:Exilus Mods]]' or nil)
:caption('Transmutable', modData.Transmutable and '[[Transmutation|{{text|green|Can be obtained from transmutation}}]][[Category:Transmutable Mods]]' or '[[Transmutation|{{text|red|Cannot be obtained from transmutation}}]][[Category:Untransmutable Mods]]')
:caption('CodexSecret', modData.CodexSecret and '[[Codex|%s]][[Category:Codex Secret]]' or nil, 'codex-secret')
:caption('UpdateInfoboxData', '[[Module:Mods/data|📝 %s]]', 'update-infobox-data')
:done()
:group():header('%s', 'max-rank-description')
:caption('Description', formattedModDesc)
:done()
:group():header('%s', 'general-information')
:row('Type', '[[Mod#Item Compatibility|%s]]', modData.Type and modData.Type..'[[Category:'..modData.Type..' Mods]]', 'type')
:row('Polarity', '[[Polarity|%s]]', modData.Polarity and Polarity._polarity(modData.Polarity)..' '..modData.Polarity..'[[Category:'..modData.Polarity..' Mods]]', 'polarity')
:row('Rarity', '[[Rarity|%s]]', modData.Rarity and modData.Rarity..'[[Category:'..modData.Rarity..' Mods]]', 'rarity')
:row('Class', '%s', modData.Class and modData.Class..'[[Category:'..modData.Class..' Mods]]', 'class')
:row('CompatibilityTags', '[[Compatibility Tag|%s]]', modData.CompatibilityTags and compatibilityTags, 'compatibility-tags')
:row('Incompatible', 'Incompatible Mods', modData.Incompatible and makeMTooltip(modData.Incompatible))
:row('IncompatibilityTags', '[[Compatibility Tag|%s]]', modData.IncompatibilityTags and incompatibilityTags, 'incompatibility-tags')
:row('MaxRank', '%s', modData.MaxRank, 'max-rank')
:row('EndoCost', '[[Endo]] Required To Max', (modData.Rarity ~= nil and not modData.NotUpgradable) and Lang:formatNum(10 * RARITY_EMUM[modData.Rarity] * (math.pow(2, modData.MaxRank) - 1)) or nil)
:row('CreditCost', '[[Credits]] Required To Max', (modData.Rarity ~= nil and not modData.NotUpgradable) and Lang:formatNum(483 * RARITY_EMUM[modData.Rarity] * (math.pow(2, modData.MaxRank) - 1)) or nil)
:row('BaseDrain', 'Base Capacity Cost', modData.BaseDrain)
:row('TradingTax', '[[Trade System|%s]]', modData.Tradable and Tooltip.icon('Credits', 'Resources')..' '..Lang:formatNum(TAX_MAP[modData.Rarity]) or nil, 'trading-tax')
:row('Introduced', '%s', modData.Introduced and Version._getVersionLink(modData.Introduced)..Version._getVersionCategory(modData.Introduced), 'introduced')
:done()
local vendorStr = Vendor._buildVendorSourceStrings(name)
local baroStr = Baro._buildBaroSourceStrings(name)
Infobox:group():header('%s', 'vendor-sources')
:tag('data'):attr('source', 'Offerings')
:tag('default')
:tag('div'):addClass('tabber-borderless')
:wikitext(('<tabber>%s%s</tabber>'):format(
(vendorStr ~= '') and '|-|Vendors='..vendorStr..'\n' or '',
(baroStr ~= '') and '|-|Baro Ki\'Teer='..baroStr..'\n' or ''
)):done()
:done()
:done()
:done()
:group():header('%s', 'official-drop-tables')
:caption('official-drop-tables', 'https://www.warframe.com/droptables', 'official-drop-tables')
:done()
return frame:preprocess(tostring(Infobox))
end
}