Module:AbilityInteraction

Revision as of 14:27, 15 July 2026 by Vergir (talk | contribs) (Use American spelling in comments per the style guide (with help from vergir-bot LLM))

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

-- Renders a standard interaction box for the interactions tab of {{AbilitySection}}.
-- Entry point: {{#invoke:AbilityInteraction|box}}, via Template:AbilityInteraction.
--
-- Presentation for each interaction lives in REGISTRY below. Call sites pick an
-- interaction by name and supply body text only; nothing else is customizable.
-- Anything bespoke should use {{IconBox}} directly rather than growing parameters here.
--
-- To add an interaction, add a REGISTRY entry:
--   aliases  = other names resolving to this entry; assumed not to overlap
--   title    = header text
--   type     = positive | negative | info
--   iconfile = image file name, without the File: prefix
--   link     = wiki page name, or a full URL

local p = {}

local getArgs = require('Module:Arguments').getArgs

local REGISTRY = {
	['debuff resist'] = {
		aliases  = { 'debuff reducer' },
		title    = 'Debuff Resist',
		type     = 'negative',
		iconfile = 'Debuff Reducer.png',
		link     = 'Debuff Resist',
	},
	['dispel'] = {
		aliases  = { 'dispel magic', 'purge', 'cleanse' },
		title    = 'Dispel',
		type     = 'negative',
		iconfile = 'Dispel Magic.png',
		link     = 'Dispel Magic',
	},
	['unstoppable'] = {
		aliases  = {},
		title    = 'Unstoppable',
		type     = 'negative',
		iconfile = 'Unstoppable.png',
		link     = 'Unstoppable',
	},
	['slowing hex'] = {
		aliases  = {},
		title    = 'Slowing Hex',
		type     = 'info',
		iconfile = 'Slowing Hex.png',
		link     = 'Slowing Hex',
	},
	['indomitable'] = {
		aliases  = {},
		title    = 'Indomitable',
		type     = 'negative',
		iconfile = 'Indomitable.png',
		link     = 'Indomitable',
	},
}

-- Lookup index of aliases plus canonical keys, built once.
-- Canonical keys are registered last so they always win.
local index = {}
for _, entry in pairs(REGISTRY) do
	for _, alias in ipairs(entry.aliases or {}) do
		index[alias] = entry
	end
end
for key, entry in pairs(REGISTRY) do
	index[key] = entry
end

local function err(msg)
	return '<strong class="error">AbilityInteraction: ' .. mw.text.nowiki(msg) .. '</strong>'
end

function p.box(frame)
	local args = getArgs(frame)

	local state = mw.ustring.lower(mw.text.trim(args.state or ''))
	local key   = mw.ustring.lower(mw.text.trim(args.interaction or ''))

	if key == '' then
		return err('no interaction specified')
	end

	local entry = index[key]
	if entry == nil then
		return err('unknown interaction "' .. key .. '"')
	end

	-- A disabled box means the interaction does not apply, so it carries no
	-- valence; the neutral header overrides the registry type.
	local box_type = entry.type
	if state == 'disabled' then
		box_type = 'info'
	end

	return frame:expandTemplate{
		title = 'IconBox',
		args  = {
			title    = entry.title,
			type     = box_type,
			iconfile = entry.iconfile,
			link     = entry.link,
			state    = state,
			text     = args.text or '',
		},
	}
end

-- Registry table for the documentation page. Not used in article space.
function p.list(frame)
	local keys = {}
	for key in pairs(REGISTRY) do
		table.insert(keys, key)
	end
	table.sort(keys)

	local out = { '{| class="wikitable"', '! Interaction !! Aliases !! Type !! Example' }
	for _, key in ipairs(keys) do
		local entry = REGISTRY[key]
		local aliases = {}
		for _, alias in ipairs(entry.aliases or {}) do
			table.insert(aliases, '<code>' .. alias .. '</code>')
		end
		table.insert(out, '|-')
		table.insert(out, '| <code>' .. key .. '</code>')
		table.insert(out, '| ' .. (#aliases > 0 and table.concat(aliases, ', ') or '—'))
		table.insert(out, '| ' .. entry.type)
		table.insert(out, '| ' .. frame:expandTemplate{
			title = 'AbilityInteraction',
			args  = { interaction = key, text = 'Example text.' },
		})
	end
	table.insert(out, '|}')
	return table.concat(out, '\n')
end

return p