Editing Module:StreetBrawlItemsGive feedback
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 5: | Line 5: | ||
local heroes = mw.loadJsonData("Data:HeroData.json") | local heroes = mw.loadJsonData("Data:HeroData.json") | ||
local NAME_TO_KEY, KEY_TO_NAME, RELEASED = {}, {}, {} | |||
local | |||
for key, h in pairs(heroes) do | for key, h in pairs(heroes) do | ||
if type(h) == "table" and h.Name then | if type(h) == "table" and h.Name then | ||
KEY_TO_NAME[key] = h.Name | |||
NAME_TO_KEY[mw.ustring.lower(h.Name)] = key | NAME_TO_KEY[mw.ustring.lower(h.Name)] = key | ||
if not h.InDevelopment and not h.IsDisabled then RELEASED[key] = true end | |||
end | end | ||
end | end | ||
| Line 26: | Line 23: | ||
local function iname(code) local it = items[code]; return it and it.Name or nil end | local function iname(code) local it = items[code]; return it and it.Name or nil end | ||
local function iok(code) local it = items[code]; return it ~= nil and it.Name ~= nil end | |||
local function iok(code) | |||
end | |||
local function itier(code) | local function itier(code) | ||
local it = items[code]; if not it then return nil end | local it = items[code]; if not it then return nil end | ||
if it.StreetBrawl == true then return 5 end | if it.StreetBrawl == true then return 5 end | ||
return it.Tier | return it.Tier | ||
end | end | ||
local function render_item(frame, code, style) | |||
local function | local name = iname(code); if not name then return nil end | ||
local | if style == "icon" then return frame:expandTemplate{title = "ItemIcon", args = {name}} end | ||
return frame:expandTemplate{title = "ItemBox", args = {name, showTierTag = "true"}} | |||
return | |||
end | end | ||
local function render_hero(frame, key) | |||
local function | local name = KEY_TO_NAME[key]; if not name then return nil end | ||
local name = | return frame:expandTemplate{title = "HeroIcon", args = {name}} | ||
return frame:expandTemplate{title = " | |||
end | end | ||
-- Lays rendered members out in a | -- Lays rendered members out in a wrapping flex row with a consistent gap. | ||
local function | local function flexrow(parts, gap, center) | ||
if #parts == 0 then return "" end | if #parts == 0 then return "" end | ||
return '<div | local align = center and "center" or "flex-start" | ||
return '<div style="display:flex; flex-wrap:wrap; gap:' .. gap .. '; align-items:' .. align .. '">' | |||
.. table.concat(parts) .. '</div>' | |||
end | end | ||
-- | -- Wraps a rendered row with an optional bold label / italic note, or a collapsible box. | ||
-- | -- Returns "" when the row is empty, so nothing (not even the label) shows. | ||
local function wrap(inner, label, note, collapse) | |||
local function | if inner == "" then return "" end | ||
return ' | if collapse then | ||
local header = (label and label ~= "") and label or " " | |||
return '{| class="wikitable mw-collapsible mw-collapsed" style="width:100%"\n' | |||
.. '! style="text-align:left" | ' .. header .. '\n|-\n| ' .. inner .. '\n|}' | |||
end | |||
local pre = "" | |||
if label and label ~= "" then pre = pre .. "'''" .. label .. "'''<br>" end | |||
if note and note ~= "" then pre = pre .. "''" .. note .. "''<br>" end | |||
return pre .. inner | |||
end | end | ||
local function hero_sets(hkey) | local function hero_sets(hkey) | ||
local favored, unfavored, counter = {}, {}, {} | local favored, unfavored, special, counter = {}, {}, {}, {} | ||
for _, o in ipairs(sb.Outliers) do | for _, o in ipairs(sb.Outliers) do | ||
if o.Hero == hkey then | if o.Hero == hkey then | ||
if o.Bucket == "Good" then favored[o.Item] = true | if o.Bucket == "Good" then favored[o.Item] = true; special[o.Item] = true | ||
elseif type(o.Weight) == "number" and o.Weight < 1 then unfavored[o.Item] = true end | elseif type(o.Weight) == "number" and o.Weight < 1 then unfavored[o.Item] = true; special[o.Item] = true end | ||
if o.Counter ~= nil then counter[#counter + 1] = o.Item end | if o.Counter ~= nil then counter[#counter + 1] = o.Item end | ||
end | end | ||
end | end | ||
return favored, unfavored, counter | return favored, unfavored, special, counter | ||
end | end | ||
local function item_code(input) | |||
local function | input = mw.text.trim(input or "") | ||
if input == "" then return nil end | |||
if items[input] then return input end | |||
for | for k, v in pairs(items) do | ||
if | if type(v) == "table" and v.Name == input and v.IsDisabled ~= true then return k end | ||
end | |||
for k, v in pairs(items) do | |||
if type(v) == "table" and v.Name == input then return k end | |||
end | end | ||
return nil | |||
return | |||
end | end | ||
-- | -- {{#invoke:StreetBrawlItems|hero|HERO|GROUP|TIER|label=..|collapse=yes|style=card|icon}} | ||
-- | -- GROUP = favored | unfavored | common (use hero_counter for counters) | ||
function p.hero(frame) | |||
local hkey = hero_key(frame.args[1]); if not hkey then return "" end | |||
local | local group = mw.text.trim(frame.args[2] or "") | ||
local | local tier = tonumber(frame.args[3]) | ||
local style = frame.args.style | |||
if not style or style == "" then style = (group == "common") and "icon" or "card" end | |||
local collapse = (frame.args.collapse == "yes" or frame.args.collapse == "true") | |||
local | local favored, unfavored, special = hero_sets(hkey) | ||
local pred | |||
if group == "favored" then pred = function(c) return favored[c] end | |||
elseif group == "unfavored" then pred = function(c) return unfavored[c] end | |||
elseif group == "common" then pred = function(c) return not special[c] end | |||
else return "" end | |||
end | |||
local | local codes = {} | ||
for _, c in ipairs(sb.AvailableItems) do | |||
if iok(c) and (tier == nil or itier(c) == tier) and pred(c) then codes[#codes + 1] = c end | |||
end | end | ||
table.sort(codes, function(a, b) return (iname(a) or a) < (iname(b) or b) end) | |||
end | |||
local parts = {} | |||
for _, c in ipairs(codes) do local r = render_item(frame, c, style); if r then parts[#parts + 1] = r end end | |||
local is_icon = (style == "icon") | |||
local inner = flexrow(parts, is_icon and "4px 10px" or "8px", is_icon) | |||
return wrap(inner, frame.args.label, nil, collapse) | |||
local | |||
local | |||
end | end | ||
-- {{#invoke:StreetBrawlItems|hero_counter|HERO|heading=..|note=..}} | -- {{#invoke:StreetBrawlItems|hero_counter|HERO|heading=..|note=..}} | ||
-- | -- Returns the whole counter block (heading + note + cards), or "" when empty. | ||
function p.hero_counter(frame) | function p.hero_counter(frame) | ||
local hkey = hero_key(frame.args[1]); if not hkey then return "" end | local hkey = hero_key(frame.args[1]); if not hkey then return "" end | ||
local _, _, counter = hero_sets(hkey) | local _, _, _, counter = hero_sets(hkey) | ||
local codes = {} | local codes = {} | ||
for _, c in ipairs(counter) do if iok(c) then codes[#codes + 1] = c end end | for _, c in ipairs(counter) do if iok(c) then codes[#codes + 1] = c end end | ||
if #codes == 0 then return "" end | if #codes == 0 then return "" end | ||
table.sort(codes, | table.sort(codes, function(a, b) return (iname(a) or a) < (iname(b) or b) end) | ||
local parts = {} | local parts = {} | ||
for _, c in ipairs(codes) do local r = render_item(frame, c); if r then parts[#parts + 1] = r end end | for _, c in ipairs(codes) do local r = render_item(frame, c, "card"); if r then parts[#parts + 1] = r end end | ||
local out = {} | local out = {} | ||
local heading = frame.args.heading | local heading = frame.args.heading | ||
if heading and heading ~= "" then out[#out + 1] = | if heading and heading ~= "" then out[#out + 1] = "=== " .. heading .. " ===" end | ||
local note = frame.args.note | local note = frame.args.note | ||
if note and note ~= "" then out[#out + 1] = "''" .. note .. "''" end | if note and note ~= "" then out[#out + 1] = "''" .. note .. "''" end | ||
out[#out + 1] = | out[#out + 1] = flexrow(parts, "8px", false) | ||
return table.concat(out, "\n") | return table.concat(out, "\n") | ||
end | end | ||
-- {{#invoke:StreetBrawlItems| | -- {{#invoke:StreetBrawlItems|item|ITEM|GROUP|label=..|note=..}} | ||
-- | -- GROUP = favored | unfavored | counter | ||
function p.item(frame) | |||
local code = item_code(frame.args[1]); if not code then return "" end | |||
local group = mw.text.trim(frame.args[2] or "") | |||
local | |||
local fav, unf, ctr = {}, {}, {} | |||
for _, o in ipairs(sb.Outliers) do | for _, o in ipairs(sb.Outliers) do | ||
if o. | if o.Item == code and RELEASED[o.Hero] then | ||
if o.Bucket == "Good" then fav[#fav + 1] = o.Hero | |||
if | elseif type(o.Weight) == "number" and o.Weight < 1 then unf[#unf + 1] = o.Hero end | ||
if o.Counter ~= nil then ctr[#ctr + 1] = o.Hero end | |||
end | end | ||
end | end | ||
local list = (group == "favored" and fav) or (group == "unfavored" and unf) or (group == "counter" and ctr) | |||
table.sort( | if not list then return "" end | ||
table.sort(list, function(a, b) return (KEY_TO_NAME[a] or a) < (KEY_TO_NAME[b] or b) end) | |||
local | local parts = {} | ||
local | for _, k in ipairs(list) do local r = render_hero(frame, k); if r then parts[#parts + 1] = r end end | ||
local inner = flexrow(parts, "4px 10px", true) | |||
return wrap(inner, frame.args.label, frame.args.note, false) | |||
end | |||
-- {{#invoke:StreetBrawlItems|item_in_pool|ITEM}} -> "1" if in the Street Brawl pool, else "" | |||
function p.item_in_pool(frame) | |||
local code = item_code(frame.args[1]); if not code then return "" end | |||
for _, c in ipairs(sb.AvailableItems) do if c == code then return "1" end end | |||
return "" | |||
return | |||
end | end | ||
return p | return p | ||