|
|
| (37 intermediate revisions by 4 users not shown) |
| Line 1: |
Line 1: |
| local p = {};
| | This page is protected from editing. Please see [[Deadlock:User pages]]. |
| local data = mw.loadJsonData("Data:ItemData.json")
| |
| | |
| -- Normalize strings for comparison
| |
| local function normalize(str)
| |
| return mw.ustring.lower(mw.text.trim(str or ""))
| |
| end
| |
| | |
| -- Clean and parse numbers
| |
| local function cleanNumber(num)
| |
| if type(num) == "number" then return num end
| |
| if not num then return 0 end
| |
| return tonumber(tostring(num):gsub("[^%d.-]", "")) or 0
| |
| end
| |
| | |
| -- Safe item access
| |
| local function get_json_item(name)
| |
| if not name or type(name) ~= 'string' then return nil end
| |
| local targetName = normalize(name)
| |
|
| |
| for _, item in pairs(data) do
| |
| if item.Name and normalize(item.Name) == targetName then
| |
| if item.IsDisabled ~= true then
| |
| return item
| |
| end
| |
| end
| |
| end
| |
| return nil
| |
| end
| |
| | |
| -- Format numbers with localization
| |
| local lang = mw.language.getContentLanguage()
| |
| local function formatNum(amount)
| |
| return lang:formatNum(cleanNumber(amount))
| |
| end
| |
| | |
| -- Main function with improved error handling
| |
| p.generate_infobox = function(frame)
| |
| local item_name = frame.args[1]
| |
| if not item_name or item_name == "" then
| |
| return frame:preprocess("{{Error|No item name specified}}")
| |
| end
| |
|
| |
| local item = get_json_item(item_name)
| |
| if not item then
| |
| return frame:preprocess("{{Error|Item not found: " .. item_name .. "}}")
| |
| end
| |
|
| |
| -- Determine item type with validation
| |
| local item_type = "Weapon" -- default
| |
| local valid_types = {
| |
| Weapon = {bg = "#80550F", header = "#C97A03", border = "#C97A03"},
| |
| Vitality = {bg = "#4D7214", header = "#659818", border = "#659818"},
| |
| Spirit = {bg = "#623585", header = "#8B56B4", border = "#8B56B4"}
| |
| }
| |
|
| |
| if item.Slot then
| |
| local slot = normalize(item.Slot)
| |
| if slot == "armor" then
| |
| item_type = "Vitality"
| |
| elseif slot == "tech" then
| |
| item_type = "Spirit"
| |
| end
| |
| end
| |
|
| |
| local colors = valid_types[item_type] or valid_types.Weapon
| |
| | |
| -- Process components
| |
| local components = {}
| |
| if item.Components and type(item.Components) == "table" then
| |
| for _, comp_id in ipairs(item.Components) do
| |
| local component = data[comp_id]
| |
| if component and component.Name then
| |
| table.insert(components, component.Name)
| |
| end
| |
| end
| |
| end
| |
| | |
| -- Process stats dynamically
| |
| local stats = {}
| |
| local stat_formats = {
| |
| TechPower = {icon = "Spirit icon.png", suffix = "Spirit Power"},
| |
| WeaponPower = {icon = "Weapon Icon.png", suffix = "Weapon Damage"},
| |
| TechResist = {icon = "Spirit Resist Icon.png", suffix = "Tech Resist"},
| |
| BulletResist = {icon = "Bullet Resist Icon.png", suffix = "Bullet Resist"},
| |
| AbilityCooldown = {icon = "Cooldown Icon.png", suffix = "s Cooldown"},
| |
| AbilityCastRange = {suffix = "m Cast Range"},
| |
| AbilityUnitTargetLimit = {prefix = "Targets: "}
| |
| }
| |
| | |
| for stat, format in pairs(stat_formats) do
| |
| local value = item[stat]
| |
| if value and value ~= "0" and value ~= 0 then
| |
| local text = "• "
| |
| if format.prefix then text = text .. format.prefix end
| |
| text = text .. tostring(value)
| |
| if format.icon then text = text .. " [[File:" .. format.icon .. "|20px]]" end
| |
| if format.suffix then text = text .. " " .. format.suffix end
| |
| table.insert(stats, text)
| |
| end
| |
| end
| |
| | |
| -- Calculate shop bonus
| |
| local shop_bonus = "+0"
| |
| local tier = cleanNumber(item.Tier or 1)
| |
| if item_type == "Weapon" then
| |
| shop_bonus = string.format("+%d%% Weapon Damage", 6 + (tier-1)*4)
| |
| elseif item_type == "Vitality" then
| |
| shop_bonus = string.format("+%d%% Base Health", 11 + (tier-1)*3)
| |
| else -- Spirit
| |
| shop_bonus = string.format("+%d Spirit Power", 4 * tier)
| |
| end
| |
| | |
| -- Build infobox parts
| |
| local parts = {
| |
| -- Header
| |
| string.format(
| |
| '<div class="infobox_item" style="float:right; display:inline-block; vertical-align:top;">\n' ..
| |
| '{| class="wikitable" style="text-align:left; border-collapse:collapse; width:312px; max-width:100%%; color: #FFEFD7; padding:12px; font-family:\'Retail Demo Regular\',serif; background-color: %s"\n' ..
| |
| '! colspan="4" style="width:280px; padding:5px 12px; text-align:center; font-size:24px; font-family:\'Retail Demo Bold\',serif; background-color: %s" | %s',
| |
| colors.bg, colors.header, item.Name
| |
| ),
| |
|
| |
| -- Image
| |
| string.format(
| |
| '|-\n| colspan=4 class="infobox-image" style="padding:5px; text-align:center;" | [[File:%s.png|144px]]',
| |
| item.Name
| |
| ),
| |
|
| |
| -- Cost
| |
| string.format(
| |
| '|-\n| colspan=2 style="text-align:right; width:50%%; border-right:1px solid %s; padding-right:0.5em;" | Cost\n' ..
| |
| '| colspan=2 style="padding-left:0.5em;" | {{Souls|%s}}',
| |
| colors.border, formatNum(item.Cost)
| |
| ),
| |
|
| |
| -- Tier
| |
| string.format(
| |
| '|-\n| colspan=2 style="text-align:right; width:50%%; border-right:1px solid %s; padding-right:0.5em;" | Tier\n' ..
| |
| '| colspan=2 style="padding-left:0.5em;" | %s',
| |
| colors.border, tier
| |
| ),
| |
|
| |
| -- Shop Bonus
| |
| string.format(
| |
| '|-\n| colspan=2 style="text-align:right; width:50%%; border-right:1px solid %s; padding-right:0.5em;" | Shop Bonus\n' ..
| |
| '| colspan=2 style="padding-left:0.5em;" | %s',
| |
| colors.border, shop_bonus
| |
| )
| |
| }
| |
| | |
| -- Add components if they exist
| |
| if #components > 0 then
| |
| table.insert(parts,
| |
| string.format(
| |
| '|-\n! colspan="4" style="text-align:left; padding:0 12px; font-weight:bold; font-size:16px; font-family:\'Retail Demo Bold\',serif; background-color: %s; color: %s" | COMPONENTS:<br/>%s',
| |
| (item_type == "Weapon" and "#9E630C" or item_type == "Vitality" and "#203500" or "#372248"),
| |
| (item_type == "Weapon" and "#DCCFC6" or item_type == "Vitality" and "#C7C9C6" or "#C9C7CB"),
| |
| table.concat(components, "<br/>{{ItemIcon|", "{{ItemIcon|", "}}")
| |
| )
| |
| )
| |
| end
| |
| | |
| -- Add description
| |
| table.insert(parts,
| |
| string.format(
| |
| '|-\n| colspan="4" style="text-align:left; padding:0 12px; color:#FFEFD7; background-color: %s" | %s',
| |
| colors.bg, item.Description or ""
| |
| )
| |
| )
| |
| | |
| -- Add stats if they exist
| |
| if #stats > 0 then
| |
| table.insert(parts,
| |
| '|-\n| ' .. table.concat(stats, "\n|-\n| ")
| |
| )
| |
| end
| |
| | |
| -- Close table
| |
| table.insert(parts, "|}\n</div>")
| |
| | |
| -- Process and return
| |
| return frame:preprocess(table.concat(parts, "\n"))
| |
| end
| |
| | |
| return p
| |