Jump to content

Module:Stat

From Community Wiki | Soulbound: Online

Renders game stat keys as player-facing names, units, ranges and rarity names. It holds the logic; the vocabulary it reads — labels, units, the rarity map — is in Module:Gear/data. Add a stat there, not here.

It replaced the long #switch chains that used to live in {{Stat}} , {{Stat/unit}}

and {{RollStat}}

. Each of those templates is now a single #invoke line with the same name and the same parameters, so no article needed changing.

Entry points

Call Used by Returns
{{#invoke:Stat|name|<key>}} {{Stat}} The stat's label — normally a link. An unknown key returns itself, unlinked, so a stat the wiki does not know about is visible rather than silently missing.
{{#invoke:Stat|unit|<key>}} {{Stat/unit}} % or an empty string. Unknown keys give an empty string.
{{#invoke:Stat|range|min|max|unit=%}} {{Range}} +(2–10)%. With max omitted, empty, or equal to min it collapses to a flat +10%. An empty min returns nothing at all.
{{#invoke:Stat|rollstat|<key>|min|max}} {{RollStat}} One sb-roll-stat chip: the stat's label, a space, then the range with the unit filled in from the stat's own entry. The dot between adjacent chips comes from CSS, not from here — callers must not type separators.
{{#invoke:Stat|rarity|<0-5>}} {{Rarity}} The colour-coded rarity name. 0 gives "None"; anything blank or outside 0–5 gives "Unknown" in the plain style rather than an error.

p._range(min, max, unit) is exported for Lua callers — a future module that needs the same +(2–10)% formatting should call it rather than re-implement the format.

Conventions this module owns

  • Signs. A positive value gets a +; a leading - is preserved as-is. Callers pass bare numbers and never their own sign.
  • Ranges are text, not numbers. They carry data-min and data-max attributes on the span for any future sorting or calculator work. Never run #expr over a range in wikitext — that is how other game wikis filled up with "Expression error".
  • Styling. Each function that emits markup attaches Template:ItemStyles/styles.css itself with frame:extensionTag, so a caller never has to remember a <templatestyles /> tag. That is also why the chip separator in the CSS must stay a general sibling selector (~): the injected style elements sit between the chips.

Changing it

Almost nothing that people want to change lives here. Adding a stat, renaming one, fixing a unit, or changing a rarity name is all Module:Gear/data. Come here only to change how something is formatted.

If you do: test in the debug console at the bottom of Module:Stat first (for example =p._range('2','10','%')), then preview a real page — Cursed Tritanium Sword exercises every function on this list — and confirm Category:Pages with script errors

is still empty afterwards.

See also


-- Module:Stat — renders game stat keys as player-facing names, units and roll lines.
-- Replaces the #switch chains in Template:Stat, Template:Stat/unit and Template:RollStat.
-- The vocabulary lives in Module:Gear/data; add stats there, not here.

local data = mw.loadData('Module:Gear/data')
local p = {}

local STYLES = 'ItemStyles/styles.css'

local function key(frame, i)
	local v = frame.args[i or 1]
	return v and mw.text.trim(v) or ''
end

local function entry(k)
	return data.stats[k]
end

-- {{#invoke:Stat|name|<key>}} -> linked display name; unknown keys render as themselves
function p.name(frame)
	local k = key(frame)
	local e = entry(k)
	return e and e.label or k
end

-- {{#invoke:Stat|unit|<key>}} -> "%" or ""
function p.unit(frame)
	local e = entry(key(frame))
	return e and e.unit or ''
end

-- number -> "+5" / "-5" / "+0.5", preserving the sign convention of the old templates
local function signed(n)
	local s = mw.text.trim(tostring(n or ''))
	if s == '' then return nil end
	if s:sub(1, 1) == '-' then return s end
	return '+' .. s
end

-- shared by Template:Range and the roll lines: "+(2–10)%" or "+10%"
function p._range(min, max, unit)
	unit = unit or ''
	min = min and mw.text.trim(min) or ''
	max = max and mw.text.trim(max) or ''
	if min == '' then return '' end
	if max == '' or max == min then
		return (signed(min) or '') .. unit
	end
	return mw.ustring.format(
		'<span class="sb-range" data-min="%s" data-max="%s">+(%s–%s)%s</span>',
		min, max, min, max, unit)
end

-- {{#invoke:Stat|range|min|max|unit=%}}
function p.range(frame)
	local a = frame.args
	local out = p._range(a[1], a[2], a.unit)
	if out == '' then return '' end
	return frame:extensionTag{ name = 'templatestyles', args = { src = STYLES } } .. out
end

-- {{#invoke:Stat|rollstat|<key>|min|max}} -> one inline bonus-stat chip
function p.rollstat(frame)
	local a = frame.args
	local k = mw.text.trim(a[1] or '')
	local e = entry(k)
	local label = e and e.label or k
	local unit = e and e.unit or ''
	return frame:extensionTag{ name = 'templatestyles', args = { src = STYLES } }
		.. '<span class="sb-roll-stat">' .. label .. ' ' .. p._range(a[2], a[3], unit) .. '</span>'
end

-- {{#invoke:Stat|rarity|<0-5>}} -> colour-coded rarity name
function p.rarity(frame)
	local n = tonumber(key(frame))
	local r = (n and data.rarity[n]) or data.rarity[0]
	local cls = (n and data.rarity[n]) and r.cls or 'sb-q0'
	local name = (n and data.rarity[n]) and r.name or 'Unknown'
	return frame:extensionTag{ name = 'templatestyles', args = { src = STYLES } }
		.. '<span class="sb-q ' .. cls .. '">' .. name .. '</span>'
end

return p