From Arms of God Wiki

Revision as of 16:04, 10 June 2026 by Ta1ha (talk | contribs) (bot: documentation pass — editor-facing docs (data descriptions, module comments, template usage, Help rewrite))
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Documentation for this module may be created at Module:StatIndex/doc

-- Module:StatIndex — "what modifies this stat?" reverse lookups.
--
-- WHAT IT DOES
--   Renders the lookup tables on the per-stat pages (Armor, Speed, ...)
--   and the damage-type hubs (Holy/Fire/Electric Damage). Nothing is
--   stored: it scans the stat-bearing source Data pages at render time,
--   so a balance change edited into a Data page updates every stat page
--   on purge.
--
-- HOW TO INVOKE
--   {{#invoke:StatIndex|boosters|Armor}}       every hero / blessing /
--       upgrade / passive / Crux power modifying the stat (desc by amount)
--   {{#invoke:StatIndex|weapons|Fire Damage}}  every weapon dealing the
--       elemental damage type (desc by amount)
--
-- SOURCE DATA IT READS (via Module:Core)
--   boosters: Data:Characters.json, Data:Blessings.json,
--   Data:Upgrades.json, Data:Passives.json, Data:Crux.json.
--   weapons: Data:Weapons.json.
local Core = require('Module:Core')
local p = {}

local TBL = '{| class="wikitable sortable" style="font-size:0.95em;background:var(--table-row-odd, #1b1c20);color:var(--table-text, #e6e6e6);border-color:var(--table-border, #3a3c44);"'
local TH  = '! style="background:var(--table-header-bg, #26272e);color:var(--infobox-header-fg, #f1e9d2);" | '

-- Same mechanic, two data names: fold 'Explosive Range' into the
-- 'Explosive Radius' lookup key (and vice versa when querying either).
local ALIAS_GROUPS = {
  ['Explosive Radius'] = {'Explosive Radius', 'Explosive Range'},
  ['Explosive Range'] = {'Explosive Radius', 'Explosive Range'},
}

local MODIFIER_CATS = {'Characters', 'Blessings', 'Upgrades', 'Passives', 'Crux'}

local function statKeysFor(query)
  return ALIAS_GROUPS[query] or {query}
end

-- Internal: list of booster entries for a stat key. {rec, cat, tier, value, sort}
function p._boosters(key)
  local keys = statKeysFor(key)
  local out = {}
  for _, cat in ipairs(MODIFIER_CATS) do
    for _, rec in ipairs(Core.load(cat)) do
      local st = rec.stats or {}
      for _, k in ipairs(keys) do
        local v = st[k]
        if v ~= nil then
          local val = Core.fmtStat(v, true)
          if val ~= nil then
            local tier = rec.tier or rec.type or ''
            out[#out + 1] = {
              rec = rec, cat = cat, tier = tostring(tier),
              value = val, sort = Core.numStat(v) or 0,
            }
          end
        end
      end
    end
  end
  table.sort(out, function(a, b)
    if a.sort ~= b.sort then return a.sort > b.sort end
    return mw.ustring.lower(a.rec.name or '') < mw.ustring.lower(b.rec.name or '')
  end)
  return out
end

-- Internal: list of weapons dealing an elemental damage type.
function p._weapons(key)
  local out = {}
  for _, rec in ipairs(Core.load('Weapons')) do
    local v = Core.numStat((rec.stats or {})[key])
    if v ~= nil and v > 0 and v < 1000 then
      out[#out + 1] = {
        rec = rec, class = Core.weaponClass(rec),
        tier = tostring(rec.tier or ''), value = Core.fmtNum(v), sort = v,
      }
    end
  end
  table.sort(out, function(a, b)
    if a.sort ~= b.sort then return a.sort > b.sort end
    return mw.ustring.lower(a.rec.name or '') < mw.ustring.lower(b.rec.name or '')
  end)
  return out
end

local function arg1(frame)
  local k = frame.args[1] or ''
  return (k:gsub('^%s+', ''):gsub('%s+$', ''))
end

function p.boosters(frame)
  local key = arg1(frame)
  local list = p._boosters(key)
  if #list == 0 then
    return "''No heroes, blessings, upgrades, passives or Crux powers " ..
      "modify this stat in the current game data.''"
  end
  local out = { TBL, '|-',
    TH .. 'Source', TH .. 'Category', TH .. 'Tier / Type', TH .. 'Amount' }
  for _, e in ipairs(list) do
    out[#out+1] = '|-'
    out[#out+1] = '| ' .. Core.iconLink(e.rec, 24)
    out[#out+1] = '| ' .. e.cat
    out[#out+1] = '| ' .. ((e.tier ~= '') and e.tier or '—')
    out[#out+1] = '| data-sort-value="' .. tostring(e.sort) .. '" | ' .. e.value
  end
  out[#out+1] = '|}'
  return table.concat(out, '\n')
end

function p.weapons(frame)
  local key = arg1(frame)
  local list = p._weapons(key)
  if #list == 0 then
    return "''No weapons deal this damage type in the current game data.''"
  end
  local out = { TBL, '|-',
    TH .. 'Weapon', TH .. 'Class', TH .. 'Tier', TH .. key }
  for _, e in ipairs(list) do
    out[#out+1] = '|-'
    out[#out+1] = '| ' .. Core.iconLink(e.rec, 24)
    out[#out+1] = '| ' .. e.class
    out[#out+1] = '| ' .. e.tier
    out[#out+1] = '| data-sort-value="' .. tostring(e.sort) .. '" | ' .. e.value
  end
  out[#out+1] = '|}'
  return table.concat(out, '\n')
end

return p