Documentation for this module may be created at Module:FFXII Data/doc

local getArgs = require("Dev:Arguments").getArgs
local html = mw.html
 
local p = {}
local BLADE = require "Module:BladeEngine".new(p, "Module:FFXII Data")

local _footmodule

function foot(...)
    --i think doing this means time is saved if 
    --(A) i don't use foot, and
    --(B) i use foot more than once
    if not _footmodule then _footmodule = require "Module:Foot" end
    if not table.pack then table = require "Module:Table" end
    return tostring(_footmodule.render(require "Module:Table".pack(...)))
end

function p.Weapons(frame)
    local datapage = "Module:FFXII Data/Weapons"
    local data = mw.loadData(datapage)
    args = getArgs(frame)

    local displayimage = true
    if args.displayimage and args.displayimage:lower() == "false" then
        displayimage = false
    end

    local displayaltname = true
    if args.displayaltnames and args.displayaltnames:lower() == "false" then
        displayaltnames = false
    end

    local displayversion = false
    if args.displayversion and args.displayversion:lower() == "true" then
        displayversion = true
    end
    
    --
    -- optcols are optional columns in the table. a Weapons table has some
    -- columns set up by default but some can be disabled and others can be
    -- enabled. if a column is not displayed then the stat will be mentioned
    -- in an add.info row below the columns
    --
    optcols = {
        type = true,
        formula = true,
        attack = true,
        evade = true,
        element = true,
        status = true,
        range = true,
        knockback = true,
        mp = false,
        speed = false,
        magickpower = false,
        vitality = false,
        ct = true,
        combo = false,
        critical = false,
        metal = true,
        value = true,
    }

    local columncount = 2--Name and License
    
    for k, v in pairs(optcols) do
        local showthiscolumn = v
        local showcolumnswitch = args[k .. "column"]
        if showcolumnswitch then
            if v == true and showcolumnswitch:lower() == "false" then
                showthiscolumn = false
            elseif v == false and showcolumnswitch:lower() == "true" then
                showthiscolumn = true
            end
        end
        if showthiscolumn then
            columncount = columncount + 1
        end
        optcols[k] = showthiscolumn
    end
    
    expectedvalues = {}
    --
    -- Expected values are like defaults. So if a weapons section says
    --  "all A have x B", then we can set "b expected=x" and it won't mention
    --  any time a weapon in the table has x B. if B is anything other than x
    --  it will be mentioned
    -- NOTE: This is for stats that do not have columns in the table and listed
    --  in the "other information" below the table
    --  if the value is in a column then the value will always be displayed in
    -- that column
    --
    for k, v in pairs(data.fields) do
        local thisexpectedvalue = args[k .. " expected"]
        local dt = v.datatype

        if thisexpectedvalue then
            expectedvalues[k] = (function()
                if dt and dt == "number" then
                    return tonumber(thisexpectedvalue)
                elseif dt and dt == "boolean" then
                    if thisexpectedvalue == "true" then
                        return true
                    elseif thisexpectedvalue == "false" then
                        return false
                    end
                else
                    return thisexpectedvalue
                end
            end)()
        end
    end
    
    local querydata = BLADE.select(data, args)
 
    local mdash = mw.text.decode("—", true)
    local wbr = mw.text.decode("​", true)
 
    local tbl = html.create("table")
        :addClass("FFXII article-table full-width")
    local thead = tbl:tag("tr"):addClass("a")
    thead:tag("th"):wikitext("Name")
    if optcols.type then
        thead:tag("th"):wikitext("Type")
    end if optcols.formula then
        thead:tag("th"):wikitext("Formula")
    end if optcols.attack then
        thead:tag("th"):wikitext(foot("Atk", "Attack"))
    end if optcols.evade then
        thead:tag("th"):wikitext(foot("Eva.", "Evade"))
    end if optcols.range then
        thead:tag("th"):wikitext(foot("Rng.", "Range"))
    end if optcols.knockback then
        thead:tag("th"):wikitext(foot("Knk" .. wbr .. "bck", "Knockback"))
    end if optcols.element then
        thead:tag("th"):wikitext("Element")
    end if optcols.status then
        thead:tag("th"):wikitext("Status")
    end if optcols.mp then
        thead:tag("th"):wikitext("Max MP")
    end if optcols.speed then
        thead:tag("th"):wikitext(foot("Spd", "Speed"))
    end if optcols.magickpower then
        thead:tag("th"):wikitext(foot("Mgk Pwr", "Magick Power"))
    end if optcols.vitality then
        thead:tag("th"):wikitext(foot("Vit.", "Vitality"))
    end if optcols.ct then
        thead:tag("th"):wikitext("CT")
    end if optcols.combo then
        thead:tag("th"):wikitext(foot("Cmb.", "Combo rate"))
    end if optcols.critical then
        thead:tag("th"):wikitext(foot("Crt.", "Critical rate"))
    end if optcols.metal then
        thead:tag("th"):wikitext(foot("[[Magnetize|Mtl]]", "Metal"))
    end if optcols.value then
        thead:tag("th"):wikitext(BLADE.fieldtitle(querydata, "value"))
    end
    thead:tag("th"):wikitext(BLADE.fieldtitle(querydata, "license"))

    for i=1, #querydata do
        local itm = querydata[i]

        local tr = tbl:tag("tr"):attr("id", itm.name)

        local addinfo = {}

        --NAME
        local name = BLADE.formatlink(querydata, itm, "link", "name")
 
        if displayaltname and itm.lit and itm.lit ~= itm.name then
            name = name .. "<br/>(" .. BLADE.formataltjpnname(querydata, itm, "japanese", "romaji", "lit") .. ")"
        end
        
        if displayimage and itm.image then
            name = name .. '<br/>' .. BLADE.formatfield(querydata, itm, "image"):setWidth(75)
        end
        
        if displayversion then
            local version = ""
            if itm.original and itm.zodiac then
                version = "Orig/Zodc"
            elseif itm.original then
                version = "Original"
            elseif itm.zodiac then
                version = "Zodiac"
            else
                version = "None"--this is odd
            end
            version = "<small>''(" .. version .. ")''</small>"
            name = name .. "<br/>" .. version
        end

        local headercell = tr:tag("th"):addClass("b"):wikitext(name)
        
        --TYPE
        --Maybe want to add links
        if optcols.type then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, "type"))
            :wikitext(BLADE.formatfield(querydata, itm, "type"))
        elseif (expectedvalues.type) ~= itm.type then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, "type") .. ":''' " .. BLADE.formatfield(querydata, itm, "type"))
        end
        
        --FORMULA
        --Maybe want to add links
        if optcols.formula then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, "formula"))
            :wikitext(BLADE.formatfield(querydata, itm, "formula"))
        elseif (expectedvalues.formula) ~= itm.formula then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, "formula") .. ":''' " .. BLADE.formatfield(querydata, itm, "formula"))
        end
        
        --ATTACK
        if optcols.attack then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, "attack"))
            :wikitext(BLADE.formatfield(querydata, itm, "attack"))
        elseif (expectedvalues.attack) ~= itm.attack then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, "attack") .. ":''' " .. BLADE.formatfield(querydata, itm, "attack"))
        end
        
        --EVADE
        if optcols.evade then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, "evade"))
            :wikitext(BLADE.formatfield(querydata, itm, "evade"))
        elseif (expectedvalues.evade or 0) ~= itm.evade then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, "evade") .. ":''' " .. BLADE.formatfield(querydata, itm, "evade"))
        end

        --RANGE
        if optcols.range then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, "range"))
            :wikitext(BLADE.formatfield(querydata, itm, "range"))
        elseif (expectedvalues.range or 1) ~= itm.range then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, "range") .. ":''' " .. BLADE.formatfield(querydata, itm, "range"))
        end

        --KNOCKBACK
        if optcols.knockback then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, "knockback"))
            :wikitext(BLADE.formatfield(querydata, itm, "knockback"))
        elseif (expectedvalues.knockback or 0) ~= itm.knockback then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, "knockback") .. ":''' " .. BLADE.formatfield(querydata, itm, "knockback"))
        end

        --ELEMENT
        local elements = { "Fire", "Ice", "Thunder", "Earth", "Wind", "Water", "Holy", "Dark" }
        local elempage = "[[Final Fantasy XII elements#%s|%s]]"
        
        local effectheader = "'''Effect:'''"
        local potencyheader = "'''Potency:'''"
        potencyheader = foot(potencyheader, "Spells of this element deal 50% more damage")

        if optcols.element then
            local effect = {}
            local potency = {}
            for i=1, #elements do
                local elem = elements[i]
                local key = elem:lower()
                if itm["effect" .. key] then
                    effect[#effect+1] = elempage:format(elem, elem)
                end
                if itm["potency" .. key] then
                    potency[#potency+1] = elempage:format(elem, elem)
                end
            end
            local elemcell = {}
            if effect[1] then
                elemcell[1] = effectheader .. " " .. table.concat(effect, ", ")
            end
            if potency[1] then
                elemcell[#elemcell+1] = potencyheader .. " " .. table.concat(potency, ", ")
            end
            if elemcell[1] then
                elemcell = table.concat(elemcell, "<br/>")
            else
                elemcell = mdash
            end
            
            tr:tag("td")
            :attr(BLADE.cellformat("string", elemcell == mdash and
                "default"
            or
                "longtext"
            ))
            :wikitext(elemcell)
        else
            for i=1, #elements do
                local elem = elements[i]
                local key = elem:lower()
                local effectkey = "effect" .. key
                local potencykey = "potency" .. key
                if itm[effectkey] and not expectedvalues[effectkey] then
                    addinfo[#addinfo+1] = effectheader .. " " .. elempage:format(elem, elem)
                end
                if itm[potencykey] and not expectedvalues[potencykey] then
                    addinfo[#addinfo+1] = potencyheader .. " " .. elempage:format(elem, elem)
                end
            end 
        end

        --STATUS
        local statuses = { "KO", "Petrify", "Stop", "Doom", "Confuse", "Disease", "Slow", "Disable", "Immobilize", "Silence", "Blind", "Poison", "Oil", "Sap", "Reflect", "Protect", "Shell", "Haste", "Bravery", "Faith", "Invisible", "Regen", "Float", "Berserk", "Bubble", "Libra" }
        local statuspage = "[[Final Fantasy XII elements#%s|%s]]"

        local onhitheader = "'''On Hit:'''"
        local equipheader = "'''Equip:'''"

        local onhitrate = itm.onhitrate and BLADE.formatfield(querydata, itm, "onhitrate")

        if optcols.status then
            local onhit = {}
            local equip = {}
            for i=1, #statuses do
                local st = statuses[i]
                local key = st:lower()
                if itm["onhit" .. key] then
                    onhit[#onhit+1] = statuspage:format(st, st)
                    .. " (" .. onhitrate ..")"
                end
                if itm["equip" .. key] then
                    equip[#equip+1] = statuspage:format(st, st)
                end
            end
            local stcell = {}
            if onhit[1] then
                stcell[1] = onhitheader .. " " .. table.concat(onhit, ", ")
            end
            if equip[1] then
                stcell[#stcell+1] = equipheader .. " " .. table.concat(equip, ", ")
            end
            if stcell[1] then
                stcell = table.concat(stcell, "<br/>")
            else
                stcell = mdash
            end
            
            tr:tag("td")
            :attr(BLADE.cellformat("string", stcell == mdash and
                "default"
            or
                "longtext"
            ))
            :wikitext(stcell)
        else
            for i=1, #statuses do
                local st = statuses[i]
                local key = st:lower()
                local onhitkey = "onhit" .. key
                local equipkey = "equip" .. key
                if itm[onhitkey] and not expectedvalues[onhitkey] then
                    addinfo[#addinfo+1] = onhitheader .. " " .. statuspage:format(st, st)
                end
                if itm[equipkey] and not expectedvalues[equipkey] then
                    addinfo[#addinfo+1] = equipheader .. " " .. statuspage:format(st, st)
                end
            end 
        end

        --MP
        local key = "mp"
        if optcols[key] then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, key))
            :wikitext(BLADE.formatfield(querydata, itm, key))
        elseif (expectedvalues[key] or 0) ~= itm[key] then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, key) .. ":''' " .. BLADE.formatfield(querydata, itm, key))
        end
        
        --Speed
        local key = "speed"
        if optcols[key] then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, key))
            :wikitext(BLADE.formatfield(querydata, itm, key))
        elseif (expectedvalues[key] or 0) ~= itm[key] then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, key) .. ":''' " .. BLADE.formatfield(querydata, itm, key))
        end

        --Magick Power
        local key = "magickpower"
        if optcols[key] then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, key))
            :wikitext(BLADE.formatfield(querydata, itm, key))
        elseif (expectedvalues[key] or 0) ~= itm[key] then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, key) .. ":''' " .. BLADE.formatfield(querydata, itm, key))
        end

        --Vitality
        local key = "vitality"
        if optcols[key] then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, key))
            :wikitext(BLADE.formatfield(querydata, itm, key))
        elseif (expectedvalues[key] or 0) ~= itm[key] then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, key) .. ":''' " .. BLADE.formatfield(querydata, itm, key))
        end

        --CT
        local key = "ct"
        if optcols[key] then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, key))
            :wikitext(BLADE.formatfield(querydata, itm, key))
        elseif (expectedvalues[key] or 0) ~= itm[key] then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, key) .. ":''' " .. BLADE.formatfield(querydata, itm, key))
        end

        --Combo
        local key = "combo"
        if optcols[key] then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, key))
            :wikitext(BLADE.formatfield(querydata, itm, key))
        elseif (expectedvalues[key] or 0) ~= itm[key] then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, key) .. ":''' " .. BLADE.formatfield(querydata, itm, key))
        end

        --Critical
        local key = "critical"
        if optcols[key] then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, key))
            :wikitext(BLADE.formatfield(querydata, itm, key))
        elseif (expectedvalues[key] or 0) ~= itm[key] then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, key) .. ":''' " .. BLADE.formatfield(querydata, itm, key))
        end

        --Metal
        local key = "metal"
        if optcols[key] then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, key))
            :wikitext(BLADE.formatfield(querydata, itm, key))
        elseif (expectedvalues[key] or 0) ~= itm[key] then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, key) .. ":''' " .. BLADE.formatfield(querydata, itm, key))
        end

        --Value
        local key = "value"
        local canbebought = not not itm.shop
        local canbesold = not itm.unsellable
        local buy = "'''Buy: '''"
        if canbebought then
            buy = buy .. itm.value
        else
            buy = buy .. "Cannot be purchased"
        end
        local sell = "'''Sell: '''"
        if canbesold then
            sell = sell .. itm.value/2
        else
            sell = sell .. "Cannot be sold"
        end
        
        if optcols[key] then
            local value = BLADE.formatfield(querydata, itm, key)
            value = foot(value, buy .. "<br>" .. sell)
            if not canbebought then value = "(" .. value .. ")" end

            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, key))
            :wikitext(value)
        elseif (expectedvalues[key] or 0) ~= itm[key] then
            if canbebought then
                table.insert(addinfo, "'''Buy:''' " .. buy)
            end
            if canbesold then
                table.insert(addinfo, "'''Sell:''' " .. sell)
            end
        end

        --LICENSE
        local licenselink = "License Board"
        if itm.original then
            licenselink = licenselink .. "/Original"
        end
        licenselink = "[[" .. licenselink .. "#%s|%s]]"

        local license = mdash
        if itm.license then
            license = itm.license
            license = licenselink:format(license, license)
        end
        
        tr:tag("td")
        :attr(BLADE.cellformatfield(querydata, key))
        :wikitext(license)

        --ADDITIONAL INFO
        if itm.nomodel and expectedvalues.nomodel ~= true then
            table.insert(addinfo, "Weapon is invisible")
        end

        if itm.onhitnodamage and expectedvalues.onhitnodamage ~= true then
            table.insert(addinfo, "Weapon does not inflict damage when On Hit status lands")
        end

        if itm.unsellable and expectedvalues.unsellable ~= true then
            table.insert(addinfo, "Weapon cannot be sold")
        end

        --OBTAINING DATA
        local obtain = {}
        local obtainfields = { "shop", "bazaar", "treasure", "drop", "steal", "poach", "hunt", "reward", "initial" }
        for i=1, #obtainfields do
            local obf = obtainfields[i]
            if itm[obf] then
                local obfheader = BLADE.fieldtitle(querydata, obf)
                table.insert(obtain, "'''" .. obfheader .. "''': " .. itm[obf])
            end
        end
        
        local rowcount = 1
        if obtain[1] then rowcount = 2 end
        if addinfo[1] then rowcount = rowcount + 1 end

        headercell:attr("rowspan", rowcount)
        
        local colspan = columncount - 1
        
        if addinfo[1] then
            tbl:tag("tr"):tag("td")
            :attr(BLADE.cellformat("string", "longtext"))
            :attr("colspan", colspan)
            :wikitext(table.concat(addinfo, "; "))
        end

        
        if obtain[1] then
            tbl:tag("tr"):tag("td")
            :attr(BLADE.cellformat("string", "longtext"))
            :attr("colspan", colspan)
            :wikitext(table.concat(obtain, "<br/>"))
        end
    end

    return html.create("div"):node(BLADE.dnav(data, datapage)):node(tbl)
end

function p.Armor(frame)
    local datapage = "Module:FFXII Data/Armor"
    local data = mw.loadData(datapage)
    args = getArgs(frame)

    local displayimage = true
    if args.displayimage and args.displayimage:lower() == "false" then
        displayimage = false
    end

    local displayaltname = true
    if args.displayaltnames and args.displayaltnames:lower() == "false" then
        displayaltnames = false
    end

    local displayversion = false
    if args.displayversion and args.displayversion:lower() == "true" then
        displayversion = true
    end
    
    --
    -- optcols are optional columns in the table. an Armor table has some
    -- columns set up by default but some can be disabled and others can be
    -- enabled. if a column is not displayed then the stat will be mentioned
    -- in an add.info row below the columns
    --
    optcols = {
        slot = true,
        type = true,
        defense = true,
        magickresist = true,
        evade = true,
        magickevade = true,
        element = true,
        equip = true,
        hp = false,
        mp = false,
        strength = false,
        magickpower = false,
        vitality = false,
        speed = false,
        metal = true,
        value = true
    }

    local columncount = 2--Name and License
    
    for k, v in pairs(optcols) do
        local showthiscolumn = v
        local showcolumnswitch = args[k .. "column"]
        if showcolumnswitch then
            if v == true and showcolumnswitch:lower() == "false" then
                showthiscolumn = false
            elseif v == false and showcolumnswitch:lower() == "true" then
                showthiscolumn = true
            end
        end
        if showthiscolumn then
            columncount = columncount + 1
        end
        optcols[k] = showthiscolumn
    end
    
    expectedvalues = {}
    --
    -- Expected values are like defaults. So if an armor section says
    --  "all A have x B", then we can set "b expected=x" and it won't mention
    --  any time an armor in the table has x B. if B is anything other than x
    --  it will be mentioned
    -- NOTE: This is for stats that do not have columns in the table and listed
    --  in the "other information" below the table
    --  if the value is in a column then the value will always be displayed in
    -- that column
    --
    for k, v in pairs(data.fields) do
        local thisexpectedvalue = args[k .. " expected"]
        local dt = v.datatype

        if thisexpectedvalue then
            expectedvalues[k] = (function()
                if dt and dt == "number" then
                    return tonumber(thisexpectedvalue)
                elseif dt and dt == "boolean" then
                    if thisexpectedvalue == "true" then
                        return true
                    elseif thisexpectedvalue == "false" then
                        return false
                    end
                else
                    return thisexpectedvalue
                end
            end)()
        end
    end
    
    local querydata = BLADE.select(data, args)
 
    local mdash = mw.text.decode("&mdash;", true)
    local wbr = mw.text.decode("&#8203;", true)
 
    local tbl = html.create("table")
        :addClass("FFXII article-table full-width")
    local thead = tbl:tag("tr"):addClass("a")
    thead:tag("th"):wikitext("Name")
    if optcols.slot then
        thead:tag("th"):wikitext(foot("Slot", "Body part armor is equipped to"))
    end if optcols.type then
        thead:tag("th"):wikitext("Type")
    end if optcols.defense then
        thead:tag("th"):wikitext(foot("Def.", "Defense"))
    end if optcols.magickresist then
        thead:tag("th"):wikitext(foot("MRes.", "Magick Resist"))
    end if optcols.evade then
        thead:tag("th"):wikitext(foot("Eva.", "Evade"))
    end if optcols.magickevade then
        thead:tag("th"):wikitext(foot("MEva.", "Magick Evade"))
    end if optcols.element then
        thead:tag("th"):wikitext("Element")
    end if optcols.equip then
        thead:tag("th"):wikitext("Equip")
    end if optcols.hp then
        thead:tag("th"):wikitext("Max HP")
    end if optcols.mp then
        thead:tag("th"):wikitext("Max MP")
    end if optcols.strength then
        thead:tag("th"):wikitext(foot("Str.", "Strength"))
    end if optcols.magickpower then
        thead:tag("th"):wikitext(foot("Mgk Pwr", "Magick Power"))
    end if optcols.vitality then
        thead:tag("th"):wikitext(foot("Vit.", "Vitality"))
    end if optcols.speed then
        thead:tag("th"):wikitext(foot("Spd", "Speed"))
    end if optcols.metal then
        thead:tag("th"):wikitext(foot("[[Magnetize|Mtl]]", "Metal"))
    end if optcols.value then
        thead:tag("th"):wikitext(BLADE.fieldtitle(querydata, "value"))
    end
    thead:tag("th"):wikitext(BLADE.fieldtitle(querydata, "license"))

    for i=1, #querydata do
        local itm = querydata[i]

        local tr = tbl:tag("tr"):attr("id", itm.name)

        local addinfo = {}

        --NAME
        local name = BLADE.formatlink(querydata, itm, "recurring", "name")
 
        if displayaltname and itm.lit and itm.lit ~= itm.name then
            name = name .. "<br/>(" .. BLADE.formataltjpnname(querydata, itm, "japanese", "romaji", "lit") .. ")"
        end
        
        if displayimage and (itm.image or itm.artwork) then
            local imagefield = itm.image and "image" or "artwork"
            name = name .. '<br/>' .. BLADE.formatfield(querydata, itm, imagefield):setWidth(75)
        end
        
        if displayversion then
            local version = ""
            if itm.original and itm.zodiac then
                version = "Orig/Zodc"
            elseif itm.original then
                version = "Original"
            elseif itm.zodiac then
                version = "Zodiac"
            else
                version = "None"--this is odd
            end
            version = "<small>''(" .. version .. ")''</small>"
            name = name .. "<br/>" .. version
        end

        local headercell = tr:tag("th"):addClass("b"):wikitext(name)
        
        --SLOT
        local key = "slot"
        if optcols[key] then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, key))
            :wikitext(BLADE.formatfield(querydata, itm, key))
        elseif (expectedvalues[key]) ~= itm[key] then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, key) .. ":''' " .. BLADE.formatfield(querydata, itm, key))
        end

        --TYPE
        --Maybe want to add links
        local key = "type"
        if optcols[key] then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, key))
            :wikitext(BLADE.formatfield(querydata, itm, key))
        elseif (expectedvalues[key]) ~= itm[key] then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, key) .. ":''' " .. BLADE.formatfield(querydata, itm, key))
        end
        
        --DEFENSE
        local key = "defense"
        if optcols[key] then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, key))
            :wikitext(BLADE.formatfield(querydata, itm, key))
        elseif (expectedvalues[key] or 0) ~= itm[key] then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, key) .. ":''' " .. BLADE.formatfield(querydata, itm, key))
        end

        --MAGICK RESIST
        local key = "magickresist"
        if optcols[key] then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, key))
            :wikitext(BLADE.formatfield(querydata, itm, key))
        elseif (expectedvalues[key] or 0) ~= itm[key] then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, key) .. ":''' " .. BLADE.formatfield(querydata, itm, key))
        end

        --EVADE
        local key = "evade"
        if optcols[key] then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, key))
            :wikitext(BLADE.formatfield(querydata, itm, key))
        elseif (expectedvalues[key] or 0) ~= itm[key] then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, key) .. ":''' " .. BLADE.formatfield(querydata, itm, key))
        end

        --MAGICK EVADE
        local key = "magickevade"
        if optcols[key] then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, key))
            :wikitext(BLADE.formatfield(querydata, itm, key))
        elseif (expectedvalues[key] or 0) ~= itm[key] then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, key) .. ":''' " .. BLADE.formatfield(querydata, itm, key))
        end

        --ELEMENT
        local elements = { "Fire", "Ice", "Thunder", "Earth", "Wind", "Water", "Holy", "Dark" }
        local elempage = "[[Final Fantasy XII elements#%s|%s]]"
        
        local potencyheader = "'''Potency:'''"
        
        local receipttypes = { "Normal", "Half", "Absorb", "Weak", "Immune" }
        local receiptheaders = {}
        potencyheader = foot(potencyheader, "Spells of this element deal 50% more damage")

        local receipt = {}
        local potency = {}
        for i=1, #receipttypes do
            local thistype = receipttypes[i]
            receiptheaders[thistype] = "'''" .. thistype .. ":'''"
            receipt[thistype] = {}
        end
        for i=1, #elements do
            local elem = elements[i]
            local key = elem:lower()

            for j=1, #receipttypes do
                local thistype = receipttypes[j]
                if itm[key] == thistype
                and (expectedvalues[key] or "Normal") ~= thistype then
                    receipt[thistype][#receipt[thistype]+1] = elempage:format(elem, elem)
                    --this is for the rowspan display which displays
                    --elements in order regardless of receipt type
                    receipt[i] = { thistype, elempage }

                    --elem cannot have multiple receipt types
                    break
                end
            end
            if itm["potency" .. key] and not expectedvalues["potency" .. key] then
                potency[#potency+1] = elempage:format(elem, elem)
            end
        end
    
        if optcols.element then
            local elemcell = {}
            if potency[1] then
                elemcell[#elemcell+1] = potencyheader .. " " .. table.concat(potency, ", ")
            end
            for i=1, #receipttypes do
                local thistype = receipttypes[i]
                if receipt[thistype][1] then
                    elemcell[#elemcell+1] = receiptheaders[thistype] .. " " .. table.concat(receipt[thistype], ", ")
                end
            end
            if elemcell[1] then
                elemcell = table.concat(elemcell, "<br/>")
            else
                elemcell = mdash
            end
            
            tr:tag("td")
            :attr(BLADE.cellformat("string", elemcell == mdash and
                "default"
            or
                "longtext"
            ))
            :wikitext(elemcell)
        else
            for i=1, #elements do
                local elem = elements[i]
                local key = elem:lower()

                local potencykey = "potency" .. key

                --this is kinda redundant
                if itm[potencykey] and not expectedvalues[potencykey] then
                    addinfo[#addinfo+1] = potencyheader .. " " .. table.remove(potency, 1)
                end
                if receipt[i] then
                    local thistype = receipt[i][1]
                    local thiselem = receipt[i][2]
                    local thisheader = receiptheaders[thistype]
                    addinfo[#addinfo+1] = thisheader .. " " .. thiselem
                end
            end 
        end

        --STATUS
        local statuses = { "KO", "Petrify", "Stop", "Doom", "Confuse", "Disease", "Slow", "Disable", "Immobilize", "Silence", "Blind", "Poison", "Oil", "Sap", "Reflect", "Protect", "Shell", "Haste", "Bravery", "Faith", "Invisible", "Regen", "Float", "Berserk", "Bubble", "Libra" }
        local statuspage = "[[Final Fantasy XII elements#%s|%s]]"

        local equipheader = "'''Equip:'''"

        local equip = {}
        for i=1, #statuses do
            local st = statuses[i]
            local key = st:lower()
            if itm["equip" .. key] then
                equip[#equip+1] = statuspage:format(st, st)
            end
        end

        if optcols.equip then
            local stcell
            if equip[1] then
                stcell = equipheader .. " " .. table.concat(equip, ", ")
            else
                stcell = mdash
            end
            
            tr:tag("td")
            :attr(BLADE.cellformat("string", stcell == mdash and
                "default"
            or
                "longtext"
            ))
            :wikitext(stcell)
        else
            for i=1, #equip do
                addinfo[#addinfo+1] = equipheader .. " " .. equip[i]
            end 
        end

        --HP
        local key = "hp"
        if optcols[key] then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, key))
            :wikitext(BLADE.formatfield(querydata, itm, key))
        elseif (expectedvalues[key] or 0) ~= itm[key] then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, key) .. ":''' " .. BLADE.formatfield(querydata, itm, key))
        end
        
        --MP
        local key = "mp"
        if optcols[key] then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, key))
            :wikitext(BLADE.formatfield(querydata, itm, key))
        elseif (expectedvalues[key] or 0) ~= itm[key] then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, key) .. ":''' " .. BLADE.formatfield(querydata, itm, key))
        end
        
        --Strength
        local key = "strength"
        if optcols[key] then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, key))
            :wikitext(BLADE.formatfield(querydata, itm, key))
        elseif (expectedvalues[key] or 0) ~= itm[key] then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, key) .. ":''' " .. BLADE.formatfield(querydata, itm, key))
        end       
        
        --Magick Power
        local key = "magickpower"
        if optcols[key] then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, key))
            :wikitext(BLADE.formatfield(querydata, itm, key))
        elseif (expectedvalues[key] or 0) ~= itm[key] then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, key) .. ":''' " .. BLADE.formatfield(querydata, itm, key))
        end
        
        --Vitality
        local key = "vitality"
        if optcols[key] then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, key))
            :wikitext(BLADE.formatfield(querydata, itm, key))
        elseif (expectedvalues[key] or 0) ~= itm[key] then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, key) .. ":''' " .. BLADE.formatfield(querydata, itm, key))
        end

        --Speed
        local key = "speed"
        if optcols[key] then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, key))
            :wikitext(BLADE.formatfield(querydata, itm, key))
        elseif (expectedvalues[key] or 0) ~= itm[key] then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, key) .. ":''' " .. BLADE.formatfield(querydata, itm, key))
        end

        --Metal
        local key = "metal"
        if optcols[key] then
            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, key))
            :wikitext(BLADE.formatfield(querydata, itm, key))
        elseif (expectedvalues[key] or 0) ~= itm[key] then
            table.insert(addinfo, "'''" .. BLADE.fieldtitle(querydata, key) .. ":''' " .. BLADE.formatfield(querydata, itm, key))
        end

        --Value
        local key = "value"
        local canbebought = not not itm.shop
        local canbesold = not itm.unsellable
        local buy = "'''Buy: '''"
        if canbebought then
            buy = buy .. itm.value
        else
            buy = buy .. "Cannot be purchased"
        end
        local sell = "'''Sell: '''"
        if canbesold then
            sell = sell .. itm.value/2
        else
            sell = sell .. "Cannot be sold"
        end
        
        if optcols[key] then
            local value = BLADE.formatfield(querydata, itm, key)
            value = foot(value, buy .. "<br>" .. sell)
            if not canbebought then value = "(" .. value .. ")" end

            tr:tag("td")
            :attr(BLADE.cellformatfield(querydata, key))
            :wikitext(value)
        elseif (expectedvalues[key] or 0) ~= itm[key] then
            if canbebought then
                table.insert(addinfo, "'''Buy:''' " .. buy)
            end
            if canbesold then
                table.insert(addinfo, "'''Sell:''' " .. sell)
            end
        end

        --LICENSE
        local licenselink = "License Board"
        if itm.original then
            licenselink = licenselink .. "/Original"
        end
        licenselink = "[[" .. licenselink .. "#%s|%s]]"

        local license = mdash
        if itm.license then
            license = itm.license
            license = licenselink:format(license, license)
        end
        
        tr:tag("td")
        :attr(BLADE.cellformatfield(querydata, key))
        :wikitext(license)

        --ADDITIONAL INFO
        if itm.counter then
            table.insert(addinfo, "'''Counter''': " .. querydata.fields["counter"].description)
        end

        if itm.improvedcounter then
            table.insert(addinfo, "'''Improved Counter''': " .. querydata.fields["improvedcounter"].description)
        end

        if itm.nomodel then
            table.insert(addinfo, "Armor is invisible")
        end

        if itm.unsellable then
            table.insert(addinfo, "Armor cannot be sold")
        end

        --OBTAINING DATA
        local obtain = {}
        local obtainfields = { "shop", "bazaar", "treasure", "drop", "steal", "poach", "hunt", "reward", "initial" }
        for i=1, #obtainfields do
            local obf = obtainfields[i]
            if itm[obf] then
                local obfheader = BLADE.fieldtitle(querydata, obf)
                table.insert(obtain, "'''" .. obfheader .. "''': " .. itm[obf])
            end
        end
        
        local rowcount = 1
        if obtain[1] then rowcount = 2 end
        if addinfo[1] then rowcount = rowcount + 1 end

        headercell:attr("rowspan", rowcount)
        
        local colspan = columncount - 1
        
        if addinfo[1] then
            tbl:tag("tr"):tag("td")
            :attr(BLADE.cellformat("string", "longtext"))
            :attr("colspan", colspan)
            :wikitext(table.concat(addinfo, "; "))
        end

        
        if obtain[1] then
            tbl:tag("tr"):tag("td")
            :attr(BLADE.cellformat("string", "longtext"))
            :attr("colspan", colspan)
            :wikitext(table.concat(obtain, "<br/>"))
        end
    end

    return html.create("div"):node(BLADE.dnav(data, datapage)):node(tbl)
end

function p.onhitstatuses(frame)
    local args = getArgs(frame)

    --because this can apply to Weapons and Ammuntion
    local subpage = args[1]

    local datapage = "Module:FFXII Data/" .. subpage
    local data = mw.loadData(datapage)

    args[1] = args[2]

    local querydata = BLADE.select(data, args)
    
    local onhitstatuses = statuslist(querydata[1], "onhit")

    for i=1, #onhitstatuses do
        onhitstatuses[i] = onhitstatuses[i] .. " (" .. querydata[1].onhitrate .. "%)"
    end
    
    return table.concat(onhitstatuses, "; ")
end

function p.equipstatuses(frame)
    local args = getArgs(frame)

    local subpage = args[1]

    local datapage = "Module:FFXII Data/" .. subpage
    local data = mw.loadData(datapage)

    args[1] = args[2]

    local querydata = BLADE.select(data, args)
    
    return table.concat(statuslist(querydata[1], "equip"), "; ")
end

function p.effectelements(frame)
    local args = getArgs(frame)

    local subpage = args[1]

    local datapage = "Module:FFXII Data/" .. subpage
    local data = mw.loadData(datapage)

    args[1] = args[2]

    local querydata = BLADE.select(data, args)
    
    return table.concat(elementlist(querydata[1], "effect"), "; ")
end

function p.potencyelements(frame)
    local args = getArgs(frame)

    --because this can apply to Weapons and Ammuntion
    local subpage = args[1]

    local datapage = "Module:FFXII Data/" .. subpage
    local data = mw.loadData(datapage)

    args[1] = args[2]

    local querydata = BLADE.select(data, args)
    
    return table.concat(elementlist(querydata[1], "potency"), "; ")
end


function statuslist(itm, prefix)
    local statuses = { "KO", "Petrify", "Stop", "Doom", "Confuse", "Disease", "Slow", "Disable", "Immobilize", "Silence", "Blind", "Poison", "Oil", "Sap", "Reflect", "Protect", "Shell", "Haste", "Bravery", "Faith", "Invisible", "Regen", "Float", "Berserk", "Bubble", "Libra" }
    local statuspage = "[[Final Fantasy XII elements#%s|%s]]"

    return searchlist(itm, prefix, statuses, statuspage)
end

function elementlist(itm, prefix)
    local elements = { "Fire", "Ice", "Thunder", "Earth", "Wind", "Water", "Holy", "Dark" }
    local elempage = "[[Final Fantasy XII elements#%s|%s]]"
    return searchlist(itm, prefix, elements, elempage)
end

function searchlist(itm, prefix, array, format)
    local list = {}
    for i=1, #array do
        if itm[prefix .. array[i]:lower()] then
            list[#list+1] = format:gsub("%%s", array[i], nil, true)
        end
    end
    return list
end

function getlink_func(subpage, args, defaultlinkformat, defaultdisplayfield)
    local datapage = "Module:FFXII Data/" .. subpage
    local data = mw.loadData(datapage)
    

    local querydata = BLADE.select(data, args)

    local result = querydata[1]

    local displayfield = args.textfield or defaultdisplayfield or "name"

    local displaytext = args.text or result[displayfield]
    local pagelink = result.link

    if not pagelink then
        if not defaultlinkformat then return displaytext end
        pagelink = defaultlinkformat:format(result.name)
    end
    
    return "[[" .. pagelink .. "|" .. displaytext .. "]]"

end

function getpage_func(subpage, args, defaultlinkformat)
    local datapage = "Module:FFXII Data/" .. subpage
    local data = mw.loadData(datapage)
    

    local querydata = BLADE.select(data, args)

    local result = querydata[1]

    local pagelink = result.link
    
    if not pagelink then
        if not defaultlinkformat then return "" end
        pagelink = defaultlinkformat:format(result.name)
    end
    
    return pagelink

end

function p.weaponpage(frame)
    local args = getArgs(frame)
    return getpage_func("Weapons", args, "Final Fantasy XII weapons#%s")
end

function p.weaponlink(frame)
    local args = getArgs(frame)
    return getlink_func("Weapons", args, "Final Fantasy XII weapons#%s", "name")
end


return p
Community content is available under CC-BY-SA unless otherwise noted.