Módulo:Infobox Bonuses new

De RuneScape Wiki
Ir para navegação Ir para pesquisar
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]
Módulo:Infobox Bonuses new's a função main é invocada por Predefinição:Infobox bônus.

-- <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:Skill clickpic')._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

-- Nomes de slot aceitos
local slots = {
	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 primária'] = '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',
	set = 'e',
	conjunto = 'e',
	nenhum = 'e',
	none = 'e'
}

-- Categorias para os slots
local slot_cats = {
    elmo = 'Objeto de slot de elmo',
	colar = 'Objeto de slot de colar',
	capa = 'Objeto de slot de capa',
	corpo = 'Objeto de slot de corpo',
	pernas = 'Objeto de slot de pernas',
	luvas = 'Objeto de slot de luvas',
	botas = 'Objeto de slot de botas',
	['munições'] = 'Objetos de slot de munições',
	anel = 'Anéis',
	aura = 'Auras',
	bolso = 'Objeto de slot de bolso',
	selo = 'Objeto de slot de selo',
	['arma de mão primária'] = 'Objeto de slot de arma de mão primária',
	['arma de duas-mãos'] = 'Objeto de slot de arma de duas-mãos',
	['mão secundária'] = 'Objeto de slot de mão secundária',
	['arma de mão secundária'] = 'Objeto de slot de arma de mão secundária',
	e = ''
}

-- Imagens usadas para a exibição dos slots
local slot_images = {
	elmo = '[[Ficheiro:Slot de elmo.png|link=Slot de elmo]]',
	['munições'] = '[[Ficheiro:Slot de munições.png|link=Slot de munições]]',
	colar = '[[Ficheiro:Slot de colar.png|link=Slot de colar]]',
	capa = '[[Ficheiro:Slot de capa.png|link=Slot de capa]]',
	['arma de mão primária'] = '[[Ficheiro:Slot de arma.png|link=Slot de arma]]',
	['arma de 2m'] = '[[Ficheiro:Slot de duas-mãos.png|link=Slot de duas-mãos]]',
	corpo = '[[Ficheiro:Slot de cota.png|link=Slot de cota]]',
	['mão secundária'] = '[[Ficheiro:Slot de escudo.png|link=Slot de escudo]]',
	['arma de mão secundária'] = '[[Ficheiro:Slot de escudo.png|link=Slot de escudo]]',
	pernas = '[[Ficheiro:Slot de perneiras.png|link=Slot de perneiras]]',
	luvas = '[[Ficheiro:Slot de luvas.png|link=Slot de luvas]]',
	botas = '[[Ficheiro:Slot de botas.png|link=Slot de botas]]',
	anel = '[[Ficheiro:Slot de anel.png|link=Slot de anel]]',
	aura = '[[Ficheiro:Slot de aura.png|link=Slot de aura]]',
	bolso = '[[Ficheiro:Slot de bolso.png|link=Slot de bolso]]',
	selo = '[[Ficheiro:Slot de selo.png|link=Slot de selo]]',
	e = 'Nenhum'
}

-- 'slots de Invenção'
local inv_slots = {
	['arma de mão primária'] = 'mp',
	['arma de 2m'] = '2m',
	['mão secundária'] = 'ms',
	['arma de mão secundária'] = 'ms',
	escudo = 'escudo',
	corpo = 'corpo',
	pernas = 'pernas',
	ferramenta = 'ferramenta'
}

-- Nomes de classes aceitas
local classes = {
	melee = 'corpo a corpo',
	ranged = 'combate à distância',
	ranging = 'combate à distância',
	range = 'combate à distância',
	magic = 'magia',
	mage = 'magia',
	all = 'todas',
	hybrid = 'híbrida',
	none = 'nenhuma',
	['n/a'] = 'nenhuma',
	['n/d'] = 'nenhuma',
	ataque = 'corpo a corpo',
	['corpo a corpo'] = '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',
	cad = 'combate à distância',
	magia = 'magia',
	tudo = 'todas',
	todas = 'todas',
	todos = 'todas',
	['híbrido'] = 'híbrida',
	['híbrida'] = 'híbrida',
	nenhuma = 'nenhuma',
	nenhum = 'nenhuma',
	nada = 'nenhuma'
}

-- Classes com imagens
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íbrida'] = '[[Ficheiro:Combate ícone.png|x24px|link=Armadura#Híbrido]]',
	todas = '[[Ficheiro:Combate ícone.png|x24px|link=Armadura#Todos]]',
	nenhuma = ''
}

local class_cats = {
	['corpo a corpo'] = 'de Corpo a Corpo',
	magia = 'de Magia',
	['combate à distância'] = 'de Combate à Distância',
	['híbrida'] = 'híbridas',
	todas = 'híbridas',
	nenhuma = 'sem classe',
}

-- Nomes de estilos aceitos
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 = 'Setas',
	setas = 'Setas',
	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',
	['n/d'] = 'Sem estilo',
	nenhum = 'Sem estilo',
}

-- Categorias para os estilos
local style_cats = {
	stab = 'Armas de perfuração',
	['perfurar'] = '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'
}

local types = {
	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 = 'Sabre',
	defensor = 'Sabre',
	sabre = 'Sabre',
	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 = {
	['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 = { '[[Sabre]]', 'Sabres' },
	defensor = { '[[Sabre]]', 'Sabres' },
	sabre = { '[[Sabre]]', 'Sabres' },
	repriser = { '[[Repulsor]]', 'Sabres' },
	repulsor = { '[[Repulsor]]', 'Sabres' },
	rebounder = { '[[Ressaltador]]', 'Sabres' },
	ressaltador = { '[[Ressaltador]]', 'Sabres' },
	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', 'Objetos que previnem o ataque' },
	['previne o ataque'] = { 'Previne o ataque', 'Objetos 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
	['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',
	['todas'] = 'outro'
}

local reductions = { -- type -> slot -> pvm, pvp multipliers
	-- aqui só traduzir os antes =, no caso adicionado eles como cópia com nome pt-br
	tanque = {
		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}
	},
	outro = { --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}
	},
	escudo = { --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 = 'imagem', func = { name = imagearg, params = { 'imagem' }, flag = 'p' } },
		{ name = 'altimagem', func = { name = imagearg, params = { 'altimagem' }, flag = 'p' } },
		{ name = 'noimgcat', func = { name = noimgcatarg, params = { 'noimgcat', 'imagem' }, flag='p' } },
		{ name = 'requisitos', func = requirementsarg },
		{ name = 'classe', func = { name = lookuparg, params = { classes, 'classe' }, flag = { 'r', 'd' } } },
		{ name = 'classimg', func = { name = lookuparg, params = { class_img, 'classe' }, flag = { 'r', 'd' } } },
		{ name = 'classstr', func = { name = classstrarg, params = {'classe', 'classimg' }, flag = 'd' } },
		{ name = 'class_smw', func = { name = classsmwarg, params = { 'classe' }, flag = { 'd' } } },
		{ name = 'nível', func = tierarg },
		{ name = 'tipo', func = { name = lookupmultiarg, params = { types, 'tipo' }, flag = { 'r', 'd' } } },
		{ name = 'type_disp', func = { name = type_display, params = { 'tipo' }, 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', 'tipo' }, flag = 'd' } },
		{ name = 'invdegrade', func = { name = invdegradearg, params = { 'invnível', 'invslot', 'slot' }, flag = 'd' } },
		{ name = 'invdegrade_span', func = { name = invdegradetooltipspanarg, params = { 'invnível', 'invslot', 'slot' }, flag = 'd' } },
		{ name = 'invdegrade_div', func = { name = invdegradetooltipdivarg, params = { 'invnível', 'invslot', 'slot' }, flag = 'd' } },
		{ name = 'normdegrades', func = { name = normdegradesarg, params = { 'degradação' }, 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', 'tipo' }, flag = 'd' } },
		{ name = 'estilo', func = { name = stylearg, params = { 'estilo', 'hasstyle' }, flag = 'd' } },
		{ name = 'alcance', func = { name = attackrangearg, params = { 'isweapon', 'attack_range', 'attack range', 'alcance' }, flag = { 'd', 'p', 'p', 'p' } } },
		{ name = 'attackrangesmw', func = { name = attackrangesmwarg, params = { 'alcance' }, flag = 'd' } },
		{ name = 'dano', func = fnumbers },
		{ name = 'precisão', func = fnumbers },
		{ name = 'dano_prim', func = { name = mainoffdamarg, params = { 'dano', 'slot', 'dano', {'arma de mão primária', 'arma de 2m', 'munições'} }, flag = { 'd', 'd', 'p', 'r' } } },
		{ name = 'precisão_prim', func = { name = mainoffaccarg, params = { 'precisão', 'slot', {'arma de mão primária', 'arma de 2m'} }, flag = { 'd', 'd', 'r' } } },
		{ name = 'dano_sec', func = { name = mainoffdamarg, params = { 'dano', 'slot', 'dano', {'arma de mão secundária'} }, flag = { 'd', 'd', 'p', 'r' } } },
		{ name = 'precisão_sec', func = { name = mainoffaccarg, params = { 'precisão', 'slot', {'arma de mão secundária'} }, flag = { 'd', 'd', 'r' } } },
		{ name = 'armadura', func = armourarg },
		{ name = 'vida', func = fnumbers2 },
		{ name = 'oração', func = fnumbers2 },
		{ name = 'bônus_magia', func = fnumbers },
		{ name = 'bônus_força', func = fnumbers },
		{ name = 'bônus_cad', func = fnumbers },
		{ name = 'magicstr', func = { name = stylebonusesarg, params = { 'bônus_magia', 'Magia', 'bônus_Magia' }, flag = { 'd', 'r', 'p' } } },
		{ name = 'strengthstr', func = { name = stylebonusesarg, params = { 'bônus_força', 'Força', 'bônus_Força' }, flag = { 'd', 'r', 'p' } } },
		{ name = 'rangedstr', func = { name = stylebonusesarg, params = { 'bônus_cad', 'Combate à Distância', 'bônus_CaD' }, flag = { 'd', 'r', 'p' } } },
		{ name = 'reductionlevel', func = { name = reductionlevelarg, params = { 'reductionlevel', 'nível', 'requisitos' }, flag = { 'p', 'd', 'd' } } },
		{ name = 'redução_pvm', func = { name = reductionarg, params = { 'reductionlevel', 'reduçãoPvM', 'tipo', 'slot', 'classe', 'pvm' }, flag = { 'd', 'p', 'd', 'd', 'd', 'r' } } },
		{ name = 'redução_pvp', func = { name = reductionarg, params = { 'reductionlevel', 'reduçãoPvP', 'tipo', 'slot', 'classe', 'pvp' }, flag = { 'd', 'p', 'd', 'd', 'd', 'r' } } },
		{ name = 'pvmreductionstr', func = { name = reductionstrarg, params = { 'redução_pvm', "'''PvM: '''" }, flag = { 'd', 'r' } } },
		{ name = 'pvpreductionstr', func = { name = reductionstrarg, params = { 'redução_pvp',  "'''PvP: '''" }, flag = { 'd', 'r' } } },
		{ name = 'speedraw', func = { name = speedrawarg, params = { 'isweapon', 'velocidade', 'aspeed' }, flag = { 'd', 'p', 'p' } } },
		{ name = 'velocidade', func = { name = speedarg, params = { 'speedraw' }, flag = 'd' } },
		{ name = 'layouttype', func = { name = layoutarg, params = { 'imagem', 'altimagem' }, flag ='d' } },
		{ name = 'recolorido', func = { name = recolourarg, params = { 'recolorido' }, flag = 'd' } },
		
		{ name = 'intbonus', func = { name = intbonusarg, params = { 'armadura', 'dano', 'bônus_força', 'bônus_cad', 'bônus_magia' }, flag ='p' } },
		
		{ name = 'tier_smw', func = { name = smwtierarg, params = { 'nível' }, flag = 'd' } },
		{ name = 'style_smw', func = { name = smwstylearg, params = { 'estilo' }, flag = 'd' } },
		{ name = 'damage_smw', func = { name = smwnumbers, params = { 'dano' }, flag = 'd' } },
		{ name = 'accuracy_smw', func = { name = smwnumbers, params = { 'precisão_prim' }, flag = 'd' } },
		{ name = 'armour_smw', func = { name = smwnumbers2, params = { 'armadura' }, flag = 'd' } },
		{ name = 'life_smw', func = { name = smwnumbers2, params = { 'vida' }, flag = 'd' } },
		{ name = 'prayer_smw', func = { name = smwnumbers2, params = { 'oração' }, flag = 'd' } },
		{ name = 'magic_smw', func = { name = smwnumbers, params = { 'magic' }, flag = 'd' } },
		{ name = 'strength_smw', func = { name = smwnumbers, params = { 'bônus_força' }, flag = 'd' } },
		{ name = 'ranged_smw', func = { name = smwnumbers, params = { 'bônus_cad' }, flag = 'd' } },
		{ name = 'cargas', func = { name = chargesarg, params = { 'degradetype', 'normdegrades' }, flag = 'd' } },
		{ name = 'invnível', func = { name = invtierarg, params = { 'degradetype', 'invnível', 'invtier' }, flag = { 'd', 'p', 'p' } } },
		{ name = 'smwJSON', func = { name = smwjsonarg, params = { 'classe', 'slot', 'style_smw', 'tipo', 'damage_smw', 'accuracy_smw', 'attackrangesmw', 'armour_smw', 'life_smw', 'speedraw', 'prayer_smw', 'strength_smw', 'ranged_smw', 'magic_smw', 'tier_smw', 'cargas', 'invnível' }, 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', 'doc' }
		}
	})
	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',
		tipo = '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',
		cargas = 'Degradation charges',
		['invnível'] = 'Invention tier',
		recolorido = 'Is cosmetic recolour',
		intbonus = 'Has integer bonuses'
	})
	
	ret:addButtonsCaption()

	ret:defineName('Infobox Bônus')
	ret:addClass('infobox-bonuses wikitable')
	
	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 = 'imagem', colspan = 6, rowspan = 11, class = 'infobox-image bordered-image' }
	}
	local row2 = {
		{ tag = 'argd', content = 'requisitos', colspan = 6, css = { ['max-width'] = '240px' } } -- stop skill reqs getting too wide
	}
	if ret:param('velocidade', 'r') ~= 'não' 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('tipo') then
		-- tier, type
		ret:addRow{
			{ tag = 'th', content = '[[Classe de equipamento|Nível]]', colspan = 3 },
			{ tag = 'th', content = 'Tipo', colspan = 3 }
		}
		:addRow{
			{ tag = 'argd', content = 'nível', colspan = 3 },
			{ tag = 'argd', content = 'type_disp', colspan = 3 }
		}
	else
		ret:addRow{
			{ tag = 'th', content = '[[Classe de equipamento|Nível]]', colspan = 6 }
		}
		:addRow{
			{ tag = 'argd', content = 'nível', 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 = 'dano_prim', colspan = 2 },
		{ tag = 'argd', content = 'dano_sec', colspan = 2 }
	}
	:addRow{ -- accuracy
		{ tag = 'th', content = 'Precisão', colspan = 2 },
		{ tag = 'argd', content = 'precisão_prim', colspan = 2 },
		{ tag = 'argd', content = 'precisão_sec', colspan = 2 }
	}
	:addRow{ -- style
		{ tag = 'th', content = 'Estilo', colspan = 2 },
		{ tag = 'argd', content = 'estilo', colspan = 4 }
	}
	:addRow{ -- range
		{ tag = 'th', content = 'Alcance', colspan = 2 },
		{ tag = 'argd', content = 'alcance', colspan = 4 }
	}
	
	if ret:param('velocidade', 'r') ~= 'não' then
		ret:addRow{ -- rate (formely speed)
			{ tag = 'th', content = 'Velocidade', colspan = 2 },
			{ tag = 'argd', content = 'velocidade', 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 = 'armadura', 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 = 'vida', 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 = 'oração', 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 = 'imagem', colspan = 6 },
			{ tag = 'argd', content = 'altimagem', colspan = 6 }
		}
	end

	local row1 = {
		{ tag = 'th', content = 'Requisitos', colspan = 6, class = 'combat-requirements' },
		{ tag = 'th', content = '[[Classe de equipamento|Nível]]', colspan = 6 }
	}
	local row2 = {
		{ tag = 'argd', content = 'requisitos', colspan = 6, css = { ['max-width'] = '240px' } }, -- stop skill reqs getting too wide
		{ tag = 'argd', content = 'nível', 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('tipo') 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('velocidade', 'r')) and ret:param('velocidade', 'r') ~= 'não' 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 = 'armadura', 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 = 'vida', 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 = 'oração', colspan = 2, css = { ['text-align'] = 'right' } }
	}
	:addRow{
		-- damage, reduction header
		{ tag = 'th', content = 'Dano', colspan = 2 },
		{ tag = 'argd', content = 'dano_prim', colspan = 2 },
		{ tag = 'argd', content = 'dano_sec', colspan = 2 },
		{ tag = 'th', content = '[[Redução de dano]]', colspan = 6 }
	}
	:addRow{
		-- accuracy, reductions
		{ tag = 'th', content = 'Precisão', colspan = 2 },
		{ tag = 'argd', content = 'precisão_prim', colspan = 2 },
		{ tag = 'argd', content = 'precisão_sec', 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 = 'estilo', colspan = 4 },
		{ tag = 'th', content = 'Bônus de estilo', colspan = 6 }
	}
	:addRow{
		-- range
		{ tag = 'th', content = 'Alcance', colspan = 2 },
		{ tag = 'argd', content = 'alcance', 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('velocidade', 'r') ~= 'não' then
		ret:addRow{ --(formely speed)
			{ tag = 'th', content = '[[Velocidade de ataque|Velocidade]]', colspan = 2 },
			{ tag = 'argd', content = 'velocidade', 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) == 'não' 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) == 'não' 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 == 'todas' then
		return 'híbrido'
	end
	return c
end

-- tier
function tierarg(t)
	t = tostring(t)
	t = t:lower()
	if t == 'n/a' or t == 'n/d' or t == 'não' or t == 'nenhum' or t == 'none' then
		t = 0
	end
	t = clean(t)
	if t then
		if t == 0 then
			return "''Nenhum''"
		end
		return t
	end
	return nil
end
function smwtierarg(t)
	if t == "''Nenhum''" 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 = {
		['arma de mão primária'] = 'true',
		['arma de 2m'] = 'true',
		['arma de mão secundária'] = 'true'

	}
	local non_weapon_types = {
		['Previne o ataque'] = '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 'Sim'
	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 'Sim'
		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 == 'munições')) 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 'não'
	end
end
function speedarg(s)
	if infobox.isDefined(s) then
		if s == 'não' then
			return 'não'
		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, cargas, 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,
		cargas = 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 = {'Equipamento'}
	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('Faltando informação 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 classe de equipamento'
	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.tipo))
	
	-- slots
	append(forAllSwitches(function(v)
		v = string.lower(tostring(v))
		if v == 'arma de mão secundária' then
			local k = mw.title.getCurrentTitle().fullText:gsub('? [Ss]ecundári[ao]', '')
			return 'Objeto de slot de arma de mão secundária|'..k
		elseif slot_cats[v] then
			return slot_cats[v]
		end
		return 'Faltando informação em slot'
	end, args.slot))
	
	-- style
	append(forAllSwitches(function(v)
		return style_cats[v]
	end, args.estilo))
	
	-- degrades
	if catargs.normdegrades.one_defined then
		append('Equipamento degradável')
	end
	
	-- class
	append(forAllSwitches(function(c,w,s)
		local cat = class_cats[c]
		if cat then
			if s == 'munições' then
				return nil
			end
			if w == 'true' then
				if cat == 'Híbridas' then
					cat = 'sem classe'
				end
				return 'Armas ' .. cat
			end
			return 'Armaduras ' .. cat
		end
		return nil
	end, args.classe, args.isweapon, args.slot))
	
	-- prayer
	append(forAllSwitches(function(p)
		if tonumber(p) then
			if tonumber(p) > 0 then
				return 'Objetos com bônus de Oração'
			end
		end
		return nil
	end, args.prayer_smw))
	
	-- range
	if not catargs.alcance.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 equipamento em números inteiros')
	end
	
	-- equipped image
	append(forAllSwitches(function(i, s, n)
		if infobox.isDefined(n) then
			return nil
		end
		if s == 'munições' or s == 'bolso' or s == 'anel' or s == 'selo' then
			return nil
		end
		if not infobox.isDefined(i) then
			return 'Precisa de imagem'
		end
		return nil
	end, args.imagem, 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>