Module:StreetBrawlAbilities: Difference between revisionsGive feedback
Add report() to list Street Brawl ability changes grouped by hero (with help from vergir-bot LLM) |
Add hero_has_changes checker for the Street Brawl hero category (with help from vergir-bot LLM) |
||
| (3 intermediate revisions by 2 users not shown) | |||
| Line 20: | Line 20: | ||
if type(card) == "table" and hero and hero.Name and hero.IsDisabled ~= true then | if type(card) == "table" and hero and hero.Name and hero.IsDisabled ~= true then | ||
for slot = 1, 8 do | for slot = 1, 8 do | ||
local ability = card[tostring(slot)] | -- 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 | if type(ability) == "table" and ability.Key then | ||
map[ability.Key] = { hero = hero.Name, slot = slot, name = ability.Name } | map[ability.Key] = { hero = hero.Name, slot = slot, name = ability.Name } | ||
| Line 46: | Line 47: | ||
local na, nb = tonumber(a), tonumber(b) | local na, nb = tonumber(a), tonumber(b) | ||
if na and nb then return na < nb end | if na and nb then return na < nb end | ||
return a < b | -- Upgrade tiers arrive as numbers, so never compare a number with a string. | ||
return tostring(a) < tostring(b) | |||
end) | end) | ||
return keys | return keys | ||
| Line 55: | Line 57: | ||
for _, key in ipairs(sorted_keys(node, top)) do | for _, key in ipairs(sorted_keys(node, top)) do | ||
local value = node[key] | local value = node[key] | ||
local path = prefix and (prefix .. "." .. key) or key | local path = prefix and (prefix .. "." .. key) or tostring(key) | ||
if type(value) == "table" then | if type(value) == "table" then | ||
flatten(value, path, out, false) | flatten(value, path, out, false) | ||
| Line 62: | Line 64: | ||
end | end | ||
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 | end | ||
| Line 72: | Line 81: | ||
return "* <code>" .. mw.text.nowiki(call) .. "</code> → '''" .. sb | return "* <code>" .. mw.text.nowiki(call) .. "</code> → '''" .. sb | ||
.. "''' ''(default " .. base .. ")''" | .. "''' ''(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 | end | ||