Module:Abilities-test/card: Difference between revisions

mNo edit summary
Tag: Manual revert
mNo edit summary
 
(10 intermediate revisions by the same user not shown)
Line 4: Line 4:


local p = {}
local p = {}
local data = mw.loadJsonData("User:Saag/AbilityCards.json")
local data = mw.loadJsonData("Data:AbilityCards.json")


-- Maps attr type to an appropriate image and page link
-- Maps attr type to an appropriate image and page link
Line 12: Line 12:
bullet_armor_down = {img='Bullet_Armor.png', link='Damage_Resistance', color = 'NoColor'},
bullet_armor_down = {img='Bullet_Armor.png', link='Damage_Resistance', color = 'NoColor'},
cast = {img='AttributeIconMaxChargesIncrease.png', link=''},
cast = {img='AttributeIconMaxChargesIncrease.png', link=''},
charges = {img='AttributeIconMaxChargesIncrease.png', link=''},
charges = {img='AttributeIconMaxChargesIncrease.png', link='', color = 'Purple'},
damage = {img='Damage_heart.png', link='', color = 'NoColor'}, -- 'NoColor' will apply no icon color and use the original image
damage = {img='Damage_heart.png', link='', color = 'NoColor'}, -- 'NoColor' will apply no icon color and use the original image
bullet_damage = {img='Bullet_damage.png', link='Bullet_Damage', color = 'NoColor'},
bullet_damage = {img='Bullet_damage.png', link='Bullet_Damage', color = 'NoColor'},
Line 19: Line 19:
health = {img='Health.png', link='Health', color = 'Green'},
health = {img='Health.png', link='Health', color = 'Green'},
move_speed = {img='Move speed.png', link='Move Speed', color = 'Green'},
move_speed = {img='Move speed.png', link='Move Speed', color = 'Green'},
range = {img='CastRange.png', link='Ability_Range'},
range = {img='CastRange.png', link='Ability_Range', color = 'Purple'},
radius = {img='CastRange.png', link='Ability_Range', color = 'Purple'},
tech_armor_up = {img='Spirit_Armor.png', link='Damage_Resistance', color = 'NoColor'},
tech_armor_up = {img='Spirit_Armor.png', link='Damage_Resistance', color = 'NoColor'},
tech_damage = {img='AttributeIconTechShieldHealth.png', link='Spirit_Damage', color = 'NoColor',size = '12px'},
tech_damage = {img='AttributeIconTechShieldHealth.png', link='Spirit_Damage', color = 'NoColor',size = '12px'},
distance = {img='AttributeIconTechRange.png', link='Ability_Range'},
distance = {img='AttributeIconTechRange.png', link='Ability_Range'},
duration = {img='AttributeIconTechDuration.png', link='Ability Duration'},
duration = {img='AttributeIconTechDuration.png', link='Ability Duration', color = 'Purple'},
slow = {img='MoveSlow.png', link=''},
slow = {img='MoveSlow.png', link='', color = 'Purple'},
melee_damage = {img='Melee damage.png', link='Melee Damage'},
melee_damage = {img='Melee damage.png', link='Melee Damage'},
cooldown = {img='AttributeIconTechDuration.png', link='Ability Cooldown'},
cooldown = {img='AttributeIconTechDuration.png', link='Ability Cooldown'},
combat_barrier = {img='Barrier.png', link='Barrier', color = 'Green'},
combat_barrier = {img='Barrier.png', link='Barrier', color = 'Green'},
time = {img='AttributeIconTechDuration.png', link='Ability Duration', color = 'Purple'},
}
}


-- TODO - replace this with utils file
-- TODO - replace this with utils file
function get_ability_card_data(hero_key, ability_num)
function utils.get_ability_card_data(hero_key, ability_num)
if(hero_key == nil) then return nil end
if(hero_key == nil) then return nil end
return data[hero_key][tonumber(ability_num)]
return data[hero_key][tonumber(ability_num)]
Line 38: Line 40:


function get_hero_key(hero_name)
function get_hero_key(hero_name)
if hero_name == nil then return nil end
-- if name starts with "hero_", use it directly as the key
if string.sub(hero_name, 1, 5) == "hero_" then return hero_name end
for i, hero in pairs(data) do
for i, hero in pairs(data) do
if hero["Name"] == hero_name then
if hero["Name"] == hero_name then
Line 66: Line 73:
-- Pulls data from Data:AbilityCards.json to populate Template:Ability card v2
-- Pulls data from Data:AbilityCards.json to populate Template:Ability card v2
function build_ability_card(hero_key, ability_num, add_link, notes, notes_source_page)
function build_ability_card(hero_key, ability_num, add_link, notes, notes_source_page)
local ability = get_ability_card_data(hero_key, ability_num)
local ability = utils.get_ability_card_data(hero_key, ability_num)
if(ability == nil) then  
if(ability == nil) then  
return 'Ability data not found for hero ' ..hero_key.. ' and num ' .. ability_num
return 'Ability data not found for hero ' ..hero_key.. ' and num ' .. ability_num
Line 146: Line 153:
icon = lang.get_string(ability.Key, 'en') .. '.png',
icon = lang.get_string(ability.Key, 'en') .. '.png',
channel_time = ability.Cast and ability.Cast.AbilityChannelTime and ability.Cast.AbilityChannelTime.Value,
channel_time = ability.Cast and ability.Cast.AbilityChannelTime and ability.Cast.AbilityChannelTime.Value ~= 9999 and ability.Cast.AbilityChannelTime.Value,
channel_time_ss = ability.Cast and get_attr_ss(ability.Cast.AbilityChannelTime),
channel_time_ss = ability.Cast and get_attr_ss(ability.Cast.AbilityChannelTime),
radius = ability.Radius and ability.Radius.Value,
radius = ability.Radius and ability.Radius.Value,
Line 157: Line 164:
cooldown =ability.AbilityCooldown and ability.AbilityCooldown.Value,
cooldown =ability.AbilityCooldown and ability.AbilityCooldown.Value,
cooldown_ss = get_attr_ss(ability.AbilityCooldown),
cooldown_ss = get_attr_ss(ability.AbilityCooldown),
charge_cooldown = ability.AbilityCooldownBetweenCharge and ability.AbilityCooldownBetweenCharge.Value,
charge_cooldown = ability.AbilityCooldownBetweenCharge and ability.AbilityCooldownBetweenCharge.Value ~= -1 and ability.AbilityCooldownBetweenCharge.Value,
charge_cooldown_ss = get_attr_ss(ability.AbilityCooldownBetweenCharge),
charge_cooldown_ss = get_attr_ss(ability.AbilityCooldownBetweenCharge),
num_of_charges = ability.AbilityCharges and ability.AbilityCharges.Value,
num_of_charges = ability.AbilityCharges and ability.AbilityCharges.Value,
Line 255: Line 262:
local info_section_num = frame.args[3]
local info_section_num = frame.args[3]
local ability = get_ability_card_data(hero_key, ability_num)
local ability = utils.get_ability_card_data(hero_key, ability_num)
if(ability == nil) then return "Ability Not Found" end
if(ability == nil) then return {} end -- return empty table, not string
local info_section = ability['Info'..info_section_num]
local info_section = ability['Info'..info_section_num]
Line 270: Line 277:


function get_info_desc(hero_key, ability_num, info_section_num)
function get_info_desc(hero_key, ability_num, info_section_num)
local ability = get_ability_card_data(hero_key, ability_num)
local ability = utils.get_ability_card_data(hero_key, 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]
local info_section = ability['Info'..info_section_num]
Line 286: Line 293:


function get_main_boxes(hero_key, ability_num, info_section_num)
function get_main_boxes(hero_key, ability_num, info_section_num)
local ability = get_ability_card_data(hero_key, ability_num)
local ability = utils.get_ability_card_data(hero_key, ability_num)
if(ability == nil) then return "Ability Not Found" end
if(ability == nil) then return "Ability Not Found" end
Line 296: Line 303:
local main = info_section.Main
local main = info_section.Main
if main == nil then
if main == nil then
return ''
return {}
end
end
local frame = mw.getCurrentFrame()
local frame = mw.getCurrentFrame()
local props = info_section.Main.Props
local props = {}
if props == nil then
return ''
-- Start with the standard Props array
if main.Props then
for _, prop in ipairs(main.Props) do
table.insert(props, prop)
end
end
end
local main_boxes = {}
local main_boxes = {}
for k, prop in pairs(props) do
for k, prop in ipairs(props) do -- use ipairs for ordered iteration
local value = prop.Value
local value = prop.Value
-- If it scales with melee damage, set the value using the hero's base melee to match in game visuals
-- If it scales with melee damage, set the value using the hero's base melee to match in game visuals
Line 316: Line 328:
local icon = get_icon(prop.Type)
local icon = get_icon(prop.Type)
local main_box = frame:expandTemplate{
title = "User:Saag/Sandbox/Ability_card_v2/Card/MainBox",
local main_box
args = {
if prop.StatusEffect then
title = prop.Title,
main_box = frame:expandTemplate{
key = prop.Key,
title = "User:Saag/Sandbox/Ability_card_v2/Card/StatusBox",
value = value,
args = {
icon = icon.img,
title = prop.Title,
icon_link = icon.link,
key = prop.Key,
icon_color = icon.color,
value = value,
icon_size = icon.size,
status_effect = prop.StatusEffect,
scale_value = prop.Scale and commonutils.round_to_sig_fig(prop.Scale.Value, 3),
icon = icon.img,
scale_type =  prop.Scale and prop.Scale.Type,
icon_link = icon.link,
hide = (value == nil or value == 0) and "true" or "false",
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,
-- allow nil value here as some status effects don't have a value but should not be hidden
hide = value == 0 and "true" or "false",
}
}
else
main_box = frame:expandTemplate{
title = "User:Saag/Sandbox/Ability_card_v2/Card/MainBox",
args = {
title = prop.Title,
key = prop.Key,
value = 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,
hide = (value == nil or value == 0) and "true" or "false",
}
}
}
}
end
table.insert(main_boxes, main_box)
table.insert(main_boxes, main_box)
end
end
Line 345: Line 379:


function get_alt_boxes(hero_key, ability_num, info_section_num)
function get_alt_boxes(hero_key, ability_num, info_section_num)
local ability = get_ability_card_data(hero_key, ability_num)
local ability = utils.get_ability_card_data(hero_key, ability_num)
if(ability == nil) then return "Ability Not Found" end
if(ability == nil) then return "Ability Not Found" end
Line 390: Line 424:
local UPGRADE_COST_MAP = {1, 2, 5}
local UPGRADE_COST_MAP = {1, 2, 5}
function get_upgrade_boxes(hero_key, ability_num)
function get_upgrade_boxes(hero_key, ability_num)
local ability = get_ability_card_data(hero_key, ability_num)
local ability = utils.get_ability_card_data(hero_key, ability_num)
if(ability == nil) then return "Ability Not Found" end
if(ability == nil) then return "Ability Not Found" end
local frame = mw.getCurrentFrame()
local frame = mw.getCurrentFrame()


local props = ability.Upgrades
local upgrades = ability.Upgrades
local upgrade_boxes = {}
local upgrade_boxes = {}
for k, prop in pairs(props) do
for k, upgrade in pairs(upgrades) do
local description = lang.get_string(prop.DescKey)
local description = lang.get_string(upgrade.DescKey)
 
-- bypass some keys if they are mistakenly left in game files
local IGNORE_DESC_KEYS = {'citadel_ability_hornet_snipe_t3_desc', 'ability_fencer_ultimate_t3_desc'}
-- Generate a description if there is no localized string
-- Generate a description if there is no localized string
if (description == nil or description == '') then
if (description == nil or description == '' or commonutils.contains(IGNORE_DESC_KEYS, upgrade.DescKey)) then
description = create_description(prop, frame)
description = create_description(upgrade, frame)
else
-- Replace embedded value placeholders with just the base value
-- Pattern: {'Value': X, 'Scale': {...}} -> X
description = description:gsub("{'Value':%s*([%d%.%-]+),%s*'Scale':%s*{[^}]+}}", function(value)
return commonutils.round_to_sig_fig(tonumber(value), 3)
end)
-- Pattern: {'Value': X} -> X
description = description:gsub("{'Value':%s*([%d%.%-]+)}", function(value)
return commonutils.round_to_sig_fig(tonumber(value), 3)
end)
end
end
Line 419: Line 466:
title = "User:Saag/Sandbox/Ability_card_v2/Card/UpgradeBox",
title = "User:Saag/Sandbox/Ability_card_v2/Card/UpgradeBox",
args = {
args = {
  cost = UPGRADE_COST_MAP[k],
index = k,
  description = frame:preprocess(description),
cost = UPGRADE_COST_MAP[k],
  scale_value = prop.Scale and commonutils.round_to_sig_fig(prop.Scale.Value, 3),
description = frame:preprocess(description),
  scale_type =  prop.Scale and prop.Scale.Type,
scale_value = upgrade.Scale and commonutils.round_to_sig_fig(upgrade.Scale.Value, 3),
  fontsize = fontsize
scale_type =  upgrade.Scale and upgrade.Scale.Type,
fontsize = fontsize
}
}
}
}
Line 431: Line 479:
return upgrade_boxes
return upgrade_boxes
end
end


function create_description(prop, frame)
function create_description(prop, frame)
Line 438: Line 487:


     for k, v in pairs(prop) do
     for k, v in pairs(prop) do
    
     local value
         if type(v) ~= 'table' then
         if type(v) == 'table' then
            local formatted_value = utils.format_value_with_prepost(k, v, frame)
        value = v.Value
            local attr_name = lang.get_string(k..'_label')
        else
            local key = formatted_value .. '|' .. attr_name  -- Unique identifier
        value = v
 
    end
            -- Skip if this combination has already been added
   
            if not seen[key] then
        local formatted_value = utils.format_value_with_prepost(k, value, frame)
            -- Add line break if this is not the first item
        local attr_name = lang.get_string(k..'_label')
                if not first then
        local key = formatted_value .. '|' .. attr_name  -- Unique identifier
                  description = description .. '<br>'
                end
-- skip DescKey for the edge case where we are generating description instead of using localization files
 
if k ~= 'DescKey' then
            description = description .. string.format('%s %s', formatted_value, attr_name)
        -- Skip if this combination has already been added
            first = false
        if not seen[key] then
            seen[key] = true  -- Mark this combination as added
        -- Add line break if this is not the first item
           
            if not first then
            end
              description = description .. '<br>'
            end
        end
        description = description .. string.format('%s %s', formatted_value, attr_name)
        first = false
        seen[key] = true  -- Mark this combination as added
         end
         end
     end
     end
Line 480: Line 535:
size = mappedAttr.size
size = mappedAttr.size
color = mappedAttr.color or color
color = mappedAttr.color or color
end
end
return {img=img, link=link, color=color, size=size}
return {img=img, link=link, color=color, size=size}
Line 538: Line 593:
end
end
local ability = get_ability_card_data(hero_key, ability_num)
local ability = utils.get_ability_card_data(hero_key, ability_num)
if(ability == nil) then  
if(ability == nil) then  
return 'Ability data not found for hero ' ..hero_key.. ' and num ' .. ability_num
return 'Ability data not found for hero ' ..hero_key.. ' and num ' .. ability_num