Module:Sandbox/User:Nephr/Infobox custom
Documentation for this module may be created at Module:Sandbox/User:Nephr/Infobox custom/doc
-- <nowiki>
--[=[
-- Implements [[Template:Infobox Bonuses]]
--]=]
local p = {}
local infobox = require('Module:Infobox')
local onmain = require('Module:Mainonly').on_main
local paramtest = require('Module:Paramtest')
local yesno = require('Module:Yesno')
local skillpic = require('Module:Skill clickpic')._main
local editbutton = require('Module:Edit button')
local commas = require('Module:Addcommas')._add
local chargedrain = require('Module:Augmented degrade')
local attack_speed_bar = require('Module:Attack speed bar').weapon
-- Accepted slot names
local slots = {
head = 'head',
neck = 'neck',
back = 'back',
cape = 'back',
torso = 'torso',
body = 'torso',
legs = 'legs',
hands = 'hands',
feet = 'feet',
ammo = 'ammo',
ring = 'ring',
aura = 'aura',
pocket = 'pocket',
sigil = 'sigil',
main = 'main hand weapon',
['main hand'] = 'main hand weapon',
['main-hand'] = 'main hand weapon',
mainhand = 'main hand weapon',
weapon = 'main hand weapon',
['2h'] = '2h weapon',
['off-hand'] = 'off-hand',
offhand = 'off-hand',
shield = 'off-hand',
['off-hand weapon'] = 'off-hand weapon',
['offhand weapon'] = 'off-hand weapon',
ohw = 'off-hand weapon',
set = 'e',
none = 'e'
}
-- Categories for slots
local slot_cats = {
head = 'Head slot items',
neck = 'Neck slot items',
back = 'Back slot items',
torso = 'Torso slot items',
legs = 'Legs slot items',
hands = 'Hand slot items',
feet = 'Feet slot items',
ammo = 'Ammunition slot items',
ring = 'Rings',
aura = 'Auras',
pocket = 'Pocket slot items',
sigil = 'Sigil slot items',
['main hand weapon'] = 'Main hand slot items',
['2h weapon'] = 'Two-handed slot items',
['off-hand'] = 'Off-hand slot items',
['off-hand weapon'] = 'Off-hand slot weapon',
e = ''
}
-- Images used for slot display
local slot_images = {
head = '[[File:Head slot.png|link=Head slot]]',
ammo = '[[File:Ammo slot.png|link=Ammunition slot]]',
neck = '[[File:Neck slot.png|link=Neck slot]]',
back = '[[File:Back slot.png|link=Back slot]]',
['main hand weapon'] = '[[File:Main hand slot.png|link=Main hand slot]]',
['2h weapon'] = '[[File:2h slot.png|link=Two-handed slot]]',
torso = '[[File:Torso slot.png|link=Torso slot]]',
['off-hand'] = '[[File:Off-hand slot.png|link=Off-hand slot]]',
['off-hand weapon'] = '[[File:Off-hand slot.png|link=Off-hand slot]]',
legs = '[[File:Legs slot.png|link=Legs slot]]',
hands = '[[File:Gloves slot.png|link=Hands slot]]',
feet = '[[File:Feet slot.png|link=Feet slot]]',
ring = '[[File:Ring slot.png|link=Ring slot]]',
aura = '[[File:Aura slot.png|link=Aura slot]]',
pocket = '[[File:Pocket slot.png|link=Pocket slot]]',
sigil = '[[File:Sigil slot.png|link=Sigil slot]]',
e = 'None'
}
-- 'invention slots'
local inv_slots = {
['main hand weapon'] = 'mh',
['2h weapon'] = '2h',
['off-hand'] = 'oh',
['off-hand weapon'] = 'oh',
shield = 'shield',
torso = 'body',
legs = 'legs',
tool = 'tool',
t = 'tool'
}
-- Accepted class names
local classes = {
melee = 'melee',
ranged = 'ranged',
ranging = 'ranged',
range = 'ranged',
magic = 'magic',
mage = 'magic',
all = 'all',
hybrid = 'hybrid',
none = 'none',
['n/a'] = 'none'
}
-- Classes with images
local class_img = {
melee = '[[File:Attack.png|x24px|link=Melee]]',
ranged = '[[File:Ranged.png|x24px|link=Ranged]]',
magic = '[[File:Magic.png|x24px|link=Magic]]',
hybrid = '[[File:CombatSwords.png|x24px|link=Armour#Hybrid]]',
all = '[[File:CombatSwords.png|x24px|link=Armour#All]]',
none = ''
}
local class_cats = {
melee = 'Melee',
magic = 'Magic',
ranged = 'Ranged',
hybrid = 'Hybrid',
all = 'Hybrid',
none = 'Typeless',
}
-- Accepted style names
local styles = {
stab = 'stab',
stabbing = 'stab',
slash = 'slash',
slashing = 'slash',
crush = 'crush',
crushing = 'crush',
arrow = 'arrows',
arrows = 'arrows',
bolt = 'bolts',
bolts = 'bolts',
thrown = 'thrown',
throwing = 'thrown',
magic = 'spell-casting',
spell = 'spell-casting',
spells = 'spell-casting',
none = 'none',
['n/a'] = 'none'
}
-- Categories for styles
local style_cats = {
stab = 'Stab weapons',
slash = 'Slash weapons',
crush = 'Crush weapons',
thrown = 'Thrown weapons'
}
local types = {
power = 'Power armour',
['power armour'] = 'Power armour',
tank = 'Tank armour',
['tank armour'] = 'Tank armour',
pvp = 'PvP armour',
['pvp armour'] = 'PvP armour',
shieldbow = 'Shieldbow',
shortbow = 'Bow',
bow = 'Bow',
defender = 'Defender',
repriser = 'Repriser',
rebounder = 'Rebounder',
halberd = 'Halberd',
shield = 'Shield',
chargebow = 'Chargebow',
cosmetic = 'Cosmetic',
['prevents attack'] = 'Prevents attack'
}
local type_cats = {
['power armour'] = 'Power armour',
['tank armour'] = 'Tank armour',
['pvp armour'] = 'PvP armour',
shieldbow = 'Shieldbows',
bow = 'Bows',
defender = 'Defenders',
repriser = 'Defenders',
rebounder = 'Defenders',
halberd = 'Halberds',
shield = 'Shields',
chargebow = 'Chargebows',
['prevents attack'] = 'Items which prevent attack'
}
local reduction_types = { -- accepts type or class
['tank armour'] = 'tank',
['power armour'] = 'other',
['pvp armour'] = 'pvp',
['shield'] = 'shield',
['shieldbow'] = 'shield',
['hybrid'] = 'other',
['all'] = 'other'
}
local reductions = { -- type -> slot -> pvm, pvp multipliers
tank = {
head = {pvm = 0.02, pvp = 0.0375},
torso = {pvm = 0.02, pvp = 0.06},
legs = {pvm = 0.02, pvp = 0.0525},
hands = {pvm = 0.02, pvp = 0},
feet = {pvm = 0.02, pvp = 0}
},
pvp = {
head = {pvm = 0, pvp = 0.0375},
torso = {pvm = 0, pvp = 0.06},
legs = {pvm = 0, pvp = 0.0525}
},
other = { --power, hybrid, all
head = {pvm = 0, pvp = 0.01875},
torso = {pvm = 0, pvp = 0.03},
legs = {pvm = 0, pvp = 0.02625}
},
shield = { --because hybrid shields are a thing
-- for consistency to continue allowing reduction.type.slot.pvx
['off-hand'] = {pvm = 0.1, pvp = 0},
['2h weapon'] = {pvm = 0.1, pvp = 0}, --shieldbows pls
}
}
function p.main(frame)
local args = frame:getParent().args
local ret = infobox.new(args)
ret:defineParams{
{ name = 'image', func = { name = imagearg, params = { 'image' }, flag = 'p' } },
{ name = 'altimage', func = { name = imagearg, params = { 'altimage' }, flag = 'p' } },
{ name = 'noimgcat', func = 'has_content' },
{ name = 'requirements', func = requirementsarg },
{ name = 'class', func = { name = lookuparg, params = { classes, 'class' }, flag = { 'r', 'd' } } },
{ name = 'classimg', func = { name = lookuparg, params = { class_img, 'class' }, flag = { 'r', 'd' } } },
{ name = 'classstr', func = { name = classstrarg, params = {'class', 'classimg' }, flag = 'd' } },
{ name = 'tier', func = tierarg },
{ name = 'type', func = { name = lookuparg, params = { types, 'type' }, flag = { 'r', 'd' } } },
{ name = 'slot', func = { name = lookuparg, params = { slots, 'slot' }, flag = { 'r', 'd' } } },
{ name = 'slotimg', func = { name = lookuparg, params = { slot_images, 'slot' }, flag = { 'r', 'd' } } },
{ name = 'isweapon', func = { name = isweaponarg, params = { 'slot', 'type' }, flag = d } },
{ name = 'invdegrade', func = { name = invdegradearg, params = { 'invtier', 'invslot', 'slot' }, flag = 'd' } },
{ name = 'invdegrade_span', func = { name = invdegradetooltipspanarg, params = { 'invtier', 'invslot', 'slot' }, flag = 'd' } },
{ name = 'invdegrade_div', func = { name = invdegradetooltipdivarg, params = { 'invtier', 'invslot', 'slot' }, flag = 'd' } },
{ name = 'normdegrades', func = { name = normdegradesarg, params = { 'degrades' }, flag = 'p' } },
{ name = 'degradetype', func = { name = degradestypearg, params = { 'normdegrades', 'invdegrade' }, flag = 'd' } },
{ name = 'degradestr', func = { name = degradesstrarg, params = { 'degradetype', 'normdegrades', 'invdegrade', 'invdegrade_span' }, flag = 'd' } },
{ name = 'degradeheader', func = { name = degradeheaderarg, params = { 'degradetype' }, flag = 'd' } },
{ name = 'style', func = { name = stylearg, params = { 'style', 'isweapon' }, flag = 'd' } },
{ name = 'attackrange', func = { name = attackrangearg, params = { 'isweapon', 'attack_range', 'attack range', 'attackrange' }, flag = { 'd', 'p', 'p', 'p' } } },
{ name = 'attackrangesmw', func = { name = attackrangesmwarg, params = { 'attackrange' }, flag = 'd' } },
{ name = 'damage', func = fnumbers },
{ name = 'accuracy', func = fnumbers },
{ name = 'maindamage', func = { name = mainoffarg, params = { 'damage', 'slot', 'main hand weapon', '2h weapon', 'ammo' }, flag = { 'd', 'd', 'r', 'r', 'r' } } },
{ name = 'mainaccuracy', func = { name = mainoffarg, params = { 'accuracy', 'slot', 'main hand weapon', '2h weapon' }, flag = { 'd', 'd', 'r', 'r' } } },
{ name = 'offdamage', func = { name = mainoffarg, params = { 'damage', 'slot', 'off-hand weapon' }, flag = { 'd', 'd', 'r' } } },
{ name = 'offaccuracy', func = { name = mainoffarg, params = { 'accuracy', 'slot', 'off-hand weapon' }, flag = { 'd', 'd', 'r' } } },
{ name = 'armour', func = fnumbers2 },
{ name = 'life', func = fnumbers2 },
{ name = 'prayer', func = fnumbers2 },
{ name = 'magic', func = fnumbers },
{ name = 'strength', func = fnumbers },
{ name = 'ranged', func = fnumbers },
{ name = 'magicstr', func = { name = stylebonusesarg, params = { 'magic', 'Magic' }, flag = { 'd', 'r' } } },
{ name = 'strengthstr', func = { name = stylebonusesarg, params = { 'strength', 'Strength' }, flag = { 'd', 'r' } } },
{ name = 'rangedstr', func = { name = stylebonusesarg, params = { 'ranged', 'Ranged' }, flag = { 'd', 'r' } } },
{ name = 'reductionlevel', func = { name = reductionlevelarg, params = { 'reductionlevel', 'tier', 'requirements' }, flag = { 'p', 'd', 'd' } } },
{ name = 'pvmreduction', func = { name = reductionarg, params = { 'reductionlevel', 'pvmReduction', 'type', 'slot', 'class', 'pvm' }, flag = { 'd', 'p', 'd', 'd', 'd', 'r' } } },
{ name = 'pvpreduction', func = { name = reductionarg, params = { 'reductionlevel', 'pvpReduction', 'type', 'slot', 'class', 'pvp' }, flag = { 'd', 'p', 'd', 'd', 'd', 'r' } } },
{ name = 'pvmreductionstr', func = { name = reductionstrarg, params = { 'pvmreduction', "'''PvM: '''" }, flag = { 'd', 'r' } } },
{ name = 'pvpreductionstr', func = { name = reductionstrarg, params = { 'pvpreduction', "'''PvP: '''" }, flag = { 'd', 'r' } } },
{ name = 'speedraw', func = { name = speedrawarg, params = { 'isweapon', 'speed', 'aspeed' }, flag = { 'd', 'p', 'p' } } },
{ name = 'speed', func = { name = speedarg, params = { 'speedraw' }, flag = 'd' } },
{ name = 'layouttype', func = { name = layoutarg, params = { 'image', 'altimage' }, flag ='d' } },
{ name = 'isrecolour', func = { name = recolourarg, params = { 'isrecolour' }, flag = 'd' } },
{ name = 'intbonus', func = { name = intbonusarg, params = { 'armour', 'damage', 'strength', 'ranged', 'magic' }, flag ='p' } },
{ name = 'tier_smw', func = { name = smwtierarg, params = { 'tier' }, flag = 'd' } },
{ name = 'style_smw', func = { name = smwstylearg, params = { 'style' }, flag = 'd' } },
{ name = 'damage_smw', func = { name = smwnumbers, params = { 'damage' }, flag = 'd' } },
{ name = 'accuracy_smw', func = { name = smwnumbers, params = { 'accuracy' }, flag = 'd' } },
{ name = 'armour_smw', func = { name = smwnumbers2, params = { 'armour' }, flag = 'd' } },
{ name = 'life_smw', func = { name = smwnumbers2, params = { 'life' }, flag = 'd' } },
{ name = 'prayer_smw', func = { name = smwnumbers2, params = { 'prayer' }, flag = 'd' } },
{ name = 'magic_smw', func = { name = smwnumbers, params = { 'magic' }, flag = 'd' } },
{ name = 'strength_smw', func = { name = smwnumbers, params = { 'strength' }, flag = 'd' } },
{ name = 'ranged_smw', func = { name = smwnumbers, params = { 'ranged' }, flag = 'd' } },
{ name = 'charges', func = { name = chargesarg, params = { 'degradetype', 'normdegrades' }, flag = 'd' } },
{ name = 'invtier', func = { name = invtierarg, params = { 'degradetype', 'invtier' }, flag = { 'd', 'p' } } },
{ name = 'smwJSON', func = { name = smwjsonarg, params = { 'class', 'slot', 'style_smw', 'type', 'damage_smw', 'accuracy_smw', 'attackrangesmw', 'armour_smw', 'life_smw', 'speedraw', 'prayer_smw', 'strength_smw', 'ranged_smw', 'magic_smw', 'tier_smw', 'charges', 'invtier' }, flag = 'd' } }
}
ret:setMaxButtons(7)
ret:setAddRSWInfoboxClass(false)
ret:create()
ret:cleanParams()
ret:customButtonPlacement(true)
ret:defineLinks({
colspan = 12,
links = {
{ 'Template:Infobox Bonuses/FAQ', 'FAQ' },
{ 'Template:Infobox Bonuses', 'docs' }
}
})
ret:css({
width = '450px',
float = 'none',
margin = '0.8em 0'
})
--smw here later
ret:useSMWSubobject({
smwJSON = 'Equipment JSON',
class = 'Combat class',
slot = 'Equipment slot',
type = 'Equipment type',
damage_smw = 'Weapon damage',
accuracy_smw = 'Weapon accuracy',
style_smw = 'Attack style',
attackrangesmw = 'Attack range',
armour_smw = 'Equipment armour',
life_smw = 'Equipment life points',
speedraw = 'Weapon attack speed',
prayer_smw = 'Prayer bonus',
strength_smw = 'Strength bonus',
ranged_smw = 'Ranged bonus',
magic_smw = 'Magic bonus',
tier_smw = 'Equipment tier',
charges = 'Degradation charges',
invtier = 'Invention tier',
isrecolour = 'Is cosmetic recolour'
})
ret:addButtonsCaption()
ret:defineName('Infobox Bonuses')
ret:addClass('infobox-bonuses wikitable')
ret:tag('caption'):wikitext("'''[[Combat Stats]]'''")
local layout = ret:param('layouttype', 'r')
p['_main'..layout](ret)
if onmain() then
local a1 = ret:param('all')
local a2 = ret:categoryData()
local cats = addcategories(ret,a1,a2)
ret._categories_test = cats
ret:wikitext(cats)
end
return ret:tostring()
end
-- 1 image
function p._mainA(ret)
local row1 = {
{ tag = 'th', content = 'Requirements', colspan = 6, class = 'combat-requirements' },
{ tag = 'argd', content = 'image', colspan = 6, rowspan = 11, class = 'infobox-image bordered-image' }
}
local row2 = {
{ tag = 'argd', content = 'requirements', colspan = 6, css = { ['max-width'] = '240px' } } -- stop skill reqs getting too wide
}
if ret:param('speed', 'r') ~= 'no' then
row1[2].rowspan = 12
end
if infobox.isDefined(ret:param('degradetype', 'r')) then
row1[1].colspan = 3
row2[1].colspan = 3
table.insert(row1, 2, { tag = 'argh', content = 'degradeheader', colspan = 3 })
table.insert(row2, 2, { tag = 'argd', content = 'degradestr', colspan = 3 })
if ret:param('degradetype', 'r') == 'invention' then
ret:append(tostring(ret:param('invdegrade_div', 'r')))
end
end
ret:addRow(row1):addRow(row2)
-- class, slot
ret:addRow{
{ tag = 'th', content = 'Class', colspan = 3 },
{ tag = 'th', content = 'Slot', colspan = 3 }
}
:addRow{
{ tag = 'argd', content = 'classstr', colspan = 3 },
{ tag = 'argd', content = 'slotimg', colspan = 3 }
}
if ret:paramDefined('type') then
-- tier, type
ret:addRow{
{ tag = 'th', content = '[[Equipment tier|Tier]]', colspan = 3 },
{ tag = 'th', content = 'Type', colspan = 3 }
}
:addRow{
{ tag = 'argd', content = 'tier', colspan = 3 },
{ tag = 'argd', content = 'type', colspan = 3 }
}
else
ret:addRow{
{ tag = 'th', content = '[[Equipment tier|Tier]]', colspan = 6 }
}
:addRow{
{ tag = 'argd', content = 'tier', colspan = 6 }
}
end
-- weapons section
ret:addRow{ --headers
{ tag = 'th', content = 'Weapons', colspan = 2, css = { width = '33%' } },
{ tag = 'th', content = 'Main', colspan = 2, css = { width = '33%' } },
{ tag = 'th', content = 'Off', colspan = 2, css = { width = '33%' } }
}
:addRow{ -- damage
{ tag = 'th', content = '[[Ability damage|Damage]]', colspan = 2 },
{ tag = 'argd', content = 'maindamage', colspan = 2 },
{ tag = 'argd', content = 'offdamage', colspan = 2 }
}
:addRow{ -- accuracy
{ tag = 'th', content = '[[Hit chance|Accuracy]]', colspan = 2 },
{ tag = 'argd', content = 'mainaccuracy', colspan = 2 },
{ tag = 'argd', content = 'offaccuracy', colspan = 2 }
}
:addRow{ -- style
{ tag = 'th', content = '[[Attack types|Style]]', colspan = 2 },
{ tag = 'argd', content = 'style', colspan = 4 }
}
:addRow{ -- range
{ tag = 'th', content = '[[Attack range|Range]]', colspan = 2 },
{ tag = 'argd', content = 'attackrange', colspan = 4 }
}
if ret:param('speed', 'r') ~= 'no' then
ret:addRow{ -- speed
{ tag = 'th', content = '[[Attack speed|Speed]]', colspan = 2 },
{ tag = 'argd', content = 'speed', colspan = 4, css = { padding = '0.2em' } }
}
end
-- attributes / bottom section
ret:addRow{ -- attribute & reduction headers
{ tag = 'th', content = 'Attributes', colspan = 6 },
{ tag = 'th', content = '[[Damage reduction]]', colspan = 6, css = { ['min-width'] = '225px' } }, -- force as wide as other side (3x th = 210 from css, + paddings and borders = 225)
}:addRow{ -- armour, reductions
{ tag = 'th', content = skillpic('Defence') .. ' Armour', colspan = 4, class = 'combat-attributes' },
{ tag = 'argd', content = 'armour', colspan = 2, css = { ['text-align'] = 'right' } },
{ tag = 'argd', content = 'pvmreductionstr', colspan = 3 },
{ tag = 'argd', content = 'pvpreductionstr', colspan = 3 }
}:addRow{ -- life points, style header
{ tag = 'th', content = skillpic('Constitution') .. ' Life points', colspan = 4, class = 'combat-attributes' },
{ tag = 'argd', content = 'life', colspan = 2, css = { ['text-align'] = 'right' } },
{ tag = 'th', content = '[[Damage bonus|Style bonuses]]', colspan = 6 },
}:addRow{ -- prayer, style bonuses
{ tag = 'th', content = skillpic('Prayer') .. ' Prayer', colspan = 4, class = 'combat-attributes' },
{ tag = 'argd', content = 'prayer', colspan = 2, css = { ['text-align'] = 'right' } },
{ tag = 'argd', content = 'strengthstr', colspan = 2 },
{ tag = 'argd', content = 'rangedstr', colspan = 2 },
{ tag = 'argd', content = 'magicstr', colspan = 2 },
}
-- bottom row
-- kinda special to accomodate the compare button
--[=[ret :tag('tr')
:addClass('infobox-bonuses-bottomrow')
:css('border', 'none')
:tag('td')
:attr('colspan', 12)
:css({
background = 'transparent !important',
border = 'none !important',
['text-align'] = 'left',
['font-size'] = 'smaller'
})
:wikitext('[[Template:Infobox Bonuses/FAQ|[FAQ]]] • [[Template:Infobox Bonuses|[doc]]]')
--]=]
end
-- 2 images or no images
function p._mainB(ret)
if ret:paramDefined('image') then
ret:addRow{
{ tag = 'argd', content = 'image', colspan = 6 },
{ tag = 'argd', content = 'altimage', colspan = 6 }
}
end
local row1 = {
{ tag = 'th', content = 'Requirements', colspan = 6, class = 'combat-requirements' },
{ tag = 'th', content = '[[Equipment tier|Tier]]', colspan = 6 }
}
local row2 = {
{ tag = 'argd', content = 'requirements', colspan = 6, css = { ['max-width'] = '240px' } }, -- stop skill reqs getting too wide
{ tag = 'argd', content = 'tier', colspan = 6 }
}
local row1tier = row1[2]
local row2tier = row2[2]
if infobox.isDefined(ret:param('degradetype', 'r')) then
row1[1].colspan = 3
row2[1].colspan = 3
table.insert(row1, 2, { tag = 'argh', content = 'degradeheader', colspan = 3 })
table.insert(row2, 2, { tag = 'argd', content = 'degradestr', colspan = 3 })
if ret:param('degradetype', 'r') == 'invention' then
ret:append(tostring(ret:param('invdegrade_div', 'r')))
end
end
if ret:paramDefined('type') then
row1tier.colspan = 3
row2tier.colspan = 3
table.insert(row1, { tag = 'th', content = 'Type', colspan = 3 })
table.insert(row2, { tag = 'argd', content = 'type', colspan = 3 })
end
ret:addRow(row1):addRow(row2)
local strSpan = 1
if infobox.isDefined(ret:param('speed', 'r')) and ret:param('speed', 'r') ~= 'no' then
strSpan = 2
end
ret:addRow{
-- class, slot, attr headers
{ tag = 'th', content = 'Class', colspan = 3, css = { width = '50%' } },
{ tag = 'th', content = 'Slot', colspan = 3, css = { width = '50%' } },
{ tag = 'th', content = 'Attributes', colspan = 6 },
}
:addRow{
-- class, slot, armour
{ tag = 'argd', content = 'classstr', rowspan = 2, colspan = 3 },
{ tag = 'argd', content = 'slotimg', rowspan = 2, colspan = 3 },
{ tag = 'th', content = skillpic('Defence') .. ' Armour', colspan = 4, class = 'combat-attributes' },
{ tag = 'argd', content = 'armour', colspan = 2, css = { ['text-align'] = 'right' } }
}
:addRow{
-- [class second row from rowspan]
-- [slot second row from rowspan]
-- life points
{ tag = 'th', content = skillpic('Constitution') .. ' Life points', colspan = 4, class = 'combat-attributes' },
{ tag = 'argd', content = 'life', colspan = 2, css = { ['text-align'] = 'right' } }
}
:addRow{
-- weapons header, prayer
{ tag = 'th', content = 'Weapons', colspan = 2, css = { width = '33%' } },
{ tag = 'th', content = 'Main', colspan = 2, css = { width = '33%' } },
{ tag = 'th', content = 'Off', colspan = 2, css = { width = '33%' } },
{ tag = 'th', content = skillpic('Prayer') .. ' Prayer', colspan = 4, class = 'combat-attributes' },
{ tag = 'argd', content = 'prayer', colspan = 2, css = { ['text-align'] = 'right' } }
}
:addRow{
-- damage, reduction header
{ tag = 'th', content = '[[Ability damage|Damage]]', colspan = 2 },
{ tag = 'argd', content = 'maindamage', colspan = 2 },
{ tag = 'argd', content = 'offdamage', colspan = 2 },
{ tag = 'th', content = '[[Damage reduction]]', colspan = 6 }
}
:addRow{
-- accuracy, reductions
{ tag = 'th', content = '[[Hit chance|Accuracy]]', colspan = 2 },
{ tag = 'argd', content = 'mainaccuracy', colspan = 2 },
{ tag = 'argd', content = 'offaccuracy', colspan = 2 },
{ tag = 'argd', content = 'pvmreductionstr', colspan = 3 },
{ tag = 'argd', content = 'pvpreductionstr', colspan = 3 }
}
:addRow{
-- style, style bonuses header
{ tag = 'th', content = '[[Attack types|Style]]', colspan = 2 },
{ tag = 'argd', content = 'style', colspan = 4 },
{ tag = 'th', content = 'Style bonuses', colspan = 6 }
}
:addRow{
-- range
{ tag = 'th', content = '[[Attack range|Range]]', colspan = 2 },
{ tag = 'argd', content = 'attackrange', colspan = 4 },
{ tag = 'argd', content = 'strengthstr', colspan = 2, rowspan = strSpan },
{ tag = 'argd', content = 'rangedstr', colspan = 2, rowspan = strSpan },
{ tag = 'argd', content = 'magicstr', colspan = 2, rowspan = strSpan }
}
if ret:param('speed', 'r') ~= 'no' then
ret:addRow{
{ tag = 'th', content = '[[Attack speed|Speed]]', colspan = 2 },
{ tag = 'argd', content = 'speed', colspan = 4, css = { padding = '0.2em' } }
}
end
end
p._mainB0 = p._mainB
p._mainB2 = p._mainB
-- images
function imagearg(f)
local height, width = 280, 220
if paramtest.is_empty(f) then
return nil
end
f = tostring(f)
if string.lower(f) == 'no' then
return nil
end
if string.find(f, "http") then
return mw.ustring.format('<div style="background-image:url('%s'); object-fit: contain; width:%spx; height:%spx; max-width:220px; max-height:280px; background-position:center;" title="%s"> </div>', f, width, height, mw.title.getCurrentTitle().text)
else
f = f:gsub('[Ff]ile:',''):gsub('{{!}}','|')
f = mw.text.split(f, '|')
f = f[1]
return mw.ustring.format('[[File:%s|%sx%spx|frameless|alt=%s: %s equipped by a player]]', f, width, height, f, mw.title.getCurrentTitle().text)
end
end
--requirements
function requirementsarg(r)
if infobox.isDefined(r) then
return mw.getCurrentFrame():preprocess(r)
end
return nil
end
-- class style type slot
function lookuparg(t, c)
return t[string.lower(c or '')]
end
function stylearg(s, w)
if w == 'true' then
s = styles[string.lower(s or '')]
if s then
return paramtest.ucfirst(s)
end
return s
end
return '-'
end
function smwstylearg(s)
if s ~= '-' then
return string.lower(tostring(s))
end
end
function classstrarg(c, ci)
if c == 'none' then
return 'None'
end
if infobox.isDefined(c) and infobox.isDefined(ci) then
return ci .. ' ' .. paramtest.ucfirst(c)
end
return nil
end
-- tier
function tierarg(t)
t = tostring(t)
t = t:lower()
if t == 'n/a' or t == 'no' or t == 'none' then
t = 0
end
t = clean(t)
if t then
if t == 0 then
return "''None''"
end
return t
end
return nil
end
function smwtierarg(t)
if t == "''None''" then
return 0
end
if type(t) == 'number' then
return t
end
return nil
end
-- numerical args
function fnumbers(x)
x = clean(x)
if x then
return x
end
return '-'
end
function fnumbers2(x)
x = clean(x)
if x then
return x
end
return 0
end
function smwnumbers(x)
if type(x) == 'number' then
return x
end
return 0
end
function smwnumbers2(x)
if type(x) == 'number' then
return x
end
return 0
end
function mainoffarg(x, s, s1, s2, s3)
if s == s1 or (s3 and s == s3) then
return x
end
if s2 then
if s == s2 then
return x
end
end
return '-'
end
function stylebonusesarg(x, t)
if x == '-' then
x = 0
end
return mw.ustring.format('<span style="float:left;">%s</span><span style="float:right;">%s</span>', skillpic(t), x)
end
-- isWeapon boolean
function isweaponarg(s,t)
local weapon_slots = {
['main hand weapon'] = 'true',
['2h weapon'] = 'true',
['off-hand weapon'] = 'true'
}
local non_weapon_types = {
['Prevents attack'] = 'true'
}
if non_weapon_types[t] then
return 'false'
end
return weapon_slots[s] or 'false'
end
-- degradation
-- invention charge drain
function invdegradearg(invtier,invslot,slot)
invtier = tonumber(invtier)
local ret = nil
if invtier then
invslot = slots[invslot] or invslot
invslot = inv_slots[invslot]
if not invslot then
invslot = inv_slots[slot]
end
ret = chargedrain.get_base(invtier,invslot)
end
return ret
end
function invdegradetooltipspanarg(invtier,invslot,slot)
invtier = tonumber(invtier)
local ret = nil
if invtier then
invslot = slots[invslot] or invslot
invslot = inv_slots[invslot]
if not invslot then
invslot = inv_slots[slot]
end
ret, _ = chargedrain.get_tooltip(invtier,invslot)
ret = tostring(ret)
end
return ret
end
function invdegradetooltipdivarg(invtier,invslot,slot)
invtier = tonumber(invtier)
local ret = nil
if invtier then
invslot = slots[invslot] or invslot
invslot = inv_slots[invslot]
if not invslot then
invslot = inv_slots[slot]
end
_, ret = chargedrain.get_tooltip(invtier,invslot)
ret = tostring(ret)
end
return ret
end
-- normal degradation
function normdegradesarg(deg)
local charges = clean(deg)
if charges then
return charges
end
if yesno(deg, false) then
return 'Yes'
end
return nil
end
function degradestypearg(deg,inv)
if infobox.isDefined(inv) then
return 'invention'
end
if infobox.isDefined(deg) then
return 'normal'
end
return nil
end
-- string representation
function degradesstrarg(dtype, deg, inv, invspan)
if dtype == 'invention' then
return mw.ustring.format('%s/s %s', inv, invspan)
end
if dtype == 'normal' then
if type(deg) == 'number' then
return commas(deg) .. ' charges'
elseif deg == true then
return 'Yes'
else
return deg
end
end
return ''
end
-- header
function degradeheaderarg(dtype)
if dtype == 'invention' then
return '[[Charge pack|Charge drain]]'
end
if dtype == 'normal' then
return '[[Equipment degradation|Degrades]]'
end
return ''
end
--smw
function chargesarg(dt, c)
if dt == 'normal' then
if type(c) == 'number' then
return c
end
end
return nil
end
function invtierarg(dt, t)
if dt == 'invention' then
t = clean(t)
if t then
return t
end
end
return nil
end
-- attack range
function attackrangearg(w,r1,r2,r3)
if w == 'true' then
return clean(r1) or clean(r2) or clean(r3)
end
return '-'
end
function attackrangesmwarg(a)
if a == '-' then
return nil
end
return a
end
-- reductions
function reductionlevelarg(r, tier, reqs)
if r then
r = clean(r)
if r then
return r
end
end
local ret = tonumber(tier) or 0
if infobox.isDefined(reqs) then
local maxR = 0
for v in string.gmatch(reqs, '(%d+) %[%[') do
if tonumber(v) and tonumber(v) > maxR then
maxR = tonumber(v)
end
end
if maxR > 0 then
ret = maxR
end
end
return ret
end
function reductionarg(rl, over, t, s, c, pvx)
over = clean(over)
if over then
--overridden
return over .. '%'
end
if not infobox.isDefined(rl) then
--tier/rl not defined
return '0%'
end
local reduction_table, reduction_type = nil,nil
if infobox.isDefined(t) then
-- check if we have a reduction for this type+slot
reduction_type = reduction_types[t:lower()]
if reduction_type then
reduction_table = reductions[reduction_type][s]
end
end
if not reduction_table and infobox.isDefined(c) then
-- couldn't find type+slot, so class+slot
reduction_type = reduction_types[c:lower()]
if reduction_type then
reduction_table = reductions[reduction_type][s]
end
end
if reduction_table then
return (reduction_table[pvx] or 0) * rl .. '%'
end
-- didn't find anything
return '0%'
end
function reductionstrarg(r, ty)
return mw.ustring.format('<span style="float:left;">%s</span><span style="float:right;">%s</span>', ty, r)
end
-- speed
function speedrawarg(iswep, s1, s2)
if iswep =='true' then
local s
if infobox.isDefined(s1) then
s = string.lower(s1)
elseif infobox.isDefined(s2) then
s = string.lower(s2)
end
return s or ''
else
return 'no'
end
end
function speedarg(s)
if infobox.isDefined(s) then
if s == 'no' then
return 'no'
else
return tostring(attack_speed_bar(s))
end
end
return nil
end
-- layout
function layoutarg(img, alt)
if infobox.isDefined(img) then
if infobox.isDefined(alt) then
-- 2 images
return 'B2'
end
-- 1 image
return 'A'
end
-- no images
return 'B0'
end
function intbonusarg(...)
for _,v in ipairs({...}) do
if paramtest.has_content(v) then
if not v:match('%d%.%d') then
return 'true'
end
end
end
return nil
end
function recolourarg(arg)
-- string to ensure it correctly passes through infobox
return tostring(infobox.isDefined(arg) and yesno(arg, false))
end
-- Removes all plus signs, commas, and percent signs
function clean(number)
if not number then
return nil
else
number = tostring(number)
number = number:gsub('[+,%%]','')
return tonumber(number,10)
end
end
-- legacy SMW JSON
function smwjsonarg(class, slot, style, itype, damage, accuracy, attack_range, armour, life, speed, prayer, strength, ranged, magic, tier, charges, invtier)
local json = {
class = class,
slot = slot,
style = style,
type = itype,
damage = damage,
accuracy = accuracy,
style = style,
attack_range = attack_range,
armour = armour,
lp = life,
speed = speed,
prayer = prayer,
strength = strength,
ranged = ranged,
magic = magic,
tier = tier,
charges = charges,
invention = invtier
}
for k,v in pairs(json) do
if not infobox.isDefined(v) then
json[k] = nil
end
end
local jsonGood, encoded = pcall(mw.text.jsonEncode,json)
if jsonGood then
return encoded
end
return nil
end
-- categories
function addcategories(ibox, args,catargs)
local cats = {'Equipment'}
local versions = ibox.versions
function forAllSwitches(func, param1, param2, param3)
local r = {}
param2 = param2 or {}
param3 = param3 or {}
local p1,p2,p3
p1 = param1.d
p2 = param2.d
p3 = param3.d
table.insert(r, func(p1,p2,p3))
if versions > 0 and (param1.switches or param2.switches or param3.switches) then
local p1s,p2s,p3s
for i = 1,versions,1 do
p1s = p1
if param1.switches then
p1s = param1.switches[i]
if p1s == infobox.nil_param then
p1s = p1
end
end
p2s = p2
if param2.switches then
p2s = param2.switches[i]
if p2s == infobox.nil_param then
p2s = p2
end
end
p3s = p3
if param3.switches then
p3s = param3.switches[i]
if p3s == infobox.nil_param then
p3s = p3
end
end
table.insert(r, func(p1s, p2s, p3s))
end
end
return r
end
function append(a)
if type(a) == 'table' then
for i,v in ipairs(a) do
table.insert(cats, v)
end
else
table.insert(cats,a)
end
end
-- slot missing
if not catargs.slot.all_defined then
append('Missing slot information')
end
-- tiers
append(forAllSwitches(function(v)
if type(v) == 'number' then
if v == 0 then
return 'Tierless equipment'
elseif v > 0 then
return 'Tier '..v..' equipment'
end
end
return 'Missing equipment tier'
end, args.tier_smw))
-- type
append(forAllSwitches(function(v)
if type(v) == 'string' then
return type_cats[v:lower()]
end
return nil
end, args.type))
-- slots
append(forAllSwitches(function(v)
v = string.lower(tostring(v))
if v == 'off-hand weapon' then
local k = mw.title.getCurrentTitle().fullText:gsub('[Oo]ff[%- ]?hand ?', '')
return 'Off-hand slot weapons|'..k
elseif slot_cats[v] then
return slot_cats[v]
end
return 'Missing slot information'
end, args.slot))
-- style
append(forAllSwitches(function(v)
return style_cats[v]
end, args.style))
-- degrades
if catargs.normdegrades.one_defined then
append('Degrading equipment')
end
-- class
append(forAllSwitches(function(c,w,s)
local cat = class_cats[c]
if cat then
if s == 'ammo' then
return nil
end
if w == 'true' then
if cat == 'Hybrid' then
cat = 'Typeless'
end
return cat .. ' weapons'
end
return cat .. ' armour'
end
return nil
end, args.class, args.isweapon, args.slot))
-- prayer
append(forAllSwitches(function(p)
if tonumber(p) then
if tonumber(p) > 0 then
return 'Items with a prayer bonus'
end
end
return nil
end, args.prayer_smw))
-- range
if not catargs.attackrange.all_defined then
append('Missing attack range')
end
-- speed
append(forAllSwitches(function(s)
if s == '' then
return 'Missing attack speed'
end
return nil
end, args.speedraw))
-- integer equipment bonuses
if catargs.intbonus.one_defined then
append('Integer equipment bonus')
end
-- equipped image
append(forAllSwitches(function(i, s, n)
if infobox.isDefined(n) then
return nil
end
if s == 'ammo' or s == 'pocket' or s == 'ring' or s == 'sigil' then
return nil
end
if not infobox.isDefined(i) then
return 'Needs equipped image'
end
return nil
end, args.image, args.slot, args.noimgcat))
local _cats = {}
for i,v in ipairs(cats) do
if paramtest.has_content(v) then
table.insert(_cats, string.format('[[Category:%s]]', v))
end
end
return table.concat(_cats, '')
end
return p
-- </nowiki>