Módulo:Infobox monstro

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 monstro/doc. [editar]
Módulo:Infobox monstro's a função main é invocada por Predefinição:Infobox monstro.
Módulo:Infobox monstro carrega dados de Módulo:Ícone fraqueza/data.

-- <nowiki>
--------------------------
-- Module for [[Template:Infobox Monster new]]
-- Please test changes to this module at [[Module:Infobox Monster/sandbox]] first
------------------------
local p = {}

-- "imports"
local onmain = require('Módulo:Mainonly').on_main
local paramtest = require('Módulo:Paramtest')
local yesno = require('Módulo:Yesno')
local commas = require('Módulo:Addcommas')._add
local infobox = require('Módulo:Infobox')
local attack_speed_bar = require('Módulo:Barra de velocidade de ataque').monster
local externo = require('Módulo:Top icons')._main

--[[
 -- Mappingt
--]]
local attack_styles = {
	['corpo a corpo'] = { image = 'Ataque ícone', link = 'Corpo a Corpo' },
	['combate à distância'] = { image = 'Combate à Distância ícone', link = 'Combate à Distância' },
	magia = { image = 'Magia ícone', link = 'Magia' },
	melee = { image = 'Ataque ícone', link = 'Corpo a Corpo' },
	ranged = { image = 'Combate à Distância ícone', link = 'Combate à Distância' },
	magic = { image = 'Magia ícone', link = 'Magia' },
	dragonfire = { image = 'Fogo de dragão ícone', link = 'Fogo de dragão' },
	['fogo de dragão'] = { image = 'Fogo de dragão ícone', link = 'Fogo de dragão' },
	['fogo do dragão'] = { image = 'Fogo de dragão ícone', link = 'Fogo de dragão' },
	['bafo de dragão'] = { image = 'Fogo de dragão ícone', link = 'Fogo de dragão' },
	['bafo do dragão'] = { image = 'Fogo de dragão ícone', link = 'Fogo de dragão' },
	na = { image = 'Sem fraqueza ícone', link = '' },
	typeless = { image = 'Sem fraqueza ícone', link = '' }
}

local styles_map = {
	melee = 'corpo a corpo',
	['corpo a corpo'] = 'corpo a corpo',
	magia = 'magia',
	magic = 'magia',
	mage = 'magia',
	['combate à distância'] = 'combate à distância',
	range = 'combate à distância',
	ranged = 'combate à distância',
	ranging = 'combate à distância',
	dragonfire = 'fogo de dragão',
	['dragon fire'] = 'fogo de dragão',
	dragonbreath = 'fogo de dragão',
	['dragon breath'] = 'fogo de dragão',
	['fogo de dragão']= 'fogo de dragão',
	['fogo do dragão']= 'fogo de dragão',
	['bafo do dragão']= 'fogo de dragão',
	['bafo de dragão']= 'fogo de dragão',
	['não'] = 'nenhum',
	['n/d'] = 'nenhum',
	nenhum = 'nenhum',
	no = 'nenhum',
	na = 'nenhum',
	none = 'nenhum',
	['n/a'] = 'nenhum'
}

local primary_styles = {
	melee = { 'inquisidor', '[[Arquivo:Cajado de inquisidor.png|25px|link=Cajado de inquisidor]]'},
	ranged = { 'terrassauro', '[[Arquivo:Malho de terrassauro.png|25px|link=Malho de terrassauro]]'},
	magic = { 'caçarrex', '[[Arquivo:Arco caçarrex.png|25px|link=Arco caçarrex]]'},
	['corpo a corpo'] = { 'inquisidor', '[[Arquivo:Cajado de inquisidor.png|25px|link=Cajado de inquisidor]]'},
	['combate à distância'] = { 'terrassauro', '[[Arquivo:Malho de terrassauro.png|25px|link=Malho de terrassauro]]'},
	magia = { 'caçarrex', '[[Arquivo:Arco caçarrex.png|25px|link=Arco caçarrex]]'},
	['Corpo a Corpo'] = { 'inquisidor', '[[Arquivo:Cajado de inquisidor.png|25px|link=Cajado de inquisidor]]'},
	['Combate à Distância'] = { 'terrassauro', '[[Arquivo:Malho de terrassauro.png|25px|link=Malho de terrassauro]]'},
	Magia = { 'caçarrex', '[[Arquivo:Arco caçarrex.png|25px|link=Arco caçarrex]]'}
}

local slay_masters = {
	turael = { text = '[[Turael]] or [[Spria]]', chathead = 'turael cabeça', category = 'Monstros designados por Turael ou Spria' },
	mazchna = { text = '[[Mazchna]] or [[Achtryn]]', chathead = 'mazchna cabeça', category = 'Monstros designados por Mazchna ou Achtryn' },
	chaeldar = { text = '[[Chaeldar]]', chathead = 'chaeldar cabeça', category = 'Monstros designados por Chaeldar' },
	sumona = { text = '[[Sumona]]', chathead = 'sumona cabeça', category = 'Monstros designados por Sumona' },
	vannaka = { text = '[[Vannaka]]', chathead = 'vannaka cabeça', category = 'Monstros designados por Vannaka' },
	duradel = { text = '[[Duradel]] or [[Lapalok]]', chathead = 'duradel cabeça', category = 'Monstros designados por Duradel ou Lapalok' },
	kuradal = { text = '[[Kuradal]]', chathead = 'kuradal cabeça', category = 'Monstros designados por Kuradal' },
	morvran = { text = '[[Morvran]]', chathead = 'morvran cabeça', category = 'Monstros designados por Morvran' },
	mandrith = { text = '[[Mandrith]]', chathead = 'Mandrith cabeça', category = 'Monstros designados por Mandrith' },
	laniakea = { text = '[[Laniakea]]', chathead = 'Laniakea cabeça', category = 'Monstros designados por Laniakea' },
}

local slay_masters_map = {
	turael = 'turael',
	spria = 'turael',
	mazchna = 'mazchna',
	achtryn = 'mazchna',
	chaeldar = 'chaeldar',
	sumona = 'sumona',
	vannaka = 'vannaka',
	duradel = 'duradel',
	lapalok = 'duradel',
	kuradal = 'kuradal',
	morvran = 'morvran',
	mandrith = 'mandrith',
	laniakea = 'laniakea',
	['não'] = 'nenhum',
	['n/d'] = 'nenhum',
	nenhum = 'nenhum',
	no = 'nenhum',
	none = 'nenhum',
	['n/a'] = 'nenhum'
}

local slay_masters_order = { 'turael', 'mazchna', 'chaeldar', 'sumona', 'vannaka', 'duradel', 'kuradal', 'morvran', 'mandrith', 'laniakea' }

local speed_map = {
	['1'] = 1,
	['2'] = 2,
	['3'] = 3,
	['4'] = 4,
	['5'] = 5,
	['6'] = 6,
	['7'] = 7,
	['8'] = 8,
	['9'] = 9,
	['10'] = 10,
	['n/a'] = 0,
	['random'] = 'random',
	['aleatório'] = 'aleatório',
	['0'] = 0
}

-- load weaknesses instead of remapping
local weaknesses = mw.loadData('Módulo:Ícone_fraqueza/data')

-- location restriction
local restriction_map = {
	surface = 'superfície',
	['superfície'] = 'superfície',
	superficie = 'superfície',
	dungeoneering = 'dungeon',
	dg = 'dungeon',
	daemonheim = 'dungeon',
	dungeon = 'dungeon',
	quest = 'missão',
	['missão'] = 'missão',
	missao = 'missão',
	minigame = 'minijogo',
	minijogo = 'minijogo',
	activity = 'minijogo',
	atividade = 'minijogo',
	removido = 'removido',
	gone = 'removido',
	removed = 'removido',
	limited = 'limitado',
	limitado = 'limitado',
}

-- Main function called with invokes
function p.main(frame)
	local args = frame:getParent().args
	local ret = infobox.new(args)
	local yn_args = {
		'agressivo'
	}
	local immune_args = {
		'imune a veneno', 'imune a dano de recuo',
		'imune a atordoamento', 'imune a drenar estatísticas'
	}
	local num_args = {
		'extermínio nível',
		'ataque', 'força', 'defesa', 'combate à distância', 'magia',
		'dano corpo', 'dano distância', 'dano magia', 'dano especial',
		'precisão corpo', 'precisão distância', 'precisão magia', 'armadura',
		'afinidade corpo', 'afinidade distância', 'afinidade magia' } --aff_weakness has a special func

	for _, v in ipairs(yn_args) do
		ret:defineParams{ { name = v, func = { name = boolargs, params = { v, v }, flag = { 'p', 'r' } } }}
		ret:defineParams{ { name = v..'_smw', func = { name = boolsmwargs, params = { v }, flag = { 'd' } } }}
	end
	for _, v in ipairs(immune_args) do
		ret:defineParams{ { name = v, func = { name = immuneargs, params = { v, v }, flag = { 'p', 'r' } } }}
		ret:defineParams{ { name = v..'_smw', func = { name = immunesmwargs, params = { v }, flag = { 'd' } } }}
	end

	for _, v in ipairs(num_args) do
		ret:defineParams{
			{ name = v, func = { name = numberargs, params = { v, v }, flag = { 'p', 'r' } } },
			{ name = v..'_smw', func = { name = numargraw, params = { v }, flag = 'd' } }
		}
	end
	ret:defineParams{
		{ name = 'vanchor', func = { name = 'has_content', params = { 'versão' }, flag = 'p' } },
		{ name = 'venenoso', func = { name = poisonarg, params = { 'venenoso' }, flag = 'p' } },
		{ name = 'venenoso_smw', func = { name = boolsmwargs, params = { 'venenoso' }, flag = 'd' } },
		{ name = 'nível', func = combatarg },
		{ name = 'level_smw', func =  { name = numargraw2, params = { 'nível' }, flag = 'p' } },
		{ name = 'estilo', func = stylearg },
		{ name = 'styleimg', func = { name = styleimgarg, params = { 'estilo' }, flag = 'p', dupes = true } },
		{ name = 'styletxt', func = { name = styletxtarg, params = { 'estilo' }, flag = 'p', dupes = true } },
		{ name = 'primarystyle_smw', func = { name = primarystylesmwarg, params = { 'estilo primário' }, flag = 'p', dupes = true } },
		{ name = 'vida', func = numargcommas },
		{ name = 'lpraw', func = { name = numargraw, params = { 'vida' }, flag = 'p' } },
		{ name = 'experiência', func = numargcommas },
		{ name = 'xpraw', func = { name = numargraw, params = { 'experiência' },  flag = 'p' } },
		{ name = 'hpxp', func = { name = hpxparg, params = { 'experiência' } } },
		{ name = 'exparma2m', func = numargcommas },
		{ name = 'exparma', func = numargcommas },
		{ name = 'exparmasec', func = numargcommas },
		{ name = 'wepxp', func = { name = wepxparg, params = { 'experiência', 'exparma2m', 'exparma', 'exparmasec' } } },
		{ name = 'extermínio exp', func = numargcommas },
		{ name = 'extermínio exp raw', func = { name = numargraw, params = { 'extermínio exp' },  flag = 'p' } },
		{ name = 'extermínio exp_smw', func = { name = numargraw, params = { 'extermínio exp' }, flag = 'd' } },
		{ name = 'fraqueza', func = weaknessarg },
		{ name = 'generalweakness', func = { name = generalweaknessarg, params = { 'afinidade corpo', 'afinidade distância', 'afinidade magia' } } },
		{ name = 'weaknessimg', func = { name = weaknessimgarg, params = { 'fraqueza' }, flag = 'p', dupes = true } },
		{ name = 'weaknesstxt', func = { name = weaknesstxtarg, params = { 'fraqueza' }, flag = 'p', dupes = true } },
		{ name = 'explicit_weakness', func = { name = explicitwkarg, params = { 'fraqueza' }, flag = 'p' } },
		{ name = 'afinidade fraqueza', func = { name = aff_weakness_arg , params = { 'afinidade fraqueza', 'afinidade fraqueza', 'fraqueza' }, flag = { 'p', 'r', 'p' } } },
		{ name = 'aff_weakness_smw', func = { name = aff_weakness_smw_arg , params = { 'afinidade fraqueza', }, flag = { 'd' } } },
		{ name = 'suscetível a', func = { name = susceptarg, params = { 'suscetível a', 'fraqueza', 'estilo primário' }, flag = 'p' } },
		{ name = 'susceptibility_smw', func = { name = susceptarg_smw, params = { 'suscetível a', 'fraqueza', 'estilo primário' }, flag = 'p' } },
		{ name = 'recursos', func = abilarg },
		{ name = 'recursos_sep', func = abilseparg },
		{ name = 'designado por', func = slayerarg },
		{ name = 'assigned_by_img', func = { name = slayerimgarg, params = { 'designado por' }, flag = 'p', dupes = true } },
		{ name = 'not_assigned', func = { name = notassarg, params = { 'designado por' }, flag = 'p' } },
		{ name = 'lançamento', func = 'release' },
		{ name = 'descontinuado', func = 'removal' },
		{ name = 'membros', func = 'has_content' },
		{ name = 'examinar', func = 'has_content' },
		{ name = 'voz', func = 'has_content' },
		{ name = 'velocidade', func = speedarg },
		{ name = 'nome', func = 'name' },
		{ name = 'inglês', func = { name = inglesarg, params = { 'inglês', 'nome', 'id' }, flag = { 'd' } } },
		{ name = 'aka', func = 'has_content' },
		{ name = 'imagem', func = 'image' },
		{ name = 'ícone', func = 'image' },
		{ name = 'ícone_cell', func = { name = icon, params = { 'nome', 'ícone' }, flag='d' } },
		{ name = 'cabeça', func = 'image' },
		{ name = 'extermínio categoria', func = slayercatarg },
		{ name = 'slayercat_smw', func = { name = slayercatsmwarg, params = { 'extermínio categoria' }, flag='d' } },
		{ name = 'restriction', func = restrictionarg },
		{ name = 'restrictionsurface', func = { name = restrsurfarg , params = { 'restriction', 'restriction' }, flag = { 'd', 'p' } } },
		{ name = 'nível roubo', func = { name = numberargs, params = { 'nível roubo', 'nível roubo' }, flag = { 'p', 'r' } } },
		{ name = 'thievelvl_smw', func =  { name = numargraw2, params = { 'nível roubo' }, flag = 'p' } },
 
		-- not used; only for categories
		{ name = 'id', func = iddisp },
		{ name = 'id_smw', func = { name = idsmw, params = { 'id' }, flag = 'p' } },
		{ name = 'chisel_links', func = { name = make_chisel_links, params = { 'id_smw', 'nome' }, flag = 'd' } },
		{ name = 'rscid', func = 'numbers' },
		{ name = 'SMWarg', func = { name = SMWarg, params = { 'nome', 'versão', 'id', 'membros', 'lançamento', 'descontinuado', 'examinar', 
			'nível', 'estilo', 'lpraw', 'fraqueza', 'xpraw', 'extermínio nível', 'extermínio exp', 'designado por', 'extermínio categoria',
			'venenoso', 'recursos_sep', 'restriction', 'agressivo', 
			'imune a atordoamento', 'imune a drenar estatísticas', 'imune a veneno', 'imune a dano de recuo',
			'ataque', 'magia', 'combate à distância', 'defesa', 'dano corpo', 'dano magia', 'dano distância', 'dano especial', 
			'precisão corpo', 'precisão magia', 'precisão distância', 'armadura', 
			'afinidade corpo', 'afinidade magia', 'afinidade distância', 'afinidade fraqueza' }, flag = 'd', dupes = true } }
	}

	ret:useSMW({
		level_smw = 'Nível de combate',
		xpraw = 'Experiência de combate',
		members = 'É somente para membros',
		release = 'Data de lançamento',
		update = 'Data de atualização',
		removal = 'Data de remoção',
		removalupdate = 'Atualização de remoção'
	})

	ret:useSMWOne({
		id_smw = 'All ID do NPC'
	})
	
	ret:useSMWSubobject({
		id_smw = 'ID do NPC',
		name = 'Nome do Monstro',
		vanchor = 'Versão',
		level_smw = 'Nível de combate',
		xpraw = 'Experiência de combate',
		thievelvl_smw = 'Nível de Roubo',
		members = 'É somente para membros',
		release = 'Data de lançamento',
		update = 'Data de atualização',
		removal = 'Data de remoção',
		removalupdate = 'Atualização de remoção',
		styleimg = 'Estilo de ataque do NPC',
		styletxt = 'Texto do estilo de ataque do NPC',
		primarystyle_smw = 'Estilo de ataque primário do NPC',
		lpraw = 'Pontos vitais do NPC',
		weaknessimg = 'Fraqueza',
		weaknesstxt = 'Texto de fraqueza',
		generalweakness = 'Fraqueza por classe',
		susceptibility_smw = 'Suscetível a',
		slayercat_smw = 'Categoria de Extermínio',
		slaylvl_smw = 'Nível de Extermínio',
		slayxp_smw = 'Experiência em Extermínio',
		assigned_by_img = 'Designado por',
		restriction = 'Local de restrição',
		attack_smw = 'Nível de Ataque do NPC',
		magic_smw = 'Nível de Magia do NPC',
		ranged_smw = 'Nível de Combate à Distância do NPC',
		defence_smw = 'Nível de Defesa do NPC',
		max_melee_smw = 'Dano máximo de Corpo a Corpo do NPC',
		max_magic_smw = 'Dano máximo de Magia do NPC',
		max_ranged_smw = 'Dano máximo de Combate à Distância do NPC',
		max_spec_smw = 'Dano máximo de Habilidade Especial do NPC',
		acc_melee_smw = 'Precisão de Corpo a Corpo do NPC',
		acc_magic_smw = 'Precisão de Magia do NPC',
		acc_ranged_smw = 'Precisão de Combate à Distância do NPC',
		armour_smw = 'Armadura do NPC',
		aff_melee_smw = 'Afinidade de Corpo a Corpo do NPC',
		aff_magic_smw = 'Afinidade de Magia do NPC',
		aff_ranged_smw = 'Afinidade de Combate à Distância do NPC',
		aff_weakness_smw = 'Afinidade de Fraqueza do NPC',
		aggressive_smw = 'NPC é agressivo',
		venenoso_smw = 'NPC é venenoso',
		immune_to_poison_smw = 'NPC suscetível a veneno',
		immune_to_deflect_smw = 'NPC suscetível a dano de recuo',
		immune_to_stun_smw = 'NPC suscetível a atordoamento',
		immune_to_drain_smw = 'NPC suscetível a drenar estatísticas',
		SMWarg = 'Monster JSON',
	})

	ret:defineLinks({
		links = {
			{ 'Predefinição:%s/FAQ', 'FAQ' },
			{ 'Predefinição:Infobox monstro/doc', 'doc' }
		},
		colspan = 12
	})
	ret:customButtonPlacement(true)
	ret:create()
	ret:cleanParams()

	ret:addClass('infobox-monster')
	ret:defineName('Infobox Monstro')
	
	-- use catargs
	if onmain() then
		local a2 = ret:categoryData()
		if not a2['restriction'].all_defined then
			ret:useSMWSubobject({
				restrictionsurface = 'Local de restrição'
			})
		end
	end

	
	-- PARAMETER: chathead
	if ret:paramDefined('cabeça', 'all') then
		ret:addRow{
			{ tag = 'argd', content = 'cabeça', class='infobox-image', colspan = '12' }
		}
	end

	-- PARAMETER: nome
	ret:addRow{
		{ tag = 'argh', content = 'nome', class='infobox-header', colspan = '12' }
	}
	ret:addButtonsRow{
		colspan = 12
	}
	-- PARAMETER: imagem
	ret:addRow{
		{ tag = 'argd', content = 'imagem', class='infobox-image bordered-image', colspan = '12' }
	}
	-- PARAMETER: ícone
	if ret:paramDefined('ícone') then
		ret:addRow{
			{ tag = 'argd', content = 'ícone', class='infobox-image', colspan = '12' }
		}
	end
	-- PARAMETER: examinar
	--	:addRow{ { tag = 'th', content = 'Examinar', class = 'infobox-subheader', colspan = '12' } }

	ret:addRow{ { tag = 'argd', content = 'examinar', css = { ['text-align'] = 'center', ['max-width'] = '250px' , ['font-style'] = 'italic'}, colspan = '12' } }

	-- PARAMETER: inglês
		:addRow{
		{ tag = 'th', content = 'Inglês', colspan = '4' },
		{ tag = 'argd', content = 'inglês', css = { ['text-align'] = 'left' }, colspan = '8' }}
	-- PARAMETER: membros
		:addRow{ { tag = 'th', content = 'Membros', colspan = '4' },
				{ tag = 'argd', content = 'membros', css = { ['text-align'] = 'left' }, colspan = '8' } }
	

	-- PARAMETER: release
	-- (update included automatically by infobox)
	ret:addRow{ { tag = 'th', content = 'Lançamento', colspan = '4' },
				{ tag = 'argd', content = 'lançamento', css = { ['text-align'] = 'left' }, colspan = '8' } }

	-- PARAMETER: removal
	if ret:paramDefined('descontinuado') then
		ret:addRow{ { tag = 'th', content = 'Descontinuado', colspan = '4' },
				{ tag = 'argd', content = 'descontinuado', css = { ['text-align'] = 'left' }, colspan = '8' } }
	end

	-- PARAMETER: aka
	-- add only if it exists
	if ret:paramDefined('aka') then
		   ret:addRow{ { tag = 'th', content = 'AKA', colspan = '4' },
					{ tag = 'argd', content = 'aka', css = { ['text-align'] = 'left', ['max-width'] = '100px' }, colspan = '8' } }
	end

	-- COMBAT INFO
	ret:addRow{ { tag = 'th', content = 'Combate', colspan = '12', class = 'combat-info-header infobox-subheader' } }
		-- PARAMETER: nível | vida | experiência | hpxp
		:addRow{ { tag = 'th', content = '[[Nível de combate|Nível]]', class = 'combat-subheader', colspan = '3' },
				{ tag = 'th', content = '[[Pontos vitais|PV]]', class = 'combat-subheader', colspan = '3' },
				{ tag = 'th', content = '[[Arquivo:Combate ícone.png|link=|20px]] EXP', class = 'combat-subheader', colspan = '3', title = 'Experiência no estilo de combate' },
				{ tag = 'th', content = '[[Arquivo:Condição Física ícone.png|link=|20px]] EXP', class = 'combat-subheader', colspan = '3', title = 'Experiência em condição física' } }

		:addRow{ { tag = 'argd', content = 'nível', colspan = '3' },
				{ tag = 'argd', content = 'vida', colspan = '3' },
				{ tag = 'argd', class='mob-cb-xp', content = 'experiência', colspan = '3' },
				{ tag = 'argd', class='mob-hp-xp', content = 'hpxp', colspan = '3' } }
		-- PARAMETER: wepxp
		:addRow{ { tag = 'th', content = 'EXP Equip. (2M/MP & Armad./MS)', class = 'combat-subheader', colspan = '12' } }
		:addRow{ { tag = 'argd', content = 'wepxp', class='mob-eq-xp', colspan = '12' } }
		-- PARAMETER: aggressive | venenoso
		:addRow{ { tag = 'th', content = 'Agressivo', class = 'combat-subheader', colspan = '6' },
				{ tag = 'th', content = 'Venenoso', class = 'combat-subheader', colspan = '6' } }
		:addRow{ { tag = 'argd', content = 'agressivo', colspan = '6' },
				{ tag = 'argd', content = 'venenoso', colspan = '6' } }
	-- Slayer information
	-- dynamic size, dependent on whether or not the monster is assigned
	local slayer_level = ret:paramDefined('extermínio nível','all')
	local not_assigned = ret:param('not_assigned','f')
	local _not_assigned = true
	if not_assigned.d == false then
		_not_assigned = false
	elseif not_assigned.switches then
		for _, v in ipairs(not_assigned.switches) do
			if v == false then
				_not_assigned = false
				break
			end
		end
	end
	-- do slayer row if a monster is assigned, or has a required level
	if _not_assigned == false or slayer_level == true then
		-- PARAMETER: slaylvl | slayxp | slayercat
		ret:addRow{ { tag = 'th', content = 'Extermínio', class = 'slayer-header', colspan = '12' } }
			:addRow{ { tag = 'th', content = 'Nível', class = 'slayer-subheader', colspan = '3' },
					{ tag = 'th', content = 'EXP', class = 'slayer-subheader', colspan = '3' },
					{ tag = 'th', content = 'Categoria', class = 'slayer-subheader', colspan = '6' } }
			:addRow{ { tag = 'argd', content = 'extermínio nível', colspan = '3' },
					{ tag = 'argd', class='mob-slay-xp', content = 'extermínio exp', colspan = '3' },
					{ tag = 'argd', content = 'extermínio categoria', colspan = '6' } }
			:addRow{ { tag = 'th', content = 'Designado por', class = 'slayer-subheader', colspan = '12' } }
			:addRow{ { tag = 'argd', content = 'designado por',colspan = '12' } }
	end
	
	----------------
	-- OFFENSIVE STATS
	local max_disc = 'Este valor é o valor padrão não legado. O número reflete o acerto máximo BASE usado pelo monstro nos cálculos de dano. Mecânicas de aumento de danos, como enrage, não são levadas em consideração.'
	ret:addRow{ { tag = 'th', content = 'Ofensivo', class = 'offensive-header', colspan = '12' } }
	
		:addRow{ { tag = 'th', content = 'Dano máximo', class = 'offensive-subheader', colspan = '12' } }
	-- PARAMETER: max_melee | max_ranged | max_magic | max_spec
		:addRow{ { tag = 'td', content = '[[Arquivo:Ataque ícone.png|20px|link=]]', title = 'Dano máximo por corpo a corpo', colspan = '3' },
				{ tag = 'td', content = '[[Arquivo:Combate à Distância ícone.png|20px|link=]]', title = 'Dano máximo por combate à distância', colspan = '3' },
				{ tag = 'td', content = '[[Arquivo:Magia ícone.png|20px|link=]]', title = 'Dano máximo por magia', colspan = '3' },
				{ tag = 'td', content = '[[Arquivo:Ataque especial ícone.png|20px|link=]]', title = 'Dano máximo por ataque especial', colspan = '3' } }
		:addRow{ { tag = 'argd', content = 'dano corpo', title = max_disc, colspan = '3' },
				{ tag = 'argd', content = 'dano distância', title = max_disc, colspan = '3' },
				{ tag = 'argd', content = 'dano magia', title = max_disc, colspan = '3' },
				{ tag = 'argd', content = 'dano especial', title = max_disc, colspan = '3' } }

	-- PARAMETER: style | rate (formely speed)
		:addRow{ { tag = 'th', content = 'Estilo', class = 'offensive-subheader', colspan = '6' },
				{ tag = 'th', content = 'Velocidade', class = 'offensive-subheader', colspan = '6' } }

		:addRow{ { tag = 'argd', content = 'estilo', colspan = '6' },
				{ tag = 'argd', content = 'velocidade', colspan = '6' } }

	-- PARAMETER: acc_melee | acc_ranged | acc_magic
		:addRow{ { tag = 'th', content = 'Níveis de Combate', class = 'offensive-subheader', colspan = '12' } }


	-- Accuracy parameters
	local levels_disc = "Este é o nível do monstro nesta habilidade de combate. Funciona da mesma forma que o de um jogador - afeta a precisão ou a armadura da mesma forma (mas não causa danos)."
	
	ret:addRow {
		{ tag = 'td', content = '[[Arquivo:Ataque ícone.png|20px|link=]]', title = 'Nível de Ataque', colspan = '4' },
		{ tag = 'td', content = '[[Arquivo:Combate à Distância ícone.png|20px|link=]]', title = 'Nível de Combate à Distância', colspan = '4' },
		{ tag = 'td', content = '[[Arquivo:Magia ícone.png|20px|link=]]', title = 'Nível de Magia', colspan = '4' }
	}

	:addRow {
		{ tag = 'argd', content = 'ataque', title = levels_disc, colspan = '4' },
		{ tag = 'argd', content = 'combate à distância', title = levels_disc, colspan = '4' },
		{ tag = 'argd', content = 'magia', title = levels_disc, colspan = '4' }
	}

	:addRow {
		{ tag = 'th', content = 'Precisão', class = 'offensive-subheader', colspan = '12' }
	}

	:addRow {
		{ tag = 'td', content = '[[Arquivo:Ataque ícone.png|20px|link=]]', title = 'Precisão de corpo a corpo como uma função de 2,5 * f(x)', colspan = '4' },
		{ tag = 'td', content = '[[Arquivo:Combate à Distância ícone.png|20px|link=]]', title = 'Precisão de combate à distância como uma função de 2.5 * f(x)', colspan = '4' },
		{ tag = 'td', content = '[[Arquivo:Magia ícone.png|20px|link=]]', title = 'Precisão de magia como uma função de 2.5 * f(x)', colspan = '4' }
	}

	:addRow {
		{ tag = 'argd', content = 'precisão corpo', colspan = '4' },
		{ tag = 'argd', content = 'precisão distância', colspan = '4' },
		{ tag = 'argd', content = 'precisão magia', colspan = '4' }
	}

	-- PARAMETER: abilities
	-- only add if they exist
	local abilities = ret:param('recursos','f')
	local _abilities = false
	if abilities.d and abilities.d ~= 'Nenhum' then
		_abilities = true
	end
	if abilities.switches then
		for _, v in ipairs(abilities.switches) do
			if v ~= _nil then
				_abilities = true
				break
		   end
		end
	end
	if _abilities then
		ret:addRow{ { tag = 'th', content = 'Recursos usados', class = 'offensive-subheader', colspan = '12' } }
			:addRow{ { tag = 'argd', content = 'recursos', colspan = '12' } }

	end
	-- DEFENSIVE STATS
	ret:addRow{ { tag = 'th', content = 'Defensivo', class = 'defensive-header', colspan = '12' } }
	-- PARAMETER: armadura | defesa | fraqueza
		:addRow{ { tag = 'th', content = 'Armadura', class = 'defensive-subheader', css = { ['padding-left'] = '0', ['padding-right'] = '0' }, colspan = '3' },
				{ tag = 'th', content = '[[Arquivo:Defesa ícone.png|link=]]', class = 'defensive-subheader', title = 'Nível de defesa', colspan = '2' },
				{ tag = 'th', content = 'Fraqueza', class = 'defensive-subheader', colspan = '3' },
				{ tag = 'th', content = 'Suscetível a', class = 'defensive-subheader', colspan = '4' } }
		:addRow{ { tag = 'argd', content = 'armadura', colspan = '3' },
				{ tag = 'argd', content = 'defesa', title = levels_disc, colspan = '2' },
				{ tag = 'argd', content = 'fraqueza', colspan = '3' },
				{ tag = 'argd', content = 'suscetível a', colspan = '4', class = "infobox-monster-susceptibility-cell" } }

	-- PARAMETER: explicit_weakness
	-- PARAMETER: aff_weakness | aff_melee | aff_ranged | aff_magic
		:addRow{ { tag = 'th', content = 'Afinidades', class = 'defensive-subheader', colspan = '12' } }
		:addRow{ { tag = 'argd', content = 'explicit_weakness', title = 'Valor de afinidade da fraqueza explícita do monstro', colspan = '3' },
				{ tag = 'td', content = '[[Arquivo:Ataque ícone.png|20px|link=]]', title = 'Valor de afinidade do monstro contra ataques de corpo a corpo', colspan = '3' },
				{ tag = 'td', content = '[[Arquivo:Combate à Distância ícone.png|20px|link=]]', title = 'Valor de afinidade do monstro contra ataques de combate à distância', colspan = '3' },
				{ tag = 'td', content = '[[Arquivo:Magia ícone.png|20px|link=]]', title = 'Valor de afinidade do monstro contra ataques de magia', colspan = '3' } }
		:addRow{ { tag = 'argd', content = 'afinidade fraqueza', colspan = '3' },
				{ tag = 'argd', content = 'afinidade corpo', colspan = '3' },
				{ tag = 'argd', content = 'afinidade distância', colspan = '3' },
				{ tag = 'argd', content = 'afinidade magia', colspan = '3' } }

	-- PARAMETER: immune_to_poison | immune_to_deflect | immune_to_stun | immune_to_drain
		:addRow{ { tag = 'th', content = 'Imunidades', class = 'defensive-subheader', colspan = '12' } }
		:addRow{ { tag = 'td', content = '[[Arquivo:Imune a veneno.png|27x27px|frameless|link=]]', title = 'Imune a veneno?', colspan = '3' },
				{ tag = 'td', content = '[[Arquivo:Imune a dano de recuo.png|27x27px|frameless|link=]]', title = 'Imune a dano de recuo?', colspan = '3' },
				{ tag = 'td', content = '[[Arquivo:Imune a atordoamento.png|27x27px|frameless|link=]]', title = 'Imune a atordoamento?', colspan = '3' },
				{ tag = 'td', content = '[[Arquivo:Imune a drenar estatísticas.png|27x27px|frameless|link=]]', title = "Imune a drenar estatísticas?", colspan = '3' } }
		:addRow{ meta = { addClass = 'infobox-monster-immunites-row' }, 
				{ tag = 'argd', content = 'imune a veneno', colspan = '3' },
				{ tag = 'argd', content = 'imune a dano de recuo', colspan = '3' },
				{ tag = 'argd', content = 'imune a atordoamento', colspan = '3' },
				{ tag = 'argd', content = 'imune a drenar estatísticas', colspan = '3' } }
	
	-- advanced data
	ret	:addRow{
			{ tag = 'th', content = 'Dados Avançados', class = 'infobox-subheader', colspan = '12' },
			meta = {addClass = 'advanced-data'}
		}
		:addRow{
			{ tag = 'th', content = 'ID de NPC', colspan = '4' },
			{ tag = 'argd', content = 'id', colspan = '6' },
			meta = {addClass = 'advanced-data'}
		}
		:addRow{
			{ tag = 'th', content = 'Links', colspan = '4' },
			{ tag = 'argd', content = 'chisel_links', colspan = '6' },
			meta = {addClass = 'advanced-data'}
		}
	
	
	-- For infobox hit calc
	--ret:addRow{ { tag = 'th', content = 'Hit Calculator', class = 'rsw-ihc-header infobox-header', colspan = '12' } }
	--	:addRow{ meta = { addClass = 'infobox-hitcalc' },
	--		{ tag = 'td', content = 'JavaScript is required for hitcalculator to function!', colspan = '12' } }
	
	ret:finish()
	if onmain() then
		local a1 = ret:param('all')
		local a2 = ret:categoryData()
		ret:wikitext(addcategories(a1,a2))
	end
	return ret:tostring()
end

-- For numerical args
function numberargs(arg,v)
	local arg_v = (arg or ''):find('%S') and string.gsub(arg,',','') or -1
	local arg_i
	if arg_v == -1 then
		arg_i = nil
	elseif string.lower(arg_v) == 'n/a' then
		arg_i = 'N/A'
	elseif string.lower(arg_v) == 'varies' then
		arg_i = 'Varies'
	else
		arg_i = tonumber(mw.ustring.gsub(arg_v:gsub(',',''), '%s+', ''),10)
		if not arg_i then
			arg_i = badarg(v,'deve ser um valor número único.')
		end
	end
	return arg_i
end

-- For combat level
function combatarg(arg)
	local arg_v = (arg or ''):find('%S') and string.gsub(arg,',','') or -1
	local arg_i
	if arg_v == -1 then
		arg_i = nil
	elseif string.lower(arg_v) == 'n/a' or tonumber(arg_v) == 0 then
		arg_i = 'N/A'
	else
		arg_i = tonumber(arg_v:gsub(',',''):gsub(' ',''),10)
		if not arg_i then
			arg_i = badarg('level','deve ser um valor número único.')
		end
	end
	return arg_i
end

-- For numbers (adds commas)
function numargcommas(arg)
	local ret = numberargs(arg)
	mw.log(ret)
	if type(ret) == 'number' then
		return commas(ret)
	else
		return ret
	end
end

-- For numbers
function numargraw(arg)
	if not arg then return 0 end
	if type(arg) ~= 'number' then
		arg = tostring(arg)
		arg = mw.ustring.gsub(arg:gsub(',', ''), '%s+', '')
	end
	return tonumber(arg) or 0
end
function numargraw2(arg)
	if not arg then return nil end
	if type(arg) ~= 'number' then
		arg = tostring(arg)
		arg = mw.ustring.gsub(arg:gsub(',', ''), '%s+', '')
	end
	return tonumber(arg)
end

-- For the icon
function icon(name, icon)
	if not icon then
		return name
	else
		return icon..' '..name
	end
end

-- For hp xp
function hpxparg(arg)
	local xp = string.gsub(arg or '',',','.')
	xp = mw.ustring.gsub(xp,'%s+','')
	if string.lower(xp) == 'n/a' then
		return 'N/A'
	else
		xp = tonumber(xp)
	end
	if type(xp) == 'number' then
		return commas(math.floor(xp*3.3)/10)
	else
		return nil
	end
end

-- weapon xp
function wepxparg(combatxp, wepxp2h, wepxpmhandarmour, wepxpoh)
	local xp = string.gsub(combatxp or '',',','.')
	xp = mw.ustring.gsub(xp,'%s+','')
	local xp2h = string.gsub(wepxp2h or '',',','.')
	xp2h = mw.ustring.gsub(xp2h or '','%s+','')
	local xpmh = string.gsub(wepxpmhandarmour or '',',','.')
	xpmh = mw.ustring.gsub(xpmh or '','%s+','')
	local xpoh = string.gsub(wepxpoh or '',',','.')
	xpoh = mw.ustring.gsub(xpoh or '','%s+','')
	
	if string.lower(xp) == 'n/a' then
		return 'N/A'
	else
		xp = tonumber(xp)
	end
	
	if string.lower(xp2h) ~= '' then
		xp2h = tonumber(xp2h)
	end
	
	if string.lower(xpmh) ~= '' then
		xpmh = tonumber(xpmh)
	end
	
	if string.lower(xpoh) ~= '' then
		xpoh = tonumber(xpoh)
	end
	
	if type(xp) == 'number' then
		local th,mh,oh
		
		if type(xp2h) == 'number' then
		    th = xp2h
		else
		    th = math.floor(xp * .06)
		end
		
		if type(xpmh) == 'number' then
		    mh = xpmh
		else
		    mh = math.floor(xp * .04)
		end
		
		if type(xpoh) == 'number' then
		    oh = xpoh
		else
		    oh = math.floor(xp * .02)
		end
		
		mw.log(th)
		mw.log( string.format('%s / %s / %s',th,mh,oh) )
		
		return string.format('%s / %s / %s',th,mh,oh)
	else
		return nil
	end
end
-- For true/false
function boolargs(arg,argr)
	local arg_v = (arg or ''):find('%S') and arg or -1

	local arg_ret

	if arg_v == -1 then
		arg_ret = nil
	else
		arg_v = yesno(arg_v)
		local argf = '<span title="Este monstro é%s %s.">%s</span>'
		local f1,f3
		local f2 = string.gsub(argr,'_',' ')

		if arg_v then
			f1 = ''
			f3 = '[[Arquivo:Sim.svg|20px|alt=Sim|link=]]'
		else
			f1 = ' not'
			f3 = '[[Arquivo:Não.svg|20px|alt=Não|link=]]'
		end

		arg_ret = string.format(argf,f1,f2,f3)
	end

	return arg_ret
end
function boolsmwargs(arg)
	if infobox.isDefined(arg) then
		arg = string.lower(arg)
		if arg:find('yes check') then
			return 'true'
		elseif arg:find('x mark') then
			return 'false'
		end
	end
	return nil
end

function immuneargs(arg,argr)
	local arg_v = (arg or ''):find('%S') and arg or -1

	local arg_ret

	if arg_v == -1 then
		arg_ret = nil
	else
		arg_v = yesno(arg_v)
		local argf = '<span class="infobox-monster-%s infobox-monster-%s monster-%s-%s" title="Este monstro é%s %s.">%s</span>'
		local f1,f3,f4
		local f2 = string.gsub(argr,'_',' ')
		local f5 = string.gsub(argr,'imune a ','')

		if arg_v then
			f1 = ''
			f3 = 'Imune'
			f4 = 'imune'
			f5 = 'é imune'
		else
			f1 = ' não'
			f3 = 'Não imune'
			f4 = 'Suscetível'
			f5 = 'não é imune'
		end

		arg_ret = string.format(argf, f4, f5, f5, f4, f1, f2, f3)
	end

	return arg_ret
end

function immunesmwargs(arg)
	if infobox.isDefined(arg) then
		arg = string.lower(arg)
		if arg:find('não é imune') then
			return 'true'
		elseif arg:find('é imune') then
			return 'false'
		end
	end
	return nil
end


-- Poison
function poisonarg(arg)
	arg = string.gsub(arg or '',',','')
	arg = string.lower(arg)

	if arg == 'sim' then
		arg = '<span title="Este monstro é venenoso porém não possuí valor base. Mude o parâmetro |venenoso para um número.">[[Arquivo:Sim.svg|20px|alt=Sim|link=]] ???</span>'
	elseif tonumber(arg) then
		arg = '<span title="Este monstro é venenoso. O número mostrado é o valor base no qual o dano por veneno começa.">[[Arquivo:Sim.svg|20px|alt=Sim|link=]] '..tonumber(arg)..'</span>'
	else
		arg = '<span title="Este monstro não é venenoso.">[[Arquivo:Não.svg|20px|alt=Não|link=]]</span>'
	end

	return arg
end
-- English name
function inglesarg(name, ptname, id)
	mw.log('inglesarg ('..name..', '..ptname..', '..id..')')
    if infobox.isDefined(name) then
        return externo({rsw=name}, pagename) .. string.gsub('[[:en:%s|%s]]', '%%s', name)
    else
    	local translate = require('Módulo:Traduções')._simple
    	local engl = false
    	if infobox.isDefined(ptname) then
    		engl = translate(ptname, 'pt', 'npc', 'en')
    	end
    	if infobox.isDefined(id) and not engl then
    		local id1 = string.match(id, '%d+')
    		mw.log('id1 = '..id1)
    		if id1 then
    			id1 = tonumber(id1)
    			engl = translate(id1, 'id', 'npc', 'en')
    		end
    	end
    	mw.log('end engl = ')
    	mw.log(engl)
    	if engl then
    		return externo({rsw=engl}, pagename) .. string.gsub('[[:en:%s|%s]]', '%%s', engl)
    	end
    end
end

-- style
function stylearg(arg)
	-- split by commas
	local atts = mw.text.split(string.lower(arg or ''),'%s*,%s*')
	local _atts = {}
	-- remake the list as a table, remove anything that's blank/doesn't exist
	for _, v in ipairs(atts) do
		local att_x = styles_map[v]
		if att_x then
			table.insert(_atts,attack_styles[att_x])
		end
	end
	local p_att
	if #_atts == 0 then
		p_att = nil
	else
		p_att = {}
		for _, v in ipairs(_atts) do
			table.insert(p_att,string.format('[[Arquivo:%s.png|25px|link=%s]]',v.image,v.link))
		end
		p_att = table.concat(p_att,' ')
	end
	return p_att
end

function styleimgarg(arg)
	-- split by commas
	local atts = mw.text.split(string.lower(arg or ''),'%s*,%s*')
	local _atts = {}
	-- remake the list as a table, remove anything that's blank/doesn't exist
	for _, v in ipairs(atts) do
		local att_x = styles_map[v]
		if att_x then
			table.insert(_atts,attack_styles[att_x])
		end
	end
	local p_att = {}
	if #_atts > 0 then
		for _, v in ipairs(_atts) do
			table.insert(p_att,string.format('Arquivo:%s.png',v.image))
		end
	end
	return table.concat(p_att, '&&SPLITPOINT&&')
end

function styletxtarg(arg)
	-- split by commas
	local atts = mw.text.split(string.lower(arg or ''),'%s*,%s*')
	local _atts = {}
	-- remake the list as a table, remove anything that's blank/doesn't exist
	for _, v in ipairs(atts) do
		local att_x = styles_map[v]
		if att_x then
			table.insert(_atts,att_x)
		end
	end
	return table.concat(_atts, '&&SPLITPOINT&&')
end

function primarystylearg(ps)
	if infobox.isDefined(ps) then
		ps = mw.text.trim(ps:lower())
	end
	if primary_styles[ps] then
		return primary_styles[ps]
	end
	return nil
end

function primarystylesmwarg(ps)
	if infobox.isDefined(ps) then
		ps = mw.text.trim(ps:lower())
	end
	if primary_styles[ps] or ps == 'corpo a corpo' then
		return ps
	end
	return nil
end

-- weakness
function weaknessarg(arg)
	-- split by commas
	local wk = mw.text.split(string.lower(arg or ''),'%s*,%s*')
	local _wk = {}

	-- remake the list as a table, remove anything that's blank/doesn't exist
	for _, v in ipairs(wk) do
		local wk_x = weaknesses[v]
		if wk_x and not wk_x._suscept then
			table.insert(_wk,wk_x)
		end
	end
	local p_wk
	if #_wk == 0 then
		p_wk = nil
	else
		p_wk = {}
		for _, v in ipairs(_wk) do
			table.insert(p_wk,string.format('[[Arquivo:%s|25px|link=%s]]',v.image,v.link))
		end
		p_wk = table.concat(p_wk,' ')
	end
	return p_wk
end

function weaknessimgarg(arg)
	-- split by commas
	local wk = mw.text.split(string.lower(arg or ''),'%s*,%s*')
	local _wk = {}

	-- remake the list as a table, remove anything that's blank/doesn't exist
	for _, v in ipairs(wk) do
		local wk_x = weaknesses[v]
		if wk_x then
			table.insert(_wk,wk_x)
		end
	end
	local p_wk = {}
	for _, v in ipairs(_wk) do
		table.insert(p_wk,string.format('Arquivo:%s',v.image))
	end
	return table.concat(p_wk, '&&SPLITPOINT&&')
end

function weaknesstxtarg(arg)
	-- split by commas
	local wk = mw.text.split(string.lower(arg or ''),'%s*,%s*')
	local _wk = {}

	-- remake the list as a table, remove anything that's blank/doesn't exist
	for _, v in ipairs(wk) do
		local wk_x = weaknesses[v]
		if wk_x then
			table.insert(_wk,v)
		end
	end
	return table.concat(_wk, '&&SPLITPOINT&&')
end

-- Explicit weakness
-- weakness / explicit weakness
function explicitwkarg(arg)
	-- split by commas
	local wk = mw.text.split(string.lower(arg or ''),'%s*,%s*')
	local _wk = weaknesses[wk[1]]
	if _wk then
		return string.format('[[Arquivo:%s|20px|link=]]',_wk.image)
	else
		return nil
	end
end

function aff_weakness_arg(aff,aff_r,weakness)
	-- split by commas
	local wk = mw.text.split(string.lower(weakness or ''),'%s*,%s*')
	local _wk = weaknesses[wk[1]]
	if _wk and _wk.text == 'Nada' then
		return '-'
	else
		return numberargs(aff,aff_r)
	end
end
function aff_weakness_smw_arg(aff)
	if tonumber(aff) then
		return tonumber(aff)
	end
	return nil
end

-- generally weak to (class)
--    looks for the class that the mob is weakest to
--    if multiple equally weak, then none
function generalweaknessarg(aff_melee, aff_ranged, aff_magic)
	aff_melee = tonumber(aff_melee) or 0
	aff_ranged = tonumber(aff_ranged) or 0
	aff_magic = tonumber(aff_magic) or 0
	local max = math.max(aff_melee, aff_magic, aff_ranged)
	if max == 0 then
		return 'nenhum'
	end
	local ret = {}
	
	if aff_melee == max then
		table.insert(ret, 'corpo a corpo')
	end
	if aff_ranged == max then
		table.insert(ret, 'combate à distância')
	end
	if aff_magic == max then
		table.insert(ret, 'magia')
	end
	if #ret == 1 then
		return ret[1]
	end
	return 'nenhum'
end

function wkcats(arg,tbl)
	for v in mw.text.gsplit(arg, infobox.splitpoint) do
		if weaknesses[v] then
			if weaknesses[v].category then
				table.insert(tbl, weaknesses[v].category)
			end
		elseif arg == 'inquisidor' then
			table.insert(tbl, 'Suscetível ao cajado de inquisidor')
		elseif arg == 'terrassauro' then
			table.insert(tbl, 'Suscetível ao malho de terrassauro')
		elseif arg == 'caçarrex' then
			table.insert(tbl, 'Suscetível ao arco caçarrex')
		end
	end
end
	
function susceptarg(sus, wk, ps)
	local sus_check = {}
	local suscepts = {}
	if primary_styles[ps] then
		sus_check[primary_styles[ps][1]] = true
		table.insert(suscepts, primary_styles[ps][2])
	end
	if infobox.isDefined(wk) then
		if wk:find('clarão negro') or wk:find('clarão prateado') then
			wk = wk..',demon bane'
		end
		sus = string.lower(tostring(sus)..','..wk)
	end
	for v in mw.text.gsplit(sus, '%s*,%s*') do
		local u = weaknesses[v]
		if u and u._suscept and not sus_check[u] then
			sus_check[u] = true
			table.insert(suscepts, string.format('[[Arquivo:%s|25px|frameless|link=%s]]', u.image, u.link))
		end
	end
	if #suscepts == 0 then
		return "Nenhum"
	end
	return table.concat(suscepts, ' ')
end
function susceptarg_smw(sus, wk, ps)
	local suscepts = {}
	if primary_styles[ps] then
		table.insert(suscepts, primary_styles[ps][1])
	end
	for v in mw.text.gsplit(string.lower(tostring(sus)..','..tostring(wk)), '%s*,%s*') do
		local u = weaknesses[v]
		if u and u._suscept then
			table.insert(suscepts, v)
		end
	end
	if #suscepts == 0 then
		return nil
	end
	return table.concat(suscepts, '&&SPLITPOINT&&')
end

function slayercatarg(arg)
	if string.match(arg or '','%S') then
		local sl = string.lower(tostring(arg))
		if sl == 'n/d' or sl == 'não' or sl == 'nenhum' or sl == 'no' or sl == 'none' or sl == 'n/a'then
			return 'N/A'
		end
		return tostring(arg)
	end
	return nil
end

function slayercatsmwarg(cat)
	if infobox.isDefined(cat) then
		cat = string.lower(tostring(cat))
		if cat == 'n/d' or cat == 'não' or cat == 'nenhum' or cat == 'no' or cat == 'none' or cat == 'n/a' then
			return nil
		end
		cat = string.gsub(cat, '[][]', '')
		cat = string.gsub(cat, ',', '&&SPLITPOINT&&')
		return cat
	end
	return nil
end

function slaycats(arg,tbl)
	for _, v in pairs(slay_masters) do
		if arg:find(v.chathead) then
			if v.category then
				table.insert(tbl,v.category)
			end
		end
	end
end

-- Slayer assigners
function slayerarg(_arg)
	local arg = _arg
	if arg then
		arg = mw.text.split(string.lower(arg),'%s*,%s*')
		local slayer_master_list = {
			turael = false,
			spria = false,
			mazchna = false,
			achtryn = false,
			vannaka = false,
			chaeldar = false,
			sumona = false,
			duradel = false,
			lapalok = false,
			kuradal = false,
			morvran = false,
			mandrith = false,
			none = false
		}
		for _, v in ipairs(arg) do
			if slay_masters_map[v] then
				slayer_master_list[slay_masters_map[v]] = true
			end
		end
		if slayer_master_list.none then
			arg = 'Não designável'
		else
			arg = {}
			for _, n in ipairs(slay_masters_order) do
				local v = slayer_master_list[n]
				if v then
					--table.insert(params.assigned_by, slay_masters[n].text)
					table.insert(arg, string.format('[[Arquivo:%s.png|30px|link=%s]]',slay_masters[n].chathead,n))
				end
			end
			arg = table.concat(arg,' ')
		end			
	else
		arg = nil
	end
	return arg
end

function slayerimgarg(_arg)
	local arg = _arg
	if arg then
		arg = mw.text.split(string.lower(arg),'%s*,%s*')
		local slayer_master_list = {
			turael = false,
			spria = false,
			mazchna = false,
			achtryn = false,
			vannaka = false,
			chaeldar = false,
			sumona = false,
			duradel = false,
			lapalok = false,
			kuradal = false,
			morvran = false,
			mandrith = false,
			none = false
		}
		for _, v in ipairs(arg) do
			if slay_masters_map[v] then
				slayer_master_list[slay_masters_map[v]] = true
			end
		end
		if not slayer_master_list.none then
			arg = {}
			for _, n in ipairs(slay_masters_order) do
				local v = slayer_master_list[n]
				if v then
					table.insert(arg, string.format('Arquivo:%s.png',slay_masters[n].chathead))
				end
			end
			return table.concat(arg, '&&SPLITPOINT&&')
		end
	end
	return ''
end

-- Not assigned
function notassarg(arg)
	if arg then
		if arg:find('%?action=edit') or not arg:find('%S') then
			return true
		end
		arg = mw.text.split(string.lower(arg),'%s*,%s*')
		for _, v in ipairs(arg) do
			if slay_masters_map[v] == 'nenhum' then
				return true
			end
		end
	end
	return false
end

-- Abilities used
function abilarg(arg)
	arg = paramtest.default_to(arg,false)
	if not arg then
		arg = 'Nenhum'
	elseif arg:find('recursos') then
		arg = mw.getCurrentFrame():preprocess(arg)
	else
		arg = 'Nenhum'
	end
	return arg
end

function abilseparg(arg)
	arg = paramtest.default_to(arg,false)
	if not arg then
		arg = ''
	elseif arg:find('recursos') then
		arg = arg:gsub('{{[rR]link|',''):gsub('}}',''):gsub('|',',')
	else
		arg = ''
	end
	return arg
end

-- Attacks speed
function speedarg(arg)
	if paramtest.is_empty(arg) then
		return nil
	end
	_,_,arg = string.find(arg:lower()..' ','^(.-)%s')
	arg = tostring(attack_speed_bar(speed_map[arg])) or badarg('velocidade',' valor de velocidade inválido.')
	return arg
end

function restrictionarg(arg)
	if paramtest.is_empty(arg) then
		return nil
	end
	return restriction_map[string.lower(arg)]
end
function restrsurfarg(cleaned, passed)
	if infobox.isDefined(cleaned) then
		return nil
	end
	return restriction_map.surface
end

function iddisp(id)
	if infobox.isDefined(id) then
		return string.gsub(id, ', *', ', ')
	end
	return nil
end
function idsmw(id)
	if infobox.isDefined(id) then
		if string.lower(tostring(id)) == 'no' then
			return nil
		end
		local r = string.gsub(id, ', *', infobox.splitpoint)
		return r
	end
	return nil
end

function make_chisel_links(id, name)
	local link1 = 'https://chisel.weirdgloop.org/bestiary/'
	local link2 = 'https://chisel.weirdgloop.org/gazproj/mrnd'
	if infobox.isDefined(id) then
		local ids = mw.text.split(id, infobox.splitpoint)
		link1 = link1 .. table.concat(ids, '%20')
		id1 = tonumber(ids[1])
		if id1 then
			if #ids == 1 then
				link2 = string.format('%sid?%s#%s-%s', link2, id1, id1-15, id1+15)
			else
				for i,j in ipairs(ids) do
					if i == 1 then
						link2 = string.format('%sid?%s#%s', link2, j, j)
					else
						link2 = link2 .. '@' .. j
					end
				end
			end
		else
			link2 = string.format('%sid#%s', link2, ids[1])
		end
	else
		local _name = name:gsub(' ', '%%20')
		link1 = link1 .. _name
		link2 = string.format('%s#%s', link2, _name)
	end
	return string.format('[%s Bestiário]&nbsp;&bull;&nbsp;[%s MRND]', link1, link2)
end

-- red ERR span with title hover for explanation
function badarg(argname, argmessage)
	return '<span '..
			'title="O parâmetro «'..argname..'» '..argmessage..'" '..
			'style="color:red; font-weight:bold; cursor:help; border-bottom:1px dotted red;">'..
			'ERRO</span>'
end

-- SMW
-- 'name', 'version', 'id', 'members', 'release', 'removal', 'examine', 'level', 'style', 'lpraw', 'weakness', 'xpraw', 'slaylvl', 'slayxp', 'assigned_by', 'slayercat', 'restriction',
-- 'poisonous', 'abilities_sep', 'aggressive', 'immune_to_stun', 'immune_to_drain', 'immune_to_poison', 'immune_to_deflect',
-- 'attack', 'magic', 'ranged', 'defence', 'max_melee', 'max_magic', 'max_ranged', 'max_spec', 'acc_melee', 'acc_magic', 'acc_ranged', 'armour', 'aff_melee', 'aff_magic', 'aff_ranged', 'aff_weakness'
function SMWarg(name, version, id, members, release, removal, examine, level, style, lp, weakness, xp, slaylvl, slayxp, assignedby, slayercat, venenoso, abilities, restriction,
				aggressive, immune_to_stun, immune_to_drain, immune_to_poison, immune_to_deflect,
				attack, magic, ranged, defence, max_melee, max_magic, max_ranged, max_spec, acc_melee, acc_magic, acc_ranged, armour, aff_melee, aff_magic, aff_ranged, aff_weakness)
	local toJSON = {
		name = name,
		version = version,
		id = id,
		members = members,
		examine = examine,
		level = level,
		style = style:gsub('|', '¦'),
		lifepoints = lp,
		weakness = weakness:gsub('|', '¦'),
		experience = xp,
		slayer = slaylvl,
		slayer_experience = slayxp,
		assigned_by = assignedby:gsub('|', '¦'),
		slayer_category = slayercat
	}
	
	local yn = {
		aggressive = aggressive,
		immune_to_stun = immune_to_stun,
		immune_to_drain = immune_to_drain,
		immune_to_poison = immune_to_poison,
		immune_to_deflect = immune_to_deflect
	}
	local num = {
		attack = attack,
		magic = magic,
		ranged = ranged,
		defence = defence,
		max_melee = max_melee,
		max_magic = max_magic,
		max_ranged = max_ranged,
		max_spec = max_spec,
		acc_melee = acc_melee,
		acc_magic = acc_magic,
		acc_ranged = acc_ranged,
		armour = armour,
		aff_melee = aff_melee,
		aff_magic = aff_magic,
		aff_ranged = aff_ranged,
		aff_weakness = aff_weakness
	}
	
	for k,v in pairs(yn) do
		if v:find('[Yy]es check') then
			toJSON[k] = true
		elseif v:find('[Xx] mark') then
			toJSON[k] = false
		end
	end
	
	for k,v in pairs(num) do
		if type(v) == 'string' then
			if v:lower() == 'n/a' or v:lower() == 'varies' then
				toJSON[k] = v
			end
		elseif type(v) == 'number' then
			toJSON[k] = v
		end
	end
	
	if paramtest.is_empty(restriction) and tostring(restriction):find('action=edit') then
		toJSON.restriction = restriction_map.surface
	else
		toJSON.restriction = restriction
	end
	
	if venenoso then
		if venenoso:find('[Yy]es check') then
			toJSON.venenoso = true
			local m = venenoso:match(' (%d+)<')
			if m then
				toJSON.poison_damage = m
			end
		elseif venenoso:find('[Xx] mark') then
			toJSON.venenoso = false
		end
	end
	
	local rel, upd, rem, updr
	rel, upd = release:match('(.-) %(%[%[Notícia:(.-)|Notícia%]%]%)')
	if rel == nil then
		rel = release:match('(.-) %(Notícia desconhecida%)')
	end
	if rel then
		toJSON.release_date = rel:gsub('%[',''):gsub('%]','')
		if upd then
			toJSON.release_update_post = upd
		end
	end
	
	rem, updr = removal:match('(.-) %(%[%[Notícia:(.-)|Notícia%]%]%)')
	if rem == nil then
		rem = removal:match('(.-) %(Notícia desconhecida%)')
	end
	if rem then
		toJSON.removal_date = rem:gsub('%[',''):gsub('%]','')
		if updr then
			toJSON.removal_update_post = updr
		end
	end
			
	
	for k,v in pairs(toJSON) do
		if v == '' or (type(v) == 'string' and string.find(v,'action=edit')) then
			toJSON[k] = nil
		end
	end
	
	return mw.text.nowiki(mw.text.jsonEncode(toJSON))
	
end

function addcategories(args,catargs)
	local ret = { 'Bestiário' }
	local cat_map = {
		-- Added if the parameter has content
		defined = {
			aka = 'Páginas com AKA',
		},
		-- Added if the parameter has no content
		notdefined = {
			image = 'Precisa de imagem',
			members = 'Precisa de status de Membro',
			release = 'Precisa de data de lançamento',
			examine = 'Precisa de texto de examinar',
			level = 'Precisa de nível de combate',
			experience = 'Precisa de EXP por abate',
			primarystyle_smw = 'Estilo de ataque primário faltando',
			immune_to_stun = 'Informação sobre imunidade à atordoamento faltando',
			immune_to_poison = 'Informação sobre imunidade à envenenamento faltando',
			immune_to_deflect = 'Informação sobre imunidade à dano refletido faltando',
			immune_to_drain = 'Informação sobre imunidade à drenagem faltando',
			attack = 'Níveis de combate faltando',
			magic = 'Níveis de combate faltando',
			ranged = 'Níveis de combate faltando',
			defence = 'Níveis de combate faltando',
			id = 'Precisa de ID'
		},
		-- regex
		grep = {
			poisonous = { ['Sim%.svg'] = 'Monstros venenosos' },
			aggressive = { ['Sim%.svg'] = 'Monstros agressivos' },
			immune_to_stun = { ['é imune'] = 'Monstros imunes a atordoamento', ['não é imune'] = 'Monstros suscetíveis a atordoamento' },
			immune_to_poison = { ['é imune'] = 'Monstros imunes a veneno', ['não é imune'] = 'Monstros suscetíveis a veneno' },
			immune_to_deflect = { ['é imune'] = 'Monstros imunes a dano de recuo', ['não é imune'] = 'Monstros suscetíveis a dano de recuo' },
			immune_to_drain = { ['é imune'] = 'Monstros imunes a drenar estatísticas', ['não é imune'] = 'Monstros suscetíveis a drenar estatísticas' },
		},
	}
 
	-- Run and add mapped 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
 
	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

	-- searches
	for n, v in pairs(cat_map.grep) do
		for m, w in pairs(v) do
			if args[n] then
				if string.find(string.lower(tostring(args[n].d) or ''),m) then
					table.insert(ret,w)
				end
				if args[n].switches then
					for _, x in ipairs(args[n].switches) do
						if string.find(string.lower(tostring(x)),m) then
							table.insert(ret,w)
						end
					end
				end
			end
		end
	end

	if args.vanchor.switches then
		local verstable = {}
		for _, v in ipairs(args.vanchor.switches) do
			if verstable[v] then
				table.insert(ret,'Páginas com um nome de subobjeto duplicado')
				break
			else
				verstable[v] = true
			end
		end
	end
	
	local levels = { args['nível'].d }
	if args['nível'].switches then
		for _, v in ipairs(args['nível'].switches) do
			if v ~= infobox.nilParam() then
				table.insert(levels,v)
			end
		end
	end

	for _, v in ipairs(levels) do
		if v == 'N/A' then
			table.insert(ret,'Monstros sem nível de combate.')
		elseif tonumber(v) then
			table.insert(ret,string.format('Monstros com nível de combate %s',v))
		end
	end
		
	if args.membros.d:find('[Nn]ão') then
		table.insert(ret,'Bestiário de jogadores gratuitos')
	elseif args.membros.switches then
		for _, v in ipairs(args.membros.switches) do
			if v:find('[Nn]ão') then
				table.insert(ret,'Bestiário de jogadores gratuitos')
				break
			end
		end
	end	
	if args.membros.d:find('[Ss]im') then
		table.insert(ret,'Bestiário de membros')
	elseif args.membros.switches then
		for _, v in ipairs(args.membros.switches) do
			if v:find('[Ss]im') then
				table.insert(ret,'Bestiário de membros')
				break
			end
		end
	end
	if args.recursos.d:find('clickpic') then
		table.insert(ret,'Monstros que não usam recursos')
	elseif args.recursos.switches then
		for _, v in ipairs(args.recursos.switches) do
			if v:find('clickpic') then
				table.insert(ret,'Monstros que usam recursos')
				break
			end
		end
	end
	if args.weaknesstxt.d then
		wkcats(args.weaknesstxt.d,ret)
	end
	if args.weaknesstxt.switches then
		for _, v in ipairs(args.weaknesstxt.switches) do
			if v ~= _nil then
				wkcats(v,ret)
			end
		end
	end
	if args.susceptibility_smw.d then
		wkcats(args.susceptibility_smw.d,ret)
	end
	if args.susceptibility_smw.switches then
		for _, v in ipairs(args.susceptibility_smw.switches) do
			if v ~= _nil then
				wkcats(v,ret)
			end
		end
	end

	if args['designado por'].d then
		slaycats(args['designado por'].d,ret)
	end
	if args['designado por'].switches then
		for _, v in ipairs(args['designado por'].switches) do
			if v ~= _nil then
				slaycats(v,ret)
			end
		end
	end

	if not args.voz.d:find('%?action=edit') and args.voz.d:find('[Ss]im') then
		table.insert(ret,"NPC's dublados")
	elseif args.voz.switches then
		for _, v in ipairs(args.voz.switches) do
			if not v:find('%?action=edit') and v:find('[Ss]im') then
				table.insert(ret,"NPC's dublados")
				break
			end
		end
	end

	-- combine table and format category wikicode
	for i, v in ipairs(ret) do
		if (v ~= '') then
			ret[i] = string.format('[[Categoria:%s]]',v)
		end
	end

	return table.concat(ret,'')
end

return p
-- </nowiki>