Module:Sandbox/LVL: Difference between revisions

LVL (talk | contribs)
No edit summary
LVL (talk | contribs)
No edit summary
Line 10: Line 10:
local hero_data_module  = require('Module:HeroData')
local hero_data_module  = require('Module:HeroData')


local function get_nested_stat_value(hero_data, stat_key, prefer_alt_fire)
local function get_nested_stat_value(hero_data, stat_key)
    if prefer_alt_fire and hero_data.Weapon and hero_data.Weapon.AltFire and hero_data.Weapon.AltFire[stat_key] ~= nil then
        return hero_data.Weapon.AltFire[stat_key]
    end
     if hero_data[stat_key] ~= nil then
     if hero_data[stat_key] ~= nil then
         return hero_data[stat_key]
         return hero_data[stat_key]
Line 65: Line 62:
             "ReloadSingle",
             "ReloadSingle",
             "BulletSpeed",
             "BulletSpeed",
            "BulletGravityScale",
             "FalloffStartRange",
             "FalloffStartRange",
             "FalloffEndRange",
             "FalloffEndRange",
            "BonusAttackRange",
             "CritDamageBonusPercent",
             "CritDamageBonusPercent",
             "RoundsPerSecondAtMaxSpin",
             "RoundsPerSecondAtMaxSpin",
Line 80: Line 75:
             "TechResist",
             "TechResist",
             "MeleeResist",
             "MeleeResist",
            "CritDamageReceivedPercent",
            "DebuffResist",
             "BulletLifesteal",
             "BulletLifesteal",
            "CritDamageReceivedPercent",
             "MaxMoveSpeed",
             "MaxMoveSpeed",
             "SprintSpeed",
             "SprintSpeed",
             "StaminaCooldown",
             "StaminaCooldown",
             "Stamina",
             "Stamina",
             "GroundDashSpeed"
             "GroundDashSpeed",
            "GravityChange"
         },
         },
         Spirit = {
         Spirit = {
Line 107: Line 104:
     end)
     end)


     local function build_hero_row(hero_entry, is_alt_row)
    -- Helper to generate a single row (primary or alt-fire)
        local hero_key  = hero_entry.key
     local function generateRow(hero_data, hero_key, is_alt_fire)
        local hero_data = hero_entry.data
         local row_str = ""
         local row_str   = ""
         local hero_name_local = localize(hero_key, hero_key)
 
         local hero_name    = localize(hero_key, hero_key)
         local hero_name_en = hero_data["Name"]
         local hero_name_en = hero_data["Name"]
         if is_alt_row then
        local template_args = {[1] = hero_name_en, l1 = hero_name_local}
             hero_name = hero_name .. " (Alt-fire)"
        local hero_icon = mw.getCurrentFrame():expandTemplate{ title = "Template:HeroIcon", args = template_args }
        local hero_cell_content = hero_icon
         if is_alt_fire then
             hero_cell_content = hero_icon .. ' <small>(Alt-fire)</small>'
         end
         end
        local template_args = {[1] = hero_name_en, l1 = hero_name}
        local hero_icon = mw.getCurrentFrame():expandTemplate{ title = "Template:HeroIcon", args = template_args }
         row_str = row_str ..
         row_str = row_str ..
             '<td style="position: sticky; left: 0; z-index: 10; background-color: #202122; isolation: isolate; overflow: hidden;">' ..
             '<td style="position: sticky; left: 0; z-index: 10; background-color: #202122; isolation: isolate; overflow: hidden;">' ..
             hero_icon .. "</td>"
             hero_cell_content .. "</td>"


         for _, category in ipairs(attribute_orders["category_order"]) do
         for _, category in ipairs(attribute_orders["category_order"]) do
             if stats_to_include[category] ~= nil then
             if stats_to_include[category] ~= nil then
                 for _, attr_key in ipairs(stats_to_include[category]) do
                 for _, attr_key in ipairs(stats_to_include[category]) do
                    -- Base value: alt-fire weapon stats from AltFire table, else normal lookup
                    local base_value
                    if is_alt_fire and category == "Weapon" then
                        base_value = (hero_data.Weapon.AltFire and hero_data.Weapon.AltFire[attr_key]) or 0
                    else
                        base_value = get_nested_stat_value(hero_data, attr_key)
                    end


                    local base_value  = get_nested_stat_value(hero_data, attr_key, is_alt_row)
                     local stat_value = base_value
                     local stat_value   = base_value
                    local scaling_data = nil
                    local scaling_strs = ""
                    local spirit_scale = 0
                    local level_scale  = 0


                     if is_alt_row then
                     -- FIX 1: Scale using AltFire key only if the stat actually exists in AltFire
                    local scaling_data
                    if is_alt_fire and hero_data.Weapon and hero_data.Weapon.AltFire and hero_data.Weapon.AltFire[attr_key] ~= nil then
                         scaling_data = hero_data_module.get_hero_scaling_data(hero_data, attr_key .. "AltFire")
                         scaling_data = hero_data_module.get_hero_scaling_data(hero_data, attr_key .. "AltFire")
                        if scaling_data ~= nil and next(scaling_data) == nil then
                     else
                            scaling_data = nil
                        end
                     end
                    if scaling_data == nil then
                         scaling_data = hero_data_module.get_hero_scaling_data(hero_data, attr_key)
                         scaling_data = hero_data_module.get_hero_scaling_data(hero_data, attr_key)
                        if scaling_data ~= nil and next(scaling_data) == nil then
                            scaling_data = nil
                        end
                     end
                     end
                    local scaling_strs = ""
                    local spirit_scale = 0
                    local level_scale  = 0


                     if scaling_data ~= nil then
                     if scaling_data ~= nil then
Line 189: Line 184:
                     )
                     )


                    local weapon_table = hero_data.Weapon
                    if is_alt_fire and weapon_table and weapon_table.AltFire then
                        weapon_table = weapon_table.AltFire
                    end
                     local hit_once = "false"
                     local hit_once = "false"
                     if (attr_key == "DPS" or attr_key == "SustainedDPS") then
                     if (attr_key == "DPS" or attr_key == "SustainedDPS")
                         if not is_alt_row then
                         and weapon_table
                            if hero_data.Weapon and hero_data.Weapon.HitOnceAcrossAllBullets then
                         and weapon_table.HitOnceAcrossAllBullets
                                hit_once = "true"
                    then
                            end
                        hit_once = "true"
                         else
                            if hero_data.Weapon and hero_data.Weapon.AltFire and hero_data.Weapon.AltFire.HitOnceAcrossAllBullets then
                                hit_once = "true"
                            end
                        end
                     end
                     end


Line 222: Line 216:
     end
     end


     -- Build table body rows
     -- Build table body rows (primary + optional alt-fire)
     for _, hero_entry in ipairs(sorted_heroes) do
     for _, hero_entry in ipairs(sorted_heroes) do
         body_str = body_str .. build_hero_row(hero_entry, false)
         local hero_key  = hero_entry.key
        local hero_data = hero_entry.data


         if hero_entry.data.Weapon and hero_entry.data.Weapon.AltFire then
        body_str = body_str .. generateRow(hero_data, hero_key, false)
             body_str = body_str .. build_hero_row(hero_entry, true)
         if hero_data.Weapon and hero_data.Weapon.AltFire then
             body_str = body_str .. generateRow(hero_data, hero_key, true)
         end
         end
     end
     end


     -- Pre-pass: determine which stats have any scaling, and which have both types
     -- Pre-pass: determine which stats have any scaling, and which have both types
    -- (now includes alt-fire scaling for weapon columns)
     local stats_with_any_scaling  = {}
     local stats_with_any_scaling  = {}
     local stats_with_both_scaling = {}
     local stats_with_both_scaling = {}
Line 239: Line 236:
             if stats_to_include[category] ~= nil then
             if stats_to_include[category] ~= nil then
                 for _, attr_key in ipairs(stats_to_include[category]) do
                 for _, attr_key in ipairs(stats_to_include[category]) do
                    -- Primary scaling
                     local scaling_data = hero_data_module.get_hero_scaling_data(hero_data, attr_key)
                     local scaling_data = hero_data_module.get_hero_scaling_data(hero_data, attr_key)
                    local alt_scaling_data = nil
                     if scaling_data ~= nil and next(scaling_data) ~= nil then
                     if hero_data.Weapon and hero_data.Weapon.AltFire then
                        alt_scaling_data = hero_data_module.get_hero_scaling_data(hero_data, attr_key .. "AltFire")
                    end
 
                    local has_scaling    = (scaling_data ~= nil and next(scaling_data) ~= nil)
                    local has_alt_scaling = (alt_scaling_data ~= nil and next(alt_scaling_data) ~= nil)
 
                    if has_scaling or has_alt_scaling then
                         stats_with_any_scaling[attr_key] = true
                         stats_with_any_scaling[attr_key] = true
                         local has_spirit = false
                         local has_spirit = false
                         local has_level  = false
                         local has_level  = false
                         if has_scaling then
                         for _, scaling_type in pairs(scaling_data) do
                            for _, scaling_type in pairs(scaling_data) do
                            if scaling_type == "Spirit" then has_spirit = true end
                                if scaling_type == "Spirit" then has_spirit = true end
                             if scaling_type == "Level"  then has_level  = true end
                                if scaling_type == "Level"  then has_level  = true end
                            end
                        end
                        if has_alt_scaling then
                             for _, scaling_type in pairs(alt_scaling_data) do
                                if scaling_type == "Spirit" then has_spirit = true end
                                if scaling_type == "Level"  then has_level  = true end
                            end
                         end
                         end
                         if has_spirit and has_level then
                         if has_spirit and has_level then
                             stats_with_both_scaling[attr_key] = true
                             stats_with_both_scaling[attr_key] = true
                        end
                    end
                    -- FIX 2: Alt-fire scaling only for stats that actually appear in AltFire
                    if hero_data.Weapon
                        and hero_data.Weapon.AltFire
                        and hero_data.Weapon.AltFire[attr_key] ~= nil
                    then
                        local alt_scaling = hero_data_module.get_hero_scaling_data(hero_data, attr_key .. "AltFire")
                        if alt_scaling ~= nil and next(alt_scaling) ~= nil then
                            stats_with_any_scaling[attr_key] = true
                            local has_spirit_alt = false
                            local has_level_alt  = false
                            for _, scaling_type in pairs(alt_scaling) do
                                if scaling_type == "Spirit" then has_spirit_alt = true end
                                if scaling_type == "Level"  then has_level_alt  = true end
                            end
                            if has_spirit_alt and has_level_alt then
                                stats_with_both_scaling[attr_key] = true
                            end
                         end
                         end
                     end
                     end