Module:Infobox Skin

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

-- <nowiki>
--
-- Sandbox Module for [[Template:Infobox Skin]]
--
-- lua module for Infobox Skin
--

local p = {}

-- "imports"
local yesno = require('Module:Yesno')
local infobox = require('Module:Infobox')
local paramtest = require('Module:Paramtest')
local recolours = require('Module:Recolours')
local onmain = require('Module:Mainonly').on_main
local cleanimg = require('Module:Clean image').clean

-- Slot names as per wardrobe filter
local slotMap = {
	['eyes'] = 'Aura', ['eye'] = 'Aura', ['gaze'] = 'Aura', ['aura'] = 'Aura', ['auras'] = 'Aura',
	['cape'] = 'Back', ['back'] = 'Back',
	['wings'] = 'Wings', ['wing'] = 'Wings',
	['shield'] = 'Shield',
	['offhand'] = 'Off-hand', ['off-hand'] = 'Off-hand', ['off hand'] = 'Off-hand', ['weapon/offhand'] = 'Off-hand', 
	['weapon/off-hand'] = 'Off-hand', ['weapon/off hand'] = 'Off-hand', ['off'] = 'Off-hand', ['oh'] = 'Off-hand',
	['2h'] = 'Two-handed', ['2h weapon'] = 'Two-handed',
	['mainhand'] = 'Main hand', ['main-hand'] = 'Main hand', ['main hand'] = 'Main hand', ['weapon'] = 'Main hand',
	['main'] = 'Main hand', ['mh'] = 'Main hand', 
	['neck'] = 'Neck', ['necklace'] = 'Neck', ['amulet'] = 'Neck',
	['hands'] = 'Hands', ['hand'] = 'Hands', ['gloves'] = 'Hands', ['glove'] = 'Hands',
	['feet'] = 'Feet', ['shoes'] = 'Feet', ['foot'] = 'Feet', ['shoe'] = 'Feet',
	['legs'] = 'Legs', ['leg'] = 'Legs', ['pants'] = 'Legs', ['skirt'] = 'Legs',
	['body'] = 'Torso', ['torso'] = 'Torso', ['top'] = 'Torso',
	['head'] = 'Head', ['helmet'] = 'Head', ['helm'] = 'Head', ['cap'] = 'Head', ['hat'] = 'Head',
	['outfit'] = 'Set', ['set'] = 'Set'
}

-- Weapon types (only applies to weapons)
local weaponTypeMap = {
	['melee'] = 'Melee', ['dagger'] = 'Dagger', ['sword'] = 'Sword',
	['mace'] = 'Mace', ['axe'] = 'Axe', ['claw'] = 'Claw',
	['claws'] = 'Claw', ['whip'] = 'Whip', ['2h sword'] = '2h Sword',
	['spear'] = 'Spear', ['maul'] = 'Maul', ['crossbow'] = 'Crossbow', 
	['ranged'] = 'Ranged', ['range'] = 'Range', ['thrown'] = 'Thrown', 
	['throwing'] = 'Thrown', ['2h crossbow'] = '2h Crossbow', ['bow'] = 'Bow', 
	['magic'] = 'Magic', ['staff'] = 'Staff', ['wand'] = 'Wand', 
	['orb'] = 'Orb', ['book'] = 'Book', ['shield'] = 'Shield'
}

-- Weapon styles (melee/ranged/magic)
local weaponStyleCat = { 
	['melee'] = 'melee', ['dagger'] = 'melee', ['sword'] = 'melee', 
	['mace'] = 'melee', ['axe'] = 'melee', ['claw'] = 'melee', 
	['claws'] = 'melee', ['whip'] = 'melee', ['2h sword'] = 'melee', 
	['spear'] = 'melee', ['maul'] = 'melee', 
	['ranged'] = 'ranged', ['range'] = 'ranged', ['crossbow'] = 'ranged', 
	['thrown'] = 'ranged', ['throwing'] = 'ranged', ['2h crossbow'] = 'ranged', 
	['bow'] = 'ranged', ['magic'] = 'magic', ['staff'] = 'magic', 
	['wand'] = 'magic', ['orb'] = 'magic', ['book'] = 'magic', 
	['shield'] = 'Shield' 
}

-- Currency used for purchases
local currencyMap = {
	['runecoins'] = 'RuneCoins', ['runecoin'] = 'RuneCoins', ['rc'] = 'RuneCoins',
	['oddments'] = 'Oddments', ['oddment'] = 'Oddments', ['odd'] = 'Oddments', 
	['loyalty points'] = 'Loyalty points', ['loyalty point'] = 'Loyalty points',
	['loyalty'] = 'Loyalty points', ['lp'] = 'Loyalty points'
}

local defaultRecolours = {
	colour1 = '#181515', name1 = 'Dark grey',
	colour2 = '#333539', name2 = 'Slate grey',
	colour3 = '#9b938d', name3 = 'Silver',
	colour4 = '#f8e8d0', name4 = 'Ivory white',
	colour5 = '#d09038', name5 = 'Goldenrod',
	colour6 = '#a03800', name6 = 'Orange',
	colour7 = '#c07098', name7 = 'Pink',
	colour8 = '#981010', name8 = 'Red',
	colour9 = '#380088', name9 = 'Violet',
	colour10 = '#183038', name10 = 'Dark blue',
	colour11 = '#205878', name11 = 'Blue',
	colour12 = '#6888c0', name12 = 'Sky blue',
	colour13 = '#207870', name13 = 'Teal',
	colour14 = '#208830', name14 = 'Lawn green',
	colour15 = '#004008', name15 = 'Forest green',
	colour16 = '#281612', name16 = 'Brown'
}

function p.main(frame)
	-- Create Infobox ret
	local args = frame:getParent().args
	local ret = infobox.new(args)

	-- Parameters for the Infobox Skin Template
	ret:defineParams{
		{ name = 'name', func = 'name' },
		{ name = 'image', func = { name = imgarg, params = { 'image' }, flag = { 'd' } } },
		{ name = 'imagebackground', func = { name = imgback, params = { 'imagebackground' }, flag = { 'd' } }, dupes = true },
		{ name = 'vanchor', func = { name = 'has_content', params = { 'version' }, flag = 'p' } },
		{ name = 'release', func = 'release' },
		{ name = 'removal', func = 'removal' },
		{ name = 'update', func = 'update' },
		{ name = 'members', func = 'has_content' },
		{ name = 'slot', func = { name = slotarg, params = { 'slot' }, flag = { 'd' } } },
		{ name = 'type', func = { name = typearg, params = { 'type' }, flag = { 'd' } } },
		{ name = 'components', func = 'components' },
		{ name = 'recolour', func = 'recolour' },
		{ name = 'recolourdisp', func = { name = recolourdisp, params = { 'recolour' }, flag = { 'd' } } },
		{ name = 'currency', func = { name = currencyarg, params = { 'currency' }, flag = { 'd' } } },
		{ name = 'marketplace', func = 'has_content' },
		{ name = 'sgs', func = 'has_content' },
		{ name = 'freeprice', func = 'has_content' },
		{ name = 'memberprice', func = { name = memberpricearg, params = { 'freeprice', 'memberprice' }, flag = { 'd', 'd' } } },
		{ name = 'loyaltyprice', func = 'loyaltyprice' },
		{ name = 'description', func = 'description' },
		{ name = 'pvp', func = { name = pvparg, params = { 'pvp' }, flag = { 'd' } } } ,
	}
	
	ret:create()
	ret:cleanParams()
	
	ret:linkParams{
		image = 'imagebackground'}
	
	-- Set links for Module/Talk pages
	ret:defineLinks({
		links = {{ 'Template:%s', 'Infobox' },
		{ 'Template_talk:%s', 'Talk page' }}, colspan = 2 })
	
	-- Define Infobox name ({{Template:arg}})
	ret:defineName('Infobox Skin')
	ret:addClass('infobox-Skin')
	
	if onmain() then
		local a2 = ret:categoryData()
	end
	
	ret:addButtonsCaption()
	
	-- ~~~~~~~~~~ PARAMETERS ~~~~~~~~~~
	-- PARAMETER: image
	if yesno(ret:param('image')) ~= false then
		ret:addRow{
			{ tag = 'argd', content = 'image', class = 'infobox-image bordered-image', colspan = '2' },
			meta = { addClass = ret:param('imagebackground', 'r') }}
	end
	
	-- PARAMETER: name
	ret:addRow{
		{ tag = 'argh', content = 'name', class = 'infobox-header', colspan = '2' } }
	
	-- PARAMETER: release
	:addRow{ 
		{ tag = 'th', content = 'Release date' },
		{ tag = 'argd', content = 'release' } }
		
	-- PARAMETER: members
	ret:addRow{
		{ tag = 'th', content = '[[Members]]' },
		{ tag = 'argd', content = 'members' } }
	
	-- PARAMETER: slot
	if ret:param('slot') ~= 'Set' then
		ret:addRow{
			{ tag = 'th', content = 'Slot' },
			{ tag = 'argd', content = 'slot' } }
	end
	
	-- PARAMETER: type
	if ret:paramDefined('type') then
		ret:addRow{
			{ tag = 'th', content = 'Type' },
			{ tag = 'argd', content = 'type' } }
	end
	
	-- PARAMETER: components
	if ret:paramDefined('components') then
		ret:addRow{
			{ tag = 'th', content = 'Components' },
			{ tag = 'argd', content = 'components' } }
	end
	
	-- PARAMETER: currency
	if ret:paramDefined('currency') then
		ret:addRow{
			{ tag = 'th', content = 'Purchasable with' },
			{ tag = 'argd', content = 'currency' } }
	end
	
	-- PARAMETER: freeprice
	if ret:paramDefined('freeprice') then
		ret:addRow{
			{ tag = 'th', content = 'Free Player Price' },
			{ tag = 'argd', content = 'freeprice' } }
	end
	
	-- PARAMETER: memberprice
	if ret:paramDefined('memberprice') or ret:paramDefined('freeprice') then
		ret:addRow{
			{ tag = 'th', content = 'Member Price' },
			{ tag = 'argd', content = 'memberprice' } }
	end
	
	-- PARAMETER: loyaltyprice
	if ret:paramDefined('loyaltyprice') then
		ret:addRow{
			{ tag = 'th', content = '[[Loyalty points|Loyalty Points]]' },
			{ tag = 'argd', content = 'loyaltyprice' } }
	end
	
	-- PARAMETER: recolour
	ret:addRow{
		{ tag = 'th', content = 'Recolourable' },
		{ tag = 'argd', content = 'recolour' } }
	if ret:paramDefined('recolour') then
		if yesno(ret:param('recolour')) == true then
			ret:addRow{
				{ tag = 'th', content = 'Available colours', class = 'infobox-subheader', colspan = '2' } }
			ret:addRow{
				{ tag = 'argd', content = 'recolourdisp', colspan = '2',
				css = { ['max-width'] = '300px', ['text-align'] = 'center' } } }
		end
	end
	
	-- PARAMETER: description
	if ret:paramDefined('description') then
		ret:addRow{
			{ tag = 'th', content = 'Description', class = 'infobox-subheader', colspan = '2' } }
		ret:addRow{
			{ tag = 'argd', content = 'description', colspan = '2',
			css = { ['max-width'] = '300px', ['text-align'] = 'center' } } }
	end
	
	-- PARAMETER: pvp
	ret:addRow{
		{ tag = 'argd', content = 'pvp', colspan = '2',
		css = { ['max-width'] = '300px', ['text-align'] = 'center' } } }
	
	-- Finalise template
	ret:finish()
	if onmain() then
		local a1 = ret:param('all')
		local a2 = ret:categoryData()
		ret:wikitext(addcategories(a1,a2))
	end
	return ret:tostring()
end

-- Added check for multiple images so outfit sets can have all pieces displayed.
-- There is probably a better and more elegant way to achieve this.
function imgarg(arg)
	if infobox.isDefined(arg) then
		local str = ''
		for k, v in string.gmatch(arg, '([^,]+)') do
			str = str .. cleanimg{ file = k, width = 300, height = 300 }
		end
		return str
	end
	return nil
end

function imgback(arg)
	if infobox.isDefined(arg) then
		if yesno(arg) then
			return 'infobox-imgbg'
		end
	end
	return nil
end

-- The following two functions check that the params for 'slot' and 'type'
-- are a valid slot name and weapon type and aims to make them consistent.
-- 'mh', 'main', 'weapon', 'main hand' all display as 'Main hand'
function slotarg(arg)
	if infobox.isDefined(arg) then
		local str = string.lower(arg)
		if slotMap[str] then
		  return slotMap[str]
		end
	end
	return nil
end

function typearg(arg)
	if infobox.isDefined(arg) then
		local str = string.lower(arg)
		if weaponTypeMap[str] then
			return weaponTypeMap[str]
		end
	end
	return nil
end

-- Calls the recolour modules _main function to display the default recolours.
function recolourdisp(arg)
	if infobox.isDefined(arg) then
		if yesno(arg) then
			return recolours._main(defaultRecolours)
		else
			return nil
		end
	end
end

-- Sets the currency used to purchase the cosmetic override.
function currencyarg(arg)
	if infobox.isDefined(arg) then
		local str = string.lower(arg)
		if currencyMap[str] then
			return '[[' .. currencyMap[str] .. ']]'
		end
	end
	return nil
end

-- If member price isn't entered it will take 10% off the free price.
function memberpricearg(arg1,arg2)
	if infobox.isDefined(arg1) and not infobox.isDefined(arg2) then
		-- Member prices are rounded down to favour the customer.
		return math.floor(arg1 * 0.9)
	end
	return arg2
end

-- Defaults to display that it will NOT override in PVP-enabled areas.
function pvparg(arg)
	local str = ' not '
	if yesno(arg) == true then
		str = ' '
	end
	return '<b>This cosmetic will' .. str .. 'display<br />in [[PvP]]-enabled areas.</b>'
end

-- Used to give weapons the correct category
-- Staff, Wand, Orb all return "magic" as the style.
function getwepstyle(arg)
	if infobox.isDefined(arg) then
		local str = string.lower(arg)
		if weaponStyleCat[str] then
			return weaponStyleCat[str]
		end
	end
	return nil
end

-- Categories
function addcategories(args,catargs)
	local ret = { 'Cosmetic overrides' }
	
	local cat_map = {
		-- Added if the parameter has content
		defined = { 
			components = 'Set overrides'
		},
		-- Added if the parameter has no content
		notdefined = {
			image = 'Needs override image',
			members = 'Needs members status',
			release = 'Needs release date',
			update = 'Needs update added',
			slot = 'Needs slot type'
		}
	}
	
	-- Check for slot and weapon type and adds the correct categories.
	if args.slot.d == 'Main hand' or args.slot.d == 'Off-hand' or args.slot.d == 'Two-handed' or args.slot.d == 'Shield' then
		-- Make sure it's not a shield or it will be set to 'Shield weapon overrides'.
		if getwepstyle(args.type.d) ~= nil and args.type.d ~= 'Shield' then
			-- Add generic weapon override and type of weapon override.
			table.insert(ret, 'Weapon overrides')
			table.insert(ret, args.slot.d .. ' ' .. getwepstyle(args.type.d) .. ' weapon overrides')
		-- If the cosmetic is a shield we can just add the 'Shield overrides' category
		elseif getwepstyle(args.type.d) == 'Shield' or args.slot.d == 'Shield' then
				table.insert(ret, 'Shield overrides')
		end
	else
		-- If it's not a weapon, add the slot type override category (Head, Torso, Legs, etc).
		table.insert(ret, args.slot.d .. ' overrides')
	end
	
	-- Check if the cosmetic is purchasable on the marketplace
	if yesno(args.marketplace.d) == true then
		table.insert(ret, 'Marketplace')
	end
	
	-- Check if the cosmetic is purchasable on Solomon's
	if yesno(args.sgs.d) == true then
		table.insert(ret, 'Solomon\'s General Store')
	end
	
	-- Check if the cosmetic is recolourable
	if yesno(args.recolour.d) == true then
		table.insert(ret, 'Recolourable overrides')
	end
	
	-- Add defined categories
	for n, v in pairs(cat_map.defined) do
		if catargs[n] and catargs[n].one_defined then
			table.insert(ret,v)
		end
	end
	
	-- Add undefined categories
	for n, v in pairs(cat_map.notdefined) do
		if catargs[n] and catargs[n].all_defined == false then
			table.insert(ret,v)
		end
	end
	
	-- combine table and format category wikicode
	for i, v in ipairs(ret) do
		if (v ~= '') then
			ret[i] = string.format('[[Category:%s]]',v)
		end
	end

	return table.concat(ret,'')
end	

return p
-- </nowiki>