4,670
edits
(Testing updated modifiers) |
No edit summary |
||
Line 7: | Line 7: | ||
local GameData = require('Module:GameData') | local GameData = require('Module:GameData') | ||
local Constants = require('Module: | 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 = | name = Shared.fixPagename(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 78: | Line 98: | ||
end | end | ||
elseif string.find(StatName, '^(.+)LevelRequired$') ~= nil and item.equipRequirements ~= nil then | elseif string.find(StatName, '^(.+)LevelRequired$') ~= nil and item.equipRequirements ~= nil then | ||
local skillName = Shared.titleCase(string.match(StatName, '^(.+)LevelRequired$')) | local skillName = nil | ||
if (string.find(StatName, '^(.+)Abyssal$')) then | |||
skillName = Shared.titleCase(string.match(StatName, '^(.+)AbyssalLevelRequired$')) | |||
else | |||
skillName = Shared.titleCase(string.match(StatName, '^(.+)LevelRequired$')) | |||
end | |||
if skillName ~= nil then | if skillName ~= nil then | ||
local skillID = Constants.getSkillID(skillName) | local skillID = Constants.getSkillID(skillName) | ||
Line 85: | Line 110: | ||
if requirement.type == "SkillLevel" and requirement.skillID == skillID then | if requirement.type == "SkillLevel" and requirement.skillID == skillID then | ||
result = requirement.level | result = requirement.level | ||
break | |||
end | |||
if requirement.type == "AbyssalLevel" and requirement.skillID == skillID then | |||
result = requirement.abyssalLevel | |||
break | break | ||
end | end | ||
Line 112: | Line 141: | ||
if result == nil and ZeroIfNil then result = 0 end | if result == nil and ZeroIfNil then result = 0 end | ||
return result | return result | ||
end | |||
function p.getItemValueByID(itemID) | |||
local item = p.getItemByID(itemID) | |||
if item == nil then | |||
return 0 | |||
end | |||
return p.getItemValue(item['name']) | |||
end | |||
function p.getItemValue(item) | |||
if type(item) == 'string' then | |||
-- Specific check if the item is GP (value of 1) | |||
if Shared.compareString('GP', item, true) | |||
or Shared.compareString('Gold Pieces', item, true) then | |||
return 1 | |||
end | |||
item = p.getItem(item) | |||
end | |||
if item then | |||
return item.sellsFor | |||
end | |||
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 125: | Line 216: | ||
end | end | ||
local result = p._getItemStat(item, StatName, ZeroIfNil) | local result = p._getItemStat(item, StatName, ZeroIfNil) | ||
if formatNum then result = | if formatNum then result = Num.formatnum(result) end | ||
return result | return result | ||
end | end | ||
--Gets the value of a given modifier for a given | --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 167: | Line 258: | ||
function p.hasCombatStats(item) | function p.hasCombatStats(item) | ||
-- Checks if the combat stat is a valid, non-zero combat stat | |||
-- Ensure that, only in the case where the item is a Familar AND | |||
-- the checked stat is summoningMaxhit, the result is ignored. | |||
local function isNonZeroStat(statName, statVal) | |||
if statName == 'summoningMaxhit' and (p._canItemUseSlot(item, 'Summon1') or p._canItemUseSlot(item, 'Summon2')) then | |||
return false | |||
end | |||
return statVal ~= 0 | |||
end | |||
if item.equipmentStats ~= nil then | if item.equipmentStats ~= nil then | ||
-- Ensure at least one stat has a non-zero value | -- Ensure at least one stat has a non-zero value | ||
for statName, statVal in pairs(item.equipmentStats) do | for statName, statVal in pairs(item.equipmentStats) do | ||
if statVal | if isNonZeroStat(statName, statVal) then | ||
return true | return true | ||
end | end | ||
end | end | ||
end | end | ||
return false | return false | ||
end | end | ||
Line 301: | Line 403: | ||
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, | table.insert(changeArray, Num.numStrWithSign(val1 - val2) .. ' ' .. Icons.Icon({skillData.data.name, type='skill', notext=true}) .. (statDef.suffix or '')) | ||
end | end | ||
end | end | ||
Line 308: | Line 410: | ||
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, | table.insert(changeArray, Num.numStrWithSign(val1 - val2) .. (statDef.suffix or '')) | ||
end | end | ||
end | end | ||
Line 314: | Line 416: | ||
-- 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 342: | Line 446: | ||
["Passive"] = 'Combat Passive Slot', | ["Passive"] = 'Combat Passive Slot', | ||
["Summon1"] = 'Summoning', | ["Summon1"] = 'Summoning', | ||
["Summon2"] = 'Summoning' | ["Summon2"] = 'Summoning', | ||
["Gem"] = "Gems_(Equipment)" | |||
} | } | ||
local slotText = {} | local slotText = {} | ||
Line 377: | Line 482: | ||
-- 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:''' " .. | 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 390: | Line 495: | ||
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 411: | Line 519: | ||
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, | table.insert(resultPart, Modifiers.getModifiersText(item.modifiers, true, false, 10)) | ||
end | end | ||
return table.concat(resultPart) | return table.concat(resultPart) | ||
Line 484: | Line 592: | ||
function p.getItemGrid(frame) | function p.getItemGrid(frame) | ||
local | --melvorF, melvorD, melvorTotH, melvorAoD | ||
table | local dlcFunc = function(item, dlc) | ||
for | local itemDLC = Shared.getLocalID(item.id) | ||
if i | if dlc == nil then | ||
return true | |||
end | |||
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 | ||
end | end | ||
return | 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 | local reqDefns = { | ||
["DungeonCompletion"] = { | |||
["dataKey"] = 'dungeons', | |||
["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 522: | Line 693: | ||
end | end | ||
return result | return result | ||
end | |||
function p._getItemResistance(item) | |||
if item.sellsForCurrency == 'melvorItA:AbyssalPieces' then | |||
return p._getItemStat(item, 'resistance', true), 'Abyssal Resistance' | |||
else | |||
return p._getItemStat(item, 'damageReduction', true), 'Damage Reduction' | |||
end | |||
end | end | ||
Line 530: | Line 709: | ||
return Shared.printError('No item named "' .. itemName .. '" exists in the data module') | return Shared.printError('No item named "' .. itemName .. '" exists in the data module') | ||
end | end | ||
local resistance, resistanceText = p._getItemResistance(item) | |||
local ico = { | local ico = { | ||
Line 538: | Line 719: | ||
["Ranged"] = Icons.Icon({'Ranged', type='skill', notext=true}), | ["Ranged"] = Icons.Icon({'Ranged', type='skill', notext=true}), | ||
["Strength"] = Icons.Icon({'Strength', type='skill', notext=true}), | ["Strength"] = Icons.Icon({'Strength', type='skill', notext=true}), | ||
["Slayer"] = Icons.Icon({'Slayer', type='skill', notext=true}) | ["Slayer"] = Icons.Icon({'Slayer', type='skill', notext=true}), | ||
["Resistance"] = Icons.Icon({resistanceText, notext=true}) | |||
} | } | ||
local reqCount = item.equipRequirements ~= nil and Shared.tableCount(item.equipRequirements) or 0 | local reqCount = item.equipRequirements ~= nil and Shared.tableCount(item.equipRequirements) or 0 | ||
local emptyRow = '\r\n!colspan="2"|' | local emptyRow = '\r\n!colspan="2"|' | ||
local damageType = p._getItemStat(item, 'damageType') == 'melvorItA:Abyssal' and 'Abyssal' or 'Normal' | |||
local resultPart = {} | local resultPart = {} | ||
Line 550: | Line 733: | ||
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;"| ' .. | 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)) | ||
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| Damage Type') | |||
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. ico['Resistance'] .. damageType) | |||
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Resistance'] .. resistanceText) | |||
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. resistance .. '%') | |||
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| Attack Type') | table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| Attack Type') | ||
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'attackType')) | table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'attackType')) | ||
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico[' | table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Defence Bonus') | ||
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, ' | table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedDefenceBonus', true)) | ||
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Strength'] .. ' Strength Bonus') | table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Strength'] .. ' Strength Bonus') | ||
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'meleeStrengthBonus', true)) | table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'meleeStrengthBonus', true)) | ||
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico[' | table.insert(resultPart, '\r\n!style="text-align:right;border-bottom:solid thin black;"| ' .. ico['Magic'] .. ' Defence Bonus') | ||
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, ' | table.insert(resultPart, '\r\n|style="text-align:right;border-bottom:solid thin black;"| ' .. p._getItemStat(item, 'magicDefenceBonus', true)) | ||
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Stab Bonus') | table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Stab Bonus') | ||
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'stabAttackBonus', true)) | table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'stabAttackBonus', true)) | ||
table.insert(resultPart, '\r\n! | table.insert(resultPart, '\r\n!colspan="2" style="border-bottom:solid thin black;"| Equip Requirements') | ||
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Slash Bonus') | table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Slash Bonus') | ||
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'slashAttackBonus', true)) | table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'slashAttackBonus', true)) | ||
table.insert(resultPart, '\r\n | if reqCount > 0 then | ||
table.insert(resultPart, p.getEquipRequirementRow(item.equipRequirements[1])) | |||
else | |||
table.insert(resultPart, '\r\n|colspan=2 style="text-align:right"|None') | |||
end | |||
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Block Bonus') | table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Block Bonus') | ||
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'blockAttackBonus', true)) | table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'blockAttackBonus', true)) | ||
if reqCount > | if reqCount > 1 then | ||
table.insert(resultPart, p.getEquipRequirementRow(item.equipRequirements[ | table.insert(resultPart, p.getEquipRequirementRow(item.equipRequirements[2])) | ||
else | else | ||
table.insert(resultPart, | table.insert(resultPart, emptyRow) | ||
end | end | ||
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Attack Bonus') | table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Attack Bonus') | ||
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedAttackBonus', true)) | table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedAttackBonus', true)) | ||
if reqCount > | if reqCount > 2 then | ||
table.insert(resultPart, p.getEquipRequirementRow(item.equipRequirements[ | table.insert(resultPart, p.getEquipRequirementRow(item.equipRequirements[3])) | ||
else | else | ||
table.insert(resultPart, emptyRow) | table.insert(resultPart, emptyRow) | ||
Line 591: | Line 782: | ||
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Strength Bonus') | table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Ranged'] .. ' Strength Bonus') | ||
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedStrengthBonus', true)) | table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'rangedStrengthBonus', true)) | ||
if reqCount > | if reqCount > 3 then | ||
table.insert(resultPart, p.getEquipRequirementRow(item.equipRequirements[ | table.insert(resultPart, p.getEquipRequirementRow(item.equipRequirements[4])) | ||
else | else | ||
table.insert(resultPart, emptyRow) | table.insert(resultPart, emptyRow) | ||
Line 599: | Line 790: | ||
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Magic'] .. ' Attack Bonus') | table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Magic'] .. ' Attack Bonus') | ||
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'magicAttackBonus', true)) | table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'magicAttackBonus', true)) | ||
if reqCount > | if reqCount > 4 then | ||
table.insert(resultPart, p.getEquipRequirementRow(item.equipRequirements[ | table.insert(resultPart, p.getEquipRequirementRow(item.equipRequirements[5])) | ||
else | else | ||
table.insert(resultPart, emptyRow) | table.insert(resultPart, emptyRow) | ||
Line 607: | Line 798: | ||
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Magic'] .. ' % Damage Bonus') | table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Magic'] .. ' % Damage Bonus') | ||
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'magicDamageBonus', true) .. '%') | table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'magicDamageBonus', true) .. '%') | ||
if reqCount > | if reqCount > 5 then | ||
table.insert(resultPart, p.getEquipRequirementRow(item.equipRequirements[ | table.insert(resultPart, p.getEquipRequirementRow(item.equipRequirements[6])) | ||
else | else | ||
table.insert(resultPart, emptyRow) | table.insert(resultPart, emptyRow) | ||
Line 615: | Line 806: | ||
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| Two Handed?') | table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| Two Handed?') | ||
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. (p._getItemStat(item, 'isTwoHanded') and 'Yes' or 'No')) | table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. (p._getItemStat(item, 'isTwoHanded') and 'Yes' or 'No')) | ||
if reqCount > | if reqCount > 6 then | ||
table.insert(resultPart, p.getEquipRequirementRow(item.equipRequirements[6])) | table.insert(resultPart, p.getEquipRequirementRow(item.equipRequirements[6])) | ||
else | else | ||
table.insert(resultPart, emptyRow) | table.insert(resultPart, emptyRow) | ||
end | end | ||
--Add extra rows at the end for items that have more than 3 different requirements | --Add extra rows at the end for items that have more than 3 different requirements | ||
if reqCount > | if reqCount > 7 then | ||
for i = | for i = 8, reqCount, 1 do | ||
table.insert(resultPart,"\r\n|-") | table.insert(resultPart,"\r\n|-") | ||
table.insert(resultPart, emptyRow) | table.insert(resultPart, emptyRow) | ||
Line 640: | Line 831: | ||
return Shared.printError('No item named "' .. itemName .. '" exists in the data module') | return Shared.printError('No item named "' .. itemName .. '" exists in the data module') | ||
end | end | ||
local resistance, resistanceText = p._getItemResistance(item) | |||
local ico = { | local ico = { | ||
Line 648: | Line 841: | ||
["Ranged"] = Icons.Icon({'Ranged', type='skill', notext=true}), | ["Ranged"] = Icons.Icon({'Ranged', type='skill', notext=true}), | ||
["Strength"] = Icons.Icon({'Strength', type='skill', notext=true}), | ["Strength"] = Icons.Icon({'Strength', type='skill', notext=true}), | ||
["Slayer"] = Icons.Icon({'Slayer', type='skill', notext=true}) | ["Slayer"] = Icons.Icon({'Slayer', type='skill', notext=true}), | ||
["Resistance"] = Icons.Icon({resistanceText, notext=true}), | |||
} | } | ||
Line 666: | Line 860: | ||
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Stab Bonus') | table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Stab Bonus') | ||
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'stabAttackBonus', 0)) | table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. p._getItemStat(item, 'stabAttackBonus', 0)) | ||
table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico[' | table.insert(resultPart, '\r\n!style="text-align:right;"| ' .. ico['Resistance'] .. resistanceText) | ||
table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. | table.insert(resultPart, '\r\n|style="text-align:right;"| ' .. resistance .. '%') | ||
table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Slash Bonus') | table.insert(resultPart, '\r\n|-\r\n!style="text-align:right;"| ' .. ico['Combat'] .. ' Slash Bonus') | ||
Line 850: | Line 1,044: | ||
table.insert(resultPart, '\r\n|}') | table.insert(resultPart, '\r\n|}') | ||
return table.concat(resultPart) | return table.concat(resultPart) | ||
end | |||
function p.getLifestealWeapons() | |||
local items = p.getItems(function(item) | |||
if item.specialAttacks ~= nil and not Shared.tableIsEmpty(item.specialAttacks) then | |||
for i, spAttID in ipairs(item.specialAttacks) do | |||
local spAtt = GameData.getEntityByID('attacks', spAttID) | |||
if spAtt ~= nil then | |||
return spAtt.lifesteal > 0 | |||
end | |||
end | |||
end | |||
return false | |||
end) | |||
for i, item in ipairs(items) do | |||
mw.log(item.name) | |||
end | |||
end | end | ||
return p | return p |