Module:Items: Difference between revisions

Added soul points to ItemBox
(Add function to grab item value (sellsfor) based on item name or item object)
(Added soul points to ItemBox)
(20 intermediate revisions by 2 users not shown)
Line 9: Line 9:
local Constants = require('Module:Constants')
local Constants = require('Module:Constants')
local Shared = require('Module:Shared')
local Shared = require('Module:Shared')
local Modifiers = require('Module:Modifiers')
local Icons = require('Module:Icons')
local Icons = require('Module:Icons')
local Num = require('Module:Number')


p.EasterEggs = {'Amulet of Calculated Promotion', 'Clue Chasers Insignia', '8', 'Lemon', 'Easter Egg',
p.EasterEggs = {'Amulet of Calculated Promotion', 'Clue Chasers Insignia', '8', 'Lemon', 'Easter Egg',
Line 23: Line 25:
'Holiday Scarf', 'Gingerbread House', 'Gingerbread Man', 'Edible Candy Cane',
'Holiday Scarf', 'Gingerbread House', 'Gingerbread Man', 'Edible Candy Cane',
'Locked Chest', 'Locked Chest Key', 'Event Token (Holiday 2021)'}
'Locked Chest', 'Locked Chest Key', 'Event Token (Holiday 2021)'}
-- List of item IDs that should typically not be included within outputs, usually
-- because they are not fully implemented despite existing within the game data
p.HiddenItems = {}
local function populateHiddenItems()
local hiddenItems = GameData.getEntities('items',
function(item)
return item.name == nil or Shared.contains({'melvorTotH:Meteorite_Dust'}, item.id)
end
)
for _, item in ipairs(hiddenItems) do
table.insert(p.HiddenItems, item.id)
end
end
populateHiddenItems()


function p.getItemByID(ID)
function p.getItemByID(ID)
Line 29: Line 46:


function p.getItem(name)
function p.getItem(name)
name = string.gsub(name, "%%27", "'")
name = Shared.fixPagename(name)
name = string.gsub(name, "'", "'")
return GameData.getEntityByName('items', name)
return GameData.getEntityByName('items', name)
end
end


function p.getItems(checkFunc)
function p.getItems(checkFunc)
return GameData.getEntities('items', checkFunc)
return GameData.getEntities('items',
function(obj)
return not Shared.contains(p.HiddenItems, obj.id) and checkFunc(obj)
end
)
end
end


Line 114: Line 134:
end
end


function p.getItemValue(item)
function p.getItemValueByID(itemID)
function isGP(itemName)
local item = p.getItemByID(itemID)
return itemName == 'GP' or itemName == 'Gold Pieces'
if item == nil then
return 0
end
end
return p.getItemValue(item['name'])
end
function p.getItemValue(item)
if type(item) == 'string' then
if type(item) == 'string' then
if isGP(item:upper()) then  
-- Specific check if the item is GP (value of 1)
return 1  
if Shared.compareString('GP', item, true)
or Shared.compareString('Gold Pieces', item, true) then
return 1
end
end
 
item = p.getItem(item)
item = p.getItem(item)
end
end
Line 132: Line 159:
return nil
return nil
end
function p.getValueText(item, minQuantity, maxQuantity)
local minQ, maxQ = 1, 1
if type(minQuantity) == 'number' then
minQ = minQuantity
end
if type(maxQuantity) == 'number' then
maxQ = maxQuantity
else
maxQ = minQ
end
local amt = item.sellsFor or 0
local currID = item.sellsForCurrency or 'melvorD:GP'
return Icons._Currency(currID, amt * minQ, amt * maxQ)
end
-- Function already exists, but without frame.
-- Giving it a slightly different name since function overloading doesn't exist
function p.getItemSellsFor(frame)
local args = frame:getParent().args
return p._getItemSellsFor(args[1], args[2], args.round)
end
function p._getItemSellsFor(itemName, multiplier, rounding)
local itemValue = p.getItemValue(itemName)
multiplier = tonumber(multiplier) or 1
rounding = tonumber(rounding) or 0
if itemValue == nil then
error('No item named "' .. itemName .. '" exists in the data module')
end
return Num.round2(itemValue * multiplier, rounding)
end
end


Line 145: Line 207:
end
end
local result = p._getItemStat(item, StatName, ZeroIfNil)
local result = p._getItemStat(item, StatName, ZeroIfNil)
if formatNum then result = Shared.formatnum(result) end
if formatNum then result = Num.formatnum(result) end
return result
return result
end
end


--Gets the value of a given modifier for a given itemg
--Gets the value of a given modifier for a given item
--asString is false by default, when true it writes the full bonus text
--asString is false by default, when true it writes the full bonus text
function p._getItemModifier(item, modifier, skillID, asString)
function p._getItemModifier(item, modifier, skillID, asString)
Line 190: Line 252:
-- Ensure that, only in the case where the item is a Familar AND
-- Ensure that, only in the case where the item is a Familar AND
-- the checked stat is summoningMaxhit, the result is ignored.
-- the checked stat is summoningMaxhit, the result is ignored.
function isNonZeroStat(statName, statVal)
local function isNonZeroStat(statName, statVal)
if statName == 'summoningMaxhit' and (p._canItemUseSlot(item, 'Summon1') or p._canItemUseSlot(item, 'Summon2')) then
if statName == 'summoningMaxhit' and (p._canItemUseSlot(item, 'Summon1') or p._canItemUseSlot(item, 'Summon2')) then
return false
return false
Line 332: Line 394:
val1, val2 = levelReqs[1][skillID] or 0, levelReqs[2][skillID] or 0
val1, val2 = levelReqs[1][skillID] or 0, levelReqs[2][skillID] or 0
if val1 ~= val2 then
if val1 ~= val2 then
table.insert(changeArray, Shared.numStrWithSign(val1 - val2) .. ' ' .. Icons.Icon({skillData.data.name, type='skill', notext=true}) .. (statDef.suffix or ''))
table.insert(changeArray, Num.numStrWithSign(val1 - val2) .. ' ' .. Icons.Icon({skillData.data.name, type='skill', notext=true}) .. (statDef.suffix or ''))
end
end
end
end
Line 339: Line 401:
val1, val2 = equipStats[1][statDef.stat] or 0, equipStats[2][statDef.stat] or 0
val1, val2 = equipStats[1][statDef.stat] or 0, equipStats[2][statDef.stat] or 0
if val1 ~= val2 then
if val1 ~= val2 then
table.insert(changeArray, Shared.numStrWithSign(val1 - val2) .. (statDef.suffix or ''))
table.insert(changeArray, Num.numStrWithSign(val1 - val2) .. (statDef.suffix or ''))
end
end
end
end
Line 345: Line 407:


-- Include differences in modifiers
-- Include differences in modifiers
local modDiff = Constants.getModifiersText(Constants.getModifiersDifference(item2.modifiers, item1.modifiers))
-- TODO Implement getModifiersDifference
--local modDiff = Constants.getModifiersText(Constants.getModifiersDifference(item2.modifiers, item1.modifiers))
local modDiff = nil
if modDiff ~= nil and modDiff ~= '' then
if modDiff ~= nil and modDiff ~= '' then
table.insert(changeArray, modDiff)
table.insert(changeArray, modDiff)
Line 373: Line 437:
["Passive"] = 'Combat Passive Slot',
["Passive"] = 'Combat Passive Slot',
["Summon1"] = 'Summoning',
["Summon1"] = 'Summoning',
["Summon2"] = 'Summoning'
["Summon2"] = 'Summoning',
["Gem"] = "Gems_(Equipment)"
}
}
local slotText = {}
local slotText = {}
Line 408: Line 473:
-- For Summoning combat familiars, show the max hit
-- For Summoning combat familiars, show the max hit
if item.equipmentStats ~= nil and item.equipmentStats.summoningMaxhit ~= nil then
if item.equipmentStats ~= nil and item.equipmentStats.summoningMaxhit ~= nil then
table.insert(resultPart, "\r\n|-\r\n|'''Max Hit:''' " .. Shared.formatnum(item.equipmentStats.summoningMaxhit * 10))
table.insert(resultPart, "\r\n|-\r\n|'''Max Hit:''' " .. Num.formatnum(item.equipmentStats.summoningMaxhit * 10))
end
end
--For potions, show the number of charges
--For potions, show the number of charges
Line 421: Line 486:
if item.prayerPoints ~= nil then
if item.prayerPoints ~= nil then
table.insert(resultPart, "\r\n|-\r\n|'''"..Icons.Icon({'Prayer', type='skill'}).." Points:''' "..item.prayerPoints)
table.insert(resultPart, "\r\n|-\r\n|'''"..Icons.Icon({'Prayer', type='skill'}).." Points:''' "..item.prayerPoints)
end
if item.soulPoints ~= nil then
table.insert(resultPart, "\r\n|-\r\n|'''"..Icons.Icon({'Prayer', 'Soul', type='item', img='Lesser Soul'}).." Points:''' "..item.soulPoints)
end
end
--For items that provide runes, show which runes are provided
--For items that provide runes, show which runes are provided
Line 442: Line 510:
table.insert(resultPart, '<span style="color:green">Passive:</span><br/>')
table.insert(resultPart, '<span style="color:green">Passive:</span><br/>')
end
end
table.insert(resultPart, Constants.getModifiersText(item.modifiers, true, false, 10))
table.insert(resultPart, Modifiers.getModifiersText(item.modifiers, true, false, 10))
end
end
return table.concat(resultPart)
return table.concat(resultPart)
Line 515: Line 583:


function p.getItemGrid(frame)
function p.getItemGrid(frame)
local resultPart = {}
--melvorF, melvorD, melvorTotH, melvorAoD
table.insert(resultPart, '{|')
local dlcFunc = function(item, dlc)
for i, item in ipairs(GameData.rawData.items) do
local itemDLC = Shared.getLocalID(item.id)
if i % 17 == 1 then
if dlc == nil then
table.insert(resultPart, '\r\n|-\r\n|')
return true
else
end
table.insert(resultPart, '||')
if dlc == 'base' then
return itemDLC == 'melvorD' or itemDLC == 'melvorF'
end
if itemDLC == dlc then
return true
end
return false
end
-- Convert list of hidden items into a key/value structure, such that
-- lookups are more efficient than repeated calls to Shared.contains()
local hiddenItemIDs = {}
for i, itemID in ipairs(p.HiddenItems) do
hiddenItemIDs[itemID] = 1
end
 
local args = frame:getParent().args
local dlc = args[1] or args.DLC or args.dlc or nil
local columns = tonumber(args[2] or args.Columns or args.columns) or 17
local html = mw.html.create('table')
:addClass('wikitable lighttable individual')
 
local curRow = html:tag('tr')
local i = 0
for _, v in pairs(GameData.rawData.items) do
if hiddenItemIDs[v.id] == nil and dlcFunc(v, dlc) == true then
if i >= columns then
curRow = html:tag('tr')
i = 0
end
local cell = curRow:tag('td')
:css('height', '48px')
:css('width', '48px')
:css('padding', '0px')
cell:tag('div')
:css('padding', '8px')
:wikitext(Icons.Icon({v.name, type='item', notext=true, size='32'}))
-- Mod operator is slow. We use this instead
i = i + 1
end
end
table.insert(resultPart, 'style="padding:3px"|'..Icons.Icon({item.name, type='item', notext=true, size='40'}))
end
end
table.insert(resultPart, '\r\n|}')
return table.concat(resultPart)
return tostring(html)
end
end


function p.getEquipRequirementRow(req)
function p.getEquipRequirementRow(req)
local result = ""
local result = ""
if req.type == "SkillLevel" then
if (req.type == "SkillLevel" or req.type == "AbyssalLevel") then
local pre = (req.type == "AbyssalLevel" and ' Abyssal') or ''
local skillName = Constants.getSkillName(req.skillID)
local skillName = Constants.getSkillName(req.skillID)
local skillIcon = Icons.Icon({skillName, type='skill', notext=true})
local skillIcon = Icons.Icon({skillName, type='skill', notext=true})
result = '\r\n!style="text-align:right;"| '..skillIcon..' Level Required'
result = '\r\n!style="text-align:right;"| '..skillIcon..pre..' Level Required'
result = result..'\r\n|style="text-align:right;"| '..req.level
result = result..'\r\n|style="text-align:right;"| '..req.level
elseif req.type == "DungeonCompletion" then
elseif (req.type == "DungeonCompletion" or req.type == "AbyssDepthCompletion") then
local dungeonName = GameData.getEntityByID("dungeons", req.dungeonID).name
local reqDefns = {
local dungeonIcon = Icons.Icon({dungeonName, type="dungeon", notext=true})
["DungeonCompletion"] = {
result = '\r\n!style="text-align:right;"| '..dungeonIcon..' Completions'
["dataKey"] = 'dungeons',
result = result..'\r\n|style="text-align:right;"| '..req.count
["IDKey"] = 'dungeonID',
["imgType"] = 'dungeon'
},
["AbyssDepthCompletion"] = {
["dataKey"] = 'abyssDepths',
["IDKey"] = 'depthID',
["imgType"] = 'combatArea'
}
}
local reqDefn = reqDefns[req.type]
if reqDefn ~= nil then
local area = GameData.getEntityByID(reqDefn.dataKey, req[reqDefn.IDKey])
if area == nil then
result = '\r\n!style="text-align:right;" colspan=2|' .. Shared.printError('Invalid area for requirement type "' .. req.type .. '"')
else
local areaIcon = Icons.Icon({area.name, type=reqDefn.imgType, notext=true})
result = '\r\n!style="text-align:right;"| '..areaIcon..' Completions'
result = result..'\r\n|style="text-align:right;"| '..Num.formatnum(req.count)
end
end
elseif req.type == "Completion" then
elseif req.type == "Completion" then
local ns = GameData.getEntityByName('namespaces', req.namespace)
local ns = GameData.getEntityByName('namespaces', req.namespace)
Line 581: Line 712:


table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| Attack Speed')
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| Attack Speed')
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. Shared.round(p._getItemStat(item, 'attackSpeed', true) / 1000, 3, 1) .. 's')
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. Num.round(p._getItemStat(item, 'attackSpeed', true) / 1000, 3, 1) .. 's')
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Defence'] .. ' Defence Bonus')
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Defence'] .. ' Defence Bonus')
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'meleeDefenceBonus', true))
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'meleeDefenceBonus', true))