Module:Sandbox: Difference between revisionsGive feedback
Jump to navigation
Jump to search
No edit summary |
No edit summary |
||
| Line 40: | Line 40: | ||
end | end | ||
-- Main function with | -- Find all recipes where this item is used as a component | ||
local function find_recipes(item_name) | |||
local recipes = {} | |||
for _, item in pairs(data) do | |||
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 == item_name then | |||
table.insert(recipes, item.Name) | |||
break -- Only need to find one match per item | |||
end | |||
end | |||
end | |||
end | |||
return recipes | |||
end | |||
-- Main function with complete item relationship handling | |||
p.generate_infobox = function(frame) | p.generate_infobox = function(frame) | ||
local item_name = frame.args[1] | local item_name = frame.args[1] | ||
| Line 65: | Line 82: | ||
-- Color definitions | -- Color definitions | ||
local colors = { | local colors = { | ||
Weapon = {bg = "#80550F", header = "#C97A03", border = "#C97A03"}, | Weapon = { | ||
Vitality = {bg = "#4D7214", header = "#659818", border = "#659818"}, | bg = "#80550F", header = "#C97A03", border = "#C97A03", | ||
Spirit = {bg = "#623585", header = "#8B56B4", border = "#8B56B4"} | components = {bg = "#9E630C", text = "#DCCFC6"}, | ||
recipes = {bg = "#704A0C", text = "#D1CBC6"} | |||
}, | |||
Vitality = { | |||
bg = "#4D7214", header = "#659818", border = "#659818", | |||
components = {bg = "#203500", text = "#C7C9C6"}, | |||
recipes = {bg = "#436310", text = "#CACFC7"} | |||
}, | |||
Spirit = { | |||
bg = "#623585", header = "#8B56B4", border = "#8B56B4", | |||
components = {bg = "#372248", text = "#C9C7CB"}, | |||
recipes = {bg = "#552D74", text = "#CCC8D2"} | |||
} | |||
} | } | ||
local color = colors[item_type] or colors.Weapon | local color = colors[item_type] or colors.Weapon | ||
-- Process components | -- Process components (what this item is made of) | ||
local component_text = "" | local component_text = "" | ||
if item.Components and type(item.Components) == "table" then | if item.Components and type(item.Components) == "table" and #item.Components > 0 then | ||
local valid_components = {} | local valid_components = {} | ||
for _, comp_id in ipairs(item.Components) do | for _, comp_id in ipairs(item.Components) do | ||
| Line 85: | Line 114: | ||
component_text = string.format( | component_text = 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', | '|-\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', | ||
color.components.bg, color.components.text, | |||
table.concat(valid_components, "<br/>") | table.concat(valid_components, "<br/>") | ||
) | ) | ||
| Line 92: | Line 120: | ||
end | end | ||
-- Process stats - | -- Process recipes (what items this is used in) | ||
local recipe_text = "" | |||
local recipes = find_recipes(item.Name) | |||
if #recipes > 0 then | |||
local recipe_links = {} | |||
for _, recipe_name in ipairs(recipes) do | |||
table.insert(recipe_links, "{{ItemIcon|" .. recipe_name .. "}}") | |||
end | |||
recipe_text = 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" | USED IN:<br/>%s', | |||
color.recipes.bg, color.recipes.text, | |||
table.concat(recipe_links, "<br/>") | |||
) | |||
end | |||
-- Process stats - comprehensive stat handling | |||
local stats = {} | local stats = {} | ||
local stat_config = { | local stat_config = { | ||
| Line 106: | Line 150: | ||
BonusAbilityCharges = {prefix = "+", suffix = " Bonus Charges"}, | BonusAbilityCharges = {prefix = "+", suffix = " Bonus Charges"}, | ||
CooldownReductionOnChargedAbilities = {suffix = "% Charged Ability Cooldown Reduction"}, | CooldownReductionOnChargedAbilities = {suffix = "% Charged Ability Cooldown Reduction"}, | ||
BaseAttackDamagePercent = {suffix = "% Base Attack Damage"} | BaseAttackDamagePercent = {suffix = "% Base Attack Damage"}, | ||
-- Add more stats as needed | |||
} | } | ||
| Line 170: | Line 215: | ||
} | } | ||
-- Add components if | -- Add components section if exists | ||
if component_text ~= "" then | if component_text ~= "" then | ||
table.insert(parts, component_text) | table.insert(parts, component_text) | ||
end | |||
-- Add recipes section if exists | |||
if recipe_text ~= "" then | |||
table.insert(parts, recipe_text) | |||
end | end | ||
-- Add description if it exists | -- Add description if it exists | ||
if item.Description then | if item.Description and item.Description ~= "" then | ||
table.insert(parts, | table.insert(parts, | ||
string.format( | string.format( | ||
Revision as of 18:36, 1 April 2025
Documentation for this module may be created at Module:Sandbox/doc
local p = {};
local data = mw.loadJsonData("Data:ItemData.json")
-- Utility function to safely convert to number
local function toNumber(value)
if type(value) == "number" then
return value
elseif type(value) == "string" then
-- Remove any formatting (commas, etc.) before conversion
local cleaned = value:gsub("[^%d.-]", "")
return tonumber(cleaned) or 0
end
return 0
end
-- Normalize strings for comparison
local function normalize(str)
return mw.ustring.lower(mw.text.trim(str or ""))
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(toNumber(amount))
end
-- Find all recipes where this item is used as a component
local function find_recipes(item_name)
local recipes = {}
for _, item in pairs(data) do
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 == item_name then
table.insert(recipes, item.Name)
break -- Only need to find one match per item
end
end
end
end
return recipes
end
-- Main function with complete item relationship 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
local item_type = "Weapon" -- default
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
-- Color definitions
local colors = {
Weapon = {
bg = "#80550F", header = "#C97A03", border = "#C97A03",
components = {bg = "#9E630C", text = "#DCCFC6"},
recipes = {bg = "#704A0C", text = "#D1CBC6"}
},
Vitality = {
bg = "#4D7214", header = "#659818", border = "#659818",
components = {bg = "#203500", text = "#C7C9C6"},
recipes = {bg = "#436310", text = "#CACFC7"}
},
Spirit = {
bg = "#623585", header = "#8B56B4", border = "#8B56B4",
components = {bg = "#372248", text = "#C9C7CB"},
recipes = {bg = "#552D74", text = "#CCC8D2"}
}
}
local color = colors[item_type] or colors.Weapon
-- Process components (what this item is made of)
local component_text = ""
if item.Components and type(item.Components) == "table" and #item.Components > 0 then
local valid_components = {}
for _, comp_id in ipairs(item.Components) do
local component = data[comp_id]
if component and component.Name then
table.insert(valid_components, "{{ItemIcon|" .. component.Name .. "}}")
end
end
if #valid_components > 0 then
component_text = 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',
color.components.bg, color.components.text,
table.concat(valid_components, "<br/>")
)
end
end
-- Process recipes (what items this is used in)
local recipe_text = ""
local recipes = find_recipes(item.Name)
if #recipes > 0 then
local recipe_links = {}
for _, recipe_name in ipairs(recipes) do
table.insert(recipe_links, "{{ItemIcon|" .. recipe_name .. "}}")
end
recipe_text = 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" | USED IN:<br/>%s',
color.recipes.bg, color.recipes.text,
table.concat(recipe_links, "<br/>")
)
end
-- Process stats - comprehensive stat handling
local stats = {}
local stat_config = {
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: "},
-- Rapid Recharge specific stats
CooldownBetweenChargeReduction = {suffix = "% Charge Cooldown Reduction"},
BonusAbilityCharges = {prefix = "+", suffix = " Bonus Charges"},
CooldownReductionOnChargedAbilities = {suffix = "% Charged Ability Cooldown Reduction"},
BaseAttackDamagePercent = {suffix = "% Base Attack Damage"},
-- Add more stats as needed
}
for stat, config in pairs(stat_config) do
local value = item[stat]
if value and value ~= "0" and value ~= 0 then
local text = "• "
if config.prefix then text = text .. config.prefix end
text = text .. tostring(value)
if config.icon then text = text .. " [[File:" .. config.icon .. "|20px]]" end
if config.suffix then text = text .. config.suffix end
table.insert(stats, text)
end
end
-- Calculate shop bonus
local tier = toNumber(item.Tier or 1)
local shop_bonus = "+0"
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',
color.bg, color.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}}',
color.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',
color.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',
color.border, shop_bonus
)
}
-- Add components section if exists
if component_text ~= "" then
table.insert(parts, component_text)
end
-- Add recipes section if exists
if recipe_text ~= "" then
table.insert(parts, recipe_text)
end
-- Add description if it exists
if item.Description and item.Description ~= "" then
table.insert(parts,
string.format(
'|-\n| colspan="4" style="text-align:left; padding:0 12px; color:#FFEFD7; background-color: %s" | %s',
color.bg, item.Description
)
)
end
-- 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