Editing Module:Sandbox/Vergir

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 = {};
return p
local heroes_data = mw.loadJsonData("Data:HeroData.json")
local util_module = require('Module:Utilities')
local lang_module = require('Module:Lang')
 
--------------------------------------------------------------------------------
-- Internal helpers
--------------------------------------------------------------------------------
 
-- Localized string for a key, falling back to a readable version of `fallback`
-- plus a "missing translation" tooltip.
local function localize(key, fallback)
local result = lang_module.get_string(key)
if (result == "") or (result == nil) then
result = util_module.add_space_before_cap(fallback) .. mw.getCurrentFrame():expandTemplate{title="MissingValveTranslationTooltip"}
end
return result
end
 
-- Raw scaling value of a stat under LevelScaling / SpiritScaling, or nil when
-- the hero has no scaling of that type for that stat.
local function raw_scaling(hero_data, scaling_type, stat)
local scaling = hero_data and hero_data[scaling_type .. "Scaling"]
if (scaling == nil or stat == nil) then return nil end
return scaling[stat]
end
 
-- Mapping from hero name to internal tag name
local TAG_NAME_MAP = {
["Abrams"] = "Abrams",
["Bebop"] = "Bebop",
["Billy"] = "Punkgoat",
["Calico"] = "Nano",
["The Doorman"] = "Doorman",
["Drifter"] = "Drifter",
["Dynamo"] = "Dynamo",
["Apollo"] = "Fencer",
["Graves"] = "Necro",
["Grey Talon"] = "Orion",
["Haze"] = "Haze",
["Holliday"] = "Astro",
["Infernus"] = "Inferno",
["Ivy"] = "Tengu",
["Kelvin"] = "Kelvin",
["Lady Geist"] = "Geist",
["Lash"] = "Lash",
["McGinnis"] = "Engineer",
["Mina"] = "VampireBat",
["Mirage"] = "Mirage",
["Mo & Krill"] = "Digger",
["Paige"] = "Bookworm",
["Paradox"] = "Chrono",
["Celeste"] = "Unicorn",
["Pocket"] = "Synth",
["Rem"] = "Familiar",
["Seven"] = "Gigawatt",
["Shiv"] = "Shiv",
["Silver"] = "Werewolf",
["Silver (Transformed)"] = "Werewolf",
["Sinclair"] = "Magician",
["Venator"] = "Priest",
["Victor"] = "Frank",
["Vindicta"] = "Vindicta",
["Viscous"] = "Viscous",
["Vyper"] = "Viper",
["Warden"] = "Warden",
["Wraith"] = "Wraith",
["Yamato"] = "Yamato",
}
 
--------------------------------------------------------------------------------
-- Data access, for use by other modules
--------------------------------------------------------------------------------
 
-- returns the table of a specific item, used by external modules
function p.get_json_item(name)
for i,v in pairs(heroes_data) do
if (v["Name"] == name) then
return v
end
end
return nil
end
 
-- Hero table for a hero_* key or an exact English name, or nil.
local function hero_by_key_or_name(input)
local hero = heroes_data[input]
if (hero == nil) then hero = p.get_json_item(input) end
return hero
end
 
-- Value of a stat, checking the hero's top level, then Weapon, then AltFire.
-- Returns nil when the hero has no such stat.
function p.get_stat(hero_data, stat)
if (hero_data == nil or stat == nil) then return nil end
local value = hero_data[stat]
if (value == nil and hero_data.Weapon) then
value = hero_data.Weapon[stat]
end
if (value == nil and hero_data.Weapon and hero_data.Weapon.AltFire) then
value = hero_data.Weapon.AltFire[stat]
end
return value
end
 
-- Ordered list of a hero's scalings for a stat, Level first then Spirit:
--  { { type = "Level", value = 1.5 }, { type = "Spirit", value = 0.04 } }
-- Absent and zero scalings are omitted, so an empty list means "no scaling".
function p.get_scalings(hero_data, stat)
local scalings = {}
for _, scaling_type in ipairs({"Level", "Spirit"}) do
local value = raw_scaling(hero_data, scaling_type, stat)
if (value ~= nil and value ~= 0) then
table.insert(scalings, { type = scaling_type, value = value })
end
end
return scalings
end
 
-- DEPRECATED, kept for [[Module:HeroComparisonTable]]. Use p.get_scalings.
-- Keyed by scaling value, so it silently drops an entry when Level and Spirit
-- scale by the same amount, and it keeps zero scalings.
function p.get_hero_scaling_data(hero_data, hero_stat_key)
local scaling_data_returned = {}
for _, scaling_type in ipairs({"Spirit", "Level"}) do
local scaling_value = raw_scaling(hero_data, scaling_type, hero_stat_key)
if (scaling_value ~= nil) then
scaling_data_returned[scaling_value] = scaling_type
end
end
return scaling_data_returned
end
 
-- Whether a hero has a stat at all: a non-zero base value, or any scaling.
function p.has_stat(hero_data, stat)
local base = p.get_stat(hero_data, stat)
if (base ~= nil and base ~= 0) then return true end
return #p.get_scalings(hero_data, stat) > 0
end
 
-- Resolves a hero_* key or an English hero name to a hero_* key.
-- Returns nil when the input matches no hero. Name matching is case-insensitive.
function p.find_hero_key(input)
if (input == nil or input == '') then return nil end
if (heroes_data[input] ~= nil) then return input end
local wanted = mw.ustring.lower(input)
for hero_key, hero_data in pairs(heroes_data) do
if (hero_data["Name"] and mw.ustring.lower(hero_data["Name"]) == wanted) then
return hero_key
end
end
return nil
end
 
-- A hero's Nth roster tag (1-3) by English name, or '' when there is no such tag.
function p.hero_tag(hero_en, index)
local tagname = hero_en and TAG_NAME_MAP[hero_en]
if (tagname == nil) then return '' end
if (index ~= 1 and index ~= 2 and index ~= 3) then return '' end
return lang_module.get_string(string.format("Citadel_%s_HeroTag_%d", tagname, index)) or ''
end
 
--------------------------------------------------------------------------------
-- Wikitext entry points
--------------------------------------------------------------------------------
 
-- returns the key of the specified hero's english name
function p.get_hero_key(frame)
local hero_name_input = frame.args[1]
if not hero_name_input then
return "Error: Hero name not specified."
end
return p.find_hero_key(hero_name_input) or "Hero not found."
end
 
--{{#invoke:HeroData|resolve_key|HERO_KEY_OR_NAME}}--
-- The matching hero_* key, or '' when the input matches no hero.
function p.resolve_key(frame)
return p.find_hero_key(frame.args[1]) or ''
end
 
--{{#invoke:HeroData|get_hero_var|HERO_NAME|STAT_NAME|sig_figs_or_localize}}--
--sig_figs optional for rounding floats
p.get_hero_var = function(frame)
    local hero_name = frame.args[1]
    local hero_stat_key = frame.args[2]
    local sig_figs_or_localize = frame.args[3]
   
    local hero = hero_by_key_or_name(hero_name)
    if(hero == nil) then return "Hero Not Found" end
   
    local var_value = p.get_stat(hero, hero_stat_key)
    if(var_value == nil) then return 0 end
   
    --round
    if (sig_figs_or_localize ~= nil and tonumber(sig_figs_or_localize) ~= nil) then
        var_value = util_module.round_to_sig_fig(var_value, sig_figs_or_localize)
        if (var_value == nil) then return "get_hero_var() error with rounding" end
    end
   
    --localize
    if (sig_figs_or_localize == "true") then
        return lang_module.get_string(var_value)
    end
 
    return var_value
end
 
--{{#invoke:HeroData|get_alt_fire_var|HERO_NAME|STAT_NAME|sig_figs_or_localize}}--
p.get_alt_fire_var = function(frame)
    local hero_name = frame.args[1]
    local stat_key = frame.args[2]
    local sig_figs_or_localize = frame.args[3]
   
    local hero = hero_by_key_or_name(hero_name)
    if(hero == nil) then return "Hero Not Found" end
   
    if not (hero.Weapon and hero.Weapon.AltFire) then
        return "No Alt Fire"
    end
   
    local var_value = hero.Weapon.AltFire[stat_key]
    if(var_value == nil) then return 0 end
   
    --round
    if (sig_figs_or_localize ~= nil and tonumber(sig_figs_or_localize) ~= nil) then
        var_value = util_module.round_to_sig_fig(var_value, sig_figs_or_localize)
    end
   
    --localize
    if (sig_figs_or_localize == "true") then
        return lang_module.get_string(var_value)
    end
 
    return var_value
end
 
--{{#invoke:HeroData|get_list_elem|HERO_NAME|VAR|NUMBER|LOCALIZE}}
p.get_list_elem = function(frame)
local hero_name = frame.args[1]
local var = frame.args[2]
local number_int = tonumber(frame.args[3])
local localize_arg = frame.args[4]
local hero = hero_by_key_or_name(hero_name)
if(hero == nil) then return "Hero Not Found" end
local list = p.get_stat(hero, var)
if (list == nil) then return "" end
local element = list[number_int]
if (element == nil) then return "" end
if localize_arg=="true" then
element = lang_module.get_string(element)
end
return element
end
 
p.get_ability_key = function(frame)
local hero_key = frame.args[1]
local bound_slot_number = frame.args[2]
local hero_data = heroes_data[hero_key]
if (hero_data == nil) then return "Hero key "..hero_key.. " not found" end
local bound_abilities_data = hero_data["BoundAbilities"]
if (bound_abilities_data == nil) then return "Hero key " .. hero_key.. " has no BoundAbilities" end
return bound_abilities_data[tonumber(bound_slot_number)]["Key"]
end
 
p.write_role_playstyle_quote = function(frame)
local hero_key = frame.args[1]
local hero_data = heroes_data[hero_key]
if (hero_data == nil) then return hero_key.." not found" end
local role_key = hero_data["Role"]
local role_localized = lang_module.get_string(role_key, nil, 'en')
local playstyle_key = hero_data["Playstyle"]
local playstyle_localized = lang_module.get_string(playstyle_key, nil, 'en')
local str = "<b>" .. role_localized .. '</b><br>' .. playstyle_localized
local template_args = {}
template_args[1] = ""
template_args[2] = str
return frame:expandTemplate{title = 'Quotation', args = template_args}
end
 
p.write_default_items = function(frame)
local hero_key = frame.args[1] --unlocalized
if (hero_key == nil) then return "No hero key provided" end
local str = ""
local hero = heroes_data[hero_key]
if (hero == nil) then return "Hero not found, must be unlocalized" end
local template_title = 'PageRef'
for i, item_key in ipairs(hero["RecommendedItems"] or {}) do
local template_args = {}
template_args[1] = lang_module.get_string(item_key, 'en')
template_args['alt_name'] = localize(item_key, item_key)
local expanded_template = mw.getCurrentFrame():expandTemplate{ title = template_title, args = template_args }
str = str .. "* " .. expanded_template .. "\n"
end
return str
end
 
--If the hero scales with the stat, it returns {{Ss|value}} or {{Ls|value}}, else blank string
--{{#invoke:HeroData|get_hero_scalar|HERO_NAME|SCALING_TYPE|STAT_NAME|sig_figs_or_localize}}--
p.get_hero_scalar = function(frame)
local hero_key = frame.args[1]
local scaling_type = frame.args[2]
local hero_stat_key = frame.args[3]
local sig_figs_or_localize = frame.args[4]
local no_template = frame.args["no_template"]
local hero_data = hero_by_key_or_name(hero_key)
if(hero_data == nil) then return "Hero not found." end
local scaling_value = raw_scaling(hero_data, scaling_type, hero_stat_key)
if scaling_value == nil then return "" end
 
--round
if (sig_figs_or_localize ~= nil and tonumber(sig_figs_or_localize) ~= nil) then
scaling_value = util_module.round_to_sig_fig(scaling_value, sig_figs_or_localize)
if (scaling_value == nil) then return "get_hero_scalar() error with rounding" end
end
--localize
if (sig_figs_or_localize == "true") then
return lang_module.get_string(scaling_value)
end
if no_template == "true" then
return scaling_value
end
return p.write_scalar_str(scaling_value, scaling_type)
end
 
-- Check if a hero has a stat (Base, Boons, or Spirit Scaling)
-- Returns "true" if found, nil if not (for #if templates)
p.hero_has_stat = function(frame)
local hero_key = frame.args[1]
local stat_key = frame.args[2]
if (hero_key == nil) then return nil end
local hero_data = hero_by_key_or_name(hero_key)
if (hero_data == nil) then return nil end
if p.has_stat(hero_data, stat_key) then return "true" end
return nil
end
 
-- Function to call hero tags based on name
p.get_hero_tag = function (frame)
local name = frame.args[1]
local number = tonumber(frame.args[2])
 
-- Validate input
if not name then
return "Error: Missing name input."
end
 
if number ~= 1 and number ~= 2 and number ~= 3 then
return string.format("Error: Invalid number '%s'. Must be 1, 2, or 3.", tostring(frame.args[2]))
end
 
if TAG_NAME_MAP[name] == nil then
return string.format("Error: Unknown name '%s'.", name)
end
 
return p.hero_tag(name, number)
end
 
--{{#invoke:HeroData|has_tags|HERO_ENGLISH_NAME}}--
-- 'true' when the hero has roster tags, '' otherwise.
function p.has_tags(frame)
if p.hero_tag(frame.args[1], 1) ~= '' then return 'true' end
return ''
end
 
-- Retrieve scaling string of a hero's given stat, if it has scaling, else return blank
-- Scaling string meaning the expanded template {{Ss|scalar}} or {{Ls|scalar}}
function p.write_scalar_str(scaling_value, scaling_type, compact)
local scaling_abbrevs = {Spirit = "Ss", Level = "PI"}
-- Return blank if it doesnt scale
if (scaling_value == 0) then return "" end
-- Round it
scaling_value = util_module.round_to_sig_fig(scaling_value, 3)
--The hero has a scaling value with this stat
local template_title = "Template:" .. scaling_abbrevs[scaling_type]
local template_args = {}
template_args["1"] = scaling_value
if compact then
template_args["compact"] = "yes"
template_args["show_value"] = "yes"
end
local template_call = mw.getCurrentFrame():expandTemplate{ title = template_title, args = template_args }
   
return template_call:gsub("\n", ""):gsub("\r", "")
end
 
-- Outputs a wikitable of heroes grouped by GroundDashDuration using {{HeroIcon|hero_name}}
-- {{#invoke:HeroData|write_ground_dash_buckets}}
p.write_ground_dash_buckets = function(frame)
    local buckets = {
        [0.62] = {},
        [0.68] = {},
        [0.72] = {},
    }
 
    -- Collect heroes
    for hero_key, hero_data in pairs(heroes_data) do
        if not hero_data.InDevelopment and not hero_data.IsDisabled then
            local dash = p.get_stat(hero_data, "GroundDashDuration")
            if dash and buckets[dash] then
                table.insert(buckets[dash], hero_data.Name or hero_key)
            end
        end
    end
 
    -- Sort alphabetically
    for _, list in pairs(buckets) do
        table.sort(list)
    end
 
    -- Determine max rows dynamically
    local max_rows = 0
    for _, list in pairs(buckets) do
        if #list > max_rows then max_rows = #list end
    end
 
    local output = {"{| class='wikitable mw-collapsible'",
    "|+Hero Dash Buckets", "! Bucket 1 !! Bucket 2 !! Bucket 3"}
    local current_frame = frame or mw.getCurrentFrame()
 
    for i = 1, max_rows do
        local row = {}
        for _, bucket in ipairs({0.62, 0.68, 0.72}) do
            local hero_name = buckets[bucket][i]
            table.insert(row, hero_name and current_frame:expandTemplate{title = "HeroIcon", args = {hero_name}} or "")
        end
        table.insert(output, "|-\n| " .. table.concat(row, " || "))
    end
 
    table.insert(output, "|}")
    return table.concat(output, "\n")
end
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: