Editing Module:LevelTables

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 1: Line 1:
local p = {};
local p = {};
local Icon = require('Module:Icon')
local Souls = require('Module:Souls')


-- Loads the necessary data from the wiki's JSON pages.
-- Loads the necessary data from the wiki's JSON pages.
local heroes_data = mw.loadJsonData("Data:HeroData.json")
local heroes_data = mw.loadJsonData("Data:HeroData.json")
local soul_unlocks_data = mw.loadJsonData("Data:SoulUnlockData.json")
local soul_unlocks_data = mw.loadJsonData("Data:SoulUnlockData.json")
-- Helper to safely get stats that may be nested under Weapon
local function get_stat_value(data, key)
    if data[key] ~= nil then return data[key] end
    if data.Weapon and data.Weapon[key] ~= nil then return data.Weapon[key] end
    return 0
end


-- Defines human-readable names for the internal property keys used in headers.
-- Defines human-readable names for the internal property keys used in headers.
Line 22: Line 12:
LightMeleeDamage = "Light Melee Damage",
LightMeleeDamage = "Light Melee Damage",
HeavyMeleeDamage = "Heavy Melee Damage"
HeavyMeleeDamage = "Heavy Melee Damage"
}
-- Provides data for special alternate fire modes that are not present in HeroData.json.
local alt_fires = {
Shiv = {base = 55.2, level = 2.64, suffix = "alt fire 12 pellets"},
Viscous = {base = 63, level = 0.9, suffix = "alt fire AOE"},
Yamato = {base = 63.36, level = 0.35, suffix = "alt fire AOE"}
}
}


Line 43: Line 40:
--]]
--]]
p.write_power_increase_table = function(frame)
p.write_power_increase_table = function(frame)
    -- Use the same smart sorting for this list.
local function hero_sort(h1, h2)
return get_sortable_name(h1.Name) < get_sortable_name(h2.Name)
end
-- Read and validate the arguments passed from the #invoke call.
-- Read and validate the arguments passed from the #invoke call.
local property = frame.args[1]
local property = frame.args[1]
Line 68: Line 61:
end
end
end
end
local max_boons = #pi_souls_list
local max_boons = #pi_souls_list
-- Define the milestones to display in the summary table.
-- Define the milestones to display in the summary table.
local milestones = {10, 20, max_boons}
local milestones = {10, 20, max_boons}
Line 77: Line 69:
local filtered_heroes = {}
local filtered_heroes = {}
for _, hero in pairs(heroes_data) do
for _, hero in pairs(heroes_data) do
if (not hero["IsDisabled"] and not hero["InDevelopment"] and hero["Name"]) then
if (not hero["IsDisabled"]) then
table.insert(filtered_heroes, hero)
table.insert(filtered_heroes, hero)
end
end
Line 83: Line 75:
-- Sort the hero list alphabetically, ignoring "The " for proper sorting.
-- Sort the hero list alphabetically, ignoring "The " for proper sorting.
table.sort(filtered_heroes, hero_sort)
table.sort(filtered_heroes, function(a, b)
return get_sortable_name(a.Name) < get_sortable_name(b.Name)
end)
-- Begin building the main data table.
-- Begin building the main data table.
Line 101: Line 95:
local required_souls = pi_souls_list[count]
local required_souls = pi_souls_list[count]
local souls_formatted = string.format("%.1fK", (required_souls + 400) / 1000)
local souls_formatted = string.format("%.1fK", (required_souls + 400) / 1000)
local soul_display = Souls._render(souls_formatted)
local soul_display = frame:expandTemplate{ title = "Souls", args = {souls_formatted} }
local full_header = header_text .. "<br /><small>(" .. soul_display .. ")</small>"
local full_header = header_text .. "<br /><small>(" .. soul_display .. ")</small>"
header_row:tag("th"):wikitext(full_header):done()
header_row:tag("th"):wikitext(full_header):done()
Line 112: Line 106:
local function addHeroRows(hero_data, is_alt_fire)
local function addHeroRows(hero_data, is_alt_fire)
local base, level, suffix
local base, level, suffix
local hero_icon_wikitext = Icon._render(hero_data['Name'])
local hero_icon_wikitext = frame:expandTemplate{ title = "HeroIcon", args = {hero_data["Name"]}}
-- Determine if this is a main weapon or an alt-fire and set the correct data.
-- Determine if this is a main weapon or an alt-fire and set the correct data.
Line 120: Line 114:
suffix = " (" .. hero_data.alt_fire.suffix .. ")"
suffix = " (" .. hero_data.alt_fire.suffix .. ")"
else
else
base = get_stat_value(hero_data, property)
base = (hero_data[property] or 0)
level = (hero_data["LevelScaling"] and hero_data["LevelScaling"][property] or 0)
level = (hero_data["LevelScaling"] and hero_data["LevelScaling"][property] or 0)
suffix = ""
suffix = ""
local shots = get_stat_value(hero_data, "BulletsPerShot")
local shots = (hero_data["BulletsPerShot"] or 1)
if shots == 0 then shots = 1 end
local burst = (hero_data["BulletsPerBurst"] or 1)
local burst = get_stat_value(hero_data, "BulletsPerBurst")
if burst == 0 then burst = 1 end
local hit_once = get_stat_value(hero_data, "HitOnceAcrossAllBullets")
if (property == "BulletDamage" and (shots * burst) > 1) then
if (property == "BulletDamage" and (shots * burst) > 1) then
if (not hit_once) then
if (not hero_data["HitOnceAcrossAllBullets"]) then
base = base * shots * burst
base = base * shots * burst
level = level * shots * burst
level = level * shots * burst
Line 179: Line 169:
local required_souls = pi_souls_list[i]
local required_souls = pi_souls_list[i]
local souls_formatted = string.format("%.1fK", (required_souls + 400) / 1000)
local souls_formatted = string.format("%.1fK", (required_souls + 400) / 1000)
local soul_display = Souls._render(souls_formatted)
local soul_display = frame:expandTemplate{ title = "Souls", args = {souls_formatted} }
local row_html = string.format("<tr><td>%s</td><td style='text-align:right;'>%.2f</td></tr>", soul_display, total)
local row_html = string.format("<tr><td>%s</td><td style='text-align:right;'>%.2f</td></tr>", soul_display, total)
Line 209: Line 199:
for _, hero in ipairs(filtered_heroes) do
for _, hero in ipairs(filtered_heroes) do
addHeroRows(hero, false)
addHeroRows(hero, false)
if (property == "BulletDamage" and alt_fires[hero["Name"]] ~= nil) then
-- Dynamically add alt-fire rows if the data exists
local alt_fire_hero_data = {
if (property == "BulletDamage" and hero.Weapon and hero.Weapon.AltFire) then
Name = hero.Name,
    local alt_fire_data = hero.Weapon.AltFire
alt_fire = alt_fires[hero.Name]
    local alt_fire_base = alt_fire_data.BulletDamage or 0
}
   
addHeroRows(alt_fire_hero_data, true)
    if alt_fire_base > 0 then
        -- Get scaling: prefer alt-fire specific key, fall back to main weapon scaling
        local alt_fire_level = (hero.LevelScaling and
            (hero.LevelScaling.BulletDamageAltFire or hero.LevelScaling[property])) or 0
       
        -- Apply same pellet/burst logic as main weapon
        local shots = alt_fire_data.BulletsPerShot or 1
        local burst = alt_fire_data.BulletsPerBurst or 1
        local hit_once = alt_fire_data.HitOnceAcrossAllBullets or false
       
        local suffix = "alt fire"
       
        if (shots * burst) > 1 and not hit_once then
            alt_fire_base = alt_fire_base * shots * burst
            alt_fire_level = alt_fire_level * shots * burst
            if shots > 1 then suffix = suffix .. " " .. shots .. " pellets" end
            if burst > 1 then suffix = suffix .. " " .. burst .. " bullets" end
        end
       
        -- Add AOE indicator (without radius)
        if alt_fire_data.ExplosionRadius then
            suffix = suffix .. " AOE"
        end
       
        local alt_fire_hero_data = {
            Name = hero.Name,
            alt_fire = {
                base = alt_fire_base,
                level = alt_fire_level,
                suffix = suffix
            }
        }
        addHeroRows(alt_fire_hero_data, true)
    end
end
end
end
end
Line 292: Line 248:
local burst_heroes = {}
local burst_heroes = {}
for _, hero in pairs(heroes_data) do
for _, hero in pairs(heroes_data) do
    local bullets_per_shot = get_stat_value(hero, "BulletsPerShot")
if ((hero["BulletsPerShot"] or 1) > 1 and not hero["IsDisabled"]) then
    local bullets_per_burst = get_stat_value(hero, "BulletsPerBurst")
   
if (bullets_per_shot > 1 and not hero["IsDisabled"] and not hero["InDevelopment"]) then
table.insert(spreadshot_heroes, hero)
table.insert(spreadshot_heroes, hero)
elseif (bullets_per_burst > 1 and not hero["IsDisabled"] and not hero["InDevelopment"]) then
elseif ((hero["BulletsPerBurst"] or 1) > 1 and not hero["IsDisabled"]) then
table.insert(burst_heroes, hero)
table.insert(burst_heroes, hero)
end
end
Line 307: Line 260:
local multishot_str = "Weapons with multiple projectiles (Spreadshot):\n"
local multishot_str = "Weapons with multiple projectiles (Spreadshot):\n"
for _, hero in ipairs(spreadshot_heroes) do
for _, hero in ipairs(spreadshot_heroes) do
local base = math.floor(get_stat_value(hero, "BulletDamage") * 100) / 100
local base = math.floor(hero["BulletDamage"] * 100) / 100
local level = math.floor(hero["LevelScaling"]["BulletDamage"] * 100) / 100
local level = math.floor(hero["LevelScaling"]["BulletDamage"] * 100) / 100
local shots = get_stat_value(hero, "BulletsPerShot")
local shots = hero["BulletsPerShot"]
local hit_once = get_stat_value(hero, "HitOnceAcrossAllBullets")
local hero_icon = frame:expandTemplate{ title = "HeroIcon", args = {hero["Name"]}}
local hero_icon = Icon._render(hero["Name"])
-- Checks for the special property and changes the output text accordingly.
-- Checks for the special property and changes the output text accordingly.
local stat_str
local stat_str
if hit_once then
if hero["HitOnceAcrossAllBullets"] then
stat_str = "* " .. hero_icon .. ": " .. shots .. " pellets, "  
stat_str = "* " .. hero_icon .. ": " .. shots .. " pellets, "  
.. base .. " total damage (hits only once), +" .. level .. " total\n"
.. base .. " total damage (hits only once), +" .. level .. " total\n"
Line 327: Line 279:
multishot_str = multishot_str .. "Weapons with burst fire (Burst Fire):\n"
multishot_str = multishot_str .. "Weapons with burst fire (Burst Fire):\n"
for _, hero in ipairs(burst_heroes) do
for _, hero in ipairs(burst_heroes) do
local base = math.floor(get_stat_value(hero, "BulletDamage") * 100) / 100
local base = math.floor(hero["BulletDamage"] * 100) / 100
local level = math.floor(hero["LevelScaling"]["BulletDamage"] * 100) / 100
local level = math.floor(hero["LevelScaling"]["BulletDamage"] * 100) / 100
local shots = get_stat_value(hero, "BulletsPerBurst")
local shots = hero["BulletsPerBurst"]
local hero_icon = Icon._render(hero["Name"])
local hero_icon = frame:expandTemplate{ title = "HeroIcon", args = {hero["Name"]}}
local stat_str = "* " .. hero_icon .. ": " .. shots .. " rounds, "  
local stat_str = "* " .. hero_icon .. ": " .. shots .. " rounds, "  
.. base .. "/bullet, +" .. level .. "/bullet\n"
.. base .. "/bullet, +" .. level .. "/bullet\n"
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