RuneScape Wiki
mNo edit summary
mNo edit summary
Line 843: Line 843:
 
--images = peLink(ourIcon, mw.text.split(T.name, "<")[1], ourTitle, T.iconSize)
 
--images = peLink(ourIcon, mw.text.split(T.name, "<")[1], ourTitle, T.iconSize)
 
else
 
else
--images = imageLink{file=mw.text.split(T.name, "<")[1],image=ourIcon}
+
images = imageLink{file=mw.text.split(T.name, "<")[1],image=ourIcon}
images = peLink(ourIcon, mw.text.split(T.name, "<")[1], ourTitle)
+
--images = peLink(ourIcon, mw.text.split(T.name, "<")[1], ourTitle)
 
end
 
end
   
Line 868: Line 868:
 
if params.ext then ext = params.ext end
 
if params.ext then ext = params.ext end
 
-- param.iconSize sets icon size if using a non-icon sized image.
 
-- param.iconSize sets icon size if using a non-icon sized image.
-- Replace this if you'd like to set all images to the same size (eg: 30px) without all the extra coding
 
   
 
if params.alt then
 
if params.alt then
Line 941: Line 940:
   
 
-- This is a simplified implementation of Template:Plink
 
-- This is a simplified implementation of Template:Plink
  +
-- Needs an image-only return value
 
function pLink(a)
 
function pLink(a)
 
return "[[File:" .. a .. ".png|link=" .. a .. "]]&nbsp;[[" .. a .. "|" .. a .. "]]"
 
return "[[File:" .. a .. ".png|link=" .. a .. "]]&nbsp;[[" .. a .. "|" .. a .. "]]"
Line 946: Line 946:
   
 
-- An extended implementation of pLink
 
-- An extended implementation of pLink
  +
-- Needs an image-only return value
 
function peLink(file, link, title)
 
function peLink(file, link, title)
 
return "[[File:" .. file .. ".png|link=" .. link .. "]]&nbsp;[[" .. link .. "|" .. title .. "]]"
 
return "[[File:" .. file .. ".png|link=" .. link .. "]]&nbsp;[[" .. link .. "|" .. title .. "]]"

Revision as of 21:58, 6 May 2018

Documentation for this module may be created at Module:Skill calc/eltGenerator/doc

-- <pre>
local commas        = require('Module:Addcommas')._add
local tables        = require('Module:Tables')
local coins         = require('Module:Coins')._amount
local currency      = require('Module:Currency')._amount
local numbers       = require('Module:Number')._round

local eltData = {}

--[=[ 
        Note: Once all existing calculators have been converted, this Module will be cleaned
              up to remove any spaghetti code.


Generates a No profit, Purely Loss skill table
skills: Construction, Firemaking, Prayer
Inputs:
    v           data from caller
    unitExp     experience per iteration
    needed      required iterations for goal
    fileName    page location
    cost        cost per iteration
    args        additional parameters from caller
returns: 
    Table of data using proper elts based on skill
--]=]
function eltData.generate_NoProfitLoss(frame)
    local T           = frame.args[1]
    local unitExp     = frame.args[2]
    local needed      = frame.args[3]
    local fileName    = frame.args[4]
    local cost        = frame.args[5]
    local eltArgs     = frame.args[6]
    local productCost = frame.args[7]
    local currLv      = frame.args[8]
    local memb        = '<sub title="Members only" style="cursor:help; margin-left:3px;">(m)</sub>'
    local images, links

    -- Set default currency settings, then determine if alternative used
    local dispCurr = "int"
    local dispCurr2 = "int"
    if T.currency then dispCurr = T.currency end
    if T.currency2 then dispCurr2 = T.currency2 end

    -- Check for multiple images
    -- This occurs when multiple materials are required
    if T.multi then
        images  = 
                    imageLink{file=mw.text.split(T.multi[1], "<")[1],image=T.multi[1]},
                    imageLink{file=mw.text.split(T.multi[2], "<")[1],image=T.multi[2]}
        links   =
                    '[[' .. mw.text.split(T.multi[1], "<")[1] .. ']]',
                    '[[' .. mw.text.split(T.multi[2], "<")[1] .. ']]'
    -- Single images only at then
    else
        -- Set the image location
        -- Default with using our page for the icon
        local ourIcon = mw.text.split(fileName, "<")[1]

        -- Check for flatpacks and adjust
        if eltArgs.disp == "Flatpacks" then ourIcon = ourIcon .. " (flatpack)" end

        -- Check if we specified an image location and make adjustments
        if T.image then ourIcon = mw.text.split(T.image, "<")[1] end
        if T.icon then ourIcon = mw.text.split(T.icon, "<")[1] end

        -- Check if the icon has been modified
        if T.iconSize then
            images = imageLink{file=mw.text.split(T.name, "<")[1],image=ourIcon,iconSize=T.iconSize}
        else
            images = imageLink{file=mw.text.split(T.name, "<")[1],image=ourIcon}
        end

        -- Set the item's [link]
        -- Default with using the item's name
        local ourTitle = mw.text.split(T.name, "<")[1]

        -- Check if we specified a page location
        if T.title then ourTitle = T.title end

        links  = '[[' .. mw.text.split(T.name, "<")[1] .. '|' .. ourTitle .. ']]'
    end

    -- Set non-link text, if any
    if T.sLink then links = T.sLink .. " " .. links end
    if T.eLink then links = links .. " " .. T.eLink end

    -- Check for Members only
    if T.mem == 1  then links = links .. memb end

    -- Start here and build the elt down through conditionals
    elts =
    {
        images,
        links
    }

    -- Prayer needs an override since it is missing parts
    if eltArgs.skill == "Prayer" then
        table.insert(elts, 3, commas(unitExp, 1))
        table.insert(elts, 4, commas(needed))
        table.insert(elts, 5, coins(cost * needed))
        if not (eltArgs.disp == "Urns") then
            table.insert(elts, 6, coins(string.format("%.2f", (cost / unitExp), 1))) end
    else
        table.insert(elts, 3, numbers(T.level)) -- T.level should be present for all of these

        if eltArgs.disp == "Rooms" then
            table.insert(elts, 4, coins(T.coins))
        else
            --table.insert(elts, 4, printCoins(unitExp, "int", currLv, T.level))
            table.insert(elts, 4, commas(unitExp, 1))
            if (eltArgs.skill == "Construction" and eltArgs.disp == "Milestones") then
                if T.coins then
                        table.insert(elts, 5, 
                    "<div style='text-align:center'>" .. coins(T.coins) .. "</div>")
                else
                    table.insert(elts, 5, "<div style='text-align:center'>-</div>")
                end
            else
                table.insert(elts, 5, commas(needed))
                if not (eltArgs.disp == "Char") then
                    if not (T.currency2 == nil) and T.material2 then
                        table.insert(elts, 6, 
                        "<div style='text-align:left'>" .. createList(T.material,needed) .. "<br />"
                        .. createList(T.material2,needed) .. "</div>")
                    else
                        table.insert(elts, 6, 
                            "<div style='text-align:left'>" .. createList(T.material,needed) .. "</div>")
                    end
                    if eltArgs.skill == "Magic" then
                        table.insert(elts, 7, coins(cost*needed))
                    else
                        if (eltArgs.skill == "Firemaking" and eltArgs.disp == "Daemonheim") then
                            cost = productCost
                        end
                        if not (eltArgs.skill == "Firemaking" and
                            (eltArgs.disp == "Barbarian" or eltArgs.disp == "Other")) then
                            table.insert(elts, 7, printCoins(cost, dispCurr, currLv, T.level))
                            table.insert(elts, 8, printCoins(cost * needed, dispCurr, currLv, T.level))
                            if not (cost == 0 and unitExp == 0) then -- if not (NaN)
                                table.insert(elts, 9, printCoins(cost / unitExp, dispCurr .. "-dec", currLv, T.level))
                            else                table.insert(elts, 9, "-") end
                        end
                        --end
                    end -- Skill == Magic
                end
            end -- Skill == Milestones or Skill ~= Milestones
        end -- Disp ~= Rooms

        -- Check for flatpack exception
        -- Add bench image
        if eltArgs.disp == "Flatpacks" then
            table.insert(elts, 3, 
                imageLink{
                    file=mw.text.split(T.bench, "<")[1],
                    image=mw.text.split(T.bench, "<")[1],
                    alt=T.bench})
        end
    end
    return elts
end -- generate_NoProfitLoss

--[=[
Generates a No Profit, No Loss skill table
skills: Agility, Slayer, Thieving
inputs:
    T           Data being processed from 'Module:Skill calc/' .. args.skill .. '/data'
    unitExp     Generated unit exp including bonuses
    needed      Required iterations for goal
    eltArgs     Data from the calculator
        ext         Image/Icon extension
        icon        File name of icon
    currLv      Current level (converted from XP, if necessary)
returns:
    Table of data using proper elts based on skill
--]=]
function eltData.generate_NoProfitNoLoss(frame)
    local T         = frame.args[1]
    local unitExp   = frame.args[2]
    local needed    = frame.args[3]
    local fileName  = frame.args[4] --##To be removed (as per Module:Skill_calc)
    local eltArgs   = frame.args[5]
    local icon      = frame.args[6] --##To be removed (as per Module:Skill_calc)
    local ext       = frame.args[7] --##To be removed (as per Module:Skill_calc)
    local currLv    = frame.args[8]
    local images, links

    -- Can be used with all other skills (may require testing first, though)
    images, links = setImgLnk(T, eltArgs)

    elts =
    {
        images,
        links,
        numbers(T.level)
    }

    if eltArgs.skill == "Slayer" then
        if eltArgs.disp == "Assignments" or eltArgs.disp == "Monsters" then
            table.insert(elts, 4, T.level2)
            table.insert(elts, 5, commas(numbers(unitExp,1)))
            if eltArgs.disp == "Assignments" then
                local modStrat = ""
                table.insert(elts, 6, printCoins(needed, "num", currLv, T.level2))
                if T.noStrat == nil then        modStrat = "[[" .. T.name .. "/Strategies|Strategy]]"
                elseif (T.noStrat == 1) then    modStrat = "[[" .. T.name .. T.strat .. "]]"
                elseif (T.noStrat == 2) then    modStrat = "[[" .. T.strat .. "]]" end
                table.insert(elts, 7, modStrat)
            end
        end
    elseif eltArgs.skill == "Agility" then
        if not (eltArgs.disp == "Milestones" or eltArgs.disp == "Multiples" 
            or eltArgs.disp == "Other") then
            table.insert(elts, 4, commas(numbers(unitExp,1)))
            table.insert(elts, 5, printCoins(needed, "num", currLv, T.level))
        end
    else
        table.insert(elts, 4, commas(numbers(unitExp,1)))
        table.insert(elts, 5, printCoins(needed, "num", currLv, T.level))
    end
    return elts
end -- generate_NoProfitNoLoss


--[=[
Generates a potential Profit, potential Loss skill table
skills: Fletching, Cooking, Farming, Smithing, Herblore, Summoning
inputs:
    T           Data being processed from 'Module:Skill calc/' .. args.skill .. '/data'
--  unitExp     experience per iteration
--  needed      required iterations for goal
--  fileName    page location
--  rawCost     ingredient cost per iteration
--  productCost product value per iteration
--  args        additional parameters from caller
returns:
    Table of data using proper elts based on skill
--]=]
function eltData.generate_ProfitLoss(frame)
    local T             = frame.args[1]
    local unitExp       = frame.args[2]
    local needed        = frame.args[3]
    local fileName      = frame.args[4]
    local rawCost       = frame.args[5]
    local eltArgs       = frame.args[6]
    local productCost   = frame.args[7]
    local currLv        = frame.args[8]
    local images, links

    -- If alternative currencies are used, the Grand Exchange will not have information
    local materials = ""
    if not (T.currency == nil) and T.material then
        materials = "<div style='text-align:left'>" .. expandedList(T.material,needed) .. "</div>"
    elseif T.material then
        materials = "<div style='text-align:left'>" .. createList(T.material,needed) .. "</div>"
    elseif T.familiar then
        local altTitle = mw.text.split(T.familiar, "<")[1]
        if T.familiarTitle then altTitle = mw.text.split(T.familiarTitle, "<")[1] end

        materials = "<div style='text-align:left'>" .. 
                        peLink(mw.text.split(T.familiarIcon, "<")[1], mw.text.split(T.familiar, "<")[1], altTitle) .. 
                    "</div>"
    end

    -- Set default currency settings, then determine if alternative used
    local displayCurrency = "int"
    if T.currency then
        displayCurrency = T.currency end

    -- Check for multiple images
    -- This occurs when multiple materials are required
    if T.multi then
        images  = 
                    imageLink{file=mw.text.split(T.multi[1], "<")[1],image=T.multi[1]},
                    imageLink{file=mw.text.split(T.multi[2], "<")[1],image=T.multi[2]}
        links   =
                    '[[' .. mw.text.split(T.multi[1], "<")[1] .. ']]',
                    '[[' .. mw.text.split(T.multi[2], "<")[1] .. ']]'

    -- Single images only at then
    else
        -- Set the image location
        -- Default with using our page for the icon
        local ourIcon = mw.text.split(fileName, "<")[1]

        -- Check for farming and make adjustments for seed icons
        if eltArgs.skill == "Farming" then 
            if T.seed then 
                ourIcon = mw.text.split(T.name, "<")[1] ..  "_" .. mw.text.split(T.seed, "<")[1] 
            end
        end

        -- Check if an image location was specified
        if T.image then ourIcon = mw.text.split(T.image, "<")[1] end
        if T.icon then ourIcon = mw.text.split(T.icon, "<")[1] end

        images = imageLink{file = mw.text.split(T.name, "<")[1], image = ourIcon}

        -- Set the item's [link]
        -- Default with using the item's name
        local ourTitle = mw.text.split(T.name, "<")[1]

        -- Check if we specified a page location
        if T.title then ourTitle = T.title end

        links  = '[[' .. mw.text.split(T.name, "<")[1] .. '|' .. ourTitle .. ']]'
    end

    elts =
    {
        images,
        links,
        numbers(T.level),
        commas(unitExp, 1),
        commas(needed)
    }

    if eltArgs.disp == "Forging" then
        table.insert(elts, 6, printCoins(productCost * needed, "int", currLv, T.level))
        table.insert(elts, 7, printCoins(productCost / unitExp, "dec", currLv, T.level))
    elseif eltArgs.disp == "Pets" then
        local foodList = ""
        elts =
        {
            images,
            links,
            numbers(T.level),
        }

        if T.food == nil and T.multif == nil then       foodList = "<div style='text-align:center'>none</div>"
        elseif T.multif then                            foodList = "<div style='text-align:left'>" .. T.multif[1] .. 
                                                            "<br/>" .. T.multif[2] .. "</div>"
        else                                            foodList = "[[" .. T.food .. "]]"
        end
        table.insert(elts, 4, foodList)
    else
        table.insert(elts, 6, materials)

        if not (string.find(eltArgs.disp,"Dungeoneering - ")) then
            table.insert(elts, 7, printCoins(rawCost * needed, displayCurrency, currLv, T.level))

            if not (eltArgs.skill == "Farming") then
                table.insert(elts, 8, printCoins(productCost * needed, displayCurrency, currLv, T.level))
                table.insert(elts, 9, printCoins((productCost - rawCost) * needed, displayCurrency, currLv, T.level))

                if T.currency then
                    table.insert(elts, 10, 
                        printCoins((productCost - rawCost) / unitExp, T.currency .. "-dec", currLv, T.level))
                else
                    table.insert(elts, 10, printCoins((productCost - rawCost) / unitExp, "dec", currLv, T.level))
                end
            end
        end

        if T.charm then
            table.insert(elts, 3, imageLink{file = mw.text.split(T.charm .. " charm", "<")[1], image = mw.text.split(T.charm .. " charm", "<")[1]})
        end
    end
    return elts
end -- generate_ProfitLoss

--[=[
Generates a Purely Profit, No Loss skill table
skills:
    Divination, Fishing, Mining, Woodcutting, Runecrafting, Hunter
inputs:
    T           Data being processed from 'Module:Skill calc/' .. args.skill .. '/data'
    unitExp     Generated unit exp including bonuses
    needed      Required iterations for goal
    ext         Image/Icon extension
    icon        File name of icon
    altName     Page name
returns:
    Table of data using proper elts based on skill
--]=]
function eltData.generate_ProfitNoLoss(frame)
    local T          = frame.args[1]
    local unitExp    = frame.args[2]
    local needed     = frame.args[3]
    local fileName   = frame.args[4]
    local rawCost    = frame.args[5]
    local eltArgs    = frame.args[6]
    local icon       = frame.args[7]
    local ext        = frame.args[8]
    local income     = frame.args[9]
    local remaining  = frame.args[10]
    local currLv     = frame.args[11]
    local memb      = '<sub title="Members only" style="cursor:help; margin-left:3px;">(m)</sub>'
    local images, links

    -- Default with using item's name for the icon
    local ourIcon = mw.text.split(fileName, "<")[1]
    -- Check if an icon image was specified
    if T.icon then ourIcon = mw.text.split(T.icon, "<")[1] end
    -- Hunter is a little different
    if eltArgs.skill == "Hunter" then
        if T.title and 
           not T.icon  then 
               ourIcon = mw.text.split(T.title, "<")[1] 
        end
    end

    -- Set the item's [link]
    -- Default with using the item's name
    local ourLink       = mw.text.split(T.name, "<")[1]
    local ourTitle      = mw.text.split(T.name, "<")[1]
    local equipmentLink = ""
    local ourIconSize      = 0

    -- Check if a page location was specified
    if T.link then ourLink = mw.text.split(T.link, "<")[1] end
    -- Check if a title was specified
    if T.title then ourTitle = mw.text.split(T.title, "<")[1] end

    if T.equipment then
        equipmentLink = mw.text.split(T.equipment, "<")[1]
        -- Check if an equipment link was specified
        if T.eLink then equipmentLink = mw.text.split(T.eLink, "<")[1] end
    end

    if T.iconSize then ourIconSize = T.iconSize end

    -- Set the actual icon image
    images = imageLink{file = ourLink, image = ourIcon, iconSize = ourIconSize}

    links  = '[[' .. ourLink .. '|' .. ourTitle .. ']]'

    -- Set non-link text, if any
    if T.sLink then links = T.sLink .. " " .. links end
    if T.eLink then links = links .. " " .. T.eLink end

    -- Check for Members only
    if T.mem == 1  then links = links .. memb end

    -- Check if there are materials and create a list
    local materialList = "-"
    if T.material then
        materialList = "<div style='text-align:left'>" .. createList(T.material,needed) .. "</div>"
    end

    -- Put it all together
    if eltArgs.disp == "Urns" then
        elts =
            {
                images,
                links,
                commas(unitExp,1),
                commas(needed),
                printCoins((rawCost * needed), "int", currLv, T.level)
            }
    elseif eltArgs.skill == "Fishing" then
        elts =
        {
            images,
            links,
            imageLink{
                file=equipmentLink,
                image=mw.text.split(T.equipment, "<")[1],
                alt=equipmentLink},
            materialList,
            numbers(T.level),
            commas(unitExp,1),
            commas(needed)
        }

        if not (eltArgs.disp == "Dungeoneering") then
            table.insert(elts, 8, printCoins(income * needed, "int", currLv, T.level))
            table.insert(elts, 9, printCoins(rawCost * needed, "int", currLv, T.level))
            table.insert(elts, 10, printCoins((income - rawCost) * needed, "int", currLv, T.level))
        end
    -- This section also accounts for base rune production multipliers
    elseif eltArgs.skill == "Runecrafting" then
        elts = 
            {
                images,
                links,
                numbers(T.level),
            }

        if eltArgs.disp == "Tiaras" then
            table.insert(elts, 3, materialList)
            table.insert(elts, 4, commas(unitExp,1))
            table.insert(elts, 5, commas(needed))
            table.insert(elts, 6, printCoins(rawCost * needed, "int", currLv, T.level))
            table.insert(elts, 7, printCoins((income * needed), "int", currLv, T.level))
            table.insert(elts, 8, printCoins((income - rawCost ) * needed, "int", currLv, T.level))
        elseif eltArgs.disp == "Runespan - Free" or eltArgs.disp == "Runespan - Members" then
            table.insert(elts, 4, commas(unitExp,1))
            table.insert(elts, 5, commas(needed))
        else
            table.insert(elts, 4, materialList)
            table.insert(elts, 5, commas(unitExp,1))
            table.insert(elts, 6, commas(needed))
            table.insert(elts, 7, printCoins(rawCost * needed, "int", currLv, T.level))
            table.insert(elts, 8, printCoins(
                    (income * needed) * levelMultiplier(ourIcon, tonumber(eltArgs.current)), "int", currLv, T.level))
            table.insert(elts, 9, printCoins(
                    ((income * levelMultiplier(ourIcon, tonumber(eltArgs.current))) - rawCost ) 
                        * needed, "int", currLv, T.level))
        end
    elseif eltArgs.skill == "Divination" then
        -- These allow for Cursed modification (tiered experience)
        local modifyExp    = 1
        local modifyNeeded = needed

        if T.name == "Cursed wisp" or T.name == "Cursed memory" then 
            modifyExp    = levelMultiplier(T.name, tonumber(eltArgs.current))
            modifyNeeded = tonumber(math.ceil(remaining / (unitExp * modifyExp)))
        elseif eltArgs.disp == "Boons" or T.boon == 1 then
            modifyNeeded = 1
        end
        --materialList needs to be recalculated with new value
        materialList = "<div style='text-align:left'>" .. createList(T.material,modifyNeeded) .. "</div>"

        elts =
            {
                images,
                links,
                numbers(T.level)
            }

        if not (eltArgs.disp == "Other") then
            table.insert(elts, 4, commas(unitExp * modifyExp, 1))
            if eltArgs.disp == "Harvest" or eltArgs.disp == "Gathering" then
                table.insert(elts, 5, commas(modifyNeeded, 1))
                table.insert(elts, 6, printCoins((income * levelMultiplier(ourIcon, tonumber(eltArgs.current))) 
                    * modifyNeeded, "int", currLv, T.level))
            else
                local targetElt = 4
                if not (eltArgs.disp == "Boons") then
                    targetElt = targetElt + 1
                    if T.boon == 1 then         table.insert(elts, targetElt, "<div style='text-align:center'>-</div>")
                    else                        table.insert(elts, targetElt, commas(modifyNeeded, 1)) end
                end
                table.insert(elts, (targetElt + 1), materialList)
                if not (eltArgs.disp == "Dungeoneering") then
                    table.insert(elts, (targetElt + 2), printCoins((0 - rawCost) * modifyNeeded, "int", currLv, T.level))
                end
            end
        end
    else
        elts =
        {
            images,
            links,
            numbers(T.level),
            commas(unitExp,1),
            commas(needed)
        }

        if not (eltArgs.disp == "Dungeoneering" or 
          (eltArgs.skill == "Woodcutting" and eltArgs.disp == "Other") or (eltArgs.skill == "Hunter")) then
            table.insert(elts, 6, printCoins(income * needed, "int", currLv, T.level)) end

        if eltArgs.skill == "Hunter" then
            local targetElt = 6

            if (eltArgs.disp == "Nets and Sprites" or
               eltArgs.disp == "Deadfall and Pitfall" or
               eltArgs.disp == "Box Trapping") then
                if T.bait then
                    table.insert(elts, targetElt, pLink(T.bait))
                else
                    table.insert(elts, targetElt, "-")
                end

                targetElt = targetElt + 1
            end

            if T.product then
                local currency = "Coins"
                if T.currency then currency = T.currency end
                    table.insert(elts, targetElt, inlineProfit(income, needed, T.product, currency))
            else
                table.insert(elts, targetElt, "-")
            end
        end
    end
    return elts
end -- generate_ProfitNoLoss

------------------------------------------------------
-------- Contemplating a global generator ------------
------------------------------------------------------

function eltData.generate_elts(frame)
    -- Don't worry about this function. I will be working on this over time to see if 
    -- everything can be generalized and merged into a single function and remain clear to remove repeated code
    -- Descriptive names make it more readily understandable

    local membersOnly = '<sub title="Members only" style="cursor:help; margin-left:3px;">(m)</sub>' -- May be implemented differently

    -- These variables will always be passed through the initial call, even if they are not used
    -- (nil will be passed instead). Trying to use T and eltArgs more in code.
    local T                 = frame.args[1]     -- Individual item data
    local eltArgs           = frame.args[2]     -- Calculator data
    local actionExp         = frame.args[3]     -- Individual item experience with bonuses
    local actionsRequired   = frame.args[4]     -- Calculated iterations using actionExp
    local expRequired       = frame.args[5]     -- User experience data
    local rawCost           = frame.args[6]     -- Cost of materials
    local productCost       = frame.args[7]     -- Income from actions
    local eltTitles         = frame.args[8]     -- Array of elt titles

    local currentLevel      = tonumber(eltArgs.current)

    local imageExtension = ".png"
    if T.ext then imageExtension = T.ext end

    ---------------------------------------
    --- Begin overrides from skill data ---
    ---------------------------------------

    ------ Handle icons ------

        local icon = T.name
        -- Check for specified icon
        if T.icon ~= nil then icon = T.icon end
        -- Check for flatpacks and adjust
        if eltArgs.disp == "Flatpacks" then icon = icon .. " (flatpack)" end
        -- Check for farming and make adjustments for seed icons
        if eltArgs.skill == "Farming" then 
            if T.seed ~= nil then 
                icon = T.name ..  "_" .. T.seed
            end
        end

    ------ Handle title & link ------

        local link = T.name
        local linkTitle = T.name
        -- Check if a title was specified
        if T.title ~= nil then linkTitle = T.title end
        -- Setup titled link
        link  = '[[' .. T.name .. '|' .. linkTitle .. ']]'
        -- If specified, append additional wiki-links
        if T.extLink ~= nil then link = link .. " " .. T.extLink end -- (eg [[Voice of Seren]])
        -- Check for Members only
        if T.members == 1  then link = link .. membersOnly end


    -- Set the actual icon image
    icon = imageLink{file = link, image = icon}

    ------ Handle materials ------

        local materials, familiar, equipment = ""
        local currency = "coins"
        -- If alternative currencies are used, the Grand Exchange will not have information
        if not (T.currency == nil) and T.material then
            materials = "<div style='text-align:left'>" .. expandedList(T.material,actionsRequired) .. "</div>"
        elseif T.material ~= nil then
            materials = "<div style='text-align:left'>" .. createList(T.material,actionsRequired) .. "</div>"
        elseif T.familiar ~= nil then
            local familiar = mw.text.split(T.familiar, "<")[1]
            if T.familiarTitle ~= nil then familiar = mw.text.split(T.familiarTitle, "<")[1] end

            materials = "<div style='text-align:left'>" .. 
                            peLink(T.familiarIcon, mw.text.split(T.familiar, "<")[1], altTitle) .. 
                        "</div>"
        end

        -- Set default currency settings, then determine if alternative used
        if T.currency ~= nil then currency = T.currency end

        -- Mostly for Fishing 
        if T.equipment ~= nil then
            local equipmentLink = mw.text.split(T.equipment, "<")[1]
            -- Check if an equipment link was specified
            if T.eLink ~= nil then equipmentLink = T.eLink end

            equipment = imageLink{
                            file=equipmentLink,
                            image=mw.text.split(T.equipment, "<")[1],
                            alt=equipmentLink}
        end

    ---------------------------------------
    ---- End overrides from skill data ----
    ---------------------------------------

    -------------------------------
    --- Begin data calculations ---
    -------------------------------

    local grossIncome, grossCost, netIncome = 0
    local avgNet, avgCost = 0
    local modifiedExp = 1   -- default value
    local modifiedNeeded = actionsRequired   -- default value

    if eltArgs.skill == "Runecrafting" and
       eltArgs.disp == "Runes" then

        grossIncome = (income * actionsRequired) * levelMultiplier(T.name, currentLevel)
        netIncome   = ((income * levelMultiplier(T.name, currentLevel)) - rawCost ) * actionsRequired

    elseif eltArgs.skill == "Divination" and                
            T.name == "Cursed wisp" or T.name == "Cursed memory" then

            modifiedExp = levelMultiplier(T.name, currentLevel)
            modifiedNeeded = tonumber(math.ceil(actionsRequired / (actionExp * modifiedExp)))

    else
        if rawCost ~= nil then
            grossCost = rawCost * actionsRequired end

        if productCost ~= nil then
            grossIncome = productCost * actionsRequired end

        if (rawCost ~= nil and productCost ~= nil) then
            netIncome = (productCost - rawCost) * actionsRequired 
        elseif rawCost ~= nil and rawCost ~= 0 then
            netIncome = 0 - grossCost -- Force a negative; may not be needed
        elseif productCost ~= nil and grossIncome ~= 0 then
            netIncome = grossIncome
        end

        avgNet = netIncome / actionsRequired
        avgCost = netIncome / actionExp

    end

    -------------------------------
    ---- End data calculations ----
    -------------------------------

    -------------------------------
    ---- Begin elt construction ---
    -------------------------------

    local generatedValues = 
            {
                icon            = icon,
                link            = link,
                level           = T.level,
                actionExp       = actionExp,
                actionsRequired = commas(actionsRequired),
                netIncome       = printCoins(netIncome, "int"),
                materials       = materials,
                rawCost         = printCoins(rawCost, "int"),
                avgCost         = printCoins(avgCost, "dec"),
                grossCost       = printCoins(grossCost, "int"),
                grossIncome     = printCoins(grossIncome, "int"),
            }

    local elts = {}

    -- I think this is going to be the cleanest method of the ones we've tried.
    -- Not sure about performance-wise, since every item calls another round of
    --  looping through titles.
    for i, title in ipairs(eltTitles) do
        findEltData(title, generatedValues, elts)
    end

    -- These are special cases not worth including in the helper function
    if eltArgs.skill == "Summoning" and 
        eltArgs.disp ~= "Scrolls" then
        local charm = imageLink{
                        file = T.charm .. " charm", 
                        image = T.charm .. " charm"}
        table.insert(elts, charm, 3)                    -- Include summoning charms required
    elseif eltArgs.skill == "Fishing" then
        table.insert(elts, equipment, 3)                -- Include necessary equipment
    elseif eltArgs.skill == "Hunter" then
        local targetElt = 6
        if (eltArgs.disp == "Nets and Sprites" or
           eltArgs.disp == "Deadfall and Pitfall" or
           eltArgs.disp == "Box Trapping") then
            if T.bait then
                table.insert(elts, targetElt, pLink(T.bait))    -- Include necessary bait
            else
                table.insert(elts, targetElt, "-")              -- No bait necessary
            end
            targetElt = targetElt + 1 
        end

        if T.product then
            local currency = "Coins"
            if T.currency then currency = T.currency end
                table.insert(elts, targetElt, inlineProfit(income, needed, T.product, currency))    -- Income
        else
            table.insert(elts, targetElt, "-")  -- Nothing can be sold
        end

    end

    -------------------------------
    ----- End elt construction ----
    -------------------------------

    return elts
end

--------------------------------------
-------- Helper Functions ------------
--------------------------------------

-- This function is used to set the images and links for all skills (eventually)
function setImgLnk(T, eltArgs)
    local memb      = '<sub title="Members only" style="cursor:help; margin-left:3px;">(m)</sub>'
    local single    = '<sub title="Can only be killed once" style="cursor:help; margin-left:3px;">(s)</sub>'
    local links, images

    -- Check for multiple images
    -- This occurs when multiple materials are required
    if T.multi then
        images  = 
                    imageLink{file=mw.text.split(T.multi[1], "<")[1],image=T.multi[1]},
                    imageLink{file=mw.text.split(T.multi[2], "<")[1],image=T.multi[2]}
        links   =
                    '[[' .. mw.text.split(T.multi[1], "<")[1] .. ']]',
                    '[[' .. mw.text.split(T.multi[2], "<")[1] .. ']]'
    -- Single images only at then
    else
        -- Set the image location
        -- Default with using our page for the icon
        local ourIcon = mw.text.split(T.name, "<")[1]

        -- Check for farming and make adjustments for seed icons
        if eltArgs.skill == "Farming" then 
            if T.seed then 
                ourIcon = mw.text.split(T.name, "<")[1] ..  "_" .. mw.text.split(T.seed, "<")[1] 
            end
        end

        -- Check for flatpacks and adjust
        if eltArgs.disp == "Flatpacks" then ourIcon = ourIcon .. " (flatpack)" end

        -- Check if we specified an image location and make adjustments
        if T.image then ourIcon = mw.text.split(T.image, "<")[1] end
        if T.icon then ourIcon = mw.text.split(T.icon, "<")[1] end

        -- Set the item's [link]
        -- Default with using the item's name
        local ourTitle = mw.text.split(T.name, "<")[1]

        -- Check if we specified a page location
        if T.title then ourTitle = T.title end

        -- Check if the icon has been modified
        if T.iconSize then
            images = imageLink{file=mw.text.split(T.name, "<")[1],image=ourIcon,iconSize=T.iconSize}
            --images = peLink(ourIcon, mw.text.split(T.name, "<")[1], ourTitle, T.iconSize)
        else
            images = imageLink{file=mw.text.split(T.name, "<")[1],image=ourIcon}
            --images = peLink(ourIcon, mw.text.split(T.name, "<")[1], ourTitle)
        end

        links  = '[[' .. mw.text.split(T.name, "<")[1] .. '|' .. ourTitle .. ']]'
    end

    -- Add any non-linking text
    if T.sLink then links = T.sLink .. " " .. links end
    if T.eLink then links = links .. " " .. T.eLink end

    -- Check for Members only, one time kill (Assignments)
    if T.mem == 1    then links = links .. memb end
    if T.single == 1 then links = links .. single end

    return images, links
end

-- ##Antiquated; needs to be phased out for pLink or peLink
function imageLink(params)
    local ext = ".png"
    local iconSize = nil
    if params.iconSize and params.iconSize > 0 then iconSize = params.iconSize end
    if params.ext then ext = params.ext end
    -- param.iconSize sets icon size if using a non-icon sized image.

    if params.alt then
        if params.image == "Bench with lathe" then
            return '[[File:Bench with lathe icon' .. ext .. '|link=' .. params.file .. '|' .. params.file .. ']]'
        elseif (iconSize) then
            return '[[File:' .. params.image .. ext .. '|' .. iconSize .. '|link=' .. params.file .. '|' .. params.alt .. ']]'
        else
            return '[[File:' .. params.image .. ext .. '|link=' .. params.file .. '|' .. params.alt .. ']]'
        end
    elseif not (iconSize == nil) then
        return '[[File:' .. params.image .. ext .. '|' .. iconSize .. 'px|link=' .. params.file .. '|' .. params.file .. ']]'
    else
        return '[[File:' .. params.image .. ext .. '|link=' .. params.file .. '|' .. params.file .. ']]'
    end
end -- imageLink

function createList(mess,a)
    local sentence = ""
    if not (mess == nil) then
        for i, v in ipairs(mess) do
            if (i%2) > 0 then
                if type(v) == "number" then
                    sentence = "" .. sentence .. " " .. commas( v * a ) 
                else
                    sentence = "" .. sentence .. " " .. v
                end
            else
                if i == table.getn(mess) then
                    sentence = sentence .. " " .. pLink(v)
                else
                    sentence = sentence .. " " .. pLink(v) .. "<br />"
                end
            end
        end
    else
        sentence = "-"
    end

    return sentence
end -- createList

-- This function is used for alternative currencies
-- ##Antiquated; should be phased out for mw.text.split usage
function expandedList(mess, a)
    local sentence = ""
    local follower = 0
    for i, v in ipairs(mess) do
        if type(v) == "number" then
            if follower == 0 then
                sentence = "" .. sentence .. " " .. commas( v * a ) 
                follower = 1
            else follower = 0 end
        else
            local parts = explode(",", v)
            local image = v
            local link = v
            if table.getn(parts) > 1 then
                image = parts[1]
                link = parts[2] end
            
            if i == table.getn(mess) then
                sentence = sentence .. " " .. peLink(image,link,link)
            else
                sentence = sentence .. " " .. peLink(image,link,link) .. "<br />"
            end
        end
    end

    return sentence
end

-- This is a simplified implementation of Template:Plink
-- Needs an image-only return value
function pLink(a)
    return "[[File:" .. a .. ".png|link=" .. a .. "]]&nbsp;[[" .. a .. "|" .. a .. "]]"
end -- plink

-- An extended implementation of pLink
-- Needs an image-only return value
function peLink(file, link, title)
    return "[[File:" .. file .. ".png|link=" .. link .. "]]&nbsp;[[" .. link .. "|" .. title .. "]]"
end -- pelink
 
function explain(message)
    local ret = mw.html.create('span'):css({['color'] = "#15f", ['border-bottom'] = "dotted 1px black", ['cursor'] = 'help'}):attr("title", message):wikitext("?")
    return "[" .. tostring(ret) .. "]"
end -- explain

-- This takes the amount of coins needed to display in table, 
--   but filters out 0s to make untradeables look better.
-- This function utilizes Module:Currency for alternative currency handling
function printCoins(amount, category, currLv, reqLv)
    --currLv = current level, reqLv = required level
    -- This will hide both zero-values and anything over the current level
    if currLv == nil then currLv = 0 end
    if reqLv  == nil then reqLv  = 0 end

    if currLv >= reqLv and amount ~= 0 then
        if category == "dec" then               return coins(string.format("%.2f", amount, 1))
        elseif category == "int" then           return coins(amount, 1)
        elseif category == "int-dec" then       return coins(string.format("%.2f", amount, 1))
        elseif category == "chimes-dec" then    return currency(string.format("%.2f", amount, 1), "chimes")
        elseif category == "chimes" then        return currency(amount, "chimes")
        elseif category == "rusty-dec" then     return currency(string.format("%.2f", amount, 1), "rusty")
        elseif category == "rusty" then         return currency(amount, "rusty")
        elseif category == "num" then           return commas(amount)
--[=[
        elseif category == "cwts" then          return currency(amount, "cwts")
        elseif category == "cwts-dec" then      return currency(string.format("%.2f", amount, 1), "cwts")
        elseif category == "cwtg" then          return currency(amount, "cwtg")
        elseif category == "cwtg-dec" then      return currency(string.format("%.2f", amount, 1), "cwtg")
--]=]
        end
    else                                        return "<div style='text-align:center'>-</div>"
    end
end

--[[ levelMultiplier function
--      input:
--              item    :: key being searched
--              level   :: subject's relevant level
--      output:
--              Returns a base multiplier to modify experience or production levels depending
--               on the item being searched. Most items refer to multiple rune production,
--               but 'cursed' versions within divination give tiered experience.
--]]
function levelMultiplier(item, level)
    local ret = 1

    if item == "Air rune" then
        if     level >= 99 then ret = 10 
        elseif level >= 88 then ret = 9
        elseif level >= 77 then ret = 8
        elseif level >= 66 then ret = 7
        elseif level >= 55 then ret = 6
        elseif level >= 44 then ret = 5
        elseif level >= 33 then ret = 4
        elseif level >= 22 then ret = 3
        elseif level >= 11 then ret = 2 end

    elseif item == "Mind rune" then
        if     level >= 112 then ret = 9
        elseif level >= 98 then ret = 8
        elseif level >= 84 then ret = 7
        elseif level >= 70 then ret = 6
        elseif level >= 56 then ret = 5
        elseif level >= 42 then ret = 4
        elseif level >= 28 then ret = 3
        elseif level >= 14 then ret = 2 end

    elseif item == "Water rune" then
        if     level >= 114 then ret = 7
        elseif level >= 95 then ret = 6
        elseif level >= 76 then ret = 5
        elseif level >= 57 then ret = 4
        elseif level >= 38 then ret = 3
        elseif level >= 19 then ret = 2 end

    elseif item == "Earth rune" then
        if     level >= 104 then ret = 5
        elseif level >= 78 then ret = 4
        elseif level >= 52 then ret = 3
        elseif level >= 26 then ret = 2 end

    elseif item == "Fire rune" then
        if     level >= 105 then ret = 4
        elseif level >= 70 then ret = 3
        elseif level >= 35 then ret = 2 end

    elseif item == "Body rune" then
        if     level >= 92 then ret = 3
        elseif level >= 46 then ret = 2 end

    elseif item == "Cosmic rune" and level >= 118 then ret = 2
    elseif item == "Chaos rune"  and level >= 74 then ret = 2
    elseif item == "Astral rune" and level >= 82 then ret = 2
    elseif item == "Nature rune" and level >= 91 then ret = 2
    elseif item == "Law rune"    and level >= 110 then ret = 2
    elseif item == "Death rune"  and level >= 131 then ret = 2

    elseif item == "Armadyl rune" then
        if     level >= 99 then ret = 10
        elseif level >= 88 then ret = 9
        elseif level >= 77 then ret = 8
        elseif level >= 72 then ret = 7 end

    elseif item == "Blood rune" and level >= 154 then ret = 2

    elseif item == "Cursed wisp" then
        if     level >= 95 then ret = 12
        elseif level >= 90 then ret = 11
        elseif level >= 85 then ret = 10
        elseif level >= 80 then ret = 9
        elseif level >= 70 then ret = 8
        elseif level >= 60 then ret = 7
        elseif level >= 50 then ret = 6
        elseif level >= 40 then ret = 5
        elseif level >= 30 then ret = 4
        elseif level >= 20 then ret = 3
        elseif level >= 10 then ret = 2 end

    elseif item == "Cursed memory" then
        if     level >= 95 then ret = 64
        elseif level >= 90 then ret = 53
        elseif level >= 85 then ret = 46
        elseif level >= 80 then ret = 41
        elseif level >= 70 then ret = 36
        elseif level >= 60 then ret = 29
        elseif level >= 50 then ret = 22
        elseif level >= 40 then ret = 13
        elseif level >= 30 then ret = 8
        elseif level >= 20 then ret = 6
        elseif level >= 10 then ret = 5
        else ret = 4 end

    end

    return ret
end -- levelMultiplier

--[[ findEltData function
--   input:
--          EltTitle    :: A list of elts returned from /elts
--          EltValues   :: An object of calculated and formatted values
--          elts        :: A reference to the elts table for modification
--   output:
--          No values returned; this function directly updates the elts object
--           with the appropriate data.
--]]
function findEltData(EltTitle, EltValues, elts)

    if EltTitle == "" then
        table.insert(elts, EltValues.icon)
    elseif EltTitle == "Name" then
        table.insert(elts, EltValues.link)
    elseif EltTitle == "Level" then
        table.insert(elts, EltValues.level)
    elseif EltTitle == "XP" then
        table.insert(elts, EltValues.actionExp)
    elseif EltTitle == "# needed" then
        table.insert(elts, EltValues.actionsRequired)
    elseif EltTitle == "Materials" then
        table.insert(elts, EltValues.materials)
    elseif EltTitle == "Unit cost" then
        table.insert(elts, EltValues.rawCost)
    elseif EltTitle == "Cost" or
           EltTitle == "Profit" or
           EltTitle == "Profit/Loss" then
        table.insert(elts, EltValues.netIncome)
    elseif EltTitle == "Raw cost" then
        table.insert(elts, EltValues.grossCost)
    elseif EltTitle == "Product cost" then
        table.insert(elts, EltValues.grossIncome)
    elseif EltTitle == "XP cost" or
           EltTitle == "Income/XP" then
        table.insert(elts, EltValues.avgCost)
    end

end -- findEltData

-- From http://lua-users.org/wiki/SplitJoin
-- ##Antiquated; needs to be replaced throughout with mw.text.split
function explode(d,p)
   local t, ll
   t={}
   ll=0
   if(#p == 1) then
      return {p}
   end
   while true do
      l = string.find(p, d, ll, true) -- find the next d in the string
      if l ~= nil then -- if "not not" found then..
         table.insert(t, string.sub(p,ll,l-1)) -- Save it in our array.
         ll = l + 1 -- save just after where we found it for searching next time.
      else
         table.insert(t, string.sub(p,ll)) -- Save what's left in our array.
         break -- Break at end, as it should be, according to the lua manual.
      end
   end
   return t
end -- explode

--[[ inlineProfit function
--      input:
--              income  :: value of object
--              needed  :: number of actions required to meet goal
--              item    :: two-part item; (icon,link)
--              curr    :: currency being used
--      output:
--              Builds a string of pLinks with their corresponding total-costs
--               meant for an in-line view.
--]]
function inlineProfit(income, needed, item, curr)
    local sentence = ""
    local value = ""
    local parts = explode(",", item)
    local image = item
    local link = item

    if income ~= 0 then
        if curr == "Chimes" then
            value = value .. " : " .. currency(income * needed, "chimes")
        else 
            value = value .. " : " .. coins(income * needed, 1)
        end
    end

    if table.getn(parts) > 1 then
        image = parts[1]
        link = parts[2] end

        sentence = sentence .. " " .. peLink(image,link,link) .. value

    return sentence
end -- inlineProfit

--[[ findItem function
--      input:
--              list    :: a table of values
--              item    :: key being searched for
--      output:
--              Returns a boolean for presence within table
--]]
function findItem (list, item)
    local status = false
    for _,v in pairs(list) do
        if v == item then
            status = true
            break
        end
    end
    return status
end -- findItem

return eltData