Module:Equipment bonuses infotable: Difference between revisions

From WIDEVERSE Wiki
Jump to navigation Jump to search
(Undid revision 35542701 by Manfegor (Talk) No need to add to add undocumented options when the option nosmw already does the same thing)
 
m (1 revision imported)
 
(No difference)

Latest revision as of 21:22, 4 November 2021

Documentation for this module may be created at Module:Equipment bonuses infotable/doc

-- <nowiki>
local p = {}
local yesno = require("Module:Yesno")
local weaknessClickpick = mw.loadData("Module:Weakness clickpic/data")
local Exchange = require("Module:Exchange")
local Coins = require("Module:Coins")._amount
local AddCommas = require("Module:Addcommas")._add
local skillClickpic = require("Module:Skill clickpic")._main
local onmain = require("Module:Mainonly").on_main

-- Accepted rowTypes
function makeRowType(c, iconOnly)
	local v = weaknessClickpick[c]
	local s = v.text or v.link
	if iconOnly then
	    return string.format("[[File:%s|x26px|link=%s]]",v.image,v.link)
	else
	    return string.format("[[File:%s|x26px|link=%s]] [[%s|%s]]",v.image,v.link,v.link,s)
	end
end

local rowTypes = {
    melee = makeRowType('melee', false),
    ['melee icon'] = makeRowType('melee', true),
    ranged = makeRowType('ranged', false),
    ['ranged icon'] = makeRowType('ranged', true),
    magic = makeRowType('magic', false),
    ['magic icon'] = makeRowType('magic', true),
    all = makeRowType('none', false),
    ['all icon'] = makeRowType('none', true),
    hybrid = "[[File:CombatSwords.png|x26px|link=Armour#Hybrid]] [[Armour#Hybrid|Hybrid]]",
    ['hybrid icon'] = "[[File:CombatSwords.png|x26px|link=Armour#Hybrid]]",
    none = "-"
}
 
-- Accepted headerTypes
local headerTypes = {
    melee = "[[File:Attack.png|x34px|link=Melee]]<br />Item",
    ranged = "[[File:Ranged.png|x34px|link=Ranged]]<br />Item",
    magic = "[[File:Magic.png|x34px|link=Magic]]<br />Item",
    all = "[[File:CombatSwords.png|link=Armour#All]]<br />Item",
    hybrid = "[[File:CombatSwords.png|link=Armour#Hybrid]]<div style='display:inline-block; width:50px; text-align:center; margin-top:-10px; margin-bottom:10px; position:relative; top:12px'>'''Hybrid''' '''Item'''</div>",
    mixed = "Item",
    none = "Item"
}

-- Accepted weapon styles
local styles = {
    stab = "'''Stab'''",
    stabbing = "'''Stab'''",
    crush = "'''Crush'''",
    crushing = "'''Crush'''",
    slash = "'''Slash'''",
    slashing = "'''Slash'''",
    arrow = "'''Arrow'''",
    arrows = "'''Arrow'''",
    bolt = "'''Bolt'''",
    bolts = "'''Bolt'''",
    thrown = "'''Thrown'''",
    spell = "'''Spell-<br />casting'''",
    spells = "'''Spell-<br />casting'''",
    ['spell-casting'] = "'''Spell-<br />casting'''",
    none = "'''None'''"
}

-- Row args that are summed and displayed in the totals row (if present)
local totalArgs = {
	mdmg = 0,
	macc = 0,
	odmg = 0,
	oacc = 0,
	armour = 0,
	life = 0,
	prayer = 0,
	strength = 0,
	ranged = 0,
	magic = 0,
}

local function isnotempty(s)
    return not (s == nil or s == "")
end

local function isempty(s)
	return not isnotempty(s)
end

local function cleanItemName(argstable, isSMW)
	local pattern = isSMW and "%[%[([^|%]]+)" or "%[%[([^|#%]]+)"
	
	return (argstable.ge and (argstable.ge:match(pattern) or argstable.ge))
        or (argstable.name and (argstable.name:match(pattern) or argstable.name))
end
 
function p.main(frame)
    local frameargs = frame:getParent().args
    local htmltable = mw.html.create("table") -- The output of this module
    local tblrow = ""
    local tblcell = ""
    local totalPrice = 0                      -- Sum of the individual prices
    local totalspanrange = 6                  -- Minimum spanrange of the label in case the totals parameter is used
    local imageRowsSpan = 0                   -- Default row span
    local smwmismatch = false                 -- Template data disagrees with SMW data
    local smwerror = false                    -- Error occurred while retrieving SMW data
    local totalsmismatch = false              -- Template data for totals row disagrees with auto-calc'd sum
    
    -- Create the tabel header
    --[[Parameters used (variable type)     [note]
        class / type    (string)            [@mandatory]
        noinv           (yes/no)            [@optional, default is no, if yes the rowspan of the class header is 1 otherwise its 2]
        skill           (string)            [@optional, accepted values are those for Module:Skill clickpic]
        skill2          (string)            [@optional, accepted values are those for Module:Skill clickpic]
        noweapon        (yes/no)            [@optional, default is no, if yes hides the weapons stats]
        nostyle			(yes/no)			[@optional, default is no, if yes hides the style bonuses]
        noattr			(yes/no)			[@optional, default is no, if yes hides the attribute bonuses]
        nosumstats      (yes/no)            [@optional, default is no, if yes will not automatically sum stat values to display in totals row]
        price           (ge/number/string)  [@optional, ge is the the string "ge", ge and number are preferred so it adds to the totalprice]
        price2          (ge/number/string)  [@optional]
        image           (string)            [@optional, image is given by the form "image name.png"]
        image2          (string)            [@optional]
        rows            (number)            [@optional, only affects image and image2]
        tot             (number)            [@optional, only affects image and image2]
        sortable        (yes/no)            [@optional]
        typeicon        (yes/no)            [@optional, default is no, if yes will force rows' "type" values to only show icons]
    ]]
    
    htmltable
        :addClass("wikitable infotableBonuses")
        :css("text-align", "center")
        
        -- Make first header row
        tblrow = htmltable:tag("tr")
            
            -- Set the header class
            tblcell = tblrow:tag("th")
                :attr("rowspan", "2")
                :wikitext(headerTypes[string.lower(frameargs.class or frameargs.type or "")] or ("''Type Unknown<br /><small>[" .. tostring(mw.uri.fullUrl( mw.title.getCurrentTitle().prefixedText, "action=edit")) .. " edit]</small>''"))
                :attr("data-sort-type", "text")
                if not yesno(frameargs.noinv) then
                    tblcell
                        :attr("colspan", "2")
                end
                
            -- Add extra type colomn if the header class is mixed
            if string.lower(frameargs.class or frameargs.type or "") == "mixed" then
                tblrow
                    :tag("th")
                        :attr("rowspan", "2")
                        :attr("data-sort-type", "text")
                        :wikitext("Type")
                    :done()
                totalspanrange = totalspanrange + 1
            end
                
            -- Add extra skill column
            if isnotempty(frameargs.skill) then
                tblrow
                    :tag("th")
                        :attr("rowspan", "2")
                        :attr("data-sort-type", "number")
                        :css("vertical-align", "bottom")
                        :wikitext(skillClickpic(frameargs.skill or ""))
                            :tag("br")
                            :done()
                        :tag("span")
                            :css("font-size", "90%")
                            :wikitext("Level")
                        :done()
                    :done()
                totalspanrange = totalspanrange + 1
            end
            
            -- Add extra skill2 column
            if isnotempty(frameargs.skill2) then
                tblrow
                    :tag("th")
                        :attr("rowspan", "2")
                        :attr("data-sort-type", "number")
                        :css("vertical-align", "bottom")
                        :wikitext(skillClickpic(frameargs.skill2 or ""))
                            :tag("br")
                            :done()
                        :tag("span")
                            :css("font-size", "90%")
                            :wikitext("Level")
                        :done()
                    :done()
                totalspanrange = totalspanrange + 1
            end
                
            -- Show/hide weapon stats
            if not yesno(frameargs.noweapon) then
                tblrow
                    :tag("th")
                        :attr("colspan", "3")
                        :wikitext("Main-hand")
                    :done()
                    :tag("th")
                        :attr("colspan", "3")
                        :wikitext("Off-hand")
                    :done()
                totalspanrange = totalspanrange + 6
            end
                
            -- Add atribute columns
            if not yesno(frameargs.noattr) then
	            tblrow
	                :tag("th")
	                    :attr("colspan", "3")
	                    :attr("title", "Determines their character's endurance determined by their armour rating, life point boost, and prayer bonus")
	                    :wikitext("Attribute")
	                :done()
	        end
             
            -- Add style bonuses columns
			if not yesno(frameargs.nostyle) then
            	tblrow
                	:tag("th")
                    	:attr("colspan", "3")
                    	:wikitext("Style&nbsp;bonus")
                	:done()
            end
            -- Add price and/or price2 column
            if yesno(frameargs.price) ~= yesno(frameargs.price2) then   -- XOR
                tblrow
                    :tag("th")
                        :attr("rowspan", "2")
                        :attr("data-sort-type", "number")
                        :wikitext("Price")
                    :done()
                totalspanrange = totalspanrange + 1
            elseif yesno(frameargs.price) and yesno(frameargs.price2) then
                tblrow
                    :tag("th")
                        :attr("rowspan", "2")
                        :attr("data-sort-type", "number")
                        :wikitext("Price<br />Main-hand")
                    :done()
                    :tag("th")
                        :attr("rowspan", "2")
                        :attr("data-sort-type", "number")
                        :wikitext("Price<br />Off-hand")
                    :done()
                totalspanrange = totalspanrange + 2
            end
            
            -- Get default rowspan for images if they are used
            if isnotempty(frameargs.image) or isnotempty(frameargs.image2) then
                for i,j in ipairs(frameargs) do
                     imageRowsSpan = imageRowsSpan + 1
                end
            end
            
            -- Add image column
            if isnotempty(frameargs.image) then
                tblrow
                    :tag("th")
                        :attr("rowspan", tostring(2 + tonumber(frameargs.rows or imageRowsSpan) + tonumber(frameargs.tot or 0)))
                        :addClass('unsortable')
                        :css("width", "125px")
                        :css("text-align", "center")
                        :css("vertical-align", "center")
                        :wikitext("[[File:" .. frameargs.image .. "]]")
                    :done()
            end
                
            -- Add image2 comlumn
            if isnotempty(frameargs.image2) then
                tblrow
                    :tag("th")
                        :attr("rowspan", tostring(2 + tonumber(frameargs.rows or imageRowsSpan) + tonumber(frameargs.tot or 0)))
                        :addClass('unsortable')
                        :css("width", "125px")
                        :css("text-align", "center")
                        :css("vertical-align", "center")
                        :wikitext("[[File:" .. frameargs.image2 .. "]]")
                    :done()
            end
            
        -- Make second header row
        tblrow = htmltable:tag("tr")
        
            -- Show/hide weapon stats
            if not yesno(frameargs.noweapon) then
                tblrow
                    :tag("th")
                        :attr("title", "Mainhand attacking style")
                        :attr("data-sort-type", "number")
                        :wikitext("Style")
                    :done()
                    :tag("th")
                        :attr("title", "Mainhand weapon damage")
                        :attr("data-sort-type", "number")
                        :wikitext("Dmg")
                    :done()
                    :tag("th")
                        :attr("title", "Mainhand weapon accuracy")
                        :attr("data-sort-type", "number")
                        :wikitext("Acc")
                    :done()
                    :tag("th")
                        :attr("title", "Offhand attacking style")
                        :attr("data-sort-type", "number")
                        :wikitext("Style")
                    :done()
                    :tag("th")
                        :attr("title", "Offhand weapon damage")
                        :attr("data-sort-type", "number")
                        :wikitext("Dmg")
                    :done()
                    :tag("th")
                        :attr("title", "Offhand weapon accuracy")
                        :attr("data-sort-type", "number")
                        :wikitext("Acc")
                    :done()
            end
                
            -- Add attribute and style bonuses columns
            if not yesno(frameargs.noattr) then
	            tblrow
	                :tag("th")
	                	:attr("data-sort-type", "number")
	                    :wikitext(skillClickpic("Defence"))
	                :done()
	                :tag("th")
	                	:attr("data-sort-type", "number")
	                    :wikitext(skillClickpic("Constitution"))
	                :done()
	                :tag("th")
	                	:attr("data-sort-type", "number")
	                    :wikitext(skillClickpic("Prayer"))
	                :done()
	            :done()
	        end
            if not yesno(frameargs.nostyle) then
	            tblrow
	                :tag("th")
	                	:attr("data-sort-type", "number")
	                    :wikitext("[[File:Attack-icon.png|20px|link=Melee]]")
	                :done()
	                :tag("th")
	                	:attr("data-sort-type", "number")
	                    :wikitext("[[File:Ranged-icon.png|20px|link=Ranged]]")
	                :done()
	                :tag("th")
	                	:attr("data-sort-type", "number")
	                    :wikitext("[[File:Magic-icon.png|20px|link=Magic]]")
	                :done()
	            :done()
            end

        -- sortable
        if yesno(frameargs.sortable) then
            htmltable:addClass("sortable")
        end
    -- Header ends here
    
    -- Table rows are created here
    --[[Parameters used     (variable type)     [note]
            [all paramerers are @optional]
        totals          (yes/no)            [Default is no]
        label           (string)            [Only has an effect if totals is used]
        ge              (string)    
        image           (string)            [Only works if the ge parameter is not used]
        name            (string)            [Only works if the ge parameter is not used]
        smwname         (string)            [Override the name used in the SMW query for stats]
        type            (string)            [Default is "-"]
        level/skill     (number/string)     [Default is "-"]
        level2/skill2   (number/string)     [Default is "-"]
        mstyle          (string)            [Default is "-"]
        mdmg            (number)            [Default is "-"]
        macc            (number)            [Default is "-"]
        ostyle          (string)            [Default is "-"]
        odmg            (number)            [Default is "-"]            
        oacc            (number)            [Default is "-"]
        armour          (number)            [Default is "-"]
        life            (number)            [Default is "-"]
        prayer          (number)            [Default is "-"]
        strength        (number)            [Default is "-"]
        ranged          (number)            [Default is "-"]
        magic           (number)            [Default is "-"]
        price           (ge/number/string)  [ge only works if the ge parameter is used. ge and number are preferred if the totals prameter is used]
        price2          (ge/number/string)
        priceimage      (string)            [can be used incase the ge parameter is not used but you want the price to add to the totalprice]
        dontaddtototal  (yes/no)            [default is no]
        nocoinstotals   (yes/no)            [default is no]
        ref             (string)
    ]]
    local argstables = {}
    local replacedrows = {}
    for rownum, j in ipairs(frameargs) do     -- Iterate in order over all frameargs with a integer key
        -- Parse the framearg j into a table of rowargs, j = {{Equipment bonuses inforow}}
        argstables[rownum] = {}
        local argstable = argstables[rownum]
        for argduo in j:gmatch("!(.-)!") do
            local argname = argduo:match("&(.-)&")
            local argvalue = argduo:match( "µ(.-)µ")
            if argvalue == "" then
                argvalue = nil
            end
            argstable[argname] = argvalue
        end
        
        -- Set up rowarg mapping to SMW properties
        if not (yesno(argstable.totals) or yesno(frameargs.nosmw) or yesno(argstable.nosmw)) then
        	local smwprops = {}
        	
        	-- Unfortunately, Module:Infobox Bonuses new doesn't try to parse out the requirements param
        	-- As such, it doesn't populate any SMW properties for requirements, meaning the EQ inforow
        	-- arguments "level/skill" and "level2/skill2" can't be automatically populated via SMW. :'(
        	smwprops["type"] = "Combat class"
        	if not yesno(frameargs.noweapon) then
        		smwprops["m/o style"] = "Attack style"
        		smwprops["m/o dmg"] = "Weapon damage"
        		smwprops["m/o acc"] = "Weapon accuracy"
    		end
    		if not yesno(frameargs.noattr) then
    			smwprops["armour"] = "Equipment armour"
    			smwprops["life"] = "Equipment life points"
    			smwprops["prayer"] = "Prayer bonus"
			end
			if not yesno(frameargs.nostyle) then
				smwprops["strength"] = "Strength bonus"
				smwprops["ranged"] = "Ranged bonus"
				smwprops["magic"] = "Magic bonus"
			end
			
			local smwname = argstable.smwname or cleanItemName(argstable, true)
			if isempty(smwname) then
				mw.log("EQ Infotable SMW error: Empty item name for row #" .. rownum)
				smwerror = true
			else
				local query = {
					"[[Equipment slot::+]] [[" .. smwname .. "]]",
					"OR [[Equipment slot::+]] [[Item name::" .. smwname .. "]]",
					"OR [[Equipment slot::+]] [[Is variant of::" .. smwname .. "]]",
					"?#-=SMW Title",
					"?Equipment slot",
					limit = "1"
				}
				for _, prop in pairs(smwprops) do
					table.insert(query, "?" .. prop)
				end
				
				local result = mw.smw.ask(query)
				if not result or #result == 0 then
					mw.log("EQ Infotable SMW error: Ask failed")
					mw.logObject(query)
					smwerror = true
				else
					result = result[1]
					isoffhand = not not result["Equipment slot"]:match("off%-hand")
					
					for argname, propname in pairs(smwprops) do
						local handarg = argname:match("m/o (.+)")
						if handarg then
							argname = (isoffhand and "o" or "m") .. handarg
						end
						
						if argstable[argname] == nil and result[propname] ~= 0 then
							argstable[argname] = result[propname]
						elseif argstable[argname] ~= nil and result[propname] ~= 0 then
							-- Only flag mismatches of numerical values if they differ by >= 1.0
							-- Allows rounding/truncation of decimal values to not flag
							-- This seems to have been a common practice when composing the
							-- older Infotables; remove if accurate values w/ decimals are preferred
							if (type(result[propname]) == "number" and math.abs(tonumber(argstable[argname]) - result[propname]) >= 1) or
							   (type(result[propname]) == "string" and not argname:match("[mo]style") and result[propname]:lower() ~= argstable[argname]:lower() ) or
							   (argname:match("[mo]style") and styles[string.lower(result[propname] or "")] ~= styles[argstable[argname]:lower()]) then
								smwmismatch = true
								mw.log("EQ Infotable SMW warning: Row mismatch for parameter: " .. argname)
								mw.log("    Item name: " .. smwname)
								mw.log("    Template value: " .. argstable[argname])
								mw.log("    SMW value: " .. (result[propname] or ""))
							end
						end
					end
				end
			end
    	end
        
        -- Special processings for totals rows
        if yesno(argstable.totals) then
        	-- Add extra row if the totals + label parameters are used
        	if isnotempty(argstable.label) then
	            tblrow = htmltable:tag("tr")
	                :addClass("attribute-total sortbottom")
	                tblcell = tblrow:tag("th")
	                    :attr("rowspan", "2")
	                    :wikitext("Totals" .. ((argstable.ref and (" " .. argstable.ref)) or ""))
	                    if not yesno(frameargs.noinv) then
	                        tblcell
	                            :attr("colspan","2")
	                    end
	                    
	            tblrow
	                :tag("th")
	                    :attr("colspan", totalspanrange)
	                    :wikitext(argstable.label)
	                :done()
            end
            
            if not yesno(frameargs.nosumstats) then
	            -- Default totals args to their corresponding sum if not specified
	            for arg, sum in pairs(totalArgs) do
	            	if sum ~= 0 then
	            		if isempty(argstable[arg]) then
	            			argstable[arg] = sum
            			elseif tonumber(argstable[arg]) ~= sum then
            				totalsmismatch = true
            				mw.log("EQ Infotable totals mismatch for parameter: " .. arg)
            				mw.log("    Template: " .. argstable[arg])
            				mw.log("    Calculated: " .. sum)
        				end
	        		end
	        	end
	        	
	        	-- Default skill level columns to max values
	        	if isnotempty(frameargs.skill) or isnotempty(frameargs.skill2) then
	        		argstable.skill = 0
	        		argstable.skill2 = 0
	        		
	        		for k = 1, rownum - 1 do
	        			if not replacedrows[k] and isempty(argstables[k].totals) then
	        				local rowSkill = argstables[k].skill or argstables[k].level
	        				local rowSkill2 = argstables[k].skill2 or argstables[k].level2
	        				argstable.skill = math.max(argstable.skill, tonumber(rowSkill) or 0)
	        				argstable.skill2 = math.max(argstable.skill2, tonumber(rowSkill2) or 0)
    					end
    				end
        		end
        	end
        else
	        -- Support replacing previous rows with the current row's stats when summing totals
	        if isnotempty(argstable.replacerow) then
	        	local replacenum = tonumber(argstable.replacerow)
	        	if replacenum == nil or replacenum < 1 or replacenum >= rownum or isnotempty(argstables[replacenum].totals) then
	        		mw.log("EQ Infotable error: Invalid replacerow value for item: " .. cleanItemName(argstable))
	        		mw.log("    replacerow="..replacenum.."; rownum="..rownum.."; numrows="..#frameargs)
        		else
        			local replacedargs = argstables[replacenum]
        			replacedrows[replacenum] = true
        			
    				-- Subtract replaced row's additions to the totals
    				for arg, sum in pairs(totalArgs) do
    					local argNum = tonumber(replacedargs[arg])
    					if argNum ~= nil then
    						totalArgs[arg] = sum - argNum
						end
					end
					
					-- Price is handled separately; subtract it if it's a number (from GE or as given)
					local argPrice = tonumber(replacedargs.price)
					if argPrice ~= nil then
						totalPrice = totalPrice - argPrice
					end
        		end
        	end
        	if not yesno(frameargs.nosumstats) and not yesno(argstable.dontaddtototal) then
	        	-- Non-totals row; add totals args to their corresponding sum if a numerical value is specified
	        	for arg, sum in pairs(totalArgs) do
	        		local argNum = tonumber(argstable[arg])
	    			if argNum ~= nil then
	    				totalArgs[arg] = sum + argNum
					end
    			end
    		end
    	end
        
        -- Create a new inforow
        tblrow = htmltable:tag("tr")
        
            -- Special handling for a totals row
            if yesno(argstable.totals) then
                tblrow
                    :addClass("attribute-total sortbottom")

	            -- Add the totals text cell (if not already added above due to requested label)
	            if isempty(argstable.label) then
	                tblcell = tblrow:tag("th")
	                    :wikitext("Totals" .. ((argstable.ref and (" " .. argstable.ref)) or ""))
	                    if not yesno(frameargs.noinv) then
	                        tblcell
	                            :attr("colspan","2")          
	                    end
                end
            else
            	-- Italicise rows that will not add to the total stats
            	if isnotempty(argstable.dontaddtototal) then
            		tblrow:css("font-style", "italic")
        		end
            	
	            -- Add the item image and name cells
	            if isnotempty(argstable.ge) then
	            	local itemLink = (argstable.ge:match("^%[%[") and argstable.ge) or "[[" .. argstable.ge .. "]]"
	            	local itemName = cleanItemName(argstable)
	                tblrow
	                    :tag("td")
	                        :wikitext("[[File:" .. itemName .. ".png|link=" .. itemName .. "]]")
	                        :addClass("inventory-image")
	                    :done()
	                    :tag("td")
	                        :css("text-align", "left")
	                        :wikitext(itemLink .. ((argstable.ref and (" " .. argstable.ref)) or ""))
	                    :done()
	            elseif isnotempty(argstable.image) then
	                tblrow
	                    :tag("td")
	                        :wikitext(argstable.image:find("[[File:", 1, true) and argstable.image or ("[[File:" .. argstable.image .. "]]"))
	                    :done()
	                if isnotempty(argstable.name) then
	                    tblrow
	                        :tag("td")
	                            :css("text-align", "left")
	                            :wikitext(argstable.name .. ((argstable.ref and (" " .. argstable.ref)) or ""))
	                        :done()
	                end
	            elseif isnotempty(argstable.name) then
	                tblrow
	                    :tag("td")
	                        :css("text-align", "left")
	                        :wikitext(argstable.name .. ((argstable.ref and (" " .. argstable.ref)) or ""))
	                    :done()
	            end
            end
            
            -- Add the type cell incase the header class is mixed
            if string.lower(frameargs.class or frameargs.type or "") == "mixed" then
            	local argType = string.lower(argstable.type or "")
            	if yesno(frameargs.typeicon) and isnotempty(argType) and not argType:match(" icon$") then
            		argType = argType .. " icon"
        		end
        		
                tblrow
                    :tag("td")
                        :wikitext(rowTypes[argType] or argstable.type or "-")
                    :done()
            end
            
            -- Add the skill cell
            if isnotempty(frameargs.skill) then
            	local skillArg = argstable.level or argstable.skill
                tblrow
                    :tag("td")
                        :wikitext(skillArg or "-")
                        :attr("data-sort-value", skillArg or 0)
                    :done()
            end
            
            -- Add the skill2 cell
            if isnotempty(frameargs.skill2) then
            	local skill2Arg = argstable.level2 or argstable.skill2
                tblrow
                    :tag("td")
                        :wikitext(skill2Arg or "-")
                        :attr("data-sort-value", skill2Arg or 0)
                    :done()
            end
            
            -- Show/hide weapon stats
            if not yesno(frameargs.noweapon) then
                tblrow
                    :tag("td")
                        :addClass("attribute-value")
                        :wikitext(styles[string.lower(argstable.mstyle or "")] or argstable.mstyle or "-")
                    :done()
                    :tag("td")
                        :addClass("attribute-value")
                        :wikitext(argstable.mdmg or "-")
                        :attr("data-sort-value", argstable.mdmg or 0)
                    :done()
                    :tag("td")
                        :addClass("attribute-value")
                        :wikitext(argstable.macc or "-")
                        :attr("data-sort-value", argstable.macc or 0)
                    :done()
                    :tag("td")
                        :wikitext(styles[string.lower(argstable.ostyle or "")] or argstable.ostyle or "-")
                    :done()
                    :tag("td")
                        :wikitext(argstable.odmg or "-")
                        :attr("data-sort-value", argstable.odmg or 0)
                    :done()
                    :tag("td")
                        :wikitext(argstable.oacc or "-")
                        :attr("data-sort-value", argstable.oacc or 0)
                    :done()
            end
            
            -- Add atribute and style bonuses cells
            if not yesno(frameargs.noattr) then
	            tblrow
	                :tag("td")
	                    :addClass("attribute-value")
	                    :wikitext(argstable.armour or "-")
	                :done()
	                :tag("td")
	                    :addClass("attribute-value")
	                    :wikitext(argstable.life or "-")
	                :done()
	                :tag("td")
	                    :addClass("attribute-value")
	                    :wikitext(argstable.prayer or "-")
	                :done()
	            :done()
	        end
            if not yesno(frameargs.nostyle) then
            	tblrow
	                :tag("td")
	                    :wikitext(argstable.strength or "-")
	                    :attr("data-sort-value", argstable.strength or 0)
	                :done()
	                :tag("td")
	                    :wikitext(argstable.ranged or "-")
	                    :attr("data-sort-value", argstable.ranged or 0)
	                :done()
	                :tag("td")
	                    :wikitext(argstable.magic or "-")
	                    :attr("data-sort-value", argstable.magic or 0)
	                :done()
	        	:done()
            end
            -- Add price cell
            if yesno(frameargs.price) then
            
                -- Total price
                if (yesno(argstable.totals) and argstable.price == nil) or string.lower(argstable.price or "") == "total" then
                    if isnotempty(argstable.priceimage) then
                        tblrow
                            :tag("td")
                                :css("text-align", "right")
                                :wikitext((argstable.priceimage and ("[[File:" .. argstable.priceimage .. "]] ")) or "")
                                :tag("span")
                                    :addClass("coins coins-pos")
                                    :wikitext(AddCommas(totalPrice))
                                :done()
                            :done()
                    else
                        tblrow
                            :tag("td")
                                :css("text-align", "right")
                                :wikitext(Coins(totalPrice, false))
                            :done()
                    end
                    
                -- Empty the cell incase price2 = ge and price is not given
                elseif string.lower(argstable.price2 or "") == "ge" and argstable.price == nil then
                    tblrow
                        :tag("td")
                            :wikitext("-")
                        :done()
                        
                -- GE price, this is the default value if no price parameter was given
                elseif string.lower(argstable.price or "") == "ge" or argstable.price == nil then
                    -- Check if the item exist on the GE
                    local itemName = cleanItemName(argstable)
                    if Exchange._exists(itemName) then
                        argstable.price = Exchange._price(itemName)
                        if not yesno(argstable.dontaddtototal) then
                            totalPrice = totalPrice + argstable.price
                        end
                        tblrow
                            :tag("td")
                                :css("text-align", "right")
                                :wikitext(Coins(argstable.price, false))
                            :done()
                    elseif string.lower(argstable.price or "") == "ge" then
                        tblrow
                            :tag("td")
                                :tag("span")
                                    :css("color", "red")
                                    :wikitext("Item does not exist on the [[Grand Exchange|")
                                        :tag("span")
                                            :css("color", "darkred")
                                            :wikitext("Grand Exchange")
                                        :done()
                                    :wikitext("]]")
                                :done()
                            :done()
                    else
                        tblrow
                            :tag("td")
                                :wikitext("-")
                            :done()
                    end
                    
                -- If the price parameter is just a number
                elseif tonumber(argstable.price) ~= nil then
                    if not yesno(argstable.dontaddtototal) then
                        totalPrice = totalPrice + tonumber(argstable.price)
                    end
                    if argstable.priceimage == nil then
                        tblrow
                            :tag("td")
                                :css("text-align", "right")
                                :wikitext(Coins(tonumber(argstable.price)))
                            :done()
                    else
                        tblrow
                            :tag("td")
                                :css("text-align", "right")
                                :wikitext((argstable.priceimage and ("[[File:" .. argstable.priceimage .. "]] ")) or "")
                                :tag("span")
                                    :addClass("coins coins-pos")
                                    :wikitext(AddCommas(tonumber(argstable.price)))
                                :done()
                            :done()
                    end
                    
                -- If the price parameter is a non recognized value
                else
                    tblrow
                        :tag("td")
                            :css("text-align", "right")
                            :wikitext(argstable.price)
                        :done()
                end
            end
            
            -- Add price2 cell
            if yesno(frameargs.price2) then
            
                -- Empty the cell incase price = ge and price2 is not given or if the totals parameter is used
                if (yesno(argstable.totals) and argstable.price2 == nil) or (argstable.price2 == nil and string.lower(argstable.price or "") == "ge") then 
                    tblrow
                        :tag("td")
                            :wikitext("-")
                        :done()
                        
                -- GE price, this is the default value if no price2 parameter was given
                elseif string.lower(argstable.price2 or "") == "ge" or argstable.price2 == nil then
                	local itemName = cleanItemName(argstable)
                    -- Check if the item exists on the GE
                    if string.lower(argstable.price2 or "") == "ge" and argstable.price == nil and Exchange._exists(string.lower(itemName or ""))then
                        local GEprice2 = Exchange._price(string.lower(itemName or ""))
                        tblrow
                            :tag("td")
                                :css("text-align", "right")
                                :wikitext(Coins(GEprice2, false))
                            :done()
                            
                    -- Check if the off-hand of the item exists on the GE
                    elseif Exchange._exists("Off-hand " .. string.lower(itemName or "")) then
                        local GEprice2 = Exchange._price("Off-hand " .. string.lower(itemName or ""))
                        tblrow
                            :tag("td")
                                :css("text-align", "right")
                                :wikitext(Coins(GEprice2, false))
                            :done()

                    -- Empty the cell if the item doesn't exist on the GE and it defaulted to GEprice, else give an error
                    elseif string.lower(argstable.price2 or "") == "ge" then
                        tblrow
                            :tag("td")
                                :tag("span")
                                    :css("color", "red")
                                    :wikitext("Item does not exist on the [[Grand Exchange|")
                                        :tag("span")
                                            :css("color", "darkred")
                                            :wikitext("Grand Exchange")
                                        :done()
                                    :wikitext("]]")
                                :done()
                            :done()
                    else
                        tblrow
                            :tag("td")
                                :wikitext("-")
                            :done()
                    end

                -- If the price2 parameter is a number
                elseif tonumber(argstable.price2) ~= nil then
                    if argstable.priceimage == nil then
                        tblrow
                            :tag("td")
                                :wikitext(Coins(argstable.price2))
                            :done()
                    else
                        tblrow
                            :tag("td")
                                :css("text-align", "right")
                                :wikitext((argstable.priceimage and ("[[File:" .. argstable.priceimage .. "]] ")) or "")
                                :tag("span")
                                    :addClass("coins coins-pos")
                                    :wikitext(AddCommas(argstable.price2))
                            :done()
                    end
                    
                -- If the price parameter is a non recognized value
                else
                    tblrow
                        :tag("td")
                            :css("text-align", "right")
                            :wikitext(argstable.price2)
                        :done()
                end
            end
        -- Inforow ends here
    end
    -- Table is complete here
    
    local retval = tostring(htmltable)
    
    -- Various tracking cats to monitor errors/incorrect values
    if onmain() then
    	local cats = ""
	    if smwerror then
	    	cats = cats .. "[[Category:Pages with script errors]]"
		end
		if smwmismatch then
			cats = cats .. "[[Category:Pages with eq infotables using values that differ from SMW]]"
		end
		if totalsmismatch then
			cats = cats .. "[[Category:Pages with eq infotables having incorrect totals]]"
		end
		
		retval = retval .. cats
	end
    
    return retval
end

return p
-- </nowiki>