Module:AmmoStats
Appearance
Documentation for this module may be created at Module:AmmoStats/doc
-- Renders ammunition statistics from [[Module:Data/Ammo]].
--
-- This module is hand-written, in the same style as Module:UnitStats.
-- Module:Data/Ammo is meant to be generated by scripts/export-wiki-data.cjs
-- (which only writes under the Module:Data/ prefix), so this file is never
-- overwritten by the export.
--
-- Entry point:
-- table - one row per ammunition {{#invoke:AmmoStats|table}} or {{#invoke:AmmoStats|table|kind=unit}}
--
-- Expected shape of Module:Data/Ammo (field names follow the game's ammo
-- table: volume, craft_time, batch_size, required_<resource>, and for
-- strategic ordnance impact_radius_meters, loss_percent, build_time):
--
-- return {
-- light_infantry_ammo = {
-- name = 'Rifle Rounds',
-- kind = 'unit', -- 'unit' | 'fortification' | 'strategic'
-- fired_by = 'Light Infantry', -- optional, wiki page name
-- volume = 0.5, -- m3 per unit, optional
-- craft_time = '10m', -- optional
-- batch_size = 100, -- optional
-- cost = { money = 50, metal = 10, concrete = 0, petrol = 0, uranium = 0 },
-- impact_radius = 5000, -- metres, strategic only
-- loss_percent = 40, -- strategic only
-- },
-- }
local p = {}
local loaded, data = pcall( mw.loadData, 'Module:Data/Ammo' )
if not loaded then
data = nil
end
local PENDING = "''Stats not yet available.''"
local RESOURCES = { 'money', 'food', 'metal', 'concrete', 'petrol', 'uranium' }
local KIND_ORDER = { unit = 1, fortification = 2, strategic = 3 }
local KIND_LABEL = { unit = 'Unit', fortification = 'Fortification', strategic = 'Strategic' }
local function formatResources( bundle )
if not bundle then
return nil
end
local parts = {}
for _, name in ipairs( RESOURCES ) do
local amount = bundle[name]
if amount and amount > 0 then
parts[#parts + 1] = string.format( '%s %s', amount, name )
end
end
if #parts == 0 then
return 'free'
end
return table.concat( parts, ', ' )
end
local function cell( value )
if value == nil or value == '' then
return '| -\n'
end
return string.format( '| %s\n', value )
end
--- Table of every ammunition, optionally filtered by kind.
-- Usage: {{#invoke:AmmoStats|table|kind=fortification}}
function p.table( frame )
if not data then
return PENDING
end
local wanted = frame.args.kind
if wanted == '' then
wanted = nil
end
local codes = {}
for code, ammo in pairs( data ) do
if not wanted or ammo.kind == wanted then
codes[#codes + 1] = code
end
end
table.sort( codes, function( a, b )
local ka, kb = KIND_ORDER[data[a].kind] or 9, KIND_ORDER[data[b].kind] or 9
if ka ~= kb then
return ka < kb
end
return ( data[a].name or a ) < ( data[b].name or b )
end )
if #codes == 0 then
return "''No ammunition of this kind.''"
end
local strategic = false
for _, code in ipairs( codes ) do
if data[code].kind == 'strategic' then
strategic = true
end
end
local out = {
'{| class="wikitable sortable" style="text-align:center"\n',
'! Ammunition !! Kind !! Fired by !! Batch size !! Craft time !! Batch cost !! Volume (m³)',
}
if strategic then
out[#out + 1] = ' !! Impact radius !! Losses'
end
out[#out + 1] = '\n'
for _, code in ipairs( codes ) do
local a = data[code]
out[#out + 1] = '|-\n'
out[#out + 1] = cell( a.name or code )
out[#out + 1] = cell( KIND_LABEL[a.kind] or a.kind )
out[#out + 1] = cell( a.fired_by and string.format( '[[%s]]', a.fired_by ) or nil )
out[#out + 1] = cell( a.batch_size )
out[#out + 1] = cell( a.craft_time )
out[#out + 1] = cell( formatResources( a.cost ) )
out[#out + 1] = cell( a.volume )
if strategic then
out[#out + 1] = cell( a.impact_radius and string.format( '%s m', a.impact_radius ) or nil )
out[#out + 1] = cell( a.loss_percent and string.format( '%s%%', a.loss_percent ) or nil )
end
end
out[#out + 1] = '|}'
return table.concat( out )
end
return p