Module:Item
Jump to navigation
Jump to search
Documentation for this module may be created at Module:Item/doc
local p = {}
local cargo = mw.ext.cargo
local game = require('Module:Game')
local func = require('Module:Func')
local cfg = require('Module:Config')
function p.fetchItemDetails(itemName)
local queryResult = cargo.query(
"items",
"Item_Name, Item_Type, Item_Rarity, Item_Lore, Item_Level_Requirement, Item_Tier, Item_Weapon_Class, Item_Restricted_Drop, Item_Craftable, Item_Set",
{ where = "Item_Name = '" .. func.encodeName(itemName) .. "'" }
)
return queryResult
end
function p.fetchFormatDetails()
local cargo = mw.ext.cargo
local query = cargo.query(
"stat_format",
"Stat_ID, Stat_Display, Stat_Color, Stat_Type",
{Stat_ID = "Stat_ID IS NOT NULL AND Stat_ID <> ''"}
)
local formatDetails = {}
for _, row in ipairs(query) do
formatDetails[row.Stat_ID] = {Stat_Display = row.Stat_Display, Stat_Color = row.Stat_Color, Stat_Type = row.Stat_Type}
end
return formatDetails
end
function p.item(frame)
local itemName = frame.args[1]
--local itemName = "Gabriel's Broken Wings"
local fetchItem = p.fetchItemDetails(itemName)
local item = fetchItem[1]
frame:callParserFunction("#vardefine", { "itemData", mw.text.jsonEncode(item) })
local image = cfg.imageFormat(item.Item_Type, item.Item_Name)
local itemBox = {}
table.insert(itemBox, string.format('<div class="item-box %s">', item.Item_Rarity)) -- ADD RARITY TO DROPDOWN FOR COLOR HERE
table.insert(itemBox, '<div class="item-header">')
table.insert(itemBox, string.format('<p class="item-name">%s</p>', item.Item_Name or 'Item Name'))
-- Determine what type information to include
local itemDescription = item.Item_Type
if game.isWeaponType(item.Item_Type) or game.isArmorType(item.Item_Type) then
itemDescription = string.format('%s %s', item.Item_Rarity, item.Item_Type)
end
-- Insert rarity and type information
table.insert(itemBox, string.format('<p class="item-rarity-type">%s</p>', itemDescription))
if item.Item_Rarity == "Runeword" then
table.insert(itemBox, p.formatRuneWord(item.Item_Name))
end
table.insert(itemBox, '</div>')
table.insert(itemBox, string.format('<p class="item-image">[[File:%s]]</p>', image or 'Item Name'))
table.insert(itemBox, p.formatItemStats(item.Item_Name))
if item.Item_Set and item.Item_Set ~= "" then
table.insert(itemBox, p.formatItemSet(item.Item_Name, item.Item_Set))
end
table.insert(itemBox, string.format('<div class="item-lore"><p>%s</p></div>', item.Item_Lore or ''))
if game.isWeaponType(item.Item_Type) then
table.insert(itemBox, string.format('<p class ="attributes"><span>[%s]</span><span>[%s]</span></p>', item.Item_Type or '', item.Item_Weapon_Class or ''))
end
table.insert(itemBox, string.format('<p class ="attributes"><span>Level Req. %s</span>',item.Item_Level_Requirement or ''))
if not game.isMiscType(item.Item_Type) then
-- Include the item tier if the item is not a miscellaneous type
table.insert(itemBox, string.format('<span>Tier: <span class="tier-%s">%s</span></span>',item.Item_Tier, item.Item_Tier or 'Unknown'))
end
table.insert(itemBox, '</p>')
table.insert(itemBox, '</div>')
return table.concat(itemBox)
end
function p.formatItemStats(itemName)
local cargo = mw.ext.cargo
local where = string.format("Item_Name = '%s'", func.encodeName(itemName))
local statsQuery, queryError = cargo.query(
'item_stats',
'Stat_ID, Spell_Name, Class_Name, Min_Value1, Max_Value1, Min_Value2, Max_Value2, Min_Value3, Max_Value3, Stat_Order',
{
where = where,
orderBy = "Stat_Order"
}
)
local formatDetails = p.fetchFormatDetails()
local baseStats = {}
local nonBaseStats = {}
local defense, block, damage, aps = 'N/A', 'N/A', 'N/A', 'N/A' -- Default values
local minRangeAS, maxRangeAS, minRangeED, maxRangeED= 0, 0, 0, 0
for _, stat in ipairs(statsQuery) do
if stat.Stat_ID == 'enhanced_defense_percent' or stat.Stat_ID == "enhanced_defense_based_on_level_percent" or stat.Stat_ID == 'enhanced_dmg_percent' or stat.Stat_ID == "enhanced_dmg_based_on_level_percent" then
minRangeED = tonumber(stat.Min_Value1) + minRangeED
maxRangeED = tonumber(stat.Max_Value1) or tonumber(stat.Min_Value1) + maxRangeED
elseif stat.Stat_ID == 'attack_speed_percent' then
minRangeAS = tonumber(stat.Min_Value1)
maxRangeAS = tonumber(stat.Max_Value1) or tonumber(stat.Min_Value1)
end
end
for _, stat in ipairs(statsQuery) do
if stat.Stat_ID == 'attack_dmg_base' or stat.Stat_ID == 'attacks_per_second_base' or stat.Stat_ID == 'defense_base' or stat.Stat_ID == 'block_chance_base' then
if stat.Stat_ID == 'defense_base' then
local minDefense = tonumber(stat.Min_Value1) * (1 + minRangeED/100)
local maxDefense = tonumber(stat.Max_Value1 or stat.Min_Value1) * (1 + maxRangeED/100)
table.insert(baseStats, string.format('<p class="base-stat">Defense: [%s-%s]</p>', math.ceil(minDefense), math.ceil(maxDefense)))
elseif stat.Stat_ID == 'block_chance_base' then
table.insert(baseStats, string.format('<p class="base-stat">Block Chance: %s</p>', stat.Min_Value1))
elseif stat.Stat_ID == 'attack_dmg_base' then
local minDamage = tonumber(stat.Min_Value1) * (1 + minRangeED/100)
local maxDamage = tonumber(stat.Max_Value1) * (1 + maxRangeED/100)
table.insert(baseStats, string.format('<p class="base-stat">Attack Damage: [%s-%s]</p>', math.ceil(minDamage), math.ceil(maxDamage)))
elseif stat.Stat_ID == 'attacks_per_second_base' then
local minAttackSpeed = (tonumber(stat.Min_Value1) * (1 + minRangeAS/100)) * 100
minAttackSpeed = math.ceil(minAttackSpeed)
minAttackSpeed = minAttackSpeed / 100
local maxAttackSpeed = (tonumber(stat.Min_Value1) * (1 + maxRangeAS/100)) * 100
maxAttackSpeed = math.ceil(maxAttackSpeed)
maxAttackSpeed = maxAttackSpeed / 100
if minAttackSpeed == maxAttackSpeed then
table.insert(baseStats, string.format('<p class="base-stat">Attacks per Second: %s</p>', minAttackSpeed))
else
table.insert(baseStats, string.format('<p class="base-stat">Attacks per Second: [%s-%s]</p>', minAttackSpeed, maxAttackSpeed))
end
end
elseif stat.Stat_ID == 'socketed_flat' then
if stat.Max_Value1 and stat.Max_Value1 ~= "" then
table.insert(nonBaseStats, string.format('<p class="stat-default">Socketed (%s-%s)</p>', stat.Min_Value1, stat.Max_Value1))
else
table.insert(nonBaseStats, string.format('<p class="stat-default">Socketed (%s)</p>', stat.Min_Value1))
end
else
table.insert(nonBaseStats, p.formatStatLine(stat, formatDetails))
end
end
-- Combine formatted stats into sections
return string.format(
'<div class="item-basestats">%s</div><div class="item-stats">%s</div>',
table.concat(baseStats, "\n"),
table.concat(nonBaseStats, "\n")
)
end
function p.formatStatLine(stat, formatDetails)
local statDetail = formatDetails[stat.Stat_ID]
local formattedStat = statDetail and statDetail.Stat_Display or stat.Stat_ID
mw.logObject(statDetail)
-- Replace placeholders for value1, value2, and value3
if stat.Min_Value1 and stat.Min_Value1 ~= "" and tonumber(stat.Min_Value1) >= 0 then formattedStat = formattedStat:gsub("value1", p.formatRange(stat.Min_Value1, stat.Max_Value1)) end
if stat.Min_Value1 and stat.Min_Value1 ~= "" and tonumber(stat.Min_Value1) < 0 then
local formattedRange = p.formatRange(stat.Min_Value1, stat.Max_Value1)
formattedStat = formattedStat:gsub("[+]?[vV]alue1", formattedRange)
end
if stat.Min_Value2 and stat.Min_Value2 ~= "" then formattedStat = formattedStat:gsub("value2", p.formatRange(stat.Min_Value2, stat.Max_Value2)) end
if stat.Min_Value3 and stat.Min_Value3 ~= "" then formattedStat = formattedStat:gsub("value3", p.formatRange(stat.Min_Value3, stat.Max_Value3)) end
if stat.Spell_Name and stat.Spell_Name ~= "" then formattedStat = formattedStat:gsub("spellvalue", string.format('<span class="item-stat-spell-link">[[%s|[%s]]]</span>', stat.Spell_Name, stat.Spell_Name)) end
if stat.Class_Name and stat.Class_NAme ~= "" then formattedStat = formattedStat .. string.format(" (%s)", stat.Class_Name) end
if statDetail and statDetail.Stat_Type == "none" then formattedStat = string.format("[[%s]]", formattedStat) end
local class = "stat-" .. (statDetail and statDetail.Stat_Color or "default")
return string.format('<p class="%s">%s</p>', class, formattedStat)
end
function p.formatItemSet(itemName, setName)
local cargo = mw.ext.cargo
local where = "Set_Name = '" .. func.encodeName(setName) .. "'"
local query = cargo.query(
"item_sets",
"Set_Name, Set_Item_1, Set_Item_2, Set_Item_3, Set_Item_4, Set_Item_5, Set_Item_6, Set_Bonus_1, Set_Bonus_2, Set_Bonus_3, Set_Bonus_4, Set_Bonus_5",
{ where = where }
)
local setInfo = query[1] -- Assuming there's only one set with this name
-- Start building the display
local output = {}
table.insert(output, '<div class="item-stats">')
for i = 1, 10 do
local bonusField = "Set_Bonus_" .. i
if setInfo[bonusField] and setInfo[bonusField] ~= '' then
table.insert(output, string.format("<p>%s</p>", setInfo[bonusField]))
end
end
table.insert(output, '</div>')
table.insert(output, '<div class="item-stats">')
table.insert(output, string.format('<p class="set-name">%s</p>', setInfo.Set_Name))
-- Display set items
for i = 1, 6 do
local itemField = "Set_Item_" .. i
if setInfo[itemField] and setInfo[itemField] ~= '' then
table.insert(output, string.format('<p class="set-item">%s</p>', setInfo[itemField]))
end
end
table.insert(output, '</div>')
return table.concat(output)
end
function p.formatRuneWord(itemName)
local where = "Runeword_Name = '" .. func.encodeName(itemName) .. "'"
-- Query the runewords
local query = cargo.query(
"runewords",
"Runeword_Name, Runeword_Item_Type, Rune_1, Rune_2, Rune_3, Rune_4, Rune_5, Rune_6, Sockets",
{ where = where }
)
-- Ensure the query returned results
if #query == 0 then
return "No runeword found."
end
-- Extract the runes from the query result
local runeword = query[1]
local runes = {}
for i = 1, 6 do
local rune = runeword["Rune_" .. i]
if rune and rune ~= "" then
table.insert(runes, rune)
end
end
-- Construct the format string based on the number of runes
local formatString = string.format("(%s)", string.rep("%s, ", #runes):sub(1, -3))
-- Format the extracted runes
local formattedRunes = string.format(formatString, unpack(runes))
return formattedRunes
end
function p.formatRange(min, max)
if max and max ~= '' and max ~= min then
return "[" .. min .. "-" .. max .. "]"
else
return min
end
end
function p.isWeaponType(itemType)
local weaponTypes = {
Sword = true,
Dagger = true,
Mace = true,
Axe = true,
Claw = true,
Polearm = true,
Chainsaw = true,
Staff = true,
Cane = true,
Wand = true,
Book = true,
Spellblade = true,
Bow = true,
Gun = true,
Flask = true,
["Throwing Weapon"] = true }
return weaponTypes[itemType] or false
end
function p.isArmorType(itemType)
local armorTypes = {
Helmet = true,
["Body Armor"] = true,
Gloves = true,
Belt = true,
Amulet = true,
Ring = true,
Boots = true,
Shield = true,
Charm = true,
}
return armorTypes[itemType] or false
end
function p.isMiscType(itemType)
local miscTypes = {
Consumable = true,
Potion = true,
Key = true,
Material = true,
Collectible = true
}
return miscTypes[itemType] or false
end
return p