Module:InfoboxHero: Difference between revisions

Vergir (talk | contribs)
Drop the deprecated no_summary and no_icon parameters in favour of show_hero_tags and show_icon (with help from vergir-bot LLM)
round health regen to 3 figs
 
(11 intermediate revisions by 4 users not shown)
Line 17: Line 17:
-- and [[Template:Infobox hero/themes.css]].
-- and [[Template:Infobox hero/themes.css]].
--
--
-- Layout is entirely described by the CONFIG block below. Adding, reordering or
-- relabelling a stat should not require touching any code beneath it.
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------


Line 30: Line 28:
local dict_module = require('Module:Dictionary')
local dict_module = require('Module:Dictionary')
local hero_module = require('Module:HeroData')
local hero_module = require('Module:HeroData')
local sb_module  = require('Module:StreetBrawlAbilities')


-- Defined below the CONFIG block; declared here so config closures can see them.
-- Shared hero-data lookups, see [[Module:HeroData]].
local get_stat, has_stat, has_override_or_stat, stat_number
local get_stat     = hero_module.get_stat
local get_scalings = hero_module.get_scalings
local has_stat    = hero_module.has_stat
 
local has_override_or_stat, stat_number


--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
Line 42: Line 45:
local FALLBACK_CARD    = 'Dummy card.png'
local FALLBACK_CARD    = 'Dummy card.png'


-- Each section is a collapsible dropdown. Rows inherit the section's icon color.
--
-- Row fields (all optional except a label):
-- Row fields (all optional except a label):
--  stat        Key in Data:HeroData.json. Resolved top-level, then .Weapon,
--  stat        Key in Data:HeroData.json. Resolved top-level, then .Weapon,
Line 189: Line 190:
link    = 'Health Regen',
link    = 'Health Regen',
icon    = 'Health regen.png',
icon    = 'Health regen.png',
sig_figs = 2,
sig_figs = 3,
},
},
{
{
Line 319: Line 320:
-- The "Information" block. Manual input only; hidden entirely when all are empty.
-- The "Information" block. Manual input only; hidden entirely when all are empty.
local INFO_ROWS = {
local INFO_ROWS = {
{ param = 'pronouns',    label_dict = 'Pronouns' },
{ param = 'voice_actor',  label_dict = 'VoiceActor', link = 'Voice actors' },
{ param = 'release_date', label_dict = 'ReleaseDate', link = 'Heroes by release' },
{ param = 'release_date', label_dict = 'ReleaseDate', link = 'Heroes by release' },
{ param = 'pronouns',     label_dict = 'Pronouns' },
{ param = 'codenames',   label_dict = 'Codenames', tooltip = 'Codenames used for this hero in the game files' },
{ param = 'voice_actor', label_dict = 'VoiceActor' },
{ param = 'codenames',    label_dict = 'Codenames' },
}
}


-- name: literal, or function(ctx) -> string.  when: function(ctx) -> boolean.
-- name: literal, or function(ctx) -> string.  when: function(ctx) -> boolean.
local CATEGORIES = {
local CATEGORIES = {
{ name = 'Heroes' },
    {
        name = function(ctx) return ctx.is_disabled and 'Unused Heroes' or 'Heroes' end,
        always = true,
    },
{
{
name = function(ctx) return ctx.hero_en end,
name = function(ctx) return (ctx.args.name ~= '' and ctx.args.name) or ctx.hero_en end,
-- Silver (Transformed) is documented on Silver's page and shares her category.
-- Silver (Transformed) is documented on Silver's page and shares her category.
when = function(ctx) return ctx.hero_en ~= 'Silver (Transformed)' end,
when = function(ctx) return ctx.hero_en ~= 'Silver (Transformed)' end,
        always = true,
},
},
{
{
Line 436: Line 441:
return 'Heroes with medium dash speed'
return 'Heroes with medium dash speed'
end,
end,
},
{
name = 'Heroes with Street Brawl changes',
when = function(ctx) return sb_module.hero_has_changes(ctx.hero_key) end,
},
},
}
}
Line 442: Line 451:
-- Data access
-- Data access
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Stats live at the top level for vitality, and under .Weapon for weapon stats.
get_stat = function(hero, stat)
if hero == nil or stat == nil then return nil end
local value = hero[stat]
if value == nil and hero.Weapon then
value = hero.Weapon[stat]
if value == nil and hero.Weapon.AltFire then
value = hero.Weapon.AltFire[stat]
end
end
return value
end
-- The raw Boon (Level) and Spirit scaling values for a stat, if any.
local function get_scaling(hero, stat)
local out = {}
for _, scaling_type in ipairs({ 'Level', 'Spirit' }) do
local scaling = hero[scaling_type .. 'Scaling']
local value = scaling and stat and scaling[stat]
if value ~= nil and value ~= 0 then
out[#out + 1] = { type = scaling_type, value = value }
end
end
return out
end
-- True when the hero has a non-zero base value, or any scaling, for a stat.
has_stat = function(hero, stat)
local value = get_stat(hero, stat)
if value ~= nil and value ~= 0 then return true end
return #get_scaling(hero, stat) > 0
end


has_override_or_stat = function(ctx, param, stat)
has_override_or_stat = function(ctx, param, stat)
Line 547: Line 523:
if row.stat and row.scaling ~= false then
if row.stat and row.scaling ~= false then
local parts = {}
local parts = {}
for _, scaling in ipairs(get_scaling(ctx.hero, row.stat)) do
for _, scaling in ipairs(get_scalings(ctx.hero, row.stat)) do
parts[#parts + 1] = hero_module.write_scalar_str(scaling.value, scaling.type)
parts[#parts + 1] = hero_module.write_scalar_str(scaling.value, scaling.type)
end
end
Line 565: Line 541:
end
end
if row.link then
if row.link then
label_cell:wikitext(string.format('[[%s|<span>%s</span>]]:',
label_cell:wikitext(string.format('[[%s|<span class="infobox-h-stat-label">%s</span>]]:',
page_link(ctx, row.link), label_of(row)))
page_link(ctx, row.link), label_of(row)))
else
else
Line 621: Line 597:
local tr = tbl:tag('tr')
local tr = tbl:tag('tr')
local label = dict_module.translate(row.label_dict)
local label = dict_module.translate(row.label_dict)
if row.tooltip then
label = ctx.frame:expandTemplate{ title = 'Tooltip', args = { label, row.tooltip } }
end
if row.link then
if row.link then
tr:tag('td'):wikitext(string.format('[[%s|<span>%s</span>]]:',
tr:tag('td'):wikitext(string.format('[[%s|<span class="infobox-h-stat-label">%s</span>]]:',
page_link(ctx, row.link), label))
page_link(ctx, row.link), label))
else
else
Line 681: Line 660:
local tags = {}
local tags = {}
for i = 1, 3 do
for i = 1, 3 do
local tag = hero_module.get_hero_tag({ args = { ctx.hero_en, tostring(i) } })
local tag = hero_module.hero_tag(ctx.hero_en, i)
if tag and tag ~= '' and not tag:find('Error:', 1, true) then
if tag ~= '' then
tags[#tags + 1] = tag
tags[#tags + 1] = tag
end
end
Line 701: Line 680:
return ''
return ''
end
end
if get_stat(ctx.hero, 'IsDisabled') ~= false then return '' end
 
    local is_disabled = get_stat(ctx.hero, 'Name') == 'TargetDummy' or get_stat(ctx.hero, 'IsDisabled')
    ctx.is_disabled = is_disabled


local out = {}
local out = {}
for _, category in ipairs(CATEGORIES) do
for _, category in ipairs(CATEGORIES) do
if category.when == nil or category.when(ctx) then
        if is_disabled and not category.always then
elseif category.when == nil or category.when(ctx) then
local name = category.name
local name = category.name
if type(name) == 'function' then name = name(ctx) end
if type(name) == 'function' then name = name(ctx) end
Line 717: Line 699:
-- Entry point
-- Entry point
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- |key= accepts a hero_* key or the hero's English name; unknown values fall back
-- to the target dummy, the default character in Sandbox mode.
local function resolve_hero_key(provided)
if provided == nil or provided == '' then return DEFAULT_HERO_KEY end
if hero_data_all[provided] ~= nil then return provided end
local wanted = mw.ustring.lower(provided)
for key, hero in pairs(hero_data_all) do
if hero.Name and mw.ustring.lower(hero.Name) == wanted then return key end
end
return DEFAULT_HERO_KEY
end


function p.render(frame)
function p.render(frame)
Line 742: Line 712:
end })
end })


local hero_key = resolve_hero_key(args.key)
-- |key= accepts a hero_* key or the hero's English name; unknown values fall
-- back to the target dummy, the default character in Sandbox mode.
local hero_key = hero_module.find_hero_key(args.key) or DEFAULT_HERO_KEY
local hero = hero_data_all[hero_key]
local hero = hero_data_all[hero_key]