Module:Infobox Monster

From Delanor Wiki
Jump to navigation Jump to search

-- Module for Template:Infobox Monster


local p = {}

local onmain = require('Module:Mainonly').on_main local commas = require('Module:Addcommas')._add local infobox = require('Module:Infobox') local signed = require('Module:Format eq stat').signed local tb = require('Module:Trailblazer Region')

local slayer_masters = { 'turael', 'spria', 'krystilia', 'mazchna', 'vannaka', 'chaeldar', 'konar', 'nieve', 'steve', 'duradel', 'kuradal' } local attributes = { demon = 'Demon', dragon = 'Draconic', fiery = 'Fiery', flying = 'Flying', golem = 'Golem', icy = 'Icy', kalphite = 'Kalphite', leafy = 'Leafy', penance = 'Penance', rat = 'Rat', shade = 'Shade', spectral = 'Spectral', undead = 'Undead', vampyre1 = 'Vampyre (tier 1)', vampyre2 = 'Vampyre (tier 2)', vampyre3 = 'Vampyre (tier 3)', xerician = 'Xerician', }

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

return p._main(args) end

function p._main(args) local ret = infobox.new(args)

local numeric_args = { 'att', 'str', 'def', 'range', 'mage', } for _, v in ipairs(numeric_args) do ret:defineParams{ { name = v, func = { name = numericarg, params = { v, v }, flag = { 'd', 'r' } } }, { name = v..'_smw', func = { name = tonumber_norefs, params = { v }, flag = { 'd' } } }, } end

local numeric_args_commas = { 'combat', 'hitpoints' } for _, v in ipairs(numeric_args_commas) do ret:defineParams{ { name = v, func = { name = numericarg_commas, params = { v, v }, flag = { 'd', 'r' } } }, { name = v..'_smw', func = { name = tonumber_norefs, params = { v }, flag = { 'p' } } }, } end

local signed_numeric_args = { 'amagic', 'arange', 'dstab', 'dslash', 'dcrush', 'dmagic', 'attbns', 'strbns', 'mbns', 'rngbns' }

for _, v in ipairs(signed_numeric_args) do ret:defineParams{ { name = v, func = { name = signednumericarg, params = { v, v }, flag = { 'd', 'r' } } }, { name = v..'_smw', func = { name = tonumber_norefs, params = { v }, flag = { 'd' } } }, } end

ret:defineParams{ { name = 'name', func = 'name'}, { name = 'image', func = 'image' }, { name = 'image_smw', func = { name = image_smw, params = { 'image' }, flag = 'p' } },

{ name = 'release', func = 'release' }, { name = 'removal', func = 'removal' }, { name = 'aka', func = 'has_content' },

{ name = 'size', func = sizeparam }, { name = 'size_smw', func = { name = 'has_content', params = {'size'}, flag = 'p'} }, { name = 'members', func = 'has_content' }, { name = 'examine', func = 'has_content' },

{ name = 'aggressive', func = 'has_content' }, { name = 'poisonous', func = 'has_content' }, { name = 'attributes', func = attributesarg }, { name = 'attributes_smw', func = { name = attributes_smw, params = { 'attributes' }, flag = 'p' } }, { name = 'attack style', func = 'has_content' }, { name = 'attack style_smw', func = { name = csv_to_multi, params = { 'attack style', true }, flag = { 'd', 'r' } } }, { name = 'attack speed', func = attackspeedarg }, { name = 'attack speed_smw', func = { name = attackspeed_smw, params = { 'attack speed' }, flag = 'p' } }, { name = 'elementalweaknesstype', func = elementalweaknesstypearg }, { name = 'elementalweaknesstype_smw', func = { name = 'has_content', params = { 'elementalweaknesstype' }, flag = 'p' } }, { name = 'elementalweaknesspercent', func = elementalweaknesspercentarg }, { name = 'elementalweaknesspercent_smw', func = { name = 'has_content', params = { 'elementalweaknesspercent' }, flag = 'p' } },

{ name = 'xpbonus', func = { name = signedpercentnumericarg, params = { 'xpbonus', 'xpbonus' }, flag = { 'd', 'r' } } }, { name = 'xpbonus_smw', func = { name = tonumber_norefs, params = { 'xpbonus' }, flag = { 'p' } } }, { name = 'flatarmour', func = 'has_content' }, { name = 'flatarmour_smw', func = { name = tonumber_norefs, params = { 'flatarmour' }, flag = { 'p' } } },

{ name = 'max hit', func = 'has_content' }, { name = 'max_hit_fmt', func = { name = csv_to_formatted, params = { 'max hit' }, flag = { 'd' } } }, { name = 'max_hit_smw', func = { name = csv_to_multi, params = { 'max hit', true }, flag = { 'd', 'r' } } },

{ name = 'respawn', func = respawnarg },

{ name = 'cat', func = 'has_content' }, { name = 'cat_smw', func = { name = csv_to_multi, params = { 'cat', true }, flag = { 'd', 'r' } } }, { name = 'slaylvl', func = { name = 'has_content', params = {'slaylvl', 'None' }, flag = { 'd', 'r' } } }, { name = 'slaylvl_smw', func = { name = tonumber_norefs, params = { 'slaylvl' }, flag = { 'd' } } }, { name = 'assignedby', func = 'has_content' }, { name = 'assignedby_pics', func = { name = assignedbyarg, params = { 'assignedby' }, flag = 'd' } }, { name = 'assignedby_smw', func = { name = csv_to_multi, params = { 'assignedby', true }, flag = { 'd', 'r' } } }, { name = 'slayxp', func = exp_arg }, { name = 'slayxp_smw', func = { name = tonumber_norefs, params = { 'slayxp' }, flag = { 'p' } } },

{ name = 'immunepoison', func = { name = immunearg, params = {'immunepoison', 'immunepoison'}, flag = { 'd', 'r', 'r' } } }, { name = 'immunepoison_smw', func = { name = immunearg_smw, params = {'immunepoison', 'immunepoison'}, flag = { 'p', 'r' } } }, { name = 'immunevenom', func = { name = immunearg, params = {'immunevenom', 'immunevenom'}, flag = { 'd', 'r', 'r' } } }, { name = 'immunevenom_smw', func = { name = immunearg_smw, params = {'immunevenom', 'immunevenom'}, flag = { 'p', 'r' } } }, { name = 'immunecannon', func = { name = immunearg, params = {'immunecannon', 'immunecannon'}, flag = { 'd', 'r', 'r' } } }, { name = 'immunecannon_smw', func = { name = immunearg_smw, params = {'immunecannon', 'immunecannon'}, flag = { 'p', 'r' } } }, { name = 'immunethrall', func = { name = immunearg, params = {'immunethrall', 'immunethrall'}, flag = { 'd', 'r', 'r' } } }, { name = 'immunethrall_smw', func = { name = immunearg_smw, params = {'immunethrall', 'immunethrall'}, flag = { 'p', 'r' } } }, { name = 'immuneburn', func = 'has_content' }, { name = 'freezeresistance', func = freezeresistancearg },

{ name = 'leagueRegion', func = tb.regionsForInfobox }, { name = 'leagueRegion_raw', func = { name = 'has_content', params = { 'leagueRegion' }, flag = 'p' } },

{ name = 'id', func = 'has_content' }, { name = 'id_smw', func = { name = csv_to_multi, params = { 'id', false }, flag = { 'p', 'r' } } }, { name = 'chisel_link', func = { name = 'chisel_link', params = { 'id', 'name', 'npc' }, flag = { 'p', 'p', 'r' } } }, { name = 'version', func = 'has_content' }, { name = 'usesinfobox', func = { name = tostring, params = { 'Monster' }, flag = 'r' } }, { name = 'usesskill', func = { name = usesskillarg, params = { 'slayxp_smw' }, flag = 'd' } }, { name = 'dropversion', func = 'has_content' }, { name = 'dpscalc', func = { name = usedpscalcarg, params = {'dpscalc', 'id'} } }, }

ret:defineParams { -- TODO: Merge these into signed_numeric_args once the pages have been backfilled { name = 'dlight', func = { name = rangedargs, params = { 'dlight', 'drange' }, flag = { 'p', 'p' } } }, { name = 'dstandard', func = { name = rangedargs, params = { 'dstandard', 'drange' }, flag = { 'p', 'p' } } }, { name = 'dheavy', func = { name = rangedargs, params = { 'dheavy', 'drange' }, flag = { 'p', 'p' } } }, { name = 'dlight_smw', func = { name = rangedargs_smw, params = { 'dlight', 'drange' }, flag = { 'p', 'p' } } }, { name = 'dstandard_smw', func = { name = rangedargs_smw, params = { 'dstandard', 'drange' }, flag = { 'p', 'p' } } }, { name = 'dheavy_smw', func = { name = rangedargs_smw, params = { 'dheavy', 'drange' }, flag = { 'p', 'p' } } }, -- TODO: Remove this entirely once all uses are updated to light/standard/heavy { name = 'drange_smw', func = { name = drange_smw, params = { 'dstandard', 'drange' }, flag = { 'p', 'p' } } }, }

ret:defineLinks({ hide = true })

local smw_mapping = { members = 'Is members only', release = 'Release date', id_smw = 'NPC ID', image_smw = 'Image', combat_smw = 'Combat level', examine = 'Examine', poisonous = 'Poisonous', attributes_smw = 'Monster attribute', hitpoints_smw = 'Hitpoints', max_hit_smw = 'Max hit', slaylvl_smw = 'Slayer level', slayxp_smw = 'Slayer experience', usesskill = 'Uses skill', assignedby_smw = 'Assigned by', att_smw = 'Attack level', str_smw = 'Strength level', def_smw = 'Defence level', range_smw = 'Ranged level', mage_smw = 'Magic level', amagic_smw = 'Magic attack bonus', arange_smw = 'Range attack bonus', dstab_smw = 'Stab defence bonus', dslash_smw = 'Slash defence bonus', dcrush_smw = 'Crush defence bonus', dmagic_smw = 'Magic defence bonus', drange_smw = 'Range defence bonus', -- TODO: Remove this after light/standard/heavy are used dlight_smw = 'Light range defence bonus', dstandard_smw = 'Standard range defence bonus', dheavy_smw = 'Heavy range defence bonus', attbns_smw = 'Attack bonus', strbns_smw = 'Strength bonus', rngbns_smw = 'Ranged Strength bonus', mbns_smw = 'Magic Damage bonus', version = 'Version anchor', name = 'Name', cat_smw = 'Slayer category', immunepoison_smw = 'Immune to poison', immunevenom_smw = 'Immune to venom', immunethrall_smw = "Immune to thralls", immunecannon_smw = "Immune to cannons", immuneburn = 'Immune to burn', ['attack style_smw'] = 'Attack style', ['attack speed_smw'] = 'Attack speed', xpbonus_smw = 'Experience bonus', flatarmour_smw = 'Flat armour', usesinfobox = 'Uses infobox', size_smw = 'Size', freezeresistance = 'Freeze resistance', elementalweaknesstype_smw = 'Elemental weakness', elementalweaknesspercent_smw = 'Elemental weakness percent', leagueRegion_raw = 'League Region', }

local smw_all_mapping = {} for param, property_name in pairs(smw_mapping) do smw_all_mapping[param] = 'All '..property_name end ret:useSMWSubobject(smw_mapping) ret:useSMWOne(smw_all_mapping)

ret:customButtonPlacement(true) ret:create() ret:cleanParams()

ret:addButtonsCaption()

ret:defineName('Infobox Monster') ret:addClass('infobox-monster')

ret:addRow{ { tag = 'argh', content = 'name', class='infobox-header', colspan = '24' } }

:pad(24) :addRow{ { tag = 'argd', content = 'image', class='infobox-image infobox-full-width-content', colspan = '24' } } :pad(24)

:addRow{ { tag = 'th', content = 'Released', colspan = '8' }, { tag = 'argd', content = 'release', colspan = '16' } }

if ret:paramDefined('removal', 'all') then ret:addRow{ { tag = 'th', content = 'Removal', colspan = '8' }, { tag = 'argd', content = 'removal', colspan = '16' } } end

if ret:paramDefined('aka', 'all') then ret:addRow{ { tag = 'th', content = 'Also called', colspan = '8' }, { tag = 'argd', content = 'aka', colspan = '16' } } end

ret:addRow{ { tag = 'th', content = 'Members', colspan = '8' }, { tag = 'argd', content = 'members', colspan = '16' } }

:addRow{ { tag = 'th', content = 'Combat level', colspan = '8' }, { tag = 'argd', content = 'combat', colspan = '16' } }

if ret:paramDefined('size', 'all') then ret:addRow{ { tag = 'th', content = 'Size', colspan = '8' }, { tag = 'argd', content = 'size', colspan = '16' } } end

ret:addRow{ { tag = 'th', content = 'Examine', colspan= '8' }, { tag = 'argd', content = 'examine', colspan = '16' } }

if ret:paramDefined('leagueRegion', 'all') then ret:addRow{ { tag = 'th', content = 'League region', colspan = '8' }, { tag = 'argd', content = 'leagueRegion', colspan = '16' }, meta = {addClass = 'leagues-global-flag'} } end ret:pad(24) :addRow{ { tag = 'th', content = 'Combat info', colspan = '24', class = 'infobox-subheader' } } :pad(24)

if ret:paramDefined('attributes', 'all') then ret:addRow{ { tag = 'th', content = 'Attribute', colspan = '8' }, { tag = 'argd', content = 'attributes', colspan = '16' } } end

if ret:paramDefined('xpbonus', 'all') then ret:addRow{ { tag = 'th', content = 'XP bonus', colspan = '8' }, { tag = 'argd', content = 'xpbonus', colspan = '16' } } end

if ret:paramDefined('flatarmour', 'all') then ret:addRow{ { tag = 'th', content = 'Flat armour', colspan = '8' }, { tag = 'argd', content = 'flatarmour', colspan = '16' } } end

ret:addRow{ { tag = 'th', content = 'Max hit', colspan = '8' }, { tag = 'argd', content = 'max_hit_fmt', colspan = '16' } }

:addRow{ { tag = 'th', content = 'Aggressive', colspan = '8' }, { tag = 'argd', content = 'aggressive', colspan = '16' } }

:addRow{ { tag = 'th', content = 'Poisonous', colspan = '8' }, { tag = 'argd', content = 'poisonous', colspan = '16' } }

:addRow{ { tag = 'th', content = 'Attack style', colspan = '8' }, { tag = 'argd', content = 'attack style', colspan = '16' } } :addRow{ { tag = 'th', content = 'Attack speed', colspan = '8' }, { tag = 'argd', content = 'attack speed', colspan = '16' } }

if ret:paramDefined('respawn', 'all') then ret:addRow{ { tag = 'th', content = 'Respawn time', colspan = '8' }, { tag = 'argd', content = 'respawn', colspan = '16' } } end

ret:pad(24)

-- If a monster is assigned or has a slayer level, include slayer info local slaylvl_defined = ret:paramGrep('slaylvl', function(x) return string.lower(x or 'none') ~= 'none' end) if ret:paramDefined('assignedby', 'all') or slaylvl_defined then ret:addRow{ { tag = 'th', content = 'File:Slayer icon.png Slayer info', colspan = '24', class = 'infobox-subheader' } } :pad(24) :addRow{ { tag = 'th', content = 'Slayer level', colspan = '8' }, { tag = 'argd', content = 'slaylvl', colspan = '16' } }

-- If a monster is assigned, include assignment info if ret:paramDefined('assignedby', 'all') then ret:addRow{ { tag = 'th', content = 'Slayer XP', colspan = '8' }, { tag = 'argd', content = 'slayxp', colspan = '16' } }

:addRow{ { tag = 'th', content = 'Category', colspan = '8' }, { tag = 'argd', content = 'cat', colspan = '16' } }

:addRow{ { tag = 'th', content = 'Assigned by', colspan = '8' }, { tag = 'argd', content = 'assignedby_pics', colspan = '16' } } else ret:addRow{ { tag = 'th', content = 'Assigned by', colspan = '8' }, { tag = 'td', content = 'Not assigned', colspan = '16' } } end

ret:pad(24) end

ret:addRow{ { tag = 'th', content = 'File:Combat icon.png Combat stats', colspan = '24', class = 'infobox-subheader' } } :pad(24)

:addRow{ { tag = 'th', content = 'File:Hitpoints icon.png', colspan = '4', class = 'infobox-nested' }, { tag = 'th', content = 'File:Attack icon.png', colspan = '4', class = 'infobox-nested' }, { tag = 'th', content = 'File:Strength icon.png', colspan = '4', class = 'infobox-nested' }, { tag = 'th', content = 'File:Defence icon.png', colspan = '4', class = 'infobox-nested' }, { tag = 'th', content = 'File:Magic icon.png', colspan = '4', class = 'infobox-nested' }, { tag = 'th', content = 'File:Ranged icon.png', colspan = '4', class = 'infobox-nested' }, }

:addRow{ { tag = 'argd', content = 'hitpoints', colspan = '4', class = 'infobox-nested' }, { tag = 'argd', content = 'att', colspan = '4', class = 'infobox-nested' }, { tag = 'argd', content = 'str', colspan = '4', class = 'infobox-nested' }, { tag = 'argd', content = 'def', colspan = '4', class = 'infobox-nested' }, { tag = 'argd', content = 'mage', colspan = '4', class = 'infobox-nested' }, { tag = 'argd', content = 'range', colspan = '4', class = 'infobox-nested' }, }

:pad(24) :addRow{ { tag = 'th', content = 'File:Attack icon.png Aggressive stats', colspan = '24', class = 'infobox-subheader' } } :pad(24)

:addRow{ { tag = 'th', content = 'Monster attack bonus', colspan = '4', class = 'infobox-nested' }, { tag = 'th', content = 'Monster strength bonus', colspan = '4', class = 'infobox-nested' }, { tag = 'th', content = 'File:Magic icon.png', colspan = '4', class = 'infobox-nested' }, { tag = 'th', content = 'Monster magic strength bonus', colspan = '4', class = 'infobox-nested' }, { tag = 'th', content = 'File:Ranged icon.png', colspan = '4', class = 'infobox-nested' }, { tag = 'th', content = 'Monster ranged strength bonus', colspan = '4', class = 'infobox-nested' }, }

:addRow{ { tag = 'argd', content = 'attbns', colspan = '4', class = 'infobox-nested' }, { tag = 'argd', content = 'strbns', colspan = '4', class = 'infobox-nested' }, { tag = 'argd', content = 'amagic', colspan = '4', class = 'infobox-nested' }, { tag = 'argd', content = 'mbns', colspan = '4', class = 'infobox-nested' }, { tag = 'argd', content = 'arange', colspan = '4', class = 'infobox-nested' }, { tag = 'argd', content = 'rngbns', colspan = '4', class = 'infobox-nested' }, }

:pad(24) :addRow{ { tag = 'th', content = 'File:Defence icon.png Melee defence', colspan = '24', class = 'infobox-subheader' } } :pad(24)

:addRow{ { tag = 'th', content = 'File:White dagger.png', colspan = '8', class = 'infobox-nested' }, { tag = 'th', content = 'File:White scimitar.png', colspan = '8', class = 'infobox-nested' }, { tag = 'th', content = 'File:White warhammer.png', colspan = '8', class = 'infobox-nested' }, } :addRow{ { tag = 'argd', content = 'dstab', colspan = '8', class = 'infobox-nested' }, { tag = 'argd', content = 'dslash', colspan = '8', class = 'infobox-nested' }, { tag = 'argd', content = 'dcrush', colspan = '8', class = 'infobox-nested' }, }


:pad(24) :addRow{ { tag = 'th', content = 'File:Magic defence icon.png Magic defence', colspan = '24', class = 'infobox-subheader' } } :pad(24)


:addRow{ { tag = 'th', content = 'File:Magic icon.png', colspan = '12', class = 'infobox-nested' }, { tag = 'argh', content = 'elementalweaknesstype', colspan = '12', class = 'infobox-nested' }, } :addRow{ { tag = 'argd', content = 'dmagic', colspan = '12', class = 'infobox-nested' }, { tag = 'argd', content = 'elementalweaknesspercent', colspan = '12', class = 'infobox-nested' } }

:pad(24) :addRow{ { tag = 'th', content = 'File:Ranged defence icon.png Ranged defence', colspan = '24', class = 'infobox-subheader' } } :pad(24)

:addRow{ { tag = 'th', content = 'Light', colspan = '8', class = 'infobox-nested' }, { tag = 'th', content = 'Standard', colspan = '8', class = 'infobox-nested' }, { tag = 'th', content = 'Heavy', colspan = '8', class = 'infobox-nested' }, } :addRow{ { tag = 'argd', content = 'dlight', colspan = '8', class = 'infobox-nested' }, { tag = 'argd', content = 'dstandard', colspan = '8', class = 'infobox-nested' }, { tag = 'argd', content = 'dheavy', colspan = '8', class = 'infobox-nested' }, }

:pad(24) :addRow{ { tag = 'th', content = 'Immunities', colspan = '24', class = 'infobox-subheader' } } :pad(24)

:addRow{ { tag = 'th', content = 'Poison', colspan = '8' }, { tag = 'argd', content = 'immunepoison', colspan = '16' } } :addRow{ { tag = 'th', content = 'Venom', colspan = '8' }, { tag = 'argd', content = 'immunevenom', colspan = '16' } } if ret:paramDefined('immunecannon', 'all') then ret:addRow{ { tag = 'th', content = 'Cannons', colspan = '8' }, { tag = 'argd', content = 'immunecannon', colspan = '16' } } end if ret:paramDefined('immunethrall', 'all') then ret:addRow{ { tag = 'th', content = 'Thralls', colspan = '8' }, { tag = 'argd', content = 'immunethrall', colspan = '16' } } end if ret:paramDefined('immuneburn', 'all') then ret:addRow{ { tag = 'th', content = 'Burn', colspan = '8' }, { tag = 'argd', content = 'immuneburn', colspan = '16' } } end if ret:paramDefined('freezeresistance', 'all') then ret:addRow{ { tag = 'th', content = 'Freeze', colspan = '8' }, { tag = 'argd', content = 'freezeresistance', colspan = '16' } } end ret:pad(24) if ret:paramDefined('dpscalc', 'all') then ret:addRow{ {tag = 'argd', content = 'dpscalc', class = 'dps-calc-button infobox-full-width-content', colspan = '24'} } end

ret:addRow{ { tag = 'th', content = 'Advanced data', class = 'infobox-subheader', colspan = '24' }, meta = {addClass = 'advanced-data'} } :pad(24, 'advanced-data') :addRow{ { tag = 'th', content = 'Monster ID', colspan = '8' }, { tag = 'argd', content = 'id', colspan = '16' }, meta = {addClass = 'advanced-data'} } :addRow{ { tag = 'th', content = 'Link', colspan = '8' }, { tag = 'argd', content = 'chisel_link', colspan = '16' }, meta = {addClass = 'advanced-data'} } :pad(24, 'advanced-data')

ret:addDropLevelVars('combat', 'combat_smw') ret:addVersionBasedVars('LeagueRegion', 'dropversion', 'leagueRegion_raw')

if onmain() then local a1 = ret:param('all') local a2 = ret:categoryData() ret:wikitext(addcategories(a1, a2)) end return ret:tostring() end

function numericarg(arg, arg_name) if not infobox.isDefined(arg) then return nil end return arg end

function numericarg_commas(arg, arg_name) if not infobox.isDefined(arg) then return nil end local n = tonumber(arg) if n == nil then return arg else return commas(tonumber(arg)) end end

-- If the arg is numeric, return the signed version (starts with + or -) function signednumericarg(arg, arg_name) local _arg = numericarg(arg, arg_name) if tonumber(_arg) ~= nil then return signed(_arg) end if arg ~= then return arg end return nil end

-- Sign the arg and append a percent sign function signedpercentnumericarg(arg, arg_name) local _arg = signednumericarg(arg, arg_name) if _arg ~= nil then return _arg..'%' end return nil end

-- Remove <ref></ref> from the string before converting tonumber() function tonumber_norefs(arg) local raw = string.gsub(arg, ".'\"`UNIQ[^`]*QINU`\"'.", ) return tonumber(raw) end

function attributesarg(arg) if not infobox.isDefined(arg) then return nil end

local arg = string.lower(arg) if arg == 'no' then return 'None' end

local result = {} for attribute_i in string.gmatch(arg, "[^,]+") do local trimmed = attribute_i:gsub("^%s*(.-)%s*$", "%1") if attributes[trimmed] then table.insert(result, attributes[trimmed]) end end

if #result > 0 then return table.concat(result, ', ') else return 'None' end end

-- Returns list of types in smw format function attributes_smw(arg) if not infobox.isDefined(arg) then return nil end

local arg = string.lower(arg) if arg == 'no' then return nil end

local result = {} for attribute_i in string.gmatch(arg, "[^,]+") do local trimmed = attribute_i:gsub("^%s*(.-)%s*$", "%1") if attributes[trimmed] then table.insert(result, trimmed) end end

if #result > 0 then return table.concat(result, '&&SPLITPOINT&&') else return nil end end

function respawnarg(arg) if not infobox.isDefined(arg) then return nil end

-- if arg is a valid number, display ticks and seconds if tonumber(arg) then local plural = tonumber(arg) ~= 1 and 's' or return arg .. ' tick' .. plural .. ' (' .. arg * 0.6 .. ' seconds)' end

-- if arg isn't a number, return it unmodified return arg end

-- Generate pics for defined slayer masters, or return nil if undefined function assignedbyarg(arg) if not infobox.isDefined(arg) then return nil end

local arg = string.lower(arg) if arg == 'no' then return 'Not assigned' end

local result = {} for i, slayer_master in ipairs(slayer_masters) do if string.match(arg, slayer_master) then table.insert(result, string.format('File:%s chathead.png', slayer_master, slayer_master)) end end

if #result > 0 then return table.concat(result, ' ') else return nil end end

function exp_arg(arg) if not infobox.isDefined(arg) then return nil end

if not tonumber(arg) then return arg end return string.format('%s xp', arg, commas(arg)) end

function immunearg_smw(arg, arg_name) if not infobox.isDefined(arg) then return nil end

local arg = string.lower(arg) if arg == 'no' or arg == 'not immune' then return 'Not immune' elseif arg == 'yes' or arg == 'immune' then return 'Immune' elseif arg:sub(1, #'poison') == 'poison' then return 'Poisons' else return badarg(arg_name, "should be 'yes' or 'no'.") end end

function immunearg(arg, arg_name) if not infobox.isDefined(arg) then return nil end

local arg = string.lower(arg) if arg == 'no' or arg == 'not immune' then return 'Not immune' elseif arg == 'yes' or arg == 'immune' then return 'Immune' elseif arg:sub(1, #'poison') == 'poison' then return ''.. 'Converts to poison' else return badarg(arg_name, "should be 'yes' or 'no'.") end end

function freezeresistancearg(arg) if not infobox.isDefined(arg) then return nil end

return arg..'% resistance' end

function image_smw(arg) local _img = string.match(arg, "File:.-%.png") return _img end

function attackspeedarg(arg) if not infobox.isDefined(arg) then return nil end

local lowarg = string.lower(arg) local numarg = tonumber(arg)

if lowarg == 'no' or lowarg == 'n/a' then return 'Does not attack' elseif lowarg == 'varies' or lowarg == 'random' then return 'Variable' end

if numarg ~= nil then return string.format('%s %s (%.1f seconds)', numarg, (numarg > 1) and 'ticks' or 'tick', numarg * 0.6) end end

function attackspeed_smw(arg) if not infobox.isDefined(arg) then return nil end

local arg = string.lower(arg) if arg == 'no' then return -1 end return arg end

function elementalweaknesstypearg(arg) if not infobox.isDefined(arg) then return 'No elemental weakness' end

local lowarg = string.lower(arg)

if string.find(lowarg, 'air') then return 'Air elemental weakness' elseif string.find(lowarg, 'earth') then return 'Earth elemental weakness' elseif string.find(lowarg, 'fire') then return 'Fire elemental weakness' elseif string.find(lowarg, 'water') then return 'Water elemental weakness' end

return 'No elemental weakness' end

function elementalweaknesspercentarg(arg) if not infobox.isDefined(arg) or string.lower(arg) == 'no' then return 'No elemental weakness' end

return arg .. '% weakness' end

function csv_to_formatted(raw) if not infobox.isDefined(raw) then return nil end

local r = string.gsub(raw, '%s*,%s*', '
')

return r end

function csv_to_multi(raw, striplinks) assert(type(striplinks) == 'boolean')

local r = raw if infobox.isDefined(raw) then if striplinks then r = string.gsub(raw,'[%[%]]', ) end r = string.gsub(r, '%s*,%s*', '&&SPLITPOINT&&') return r end return nil end

-- red ERR span with title hover for explanation function badarg(argname, argmessage) return ''.. 'ERR' end

function sizeparam(arg) if not infobox.isDefined(arg) then return nil end

return string.format('%sx%s', arg, arg) end

function usesskillarg(slayxp) local ret = {} if infobox.isDefined(slayxp) then table.insert(ret, "Slayer") end -- If needed, insert additional skills to the ret table here. return csv_to_multi(table.concat(ret, ","), false) end

function usedpscalcarg(arg, id) -- If dpscalc is no or we don't have an id to grab, don't show the button if not infobox.isDefined(id) then return nil end if infobox.isDefined(arg) and string.lower(arg) == 'no' then return nil end local ids = {} -- If multiple ids exist, just default to the first one for id_i in string.gmatch(id, "[^,]+") do table.insert(ids, id_i) end local firstid = ids[1]

return '

'

end

-- TODO: Remove this fallback behavior once dlight/dstandard/dheavy are backfilled function rangedargs(arg, drangearg) if infobox.isDefined(arg) then return signednumericarg(arg) end

return signednumericarg(drangearg) end

-- TODO: Remove this fallback behavior once dlight/dstandard/dheavy are backfilled function rangedargs_smw(arg, drangearg) if infobox.isDefined(arg) then return tonumber_norefs(arg) end

return tonumber_norefs(drangearg) end

-- TODO: Remove this fallback behavior once nothing uses drange function drange_smw(dstandard, drange) if infobox.isDefined(dstandard) then return tonumber_norefs(dstandard) end

return tonumber_norefs(drange) end

function addcategories(args, catargs) local ret = { 'Monsters' }

	-- Add the associated category if the parameter has content

local defined_args = { aka = 'Pages with AKA', aspeed = 'Pages with aspeed', } for n, v in pairs(defined_args) do if catargs[n] and catargs[n].one_defined then table.insert(ret, v) end end

	-- Add the associated category if the parameter doesn't have content
	local notdefined_args = {
		image = 'Needs image',
		members = 'Needs members status',
		release = 'Needs release date',
		examine = 'Needs examine added',
 		update = 'Needs update added',
		combat = 'Needs combat level',
		id = 'Needs ID'
	}

for n, v in pairs(notdefined_args) do if catargs[n] and catargs[n].all_defined == false then table.insert(ret, v) end end

-- Adds Category:Needs Monster Examine if any of these are not defined local monster_examine_args = { 'att', 'str', 'def', 'range', 'mage', 'amagic', 'arange', 'dstab', 'dslash', 'dcrush', 'dmagic', 'dlight', 'dstandard', 'dheavy', 'attbns', 'strbns', 'rngbns', 'mbns', 'immunepoison', 'immunevenom', 'attack speed' } for _, arg in ipairs(monster_examine_args) do if not catargs[arg] or not catargs[arg].all_defined then table.insert(ret, 'Needs Monster Examine') break end end

-- Adds Category:Needs slayer information if slayer info is required -- but not all args are defined local slayer_args = { 'slaylvl', 'slayxp', 'cat' } if catargs['assignedby'].one_defined then table.insert(ret, 'Slayer monsters') for i, arg in ipairs(slayer_args) do if not catargs[arg] or not catargs[arg].all_defined then table.insert(ret, 'Needs slayer information') break end end end

local cat_map = { -- Parameters that have text -- map a category to a value matches = { members = { yes = 'Members\' monsters', no = 'Free-to-play monsters' }, } }

-- searches for n, v in pairs(cat_map.matches) do for m, w in pairs(v) do if args[n] then if 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.lower(tostring(x)) == m then table.insert(ret, w) end end end end end end

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

return table.concat(ret, ) end

return p