Module:HeroDataArrays: Difference between revisionsGive feedback
Jump to navigation
Jump to search
Gammaton32 (talk | contribs) No edit summary |
Gammaton32 (talk | contribs) added more alt fire stats |
||
| Line 159: | Line 159: | ||
local tableDefs = { | local tableDefs = { | ||
{ | { | ||
title = "Hero Base Alt Fire Damage", | title = "Hero Base Alt-Fire Damage", | ||
columns = { | columns = { | ||
{ label = "Damage per sec", field = "altDPS" }, | { label = "Damage per sec", field = "altDPS" }, | ||
| Line 221: | Line 221: | ||
p.heroBulletSpeedTable = function(frame) | p.heroBulletSpeedTable = function(frame) | ||
local heroBulletSpeedData = heroDataArray({"Name", "Weapon>BulletSpeed"}) | local heroBulletSpeedData = heroDataArray({"Name", "Weapon>BulletSpeed", "Weapon>AltFire>BulletSpeed"}) | ||
local rows = {} | local rows = {} | ||
| Line 227: | Line 227: | ||
table.insert(rows, { | table.insert(rows, { | ||
name = name, | name = name, | ||
bulletSpeed = data["Weapon>BulletSpeed"] or 0 | bulletSpeed = data["Weapon>BulletSpeed"] or 0, | ||
altBulletSpeed = data["Weapon>AltFire>BulletSpeed"] or 0 | |||
}) | }) | ||
end | end | ||
| Line 244: | Line 245: | ||
end | end | ||
z = z.."|}" | z = z.."|}" | ||
return z | table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end) | ||
local tableDefs = { | |||
{ | |||
title = "Base Alt-Fire Bullet Velocity", | |||
columns = { | |||
{ label = "m/s", field = "altBulletSpeed" }, | |||
} | |||
} | |||
} | |||
local output = "" | |||
for _, tableDef in ipairs(tableDefs) do | |||
local filteredRows = {} | |||
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 | |||
return z .. "\n\n" .. output | |||
end | end | ||
p.heroClipSizeTable = function(frame) | p.heroClipSizeTable = function(frame) | ||
local heroClipSizeData = heroDataArray({"Name", "Weapon>ClipSize"}) | local heroClipSizeData = heroDataArray({"Name", "Weapon>ClipSize","Weapon>AltFire>AmmoConsumedPerShot"}) | ||
local rows = {} | local rows = {} | ||
| Line 254: | Line 313: | ||
table.insert(rows, { | table.insert(rows, { | ||
name = name, | name = name, | ||
clipSize = data["Weapon>ClipSize"] or 0 | clipSize = data["Weapon>ClipSize"] or 0, | ||
ammoConsumedPerShot = data["Weapon>AltFire>AmmoConsumedPerShot"] or 0 | |||
}) | }) | ||
end | end | ||
| Line 271: | Line 331: | ||
end | end | ||
z = z.."|}" | z = z.."|}" | ||
return z | |||
table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end) | |||
local tableDefs = { | |||
{ | |||
title = "Alt-Fire Ammo Cost", | |||
columns = { | |||
{ label = "Ammo Per Shot", field = "ammoConsumedPerShot" }, | |||
} | |||
} | |||
} | |||
local output = "" | |||
for _, tableDef in ipairs(tableDefs) do | |||
local filteredRows = {} | |||
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 | |||
return z .. "\n\n" .. output | |||
end | end | ||
p.heroRoundsPerSecondTable = function(frame) | p.heroRoundsPerSecondTable = function(frame) | ||
local heroRoundsPerSecondData = heroDataArray({"Name", "Weapon>RoundsPerSecond"}) | local heroRoundsPerSecondData = heroDataArray({"Name", "Weapon>RoundsPerSecond", "Weapon>AltFire>RoundsPerSecond"}) | ||
local rows = {} | local rows = {} | ||
| Line 281: | Line 400: | ||
table.insert(rows, { | table.insert(rows, { | ||
name = name, | name = name, | ||
roundsPerSecond = data["Weapon>RoundsPerSecond"] or 0 | roundsPerSecond = data["Weapon>RoundsPerSecond"] or 0, | ||
altRoundsPerSecond = data["Weapon>AltFire>RoundsPerSecond"] or 0 | |||
}) | }) | ||
end | end | ||
| Line 298: | Line 418: | ||
end | end | ||
z = z.."|}" | z = z.."|}" | ||
return z | |||
table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end) | |||
local tableDefs = { | |||
{ | |||
title = "Base Alt-Fire Fire Rate", | |||
columns = { | |||
{ label = "Rounds/s", field = "altRoundsPerSecond" }, | |||
} | |||
} | |||
} | |||
local output = "" | |||
for _, tableDef in ipairs(tableDefs) do | |||
local filteredRows = {} | |||
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 | |||
return z .. "\n\n" .. output | |||
end | end | ||
p.heroFalloffRangeTable = function(frame) | p.heroFalloffRangeTable = function(frame) | ||
local heroFalloffRangeData = heroDataArray({"Name", "Weapon>FalloffStartRange", "Weapon>FalloffEndRange"}) | local heroFalloffRangeData = heroDataArray({"Name", "Weapon>FalloffStartRange", "Weapon>FalloffEndRange", "Weapon>AltFire>FalloffStartRange", "Weapon>AltFire>FalloffEndRange", | ||
"Weapon>AltFire>ExplosionRadius"}) | |||
local rows = {} | local rows = {} | ||
| Line 309: | Line 489: | ||
name = name, | name = name, | ||
falloffStartRange = data["Weapon>FalloffStartRange"] or 0, | falloffStartRange = data["Weapon>FalloffStartRange"] or 0, | ||
falloffEndRange = data["Weapon>FalloffEndRange"] or 0 | falloffEndRange = data["Weapon>FalloffEndRange"] or 0, | ||
altFalloffStartRange = data["Weapon>AltFire>FalloffStartRange"] or 0, | |||
altFalloffEndRange = data["Weapon>AltFire>FalloffEndRange"] or 0, | |||
altExplosionRadius = data["Weapon>AltFire>ExplosionRadius"] or 0 | |||
}) | }) | ||
end | end | ||
| Line 326: | Line 509: | ||
end | end | ||
z = z.."|}" | z = z.."|}" | ||
return z | table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end) | ||
local tableDefs = { | |||
{ | |||
title = "Base Alt-Fire Falloff Range", | |||
columns = { | |||
{ label = "Minimum Range (m)", field = "altFalloffStartRange" }, | |||
{ label = "Maximum Range (m)", field = "altFalloffEndRange" }, | |||
{ label = "Explosion Radius (m)", field = "altExplosionRadius" }, | |||
} | |||
} | |||
} | |||
local output = "" | |||
for _, tableDef in ipairs(tableDefs) do | |||
local filteredRows = {} | |||
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 | |||
return z .. "\n\n" .. output | |||
end | end | ||
p.heroBulletDamageTable = function(frame) | p.heroBulletDamageTable = function(frame) | ||
-- Pull data | -- Pull data | ||
local heroBulletDamageData = heroDataArray({"Name", "Weapon>BulletDamage", "LevelScaling>BulletDamage"}) | local heroBulletDamageData = heroDataArray({"Name", "Weapon>BulletDamage", "LevelScaling>BulletDamage", "Weapon>AltFire>BulletDamage", "LevelScaling>BulletDamageAltFire"}) | ||
local rows = {} | local rows = {} | ||
| Line 338: | Line 581: | ||
name = name, | name = name, | ||
bulletDamage = tonumber(data["Weapon>BulletDamage"]) or 0, | bulletDamage = tonumber(data["Weapon>BulletDamage"]) or 0, | ||
scalingDamage = tonumber(data["LevelScaling>BulletDamage"]) or 0 | scalingDamage = tonumber(data["LevelScaling>BulletDamage"]) or 0, | ||
altBulletDamage = tonumber(data["Weapon>AltFire>BulletDamage"]) or 0, | |||
altScalingDamage = tonumber(data["LevelScaling>BulletDamageAltFire"]) or 0 | |||
}) | }) | ||
end | end | ||
Revision as of 22:49, 22 April 2026
Overview
This module consists of one generic function, heroDataArray, and a series of functions that create specific wikitables using the output from heroDataArray.
local p = {};
local util_module = require('Module:Utilities')
local allHeroData = mw.loadJsonData("Data:HeroData.json")
local soul_unlock = require('Module:SoulUnlock')
local inGameHeroData = {}
-- Just get heroes that are playable and have a "name" in HeroData
for i, heroData in pairs(allHeroData) do
if heroData["InDevelopment"] == false then
if heroData["IsDisabled"] == false then
if heroData["Name"] ~= nil then
table.insert(inGameHeroData, heroData)
end
end
end
end
-- Helper function to round numeric values
local function roundValue(value)
if type(value) == "number" then
return util_module.round_to_sig_fig(value, 3)
end
return value
end
-- heroDataArray takes as argument a table of any length containing keys or
-- paths of keys in the HeroData JSON, e.g. {Name, MaxHealth, LevelScaling>Health}.
-- A path of keys should be specified as such, with the ">" character separating
-- subsequent keys.
local heroDataArray = function(args)
local outData = {}
for i, heroData in ipairs(inGameHeroData) do -- Iterate over each hero
local out = {} -- First creating a table to hold data
for j, key in pairs(args) do -- Iterate over each key:
if string.find(key, ">") ~= nil then -- If the key is actually a path of keys,
local node = heroData -- start with the biggest node heroData, and
for k in string.gmatch(key, "([^>]+)") do -- iterate over each key, splitting on ">",
if node and node[k] ~= nil then -- trying the key as a string e.g. "1", (Added 'node and' for safety)
node = node[k]
elseif node and node[tonumber(k)] ~= nil then -- else using the key as numeric, (Added 'node and' for safety)
node = node[tonumber(k)]
else -- If at any point the path breaks, the result is nil
node = nil
break
end -- drilling down the JSON node after node
end
out[key] = roundValue(node) -- until outputting the final node (rounded)
else
out[key] = roundValue(heroData[key]) -- or just grab the data if not a path (rounded)
end
end
outData[heroData["Name"]] = out -- Save data in the big table of heroes
end
return(outData)
end
p.heroHealthTable = function(frame)
-- Pull data
local heroHealthData = heroDataArray({"Name", "MaxHealth", "LevelScaling>MaxHealth"})
local rows = {}
for name, data in pairs(heroHealthData) do
table.insert(rows, {
name = name,
maxHealth = tonumber(data["MaxHealth"]) or 0,
scalingHealth = tonumber(data["LevelScaling>MaxHealth"]) or 0
})
end
table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)
-- Input table will be called a, output wikitable will be called z
local z = "{| class=\"wikitable sortable mw-collapsible\" style=\"text-align:center\" \n"..
"|+ Hero Base Health Stats \n"..
"! Hero !! Starting !! Added per Boon !! At Max Boon \n"
-- Iterate over heroes adding a new row to the wikitable for each
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
z = z.."|}"
return z
end
p.heroRegenTable = function(frame)
local heroRegenData = heroDataArray({"Name", "BaseHealthRegen"})
local rows = {}
for name, data in pairs(heroRegenData) do
table.insert(rows, {
name = name,
baseHealthRegen = data["BaseHealthRegen"] 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 Health Regen \n"..
"! Hero !! HP/s \n"
for _, r in ipairs(rows) do
z = z..
"|- \n"..
"| style=\"text-align:left;\" | "..
frame:expandTemplate{title="PageRef", args={r.name}}..
" || "..r.baseHealthRegen.." \n"
end
z = z.."|}"
return z
end
p.heroDpsTable = function(frame)
local heroDpsData = heroDataArray({"Name","Weapon>DPS","Weapon>ReloadSingle","Weapon>ReloadDelay","Weapon>ReloadTime",
"Weapon>ClipSize","Weapon>RoundsPerSecond","Weapon>BulletDamage","Weapon>BulletsPerShot","Weapon>AltFire>DPS",
"Weapon>AltFire>AmmoConsumedPerShot","Weapon>AltFire>RoundsPerSecond","Weapon>AltFire>BulletDamage","Weapon>AltFire>BulletsPerShot"})
local rows = {}
for name, data in pairs(heroDpsData) do
table.insert(rows, {
name = name,
DPS = data["Weapon>DPS"] or 0,
reloadDelay = data["Weapon>ReloadDelay"] or 0,
reloadTime = data["Weapon>ReloadTime"] or 0,
clipSize = data["Weapon>ClipSize"] or 0,
roundsPerSecond = data["Weapon>RoundsPerSecond"] or 0,
bulletDamage = data["Weapon>BulletDamage"] or 0,
bulletsPerShot = data["Weapon>BulletsPerShot"] or 0,
altDPS = data["Weapon>AltFire>DPS"] or 0,
altAmmoConsumedPerShot = data["Weapon>AltFire>AmmoConsumedPerShot"] or 0,
altRoundsPerSecond = data["Weapon>AltFire>RoundsPerSecond"] or 0,
altBulletDamage = data["Weapon>AltFire>BulletDamage"] 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"
for _, r in ipairs(rows) do
z = z..
"|- \n"..
"| style=\"text-align:left;\" | "..
frame:expandTemplate{title="PageRef", args={r.name}}..
" || "..r.DPS.." || "..r.reloadDelay.." || "..r.reloadTime.." || "..r.clipSize..
" || "..r.roundsPerSecond.." || "..r.bulletDamage.." || "..r.bulletsPerShot.." \n"
end
z = z.."|}"
table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)
local tableDefs = {
{
title = "Hero Base Alt-Fire Damage",
columns = {
{ label = "Damage per sec", field = "altDPS" },
{ label = "Ammo Per Shot", field = "altAmmoConsumedPerShot" },
{ label = "Bullets per sec", field = "altRoundsPerSecond" },
{ label = "Bullet Damage", field = "altBulletDamage" },
{ label = "Bullets Per Shot", field = "altBulletsPerShot" },
}
}
}
local output = ""
for _, tableDef in ipairs(tableDefs) do
local filteredRows = {}
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
return z .. "\n\n" .. output
end
p.heroBulletSpeedTable = function(frame)
local heroBulletSpeedData = heroDataArray({"Name", "Weapon>BulletSpeed", "Weapon>AltFire>BulletSpeed"})
local rows = {}
for name, data in pairs(heroBulletSpeedData) do
table.insert(rows, {
name = name,
bulletSpeed = data["Weapon>BulletSpeed"] or 0,
altBulletSpeed = data["Weapon>AltFire>BulletSpeed"] 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"..
"|+ 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 = {
{
title = "Base Alt-Fire Bullet Velocity",
columns = {
{ label = "m/s", field = "altBulletSpeed" },
}
}
}
local output = ""
for _, tableDef in ipairs(tableDefs) do
local filteredRows = {}
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
return z .. "\n\n" .. output
end
p.heroClipSizeTable = function(frame)
local heroClipSizeData = heroDataArray({"Name", "Weapon>ClipSize","Weapon>AltFire>AmmoConsumedPerShot"})
local rows = {}
for name, data in pairs(heroClipSizeData) do
table.insert(rows, {
name = name,
clipSize = data["Weapon>ClipSize"] or 0,
ammoConsumedPerShot = data["Weapon>AltFire>AmmoConsumedPerShot"] 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"..
"|+ 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 = {
{
title = "Alt-Fire Ammo Cost",
columns = {
{ label = "Ammo Per Shot", field = "ammoConsumedPerShot" },
}
}
}
local output = ""
for _, tableDef in ipairs(tableDefs) do
local filteredRows = {}
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
return z .. "\n\n" .. output
end
p.heroRoundsPerSecondTable = function(frame)
local heroRoundsPerSecondData = heroDataArray({"Name", "Weapon>RoundsPerSecond", "Weapon>AltFire>RoundsPerSecond"})
local rows = {}
for name, data in pairs(heroRoundsPerSecondData) do
table.insert(rows, {
name = name,
roundsPerSecond = data["Weapon>RoundsPerSecond"] or 0,
altRoundsPerSecond = data["Weapon>AltFire>RoundsPerSecond"] 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"..
"|+ 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 = {
{
title = "Base Alt-Fire Fire Rate",
columns = {
{ label = "Rounds/s", field = "altRoundsPerSecond" },
}
}
}
local output = ""
for _, tableDef in ipairs(tableDefs) do
local filteredRows = {}
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
return z .. "\n\n" .. output
end
p.heroFalloffRangeTable = function(frame)
local heroFalloffRangeData = heroDataArray({"Name", "Weapon>FalloffStartRange", "Weapon>FalloffEndRange", "Weapon>AltFire>FalloffStartRange", "Weapon>AltFire>FalloffEndRange",
"Weapon>AltFire>ExplosionRadius"})
local rows = {}
for name, data in pairs(heroFalloffRangeData) do
table.insert(rows, {
name = name,
falloffStartRange = data["Weapon>FalloffStartRange"] or 0,
falloffEndRange = data["Weapon>FalloffEndRange"] or 0,
altFalloffStartRange = data["Weapon>AltFire>FalloffStartRange"] or 0,
altFalloffEndRange = data["Weapon>AltFire>FalloffEndRange"] or 0,
altExplosionRadius = data["Weapon>AltFire>ExplosionRadius"] 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"..
"|+ 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 = {
{
title = "Base Alt-Fire Falloff Range",
columns = {
{ label = "Minimum Range (m)", field = "altFalloffStartRange" },
{ label = "Maximum Range (m)", field = "altFalloffEndRange" },
{ label = "Explosion Radius (m)", field = "altExplosionRadius" },
}
}
}
local output = ""
for _, tableDef in ipairs(tableDefs) do
local filteredRows = {}
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
return z .. "\n\n" .. output
end
p.heroBulletDamageTable = function(frame)
-- Pull data
local heroBulletDamageData = heroDataArray({"Name", "Weapon>BulletDamage", "LevelScaling>BulletDamage", "Weapon>AltFire>BulletDamage", "LevelScaling>BulletDamageAltFire"})
local rows = {}
for name, data in pairs(heroBulletDamageData) do
table.insert(rows, {
name = name,
bulletDamage = tonumber(data["Weapon>BulletDamage"]) or 0,
scalingDamage = tonumber(data["LevelScaling>BulletDamage"]) or 0,
altBulletDamage = tonumber(data["Weapon>AltFire>BulletDamage"]) or 0,
altScalingDamage = tonumber(data["LevelScaling>BulletDamageAltFire"]) 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 Bullet Damage Stats \n"..
"! Hero !! Starting !! Added per Boon !! At Max Boon \n"
-- Iterate over heroes adding a new row to the wikitable for each
for _, r in ipairs(rows) do
z = z..
"|- \n"..
"| style=\"text-align:left;\" | "..
frame:expandTemplate{title="PageRef", args={r.name}}..
" || "..r.bulletDamage.." || +"..r.scalingDamage.." || "..
tostring(roundValue(r.bulletDamage + r.scalingDamage * soul_unlock.get_max('PowerIncrease'))).." \n"
end
z = z.."|}"
return z
end
p.heroLightMeleeTable = function(frame)
-- Pull data
local heroLightMeleeData = heroDataArray({"Name", "LightMeleeDamage", "LevelScaling>LightMeleeDamage"})
local rows = {}
for name, data in pairs(heroLightMeleeData) do
table.insert(rows, {
name = name,
lightMeleeDamage = tonumber(data["LightMeleeDamage"]) or 0,
scalingDamage = tonumber(data["LevelScaling>LightMeleeDamage"]) 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 Light Melee Stats \n"..
"! Hero !! Starting !! Added per Boon !! At Max Boon \n"
-- Iterate over heroes adding a new row to the wikitable for each
for _, r in ipairs(rows) do
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
z = z.."|}"
return z
end
p.heroHeavyMeleeTable = function(frame)
-- Pull data
local heroHeavyMeleeData = heroDataArray({"Name", "HeavyMeleeDamage", "LevelScaling>HeavyMeleeDamage"})
local rows = {}
for name, data in pairs(heroHeavyMeleeData) do
table.insert(rows, {
name = name,
heavyMeleeDamage = tonumber(data["HeavyMeleeDamage"]) or 0,
scalingDamage = tonumber(data["LevelScaling>HeavyMeleeDamage"]) 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 Heavy Melee Stats \n"..
"! Hero !! Starting !! Added per Boon !! At Max Boon \n"
-- Iterate over heroes adding a new row to the wikitable for each
for _, r in ipairs(rows) do
z = z..
"|- \n"..
"| style=\"text-align:left;\" | "..
frame:expandTemplate{title="PageRef", args={r.name}}..
" || "..r.heavyMeleeDamage.." || +"..r.scalingDamage.." || "..
tostring(roundValue(r.heavyMeleeDamage + r.scalingDamage * soul_unlock.get_max('PowerIncrease'))).." \n"
end
z = z.."|}"
return z
end
p.heroStaminaTable = function(frame)
local heroStaminaData = heroDataArray({"Name", "Stamina", "StaminaCooldown"})
local rows = {}
for name, data in pairs(heroStaminaData) do
table.insert(rows, {
name = name,
stamina = data["Stamina"] or 0,
staminaCooldown = data["StaminaCooldown"] 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 Stamina Stats \n"..
"! Hero !! Stamina Bars !! Cooldown (s) \n"
for _, r in ipairs(rows) do
z = z..
"|- \n"..
"| style=\"text-align:left;\" | "..
frame:expandTemplate{title="PageRef", args={r.name}}..
" || "..r.stamina.." || "..r.staminaCooldown.." \n"
end
z = z.."|}"
return z
end
p.heroDashTable = function(frame)
local heroDashData = heroDataArray({"Name", "GroundDashSpeed"})
local rows = {}
for name, data in pairs(heroDashData) do
table.insert(rows, {
name = name,
duration = tonumber(data.GroundDashSpeed) 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 Dash Speed Stats\n' ..
'! Hero !! Dash Speed (m/s)\n'
for _, r in ipairs(rows) do
z = z .. '|-\n| style="text-align:left;" | ' ..
frame:expandTemplate{title = 'PageRef', args = {r.name}} ..
' || ' .. r.duration .. '\n'
end
return z .. '|}'
end
p.heroReloadTable = function(frame)
local heroReloadData = heroDataArray({"Name", "Weapon>ReloadTime"})
-- 1. collect rows
local rows = {}
for name, data in pairs(heroReloadData) do
table.insert(rows, {
name = name,
reloadTime = tonumber(data["Weapon>ReloadTime"]) or 0
})
end
-- 2. alphabetical by hero name
table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)
-- 3. build table
local z = '{| class="wikitable sortable mw-collapsible" style="text-align:center"\n' ..
'|+ Hero Base Reload Time Stats\n' ..
'! Hero !! Reload Time (s) \n'
for _, r in ipairs(rows) do
z = z ..
'|-\n' ..
'| style="text-align:left;" | ' ..
frame:expandTemplate{title = 'PageRef', args = {r.name}} ..
' || '.. r.reloadTime ..' \n'
end
return z .. '|}'
end
p.heroReloadDelayTable = function(frame)
local heroReloadDelayData = heroDataArray({"Name", "Weapon>ReloadDelay"})
local rows = {}
for name, data in pairs(heroReloadDelayData) do
table.insert(rows, {
name = name,
reloadDelay = data["Weapon>ReloadDelay"] or 0
})
end
table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)
local tableDefs = {
{
title = "Hero Base Reload Delay Stats",
columns = {
{ label = "Reload Delay (s)", field = "reloadDelay" }
}
}
}
local output = ""
for _, tableDef in ipairs(tableDefs) do
local filteredRows = {}
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
return output
end
p.heroMoveSpeedTable = function(frame)
local heroMoveSpeedData = heroDataArray({"Name", "MaxMoveSpeed", "SprintSpeed"})
local rows = {}
for name, data in pairs(heroMoveSpeedData) do
table.insert(rows, {
name = name,
moveSpeed = tonumber(data["MaxMoveSpeed"]) or 0,
sprintSpeed = tonumber(data["SprintSpeed"]) 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 Move Speed Stats \n"..
"! Hero !! Move Speed (m/s) !! Sprint Speed (m/s) !! Total Speed (m/s) \n"
for _, r in ipairs(rows) do
z = z..
"|- \n"..
"| style=\"text-align:left;\" | "..
frame:expandTemplate{title="PageRef", args={r.name}}..
" || "..r.moveSpeed.." || "..r.sprintSpeed.." || "..r.moveSpeed + r.sprintSpeed .." \n"
end
z = z.."|}"
return z
end
p.heroDamageResistTable = function(frame)
local heroDamageResistData = heroDataArray({"Name", "BulletResist", "LevelScaling>BulletResist", "TechResist", "LevelScaling>TechResist", "MeleeResist", "CritDamageReceivedPercent"})
local rows = {}
for name, data in pairs(heroDamageResistData) do
table.insert(rows, {
name = name,
bulletResist = data["BulletResist"] or 0,
bulletScaling = data["LevelScaling>BulletResist"] or 0,
spiritResist = data["TechResist"] or 0,
spiritScaling = data["LevelScaling>TechResist"] or 0,
meleeResist = data["MeleeResist"] or 0,
critReduction = data["CritDamageReceivedPercent"] or 0
})
end
table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)
local tableDefs = {
{
title = "Hero Base Bullet Resist Stats",
columns = {
{ label = "Bullet Resist (%)", field = "bulletResist" },
{ label = "BR per Boon (%)", field = "bulletScaling" },
}
},
{
title = "Hero Base Spirit Resist Stats",
columns = {
{ label = "Spirit Resist (%)", field = "spiritResist" },
{ label = "SR per Boon (%)", field = "spiritScaling" },
}
},
{
title = "Hero Base Melee Resist Stats",
columns = {
{ label = "Melee Resist (%)", field = "meleeResist" },
}
},
{
title = "Hero Base Crit Reduction Stats",
columns = {
{ label = "Crit Reduction (%)", field = "critReduction" },
}
},
}
local output = ""
for _, tableDef in ipairs(tableDefs) do
local filteredRows = {}
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
return output
end
p.heroCritTable = function(frame)
local heroCritData = heroDataArray({"Name", "CritDamageBonusPercent"})
local rows = {}
for name, data in pairs(heroCritData) do
table.insert(rows, {
name = name,
critBonusScale = data["CritDamageBonusPercent"] or 0
})
end
table.sort(rows, function(a, b) return a.name:lower() < b.name:lower() end)
local tableDefs = {
{
title = "Hero Base Crit Bonus Scale Stats",
columns = {
{ label = "Crit Bonus Scale (%)", field = "critBonusScale" }
}
}
}
local output = ""
for _, tableDef in ipairs(tableDefs) do
local filteredRows = {}
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
return output
end
return p