Module:GameData
Appearance
Documentation for this module may be created at Module:GameData/doc
local p = {}
local snapshot
local function data()
if not snapshot then snapshot = mw.loadJsonData('GameData:Reference.json') end
return snapshot
end
local function missing(key)
return '<strong class="error">Missing game reference: ' .. mw.text.nowiki(key) ..
'</strong>[[Category:Pages with missing game references]]'
end
local function duration(value)
local seconds = value / 1000
local units = {{86400, 'day'}, {3600, 'hour'}, {60, 'minute'}, {1, 'second'}}
for _, unit in ipairs(units) do
if seconds >= unit[1] then
local amount = math.floor(seconds / unit[1] * 100 + 0.5) / 100
return mw.language.getContentLanguage():formatNum(amount) .. ' ' .. unit[2] .. (amount == 1 and '' or 's')
end
end
return tostring(value) .. ' milliseconds'
end
local function format(record)
if record.format == 'markdown' then return record.wikitext or missing('markdown') end
if record.format == 'duration' then return duration(tonumber(record.value)) end
if record.format == 'number' then return mw.language.getContentLanguage():formatNum(record.value) end
return mw.text.nowiki(tostring(record.value))
end
local function args(frame)
return frame:getParent() and frame:getParent().args or frame.args
end
function p.value(frame)
local a = args(frame)
local key = mw.text.trim(a[1] or '')
local record = data().values[key]
if not record then return missing(key) end
return format(record)
end
local function item(id)
if not tostring(id):match('^%d+$') then return nil end
return data().items['item' .. tostring(tonumber(id))]
end
local function linkByName(name)
for _, entry in pairs(data().items) do
if entry.idName == name then
return '[[' .. mw.text.nowiki(entry.article) .. '|' .. mw.text.nowiki(entry.name) .. ']]'
end
end
return mw.text.nowiki(name)
end
function p.itemValue(frame)
local a = args(frame)
local entry = item(a.id or a[1] or '')
if not entry then return missing('item ' .. (a.id or a[1] or '')) end
local field = a.field or a[2] or ''
local value = entry[field]
if value == nil or type(value) == 'table' then return missing(field) end
local kind = 'text'
if field == 'growTime' or field == 'cooldownTime' then kind = 'duration'
elseif type(value) == 'number' then kind = 'number' end
return format({value = value, format = kind})
end
function p.infobox(frame)
local a = args(frame)
local entry = item(a.id or a[1] or '')
if not entry then return missing('item ' .. (a.id or a[1] or '')) end
local box = mw.html.create('table'):addClass('wikitable bc-item-infobox')
box:tag('caption'):wikitext(mw.text.nowiki(entry.name))
local function row(label, value)
if value == nil then return end
local tr = box:tag('tr')
tr:tag('th'):attr('scope', 'row'):wikitext(label)
tr:tag('td'):wikitext(value)
end
local function number(value)
return value and mw.language.getContentLanguage():formatNum(value) or nil
end
if entry.imageFile then
box:tag('tr'):tag('td'):attr('colspan', 2):addClass('bc-item-picture')
:wikitext('[[File:' .. mw.text.nowiki(entry.imageFile) .. '|128px|alt=' .. mw.text.nowiki(entry.name) .. ']]')
end
if entry.desc then row('Description', mw.text.nowiki(entry.desc)) end
row('Item ID', tostring(entry.id))
if entry.retired then row('Status', 'Retired from the current game catalog') end
row('Base worth', number(entry.cost) .. ' BC')
local attributes = {}
for _, value in ipairs(entry.attributes) do attributes[value] = true end
row('Account bound', attributes.accountBound and 'Yes' or 'No')
row('Market listing', (attributes.accountBound or attributes.excludeFromMarket) and 'Unavailable' or 'Allowed on eligible profiles')
row('Equippable', attributes.equippable and 'Yes' or 'No')
row('Pet holdable', (attributes.petHoldable or entry.damageMultiplier) and 'Yes' or 'No')
local labels = {petHoldable='Pet holdable', equippable='Equippable', excludeFromMarket='Excluded from Market',
accountBound='Account bound', relayRestricted='Relay restricted', relayItem='Relay item'}
local flags = {}
for _, value in ipairs(entry.attributes) do table.insert(flags, mw.text.nowiki(labels[value] or value)) end
if #flags > 0 then row('Attributes', table.concat(flags, ', ')) end
if entry.growTime then row('Base crop grow time', duration(entry.growTime)) end
if entry.cooldownTime then row('Cooldown', duration(entry.cooldownTime)) end
row('Base damage', number(entry.damage))
row('Damage / worth', entry.damageMultiplier and number(entry.damageMultiplier) .. '×' or nil)
row('Food tier', number(entry.foodTier))
row('Base pet energy', number(entry.petEnergy))
local function boost(label, effect)
if effect then row(label, number(effect.multiplier) .. '× for ' .. duration(effect.duration)) end
end
boost('Pet adventure boost', entry.petAdventureBoostEffect)
boost('Farm plot boost', entry.farmPlotBoostEffect)
boost('Augment', entry.augmentProperties)
if entry.effect then
local label = entry.effect.type == 'actionBoost' and (entry.effect.action .. ' action boost') or 'Rare loot boost'
boost(mw.text.nowiki(label), entry.effect)
end
for field, label in pairs({worthPerGainedFromBurn='Base BC burned per item',
worthPerGainedFromPetFeed='Base feeding worth per item', worthPerGainedFromHarvest='Base harvest worth per item'}) do
row(label, number(entry[field]))
end
if entry.useLimit then row('Use limit', number(entry.useLimit)) end
local recipe = {}
for _, ingredient in ipairs(entry.recipe) do
table.insert(recipe, linkByName(ingredient[1]) .. ' × ' .. number(ingredient[2]))
end
row('Crafting recipe', entry.uncraftable and 'Not craftable' or table.concat(recipe, '<br />'))
local uses = {}
for _, name in ipairs(entry.usedToCraft) do table.insert(uses, linkByName(name)) end
if #uses > 0 then row('Used to craft', table.concat(uses, ', ')) end
local sources = {}
for _, source in ipairs(entry.lootSources) do table.insert(sources, mw.text.nowiki(source)) end
if #sources > 0 then row('Loot pools', table.concat(sources, ', ')) end
row('Source', '[[GameData:Reference.json|Synchronized game definitions]]; base properties before player bonuses')
return tostring(box)
end
function p.referenceTable(frame)
local key = args(frame)[1] or ''
local source = data().tables[key]
if not source then return missing(key) end
local output = mw.html.create('table'):addClass('wikitable')
local head = output:tag('tr')
for _, column in ipairs(source.columns) do head:tag('th'):attr('scope', 'col'):wikitext(mw.text.nowiki(column)) end
for _, record in ipairs(source.rows) do
local tr = output:tag('tr')
for _, value in ipairs(record) do
tr:tag('td'):wikitext(format({value=value, format=type(value) == 'number' and 'number' or 'text'}))
end
end
return tostring(output)
end
return p