Editing Module:StreetBrawlAbilities

Jump to navigation Jump to search
Warning: You are not logged in. Once you make an edit, a temporary account will be created for you. Learn more. Log in or create an account to continue receiving notifications after this account expires, and to access other features.
The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
Latest revision Your text
Line 1: Line 1:
-- 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
-- The card's slot keys decode as numbers, so index with one.
local ability = card[slot] or 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
-- Upgrade tiers arrive as numbers, so never compare a number with a string.
return tostring(a) < tostring(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 tostring(key)
if type(value) == "table" then
flatten(value, path, out, false)
else
out[#out + 1] = path
end
end
end
-- Reads a property both ways, returning its Street Brawl value and its normal one.
local function both_values(frame, ability, prop)
local sb  = frame:expandTemplate{ title = "DataProp", args = { ability, prop, "streetbrawl" } }
local base = frame:expandTemplate{ title = "DataProp", args = { ability, prop } }
return tonumber(sb), tonumber(base)
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> &rarr; '''" .. sb
.. "''' ''(default " .. base .. ")''"
end
-- True when Street Brawl changes at least one of this hero's abilities. Accepts a
-- hero_* key or the hero's English name, so callers may pass whichever they hold.
function p.hero_has_changes(hero)
if hero == nil or hero == "" then return false end
local record  = mw.loadJsonData(HERO_PAGE)[hero]
local name    = (record and record.Name) or hero
local owners  = build_owner_map()
local changes = mw.loadJsonData(SB_PAGE)["ability-changes"]
for key in pairs(changes) do
local owner = owners[key]
if owner and owner.hero == name then return true end
end
return false
end
-- {{#invoke:StreetBrawlAbilities|hasChanges|HERO}} exposes the same check to wikitext,
-- answering "1" or the empty string so #if can branch on it.
function p.hasChanges(frame)
return p.hero_has_changes(mw.text.trim(frame.args[1] or "")) and "1" or ""
end
-- {{#invoke:StreetBrawlAbilities|change|ABILITY|PROP}} describes how far a property moved
-- in Street Brawl, as "reduced by 45%" or "increased by ~40%".
function p.change(frame)
local ability = mw.text.trim(frame.args[1] or "")
local prop    = mw.text.trim(frame.args[2] or "")
local sb, base = both_values(frame, ability, prop)
-- DataProp answers a failed lookup with a red notice rather than a number.
if not sb or not base or base == 0 then
return '<span style="color:red;">No change for ' .. ability .. '/' .. prop .. '</span>'
end
-- Properties Street Brawl leaves alone fall back to the base value, so two equal
-- numbers mean this property was never in the overlay.
if sb == base then
return '<span style="color:red;">Street Brawl does not change ' .. ability .. '/' .. prop .. '</span>'
end
-- Purely a comparison of the two numbers; whether that helps or hurts the hero is
-- for the surrounding prose to say.
local direction = sb > base and "increased" or "reduced"
local percent = math.abs(sb - base) / math.abs(base) * 100
-- Rounded to the nearest 5% so the prose reads as a round figure; when that rounding
-- moves the number by more than 1.5 points, "~" marks it as approximate.
local rounded = math.floor(percent / 5 + 0.5) * 5
local approx = math.abs(percent - rounded) > 1.5 and "~" or ""
return direction .. " by " .. approx .. string.format("%.0f", rounded) .. "%"
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
Please note that all contributions to The Deadlock Wiki are considered to be released under the Creative Commons Attribution-NonCommercial-ShareAlike (see Deadlock:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!
Cancel Editing help (opens in new window)
Preview page with this template

Page included on this page: