Module:Sandbox/User:Chee/Module:Infobox Defence Revisions: Difference between revisions
Jump to navigation
Jump to search
mNo edit summary |
(No difference)
|
Revision as of 00:20, 13 October 2020
Documentation for this module may be created at Module:Sandbox/User:Chee/Module:Infobox Defence Revisions/doc
-- <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('Module:Mainonly').on_main
local paramtest = require('Module:Paramtest')
local yesno = require('Module:Yesno')
local commas = require('Module:Addcommas')._add
local infobox = require('Module:Infobox')
local attack_speed_bar = require('Module:Attack speed bar').monster
--[[
-- Mapping
--]]
local attack_styles = {
melee = { image = 'Attack-icon', link = 'Melee' },
ranged = { image = 'Ranged-icon', link = 'Ranged' },
magic = { image = 'Magic-icon', link = 'Magic' },
dragonfire = { image = 'Dragonfire icon', link = 'Dragonfire' },
na = { image = 'Zero weakness icon', link = '' },
typeless = { image = 'Zero weakness icon', link = '' }
}
local styles_map = {
melee = 'melee',
magic = 'magic',
mage = 'magic',
range = 'ranged',
ranged = 'ranged',
ranging = 'ranged',
dragonfire = 'dragonfire',
['dragon fire'] = 'dragonfire',
dragonbreath = 'dragonfire',
['dragon breath'] = 'dragonfire',
['n/a'] = 'na',
na = 'na',
none = 'na'
}
local primary_styles = {
melee = { 'inquisitor', '[[File:Inquisitor staff.png|25px|link=Inquisitor staff]]'},
ranged = { 'terrasaur', '[[File:Terrasaur maul.png|25px|link=Terrasaur maul]]'},
magic = { 'hexhunter', '[[File:Hexhunter bow.png|25px|link=Hexhunter bow]]'},
}
local slay_masters = {
turael = { text = '[[Turael]] or [[Spria]]', chathead = 'turael chathead', category = 'Monsters assigned by Turael or Spria' },
mazchna = { text = '[[Mazchna]] or [[Achtryn]]', chathead = 'mazchna chathead', category = 'Monsters assigned by Mazchna or Achtryn' },
chaeldar = { text = '[[Chaeldar]]', chathead = 'chaeldar chathead', category = 'Monsters assigned by Chaeldar' },
sumona = { text = '[[Sumona]]', chathead = 'sumona chathead', category = 'Monsters assigned by Sumona' },
vannaka = { text = '[[Vannaka]]', chathead = 'vannaka chathead', category = 'Monsters assigned by Vannaka' },
duradel = { text = '[[Duradel]] or [[Lapalok]]', chathead = 'duradel chathead', category = 'Monsters assigned by Duradel or Lapalok' },
kuradal = { text = '[[Kuradal]]', chathead = 'kuradal chathead', category = 'Monsters assigned by Kuradal' },
morvran = { text = '[[Morvran]]', chathead = 'morvran chathead', category = 'Monsters assigned by Morvran' },
mandrith = { text = '[[Mandrith]]', chathead = 'Mandrith chathead', category = 'Monsters assigned by Mandrith' },
laniakea = { text = '[[Laniakea]]', chathead = 'Laniakea chathead', category = 'Monsters assigned by 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',
no = 'none',
none = 'none',
['n/a'] = 'none'
}
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',
['0'] = 0
}
-- load weaknesses instead of remapping
local weaknesses = mw.loadData('Module:Weakness clickpic/data')
-- location restriction
local restriction_map = {
surface = 'surface',
dungeoneering = 'dungeoneering',
dg = 'dungeoneering',
daemonheim = 'dungeoneering',
quest = 'quest',
minigame = 'minigame',
activity = 'minigame',
gone = 'removed',
removed = 'removed',
limited = 'limited'
}
-- Main function called with invokes
function p.main(frame)
local args = frame:getParent().args
local ret = infobox.new(args)
local yn_args = {
'aggressive'
}
local immune_args = {
'immune_to_poison', 'immune_to_deflect',
'immune_to_stun', 'immune_to_drain'
}
local num_args = {
'slaylvl', 'slayxp',
'attack', 'strength', 'defence', 'ranged', 'magic',
'max_melee', 'max_ranged', 'max_magic', 'max_spec',
'acc_melee', 'acc_ranged', 'acc_magic', 'armour',
'aff_melee', 'aff_ranged', 'aff_magic' } --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 = { 'version' }, flag = 'p' } },
{ name = 'poisonous', func = { name = poisonarg, params = { 'poisonous' }, flag = 'p' } },
{ name = 'poisonous_smw', func = { name = boolsmwargs, params = { 'poisonous' }, flag = 'd' } },
{ name = 'level', func = combatarg },
{ name = 'level_smw', func = { name = numargraw2, params = { 'level' }, flag = 'p' } },
{ name = 'style', func = stylearg },
{ name = 'styleimg', func = { name = styleimgarg, params = { 'style' }, flag = 'p', dupes = true } },
{ name = 'styletxt', func = { name = styletxtarg, params = { 'style' }, flag = 'p', dupes = true } },
{ name = 'primarystyle_smw', func = { name = primarystylesmwarg, params = { 'primarystyle' }, flag = 'p', dupes = true } },
{ name = 'lifepoints', func = numargcommas },
{ name = 'lpraw', func = { name = numargraw, params = { 'lifepoints' }, flag = 'p' } },
{ name = 'experience', func = numargcommas },
{ name = 'xpraw', func = { name = numargraw, params = { 'experience' }, flag = 'p' } },
{ name = 'hpxp', func = { name = hpxparg, params = { 'experience' } } },
{ name = 'wepxp2h', func = numargcommas },
{ name = 'wepxpmhandarmour', func = numargcommas },
{ name = 'wepxpoh', func = numargcommas },
{ name = 'wepxp', func = { name = wepxparg, params = { 'experience', 'wepxp2h', 'wepxpmhandarmour', 'wepxpoh' } } },
{ name = 'weakness', func = weaknessarg },
{ name = 'generalweakness', func = { name = generalweaknessarg, params = { 'aff_melee', 'aff_ranged', 'aff_magic' } } },
{ name = 'weaknessimg', func = { name = weaknessimgarg, params = { 'weakness' }, flag = 'p', dupes = true } },
{ name = 'weaknesstxt', func = { name = weaknesstxtarg, params = { 'weakness' }, flag = 'p', dupes = true } },
{ name = 'explicit_weakness', func = { name = explicitwkarg, params = { 'weakness' }, flag = 'p' } },
{ name = 'aff_weakness', func = { name = aff_weakness_arg , params = { 'aff_weakness', 'aff_weakness', 'weakness' }, flag = { 'p', 'r', 'p' } } },
{ name = 'aff_weakness_smw', func = { name = aff_weakness_smw_arg , params = { 'aff_weakness', }, flag = { 'd' } } },
{ name = 'susceptibility', func = { name = susceptarg, params = { 'susceptibility', 'weakness', 'primarystyle' }, flag = 'p' } },
{ name = 'susceptibility_smw', func = { name = susceptarg_smw, params = { 'susceptibility', 'weakness', 'primarystyle' }, flag = 'p' } },
{ name = 'abilities', func = abilarg },
{ name = 'abilities_sep', func = abilseparg },
{ name = 'assigned_by', func = slayerarg },
{ name = 'assigned_by_img', func = { name = slayerimgarg, params = { 'assigned_by' }, flag = 'p', dupes = true } },
{ name = 'not_assigned', func = { name = notassarg, params = { 'assigned_by' }, flag = 'p' } },
{ name = 'release', func = 'release' },
{ name = 'removal', func = 'removal' },
{ name = 'members', func = 'has_content' },
{ name = 'examine', func = 'has_content' },
{ name = 'voice', func = 'has_content' },
{ name = 'speed', func = speedarg },
{ name = 'name', func = 'name' },
{ name = 'aka', func = 'has_content' },
{ name = 'image', func = 'image' },
{ name = 'icon', func = 'image' },
{ name = 'icon_cell', func = { name = icon, params = { 'name', 'icon' }, flag='d' } },
{ name = 'chathead', func = 'image' },
{ name = 'slayercat', func = slayercatarg },
{ name = 'slayercat_smw', func = { name = slayercatsmwarg, params = { 'slayercat' }, flag='d' } },
{ name = 'restriction', func = restrictionarg },
{ name = 'restrictionsurface', func = { name = restrsurfarg , params = { 'restriction', 'restriction' }, flag = { 'd', 'p' } } },
{ name = 'thievelvl', func = { name = numberargs, params = { 'thievelvl', 'thievelvl' }, flag = { 'p', 'r' } } },
{ name = 'thievelvl_smw', func = { name = numargraw2, params = { 'thievelvl' }, 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', 'name' }, flag = 'd' } },
{ name = 'rscid', func = 'numbers' },
{ name = 'SMWarg', func = { name = SMWarg, params = { 'name', 'version', 'id', 'members', 'release', 'removal', 'examine', 'level', 'style', 'lpraw', 'weakness', 'xpraw', 'slaylvl', 'slayxp', 'assigned_by', 'slayercat',
'poisonous', 'abilities_sep', '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' }, flag = 'd', dupes = true } }
}
ret:useSMW({
level_smw = 'Combat level',
xpraw = 'Combat experience',
members = 'Is members only',
release = 'Release date',
update = 'Release update',
removal = 'Removal date',
removalupdate = 'Removal update'
})
ret:useSMWOne({
id_smw = 'All NPC ID'
})
ret:useSMWSubobject({
id_smw = 'NPC ID',
name = 'Monster name',
vanchor = 'Version anchor',
level_smw = 'Combat level',
xpraw = 'Combat experience',
thievelvl_smw = 'Thieving level',
members = 'Is members only',
release = 'Release date',
update = 'Release update',
removal = 'Removal date',
removalupdate = 'Removal update',
styleimg = 'NPC attack style',
styletxt = 'NPC attack style text',
primarystyle_smw = 'NPC primary attack style',
lpraw = 'NPC life points',
weaknessimg = 'Weakness',
weaknesstxt = 'Weakness text',
generalweakness = 'Weakness by class',
susceptibility_smw = 'Susceptible to',
slayercat_smw = 'Slayer category',
slaylvl_smw = 'Slayer level',
slayxp_smw = 'Slayer experience',
assigned_by_img = 'Assigned by',
restriction = 'Location restriction',
attack_smw = 'NPC Attack level',
magic_smw = 'NPC Magic level',
ranged_smw = 'NPC Ranged level',
defence_smw = 'NPC Defence level',
max_melee_smw = 'NPC melee max hit',
max_magic_smw = 'NPC magic max hit',
max_ranged_smw = 'NPC ranged max hit',
max_spec_smw = 'NPC special max hit',
acc_melee_smw = 'NPC melee accuracy',
acc_magic_smw = 'NPC magic accuracy',
acc_ranged_smw = 'NPC ranged accuracy',
armour_smw = 'NPC armour',
aff_melee_smw = 'NPC melee affinity',
aff_magic_smw = 'NPC magic affinity',
aff_ranged_smw = 'NPC ranged affinity',
aff_weakness_smw = 'NPC weakness affinity',
aggressive_smw = 'Is NPC aggressive',
poisonous_smw = 'Is NPC poisonous',
immune_to_poison_smw = 'NPC susceptible to poison',
immune_to_deflect_smw = 'NPC susceptible to deflect',
immune_to_stun_smw = 'NPC susceptible to stun',
immune_to_drain_smw = 'NPC susceptible to drain',
SMWarg = 'Monster JSON',
})
ret:defineLinks({
links = {
{ 'Template:%s/FAQ', 'FAQ' },
{ 'Template:Infobox Monster new/doc', 'doc' }
},
colspan = 12
})
ret:customButtonPlacement(true)
ret:create()
ret:cleanParams()
ret:addClass('infobox-monster')
ret:defineName('Infobox Monster')
-- DEFENSIVE STATS
ret:addRow{ { tag = 'th', content = 'Defensive', class = 'defensive-header', colspan = '12' } }
-- PARAMETER: armour | defence | weakness
:addRow{ { tag = 'th', content = 'Armour', class = 'defensive-subheader', css = { ['padding-left'] = '0', ['padding-right'] = '0' }, colspan = '2' },
{ tag = 'th', content = '[[File:Defence-icon.png|link=]]', class = 'defensive-subheader', title = 'Defence level', colspan = '2' },
{ tag = 'th', content = '[[Weakness]]', class = 'defensive-subheader', colspan = '3' },
{ tag = 'th', content = '[[Susceptibility|Susceptible]]', class = 'defensive-subheader', colspan = '5' } }
:addRow{ { tag = 'argd', content = 'armour', colspan = '2' },
{ tag = 'argd', content = 'defence', title = levels_disc, colspan = '2' },
{ tag = 'argd', content = 'weakness', colspan = '3' },
{ tag = 'argd', content = 'susceptibility', colspan = '5', class = "infobox-monster-susceptibility-cell" } }
-- PARAMETER: explicit_weakness
-- PARAMETER: aff_weakness | aff_melee | aff_ranged | aff_magic
:addRow{ { tag = 'th', content = '[[Affinity|Affinities]]', class = 'defensive-subheader', colspan = '12' } }
:addRow{ { tag = 'argd', content = 'explicit_weakness', title = 'Affinity value of the monster\'s explicit weakness', colspan = '3' },
{ tag = 'td', content = '[[File:Attack-icon.png|20px|link=]]', title = 'Affinity value of the monster against melee attacks', colspan = '3' },
{ tag = 'td', content = '[[File:Ranged-icon.png|20px|link=]]', title = 'Affinity value of the monster against ranged attacks', colspan = '3' },
{ tag = 'td', content = '[[File:Magic-icon.png|20px|link=]]', title = 'Affinity value of the monster against magic attacks', colspan = '3' } }
:addRow{ { tag = 'argd', content = 'aff_weakness', colspan = '3' },
{ tag = 'argd', content = 'aff_melee', colspan = '3' },
{ tag = 'argd', content = 'aff_ranged', colspan = '3' },
{ tag = 'argd', content = 'aff_magic', colspan = '3' } }
-- PARAMETER: immune_to_poison | immune_to_deflect | immune_to_stun | immune_to_drain
:addRow{ { tag = 'th', content = 'Immunities', class = 'defensive-subheader', colspan = '12' } }
:addRow{ { tag = 'td', content = '[[File:Poison immunity icon.png|27x27px|frameless|link=]]', title = 'Immune to poison?', colspan = '3' },
{ tag = 'td', content = '[[File:Deflect immunity icon.png|27x27px|frameless|link=]]', title = 'Immune to deflect?', colspan = '3' },
{ tag = 'td', content = '[[File:Stun immunity icon.png|27x27px|frameless|link=]]', title = 'Immune to stun?', colspan = '3' },
{ tag = 'td', content = '[[File:Drain immunity icon.png|27x27px|frameless|link=]]', title = "Immune to stat drain?", colspan = '3' } }
:addRow{ meta = { addClass = 'infobox-monster-immunites-row' },
{ tag = 'argd', content = 'immune_to_poison', colspan = '3' },
{ tag = 'argd', content = 'immune_to_deflect', colspan = '3' },
{ tag = 'argd', content = 'immune_to_stun', colspan = '3' },
{ tag = 'argd', content = 'immune_to_drain', colspan = '3' } }
ret:finish()
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(arg_v:gsub(',',''),10)
if not arg_i then
arg_i = badarg(v,'should be a single numerical value.')
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(',',''),10)
if not arg_i then
arg_i = badarg('level','should be a single numerical value.')
end
end
return arg_i
end
-- For numbers (adds commas)
function numargcommas(arg)
local ret = numberargs(arg)
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 = arg:gsub(',', '')
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 = arg:gsub(',', '')
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 '',',','')
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 '',',','')
local xp2h = string.gsub(wepxp2h or '',',','')
local xpmh = string.gsub(wepxpmhandarmour or '',',','')
local xpoh = string.gsub(wepxpoh or '',',','')
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
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="This monster is%s %s.">%s</span>'
local f1,f3
local f2 = string.gsub(argr,'_',' ')
if arg_v then
f1 = ''
f3 = '[[File:Yes check.svg|20px|alt=Yes|link=]]'
else
f1 = ' not'
f3 = '[[File:X mark.svg|20px|alt=No|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="This monster is%s %s.">%s</span>'
local f1,f3,f4
local f2 = string.gsub(argr,'_',' ')
local f5 = string.gsub(argr,'immune_to_','')
if arg_v then
f1 = ''
f3 = 'Immune'
f4 = 'immune'
else
f1 = ' not'
f3 = 'Not immune'
f4 = 'susceptible'
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('is not immune') then
return 'true'
elseif arg:find('is immune') then
return 'false'
end
end
return nil
end
-- Poison
function poisonarg(arg)
arg = string.gsub(arg or '',',','')
arg = string.lower(arg)
if arg == 'yes' then
arg = '<span title="This monster is poisonous but has no base value defined. Change the |poisonous parameter to a number.">[[File:Yes check.svg|20px|alt=Yes|link=]] ???</span>'
elseif tonumber(arg) then
arg = '<span title="This monster is poisonous. The number shown is the base value at which poison damage starts.">[[File:Yes check.svg|20px|alt=Yes|link=]] '..tonumber(arg)..'</span>'
else
arg = '<span title="This monster is not poisonous.">[[File:X mark.svg|20px|alt=No|link=]]</span>'
end
return arg
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('[[File:%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('File:%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 == 'melee' 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('[[File:%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('File:%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('[[File:%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 == 'Nothing' 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 'none'
end
local ret = {}
if aff_melee == max then
table.insert(ret, 'melee')
end
if aff_ranged == max then
table.insert(ret, 'ranged')
end
if aff_magic == max then
table.insert(ret, 'magic')
end
if #ret == 1 then
return ret[1]
end
return 'none'
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 == 'inquisitor' then
table.insert(tbl, 'Susceptible to inquisitor staff')
elseif arg == 'terrasaur' then
table.insert(tbl, 'Susceptible to terrasaur maul')
elseif arg == 'hexhunter' then
table.insert(tbl, 'Susceptible to hexhunter bow')
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('darklight') or wk:find('silverlight') 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('[[File:%s|25px|frameless|link=%s]]', u.image, u.link))
end
end
if #suscepts == 0 then
return "None"
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/a' or sl == 'no' or sl == 'none' 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/a' or cat == 'no' or cat == 'none' 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 = 'Not assigned'
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('[[File:%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('File:%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] == 'none' 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 = 'None'
elseif arg:find('clickpic') then
arg = mw.getCurrentFrame():preprocess(arg)
else
arg = 'None'
end
return arg
end
function abilseparg(arg)
arg = paramtest.default_to(arg,false)
if not arg then
arg = ''
elseif arg:find('clickpic') then
arg = arg:gsub('{{[aA]bility clickpic|',''):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('speed',' is not a valid attack rate')
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 bestiary] • [%s MRND]', link1, link2)
end
-- red ERR span with title hover for explanation
function badarg(argname, argmessage)
return '<span '..
'title="The parameter «'..argname..'» '..argmessage..'" '..
'style="color:red; font-weight:bold; cursor:help; border-bottom:1px dotted red;">'..
'ERR</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, poisonous, 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 poisonous then
if poisonous:find('[Yy]es check') then
toJSON.poisonous = true
local m = poisonous:match(' (%d+)<')
if m then
toJSON.poison_damage = m
end
elseif poisonous:find('[Xx] mark') then
toJSON.poisonous = false
end
end
local rel, upd, rem, updr
rel, upd = release:match('(.-) %(%[%[Update:(.-)|Update%]%]%)')
if rel == nil then
rel = release:match('(.-) %(Update unknown%)')
end
if rel then
toJSON.release_date = rel:gsub('%[',''):gsub('%]','')
if upd then
toJSON.release_update_post = upd
end
end
rem, updr = removal:match('(.-) %(%[%[Update:(.-)|Update%]%]%)')
if rem == nil then
rem = removal:match('(.-) %(Update unknown%)')
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 = { 'Bestiary' }
local cat_map = {
-- Added if the parameter has content
defined = {
aka = 'Pages with AKA',
},
-- Added if the parameter has no content
notdefined = {
image = 'Needs image',
members = 'Needs members status',
release = 'Needs release date',
examine = 'Needs examine added',
level = 'Needs combat level',
experience = 'Needs XP per kill',
primarystyle_smw = 'Missing primary attack style',
immune_to_stun = 'Missing stun immunity information',
immune_to_poison = 'Missing poison immunity information',
immune_to_deflect = 'Missing deflect immunity information',
immune_to_drain = 'Missing drain immunity information',
attack = 'Missing combat skill levels',
magic = 'Missing combat skill levels',
ranged = 'Missing combat skill levels',
defence = 'Missing combat skill levels',
id = 'Needs ID'
},
-- regex
grep = {
poisonous = { ['yes check%.svg'] = 'Poisonous monsters' },
aggressive = { ['yes check%.svg'] = 'Aggressive monsters' },
immune_to_stun = { ['is immune'] = 'Stun-immune monsters', ['is not immune'] = 'Stun-susceptible monsters' },
immune_to_poison = { ['is immune'] = 'Poison-immune monsters', ['is not immune'] = 'Poison-susceptible monsters' },
immune_to_deflect = { ['is immune'] = 'Deflect-immune monsters', ['is not immune'] = 'Deflect-susceptible monsters' },
immune_to_drain = { ['is immune'] = 'Drain-immune monsters', ['is not immune'] = 'Drain-susceptible monsters' },
},
}
-- 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,'Pages with a duplicate subobject name')
break
else
verstable[v] = true
end
end
end
local levels = { args.level.d }
if args.level.switches then
for _, v in ipairs(args.level.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,'Monsters with no combat level')
elseif tonumber(v) then
table.insert(ret,string.format('Combat level %s monsters',v))
end
end
if args.members.d:find('[Nn]o') then
table.insert(ret,'F2P bestiary')
elseif args.members.switches then
for _, v in ipairs(args.members.switches) do
if v:find('[Nn]o') then
table.insert(ret,'F2P bestiary')
break
end
end
end
if args.members.d:find('[Yy]es') then
table.insert(ret,'P2P bestiary')
elseif args.members.switches then
for _, v in ipairs(args.members.switches) do
if v:find('[Yy]es') then
table.insert(ret,'P2P bestiary')
break
end
end
end
if args.abilities.d:find('clickpic') then
table.insert(ret,'Monsters that use abilities')
elseif args.abilities.switches then
for _, v in ipairs(args.abilities.switches) do
if v:find('clickpic') then
table.insert(ret,'Monsters that use abilities')
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.assigned_by.d then
slaycats(args.assigned_by.d,ret)
end
if args.assigned_by.switches then
for _, v in ipairs(args.assigned_by.switches) do
if v ~= _nil then
slaycats(v,ret)
end
end
end
if not args.voice.d:find('%?action=edit') and args.voice.d:find('[Yy]es') then
table.insert(ret,'Voice acted NPCs')
elseif args.voice.switches then
for _, v in ipairs(args.voice.switches) do
if not v:find('%?action=edit') and v:find('[Yy]es') then
table.insert(ret,'Voice acted NPCs')
break
end
end
end
-- combine table and format category wikicode
for i, v in ipairs(ret) do
if (v ~= '') then
ret[i] = string.format('[[Category:%s]]',v)
end
end
return table.concat(ret,'')
end
return p
-- </nowiki>