|
|
(33 intermediate revisions by 2 users not shown) |
Line 1: |
Line 1: |
| local lang = require "Module:Lang" | | local data = mw.loadJsonData("Data:AbilityCards.json") |
| local utils = require "Module:Utilities"
| |
|
| |
|
| local p = {} | | local p = {} |
| local data = mw.loadJsonData("Data:AbilityCards.json")
| |
|
| |
| -- Maps attr type to an appropriate image and page link
| |
| -- Optional icon size, otherwise will be defaulted on the template
| |
| local ATTR_TYPE_ICON_MAP = {
| |
| bullet_armor_up = {img='Bullet_Armor.png', link='Damage_Resistance'},
| |
| charges = {img='AttributeIconMaxChargesIncrease.png', link=''},
| |
| damage = {img='Damage_heart.png', link='', color = nil},
| |
| bullet_damage = {img='Damage.png', link='Bullet_Damage', color = 'Brown'},
| |
| fire_rate = {img='Fire Rate.png', link='Fire_Rate'},
| |
| healing = {img='Health regen.png', link='Health_Regen'},
| |
| health = {img='Extra Health.png', link='Health'},
| |
| range = {img='CastRange.png', link='Ability_Range'},
| |
| tech_armor_up = {img='Spirit_Armor.png', link='Damage_Resistance'},
| |
| tech_damage = {img='AttributeIconTechShieldHealth.png', link='Spirit_Damage', color = 'Purple',size = '12px'},
| |
| distance = {img='AttributeIconTechRange.png', link='Ability_Range'},
| |
| duration = {img='AttributeIconTechDuration.png', link='Ability Duration'},
| |
| slow = {img='MoveSlow.png', link=''}
| |
| }
| |
|
| |
|
| -- returns the table of a specific item | | -- returns the table of a specific item |
| function get_ability(hero_name, ability_num) | | function get_ability(hero_key, ability_num) |
| local hero_key = get_hero_key(hero_name) | | local ui_data = data[hero_key] |
| if(hero_key == nil) then return "Hero Not Found" end | | if(ui_data == nil) then return "Hero Not Found" end |
| return data[hero_key][tonumber(ability_num)] | | return ui_data[tonumber(ability_num)] |
| end | | end |
|
| |
|
| function get_hero_key(hero_name)
| | --{{#invoke:AbilityData|get_ability_name|HERO_NAME|ABILITY_NUM}}-- |
| for i, hero in pairs(data) do
| | p.get_ability_name = function(frame) |
| if hero["Name"] == hero_name then
| |
| return i
| |
| end
| |
| end
| |
| return nil
| |
| end
| |
| | |
| --{{#invoke:AbilityData|get_ability_card|HERO_NAME|ABILITY_NUM|ADD_LINK|NOTES}}-- | |
| p.get_ability_card = function(frame)
| |
| local hero_name = frame.args[1]
| |
| local ability_num = frame.args[2]
| |
| local add_link = frame.args[3]
| |
| local notes = frame.args[4]
| |
| | |
| local ability = get_ability(hero_name, ability_num)
| |
| if(ability == nil) then
| |
| return 'Ability data not found for hero ' ..hero_name.. ' and num ' .. ability_num
| |
| end
| |
|
| |
| local name_link = nil
| |
| if add_link == 'true' then
| |
| name_link = string.format("%s#(%s)_%s", hero_name, ability_num, ability.Name)
| |
| end
| |
|
| |
| return frame:expandTemplate{
| |
| title = "Ability card v2",
| |
| args = {
| |
| hero_name = hero_name,
| |
| ability_num = ability_num,
| |
| name = lang._get_string(ability.Key),
| |
| name_link = name_link,
| |
| icon = lang._get_string(ability.Key, 'en') .. '.png',
| |
| description = lang._get_string(ability.DescKey),
| |
| radius = ability.Radius and ability.Radius.Value,
| |
| range = ability.AbilityCastRange and ability.AbilityCastRange.Value,
| |
| duration = ability.AbilityDuration and ability.AbilityDuration.Value,
| |
| -- ability_width = format_value_with_prepost(width_key, ability[width_key]),
| |
| cooldown =ability.AbilityCooldown and ability.AbilityCooldown.Value,
| |
| charge_cooldown = ability.AbilityCooldownBetweenCharge and ability.AbilityCooldownBetweenCharge.Value,
| |
| num_of_charges = ability.AbilityCharges and ability.AbilityCharges.Value,
| |
| notes = notes
| |
| }
| |
| }
| |
| end
| |
| | |
| -- Get the description for an ability's info section
| |
| --{{#invoke:AbilityData|get_info_desc|HERO_NAME|ABILITY_NUM|INFO_SECTION_INDEX}}--
| |
| p.get_info_desc = function(frame) | |
| local hero_name = frame.args[1] | | local hero_name = frame.args[1] |
| local ability_num = frame.args[2] | | local ability_num = frame.args[2] |
| local info_section_num = frame.args[3]
| |
| | | |
| local ability = get_ability(hero_name, ability_num) | | local ability = get_ability(hero_name, ability_num) |
| if(ability == nil) then return "Ability Not Found" end | | if(ability == nil) then return "Ability Not Found" end |
| local info_section = ability['Info'..info_section_num] | | return ability.Name |
|
| |
| -- some abilities have no info sections
| |
| if info_section == nil then return '' end
| |
|
| |
| return lang._get_string(info_section.DescKey)
| |
| end
| |
|
| |
| --{{#invoke:AbilityData|get_info_main|HERO_NAME|ABILITY_NUM|INFO_SECTION_INDEX}}--
| |
| p.get_info_main = function(frame)
| |
| local hero_name = frame.args[1]
| |
| local ability_num = frame.args[2]
| |
| local info_section_num = frame.args[3]
| |
|
| |
| local ability = get_ability(hero_name, ability_num)
| |
| if(ability == nil) then return "Ability Not Found" end
| |
|
| |
| local info_section = ability['Info'..info_section_num]
| |
|
| |
| -- some abilities have no info sections
| |
| if info_section == nil then return '' end
| |
|
| |
| local props = info_section.Main.Props
| |
| | |
| -- Concatenate multiple section boxes into a single output template
| |
| local info_box_template = ''
| |
| for k, prop in pairs(props) do
| |
| -- Exclude 0 values
| |
| if prop.Value ~= 0 then
| |
| local icon = get_icon(prop.Type)
| |
|
| |
| section_box = frame:expandTemplate{
| |
| title = "Ability_card_v2/MainBox",
| |
| args = {
| |
| key = prop.Key,
| |
| value = prop.Value,
| |
| icon = icon.img,
| |
| icon_link = icon.link,
| |
| icon_color = icon.color,
| |
| icon_size = icon.size,
| |
| scale_value = prop.Scale and utils.round_to_sig_fig(prop.Scale.Value, 3),
| |
| scale_type = prop.Scale and prop.Scale.Type
| |
| }
| |
| }
| |
| info_box_template = info_box_template .. section_box .. '\n'
| |
| end
| |
| end
| |
|
| |
| return info_box_template
| |
| end
| |
| | |
| --{{#invoke:AbilityData|get_info_alt|HERO_NAME|ABILITY_NUM|INFO_SECTION_INDEX}}--
| |
| p.get_info_alt = function(frame)
| |
| local hero_name = frame.args[1]
| |
| local ability_num = frame.args[2]
| |
| local info_section_num = frame.args[3]
| |
|
| |
| local ability = get_ability(hero_name, ability_num)
| |
| if(ability == nil) then return "Ability Not Found" end
| |
|
| |
| local info_section = ability['Info'..info_section_num]
| |
|
| |
| -- some abilities have no info sections
| |
| if info_section == nil then return '' end
| |
|
| |
| local props = info_section.Alt
| |
|
| |
| -- Concatenate multiple section boxes into a single output template
| |
| local info_box_template = ''
| |
| for k, prop in pairs(props) do
| |
| -- Some props don't have values, as those come from upgrades
| |
| -- For now, we will ignore these and only show data for the base ability
| |
| if prop.Value then
| |
| local icon = get_icon(prop.Type)
| |
|
| |
| section_box = frame:expandTemplate{
| |
| title = "Ability_card_v2/AltBox",
| |
| args = {
| |
| key = prop.Key,
| |
| value = prop.Value,
| |
| icon = icon.img,
| |
| icon_link = icon.link,
| |
| icon_color = icon.color,
| |
| icon_size = icon.size,
| |
| scale_value = prop.Scale and utils.round_to_sig_fig(prop.Scale.Value, 3),
| |
| scale_type = prop.Scale and prop.Scale.Type
| |
| }
| |
| }
| |
| info_box_template = info_box_template .. section_box .. '\n'
| |
| end
| |
| end
| |
|
| |
| return info_box_template
| |
| end | | end |
|
| |
|
| local UPGRADE_COST_MAP = {1, 2, 5}
| | --Write's an ability link for a given ability name in english |
| --{{#invoke:AbilityData|get_upgrades|HERO_NAME|ABILITY_NUM}}-- | | --Siphon Life --> Abrams#(1)_Siphon_Life |
| p.get_upgrades = function(frame)
| | function ability_to_hyperlink(ability_name_to_search) |
| local hero_name = frame.args[1]
| | if (ability_name_to_search == nil) then return "No ability name provided" end |
| local ability_num = frame.args[2]
| | local hero_name |
| local ability = get_ability(hero_name, ability_num)
| | local ability_name |
| if(ability == nil) then return "Ability Not Found" end | |
| | |
| local props = ability.Upgrades | |
| | | |
| -- Concatenate multiple section boxes into a single output template | | -- Iterate heros |
| local upgrades_template = ''
| | for hero_key, hero_data in pairs(data) do |
| for k, prop in pairs(props) do | | -- Iterate abilities |
| local description = lang._get_string(prop.DescKey) | | hero_name = hero_data["Name"] |
| | | for ability_num, ability_data in pairs(hero_data) do |
| -- Generate a description if there is no localized string | | if (ability_num ~= "Name") then |
| if description == nil then
| | ability_name = ability_data["Name"] |
| description = create_description(prop, frame)
| | if (ability_name == ability_name_to_search) then |
| end
| | -- Ability number and hero found |
|
| | -- "Siphon Life" > "Siphon_Life" |
| -- Vary the font size based on the number of characters to prevent overflow
| | ability_name = ability_name:gsub(" ", "_") |
| local fontsize = '1rem'
| | return hero_name .. "#(" .. ability_num .. ")_" .. ability_name |
| if #description > 60 and #description < 71 then
| | end |
| fontsize = '0.95rem'
| | end |
| elseif #description > 70 and #description < 91 then
| |
| fontsize = '0.875rem'
| |
| elseif #description > 90 then
| |
| fontsize = '0.8rem' | |
| end | | end |
|
| |
| box = frame:expandTemplate{
| |
| title = "Ability_card_v2/UpgradeBox",
| |
| args = {
| |
| cost = UPGRADE_COST_MAP[k],
| |
| description = description,
| |
| scale_value = prop.Scale and utils.round_to_sig_fig(prop.Scale.Value, 3),
| |
| scale_type = prop.Scale and prop.Scale.Type,
| |
| fontsize = fontsize
| |
| }
| |
| }
| |
| upgrades_template = upgrades_template .. box .. '\n'
| |
| end | | end |
| | | |
| return upgrades_template | | return nil |
| end | | end |
|
| |
|
| function create_description(prop, frame)
| | --Writes an ability's icon from its name |
| local description = ''
| | --Shoulder Charge --> [[File:Shoulder Charge.png|link=Abrams#(1)_Shoulder_Charge|size=20px]] [[Abrams...|Shoulder Charge]] |
| for k, v in pairs(prop) do
| | p.write_ability_icon = function(frame) |
| local formatted_value = format_value_with_prepost(k, v, frame)
| | local ability_name = frame.args[1] |
| local attr_name = lang._get_string(k..'_label')
| | local custom_display_text = frame.args[2] |
| description = description .. string.format('%s %s', formatted_value, attr_name)
| | if (custom_display_text == nil or custom_display_text == "") then custom_display_text = ability_name end |
| end
| |
| | | |
| return description
| | local size = 20 |
| end
| |
| | |
| function get_icon(attr_type)
| |
| local mappedAttr = ATTR_TYPE_ICON_MAP[attr_type] | |
| local img = 'GenericProperty.png'
| |
| local link = ''
| |
| local size = nil
| |
| local color = 'Grey'
| |
| if mappedAttr then
| |
| img = mappedAttr.img
| |
| link = mappedAttr.link
| |
| size = mappedAttr.size
| |
| color = mappedAttr.color
| |
| end
| |
| | | |
| return {img=img, link=link, size=size} | | local hyperlink = ability_to_hyperlink(ability_name) |
| end
| | if (hyperlink == nil) then return "Ability " .. ability_name .. " not found" end |
| | |
| --{{#invoke:AbilityData|get_ability_name|HERO_NAME|ABILITY_NUM}}--
| |
| p.get_ability_name = function(frame)
| |
| local hero_name = frame.args[1] | |
| local ability_num = frame.args[2]
| |
| | | |
| local ability = get_ability(hero_name, ability_num) | | local icon = "[[File:" .. ability_name .. ".png|link=" .. hyperlink .. "|" .. size .. "px]]" |
| if(ability == nil) then return "Ability Not Found" end
| | icon = '<span style="position: relative; bottom: 2px; filter: brightness(0) saturate(100%);">' .. icon .. '</span>' |
| return ability.Name
| |
| end
| |
| | |
| -- Add prefix and postfix labels to a value. Eg. "32" -> "32s"
| |
| function format_value_with_prepost(key, value, frame)
| |
| if (value == nil) then return nil end
| |
|
| |
| local prefix = lang._get_string(string.format("%s_prefix",key))
| |
| local postfix = lang._get_string(string.format("%s_postfix",key)) | |
| | | |
| -- Default pre/post fix to empty string, as they may not exist | | local link = "[[" .. hyperlink .. "|" .. custom_display_text .. "]]" |
| if (prefix == nil) then prefix = '' end
| |
| if (postfix == nil) then postfix = '' end
| |
| | | |
| -- If string ends with 'm', then set the postfix to 'm' and remove it | | return icon .. " " .. link |
| if utils.string_endswith(tostring(value), 'm') then
| |
| value = tonumber(value:sub(1, -2))
| |
| postfix = 'm'
| |
| end
| |
|
| |
| if (prefix == '{s:sign}') then
| |
| if value < 0 then
| |
| prefix = '-'
| |
| else
| |
| prefix = '+'
| |
| end
| |
| -- if no prefix on positive value, add a '+'
| |
| else
| |
| if value > 0 then
| |
| prefix = '+'
| |
| end
| |
| end
| |
|
| |
| value_and_uom = frame:expandTemplate{
| |
| title = 'Template:ValueAndUom',
| |
| args = {
| |
| prefix..value,
| |
| postfix,
| |
| uom_style = 'font-size: 12px;'
| |
| }
| |
| }
| |
| | |
| return value_and_uom
| |
| end
| |
| | |
| function find_width_key(ability)
| |
| for key, value in pairs(ability) do
| |
| if type(key) == "string" and key:sub(-5) == "Width" then
| |
| return key
| |
| end
| |
| end
| |
| return nil
| |
| end
| |
| | |
| function string_in_list(str, list)
| |
| for _, value in ipairs(list) do
| |
| if value == str then
| |
| return true
| |
| end
| |
| end
| |
| return false
| |
| end | | end |
|
| |
|
| return p | | return p |