automation
automation
Line 50: Line 50:
local info = TYPES[t]
local info = TYPES[t]
if not info then return t end
if not info then return t end
return string.format('[[File:%s{{!}}16x16px{{!}}link=%s]] [[%s{{!}}%s]]', info.t1, info.link, info.link, t)
return string.format('[[File:%s|16x16px|link=%s]] [[%s|%s]]', info.t1, info.link, info.link, t)
end
end


Line 80: Line 80:
applies[#applies + 1] = typeLink(t)
applies[#applies + 1] = typeLink(t)
end
end
out[#out + 1] = table.concat({
out[#out + 1] = frame:expandTemplate{ title = 'ItemInfobox', args = {
'{{ItemInfobox',
title = r.name .. ' Skin',
'| title = ' .. r.name .. ' Skin',
images = spriteFile(r),
'| images = ' .. spriteFile(r),
Desc = r.desc,
'| Desc = ' .. r.desc,
Ability = "'''Applies to:'''<br>" .. table.concat(applies, '<br>'),
"| Ability = '''Applies to:'''<br>" .. table.concat(applies, '<br>'),
Drop = r.obtained,
'| Drop = ' .. r.obtained,
} }
'}}',
}, '\n')
end
end
end
end

Revision as of 12:25, 16 June 2026

Module:Reskins holds the master list of cosmetic reskin items (Cherub, Halloween, Valentine's, Christmas, Custom) and renders them either as a gallery for a theme page or as an "Applicable Reskins" list inside an item's infobox.

Overview

A "reskin" is a cosmetic skin that can be applied to one or more item types (e.g. the Christmas "Sharpened Candy Cane" reskins any Sword). All of the reskins the wiki knows about are stored as a single Lua table inside this module — each entry records the skin's name, its theme, where it's obtained, a flavour desc, and the list of item types it applies to.

The module is used two ways:

  1. On theme pages (e.g. the Cherub reskins template) — it renders a full infobox gallery of every reskin in that theme.
  2. Inside {{ItemInfobox}} — for a given item type it lists the named reskins that can be applied to that type, in the infobox's "Applicable Reskins" section.

Because the data lives in this module, adding or editing a reskin means editing the reskins table here — there is no separate per-reskin page to maintain.

Functions / entry points

Function (#invoke) What it does Called by
p.forType Given an item type name (e.g. Sword), returns a
-separated list of clickable reskin entries (sprite icon + "<Name> Skin" linking to the Reskins page) for every reskin whose types include that type. Skips themes flagged NO_APPLY (currently Custom). Used to fill the Reskins section of an item infobox.
{{ItemInfobox}} (via )
p.theme Given a theme key (e.g. Cherub), renders a full {{ItemInfobox}} for every reskin in that theme — using the skin's sprite, description, "Applies to:" type list, and "obtained" text. Returns No reskins in this category yet. if the theme has none. Theme listing templates, e.g. {{Cherub/Reskins}}, {{Christmas/Reskins}}, {{Custom/Reskins}}

How it's used

Inside the item infobox (already wired into {{ItemInfobox}} — editors don't add this themselves). The infobox only requests reskins for untiered items (when none of T1–T8 are set):

|ReskinList={{#if:{{{T1|}}}...{{{T8|}}}||{{#invoke:Reskins|forType|{{{type|{{#var:itemtype}}}}}}}}}

On a theme page (e.g. the Cherub reskins listing template):

<div class="display-items">
{{#invoke:Reskins|theme|Cherub}}
</div>

To add a new reskin, edit the reskins table in the module and give it a name, theme, obtained, desc and types. To list a new theme on its own page, create a template that calls No reskins in this category yet..

Notes

  • Sprite file naming. Reskin sprite files are built automatically as <ThemePrefix>Reskin-<NameWithoutSpaces>.png. The theme prefixes are: Cherub → CH, Halloween → H, Valentines → V, Christmas → C, Custom → Custom. Example: the Cherub "Blade of False Eden" expects File:CHReskin-BladeOfFalseEden.png. The name is title-cased and stripped of spaces before the prefix is added, so the uploaded file must match that exact form.
  • Type → sprite/link table. The module's TYPES table maps each item type to a T1 icon (e.g. T1Sword.png) and a section link (e.g. Weapons#Swords, Abilities#Bombs, or just Armours). This is used by p.theme to render the clickable "Applies to:" list.
  • Custom theme is excluded from item infoboxes. NO_APPLY = { Custom = true } means custom/community reskins are shown only on their own theme page via p.theme, not in the per-item "Applicable Reskins" list.
  • The CLAUDE/project convention notes that reskins live on a separate page rather than on the base item's page; this module is the mechanism behind that separation.
  • Related: {{Infobox}}m (renders each infobox), {{Equipment}}m and {{Shinies}}m (sibling display modules), {{ItemInfobox}}.

local p = {}

local reskins = {
	{ name = 'Bramble Bow', theme = 'Halloween', obtained = 'Halloween Event', desc = 'Woven from cursed brambles that thirst for wandering souls.', types = { 'Bow' } },
}

local THEME_PREFIX = { Cherub = 'CH', Halloween = 'H', Valentines = 'V', Christmas = 'C', Custom = 'Custom' }
local NO_APPLY = { Custom = true }

local TYPES = {
	['Sword']     = { t1 = 'T1Sword.png',     link = 'Weapons#Swords' },
	['Katana']    = { t1 = 'T1Katana.png',    link = 'Weapons#Katanas' },
	['Bow']       = { t1 = 'T1Bow.png',       link = 'Weapons#Bows' },
	['Dagger']    = { t1 = 'T1Dagger.png',    link = 'Weapons#Daggers' },
	['Staff']     = { t1 = 'T1Staff.png',     link = 'Weapons#Staves' },
	['Sceptre']   = { t1 = 'T1Sceptre.png',   link = 'Weapons#Sceptres' },
	['Bomb']      = { t1 = 'T1Bomb.png',      link = 'Abilities#Bombs' },
	['Jewel']     = { t1 = 'T1Jewel.png',     link = 'Abilities#Jewels' },
	['Poison']    = { t1 = 'T1Poison.png',    link = 'Abilities#Poisons' },
	['Emblem']    = { t1 = 'T1Emblem.png',    link = 'Abilities#Emblems' },
	['Scripture'] = { t1 = 'T1Scripture.png', link = 'Abilities#Scriptures' },
	['Orb']       = { t1 = 'T1Orb.png',       link = 'Abilities#Orbs' },
	['Star']      = { t1 = 'T1Star.png',      link = 'Abilities#Stars' },
	['Kunai']     = { t1 = 'T1Kunai.png',     link = 'Abilities#Kunais' },
	['Shield']    = { t1 = 'T1Shield.png',    link = 'Abilities#Shields' },
	['Cloak']     = { t1 = 'T1Cloak.png',     link = 'Abilities#Cloaks' },
	['Skull']     = { t1 = 'T1Skull.png',     link = 'Abilities#Skulls' },
	['Trap']      = { t1 = 'T1Trap.png',      link = 'Abilities#Traps' },
	['Heavy Helmet']       = { t1 = 'T1HeavyH.png', link = 'Armours' },
	['Heavy Chestplate']   = { t1 = 'T1HeavyC.png', link = 'Armours' },
	['Heavy Leggings']     = { t1 = 'T1HeavyL.png', link = 'Armours' },
	['Heavy Boots']        = { t1 = 'T1HeavyB.png', link = 'Armours' },
	['Light Helmet']       = { t1 = 'T1LightH.png', link = 'Armours' },
	['Light Chestplate']   = { t1 = 'T1LightC.png', link = 'Armours' },
	['Light Leggings']     = { t1 = 'T1LightL.png', link = 'Armours' },
	['Light Boots']        = { t1 = 'T1LightB.png', link = 'Armours' },
	['Magical Helmet']     = { t1 = 'T1MagicH.png', link = 'Armours' },
	['Magical Chestplate'] = { t1 = 'T1MagicC.png', link = 'Armours' },
	['Magical Leggings']   = { t1 = 'T1MagicL.png', link = 'Armours' },
	['Magical Boots']      = { t1 = 'T1MagicB.png', link = 'Armours' },
}

local function spriteFile(r)
	local s = r.name:gsub("(%a)([%w']*)", function(a, b) return a:upper() .. b end)
	s = s:gsub("%s+", "")
	return (THEME_PREFIX[r.theme] or '') .. 'Reskin-' .. s .. '.png'
end

local function typeLink(t)
	local info = TYPES[t]
	if not info then return t end
	return string.format('[[File:%s|16x16px|link=%s]] [[%s|%s]]', info.t1, info.link, info.link, t)
end

function p.forType(frame)
	local t = mw.text.trim(frame.args[1] or '')
	if t == '' then return '' end
	local out = {}
	for _, r in ipairs(reskins) do
		if not NO_APPLY[r.theme] then
			for _, rt in ipairs(r.types) do
				if rt == t then
					out[#out + 1] = string.format(
						'[[File:%s|16x16px|link=Reskins]] [[Reskins|%s]]', spriteFile(r), r.name .. ' Skin')
					break
				end
			end
		end
	end
	return table.concat(out, '<br>')
end

function p.theme(frame)
	local key = mw.text.trim(frame.args[1] or '')
	local out = {}
	for _, r in ipairs(reskins) do
		if r.theme == key then
			local applies = {}
			for _, t in ipairs(r.types) do
				applies[#applies + 1] = typeLink(t)
			end
			out[#out + 1] = frame:expandTemplate{ title = 'ItemInfobox', args = {
				title = r.name .. ' Skin',
				images = spriteFile(r),
				Desc = r.desc,
				Ability = "'''Applies to:'''<br>" .. table.concat(applies, '<br>'),
				Drop = r.obtained,
			} }
		end
	end
	if #out == 0 then return "''No reskins in this category yet.''" end
	return table.concat(out, '\n')
end

return p