Module:StreetBrawlAbilitiesGive feedback
Documentation for this module may be created at Module:StreetBrawlAbilities/doc
-- Lists the Street Brawl ability overrides from [[Data:StreetBrawlData.json]] with the
-- {{DataProp}} call that cites each one and the base value it replaces.
local p = {}
local SB_PAGE = "Data:StreetBrawlData.json"
local CARDS_PAGE = "Data:AbilityCards.json"
local HERO_PAGE = "Data:HeroData.json"
local UNMATCHED = "Unmatched abilities"
-- Maps each ability key to the hero who owns it.
local function build_owner_map()
local cards = mw.loadJsonData(CARDS_PAGE)
local heroes = mw.loadJsonData(HERO_PAGE)
local map = {}
for hero_key, card in pairs(cards) do
local hero = heroes[hero_key]
-- Unreleased hero stubs reuse released heroes' ability keys (hero_gunslinger
-- carries Paradox's Pulse Grenade), so only live hero records may claim one.
if type(card) == "table" and hero and hero.Name and hero.IsDisabled ~= true then
for slot = 1, 8 do
local ability = card[tostring(slot)]
if type(ability) == "table" and ability.Key then
map[ability.Key] = { hero = hero.Name, slot = slot, name = ability.Name }
end
end
end
end
return map
end
-- Orders one node's keys: plain props before Upgrades, Value before Scale, tiers numerically.
local function sorted_keys(node, top)
local keys = {}
for k in pairs(node) do
-- Name labels the record; it is not one of the changed properties.
if not (top and k == "Name") then keys[#keys + 1] = k end
end
table.sort(keys, function(a, b)
if top then
if a == "Upgrades" then return false end
if b == "Upgrades" then return true end
end
if a == "Value" then return true end
if b == "Value" then return false end
local na, nb = tonumber(a), tonumber(b)
if na and nb then return na < nb end
return a < b
end)
return keys
end
-- Collects the changed properties as dot-notation paths, the form {{DataProp}} accepts.
local function flatten(node, prefix, out, top)
for _, key in ipairs(sorted_keys(node, top)) do
local value = node[key]
local path = prefix and (prefix .. "." .. key) or key
if type(value) == "table" then
flatten(value, path, out, false)
else
out[#out + 1] = path
end
end
end
-- Builds one property line: the wikitext to copy, its Street Brawl value, and the default.
local function render_line(frame, ability, path)
local call = "{{DataProp|" .. ability .. "|" .. path .. "|streetbrawl}}"
-- Expanded rather than read from the JSON, so this shows what a copied call really gives.
local sb = frame:expandTemplate{ title = "DataProp", args = { ability, path, "streetbrawl" } }
local base = frame:expandTemplate{ title = "DataProp", args = { ability, path } }
return "* <code>" .. mw.text.nowiki(call) .. "</code> → '''" .. sb
.. "''' ''(default " .. base .. ")''"
end
-- {{#invoke:StreetBrawlAbilities|report}} renders every change, grouped by hero.
function p.report(frame)
local changes = mw.loadJsonData(SB_PAGE)["ability-changes"]
local owners = build_owner_map()
local by_hero, hero_order = {}, {}
for key, record in pairs(changes) do
local owner = owners[key]
local hero = owner and owner.hero or UNMATCHED
if not by_hero[hero] then
by_hero[hero] = {}
hero_order[#hero_order + 1] = hero
end
local paths = {}
flatten(record, nil, paths, true)
table.insert(by_hero[hero], {
slot = owner and owner.slot or 99,
name = record.Name or (owner and owner.name) or key,
paths = paths,
})
end
-- Anything the data adds that no live hero claims is listed last rather than dropped.
table.sort(hero_order, function(a, b)
if a == UNMATCHED then return false end
if b == UNMATCHED then return true end
return a < b
end)
local out = {}
for _, hero in ipairs(hero_order) do
local abilities = by_hero[hero]
table.sort(abilities, function(a, b) return a.slot < b.slot end)
local matched = hero ~= UNMATCHED
out[#out + 1] = "\n== "
.. (matched and frame:expandTemplate{ title = "HeroIcon", args = { hero } } or hero)
.. " =="
for _, ability in ipairs(abilities) do
out[#out + 1] = "=== "
.. (matched and frame:expandTemplate{ title = "AbilityIcon", args = { ability.name } } or ability.name)
.. " ==="
for _, path in ipairs(ability.paths) do
out[#out + 1] = render_line(frame, ability.name, path)
end
end
end
return table.concat(out, "\n")
end
return p