Module:ItemCategoryTable
Documentation for this module may be created at Module:ItemCategoryTable/doc
local p = {}
-- Parent categories and their child types
local parentCategories = {
["Accessories"] = {"Ring", "Necklace", "Gloves"},
["Weapons"] = {"Sword", "Large Sword", "Dagger", "Knife", "Axe", "Large Axe", "Bow", "Staff", "Orb"},
["Shields"] = {"Small Shield", "Large Shield"},
["Armor"] = {"Heavy Chest", "Heavy Legs", "Heavy Helmet", "Heavy Boots", "Light Chest", "Light Legs", "Light Helmet", "Light Boots", "Light Mask", "Light Neck"},
["Heavy Armor"] = {"Heavy Chest", "Heavy Legs", "Heavy Helmet", "Heavy Boots"},
["Light Armor"] = {"Light Chest", "Light Legs", "Light Helmet", "Light Boots", "Light Mask", "Light Neck"},
["Food"] = {"Cooked Food", "Edible Food", "Raw Food", "Special Food"},
["Consumables"] = {"Potions", "Drinks", "Cooked Food", "Edible Food", "Raw Food", "Special Food"},
["Materials"] = {"Book Products", "Cloth Products", "Cooking Items", "Desert Products", "Forge Products", "Grave Products", "Holy Products", "Monster Products", "North Products", "Plains Products", "Swamp Products"},
}
-- Query items by type from Cargo
local function getItemsByType(itemType)
local tables = 'Items'
local fields = 'name,sprite,type,weight,damage,armor,defense,health,mana,ability,magic,rng,move_speed,attack_speed,health_regen,mana_regen,container,size,rarity'
local args = {
where = 'type LIKE "%' .. itemType .. '%"',
orderBy = 'name',
limit = 500
}
return mw.ext.cargo.query(tables, fields, args)
end
-- Query items by multiple types
local function getItemsByTypes(types)
local tables = 'Items'
local fields = 'name,sprite,type,weight,damage,armor,defense,health,mana,ability,magic,rng,move_speed,attack_speed,health_regen,mana_regen,container,size,rarity'
-- Build OR conditions for each type
local conditions = {}
for _, t in ipairs(types) do
table.insert(conditions, 'type LIKE "%' .. t .. '%"')
end
local args = {
where = table.concat(conditions, ' OR '),
orderBy = 'name',
limit = 500
}
return mw.ext.cargo.query(tables, fields, args)
end
-- Get the singular type name from a plural category name
local function singularize(plural)
local mapping = {
["Rings"] = "Ring",
["Necklaces"] = "Necklace",
["Staves"] = "Staff",
["Knives"] = "Knife",
["Axes"] = "Axe",
["Large Axes"] = "Large Axe",
["Swords"] = "Sword",
["Large Swords"] = "Large Sword",
["Regular Swords"] = "Regular Sword",
["Daggers"] = "Dagger",
["Bows"] = "Bow",
["Orbs"] = "Orb",
["Small Shields"] = "Small Shield",
["Large Shields"] = "Large Shield",
["Gloves"] = "Gloves",
["Containers"] = "Container",
["Tools"] = "Tools",
["Heavy Helmets"] = "Heavy Helmet",
["Light Helmets"] = "Light Helmet",
["Light Masks"] = "Light Mask",
["Heavy Boots"] = "Heavy Boots",
["Light Boots"] = "Light Boots",
["Heavy Legs"] = "Heavy Legs",
["Light Legs"] = "Light Legs",
["Heavy Chest Armor"] = "Heavy Chest",
["Light Chest Armor"] = "Light Chest",
["Light Neck Armor"] = "Light Neck",
["Potions"] = "Potions",
["Drinks"] = "Drinks",
["Arrows"] = "Arrows",
["Conjured Arrows"] = "Conjured Arrows",
["Books"] = "Book",
["Cooked Food"] = "Cooked Food",
["Edible Food"] = "Edible Food",
["Raw Food"] = "Raw Food",
["Special Food"] = "Special Food",
["Light Sources"] = "Light Sources",
["Flowers"] = "Flowers",
["Currency"] = "Currency",
["Book Products"] = "Book Products",
["Cloth Products"] = "Cloth Products",
["Cooking Items"] = "Cooking Items",
["Desert Products"] = "Desert Products",
["Forge Products"] = "Forge Products",
["Grave Products"] = "Grave Products",
["Holy Products"] = "Holy Products",
["Monster Products"] = "Monster Products",
["North Products"] = "North Products",
["Plains Products"] = "Plains Products",
["Swamp Products"] = "Swamp Products",
}
return mapping[plural] or plural:gsub("s$", "")
end
-- Get the plural/category name from a type
local function pluralize(singular)
local mapping = {
["Ring"] = "Rings",
["Necklace"] = "Necklaces",
["Staff"] = "Staves",
["Knife"] = "Knives",
["Axe"] = "Axes",
["Large Axe"] = "Large Axes",
["Sword"] = "Swords",
["Large Sword"] = "Large Swords",
["Dagger"] = "Daggers",
["Bow"] = "Bows",
["Orb"] = "Orbs",
["Small Shield"] = "Small Shields",
["Large Shield"] = "Large Shields",
["Gloves"] = "Gloves",
["Container"] = "Containers",
["Heavy Helmet"] = "Heavy Helmets",
["Light Helmet"] = "Light Helmets",
["Light Mask"] = "Light Masks",
["Heavy Boots"] = "Heavy Boots",
["Light Boots"] = "Light Boots",
["Heavy Legs"] = "Heavy Legs",
["Light Legs"] = "Light Legs",
["Heavy Chest"] = "Heavy Chest Armor",
["Light Chest"] = "Light Chest Armor",
["Light Neck"] = "Light Neck Armor",
}
return mapping[singular] or singular
end
-- Get numeric value from stat (0 if empty)
local function statNum(value)
if value and value ~= "" then
return tonumber(value) or 0
end
return 0
end
-- Format stat value (return 0 if empty)
local function stat(value)
if value and value ~= "" then
return value
end
return "0"
end
-- Calculate total stat power for an item
local function calcPower(item)
return statNum(item.damage) + statNum(item.armor) + statNum(item.defense) +
statNum(item.health) + statNum(item.mana) + statNum(item.ability) +
statNum(item.magic) + statNum(item.rng) + statNum(item.move_speed) +
statNum(item.attack_speed)
end
function p.render(frame)
local args = frame:getParent().args
local categoryName = args[1] or args.category or mw.title.getCurrentTitle().text:gsub("^Category:", "")
-- Check if this is a parent category
local isParent = parentCategories[categoryName] ~= nil
local items
if isParent then
items = getItemsByTypes(parentCategories[categoryName])
else
local itemType = singularize(categoryName)
items = getItemsByType(itemType)
end
if not items or #items == 0 then
return '<p class="mw-empty">No items found.</p>'
end
-- Calculate power for each item and sort by it (descending)
for _, item in ipairs(items) do
item._power = calcPower(item)
end
table.sort(items, function(a, b) return a._power > b._power end)
-- Build sortable table
local tbl = mw.html.create('table')
tbl:addClass('wikitable')
:addClass('sortable')
:css('width', '100%')
-- Header row
local header = tbl:tag('tr')
header:tag('th'):wikitext('Item')
if isParent then
header:tag('th'):wikitext('Type')
end
header:tag('th'):attr('title', 'Weight'):wikitext('WGT')
header:tag('th'):attr('title', 'Damage'):wikitext('DMG')
header:tag('th'):attr('title', 'Armor'):wikitext('ARM')
header:tag('th'):attr('title', 'Defense'):wikitext('DEF')
header:tag('th'):attr('title', 'Health'):wikitext('HP')
header:tag('th'):attr('title', 'Mana'):wikitext('MP')
header:tag('th'):attr('title', 'Ability'):wikitext('ABL')
header:tag('th'):attr('title', 'Magic'):wikitext('MAG')
header:tag('th'):attr('title', 'Range'):wikitext('RNG')
header:tag('th'):attr('title', 'Move Speed'):wikitext('MS')
header:tag('th'):attr('title', 'Attack Speed'):wikitext('AS')
header:tag('th'):attr('title', 'Total Stats'):wikitext('Total')
-- Data rows
for _, item in ipairs(items) do
local row = tbl:tag('tr')
-- Item name with sprite
local nameCell = row:tag('td')
local sprite = item.sprite or item.name
nameCell:wikitext(frame:preprocess('{{Sprite|' .. sprite .. '|x2}}'))
nameCell:wikitext(' [[' .. item.name .. ']]')
-- Type column (for parent categories)
if isParent then
local typeCategory = pluralize(item.type or "")
row:tag('td'):wikitext('[[:Category:' .. typeCategory .. '|' .. (item.type or "") .. ']]')
end
-- Stats
row:tag('td'):css('text-align', 'right'):wikitext(stat(item.weight))
row:tag('td'):css('text-align', 'right'):wikitext(stat(item.damage))
row:tag('td'):css('text-align', 'right'):wikitext(stat(item.armor))
row:tag('td'):css('text-align', 'right'):wikitext(stat(item.defense))
row:tag('td'):css('text-align', 'right'):wikitext(stat(item.health))
row:tag('td'):css('text-align', 'right'):wikitext(stat(item.mana))
row:tag('td'):css('text-align', 'right'):wikitext(stat(item.ability))
row:tag('td'):css('text-align', 'right'):wikitext(stat(item.magic))
row:tag('td'):css('text-align', 'right'):wikitext(stat(item.rng))
row:tag('td'):css('text-align', 'right'):wikitext(stat(item.move_speed))
row:tag('td'):css('text-align', 'right'):wikitext(stat(item.attack_speed))
row:tag('td'):css('text-align', 'right'):wikitext(item._power)
end
return tostring(tbl)
end
return p