Módulo:Infobox Bonuses new

De RuneScape Wiki
Ir para: navegação, pesquisa
Documentação do módulo
Esta documentação é transcluída de Predefinição:Sem documentação/doc. [editar] [atualizar]
Este módulo não possui nenhuma documentação. Por favor, considere adicionar uma documentação em Módulo:Infobox Bonuses new/doc. [editar]
-- <nowiki>
--[=[
-- Implements [[Template:Infobox Bonuses]]
--]=]

local p = {}
local infobox = require('Módulo:Infobox')
local onmain = require('Módulo:Mainonly').on_main
local paramtest = require('Módulo:Paramtest')
local yesno = require('Módulo:Yesno')
local skillpic = require('Módulo:Ícone')._main
local editbutton = require('Módulo:Edit button')
local commas = require('Módulo:Addcommas')._add
local chargedrain = require('Módulo:Augmented degrade')
local attack_speed_bar = require('Módulo:Barra de velocidade de ataque').weapon

-- Accepted slot names
local slots = {
	head = 'head',
	neck = 'neck',
	back = 'back',
	cape = 'back',
	torso = 'torso',
	body = 'torso',
	legs = 'legs',
	hands = 'hands',
	feet = 'feet',
	ammo = 'ammo',
	ring = 'ring',
	aura = 'aura',
	pocket = 'pocket',
	sigil = 'sigil',
	main = 'main hand weapon',
	['main hand'] = 'main hand weapon',
	['main-hand'] = 'main hand weapon',
	mainhand = 'main hand weapon',
	weapon = 'main hand weapon',
	['2h'] = '2h weapon',
	['off-hand'] = 'off-hand',
	offhand = 'off-hand',
	shield = 'off-hand',
	['off-hand weapon'] = 'off-hand weapon',
	['offhand weapon'] = 'off-hand weapon',
	ohw = 'off-hand weapon',
	set = 'e',
	none = 'e'
	-- Traduzir daqui pra baixo o 1° termo, o q vai antes do =
	--[[ 
	elmo = 'elmo',
	['cabeça'] = 'elmo',
	colar = 'colar',
	amuleto = 'colar',
	capa = 'capa',
	corpo = 'corpo',
	tronco = 'corpo',
	cota = 'corpo',
	perneiras = 'pernas',
	pernas = 'pernas'
	luvas = 'luvas',
	botas = 'botas',
	['munição'] = 'munições',
	['munições'] = 'munições',
	anel = 'anel',
	aura = 'aura',
	bolso = 'bolso',
	selo = 'selo',
	arma = 'arma de mão primária',
	['arma de mão primária'] = 'arma de mão primária',
	['2m'] = 'arma de 2m',
	['duas mãos'] = 'arma de 2m'
	['mão secundária'] = 'mão secundária',
	escudo = 'mão secundária',
	['arma de mão secundária'] = 'arma de mão secundária',
	['arma secundária'] = 'arma de mão secundária',
	--]]
}

-- Categories for slots
local slot_cats = {
	head = 'Head slot items',
	neck = 'Neck slot items',
	back = 'Back slot items',
	torso = 'Torso slot items',
	legs = 'Legs slot items',
	hands = 'Hand slot items',
	feet = 'Feet slot items',
	ammo = 'Ammunition slot items',
	ring = 'Rings',
	aura = 'Auras',
	pocket = 'Pocket slot items',
	sigil = 'Sigil slot items',
	['main hand weapon'] = 'Main hand slot items',
	['2h weapon'] = 'Two-handed slot items',
	['off-hand'] = 'Off-hand slot items',
	['off-hand weapon'] = 'Off-hand slot weapon',
	e = '',
	-- Mesmo esquema aqui
	--[[ 
	elmo = 'Item de slot de elmo',
	colar = 'Item de slot de colar',
	capa = 'Item de slot de capa',
	corpo = 'Item de slot de corpo',
	pernas = 'Item de slot de pernas',
	luvas = 'Item de slot de luvas',
	botas = 'Item de slot de botas',
	['munições'] = 'Itens de slot de munições',
	anel = 'Anel',
	aura = 'Aura',
	bolso = 'Item de slot de bolso',
	selo = 'Item de slot de selo',
	['arma de mão primária'] = 'Item de slot de arma de mão primária',
	['arma de duas-mãos'] = 'Item de slot de arma de duas-mãos',
	['mão secundária'] = 'Item de slot de mão secundária',
	['arma de mão secundária'] = 'Item de slot de arma de mão secundária'
	--]]
}

-- Images used for slot display
local slot_images = {
	head = '[[Ficheiro:Slot de elmo.png|link=Slot de elmo]]',
	ammo = '[[Ficheiro:Slot de munições.png|link=Slot de munições]]',
	neck = '[[Ficheiro:Slot de colar.png|link=Slot de colar]]',
	back = '[[Ficheiro:Slot de capa.png|link=Slot de capa]]',
	['main hand weapon'] = '[[Ficheiro:Slot de arma.png|link=Slot de arma]]',
	['2h weapon'] = '[[Ficheiro:Slot de duas-mãos.png|link=Slot de duas-mãos]]',
	torso = '[[Ficheiro:Slot de cota.png|link=Slot de cota]]',
	['off-hand'] = '[[Ficheiro:Slot de escudo.png|link=Slot de escudo]]',
	['off-hand weapon'] = '[[Ficheiro:Slot de escudo.png|link=Slot de escudo]]',
	legs = '[[Ficheiro:Slot de perneiras.png|link=Slot de perneiras]]',
	hands = '[[Ficheiro:Slot de luvas.png|link=Slot de luvas]]',
	feet = '[[Ficheiro:Slot de botas.png|link=Slot de botas]]',
	ring = '[[Ficheiro:Slot de anel.png|link=Slot de anel]]',
	aura = '[[Ficheiro:Slot de aura.png|link=Slot de aura]]',
	pocket = '[[Ficheiro:Slot de bolso.png|link=Slot de bolso]]',
	sigil = '[[Ficheiro:Slot de selo.png|link=Slot de selo]]',
	e = 'Nenhum'
}

-- 'invention slots'
local inv_slots = {
	['main hand weapon'] = 'mp',
	['2h weapon'] = '2m',
	['off-hand'] = 'oh',
	['off-hand weapon'] = 'oh',
	shield = 'shield',
	torso = 'body',
	legs = 'legs',
	tool = 'tool',
	t = 'tool'
}

-- Accepted class names
local classes = {
	melee = 'corpo a corpo',
	ranged = 'combate à distância',
	ranging = 'combate à distância',
	range = 'combate à distância',
	magic = 'magia',
	mage = 'magia',
	all = 'tudo',
	hybrid = 'híbrido',
	none = 'nenhuma',
	['n/a'] = 'nenhuma',
	['n/d'] = 'nenhuma',
	ataque = 'corpo a corpo',
	['corpo a corpo'] = 'corpo a corpo',
	['força'] = 'corpo a corpo',
	['distância'] = 'combate à distância',
	['combate'] = 'combate à distância',
	['combate à distância'] = 'combate à distância',
	magia = 'magia',
	tudo = 'tudo',
	['híbrido'] = 'híbrido',
	nenhuma = 'nenhuma',
	nenhum = 'nenhuma',
	nada = 'nenhuma'
}

-- Classes with images
local class_img = {
	['corpo a corpo'] = '[[Ficheiro:Ataque ícone.png|x24px|link=Corpo a corpo]]',
	['combate à distância'] = '[[Ficheiro:Combate à Distância ícone.png|x24px|link=Combate à Distância]]',
	magia = '[[Ficheiro:Magia ícone.png|x24px|link=Magia]]',
	['híbrido'] = '[[Ficheiro:Combate ícone.png|x24px|link=Armadura#Híbrido]]',
	tudo = '[[Ficheiro:Combate ícone.png|x24px|link=Armadura#Todos]]',
	nenhuma = ''
}

local class_cats = {
	['corpo a corpo'] = 'Corpo a Corpo',
	magia = 'Magia',
	['combate à distância'] = 'Combate à Distância',
	['híbrido'] = 'Híbrido',
	tudo = 'Híbrido',
	nenhuma = 'Sem classe',
}

-- Accepted style names
local styles = {
	stab = 'Perfuração',
	stabbing = 'Perfuração',
	['perfuração'] = 'Perfuração',
	perfurar = 'Perfuração',
	slash = 'Dilacerar',
	slashing = 'Dilacerar',
	dilacerar = 'Dilacerar',
	['dilaceração'] = 'Dilacerar',
	crush = 'Esmagar',
	crushing = 'Esmagar',
	esmagar = 'Esmagar',
	esmagamento = 'Esmagar',
	arrow = 'Flechas',
	arrows = 'Flechas',
	flecha = 'Flechas',
	flechas = 'Flechas',
	seta = 'Flechas',
	setas = 'Flechas',
	bolt = 'Setas',
	bolts = 'Setas',
	thrown = 'Arremesso',
	throwing = 'Arremesso',
	arremesso = 'Arremesso',
	arremessar = 'Arremesso',
	magic = 'Feitiços',
	spell = 'Feitiços',
	spells = 'Feitiços',
	magia = 'Feitiços',
	['feitiços'] = 'Feitiços',
	['feitiço'] = 'Feitiços',
	none = 'Sem estilo',
	['n/a'] = 'Sem estilo',
}

-- Categories for styles
local style_cats = {
	stab = 'Armas de perfuração',
	['perfuração'] = 'Armas de perfuração',
	slash = 'Armas de dilacerar',
	dilacerar = 'Armas de dilacerar',
	crush = 'Armas de esmagar',
	esmagar = 'Armas de esmagar',
	thrown = 'Armas de arremesso',
	arremesso = 'Armas de arremesso'
	-- Traduzir os 'entre aspas simples' e adicionar as versões em pt-br dos
	-- antes de =
}

local types = {
	-- mesmo esquema do acima
	power = 'Armadura de dano',
	dano = 'Amadura de dano',
	['power armour'] = 'Armadura de dano',
	['armadura de dano'] = 'Armadura de dano',
	tank = 'Armadura de tanque',
	tanque = 'Armadura de tanque',
	['tank armour'] = 'Armadura de tanque',
	['armadura de tanque'] = 'Armadura de tanque',
	pvp = 'Armadura de PvP',
	['pvp armour'] = 'Armadura de PvP',
	['armadura de PvP'] = 'Armadura de PvP',
	shieldbow = 'Arco-escudo',
	['arco-escudo'] = 'Arco-escudo',
	shortbow = 'Arco curto',
	['arco curto'] = 'Arco curto',
	defender = 'Defensor',
	defensor = 'Defensor',
	repriser = 'Repulsor',
	repulsor = 'Repulsor',
	rebounder = 'Ressaltador',
	ressaltador = 'Ressaltador',
	halberd = 'Alabarda',
	alabarda = 'Alabarda',
	shield = 'Escudo',
	escudo = 'Escudo',
	chargebow = 'Autoarco',
	autoarco = 'Autoarco',
	cosmetic = 'Estético',
	['estético'] = 'Estético',
	['prevents attack'] = 'Previne o ataque',
	['previne o ataque'] = 'Previne o ataque',
	
	-- weapon diversity
	dagger = 'Adaga',
	adaga = 'Adaga',
	spear = 'Lança',
	['lança'] = 'Lança',
	scimitar = 'Cimitarra',
	cimitarra = 'Cimitarra',
	['2h sword'] = 'Espada de 2m',
	['espada 2m'] = 'Espada de 2m',
	['espada de 2m'] = 'Espada de 2m',
	['two handed sword'] = 'Espada de 2m',
	['espada de duas mãos'] = 'Espada de 2m',
	mace = 'Maça',
	['maça'] = 'Maça',
	maul = 'Malho',
	malho = 'Malho',
	['1h crossbow'] = 'Balestra',
	['balestra de 1m'] = 'Balestra',
	['balestra 1m'] = 'Balestra',
	['one handed crossbow'] = 'Balestra',
	['balestra de mão primária'] = 'Balestra',
	['balestra primária'] = 'Balestra',
	['crossbow'] = 'Balestra',
	balestra = 'Balestra',
	['2h crossbow'] = 'Balestra de 2m',
	['balestra de 2m'] = 'Balestra de 2m',
	['balestra 2m'] = 'Balestra de 2m',
	['two handed crossbow'] = 'Balestra de 2m',
	['balestra de duas mãos'] = 'Balestra de 2m',
	['throwing knife'] = 'Faca de arremesso',
	['faca de arremesso'] = 'Faca de arremesso',
	['throwing axe'] = 'Machado de arremesso',
	['machado de arremesso'] = 'Machado de arremesso',
}

local type_cats = {
	-- mesmo esquema do acima
	['cosmetic'] = { '[[Estético]]' },
	['estético'] = { '[[Estético]]' },
	['power armour'] = { '[[Armadura de dano]]', 'Armadura de dano' },
	['armadura de dano'] = { '[[Armadura de dano]]', 'Armadura de dano' },
	['tank armour'] = { '[[Armadura de tanque]]', 'Armadura de tanque' },
	['armadura de tanque'] = { '[[Armadura de tanque]]', 'Armadura de tanque' },
	['pvp armour'] = { '[[Armadura de PvP]]', 'Armadura de PvP' },
	['armadura de pvp'] = { '[[Armadura de PvP]]', 'Armadura de PvP' },
	shieldbow = { '[[Arco-escudo (tipos de arco)|Arco-escudo]]', 'Arco-escudo' },
	['arco-escudo'] = { '[[Arco-escudo (tipos de arco)|Arco-escudo]]', 'Arco-escudo' },
	shortbow = { '[[Arco curto (tipos de arco)|Arco curto]]','Arco curto' },
	['arco curto'] = { '[[Arco curto (tipos de arco)|Arco curto]]', 'Arco curto' },
	defender = { '[[Defensor]]', 'Defensores' },
	defensor = { '[[Defensor]]', 'Defensores' },
	repriser = { '[[Repulsor]]', 'Defensores' },
	repulsor = { '[[Repulsor]]', 'Defensores' },
	rebounder = { '[[Ressaltador]]', 'Defensores' },
	ressaltador = { '[[Ressaltador]]', 'Defensores' },
	halberd = { '[[Alabarda]]', 'Alabardas' },
	alabarda = { '[[Alabarda]]', 'Alabardas' },
	shield = { '[[Escudo]]', 'Escudos' },
	escudo = { '[[Escudo]]', 'Escudos' },
	chargebow = { '[[Autoarco (tipos de arco)|Autoarco]]', 'Autoarcos' },
	autoarco = { '[[Autoarco (tipos de arco)|Autoarco]]', 'Autoarcos' },
	['prevents attack'] = { 'Previne o ataque', 'Itens que previnem o ataque' },
	['previne o ataque'] = { 'Previne o ataque', 'Itens que previnem o ataque' },
	dagger = { '[[Adaga]]', 'Adagas' },
	adaga = { '[[Adaga]]', 'Adagas' },
	spear = { '[[Lança]]', 'Lanças' },
	['lança'] = { '[[Lança]]', 'Lanças' },
	scimitar = { '[[Cimitarra]]', 'Cimitarras' },
	cimitarra = { '[[Cimitarra]]', 'Cimitarras' },
	['2h sword'] = { '[[Espada de duas mãos|Espada de 2m]]', 'Espadas de duas mãos'},
	['espada de 2m'] = { '[[Espada de duas mãos|Espada de 2m]]', 'Espadas de duas mãos'},
	mace = { '[[Maça]]', 'Maças' },
	['maça'] = { '[[Maça]]', 'Maças' },
	maul = { '[[Malho]]', 'Malhos' },
	malho = { '[[Malho]]', 'Malhos' },
	['crossbow'] = { '[[Balestra (tipos de balestra)|Balestra]]', 'Balestra primária' },
	balestra = { '[[Balestra (tipos de balestra)|Balestra]]', 'Balestra primária' },
	['2h crossbow'] = { '[[Balestra de duas mãos|Balestra de 2m]]', 'Balestra de duas mãos' },
	['balestra de 2m'] = { '[[Balestra de duas mãos|Balestra de 2m]]', 'Balestra de duas mãos' },
	['throwing knife'] = { '[[Faca de arremesso]]', 'Faca de arremesso' },
	['faca de arremesso'] = { '[[Faca de arremesso]]', 'Facas de arremesso' },
	['throwing axe'] = { '[[Machados de arremesso|Machado de arremesso]]', 'Machados de arremesso' },
	['machado de arremesso'] = { '[[Machados de arremesso|Machado de arremesso]]', 'Machados de arremesso' },
}

local reduction_types = { -- accepts type or class
	-- mesmo esquema do acima
	['tank armour'] = 'tanque',
	['armadura de tanque'] = 'tanque',
	['power armour'] = 'outro',
	['armadura de dano'] = 'outro',
	['pvp armour'] = 'pvp',
	['armadura de pvp'] = 'pvp',
	['shield'] = 'escudo',
	['escudo'] = 'escudo',
	['shieldbow'] = 'escudo',
	['arco-escudo'] = 'escudo',
	['hybrid'] = 'outro',
	['hibrido'] = 'outro',
	['all'] = 'outro',
	['tudo'] = 'outro',
}

local reductions = { -- type -> slot -> pvm, pvp multipliers
	-- aqui só traduzir os antes =, no caso adicionado eles como cópia com nome pt-br
	tank = {
		head = {pvm = 0.02, pvp = 0.0375},
		elmo = {pvm = 0.02, pvp = 0.0375},
		torso = {pvm = 0.02, pvp = 0.06},
		corpo = {pvm = 0.02, pvp = 0.06},
		legs = {pvm = 0.02, pvp = 0.0525},
		pernas = {pvm = 0.02, pvp = 0.0525},
		hands = {pvm = 0.02, pvp = 0},
		luvas = {pvm = 0.02, pvp = 0},
		feet = {pvm = 0.02, pvp = 0},
		botas = {pvm = 0.02, pvp = 0}
	},
	pvp = {
		head = {pvm = 0, pvp = 0.0375},
		elmo = {pvm = 0, pvp = 0.0375},
		torso = {pvm = 0, pvp = 0.06},
		corpo = {pvm = 0, pvp = 0.06},
		legs = {pvm = 0, pvp = 0.0525},
		pernas = {pvm = 0, pvp = 0.0525}
	},
	other = { --power, hybrid, all
		head = {pvm = 0, pvp = 0.01875},
		elmo = {pvm = 0, pvp = 0.01875},
		torso = {pvm = 0, pvp = 0.03},
		corpo = {pvm = 0, pvp = 0.03},
		legs = {pvm = 0, pvp = 0.02625},
		pernas = {pvm = 0, pvp = 0.02625}
	},
	shield = { --because hybrid shields are a thing
		 -- for consistency to continue allowing reduction.type.slot.pvx
		['off-hand'] = {pvm = 0.1, pvp = 0},
		['mão secundária'] = {pvm = 0.1, pvp = 0},
		['2h weapon'] = {pvm = 0.1, pvp = 0}, --shieldbows pls
		['arma de 2m'] = {pvm = 0.1, pvp = 0}
	}
}


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

	ret:defineParams{
		{ name = 'image', func = { name = imagearg, params = { 'image' }, flag = 'p' } },
		{ name = 'altimage', func = { name = imagearg, params = { 'altimage' }, flag = 'p' } },
		{ name = 'noimgcat', func = { name = noimgcatarg, params = { 'noimgcat', 'image' }, flag='p' } },
		{ name = 'requirements', func = requirementsarg },
		{ name = 'class', func = { name = lookuparg, params = { classes, 'class' }, flag = { 'r', 'd' } } },
		{ name = 'classimg', func = { name = lookuparg, params = { class_img, 'class' }, flag = { 'r', 'd' } } },
		{ name = 'classstr', func = { name = classstrarg, params = {'class', 'classimg' }, flag = 'd' } },
		{ name = 'class_smw', func = { name = classsmwarg, params = { 'class' }, flag = { 'd' } } },
		{ name = 'tier', func = tierarg },
		{ name = 'type', func = { name = lookupmultiarg, params = { types, 'type' }, flag = { 'r', 'd' } } },
		{ name = 'type_disp', func = { name = type_display, params = { 'type' }, flag = { 'd' } } },
		{ name = 'slot', func = { name = lookuparg, params = { slots, 'slot' }, flag = { 'r', 'd' } } },
		{ name = 'slotimg', func = { name = lookuparg, params = { slot_images, 'slot' }, flag = { 'r', 'd' } } },
		{ name = 'isweapon', func = { name = isweaponarg, params = { 'slot', 'type' }, flag = 'd' } },
		{ name = 'invdegrade', func = { name = invdegradearg, params = { 'invtier', 'invslot', 'slot' }, flag = 'd' } },
		{ name = 'invdegrade_span', func = { name = invdegradetooltipspanarg, params = { 'invtier', 'invslot', 'slot' }, flag = 'd' } },
		{ name = 'invdegrade_div', func = { name = invdegradetooltipdivarg, params = { 'invtier', 'invslot', 'slot' }, flag = 'd' } },
		{ name = 'normdegrades', func = { name = normdegradesarg, params = { 'degrades' }, flag = 'p' } },
		{ name = 'degradetype', func = { name = degradestypearg, params = { 'normdegrades', 'invdegrade' }, flag = 'd' } },
		{ name = 'degradestr', func = { name = degradesstrarg, params = { 'degradetype', 'normdegrades', 'invdegrade', 'invdegrade_span' }, flag = 'd' } },
		{ name = 'degradeheader', func = { name = degradeheaderarg, params = { 'degradetype' }, flag = 'd' } },
		{ name = 'hasstyle', func = { name = hasstylearg, params = { 'slot', 'type' }, flag = 'd' } },
		{ name = 'style', func = { name = stylearg, params = { 'style', 'hasstyle' }, flag = 'd' } },
		{ name = 'attackrange', func = { name = attackrangearg, params = { 'isweapon', 'attack_range', 'attack range', 'attackrange' }, flag = { 'd', 'p', 'p', 'p' } } },
		{ name = 'attackrangesmw', func = { name = attackrangesmwarg, params = { 'attackrange' }, flag = 'd' } },
		{ name = 'damage', func = fnumbers },
		{ name = 'accuracy', func = fnumbers },
		{ name = 'maindamage', func = { name = mainoffdamarg, params = { 'damage', 'slot', 'damage', {'main hand weapon', '2h weapon', 'ammo'} }, flag = { 'd', 'd', 'p', 'r' } } },
		{ name = 'mainaccuracy', func = { name = mainoffaccarg, params = { 'accuracy', 'slot', {'main hand weapon', '2h weapon'} }, flag = { 'd', 'd', 'r' } } },
		{ name = 'offdamage', func = { name = mainoffdamarg, params = { 'damage', 'slot', 'damage', {'off-hand weapon'} }, flag = { 'd', 'd', 'p', 'r' } } },
		{ name = 'offaccuracy', func = { name = mainoffaccarg, params = { 'accuracy', 'slot', {'off-hand weapon'} }, flag = { 'd', 'd', 'r' } } },
		{ name = 'armour', func = armourarg },
		{ name = 'life', func = fnumbers2 },
		{ name = 'prayer', func = fnumbers2 },
		{ name = 'magic', func = fnumbers },
		{ name = 'strength', func = fnumbers },
		{ name = 'ranged', func = fnumbers },
		{ name = 'magicstr', func = { name = stylebonusesarg, params = { 'magic', 'Magic', 'magic' }, flag = { 'd', 'r', 'p' } } },
		{ name = 'strengthstr', func = { name = stylebonusesarg, params = { 'strength', 'Strength', 'strength' }, flag = { 'd', 'r', 'p' } } },
		{ name = 'rangedstr', func = { name = stylebonusesarg, params = { 'ranged', 'Ranged', 'ranged' }, flag = { 'd', 'r', 'p' } } },
		{ name = 'reductionlevel', func = { name = reductionlevelarg, params = { 'reductionlevel', 'tier', 'requirements' }, flag = { 'p', 'd', 'd' } } },
		{ name = 'pvmreduction', func = { name = reductionarg, params = { 'reductionlevel', 'pvmReduction', 'type', 'slot', 'class', 'pvm' }, flag = { 'd', 'p', 'd', 'd', 'd', 'r' } } },
		{ name = 'pvpreduction', func = { name = reductionarg, params = { 'reductionlevel', 'pvpReduction', 'type', 'slot', 'class', 'pvp' }, flag = { 'd', 'p', 'd', 'd', 'd', 'r' } } },
		{ name = 'pvmreductionstr', func = { name = reductionstrarg, params = { 'pvmreduction', "'''PvM: '''" }, flag = { 'd', 'r' } } },
		{ name = 'pvpreductionstr', func = { name = reductionstrarg, params = { 'pvpreduction',  "'''PvP: '''" }, flag = { 'd', 'r' } } },
		{ name = 'speedraw', func = { name = speedrawarg, params = { 'isweapon', 'speed', 'aspeed' }, flag = { 'd', 'p', 'p' } } },
		{ name = 'speed', func = { name = speedarg, params = { 'speedraw' }, flag = 'd' } },
		{ name = 'layouttype', func = { name = layoutarg, params = { 'image', 'altimage' }, flag ='d' } },
		{ name = 'isrecolour', func = { name = recolourarg, params = { 'isrecolour' }, flag = 'd' } },
		
		{ name = 'intbonus', func = { name = intbonusarg, params = { 'armour', 'damage', 'strength', 'ranged', 'magic' }, flag ='p' } },
		
		{ name = 'tier_smw', func = { name = smwtierarg, params = { 'tier' }, flag = 'd' } },
		{ name = 'style_smw', func = { name = smwstylearg, params = { 'style' }, flag = 'd' } },
		{ name = 'damage_smw', func = { name = smwnumbers, params = { 'damage' }, flag = 'd' } },
		{ name = 'accuracy_smw', func = { name = smwnumbers, params = { 'accuracy' }, flag = 'd' } },
		{ name = 'armour_smw', func = { name = smwnumbers2, params = { 'armour' }, flag = 'd' } },
		{ name = 'life_smw', func = { name = smwnumbers2, params = { 'life' }, flag = 'd' } },
		{ name = 'prayer_smw', func = { name = smwnumbers2, params = { 'prayer' }, flag = 'd' } },
		{ name = 'magic_smw', func = { name = smwnumbers, params = { 'magic' }, flag = 'd' } },
		{ name = 'strength_smw', func = { name = smwnumbers, params = { 'strength' }, flag = 'd' } },
		{ name = 'ranged_smw', func = { name = smwnumbers, params = { 'ranged' }, flag = 'd' } },
		{ name = 'charges', func = { name = chargesarg, params = { 'degradetype', 'normdegrades' }, flag = 'd' } },
		{ name = 'invtier', func = { name = invtierarg, params = { 'degradetype', 'invtier' }, flag = { 'd', 'p' } } },
		{ name = 'smwJSON', func = { name = smwjsonarg, params = { 'class', 'slot', 'style_smw', 'type', 'damage_smw', 'accuracy_smw', 'attackrangesmw', 'armour_smw', 'life_smw', 'speedraw', 'prayer_smw', 'strength_smw', 'ranged_smw', 'magic_smw', 'tier_smw', 'charges', 'invtier' }, flag = 'd' } }
	}

	ret:setMaxButtons(7)
	ret:setAddRSWInfoboxClass(false)
	ret:create()
	ret:cleanParams()
	ret:customButtonPlacement(true)
	
	ret:defineLinks({
		colspan = 12,
		links = { 
			{ 'Predefinição:Infobox bônus/FAQ', 'FAQ' },
			{ 'Predefinição:Infobox bônus', 'docs' }
		}
	})
	ret:css({
		width = '450px',
		float = 'none',
		margin = '0.8em 0'
	})
	
	--smw here later
	ret:useSMWSubobject({
		smwJSON = 'Equipment JSON',
		class_smw = 'Combat class',
		slot = 'Equipment slot',
		type = 'Equipment type',
		damage_smw = 'Weapon damage',
		accuracy_smw = 'Weapon accuracy',
		style_smw = 'Attack style',
		attackrangesmw = 'Attack range',
		armour_smw = 'Equipment armour',
		life_smw = 'Equipment life points',
		speedraw = 'Weapon attack speed',
		prayer_smw = 'Prayer bonus',
		strength_smw = 'Strength bonus',
		ranged_smw = 'Ranged bonus',
		magic_smw = 'Magic bonus',
		tier_smw = 'Equipment tier',
		charges = 'Degradation charges',
		invtier = 'Invention tier',
		isrecolour = 'Is cosmetic recolour',
		intbonus = 'Has integer bonuses'
	})
	
	ret:addButtonsCaption()

	ret:defineName('Infobox Bonuses')
	ret:addClass('infobox-bonuses wikitable')
	ret:tag('caption'):wikitext("'''[[Estatísticas de combate]]'''")
	
	local layout = ret:param('layouttype', 'r')
	p['_main'..layout](ret)

	if onmain() then
		local a1 = ret:param('all')
		local a2 = ret:categoryData()
		local cats = addcategories(ret,a1,a2)
		ret._categories_test = cats
		ret:wikitext(cats)
	end

	return ret:tostring()

end

-- 1 image
function p._mainA(ret)
	local row1 = {
		{ tag = 'th', content = 'Requisitos', colspan = 6, class = 'combat-requirements' },
		{ tag = 'argd', content = 'image', colspan = 6, rowspan = 11, class = 'infobox-image bordered-image' }
	}
	local row2 = {
		{ tag = 'argd', content = 'requirements', colspan = 6, css = { ['max-width'] = '240px' } } -- stop skill reqs getting too wide
	}
	if ret:param('speed', 'r') ~= 'no' then
		row1[2].rowspan = 12
	end
	
	if infobox.isDefined(ret:param('degradetype', 'r')) then
		row1[1].colspan = 3
		row2[1].colspan = 3
		table.insert(row1, 2, { tag = 'argh', content = 'degradeheader', colspan = 3 })
		table.insert(row2, 2, { tag = 'argd', content = 'degradestr', colspan = 3 })
		if ret:param('degradetype', 'r') == 'invention' then
			ret:append(tostring(ret:param('invdegrade_div', 'r')))
		end
	end
	ret:addRow(row1):addRow(row2)

	-- class, slot
	ret:addRow{
		{ tag = 'th', content = 'Classe', colspan = 3 },
		{ tag = 'th', content = 'Slot', colspan = 3 }
	}
	:addRow{
		{ tag = 'argd', content = 'classstr', colspan = 3 },
		{ tag = 'argd', content = 'slotimg', colspan = 3 }
	}

	if ret:paramDefined('type') then
		-- tier, type
		ret:addRow{
			{ tag = 'th', content = '[[Nível de equipamento|Nível]]', colspan = 3 },
			{ tag = 'th', content = 'Tipo', colspan = 3 }
		}
		:addRow{
			{ tag = 'argd', content = 'tier', colspan = 3 },
			{ tag = 'argd', content = 'type_disp', colspan = 3 }
		}
	else
		ret:addRow{
			{ tag = 'th', content = '[[Nível de equipamento|Nível]]', colspan = 6 }
		}
		:addRow{
			{ tag = 'argd', content = 'tier', colspan = 6 }
		}
	end

	-- weapons section
	ret:addRow{ --headers
		{ tag = 'th', content = 'Armas', colspan = 2, css = { width = '33%' } },
		{ tag = 'th', content = 'Prim.', colspan = 2, css = { width = '33%' } },
		{ tag = 'th', content = 'Sec.', colspan = 2, css = { width = '33%' } }
	}
	:addRow{ -- damage
		{ tag = 'th', content = 'Dano', colspan = 2 },
		{ tag = 'argd', content = 'maindamage', colspan = 2 },
		{ tag = 'argd', content = 'offdamage', colspan = 2 }
	}
	:addRow{ -- accuracy
		{ tag = 'th', content = 'Precisão', colspan = 2 },
		{ tag = 'argd', content = 'mainaccuracy', colspan = 2 },
		{ tag = 'argd', content = 'offaccuracy', colspan = 2 }
	}
	:addRow{ -- style
		{ tag = 'th', content = 'Estilo', colspan = 2 },
		{ tag = 'argd', content = 'style', colspan = 4 }
	}
	:addRow{ -- range
		{ tag = 'th', content = 'Alcance', colspan = 2 },
		{ tag = 'argd', content = 'attackrange', colspan = 4 }
	}
	
	if ret:param('speed', 'r') ~= 'no' then
		ret:addRow{ -- rate (formely speed)
			{ tag = 'th', content = 'Velocidade', colspan = 2 },
			{ tag = 'argd', content = 'speed', colspan = 4, css = { padding = '0.2em' } }
		}
	end

	-- attributes / bottom section
	ret:addRow{ -- attribute & reduction headers
		{ tag = 'th', content = 'Atributos', colspan = 6 },
		{ tag = 'th', content = '[[Redução de dano]]', colspan = 6, css = { ['min-width'] = '225px' } }, -- force as wide as other side (3x th = 210 from css, + paddings and borders = 225)
	}:addRow{ -- armour, reductions
		{ tag = 'th', content = skillpic('Defesa') .. ' Armadura', colspan = 4, class = 'combat-attributes' },
		{ tag = 'argd', content = 'armour', colspan = 2, css = { ['text-align'] = 'right' } },
		{ tag = 'argd', content = 'pvmreductionstr', colspan = 3 },
		{ tag = 'argd', content = 'pvpreductionstr', colspan = 3 }
	}:addRow{ -- life points, style header
		{ tag = 'th', content = skillpic('Condição Física') .. ' Vida', colspan = 4, class = 'combat-attributes' },
		{ tag = 'argd', content = 'life', colspan = 2, css = { ['text-align'] = 'right' } },
		{ tag = 'th', content = 'Bônus de estilos', colspan = 6 },
	}:addRow{ -- prayer, style bonuses
		{ tag = 'th', content = skillpic('Oração') .. ' Oração', colspan = 4, class = 'combat-attributes' },
		{ tag = 'argd', content = 'prayer', colspan = 2, css = { ['text-align'] = 'right' } },
		{ tag = 'argd', content = 'strengthstr', colspan = 2 },
		{ tag = 'argd', content = 'rangedstr', colspan = 2 },
		{ tag = 'argd', content = 'magicstr', colspan = 2 },
	}

	-- bottom row
	-- kinda special to accomodate the compare button
	--[=[ret	:tag('tr')
			:addClass('infobox-bonuses-bottomrow')
			:css('border', 'none')
			:tag('td')
				:attr('colspan', 12)
				:css({
					background = 'transparent !important',
					border = 'none !important',
					['text-align'] = 'left',
					['font-size'] = 'smaller'
				})
				:wikitext('[[Template:Infobox Bonuses/FAQ|&#91;FAQ&#93;]] &bull; [[Template:Infobox Bonuses|&#91;doc&#93;]]')
	--]=]

end

-- 2 images or no images
function p._mainB(ret, hasImages)
	if hasImages then
		ret:addRow{
			{ tag = 'argd', content = 'image', colspan = 6 },
			{ tag = 'argd', content = 'altimage', colspan = 6 }
		}
	end

	local row1 = {
		{ tag = 'th', content = 'Requisitos', colspan = 6, class = 'combat-requirements' },
		{ tag = 'th', content = '[[Nível do equipamento|Nível]]', colspan = 6 }
	}
	local row2 = {
		{ tag = 'argd', content = 'requirements', colspan = 6, css = { ['max-width'] = '240px' } }, -- stop skill reqs getting too wide
		{ tag = 'argd', content = 'tier', colspan = 6 }
	}
	local row1tier = row1[2]
	local row2tier = row2[2]

	if infobox.isDefined(ret:param('degradetype', 'r')) then
		row1[1].colspan = 3
		row2[1].colspan = 3
		table.insert(row1, 2, { tag = 'argh', content = 'degradeheader', colspan = 3 })
		table.insert(row2, 2, { tag = 'argd', content = 'degradestr', colspan = 3 })
		if ret:param('degradetype', 'r') == 'invention' then
			ret:append(tostring(ret:param('invdegrade_div', 'r')))
		end
	end
	
	if ret:paramDefined('type') then
		row1tier.colspan = 3
		row2tier.colspan = 3
		table.insert(row1, { tag = 'th', content = 'Tipo', colspan = 3 })
		table.insert(row2, { tag = 'argd', content = 'type_disp', colspan = 3 })
	end
	ret:addRow(row1):addRow(row2)
	local strSpan = 1
	if infobox.isDefined(ret:param('speed', 'r')) and ret:param('speed', 'r') ~= 'no' then
		strSpan = 2
	end
	ret:addRow{
		-- class, slot, attr headers
		{ tag = 'th', content = 'Classe', colspan = 3, css = { width = '50%' } },
		{ tag = 'th', content = 'Slot', colspan = 3, css = { width = '50%' } },
		{ tag = 'th', content = 'Atributos', colspan = 6 },
	}
	:addRow{
		-- class, slot, armour
		{ tag = 'argd', content = 'classstr', rowspan = 2, colspan = 3 },
		{ tag = 'argd', content = 'slotimg', rowspan = 2, colspan = 3 },
		{ tag = 'th', content = skillpic('Defesa') .. ' Armadura', colspan = 4, class = 'combat-attributes' },
		{ tag = 'argd', content = 'armour', colspan = 2, css = { ['text-align'] = 'right' } }
	}
	:addRow{
		-- [class second row from rowspan]
		-- [slot second row from rowspan]
		-- life points
		{ tag = 'th', content = skillpic('Condição Física') .. ' Vida', colspan = 4, class = 'combat-attributes' },
		{ tag = 'argd', content = 'life', colspan = 2, css = { ['text-align'] = 'right' } }
	}
	:addRow{
		-- weapons header, prayer
		{ tag = 'th', content = 'Armas', colspan = 2, css = { width = '33%' } },
		{ tag = 'th', content = 'Prim.', colspan = 2, css = { width = '33%' } },
		{ tag = 'th', content = 'Sec.', colspan = 2, css = { width = '33%' } },
		{ tag = 'th', content = skillpic('Oração') .. ' Oração', colspan = 4, class = 'combat-attributes' },
		{ tag = 'argd', content = 'prayer', colspan = 2, css = { ['text-align'] = 'right' } }
	}
	:addRow{
		-- damage, reduction header
		{ tag = 'th', content = 'Dano', colspan = 2 },
		{ tag = 'argd', content = 'maindamage', colspan = 2 },
		{ tag = 'argd', content = 'offdamage', colspan = 2 },
		{ tag = 'th', content = '[[Redução de dano]]', colspan = 6 }
	}
	:addRow{
		-- accuracy, reductions
		{ tag = 'th', content = 'Precisão', colspan = 2 },
		{ tag = 'argd', content = 'mainaccuracy', colspan = 2 },
		{ tag = 'argd', content = 'offaccuracy', colspan = 2 },
		{ tag = 'argd', content = 'pvmreductionstr', colspan = 3 },
		{ tag = 'argd', content = 'pvpreductionstr', colspan = 3 }
	}
	:addRow{
		-- style, style bonuses header
		{ tag = 'th', content = 'Estilo', colspan = 2 },
		{ tag = 'argd', content = 'style', colspan = 4 },
		{ tag = 'th', content = 'Bônus de estilo', colspan = 6 }
	}
	:addRow{
		-- range
		{ tag = 'th', content = 'Alcance', colspan = 2 },
		{ tag = 'argd', content = 'attackrange', colspan = 4 },
		{ tag = 'argd', content = 'strengthstr', colspan = 2, rowspan = strSpan },
		{ tag = 'argd', content = 'rangedstr', colspan = 2, rowspan = strSpan },
		{ tag = 'argd', content = 'magicstr', colspan = 2, rowspan = strSpan }
	}
	if ret:param('speed', 'r') ~= 'no' then
		ret:addRow{ --(formely speed)
			{ tag = 'th', content = '[[Velocidade de ataque|Velocidade]]', colspan = 2 },
			{ tag = 'argd', content = 'speed', colspan = 4, css = { padding = '0.2em' } }
		}
	end

end
function p._mainB0(ret)
	return p._mainB(ret, false)
end
function p._mainB2(ret)
	return p._mainB(ret, true)
end

-- images
function imagearg(f)
	local height, width = 280, 220
	if paramtest.is_empty(f) then
		return nil
	end
	f = tostring(f)
	if string.lower(f) == 'no' then
		return nil
	end
	f = f:gsub('[Ff]icheiro:',''):gsub('{{!}}','|')
	f = mw.text.split(f, '|')
	f = f[1]

	return mw.ustring.format('[[Ficheiro:%s|%sx%spx|frameless|alt=%s: %s equipado por um jogador]]', f, width, height, f, mw.title.getCurrentTitle().text)
end
function noimgcatarg(nocat, img)
	if infobox.isDefined(nocat) then
		return 'true'
	end
	if infobox.isDefined(img) then
		if string.lower(img) == 'no' then
			return 'true'
		end
	end
	return nil
end

--requirements
function requirementsarg(r)
	if infobox.isDefined(r) then
		return mw.getCurrentFrame():preprocess(r)
	end
	return nil
end

-- class style type slot
function lookuparg(t, c)
	return t[string.lower(c or '')]
end
function lookupmultiarg(t, c)
	local out = {}
	if not infobox.isDefined(c) then
		return nil
	end
	c = string.lower(c)
	for i in mw.text.gsplit(c, ',') do
		table.insert(out, t[mw.text.trim(i)])
	end
	if #out == 0 then
		return nil
	end
	return table.concat(out, infobox.splitpoint)
end
function type_display(a)
	if a == nil then
		return nil
	end
	local out = {}
	for i in mw.text.gsplit(a, infobox.splitpoint) do
		i = i:lower()
		if type_cats[i] then
			table.insert(out, type_cats[i][1])
		end
	end
	return table.concat(out, ', ')
end
function stylearg(s, b)
	if b == 'true' then
		s = styles[string.lower(s or '')]
		if s then
			return paramtest.ucfirst(s)
		end
		return s
	end
	return '-'
end
function smwstylearg(s)
	if s ~= nil and s ~= '-' then
		return string.lower(tostring(s))
	end
end
function classstrarg(c, ci)
	if c == 'nenhuma' then
		return 'Nenhuma'
	end
	if infobox.isDefined(c) and infobox.isDefined(ci) then
		return ci .. ' ' .. paramtest.ucfirst(c)
	end
	return nil
end
function classsmwarg(c)
	if c == 'tudo' then
		return 'híbrido'
	end
	return c
end

-- tier
function tierarg(t)
	t = tostring(t)
	t = t:lower()
	if t == 'n/a' or t == 'no' or t == 'none' then
		t = 0
	end
	t = clean(t)
	if t then
		if t == 0 then
			return "''None''"
		end
		return t
	end
	return nil
end
function smwtierarg(t)
	if t == "''None''" then
		return 0
	end
	if type(t) == 'number' then
		return t
	end
	return nil
end

-- numerical args
function fnumbers(x)
	x = clean(x)
	if x then
		return x
	end
	return '-'
end
function fnumbers2(x)
	x = clean(x)
	if x then
		return x
	end
	return 0
end
function smwnumbers(x)
	if tonumber(x) then
		return x
	end
	return 0
end
function smwnumbers2(x)
	if tonumber(x) then
		return x
	end
	return 0
end
function armourarg(pas)
	local x = fnumbers(pas)
	if x == '-' then --nil
		return '0.0'
	elseif pas:find('%d%.%d') then --has decimal
		return string.format('%.1f', x)
	end
	return x --no decimal
end
function mainoffaccarg(x, s, slots)
	for i,v in ipairs(slots) do
		if s == v then
			return tonumber(x)
		end
	end
	return '-'
end
function mainoffdamarg(x, s, pas, slots)
	local r = nil
	local found = false
	for i,v in ipairs(slots) do
		if s == v then
			r = tonumber(x)
			found = true
			break
		end
	end
	if r then
		if pas:find('%d%.%d') then
			r = string.format('%.1f', r)
		end
		return r
	end
	if found then
		return nil
	end
	return '-'
end

function stylebonusesarg(x, t, passed)
	local s = tostring(x)
	if x == '-' then
		s = '0.0'
	elseif passed:find('%d%.%d') then
		s  = string.format('%.1f', x)
	end
	return mw.ustring.format('<span style="float:left;">%s</span><span style="float:right;">%s</span>', skillpic(t), s)
end

-- isWeapon boolean
function isweaponarg(s,t)
	local weapon_slots = {
		['main hand weapon'] = 'true',
		['2h weapon'] = 'true',
		['off-hand weapon'] = 'true'

	}
	local non_weapon_types = {
		['Prevents attack'] = 'true'
	}
	if non_weapon_types[t] then
		return 'false'
	end
	return weapon_slots[s] or 'false'
end

-- degradation
-- invention charge drain
function invdegradearg(invtier,invslot,slot)
	invtier = tonumber(invtier)
	local ret = nil
	if invtier then
		invslot = slots[invslot] or invslot
		invslot = inv_slots[invslot]
		if not invslot then
			invslot = inv_slots[slot]
		end
		ret = chargedrain.get_base(invtier,invslot)
	end
	return ret
end
function invdegradetooltipspanarg(invtier,invslot,slot)
	invtier = tonumber(invtier)
	local ret = nil
	if invtier then
		invslot = slots[invslot] or invslot
		invslot = inv_slots[invslot]
		if not invslot then
			invslot = inv_slots[slot]
		end
		ret, _ = chargedrain.get_tooltip(invtier,invslot)
		ret = tostring(ret)
	end
	return ret
end
function invdegradetooltipdivarg(invtier,invslot,slot)
	invtier = tonumber(invtier)
	local ret = nil
	if invtier then
		invslot = slots[invslot] or invslot
		invslot = inv_slots[invslot]
		if not invslot then
			invslot = inv_slots[slot]
		end
		_, ret = chargedrain.get_tooltip(invtier,invslot)
		ret = tostring(ret)
	end
	return ret
end
-- normal degradation
function normdegradesarg(deg)
	local charges = clean(deg)
	if charges then
		return charges
	end
	if yesno(deg, false) then
		return 'Yes'
	end
	return nil
end
function degradestypearg(deg,inv)
	if infobox.isDefined(inv) and infobox.isDefined(deg) then
		return 'both'
	end
	if infobox.isDefined(inv) then
		return 'invention'
	end
	if infobox.isDefined(deg) then
		return 'normal'
	end
	return nil
end
-- string representation
function degradesstrarg(dtype, deg, inv, invspan)
	if dtype == 'invention' then
		return mw.ustring.format('%s/s %s', inv, invspan)
	end
	if dtype == 'normal' or dtype == 'both' then
		if type(deg) == 'number' then
			return commas(deg) .. ' cargas'
		elseif deg == true then
			return 'Yes'
		else
			return deg
		end
	end
	return ''
end
-- header
function degradeheaderarg(dtype)
	if dtype == 'invention' then
		return '[[Bateria de carga|Drenagem de carga]]'
	end
	if dtype == 'normal' or dtype == 'both' then
		return '[[Degradação de equipamento|Degradação]]'
	end
	return ''
end
--smw
function chargesarg(dt, c)
	if dt == 'normal' then
		if type(c) == 'number' then
			return c
		end
	end
	return nil
end
function invtierarg(dt, t)
	if dt == 'invention' then
		t = clean(t)
		if t then
			return t
		end
	end
	return nil
end

-- hasStyle boolean
function hasstylearg(s,t)
	return (isweaponarg(s,t) == 'true' or (s == 'ammo')) and 'true' or 'false'
end

-- attack range
function attackrangearg(w,r1,r2,r3)
	if w == 'true' then
		return clean(r1) or clean(r2) or clean(r3)
	end
	return '-'
end
function attackrangesmwarg(a)
	if a == '-' then
		return nil
	end
	return a
end

-- reductions
function reductionlevelarg(r, tier, reqs)
	if r then
		r = clean(r)
		if r then
			return r
		end
	end
	local ret = tonumber(tier) or 0
	if infobox.isDefined(reqs) then
		local maxR = 0
		for v in string.gmatch(reqs, '(%d+) %[%[') do
			if tonumber(v) and tonumber(v) > maxR then
				maxR = tonumber(v)
			end
		end
		if maxR > 0 then
			ret = maxR
		end
	end
	return ret
end
function reductionarg(rl, over, t, s, c, pvx)
	over = clean(over)
	if over then
		--overridden
		return over .. '%'
	end
	if not infobox.isDefined(rl) then
		--tier/rl not defined
		return '0%'
	end
	local reduction_table, reduction_type = nil,nil
	if infobox.isDefined(t) then
		-- check if we have a reduction for this type+slot
		reduction_type = reduction_types[t:lower()]
		if reduction_type then
			reduction_table = reductions[reduction_type][s]
		end
	end
	if not reduction_table and infobox.isDefined(c) then
		-- couldn't find type+slot, so class+slot
		reduction_type = reduction_types[c:lower()]
		if reduction_type then
			reduction_table = reductions[reduction_type][s]
		end
	end
	if reduction_table then
		return (reduction_table[pvx] or 0) * rl .. '%'
	end
	-- didn't find anything
	return '0%'
end
function reductionstrarg(r, ty)
	return mw.ustring.format('<span style="float:left;">%s</span><span style="float:right;">%s</span>', ty, r)
end

-- speed
function speedrawarg(iswep, s1, s2)
	if iswep =='true' then
		local s
		if infobox.isDefined(s1) then
			s = string.lower(s1)
		elseif infobox.isDefined(s2) then
			s = string.lower(s2)
		end
		return s or ''
	else
		return 'no'
	end
end
function speedarg(s)
	if infobox.isDefined(s) then
		if s == 'no' then
			return 'no'
		else
			return tostring(attack_speed_bar(s))
		end
	end
	return nil
end

-- layout
function layoutarg(img, alt)
	if infobox.isDefined(img) then
		if infobox.isDefined(alt) then
			-- 2 images
			return 'B2'
		end
		-- 1 image
		return 'A'
	end
	-- no images
	return 'B0'
end

function intbonusarg(...)
	for _,v in ipairs({...}) do
		if paramtest.has_content(v) then
			if not v:match('%d%.%d') then
				return 'true'
			end
		end
	end
	return nil
end

function recolourarg(arg)
	-- string to ensure it correctly passes through infobox
	return tostring(infobox.isDefined(arg) and yesno(arg, false))
end

-- Removes all plus signs, commas, and percent signs
function clean(number)
	if not number then
		return nil
	else
		number = tostring(number)
		number = number:gsub('[+,%%]','')
		return tonumber(number,10)
	end
end

-- legacy SMW JSON
function smwjsonarg(class, slot, style, itype, damage, accuracy, attack_range, armour, life, speed, prayer, strength, ranged, magic, tier, charges, invtier)
	local json = {
		class = class,
		slot = slot,
		style = style,
		type = itype,
		damage = damage,
		accuracy = accuracy,
		style = style,
		attack_range = attack_range,
		armour = armour,
		lp = life,
		speed = speed,
		prayer = prayer,
		strength = strength,
		ranged = ranged,
		magic = magic,
		tier = tier,
		charges = charges,
		invention = invtier
	}
	for k,v in pairs(json) do
		if not infobox.isDefined(v) then
			json[k] = nil
		end
	end
	local jsonGood, encoded = pcall(mw.text.jsonEncode,json)
	if jsonGood then
		return encoded
	end
	return nil
end

-- categories
function addcategories(ibox, args, catargs)
	local cats = {'Equipmento'}
	local versions = ibox.versions
	function forAllSwitches(func, param1, param2, param3)
		local r = {}
		param2 = param2 or {}
		param3 = param3 or {}
		local p1,p2,p3
		p1 = param1.d
		p2 = param2.d
		p3 = param3.d
		if versions == 0 or not (param1.switches or param2.switches or param3.switches) then
			table.insert(r, func(p1,p2,p3))
		else
			local p1s,p2s,p3s
			for i = 1,versions,1 do
				p1s = p1
				if param1.switches then
					p1s = param1.switches[i]
					if p1s == infobox.nil_param then
						p1s = p1
					end
				end
				p2s = p2
				if param2.switches then
					p2s = param2.switches[i]
					if p2s == infobox.nil_param then
						p2s = p2
					end
				end
				p3s = p3
				if param3.switches then
					p3s = param3.switches[i]
					if p3s == infobox.nil_param then
						p3s = p3
					end
				end
				local ret = func(p1s, p2s, p3s)
				if type(ret) == 'table' then
					for ir,vr in ipairs(ret) do
						table.insert(r, vr)
					end
				else
					table.insert(r, ret)
				end
			end
		end
		return r
	end
	function append(a)
		if type(a) == 'table' then
			for i,v in ipairs(a) do
				table.insert(cats, v)
			end
		else
			table.insert(cats,a)
		end
	end
	
	-- slot missing
	if not catargs.slot.all_defined then
		append('Falta de informações em slot')
	end
	
	-- tiers
	append(forAllSwitches(function(v)
		if type(v) == 'number' then
			if v == 0 then
				return 'Equipamento sem nível'
			elseif v > 0 then
				return 'Equipamento de nível '.. v
			end
		end
		return 'Faltando nível do equipmento'
	end, args.tier_smw))
	
	-- type
	append(forAllSwitches(function(v)
		local out = {}
		if type(v) == 'string' then
			for i in mw.text.gsplit(v, infobox.splitpoint) do
				i = i:lower()
				if type_cats[i] then
					table.insert(out, type_cats[i][2])
				end
			end
		end
		return out
	end, args.type))
	
	-- slots
	append(forAllSwitches(function(v)
		v = string.lower(tostring(v))
		if v == 'off-hand weapon' then
			local k = mw.title.getCurrentTitle().fullText:gsub('[Oo]ff[%- ]?hand ?', '')
			return 'Off-hand slot weapons|'..k
		elseif slot_cats[v] then
			return slot_cats[v]
		end
		return 'Falta de informações em slot'
	end, args.slot))
	
	-- style
	append(forAllSwitches(function(v)
		return style_cats[v]
	end, args.style))
	
	-- degrades
	if catargs.normdegrades.one_defined then
		append('Equipamento degradante')
	end
	
	-- class
	append(forAllSwitches(function(c,w,s)
		local cat = class_cats[c]
		if cat then
			if s == 'munição' then
				return nil
			end
			if w == 'true' then
				if cat == 'Híbrido' then
					cat = 'Sem classe'
				end
				return cat .. ' armas'
			end
			return cat .. ' armadura'
		end
		return nil
	end, args.class, args.isweapon, args.slot))
	
	-- prayer
	append(forAllSwitches(function(p)
		if tonumber(p) then
			if tonumber(p) > 0 then
				return 'Objetos com bônus em oração'
			end
		end
		return nil
	end, args.prayer_smw))
	
	-- range
	if not catargs.attackrange.all_defined then
		append('Faltando informação de alcance')
	end
	
	-- speed
	append(forAllSwitches(function(s)
		if s == '' then
			return 'Faltando informação de velocidade'
		end
		return nil
	end, args.speedraw))
	
	-- integer equipment bonuses
	if catargs.intbonus.one_defined then
		append('Bônus de conjunto completo')
	end
	
	-- equipped image
	append(forAllSwitches(function(i, s, n)
		if infobox.isDefined(n) then
			return nil
		end
		if s == 'munição' or s == 'bolso' or s == 'anel' or s == 'sigil' then
			return nil
		end
		if not infobox.isDefined(i) then
			return 'Precisa de imagem'
		end
		return nil
	end, args.image, args.slot, args.noimgcat))
	
	local _cats = {}
	for i,v in ipairs(cats) do
		if type(v) == 'table' then
			for j,u in ipairs(v) do
				if paramtest.has_content(u) then
					table.insert(_cats, string.format('[[Categoria:%s]]', u))
				end
			end
		elseif paramtest.has_content(v) then
			table.insert(_cats, string.format('[[Categoria:%s]]', v))
		end
	end
	return table.concat(_cats, '')
end

return p
-- </nowiki>