Editing Module:HeroDataArrays

Jump to navigation Jump to search
Warning: You are not logged in. Once you make an edit, a temporary account will be created for you. Learn more. Log in or create an account to continue receiving notifications after this account expires, and to access other features.
The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
Latest revision Your text
Line 14: Line 14:
         end
         end
     end
     end
end
-- Use sort name for edge cases like "The Doorman"
local function sortHeroes(rows)
    local function getSortName(name)
        return (name:gsub("^The ", ""))
    end
    table.sort(rows, function(a, b)
        local nameA = getSortName(a.sortName or a.name or "")
        local nameB = getSortName(b.sortName or b.name or "")
        return nameA:lower() < nameB:lower()
    end)
end
end


Line 35: Line 22:
     end
     end
     return value
     return value
end
-- Round to 4 digits
local function roundValueFour(value)
    if type(value) == "number" then
        return util_module.round_to_sig_fig(value, 4)
    end
    return value
end
-- Round to an integer (up to 2 digits)
local function roundValueInteger(value)
    if type(value) == "number" then
        return util_module.round_to_sig_fig(value, 2)
    end
    return value
end
-- Generate tables from given properties
local function buildTable(frame, rows, tableDef, options)
    options = options or {}
    -- option to ignore heroes who don't have any of the given properties. true by default
    local filterZero = options.filterZero or true
    local filteredRows = {}
    for _, r in ipairs(rows) do
        local hasValue = not filterZero
        if filterZero then
            for _, col in ipairs(tableDef.columns) do
                if r[col.field] ~= 0 and r[col.field] ~= nil then
                if r[col.field] ~= "+0" then
                    hasValue = true
                    break
                    end
                end
            end
        end
        if hasValue then
            table.insert(filteredRows, r)
        end
    end
    if #filteredRows == 0 then
        return ""
    end
    -- Build header
    local header = ""
    for _, col in ipairs(tableDef.columns) do
        header = header .. " !! " .. col.label
    end
    -- Start table
    local t = "{| class=\"wikitable sortable mw-collapsible\" style=\"text-align:center\" \n" ..
        "|+ " .. tableDef.title .. " \n" ..
        "! Hero" .. header .. " \n"
    -- Rows
    for _, r in ipairs(filteredRows) do
        local cells = ""
        for _, col in ipairs(tableDef.columns) do
            cells = cells .. " || " .. (r[col.field] or 0)
        end
        -- A row may carry an alternate sort key and a label suffix, used by
        -- secondary fire rows so they stay underneath their hero's main row
        local nameCell = "| style=\"text-align:left;\""
        if r.sortName then
            nameCell = nameCell .. " data-sort-value=\"" .. r.sortName .. "\""
        end
        nameCell = nameCell .. " | " ..
            frame:expandTemplate{ title = "PageRef", args = { r.name } } ..
            (r.nameSuffix or "")
        t = t ..
            "|- \n" ..
            nameCell ..
            cells .. " \n"
    end
    t = t .. "|}"
    return t
end
end


Line 163: Line 64:
         table.insert(rows, {
         table.insert(rows, {
             name = name,
             name = name,
             maxHealth = data["MaxHealth"] or 0,
             maxHealth = tonumber(data["MaxHealth"]) or 0,
             scalingHealth = "+" .. data["LevelScaling>MaxHealth"] or 0,
             scalingHealth = tonumber(data["LevelScaling>MaxHealth"]) or 0
            maxScalingHealth = (data["MaxHealth"] + data["LevelScaling>MaxHealth"] * soul_unlock.get_max("PowerIncrease")) or 0
         })
         })
     end
     end
     sortHeroes(rows)
     table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)


     local tableDefs = {
    -- Input table will be called a, output wikitable will be called z
         {
     local z = "{| class=\"wikitable sortable mw-collapsible\" style=\"text-align:center\" \n"..
            title = "Base Health Stats",
         "|+ Hero Base Health Stats \n"..
            columns = {
        "! Hero !! Starting !! Added per Boon !! At Max Boon \n"
                { label = "Starting", field = "maxHealth" },
 
                 { label = "Added per Boon", field = "scalingHealth" },
    -- Iterate over heroes adding a new row to the wikitable for each
                 { label = "At Max Boon", field = "maxScalingHealth" },
    for _, r in ipairs(rows) do
            }
        z = z..
        }
            "|- \n"..
     }
            "| style=\"text-align:left;\" | "..
                 frame:expandTemplate{title="PageRef", args={r.name}}..
                 " || "..r.maxHealth.." || +"..r.scalingHealth.." || "..
                tostring(roundValue(r.maxHealth + r.scalingHealth * soul_unlock.get_max('PowerIncrease'))).." \n"
     end
      
      
local output = {}
     z = z.."|}"
     for _, def in ipairs(tableDefs) do
     return z
        local t = buildTable(frame, rows, def, def.options)
        if t ~= "" then
            table.insert(output, t)
        end
    end
 
     return table.concat(output, "\n\n")
end
end


p.heroRegenTable = function(frame)
p.heroRegenTable = function(frame)
     local heroRegenData = heroDataArray({"Name", "BaseHealthRegen", "SpiritScaling>BaseHealthRegen"})
     local heroRegenData = heroDataArray({"Name", "BaseHealthRegen"})
      
      
     local rows = {}
     local rows = {}
Line 199: Line 96:
         table.insert(rows, {
         table.insert(rows, {
             name = name,
             name = name,
             baseHealthRegen = data["BaseHealthRegen"] or 0,
             baseHealthRegen = data["BaseHealthRegen"] or 0
            spiritHealthRegen = "+".. (data["SpiritScaling>BaseHealthRegen"] or 0),
         })
         })
     end
     end
     sortHeroes(rows)
     table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)


     local tableDefs = {
     local z = "{| class=\"wikitable sortable mw-collapsible\" style=\"text-align:center\" \n"..
         {
         "|+ Hero Base Health Regen \n"..
            title = "Base Health Regen Stats",
        "! Hero !! HP/s \n"
            columns = {
                { label = "HP/s", field = "baseHealthRegen" },
                { label = "Spirit Scaling", field = "spiritHealthRegen" }
            }
        }
    }


local output = {}
     for _, r in ipairs(rows) do
     for _, def in ipairs(tableDefs) do
         z = z..
         local t = buildTable(frame, rows, def, def.options)
            "|- \n"..
        if t ~= "" then
             "| style=\"text-align:left;\" | "..
             table.insert(output, t)
                frame:expandTemplate{title="PageRef", args={r.name}}..
        end
                " || "..r.baseHealthRegen.." \n"
     end
     end
 
     z = z.."|}"
     return table.concat(output, "\n\n")
    return z
end
end


Line 248: Line 138:
             altBulletsPerShot = data["Weapon>AltFire>BulletsPerShot"] or 0
             altBulletsPerShot = data["Weapon>AltFire>BulletsPerShot"] or 0
         })
         })
    end
    table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)
    local z = "{| class=\"wikitable sortable mw-collapsible\" style=\"text-align:center\" \n"..
        "|+ Hero Base Damage \n"..
        "! Hero !! Damage per sec !! Reload Delay (s) !! Reload Time (s) !! Ammo !! Bullets per sec !! Bullet Damage !! Bullets Per Shot \n"
          
          
         local altBulletDamage = data["Weapon>AltFire>BulletDamage"]
    for _, r in ipairs(rows) do
        local altDPS = data["Weapon>AltFire>DPS"]
         z = z..
        local altRoundsPerSecond = data["Weapon>AltFire>RoundsPerSecond"]
            "|- \n"..
        local altBulletsPerShot = data["Weapon>AltFire>BulletsPerShot"]
            "| style=\"text-align:left;\" | "..
        if altBulletDamage and altBulletDamage ~= 0 then
                 frame:expandTemplate{title="PageRef", args={r.name}}..
            table.insert(rows, {
                 " || "..r.DPS.." || "..r.reloadDelay.." || "..r.reloadTime.." || "..r.clipSize..
                 name = name,
                 " || "..r.roundsPerSecond.." || "..r.bulletDamage.." || "..r.bulletsPerShot.." \n"
                sortName = name .. " (alt fire)",
                 nameSuffix = " (alt fire)",
                DPS = altDPS,
                reloadDelay = data["Weapon>ReloadDelay"] or 0,
                reloadTime = data["Weapon>ReloadTime"] or 0,
                 clipSize = data["Weapon>ClipSize"] or 0,
                roundsPerSecond = altRoundsPerSecond,
                bulletDamage = altBulletDamage,
                bulletsPerShot = altBulletsPerShot
            })
        end
     end
     end
     sortHeroes(rows)
    z = z.."|}"
 
     table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)


     local tableDefs = {
     local tableDefs = {
     {
     {
             title  = "Base Damage Stats",
             title  = "Hero Base Alt-Fire Damage",
             columns = {
             columns = {
                 { label = "Damage per sec", field = "DPS"  },
                 { label = "Damage per sec", field = "altDPS"  },
                { label = "Reload Delay (s)", field = "reloadDelay"  },
                 { label = "Ammo Per Shot", field = "altAmmoConsumedPerShot"  },
                { label = "Reload Time (s)", field = "reloadTime"  },
                 { label = "Bullets per sec", field = "altRoundsPerSecond"  },
                 { label = "Ammo", field = "clipSize"  },
                 { label = "Bullet Damage", field = "altBulletDamage"  },
                 { label = "Bullets per sec", field = "roundsPerSecond"  },
                 { label = "Bullets Per Shot", field = "altBulletsPerShot"  },
                 { label = "Bullet Damage", field = "bulletDamage"  },
                 { label = "Bullets Per Shot", field = "bulletsPerShot"  },
             }
             }
         }  
         }  
     }
     }


     local output = {}
     local output = ""
     for _, def in ipairs(tableDefs) do
 
         local t = buildTable(frame, rows, def, def.options)
     for _, tableDef in ipairs(tableDefs) do
        if t ~= "" then
         local filteredRows = {}
             table.insert(output, t)
        for _, r in ipairs(rows) do
            local hasValue = false
            for _, col in ipairs(tableDef.columns) do
                if r[col.field] ~= 0 then
                    hasValue = true
                    break
                end
             end
            if hasValue then
                table.insert(filteredRows, r)
            end
        end
 
        if #filteredRows > 0 then
            local header = ""
            for _, col in ipairs(tableDef.columns) do
                header = header.." !! "..col.label
            end
 
            local t = "{| class=\"wikitable sortable mw-collapsible\" style=\"text-align:center\" \n"..
                "|+ "..tableDef.title.." \n"..
                "! Hero"..header.." \n"
 
            for _, r in ipairs(filteredRows) do
                local cells = ""
                for _, col in ipairs(tableDef.columns) do
                    cells = cells.." || "..r[col.field]
                end
                t = t..
                    "|- \n"..
                    "| style=\"text-align:left;\" | "..
                        frame:expandTemplate{title="PageRef", args={r.name}}..
                        cells.." \n"
            end
 
            t = t.."|}"
            if output ~= "" then
                output = output.."\n\n"
            end
            output = output..t
         end
         end
     end
     end


     return table.concat(output, "\n\n")
     return z .. "\n\n" .. output
end
end


p.heroBulletSpeedTable = function(frame)
p.heroBulletSpeedTable = function(frame)
     local heroBulletSpeedData = heroDataArray({
     local heroBulletSpeedData = heroDataArray({"Name", "Weapon>BulletSpeed", "Weapon>AltFire>BulletSpeed"})
        "Name",
   
        "Weapon>BulletSpeed",
        "Weapon>AltFire>BulletSpeed"
    })
 
     local rows = {}
     local rows = {}
     for name, data in pairs(heroBulletSpeedData) do
     for name, data in pairs(heroBulletSpeedData) do
Line 310: Line 230:
             altBulletSpeed = data["Weapon>AltFire>BulletSpeed"] or 0
             altBulletSpeed = data["Weapon>AltFire>BulletSpeed"] or 0
         })
         })
       
        local altBulletSpeed = data["Weapon>AltFire>BulletSpeed"]
        if altBulletSpeed and altBulletSpeed ~= 0 then
            table.insert(rows, {
                name = name,
                sortName = name .. " (alt fire)",
                nameSuffix = " (alt fire)",
                bulletSpeed = altBulletSpeed
            })
        end
     end
     end
    table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)


     sortHeroes(rows)
     local z = "{| class=\"wikitable sortable mw-collapsible\" style=\"text-align:center\" \n"..
        "|+ Base Bullet Velocity \n"..
        "! Hero !! m/s \n"
 
    for _, r in ipairs(rows) do
        z = z..
            "|- \n"..
            "| style=\"text-align:left;\" | "..
                frame:expandTemplate{title="PageRef", args={r.name}}..
                " || "..r.bulletSpeed.." \n"
    end
    z = z.."|}"
    table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)


     local tableDefs = {
     local tableDefs = {
        {
    {
             title = "Base Bullet Velocity",
             title   = "Base Alt-Fire Bullet Velocity",
             columns = {
             columns = {
                 { label = "m/s", field = "bulletSpeed" }
                 { label = "m/s", field = "altBulletSpeed" },
             }
             }
         }
         }  
     }
     }


     local output = {}
     local output = ""
     for _, def in ipairs(tableDefs) do
 
         local t = buildTable(frame, rows, def, def.options)
     for _, tableDef in ipairs(tableDefs) do
        if t ~= "" then
         local filteredRows = {}
             table.insert(output, t)
        for _, r in ipairs(rows) do
            local hasValue = false
            for _, col in ipairs(tableDef.columns) do
                if r[col.field] ~= 0 then
                    hasValue = true
                    break
                end
             end
            if hasValue then
                table.insert(filteredRows, r)
            end
        end
 
        if #filteredRows > 0 then
            local header = ""
            for _, col in ipairs(tableDef.columns) do
                header = header.." !! "..col.label
            end
 
            local t = "{| class=\"wikitable sortable mw-collapsible\" style=\"text-align:center\" \n"..
                "|+ "..tableDef.title.." \n"..
                "! Hero"..header.." \n"
 
            for _, r in ipairs(filteredRows) do
                local cells = ""
                for _, col in ipairs(tableDef.columns) do
                    cells = cells.." || "..r[col.field]
                end
                t = t..
                    "|- \n"..
                    "| style=\"text-align:left;\" | "..
                        frame:expandTemplate{title="PageRef", args={r.name}}..
                        cells.." \n"
            end
 
            t = t.."|}"
            if output ~= "" then
                output = output.."\n\n"
            end
            output = output..t
         end
         end
     end
     end


     return table.concat(output, "\n\n")
     return z .. "\n\n" .. output
end
end


p.heroClipSizeTable = function(frame)
p.heroClipSizeTable = function(frame)
     local heroClipSizeData = heroDataArray({"Name", "Weapon>ClipSize","Weapon>BulletsPerBurst","Weapon>AltFire>AmmoConsumedPerShot","SpiritScaling>ClipSize"})
     local heroClipSizeData = heroDataArray({"Name", "Weapon>ClipSize","Weapon>AltFire>AmmoConsumedPerShot"})
      
      
     local rows = {}
     local rows = {}
Line 352: Line 314:
             name = name,
             name = name,
             clipSize = data["Weapon>ClipSize"] or 0,
             clipSize = data["Weapon>ClipSize"] or 0,
            spiritClipSize = "+".. (data["SpiritScaling>ClipSize"] or 0),
            bulletsPerBurst = data["Weapon>BulletsPerBurst"] or 0,
            burstClipSize = data["Weapon>ClipSize"] or 0 / data["Weapon>BulletsPerBurst"] or 0,
             ammoConsumedPerShot = data["Weapon>AltFire>AmmoConsumedPerShot"] or 0
             ammoConsumedPerShot = data["Weapon>AltFire>AmmoConsumedPerShot"] or 0
         })
         })
       
        local ammoConsumedPerShot = data["Weapon>AltFire>AmmoConsumedPerShot"]
        if ammoConsumedPerShot and ammoConsumedPerShot ~= 0 then
            table.insert(rows, {
                name = name,
                sortName = name .. " (alt fire)",
                nameSuffix = " (alt fire)",
                bulletsPerBurst = ammoConsumedPerShot,
                clipSize = data["Weapon>ClipSize"] or 0,
                spiritClipSize = "+".. (data["SpiritScaling>ClipSize"] or 0),
            })
        end
     end
     end
    table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)
     sortHeroes(rows)
 
    local z = "{| class=\"wikitable sortable mw-collapsible\" style=\"text-align:center\" \n"..
        "|+ Base Ammo Count \n"..
        "! Hero !! Ammo \n"
 
    for _, r in ipairs(rows) do
        z = z..
            "|- \n"..
            "| style=\"text-align:left;\" | "..
                frame:expandTemplate{title="PageRef", args={r.name}}..
                " || "..r.clipSize.." \n"
    end
     z = z.."|}"
   
    table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)


     local tableDefs = {
     local tableDefs = {
     {
     {
             title  = "Base Ammo Count",
             title  = "Alt-Fire Ammo Cost",
             columns = {
             columns = {
                { label = "Ammo", field = "clipSize"  },
                 { label = "Ammo Per Shot", field = "ammoConsumedPerShot"  },
                 { label = "Ammo Per Shot", field = "bulletsPerBurst"  },
                { label = "Spirit Scaling", field = "spiritClipSize"  },
             }
             }
         }  
         }  
     }
     }


     local output = {}
     local output = ""
     for _, def in ipairs(tableDefs) do
 
         local t = buildTable(frame, rows, def, def.options)
     for _, tableDef in ipairs(tableDefs) do
        if t ~= "" then
         local filteredRows = {}
             table.insert(output, t)
        for _, r in ipairs(rows) do
            local hasValue = false
            for _, col in ipairs(tableDef.columns) do
                if r[col.field] ~= 0 then
                    hasValue = true
                    break
                end
             end
            if hasValue then
                table.insert(filteredRows, r)
            end
        end
 
        if #filteredRows > 0 then
            local header = ""
            for _, col in ipairs(tableDef.columns) do
                header = header.." !! "..col.label
            end
 
            local t = "{| class=\"wikitable sortable mw-collapsible\" style=\"text-align:center\" \n"..
                "|+ "..tableDef.title.." \n"..
                "! Hero"..header.." \n"
 
            for _, r in ipairs(filteredRows) do
                local cells = ""
                for _, col in ipairs(tableDef.columns) do
                    cells = cells.." || "..r[col.field]
                end
                t = t..
                    "|- \n"..
                    "| style=\"text-align:left;\" | "..
                        frame:expandTemplate{title="PageRef", args={r.name}}..
                        cells.." \n"
            end
 
            t = t.."|}"
            if output ~= "" then
                output = output.."\n\n"
            end
            output = output..t
         end
         end
     end
     end


     return table.concat(output, "\n\n")
     return z .. "\n\n" .. output
end
end


p.heroRoundsPerSecondTable = function(frame)
p.heroRoundsPerSecondTable = function(frame)
     local heroRoundsPerSecondData = heroDataArray({"Name", "Weapon>RoundsPerSecond", "Weapon>AltFire>RoundsPerSecond", "SpiritScaling>RoundsPerSecond", "SpiritScaling>FireRate"})
     local heroRoundsPerSecondData = heroDataArray({"Name", "Weapon>RoundsPerSecond", "Weapon>AltFire>RoundsPerSecond"})
      
      
     local rows = {}
     local rows = {}
Line 403: Line 401:
             name = name,
             name = name,
             roundsPerSecond = data["Weapon>RoundsPerSecond"] or 0,
             roundsPerSecond = data["Weapon>RoundsPerSecond"] or 0,
             altRoundsPerSecond = data["Weapon>AltFire>RoundsPerSecond"] or 0,
             altRoundsPerSecond = data["Weapon>AltFire>RoundsPerSecond"] or 0
            spiritRoundsPerSecond = "+".. (data["SpiritScaling>RoundsPerSecond"] or 0),
            spiritFireRate = "+".. (data["SpiritScaling>FireRate"] or 0),
         })
         })
       
        local altRoundsPerSecond = data["Weapon>AltFire>RoundsPerSecond"]
        if altRoundsPerSecond and altRoundsPerSecond ~= 0 then
            table.insert(rows, {
                name = name,
                sortName = name .. " (alt fire)",
                nameSuffix = " (alt fire)",
                roundsPerSecond = altRoundsPerSecond,
                spiritRoundsPerSecond = "+".. (data["SpiritScaling>RoundsPerSecond"] or 0),
            })
        end
     end
     end
     sortHeroes(rows)
     table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)
 
    local z = "{| class=\"wikitable sortable mw-collapsible\" style=\"text-align:center\" \n"..
        "|+ Base Fire Rate \n"..
        "! Hero !! Rounds/s \n"
 
    for _, r in ipairs(rows) do
        z = z..
            "|- \n"..
            "| style=\"text-align:left;\" | "..
                frame:expandTemplate{title="PageRef", args={r.name}}..
                " || "..r.roundsPerSecond.." \n"
    end
    z = z.."|}"
   
    table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)


     local tableDefs = {
     local tableDefs = {
     {
     {
             title  = "Base Fire Rate",
             title  = "Base Alt-Fire Fire Rate",
             columns = {
             columns = {
                 { label = "Rounds/s", field = "roundsPerSecond"  },
                 { label = "Rounds/s", field = "altRoundsPerSecond"  },
                { label = "Spirit Scaling", field = "spiritRoundsPerSecond"  },
             }
             }
         }
         }  
     }
     }


     local output = {}
     local output = ""
     for _, def in ipairs(tableDefs) do
 
         local t = buildTable(frame, rows, def, def.options)
     for _, tableDef in ipairs(tableDefs) do
        if t ~= "" then
         local filteredRows = {}
             table.insert(output, t)
        for _, r in ipairs(rows) do
            local hasValue = false
            for _, col in ipairs(tableDef.columns) do
                if r[col.field] ~= 0 then
                    hasValue = true
                    break
                end
             end
            if hasValue then
                table.insert(filteredRows, r)
            end
        end
 
        if #filteredRows > 0 then
            local header = ""
            for _, col in ipairs(tableDef.columns) do
                header = header.." !! "..col.label
            end
 
            local t = "{| class=\"wikitable sortable mw-collapsible\" style=\"text-align:center\" \n"..
                "|+ "..tableDef.title.." \n"..
                "! Hero"..header.." \n"
 
            for _, r in ipairs(filteredRows) do
                local cells = ""
                for _, col in ipairs(tableDef.columns) do
                    cells = cells.." || "..r[col.field]
                end
                t = t..
                    "|- \n"..
                    "| style=\"text-align:left;\" | "..
                        frame:expandTemplate{title="PageRef", args={r.name}}..
                        cells.." \n"
            end
 
            t = t.."|}"
            if output ~= "" then
                output = output.."\n\n"
            end
            output = output..t
         end
         end
     end
     end


     return table.concat(output, "\n\n")
     return z .. "\n\n" .. output
end
end


p.heroFalloffRangeTable = function(frame)
p.heroFalloffRangeTable = function(frame)
     local heroFalloffRangeData = heroDataArray({"Name", "Weapon>FalloffStartRange", "Weapon>FalloffEndRange",  "Weapon>AltFire>FalloffStartRange", "Weapon>AltFire>FalloffEndRange",
     local heroFalloffRangeData = heroDataArray({"Name", "Weapon>FalloffStartRange", "Weapon>FalloffEndRange",  "Weapon>AltFire>FalloffStartRange", "Weapon>AltFire>FalloffEndRange",
     "Weapon>AltFire>ExplosionRadius", "Weapon>FalloffEndScale", "Weapon>AltFire>ExplosionDamageScaleAtMaxRadius",})
     "Weapon>AltFire>ExplosionRadius"})
      
      
     local rows = {}
     local rows = {}
Line 452: Line 490:
             falloffStartRange = data["Weapon>FalloffStartRange"] or 0,
             falloffStartRange = data["Weapon>FalloffStartRange"] or 0,
             falloffEndRange = data["Weapon>FalloffEndRange"] or 0,
             falloffEndRange = data["Weapon>FalloffEndRange"] or 0,
            falloffEndScale = -100 + (100 * (data["Weapon>FalloffEndScale"] or 0)),
             altFalloffStartRange = data["Weapon>AltFire>FalloffStartRange"] or 0,
             altFalloffStartRange = data["Weapon>AltFire>FalloffStartRange"] or 0,
             altFalloffEndRange = data["Weapon>AltFire>FalloffEndRange"] or 0,
             altFalloffEndRange = data["Weapon>AltFire>FalloffEndRange"] or 0,
             altExplosionRadius = 0,
             altExplosionRadius = data["Weapon>AltFire>ExplosionRadius"] or 0
            altExplosionEndScale = (100 * (data["Weapon>AltFire>ExplosionDamageScaleAtMaxRadius"] or 0))
         })
         })
   
        local altFalloffStartRange = data["Weapon>AltFire>FalloffStartRange"]
        local altFalloffEndRange = data["Weapon>AltFire>FalloffEndRange"]
        local altExplosionRadius = data["Weapon>AltFire>ExplosionRadius"] or 0
        local altExplosionEndScale = (100 * (data["Weapon>AltFire>ExplosionDamageScaleAtMaxRadius"] or 0))
        if altFalloffStartRange and altFalloffStartRange ~= 0 then
            table.insert(rows, {
                name = name,
                sortName = name .. " (alt fire)",
                nameSuffix = " (alt fire)",
                falloffStartRange = altFalloffStartRange,
                falloffEndRange = altFalloffEndRange,
                altExplosionRadius = data["Weapon>AltFire>ExplosionRadius"] or 0,
                falloffEndScale = -100 + (100 * (data["Weapon>FalloffEndScale"] or 0))
            })
        end
     end
     end
     sortHeroes(rows)
     table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)
 
    local z = "{| class=\"wikitable sortable mw-collapsible\" style=\"text-align:center\" \n"..
        "|+ Base Falloff Range \n"..
        "! Hero !! Minimum Range (m) !! Maximum Range (m)  \n"
 
    for _, r in ipairs(rows) do
        z = z..
            "|- \n"..
            "| style=\"text-align:left;\" | "..
                frame:expandTemplate{title="PageRef", args={r.name}}..
                " || "..r.falloffStartRange.." || "..r.falloffEndRange.." \n"
    end
    z = z.."|}"
    table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)


     local tableDefs = {
     local tableDefs = {
     {
     {
             title  = "Base Falloff Range",
             title  = "Base Alt-Fire Falloff Range",
             columns = {
             columns = {
                 { label = "Minimum Range (m)", field = "falloffStartRange"  },
                 { label = "Minimum Range (m)", field = "altFalloffStartRange"  },
                 { label = "Maximum Range (m)", field = "falloffEndRange"  },
                 { label = "Maximum Range (m)", field = "altFalloffEndRange"  },
                { label = "Damage Falloff (%)", field = "falloffEndScale"  },
                 { label = "Explosion Radius (m)", field = "altExplosionRadius"  },
                 { label = "Explosion Radius (m)", field = "altExplosionRadius"  },
             }
             }
Line 489: Line 522:
     }
     }


     local output = {}
     local output = ""
     for _, def in ipairs(tableDefs) do
 
         local t = buildTable(frame, rows, def, def.options)
     for _, tableDef in ipairs(tableDefs) do
        if t ~= "" then
         local filteredRows = {}
             table.insert(output, t)
        for _, r in ipairs(rows) do
            local hasValue = false
            for _, col in ipairs(tableDef.columns) do
                if r[col.field] ~= 0 then
                    hasValue = true
                    break
                end
             end
            if hasValue then
                table.insert(filteredRows, r)
            end
         end
         end
    end


    return table.concat(output, "\n\n")
        if #filteredRows > 0 then
end
            local header = ""
            for _, col in ipairs(tableDef.columns) do
                header = header.." !! "..col.label
            end


p.heroBulletDamageTable = function(frame)
            local t = "{| class=\"wikitable sortable mw-collapsible\" style=\"text-align:center\" \n"..
    -- Pull data
                "|+ "..tableDef.title.." \n"..
    local heroBulletDamageData = heroDataArray({"Name", "Weapon>BulletDamage", "LevelScaling>BulletDamage", "Weapon>AltFire>BulletDamage", "LevelScaling>BulletDamageAltFire",
                "! Hero"..header.." \n"
    "SpiritScaling>BulletDamage", "Weapon>BulletsPerShot", "Weapon>BulletsPerBurst"})


    local rows = {}
            for _, r in ipairs(filteredRows) do
    for name, data in pairs(heroBulletDamageData) do
                local cells = ""
        table.insert(rows, {
                for _, col in ipairs(tableDef.columns) do
            name = name,
                    cells = cells.." || "..r[col.field]
            bulletDamage = data["Weapon>BulletDamage"] or 0,
                end
            bulletDamagePerShot = ((data["Weapon>BulletDamage"] or 0) * (data["Weapon>BulletsPerShot"] or 0) * (data["Weapon>BulletsPerBurst"] or 0)),
                t = t..
            scalingDamage = "+" .. data["LevelScaling>BulletDamage"] or 0,
                    "|- \n"..
            maxScalingDamage = (roundValue(data["Weapon>BulletDamage"] + data["LevelScaling>BulletDamage"] * soul_unlock.get_max("PowerIncrease"))) or 0,
                    "| style=\"text-align:left;\" | "..
            altBulletDamage = data["Weapon>AltFire>BulletDamage"] or 0,
                        frame:expandTemplate{title="PageRef", args={r.name}}..
            spiritScalingDamage = "+" .. (data["SpiritScaling>BulletDamage"] or 0),
                        cells.." \n"
        })
            end


        -- Secondary fire is listed as its own row, right under the hero's main row
            t = t.."|}"
        local altDamage = data["Weapon>AltFire>BulletDamage"]
            if output ~= "" then
        if altDamage and altDamage ~= 0 then
                 output = output.."\n\n"
            local altScaling = data["LevelScaling>BulletDamageAltFire"] or 0
            end
            table.insert(rows, {
            output = output..t
                 name = name,
                sortName = name .. " (alt fire)",
                nameSuffix = " (alt fire)",
                bulletDamage = altDamage,
                scalingDamage = "+" .. altScaling,
                maxScalingDamage = roundValue(altDamage + altScaling * soul_unlock.get_max("PowerIncrease")),
                spiritScalingDamage = "+0",
            })
         end
         end
     end
     end
    sortHeroes(rows)


     local tableDefs = {
     return z .. "\n\n" .. output
    {
            title  = "Base Bullet Damage Stats",
            columns = {
                { label = "Starting", field = "bulletDamage"  },
                { label = "Added per Boon", field = "scalingDamage"  },
                { label = "At Max Boon", field = "maxScalingDamage"  },
                { label = "Spirit Scaling", field = "spiritScalingDamage"  },
            }
        },
    }
 
    local output = {}
    for _, def in ipairs(tableDefs) do
        local t = buildTable(frame, rows, def, def.options)
        if t ~= "" then
            table.insert(output, t)
        end
    end
 
    return table.concat(output, "\n\n")
end
end


p.heroMeleeTable = function(frame)
p.heroBulletDamageTable = function(frame)
     -- Pull data
     -- Pull data
     local heroMeleeData = heroDataArray({"Name", "LightMeleeDamage", "LevelScaling>LightMeleeDamage", "HeavyMeleeDamage", "LevelScaling>HeavyMeleeDamage", "SpiritScaling>HeavyMeleeDamage"})
     local heroBulletDamageData = heroDataArray({"Name", "Weapon>BulletDamage", "LevelScaling>BulletDamage", "Weapon>AltFire>BulletDamage", "LevelScaling>BulletDamageAltFire"})


     local rows = {}
     local rows = {}
     for name, data in pairs(heroMeleeData) do
     for name, data in pairs(heroBulletDamageData) do
         table.insert(rows, {
         table.insert(rows, {
             name = name,
             name = name,
             lightMeleeDamage = data["LightMeleeDamage"] or 0,
             bulletDamage = tonumber(data["Weapon>BulletDamage"]) or 0,
            lightScalingDamage = "+" .. data["LevelScaling>LightMeleeDamage"] or 0,
             scalingDamage = tonumber(data["LevelScaling>BulletDamage"]) or 0,
             lightMaxScalingDamage = (roundValueFour(data["LightMeleeDamage"] + data["LevelScaling>LightMeleeDamage"] * soul_unlock.get_max("PowerIncrease"))) or 0,
             altBulletDamage = tonumber(data["Weapon>AltFire>BulletDamage"]) or 0,
             heavyMeleeDamage = data["HeavyMeleeDamage"] or 0,
             altScalingDamage tonumber(data["LevelScaling>BulletDamageAltFire"]) or 0
            heavyScalingDamage = "+" .. data["LevelScaling>HeavyMeleeDamage"] or 0,
             heavyMaxScalingDamage (roundValueFour(data["HeavyMeleeDamage"] + data["LevelScaling>HeavyMeleeDamage"] * soul_unlock.get_max("PowerIncrease"))) or 0,
            heavySpiritScalingDamage = "+" .. (data["SpiritScaling>HeavyMeleeDamage"] or 0),
         })
         })
     end
     end
     sortHeroes(rows)
     table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)


     local tableDefs = {
     local z = "{| class=\"wikitable sortable mw-collapsible\" style=\"text-align:center\" \n"..
    {
        "|+ Hero Base Bullet Damage Stats \n"..
            title  = "Base Light & Heavy Melee Stats",
        "! Hero !! Starting !! Added per Boon !! At Max Boon \n"
            columns = {
 
                { label = "Starting Light", field = "lightMeleeDamage" },
    -- Iterate over heroes adding a new row to the wikitable for each
                { label = "Added per Boon (L)", field = "lightScalingDamage"  },
    for _, r in ipairs(rows) do
                { label = "At Max Boon (L)", field = "lightMaxScalingDamage" },
        z = z..
                { label = "Starting Heavy", field = "heavyMeleeDamage" },
            "|- \n"..
                 { label = "Added per Boon (H)", field = "heavyScalingDamage"  },
            "| style=\"text-align:left;\" | "..
                 { label = "At Max Boon (H)", field = "heavyMaxScalingDamage" },
                 frame:expandTemplate{title="PageRef", args={r.name}}..
                 { label = "Spirit Scaling (H)", field = "heavySpiritScalingDamage" },
                 " || "..r.bulletDamage.." || +"..r.scalingDamage.." || "..
               
                 tostring(roundValue(r.bulletDamage + r.scalingDamage * soul_unlock.get_max('PowerIncrease'))).." \n"
            }
     end
        }
     }
      
      
     local output = {}
     z = z.."|}"
    for _, def in ipairs(tableDefs) do
     return z
        local t = buildTable(frame, rows, def, def.options)
        if t ~= "" then
            table.insert(output, t)
        end
    end
 
     return table.concat(output, "\n\n")
end
end


Line 611: Line 614:
         table.insert(rows, {
         table.insert(rows, {
             name = name,
             name = name,
             lightMeleeDamage = data["LightMeleeDamage"] or 0,
             lightMeleeDamage = tonumber(data["LightMeleeDamage"]) or 0,
             scalingDamage = "+" .. data["LevelScaling>LightMeleeDamage"] or 0,
             scalingDamage = tonumber(data["LevelScaling>LightMeleeDamage"]) or 0
            maxScalingDamage =  (roundValueFour(data["LightMeleeDamage"] + data["LevelScaling>LightMeleeDamage"] * soul_unlock.get_max("PowerIncrease"))) or 0,
         })
         })
     end
     end
     sortHeroes(rows)
     table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)


     local tableDefs = {
     local z = "{| class=\"wikitable sortable mw-collapsible\" style=\"text-align:center\" \n"..
    {
        "|+ Hero Base Light Melee Stats \n"..
            title  = "Base Light Melee Stats",
        "! Hero !! Starting !! Added per Boon !! At Max Boon \n"
            columns = {
 
                { label = "Starting", field = "lightMeleeDamage" },
    -- Iterate over heroes adding a new row to the wikitable for each
                 { label = "Added per Boon", field = "scalingDamage"  },
    for _, r in ipairs(rows) do
                 { label = "At Max Boon", field = "maxScalingDamage" },
        z = z..
            }
            "|- \n"..
        }
            "| style=\"text-align:left;\" | "..
     }
                 frame:expandTemplate{title="PageRef", args={r.name}}..
                 " || "..r.lightMeleeDamage.." || +"..r.scalingDamage.." || "..
                tostring(roundValue(r.lightMeleeDamage + r.scalingDamage * soul_unlock.get_max('PowerIncrease'))).." \n"
     end
      
      
     local output = {}
     z = z.."|}"
    for _, def in ipairs(tableDefs) do
     return z
        local t = buildTable(frame, rows, def, def.options)
        if t ~= "" then
            table.insert(output, t)
        end
    end
 
     return table.concat(output, "\n\n")
end
end


p.heroHeavyMeleeTable = function(frame)
p.heroHeavyMeleeTable = function(frame)
     -- Pull data
     -- Pull data
     local heroHeavyMeleeData = heroDataArray({"Name", "HeavyMeleeDamage", "LevelScaling>HeavyMeleeDamage", "SpiritScaling>HeavyMeleeDamage"})
     local heroHeavyMeleeData = heroDataArray({"Name", "HeavyMeleeDamage", "LevelScaling>HeavyMeleeDamage"})


     local rows = {}
     local rows = {}
Line 648: Line 646:
         table.insert(rows, {
         table.insert(rows, {
             name = name,
             name = name,
             heavyMeleeDamage = data["HeavyMeleeDamage"] or 0,
             heavyMeleeDamage = tonumber(data["HeavyMeleeDamage"]) or 0,
             scalingDamage = "+" .. data["LevelScaling>HeavyMeleeDamage"] or 0,
             scalingDamage = tonumber(data["LevelScaling>HeavyMeleeDamage"]) or 0
            maxScalingDamage = (roundValueFour(data["HeavyMeleeDamage"] + data["LevelScaling>HeavyMeleeDamage"] * soul_unlock.get_max("PowerIncrease"))) or 0,
            spiritScalingDamage = "+" .. (data["SpiritScaling>HeavyMeleeDamage"] or 0),
         })
         })
     end
     end
     sortHeroes(rows)
     table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)
 
    local z = "{| class=\"wikitable sortable mw-collapsible\" style=\"text-align:center\" \n"..
        "|+ Hero Base Heavy Melee Stats \n"..
        "! Hero !! Starting !! Added per Boon !! At Max Boon \n"


     local tableDefs = {
     -- Iterate over heroes adding a new row to the wikitable for each
    {
    for _, r in ipairs(rows) do
             title  = "Base Heavy Melee Stats",
        z = z..
             columns = {
             "|- \n"..
                { label = "Starting", field = "heavyMeleeDamage"  },
             "| style=\"text-align:left;\" | "..
                 { label = "Added per Boon", field = "scalingDamage"  },
                 frame:expandTemplate{title="PageRef", args={r.name}}..
                 { label = "At Max Boon", field = "maxScalingDamage" },
                 " || "..r.heavyMeleeDamage.." || +"..r.scalingDamage.." || "..
                 { label = "Spirit Scaling", field = "spiritScalingDamage"  },
                 tostring(roundValue(r.heavyMeleeDamage + r.scalingDamage * soul_unlock.get_max('PowerIncrease'))).." \n"
            }
     end
        }
     }
      
      
     local output = {}
     z = z.."|}"
    for _, def in ipairs(tableDefs) do
     return z
        local t = buildTable(frame, rows, def, def.options)
        if t ~= "" then
            table.insert(output, t)
        end
    end
 
     return table.concat(output, "\n\n")
end
end


Line 690: Line 681:
         })
         })
     end
     end
     sortHeroes(rows)
     table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)
 
    local z = "{| class=\"wikitable sortable mw-collapsible\" style=\"text-align:center\" \n"..
        "|+ Hero Base Stamina Stats \n"..
        "! Hero !! Stamina Bars !! Cooldown (s) \n"


     local tableDefs = {
     for _, r in ipairs(rows) do
    {
        z = z..
             title  = "Base Stamina Stats",
             "|- \n"..
             columns = {
             "| style=\"text-align:left;\" | "..
                 { label = "Stamina Bars", field = "stamina"  },
                 frame:expandTemplate{title="PageRef", args={r.name}}..
                 { label = "Cooldown (s)", field = "staminaCooldown"  },
                 " || "..r.stamina.." || "..r.staminaCooldown.." \n"
            }
        }
    }
   
    local output = {}
    for _, def in ipairs(tableDefs) do
        local t = buildTable(frame, rows, def, def.options)
        if t ~= "" then
            table.insert(output, t)
        end
     end
     end
 
     z = z.."|}"
     return table.concat(output, "\n\n")
    return z
end
end


p.heroDashTable = function(frame)
p.heroDashTable = function(frame)
     local heroDashData = heroDataArray({"Name", "GroundDashSpeed", "GroundDashDuration", "AirDashSpeed", "AirDashDuration"})
     local heroDashData = heroDataArray({"Name", "GroundDashSpeed"})


     local rows = {}
     local rows = {}
Line 720: Line 705:
         table.insert(rows, {
         table.insert(rows, {
             name    = name,
             name    = name,
             dashSpeed = data["GroundDashSpeed"] or 0,
             duration = tonumber(data.GroundDashSpeed) or 0
            dashDuration = data["GroundDashDuration"] or 0,
            airDashSpeed = data["AirDashSpeed"] or 0,
            airDashDuration = data["AirDashDuration"] or 0,
         })
         })
     end
     end
     sortHeroes(rows)
     table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)
   
 
     local tableDefs = {
     local z = '{| class="wikitable sortable mw-collapsible" style="text-align:center"\n' ..
    {
              '|+ Hero Base Dash Speed Stats\n' ..
            title  = "Base Dash Speed Stats",
              '! Hero !! Dash Speed (m/s)\n'
            columns = {
     for _, r in ipairs(rows) do
                { label = "Dash Speed (m/s)", field = "dashSpeed"  },
         z = z .. '|-\n| style="text-align:left;" | ' ..
                { label = "Dash Duration (s)", field = "dashDuration"  },
              frame:expandTemplate{title = 'PageRef', args = {r.name}} ..
                { label = "Air Dash Speed (m/s)", field = "airDashSpeed"  },
              ' || ' .. r.duration .. '\n'
                { label = "Air Dash Duration (s)", field = "airDashDuration"  },
            }
        }
    }
   
    local output = {}
     for _, def in ipairs(tableDefs) do
         local t = buildTable(frame, rows, def, def.options)
        if t ~= "" then
            table.insert(output, t)
        end
     end
     end
 
     return z .. '|}'
     return table.concat(output, "\n\n")
end
end


Line 754: Line 724:
     local heroReloadData = heroDataArray({"Name", "Weapon>ReloadTime"})
     local heroReloadData = heroDataArray({"Name", "Weapon>ReloadTime"})


    -- 1. collect rows
     local rows = {}
     local rows = {}
     for name, data in pairs(heroReloadData) do
     for name, data in pairs(heroReloadData) do
         table.insert(rows, {
         table.insert(rows, {
             name      = name,
             name      = name,
             reloadTime = data["Weapon>ReloadTime"] or 0
             reloadTime = tonumber(data["Weapon>ReloadTime"]) or 0
         })
         })
     end
     end


     sortHeroes(rows)
     -- 2. alphabetical by hero name
    table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)


     local tableDefs = {
    -- 3. build table
    {
     local z = '{| class="wikitable sortable mw-collapsible" style="text-align:center"\n' ..
            title  = "Base Reload Time",
              '|+ Hero Base Reload Time Stats\n' ..
            columns = {
              '! Hero !! Reload Time (s) \n'
                { label = "Reload Time (s)", field = "reloadTime"  },
 
            }
     for _, r in ipairs(rows) do
        }
         z = z ..
    }
            '|-\n' ..
   
            '| style="text-align:left;" | ' ..
    local output = {}
             frame:expandTemplate{title = 'PageRef', args = {r.name}} ..
     for _, def in ipairs(tableDefs) do
            ' || '.. r.reloadTime ..' \n'
         local t = buildTable(frame, rows, def, def.options)
        if t ~= "" then
             table.insert(output, t)
        end
     end
     end
 
     return z .. '|}'
     return table.concat(output, "\n\n")
end
end


Line 794: Line 761:
         })
         })
     end
     end
     sortHeroes(rows)
     table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)


     local tableDefs = {
     local tableDefs = {
     {
     {
             title  = "Base Reload Delay",
             title  = "Hero Base Reload Delay Stats",
             columns = {
             columns = {
                 { label = "Reload Delay (s)", field = "reloadDelay"  }
                 { label = "Reload Delay (s)", field = "reloadDelay"  }
Line 805: Line 772:
     }
     }


     local output = {}
     local output = ""
     for _, def in ipairs(tableDefs) do
 
         local t = buildTable(frame, rows, def, def.options)
     for _, tableDef in ipairs(tableDefs) do
        if t ~= "" then
         local filteredRows = {}
             table.insert(output, t)
        for _, r in ipairs(rows) do
            local hasValue = false
            for _, col in ipairs(tableDef.columns) do
                if r[col.field] ~= 0 then
                    hasValue = true
                    break
                end
             end
            if hasValue then
                table.insert(filteredRows, r)
            end
        end
 
        if #filteredRows > 0 then
            local header = ""
            for _, col in ipairs(tableDef.columns) do
                header = header.." !! "..col.label
            end
 
            local t = "{| class=\"wikitable sortable mw-collapsible\" style=\"text-align:center\" \n"..
                "|+ "..tableDef.title.." \n"..
                "! Hero"..header.." \n"
 
            for _, r in ipairs(filteredRows) do
                local cells = ""
                for _, col in ipairs(tableDef.columns) do
                    cells = cells.." || "..r[col.field]
                end
                t = t..
                    "|- \n"..
                    "| style=\"text-align:left;\" | "..
                        frame:expandTemplate{title="PageRef", args={r.name}}..
                        cells.." \n"
            end
 
            t = t.."|}"
            if output ~= "" then
                output = output.."\n\n"
            end
            output = output..t
         end
         end
     end
     end


     return table.concat(output, "\n\n")
     return output
end
end


p.heroMoveSpeedTable = function(frame)
p.heroMoveSpeedTable = function(frame)
     local heroMoveSpeedData = heroDataArray({"Name", "MaxMoveSpeed", "SprintSpeed", "Weapon>ShootMoveSpeed", "SpiritScaling>MaxMoveSpeed", "SpiritScaling>SprintSpeed"})
     local heroMoveSpeedData = heroDataArray({"Name", "MaxMoveSpeed", "SprintSpeed"})


     local rows = {}
     local rows = {}
Line 823: Line 829:
         table.insert(rows, {
         table.insert(rows, {
             name = name,
             name = name,
             moveSpeed = data["MaxMoveSpeed"] or 0,
             moveSpeed = tonumber(data["MaxMoveSpeed"]) or 0,
             sprintSpeed = data["SprintSpeed"] or 0,
             sprintSpeed = tonumber(data["SprintSpeed"]) or 0
            totalSpeed = data["MaxMoveSpeed"] + data["SprintSpeed"] or 0,
            shootSpeed = (data["Weapon>ShootMoveSpeed"] or 0) * 100,
            totalShootingSpeed = roundValue((data["MaxMoveSpeed"] + data["SprintSpeed"] or 0) * (data["Weapon>ShootMoveSpeed"] or 0)),
            spiritMoveSpeed = "+" .. (data["SpiritScaling>MaxMoveSpeed"] or 0),
            spiritSprintSpeed = "+" .. (data["SpiritScaling>SprintSpeed"] or 0),
         })
         })
     end
     end
     sortHeroes(rows)
     table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)


     local tableDefs = {
     local z = "{| class=\"wikitable sortable mw-collapsible\" style=\"text-align:center\" \n"..
    {
        "|+ Hero Base Move Speed Stats \n"..
            title  = "Base Move Speed Stats",
        "! Hero !! Move Speed (m/s) !! Sprint Speed (m/s) !! Total Speed (m/s) \n"
            columns = {
                { label = "Move Speed (m/s)", field = "moveSpeed"  },
                { label = "Sprint Speed (m/s)", field = "sprintSpeed"  },
                { label = "Total Speed (m/s)", field = "totalSpeed"  },
                { label = "Shooting Speed (m/s)", field = "totalShootingSpeed"  },
                { label = "Shooting Mult (%)", field = "shootSpeed"  },
                { label = "MS Spirit Scaling", field = "spiritMoveSpeed"  },
                { label = "SS Spirit Scaling", field = "spiritSprintSpeed"  },
            }
        }   
    }


    local output = {}
     for _, r in ipairs(rows) do
     for _, def in ipairs(tableDefs) do
         z = z..
         local t = buildTable(frame, rows, def, def.options)
            "|- \n"..
        if t ~= "" then
             "| style=\"text-align:left;\" | "..
             table.insert(output, t)
                frame:expandTemplate{title="PageRef", args={r.name}}..
        end
                " || "..r.moveSpeed.." || "..r.sprintSpeed.." || "..r.moveSpeed + r.sprintSpeed .." \n"
     end
     end
 
     z = z.."|}"
     return table.concat(output, "\n\n")
    return z
end
end


p.heroDamageResistTable = function(frame)
p.heroDamageResistTable = function(frame)
     local heroDamageResistData = heroDataArray({"Name", "BulletResist", "LevelScaling>BulletResist", "TechResist", "LevelScaling>TechResist", "MeleeResist", "CritDamageReceivedPercent",
     local heroDamageResistData = heroDataArray({"Name", "BulletResist", "LevelScaling>BulletResist", "TechResist", "LevelScaling>TechResist", "MeleeResist", "CritDamageReceivedPercent"})
  "SpiritScaling>BulletResist", "SpiritScaling>TechResist",
    })


     local rows = {}
     local rows = {}
Line 870: Line 858:
             name = name,
             name = name,
             bulletResist  = data["BulletResist"] or 0,
             bulletResist  = data["BulletResist"] or 0,
             bulletResistScaling = "+".. (data["LevelScaling>BulletResist"] or 0),
             bulletScaling = data["LevelScaling>BulletResist"] or 0,
            bulletResistScalingMax = ((roundValue((data["BulletResist"] or 0) + (data["LevelScaling>BulletResist"] or 0) * soul_unlock.get_max("PowerIncrease"))) or 0),
            bulletResistSpiritScaling = "+".. (data["SpiritScaling>BulletResist"] or 0),
             spiritResist  = data["TechResist"] or 0,
             spiritResist  = data["TechResist"] or 0,
             spiritResistScaling = "+".. (data["LevelScaling>TechResist"] or 0),
             spiritScaling = data["LevelScaling>TechResist"] or 0,
            spiritResistScalingMax = ((roundValue((data["TechResist"] or 0) + (data["LevelScaling>TechResist"] or 0) * soul_unlock.get_max("PowerIncrease"))) or 0),
            spiritResistSpiritScaling = "+".. (data["SpiritScaling>TechResist"] or 0),
             meleeResist  = data["MeleeResist"] or 0,
             meleeResist  = data["MeleeResist"] or 0,
             critReduction = data["CritDamageReceivedPercent"] or 0
             critReduction = data["CritDamageReceivedPercent"] or 0
         })
         })
     end
     end
     sortHeroes(rows)
     table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)


     local tableDefs = {
     local tableDefs = {
         {
         {
             title  = "Base Bullet Resist Stats",
             title  = "Hero Base Bullet Resist Stats",
             columns = {
             columns = {
                 { label = "Starting (%)", field = "bulletResist"  },
                 { label = "Bullet Resist (%)", field = "bulletResist"  },
                 { label = "Added per Boon (%)",  field = "bulletResistScaling" },
                 { label = "BR per Boon (%)",  field = "bulletScaling" },
                { label = "At Max Boon (%)",  field = "bulletResistScalingMax" },
                { label = "Spirit Scaling (%)",  field = "bulletResistSpiritScaling" },
             }
             }
         },
         },
         {
         {
             title  = "Base Spirit Resist Stats",
             title  = "Hero Base Spirit Resist Stats",
             columns = {
             columns = {
                 { label = "Starting (%)", field = "spiritResist"  },
                 { label = "Spirit Resist (%)", field = "spiritResist"  },
                 { label = "Added per Boon (%)",  field = "spiritResistScaling" },
                 { label = "SR per Boon (%)",  field = "spiritScaling" },
                { label = "At Max Boon (%)",  field = "spiritResistScalingMax" },
                { label = "Spirit Scaling (%)",  field = "spiritResistSpiritScaling" },
             }
             }
         },
         },
         {
         {
             title  = "Base Melee Resist Stats",
             title  = "Hero Base Melee Resist Stats",
             columns = {
             columns = {
                 { label = "Melee Resist (%)", field = "meleeResist" },
                 { label = "Melee Resist (%)", field = "meleeResist" },
Line 909: Line 889:
         },
         },
         {
         {
             title  = "Base Crit Reduction Stats",
             title  = "Hero Base Crit Reduction Stats",
             columns = {
             columns = {
                 { label = "Crit Reduction (%)", field = "critReduction" },
                 { label = "Crit Reduction (%)", field = "critReduction" },
Line 916: Line 896:
     }
     }


     local output = {}
     local output = ""
    for _, def in ipairs(tableDefs) do
        local t = buildTable(frame, rows, def, def.options)
        if t ~= "" then
            table.insert(output, t)
        end
    end
 
    return table.concat(output, "\n\n")
end


p.heroCritTable = function(frame)
     for _, tableDef in ipairs(tableDefs) do
     local heroCritData = heroDataArray({"Name", "CritDamageBonusPercent"})
        local filteredRows = {}
 
        for _, r in ipairs(rows) do
    local rows = {}
             local hasValue = false
    for name, data in pairs(heroCritData) do
             for _, col in ipairs(tableDef.columns) do
        table.insert(rows, {
                if r[col.field] ~= 0 then
             name = name,
                    hasValue = true
            critBonusScale  = data["CritDamageBonusPercent"] or 0
                    break
        })
                end
    end
            end
    sortHeroes(rows)
             if hasValue then
 
                table.insert(filteredRows, r)
    local tableDefs = {
            end
    {
            title  = "Base Crit Bonus Scale Stats",
            columns = {
                { label = "Crit Bonus Scale (%)", field = "critBonusScale"  }
             }
        }   
    }
 
    local output = {}
    for _, def in ipairs(tableDefs) do
        local t = buildTable(frame, rows, def, def.options)
        if t ~= "" then
             table.insert(output, t)
         end
         end
    end


    return table.concat(output, "\n\n")
        if #filteredRows > 0 then
end
            local header = ""
            for _, col in ipairs(tableDef.columns) do
                header = header.." !! "..col.label
            end


p.heroSpiritTable = function(frame)
            local t = "{| class=\"wikitable sortable mw-collapsible\" style=\"text-align:center\" \n"..
    local heroSpiritData = heroDataArray({"Name", "LevelScaling>TechPower"})
                "|+ "..tableDef.title.." \n"..
                "! Hero"..header.." \n"


    local rows = {}
            for _, r in ipairs(filteredRows) do
    for name, data in pairs(heroSpiritData) do
                local cells = ""
        table.insert(rows, {
                for _, col in ipairs(tableDef.columns) do
            name = name,
                    cells = cells.." || "..r[col.field]
            spiritScaling  = "+".. data["LevelScaling>TechPower"] or 0,
                end
            maxSpiritScaling = (data["LevelScaling>TechPower"] * soul_unlock.get_max("PowerIncrease")) or 0,
                t = t..
        })
                    "|- \n"..
    end
                    "| style=\"text-align:left;\" | "..
    sortHeroes(rows)
                        frame:expandTemplate{title="PageRef", args={r.name}}..
                        cells.." \n"
            end


    local tableDefs = {
             t = t.."|}"
    {
             if output ~= "" then
             title  = "Spirit Scaling Stats",
                 output = output.."\n\n"
             columns = {
             end
                { label = "Spirit Per Boon", field = "spiritScaling"  },
            output = output..t
                 { label = "At Max Boon", field = "maxSpiritScaling"  },
             }
        }   
    }
 
    local output = {}
    for _, def in ipairs(tableDefs) do
        local t = buildTable(frame, rows, def, def.options)
        if t ~= "" then
            table.insert(output, t)
         end
         end
     end
     end


     return table.concat(output, "\n\n")
     return output
end
end


p.heroGravityTable = function(frame)
p.heroCritTable = function(frame)
     local heroGravityData = heroDataArray({"Name", "GravityChange"})
     local heroCritData = heroDataArray({"Name", "CritDamageBonusPercent"})


     local rows = {}
     local rows = {}
     for name, data in pairs(heroGravityData) do
     for name, data in pairs(heroCritData) do
         table.insert(rows, {
         table.insert(rows, {
             name = name,
             name = name,
             gravityScale = (data["GravityChange"] or 0),
             critBonusScale = data["CritDamageBonusPercent"] or 0
         })
         })
     end
     end
     sortHeroes(rows)
     table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)


     local tableDefs = {
     local tableDefs = {
     {
     {
             title  = "Base Gravity Scale Stats",
             title  = "Hero Base Crit Bonus Scale Stats",
             columns = {
             columns = {
                 { label = "Gravity Scale (%)", field = "gravityScale"  },
                 { label = "Crit Bonus Scale (%)", field = "critBonusScale"  }
             }
             }
         }     
         }     
     }
     }


     local output = {}
     local output = ""
    for _, def in ipairs(tableDefs) do
        local t = buildTable(frame, rows, def, def.options)
        if t ~= "" then
            table.insert(output, t)
        end
    end


     return table.concat(output, "\n\n")
     for _, tableDef in ipairs(tableDefs) do
end
        local filteredRows = {}
 
        for _, r in ipairs(rows) do
p.bulletGravityTable = function(frame)
             local hasValue = false
    local heroGravityData = heroDataArray({"Name", "Weapon>BulletGravityScale", "Weapon>AltFire>BulletGravityScale"})
             for _, col in ipairs(tableDef.columns) do
 
                if r[col.field] ~= 0 then
    local rows = {}
                    hasValue = true
    for name, data in pairs(heroGravityData) do
                    break
        table.insert(rows, {
                 end
             name = name,
             end
             gravityScale  = (data["Weapon>BulletGravityScale"] or 0),
             if hasValue then
            altGravityScale  = (data["Weapon>AltFire>BulletGravityScale"] or 0),
                table.insert(filteredRows, r)
        })
            end
    end
    sortHeroes(rows)
 
    local tableDefs = {
    {
            title  = "Base Bullet Gravity Scale Stats",
            columns = {
                 { label = "Gravity Scale", field = "gravityScale"  },
             }
        },
        {
            title  = "Base Alt-fire Bullet Gravity Scale Stats",
            columns = {
                { label = "Gravity Scale", field = "altGravityScale"  },
             }
        }
    }
 
    local output = {}
    for _, def in ipairs(tableDefs) do
        local t = buildTable(frame, rows, def, def.options)
        if t ~= "" then
            table.insert(output, t)
         end
         end
    end


    return table.concat(output, "\n\n")
        if #filteredRows > 0 then
end
            local header = ""
            for _, col in ipairs(tableDef.columns) do
                header = header.." !! "..col.label
            end


p.bulletRadiusTable = function(frame)
            local t = "{| class=\"wikitable sortable mw-collapsible\" style=\"text-align:center\" \n"..
    local heroBulletRadiusData = heroDataArray({"Name", "Weapon>BulletRadius", "Weapon>AltFire>BulletRadius"})
                "|+ "..tableDef.title.." \n"..
                "! Hero"..header.." \n"


    local rows = {}
            for _, r in ipairs(filteredRows) do
    for name, data in pairs(heroBulletRadiusData) do
                local cells = ""
        table.insert(rows, {
                for _, col in ipairs(tableDef.columns) do
            name = name,
                    cells = cells.." || "..r[col.field]
            bulletRadius  = (data["Weapon>BulletRadius"] or 0) * 100,
                end
            bulletRadiusInches  = roundValueInteger((data["Weapon>BulletRadius"] or 0) * 100 * 0.394),
                t = t..
            altBulletRadius  = (data["Weapon>AltFire>BulletRadius"] or 0) * 100,
                    "|- \n"..
            altBulletRadiusInches  = roundValueInteger((data["Weapon>AltFire>BulletRadius"] or 0) * 100 * 0.394),
                    "| style=\"text-align:left;\" | "..
        })
                        frame:expandTemplate{title="PageRef", args={r.name}}..
       
                        cells.." \n"
        local altBulletRadius = (data["Weapon>AltFire>BulletRadius"] or 0) * 100
             end
        local altBulletRadiusInches  = roundValueInteger((data["Weapon>AltFire>BulletRadius"] or 0) * 100 * 0.394)
        if altBulletRadius and altBulletRadius ~= 0 then
            table.insert(rows, {
                name = name,
                sortName = name .. " (alt fire)",
                nameSuffix = " (alt fire)",
                bulletRadius = altBulletRadius,
                bulletRadiusInches = altBulletRadiusInches
             })
        end
    end
    sortHeroes(rows)


    local tableDefs = {
             t = t.."|}"
    {
             if output ~= "" then
             title  = "Base Bullet Radius Stats",
                 output = output.."\n\n"
             columns = {
             end
                { label = "Bullet Radius (cm)", field = "bulletRadius"  },
            output = output..t
                 { label = "Bullet Radius (in)", field = "bulletRadiusInches"  },
             }
        }
    }
 
    local output = {}
    for _, def in ipairs(tableDefs) do
        local t = buildTable(frame, rows, def, def.options)
        if t ~= "" then
            table.insert(output, t)
         end
         end
     end
     end


     return table.concat(output, "\n\n")
     return output
end
end


return p
return p
Please note that all contributions to The Deadlock Wiki are considered to be released under the Creative Commons Attribution-NonCommercial-ShareAlike (see Deadlock:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!
Cancel Editing help (opens in new window)
Preview page with this template

Page included on this page: