|
|
Line 1: |
Line 1: |
| local lang = require "Module:Lang"
| |
| local commonutils = require "Module:Utilities"
| |
| local utils = require "Module:Abilities/utils"
| |
|
| |
| local p = {} | | local p = {} |
| local data = mw.loadJsonData("Data:AbilityCards.json")
| |
|
| |
| -- Maps attr type to an appropriate image and page link
| |
| -- Optional icon size, will be defaulted on the template
| |
| local ATTR_TYPE_ICON_MAP = {
| |
| bullet_armor_up = {img='Bullet_Armor.png', link='Damage_Resistance'},
| |
| bullet_armor_down = {img='Bullet_armor_down.png', link='Damage_Resistance', size='23px'},
| |
| cast = {img='AttributeIconMaxChargesIncrease.png', link=''},
| |
| charges = {img='AttributeIconMaxChargesIncrease.png', link=''},
| |
| damage = {img='Damage_heart.png', link='', color = 'NoColor'}, -- 'NoColor' will apply no icon color and use the original image
| |
| 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'},
| |
| move_speed = {img='Move speed.png', link='Move Speed'},
| |
| 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
| |
| function get_ability(hero_key, ability_num)
| |
| local ui_data = data[hero_key]
| |
| if(ui_data == nil) then return "Hero Not Found" end
| |
| return ui_data[tonumber(ability_num)]
| |
| end
| |
|
| |
| function get_hero_key(hero_name)
| |
| for i, hero in pairs(data) do
| |
| 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}}--
| |
| --Simply calls get_ability_card_from_key with the same parameters, but with key
| |
| --get_ability_card and invoke_get_ability_card_key will eventually be removed, and
| |
| --get_ability_card_from_key will be renamed to get_ability_card
| |
| --both routes exist temporarily as current hero pages use get_ability_card via hero name
| |
| --and im currently testing via hero_key on [[User:Sur/Abrams]]
| |
| --on the final version with fully automated pages, hero_key will be used.
| |
| --for now, hero_name can suffice
| |
| 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 hero_key = get_hero_key(hero_name)
| |
|
| |
| return p.get_ability_card_from_key(hero_key, ability_num, add_link, notes)
| |
| end
| |
|
| |
| function p.get_ability_card_from_key(hero_key, ability_num, add_link, notes)
| |
| if type(hero_key) == 'table' and hero_key.args then
| |
| local frame = hero_key
| |
| hero_key = frame.args[1]
| |
| ability_num = frame.args[2]
| |
| add_link = frame.args[3]
| |
| notes = frame.args[4]
| |
| end
| |
|
| |
| local ability = get_ability(hero_key, ability_num)
| |
| if(ability == nil) then
| |
| return 'Ability data not found for hero ' ..hero_key.. ' and num ' .. ability_num
| |
| end
| |
|
| |
| local ability_name_localized = lang.get_string(ability.Key)
| |
| local name_link = nil
| |
| if add_link == 'true' then
| |
| name_link = ability_name_localized
| |
| end
| |
|
| |
| return mw.getCurrentFrame():expandTemplate{
| |
| title = "Ability card v2/Card",
| |
| args = {
| |
| hero_key = hero_key,
| |
| ability_num = ability_num,
| |
| name = ability_name_localized,
| |
| name_link = name_link,
| |
| icon = lang.get_string(ability.Key, 'en') .. '.png',
| |
| description = mw.getCurrentFrame():preprocess(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 all info sections for specified ability
| |
| --{{#invoke:AbilityData|get_ability_card|HERO_KEY|ABILITY_NUM}}--
| |
| p.get_all_info_sections = function(frame)
| |
| local hero_key = frame.args[1]
| |
| local ability_num = frame.args[2]
| |
|
| |
| local ability = get_ability(hero_key, ability_num)
| |
| if(ability == nil) then return "Ability Not Found" end
| |
|
| |
| local output_template = ''
| |
| for info_section_num=1, 10 do
| |
| local info_section = ability['Info'..info_section_num]
| |
| -- some abilities have no info sections
| |
| if info_section == nil then break end
| |
| local info_template = frame:expandTemplate{
| |
| title = "Ability_card_v2/Card/Info section",
| |
| args = {
| |
| hero_key = hero_key,
| |
| ability_num = ability_num,
| |
| info_section_num = info_section_num,
| |
| }
| |
| }
| |
| output_template = output_template .. info_template
| |
| end
| |
|
| |
| return output_template
| |
| end
| |
|
| |
| -- Get the description for an ability's info section
| |
| --{{#invoke:AbilityData|get_info_desc|HERO_KEY|ABILITY_NUM|INFO_SECTION_INDEX}}--
| |
| p.get_info_desc = function(frame)
| |
| local hero_key = frame.args[1]
| |
| local ability_num = frame.args[2]
| |
| local info_section_num = frame.args[3]
| |
|
| |
| local ability = get_ability(hero_key, 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
| |
|
| |
| if info_section.DescKey == nil then
| |
| return ''
| |
| end
| |
|
| |
| return frame:preprocess(lang.get_string(info_section.DescKey))
| |
| end
| |
|
| |
| --{{#invoke:AbilityData|get_info_main|HERO_KEY|ABILITY_NUM|INFO_SECTION_INDEX}}--
| |
| p.get_info_main = function(frame)
| |
| local hero_key = frame.args[1]
| |
| local ability_num = frame.args[2]
| |
| local info_section_num = frame.args[3]
| |
|
| |
| local ability = get_ability(hero_key, 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 main = info_section.Main
| |
| if main == 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 and prop.Value ~= 0 then
| |
| local icon = get_icon(prop.Type)
| |
|
| |
| section_box = frame:expandTemplate{
| |
| title = "Ability_card_v2/Card/MainBox",
| |
| args = {
| |
| title = prop.Title,
| |
| 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 commonutils.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_KEY|ABILITY_NUM|INFO_SECTION_INDEX}}--
| |
| p.get_info_alt = function(frame)
| |
| local hero_key = frame.args[1]
| |
| local ability_num = frame.args[2]
| |
| local info_section_num = frame.args[3]
| |
|
| |
| local ability = get_ability(hero_key, 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
| |
| if props == nil then
| |
| return ''
| |
| end
| |
|
| |
| -- 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 and prop.Value ~= 0 then
| |
| local icon = get_icon(prop.Type)
| |
| section_box = frame:expandTemplate{
| |
| title = "Ability_card_v2/Card/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 commonutils.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
| |
|
| |
| local UPGRADE_COST_MAP = {1, 2, 5}
| |
| --{{#invoke:AbilityData|get_upgrades|HERO_KEY|ABILITY_NUM}}--
| |
| p.get_upgrades = function(frame)
| |
| local hero_key = frame.args[1]
| |
| local ability_num = frame.args[2]
| |
| local ability = get_ability(hero_key, ability_num)
| |
| if(ability == nil) then return "Ability Not Found" end
| |
|
| |
| local props = ability.Upgrades
| |
|
| |
| -- Concatenate multiple section boxes into a single output template
| |
| local upgrades_template = ''
| |
| for k, prop in pairs(props) do
| |
| local description = lang.get_string(prop.DescKey)
| |
|
| |
| -- Generate a description if there is no localized string
| |
| if (description == nil or description == '') then
| |
| description = create_description(prop, frame)
| |
| end
| |
|
| |
| -- Vary the font size based on the number of characters to prevent overflow
| |
| local fontsize = '1rem'
| |
| if #description > 60 and #description < 71 then
| |
| fontsize = '0.95rem'
| |
| elseif #description > 70 and #description < 91 then
| |
| fontsize = '0.875rem'
| |
| elseif #description > 90 then
| |
| fontsize = '0.8rem'
| |
| end
| |
|
| |
| box = frame:expandTemplate{
| |
| title = "Ability_card_v2/Card/UpgradeBox",
| |
| args = {
| |
| cost = UPGRADE_COST_MAP[k],
| |
| description = frame:preprocess(description),
| |
| scale_value = prop.Scale and commonutils.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
| |
|
| |
| return upgrades_template
| |
| end
| |
|
| |
| function create_description(prop, frame)
| |
| local description = ''
| |
| for k, v in pairs(prop) do
| |
| local formatted_value = utils.format_value_with_prepost(k, v, frame)
| |
| local attr_name = lang.get_string(k..'_label')
| |
| description = description .. string.format('%s %s', formatted_value, attr_name)
| |
| end
| |
|
| |
| return description
| |
| 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 or color
| |
| end
| |
|
| |
| return {img=img, link=link, color=color, size=size}
| |
| end
| |
|
| |
| --{{#invoke:AbilityData|get_ability_name|HERO_NAME|ABILITY_NUM}}-- | | --{{#invoke:AbilityData|get_ability_name|HERO_NAME|ABILITY_NUM}}-- |
| p.get_ability_name = function(frame) | | p.get_ability_name = function(frame) |