Module:HeroData/nav: Difference between revisions

From The Deadlock Wiki
Jump to navigation Jump to search
m Reverted edits by Saag (talk) to last revision by Monster Domosed
Tag: Rollback
3D model function
 
(25 intermediate revisions by 6 users not shown)
Line 3: Line 3:
local hero_release_module = require('Module:HeroData/release')
local hero_release_module = require('Module:HeroData/release')
local lang_module = require('Module:Lang')
local lang_module = require('Module:Lang')
local utilities = require('Module:Utilities')


-- for [[Template:Deadlock_Wiki/Heroes]] on home page, i.e. [[Template:Hero card2]]
-- Cache to store results of get_heroes if called multiple times in one page render
function p.get_hero_nav_cards(frame)
local heroes_cache = {}
    local in_herolabs = frame.args['in_herolabs'] -- true or false
 
    local text_size = frame.args['text_size']
-- Shared helper function
    local card_size = frame.args['card_size']
local function get_heroes(in_herolabs)
    local sticker_size = frame.args['sticker_size']
     -- Return cached result if it exists
    local herolabs_text_size = frame.args['herolabs_text_size']
     if heroes_cache[in_herolabs] then
    local debug_mode = frame.args['debug_mode']
         return heroes_cache[in_herolabs]
local lang_code = lang_module.get_lang_code() -- Get the language code
   
     -- Turn debug_mode from string to bool, default to false
     if debug_mode == nil then
         debug_mode = false
    elseif debug_mode == 'true' then
        debug_mode = true
    elseif debug_mode == 'false' then
        debug_mode = false
     end
     end


    if in_herolabs ~= 'true' and in_herolabs ~= 'false' then
        return 'in_herolabs must be either true or false'
    end
   
    -- Only add subpage if not English
    local subpage_str = ''
    if lang_code ~= 'en' then
        subpage_str = '/' .. lang_code
    end
   
    -- Iterate heroes
     local heroes = {}
     local heroes = {}
     for hero_key, hero_data in pairs(heroes_data) do
     for hero_key, hero_data in pairs(heroes_data) do
         if hero_data["Name"] ~= nil then
        -- hero_werewolf_transformed is consolidated in Silver's page
            -- if herolabs is requested, only needs to have herolabs=true
         if hero_data["Name"] ~= nil and hero_key ~= 'hero_werewolf_transformed' then
            -- otherwise, needs to be not disabled, in development, nd herolabs is nil or false
 
             local this_hero_status = hero_release_module.get_hero_release_status(hero_key)
             local this_hero_status = hero_release_module.get_hero_release_status(hero_key)
           
 
            if this_in_herolabs == nil then this_in_herolabs = false end
           
             if ((in_herolabs == 'true' and this_hero_status == 'HeroLabs') or
             if ((in_herolabs == 'true' and this_hero_status == 'HeroLabs') or
                 (in_herolabs == 'false' and this_hero_status == 'Released')) then
                 (in_herolabs == 'false' and this_hero_status == 'Released')) then
               
 
                 local is_recommended = hero_data['IsRecommended']
                 local is_recommended = hero_data['IsRecommended'] or false
                 if is_recommended == nil then
 
                     is_recommended = false
                --- Create a sort key for each hero to ensure correct alphabetical ordering.
                local hero_name = lang_module.get_string(hero_key, nil, 'en')
                 local sort_key_to_find = hero_key .. '_sort'
                local potential_sort_key = lang_module.get_string(sort_key_to_find, nil, 'en')
 
                local sort_key
                -- Detect translation failure if the returned string contains the original search key
                if string.find(potential_sort_key, sort_key_to_find, 1, true) then
                     sort_key = hero_name
                else
                    sort_key = potential_sort_key
                 end
                 end
                  
 
                 local hero_str = '|name=' .. lang_module.get_string(hero_key, nil, 'en') ..  
                 -- NOTE: Check if lang_module.get_string(hero_key, 'en') returns the same value as hero_name.
                              '|link=' .. lang_module.get_string(hero_key, 'en') ..  
                -- If the second argument defaults to nil natively, you can optimize further by setting: link = hero_name
                              '|subpage=' .. subpage_str ..  
                 local hero_link = lang_module.get_string(hero_key, 'en')
                              '|recommended=' .. tostring(is_recommended)
 
                  
                -- Store reusable hero data
                 table.insert(heroes, hero_str)
                local hero = {
                    key = hero_key,
                    name = hero_name,
                    sort_key = sort_key,
                    link = hero_link,
                    recommended = tostring(is_recommended)
                }
 
                table.insert(heroes, hero)
            end
        end
    end
 
    -- Sort heroes
    table.sort(heroes, function(a, b)
        return a.sort_key < b.sort_key
    end)
 
    heroes_cache[in_herolabs] = heroes
    return heroes
end
 
-- for [[Template:Deadlock_Wiki/Heroes]]
function p.get_hero_nav_cards(frame)
    local text_size = frame.args['text_size']
    local card_size = frame.args['card_size']
    local in_herolabs = frame.args['in_herolabs'] or 'false'
    local debug_mode = frame.args['debug_mode'] == 'true'
 
    local heroes = get_heroes(in_herolabs)
    local parts = {}
 
    for _, hero in ipairs(heroes) do
        table.insert(parts, string.format('{{Hero card2|heroName=%s|cardSize=%s|textSize=%s|isHeroLabs=%s}}',
            hero.link, card_size, text_size, in_herolabs))
    end
 
    local ret = table.concat(parts)
 
    if debug_mode then
        return ret
    else
        return frame:preprocess(ret)
    end
end
 
-- for [[Template:Roster]]
function p.get_hero_roster(frame)
    local in_herolabs = frame.args['in_herolabs'] or 'false'
    local debug_mode = frame.args['debug_mode'] == 'true'
 
    local heroes = get_heroes(in_herolabs)
    local parts = {}
 
    for _, hero in ipairs(heroes) do
        table.insert(parts, string.format('{{HeroRosterCard|name=%s|key=%s}}', hero.name, hero.key))
    end
 
    local ret = table.concat(parts)
 
    if debug_mode then
        return ret
    else
        return frame:preprocess(ret)
    end
end
 
-- for [[Template:Quotes Navbox]] etc.
p.get_hero_bulletpoints = function(frame)
    local subpage = frame.args['1']
    local in_herolabs = frame.args['in_herolabs'] or 'false'
    local debug_mode = frame.args['debug_mode'] == 'true'
    local no_redlinks = frame.args['no_redlinks'] == 'true'
 
    local heroes = get_heroes(in_herolabs)
    local parts = {}
 
    for _, hero in ipairs(heroes) do
        -- Lua optimization: clean ternary fallback for page_title assignment
        local page_title = subpage and (hero.link .. '/' .. subpage) or hero.name
 
        -- Skip redlinks entirely when enabled
        if not (no_redlinks and not utilities.page_exists(page_title)) then
            local item
            if subpage then
                 item = string.format('{{PageRef|%s|alt_link=%s}}', hero.link, page_title)
            else
                 item = string.format('{{HeroIcon|%s}}', hero.link)
             end
             end
            table.insert(parts, item)
         end
         end
     end
     end
          
 
     -- Order list alphabetically
    local ret = table.concat(parts, ' &bull; ')
     table.sort(heroes) -- O(nlogn)
 
    if debug_mode then
         return ret
     else
        return frame:preprocess(ret)
    end
end
 
-- for image galleries
p.get_hero_gallery = function(frame)
    local file_name = frame.args['1'] or ''
     local description = frame.args['2'] or ''
    local in_herolabs = frame.args['in_herolabs'] or 'false'
    local debug_mode = frame.args['debug_mode'] == 'true'
 
    local heroes = get_heroes(in_herolabs)
    local parts = {}
 
    for _, hero in ipairs(heroes) do
        table.insert(parts, string.format('File:%s%s|%s%s\n', hero.link, file_name, hero.name, description))
    end
      
      
    -- Add each item to output
     local ret = '<gallery>\n' .. table.concat(parts) .. '</gallery>'
     local ret = ''
 
    for index, hero_name in ipairs(heroes) do
    if debug_mode then
        ret = ret .. '{{Hero card2' .. hero_name
         return ret
        ret = ret .. '|text_size=' .. text_size
    else
        ret = ret .. '|herolabs=' .. in_herolabs
         return frame:preprocess(ret)
        ret = ret .. '|card_size=' .. card_size
         ret = ret .. '|sticker_size=' .. sticker_size
        ret = ret .. '|herolabs_text_size=' .. herolabs_text_size
         ret = ret .. '}} '
     end
     end
   
end
    -- Remove the last space
 
     ret = string.sub(ret, 1, -(string.len(' '))-1)
-- Generate 3D model gallery
   
function p.get_hero_models(frame)
    local in_herolabs = frame.args['in_herolabs'] or 'false'
     local debug_mode = frame.args['debug_mode'] == 'true'
 
    local heroes = get_heroes(in_herolabs)
    local parts = {}
 
    for _, hero in ipairs(heroes) do
        table.insert(parts, string.format('{{3D Model|%s}}', hero.name))
    end
 
    local ret = table.concat(parts)
 
     if debug_mode then
     if debug_mode then
         return ret
         return ret
     else -- evaluate wikitext if not in debug mode
     else
         return frame:preprocess(ret)
         return frame:preprocess(ret)
     end
     end
end
end
return p
return p

Latest revision as of 13:54, 7 August 2026

Overview

[edit source]

Generates hero navigation cards

Functions

[edit source]

get_hero_nav_cards

[edit source]

For Template:Hero Navbox on Heroes, individual hero pages like Abrams, and the home page.

Examples

[edit source]

First with debug_mode on, to help visualize what the output's source looks like.

{{#invoke:HeroData/nav|get_hero_nav_cards
|text_size=13
|card_size=88
|in_herolabs=false
|debug_mode=true
}}

{{Hero card2|heroName=Abrams|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Apollo|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Bebop|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Billy|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Calico|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Celeste|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=The Doorman|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Drifter|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Dynamo|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Graves|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Grey Talon|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Haze|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Holliday|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Infernus|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Ivy|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Kelvin|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Lady Geist|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Lash|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=McGinnis|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Mina|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Mirage|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Mo & Krill|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Paige|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Paradox|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Pocket|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Rem|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Seven|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Shiv|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Silver|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Sinclair|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Venator|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Victor|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Vindicta|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Viscous|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Vyper|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Warden|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Wraith|cardSize=88|textSize=13|isHeroLabs=false}}{{Hero card2|heroName=Yamato|cardSize=88|textSize=13|isHeroLabs=false}}

Now with debug_mode defaulted to false (off) to see actual visual output.

{{#invoke:HeroData/nav|get_hero_nav_cards
|text_size=13
|card_size=88
|in_herolabs=false
}}

Hero Labs

Abrams

Hero Labs

Apollo

Hero Labs

Bebop

Hero Labs

Billy

Hero Labs

Calico

Hero Labs

Celeste

Hero Labs

The Doorman

Hero Labs

Drifter

Hero Labs

Dynamo

Hero Labs

Graves

Hero Labs

Grey Talon

Hero Labs

Haze

Hero Labs

Holliday

Hero Labs

Infernus

Hero Labs

Ivy

Hero Labs

Kelvin

Hero Labs

Lady Geist

Hero Labs

Lash

Hero Labs

McGinnis

Hero Labs

Mina

Hero Labs

Mirage

Hero Labs

Mo & Krill

Hero Labs

Paige

Hero Labs

Paradox

Hero Labs

Pocket

Hero Labs

Rem

Hero Labs

Seven

Hero Labs

Shiv

Hero Labs

Silver

Hero Labs

Sinclair

Hero Labs

Venator

Hero Labs

Victor

Hero Labs

Vindicta

Hero Labs

Viscous

Hero Labs

Vyper

Hero Labs

Warden

Hero Labs

Wraith

Hero Labs

Yamato

Parameters

[edit source]
  • text_size - Font size of the hero name
  • card_size - Size of the hero card
  • in_herolabs - Get hero labs heroes (there are none at the moment)
  • debug_mode - (OPTIONAL) Defaults to false. With true, the output is raw wikitext source that isn't processed, allowing to see more clearly what is ran.

debug_mode is the only optional parameter. All other parameters are required. Template:Hero card2 utilizes this with some default values, see there for suggested values.

get_hero_roster

[edit source]

For Template:Roster on Heroes, generate a list using Template:HeroRosterCard.

get_hero_bulletpoints

[edit source]

For navboxes such as Template:Quotes Navbox, generate a bulletpoint list of heroes.

Add the name of a subpage to link to specific subpages. It will still display only the hero name but link to the subpage instead.

Add variable "no_redlinks=true" to hide red links (non-existent pages).

Examples

[edit source]
{{#invoke:HeroData/nav|get_hero_bulletpoints}}

Abrams Apollo Bebop Billy Calico Celeste The Doorman Drifter Dynamo Graves Grey Talon Haze Holliday Infernus Ivy Kelvin Lady Geist Lash McGinnis Mina Mirage Mo & Krill Paige Paradox Pocket Rem Seven Shiv Silver Sinclair Venator Victor Vindicta Viscous Vyper Warden Wraith Yamato

To link to "/Movement" subpages:

{{#invoke:HeroData/nav|get_hero_bulletpoints|Movement}}

AbramsApolloBebopBillyCalicoCelesteThe DoormanDrifterDynamoGravesGrey TalonHazeHollidayInfernusIvyKelvinLady GeistLashMcGinnisMinaMirageMo & KrillPaigeParadoxPocketRemSevenShivSilverSinclairVenatorVictorVindictaViscousVyperWardenWraithYamato

Hide redlinks:

{{#invoke:HeroData/nav|get_hero_bulletpoints|Movement|no_redlinks=true}}

AbramsThe DoormanDrifterDynamoHazeHollidayInfernusIvyLashMo & KrillParadoxPocketSevenShivSinclairVindictaViscousWraithYamato


local p = {}
local heroes_data = mw.loadJsonData("Data:HeroData.json")
local hero_release_module = require('Module:HeroData/release')
local lang_module = require('Module:Lang')
local utilities = require('Module:Utilities')

-- Cache to store results of get_heroes if called multiple times in one page render
local heroes_cache = {}

-- Shared helper function
local function get_heroes(in_herolabs)
    -- Return cached result if it exists
    if heroes_cache[in_herolabs] then
        return heroes_cache[in_herolabs]
    end

    local heroes = {}

    for hero_key, hero_data in pairs(heroes_data) do
        -- hero_werewolf_transformed is consolidated in Silver's page
        if hero_data["Name"] ~= nil and hero_key ~= 'hero_werewolf_transformed' then

            local this_hero_status = hero_release_module.get_hero_release_status(hero_key)

            if ((in_herolabs == 'true' and this_hero_status == 'HeroLabs') or
                (in_herolabs == 'false' and this_hero_status == 'Released')) then

                local is_recommended = hero_data['IsRecommended'] or false

                --- Create a sort key for each hero to ensure correct alphabetical ordering.
                local hero_name = lang_module.get_string(hero_key, nil, 'en')
                local sort_key_to_find = hero_key .. '_sort'
                local potential_sort_key = lang_module.get_string(sort_key_to_find, nil, 'en')

                local sort_key
                -- Detect translation failure if the returned string contains the original search key
                if string.find(potential_sort_key, sort_key_to_find, 1, true) then
                    sort_key = hero_name
                else
                    sort_key = potential_sort_key
                end

                -- NOTE: Check if lang_module.get_string(hero_key, 'en') returns the same value as hero_name.
                -- If the second argument defaults to nil natively, you can optimize further by setting: link = hero_name
                local hero_link = lang_module.get_string(hero_key, 'en')

                -- Store reusable hero data
                local hero = {
                    key = hero_key,
                    name = hero_name,
                    sort_key = sort_key,
                    link = hero_link,
                    recommended = tostring(is_recommended)
                }

                table.insert(heroes, hero)
            end
        end
    end

    -- Sort heroes
    table.sort(heroes, function(a, b)
        return a.sort_key < b.sort_key
    end)

    heroes_cache[in_herolabs] = heroes
    return heroes
end

-- for [[Template:Deadlock_Wiki/Heroes]]
function p.get_hero_nav_cards(frame)
    local text_size = frame.args['text_size']
    local card_size = frame.args['card_size']
    local in_herolabs = frame.args['in_herolabs'] or 'false'
    local debug_mode = frame.args['debug_mode'] == 'true'

    local heroes = get_heroes(in_herolabs)
    local parts = {}

    for _, hero in ipairs(heroes) do
        table.insert(parts, string.format('{{Hero card2|heroName=%s|cardSize=%s|textSize=%s|isHeroLabs=%s}}',
            hero.link, card_size, text_size, in_herolabs))
    end

    local ret = table.concat(parts)

    if debug_mode then
        return ret
    else
        return frame:preprocess(ret)
    end
end

-- for [[Template:Roster]]
function p.get_hero_roster(frame)
    local in_herolabs = frame.args['in_herolabs'] or 'false'
    local debug_mode = frame.args['debug_mode'] == 'true'

    local heroes = get_heroes(in_herolabs)
    local parts = {}

    for _, hero in ipairs(heroes) do
        table.insert(parts, string.format('{{HeroRosterCard|name=%s|key=%s}}', hero.name, hero.key))
    end

    local ret = table.concat(parts)

    if debug_mode then
        return ret
    else
        return frame:preprocess(ret)
    end
end

-- for [[Template:Quotes Navbox]] etc.
p.get_hero_bulletpoints = function(frame)
    local subpage = frame.args['1']
    local in_herolabs = frame.args['in_herolabs'] or 'false'
    local debug_mode = frame.args['debug_mode'] == 'true'
    local no_redlinks = frame.args['no_redlinks'] == 'true'

    local heroes = get_heroes(in_herolabs)
    local parts = {}

    for _, hero in ipairs(heroes) do
        -- Lua optimization: clean ternary fallback for page_title assignment
        local page_title = subpage and (hero.link .. '/' .. subpage) or hero.name

        -- Skip redlinks entirely when enabled
        if not (no_redlinks and not utilities.page_exists(page_title)) then
            local item
            if subpage then
                item = string.format('{{PageRef|%s|alt_link=%s}}', hero.link, page_title)
            else
                item = string.format('{{HeroIcon|%s}}', hero.link)
            end
            table.insert(parts, item)
        end
    end

    local ret = table.concat(parts, ' &bull; ')

    if debug_mode then
        return ret
    else
        return frame:preprocess(ret)
    end
end

-- for image galleries
p.get_hero_gallery = function(frame)
    local file_name = frame.args['1'] or ''
    local description = frame.args['2'] or ''
    local in_herolabs = frame.args['in_herolabs'] or 'false'
    local debug_mode = frame.args['debug_mode'] == 'true'

    local heroes = get_heroes(in_herolabs)
    local parts = {}

    for _, hero in ipairs(heroes) do
        table.insert(parts, string.format('File:%s%s|%s%s\n', hero.link, file_name, hero.name, description))
    end
    
    local ret = '<gallery>\n' .. table.concat(parts) .. '</gallery>'

    if debug_mode then
        return ret
    else
        return frame:preprocess(ret)
    end
end

-- Generate 3D model gallery
function p.get_hero_models(frame)
    local in_herolabs = frame.args['in_herolabs'] or 'false'
    local debug_mode = frame.args['debug_mode'] == 'true'

    local heroes = get_heroes(in_herolabs)
    local parts = {}

    for _, hero in ipairs(heroes) do
        table.insert(parts, string.format('{{3D Model|%s}}', hero.name))
    end

    local ret = table.concat(parts)

    if debug_mode then
        return ret
    else
        return frame:preprocess(ret)
    end
end

return p