Module:Sandbox: Difference between revisionsGive feedback
No edit summary |
No edit summary |
||
| Line 2: | Line 2: | ||
local data = mw.loadJsonData("Data:ItemData.json") | local data = mw.loadJsonData("Data:ItemData.json") | ||
-- Utility function to get item by name | -- Utility function to get item by name (case-insensitive) | ||
local function get_json_item(name) | local function get_json_item(name) | ||
if not name or type(name) ~= 'string' then return nil end | |||
local lowerName = mw.ustring.lower(name) | |||
for _, v in pairs(data) do | for _, v in pairs(data) do | ||
if v["Name"] == | if v["Name"] and mw.ustring.lower(v["Name"]) == lowerName then | ||
if v["IsDisabled"] == false or v["IsDisabled"] == nil then | |||
return v | |||
end | |||
end | end | ||
end | end | ||
| Line 12: | Line 17: | ||
end | end | ||
-- | -- Safe number formatting with error handling | ||
local lang = mw.language.getContentLanguage() | local lang = mw.language.getContentLanguage() | ||
local function formatNum(amount) | local function formatNum(amount) | ||
return lang:formatNum | if amount == nil then return "0" end | ||
if type(amount) == 'string' then | |||
amount = tonumber(amount) or 0 | |||
end | |||
return lang:formatNum(amount) | |||
end | end | ||
| Line 21: | Line 30: | ||
p.generate_infobox = function(frame) | p.generate_infobox = function(frame) | ||
local item_name = frame.args[1] | local item_name = frame.args[1] | ||
if not item_name or item_name == '' then | |||
return "<span class='error'>No item name specified</span>" | |||
end | |||
local item = get_json_item(item_name) | local item = get_json_item(item_name) | ||
if not item then return "<span class='error'>Item not found: " .. item_name .. "</span>" end | if not item then | ||
return "<span class='error'>Item not found: " .. item_name .. "</span>" | |||
end | |||
-- Determine item type | -- Determine item type with fallback | ||
local item_type = "Weapon" | local item_type = "Weapon" -- default | ||
if item.Slot == "Armor" then | if item.Slot then | ||
if item.Slot == "Armor" then | |||
item_type = "Vitality" | |||
elseif item.Slot == "Tech" then | |||
item_type = "Spirit" | |||
end | |||
end | end | ||
-- Generate stats section with all possible stats | |||
local stats = {} | |||
local stat_order = { | |||
'TechPower', 'WeaponPower', 'TechResist', 'BulletResist', | |||
'AbilityCooldown', 'AbilityCastRange', 'AbilityUnitTargetLimit' | |||
} | |||
for _, stat in ipairs(stat_order) do | |||
if item[stat] and item[stat] ~= "0" and item[stat] ~= 0 then | |||
local stat_text = "• " | |||
if stat == 'TechPower' then | |||
stat_text = stat_text .. item[stat] .. " [[File:Spirit icon.png|20px]] Spirit Power" | |||
elseif stat == 'WeaponPower' then | |||
stat_text = stat_text .. item[stat] .. " [[File:Weapon Icon.png|20px]] Weapon Damage" | |||
elseif stat == 'TechResist' then | |||
stat_text = stat_text .. item[stat] .. " [[File:Spirit Resist Icon.png|20px]] Tech Resist" | |||
elseif stat == 'BulletResist' then | |||
stat_text = stat_text .. item[stat] .. " [[File:Bullet Resist Icon.png|20px]] Bullet Resist" | |||
elseif stat == 'AbilityCooldown' then | |||
stat_text = stat_text .. "[[File:Cooldown Icon.png|20px]] " .. item[stat] .. "s Cooldown" | |||
elseif stat == 'AbilityCastRange' then | |||
stat_text = stat_text .. item[stat] .. "m Cast Range" | |||
elseif stat == 'AbilityUnitTargetLimit' then | |||
stat_text = stat_text .. "Targets: " .. item[stat] | |||
end | |||
table.insert(stats, stat_text) | |||
end | |||
end | end | ||
local stats_text = table.concat(stats, "\n|-\n| ") | local stats_text = table.concat(stats, "\n|-\n| ") | ||
-- Generate components section if exists | -- Generate components section if exists | ||
local components_text = "" | local components_text = "" | ||
if item.Components then | if item.Components and #item.Components > 0 then | ||
local | local component_names = {} | ||
if | for _, comp_id in ipairs(item.Components) do | ||
components_text = [=[ | local component = data[comp_id] | ||
! colspan="4" style="text-align:left; padding:0 12px; font-weight:bold; font-size:16px; font-family:'Retail Demo Bold',serif; ]=] | if component and component.Name then | ||
table.insert(component_names, component.Name) | |||
end | |||
end | |||
if #component_names > 0 then | |||
components_text = string.format( | |||
[=[! colspan="4" style="text-align:left; padding:0 12px; font-weight:bold; font-size:16px; font-family:'Retail Demo Bold',serif; %s">COMPONENTS:<br/>]=], | |||
(item_type == "Weapon" and "background-color: #9E630C; color: #DCCFC6;" or | (item_type == "Weapon" and "background-color: #9E630C; color: #DCCFC6;" or | ||
item_type == "Vitality" and "background-color: #203500; color: #C7C9C6;" or | item_type == "Vitality" and "background-color: #203500; color: #C7C9C6;" or | ||
"background-color: #372248; color: #C9C7CB;") .. | "background-color: #372248; color: #C9C7CB;") | ||
) | |||
for i, name in ipairs(component_names) do | |||
if i > 1 then components_text = components_text .. "<br/>" end | |||
components_text = components_text .. "{{ItemIcon|" .. name .. "}}" | |||
end | |||
end | |||
end | |||
-- Calculate shop bonus dynamically | |||
local shop_bonus = "+0" | |||
if item.Tier then | |||
local tier = tonumber(item.Tier) or 1 | |||
if item_type == "Weapon" then | |||
shop_bonus = "+" .. (6 + (tier-1)*4) .. "% Weapon Damage" | |||
elseif item_type == "Vitality" then | |||
shop_bonus = "+" .. (11 + (tier-1)*3) .. "% Base Health" | |||
else -- Spirit | |||
shop_bonus = "+" .. (4 * tier) .. " Spirit Power" | |||
end | end | ||
end | end | ||
-- Generate the full infobox | -- Generate the full infobox | ||
local infobox = [=[ | local infobox = string.format([=[ | ||
<div class="infobox_item" style="float:right; display:inline-block; vertical-align:top;"> | <div class="infobox_item" style="float:right; display:inline-block; vertical-align:top;"> | ||
{| style="text-align:left; border-collapse:collapse; width:312px; max-width:100%; height:30px; color: #FFEFD7; padding:12px; font-family:'Retail Demo Regular',serif; | {| style="text-align:left; border-collapse:collapse; width:312px; max-width:100%%; height:30px; color: #FFEFD7; padding:12px; font-family:'Retail Demo Regular',serif; %s" | ||
! colspan="4"; style="width:280px; padding:5px 12px; text-align:center; font-size:24px; font-family:'Retail Demo Bold',serif; %s">%s | |||
! colspan="4"; style="width:280px; padding:5px 12px; text-align:center; font-size:24px; font-family:'Retail Demo Bold',serif; | |||
|- | |- | ||
| colspan=4 class="infobox-image" style="padding:5px; text-align:center;">[[File: | | colspan=4 class="infobox-image" style="padding:5px; text-align:center;">[[File:%s.png|144px]] | ||
|- | |- | ||
| colspan=2 style="text-align:right; width:50%; | | colspan=2 style="text-align:right; width:50%%; %s padding-right:0.5em;">Cost | ||
| colspan=2 style="padding-left:0.5em;">{{Souls|%s}} | |||
| colspan=2 style="padding-left:0.5em;">{{Souls| | |||
|- | |- | ||
| colspan=2 style="text-align:right; width:50%; | | colspan=2 style="text-align:right; width:50%%; %s padding-right:0.5em;">Tier | ||
| colspan=2 style="padding-left:0.5em;">%s | |||
| colspan=2 style="padding-left:0.5em;"> | |||
|- | |- | ||
| colspan=2 style="text-align:right; width:50%; | | colspan=2 style="text-align:right; width:50%%; %s padding-right:0.5em;">Shop Bonus | ||
| colspan=2 style="padding-left:0.5em;">%s | |||
| colspan=2 style="padding-left:0.5em;"> | |||
|- | |- | ||
%s | |||
|- | |- | ||
| colspan="4" style="text-align:left; padding:0 12px; color:#FFEFD7; | | colspan="4" style="text-align:left; padding:0 12px; color:#FFEFD7; %s">%s | ||
|- | |- | ||
| | | %s | ||
|} | |} | ||
</div>]=] | </div>]=], | ||
-- Background color | |||
(item_type == "Weapon" and "background-color: #80550F;" or | |||
item_type == "Vitality" and "background-color: #4D7214;" or | |||
"background-color: #623585;"), | |||
-- Header color | |||
(item_type == "Weapon" and "background-color: #C97A03;" or | |||
item_type == "Vitality" and "background-color: #659818;" or | |||
"background-color: #8B56B4;"), | |||
-- Item name | |||
item.Name, | |||
-- Image | |||
item.Name, | |||
-- Cost border | |||
(item_type == "Weapon" and "border-right:1px solid #C97A03;" or | |||
item_type == "Vitality" and "border-right:1px solid #659818;" or | |||
"border-right:1px solid #8B56B4;"), | |||
-- Cost value | |||
formatNum(item.Cost or 0), | |||
-- Tier border (same as cost) | |||
(item_type == "Weapon" and "border-right:1px solid #C97A03;" or | |||
item_type == "Vitality" and "border-right:1px solid #659818;" or | |||
"border-right:1px solid #8B56B4;"), | |||
-- Tier value | |||
item.Tier or "1", | |||
-- Shop bonus border (same as cost) | |||
(item_type == "Weapon" and "border-right:1px solid #C97A03;" or | |||
item_type == "Vitality" and "border-right:1px solid #659818;" or | |||
"border-right:1px solid #8B56B4;"), | |||
-- Shop bonus | |||
shop_bonus, | |||
-- Components | |||
components_text, | |||
-- Description background | |||
(item_type == "Weapon" and "background-color: #80550F;" or | |||
item_type == "Vitality" and "background-color: #4D7214;" or | |||
"background-color: #623585;"), | |||
-- Description text | |||
item.Description or "", | |||
-- Stats | |||
stats_text | |||
) | |||
return infobox | return infobox | ||