Module:Sandbox/User:Manfegor/Calc

From WIDEVERSE Wiki
Revision as of 07:11, 27 August 2021 by en>Manfegor
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Documentation for this module may be created at Module:Sandbox/User:Manfegor/Calc/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
			
			if (isempty(frameargs.general) or not yesno(frameargs.general)) then
				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
					mw.log(smwname)
					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
    	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>