Anonymous

Module:Items: Difference between revisions

From Melvor Idle
2,818 bytes added ,  11 October 2021
Fixed check for WeaponAttackType for throwing knives and javelins
(Added Passive slot mention for passive items)
(Fixed check for WeaponAttackType for throwing knives and javelins)
(20 intermediate revisions by 4 users not shown)
Line 6: Line 6:
local p = {}
local p = {}


local MonsterData = mw.loadData('Module:Monsters/data')
local ItemData = mw.loadData('Module:Items/data')
local ItemData = mw.loadData('Module:Items/data')
local SkillData = mw.loadData('Module:Skills/data')
local Constants = mw.loadData('Module:Constants/data')


local Constants = require('Module:Constants')
local Shared = require('Module:Shared')
local Shared = require('Module:Shared')
local Icons = require('Module:Icons')
local Icons = require('Module:Icons')


p.EasterEggs = {'Amulet of Calculated Promotion', 'Clue Chasers Insignia', '8', 'Lemon'}
p.EasterEggs = {'Amulet of Calculated Promotion', 'Clue Chasers Insignia', '8', 'Lemon', 'Easter Egg', 'Abnormal Log', 'Red Herring', 'Cool Glasses'}
p.OtherShopItems = {'Cooking Gloves', 'Mining Gloves', 'Gem Gloves', 'Smithing Gloves', 'Thieving Gloves'}
p.OtherShopItems = {'Cooking Gloves', 'Mining Gloves', 'Gem Gloves', 'Smithing Gloves', 'Thieving Gloves'}
--This is hardcoded, so there's no easy way to scrape it. Hopefully it doesn't change
--This is hardcoded, so there's no easy way to scrape it. Hopefully it doesn't change
p.GemTable = {["Topaz"] = {name = 'Topaz', id = 128, chance = 50},  
p.GemTable = {["Topaz"] = {name = 'Topaz', id = 128, chance = 50},
                   ["Sapphire"] = {name = "Sapphire", id = 129, chance = 17.5},  
                   ["Sapphire"] = {name = "Sapphire", id = 129, chance = 17.5},
                   ["Ruby"] = {name = "Ruby", id = 130, chance = 17.5},  
                   ["Ruby"] = {name = "Ruby", id = 130, chance = 17.5},
                   ["Emerald"] = {name = "Emerald", id = 131, chance = 10},  
                   ["Emerald"] = {name = "Emerald", id = 131, chance = 10},
                   ["Diamond"] = {name = "Diamond", id = 132, chance = 5}}
                   ["Diamond"] = {name = "Diamond", id = 132, chance = 5}}
--The base chance to receive a gem while mining
--The base chance to receive a gem while mining
Line 27: Line 25:
p.junkCount = 8
p.junkCount = 8
--Items (aside from bars & gems) which can be created via Alt Magic
--Items (aside from bars & gems) which can be created via Alt Magic
local AltMagicProducts = {'Rune Essence', 'Bones', 'Holy Dust'}
p.AltMagicProducts = {'Rune Essence', 'Bones', 'Holy Dust'}
--The kinds of gloves with cost & charges
--The kinds of gloves with cost & charges
p.GloveTable = {['Cooking Gloves'] = {cost=50000, charges=500},
p.GloveTable = {['Cooking Gloves'] = {cost=50000, charges=500},
Line 56: Line 54:
   local result = 'p.specialFishWt = '..totalWt..'\r\n'
   local result = 'p.specialFishWt = '..totalWt..'\r\n'
   result = result..'p.specialFishLoot = {'..table.concat(lootArray, ', ')..'}'
   result = result..'p.specialFishLoot = {'..table.concat(lootArray, ', ')..'}'
  return result
end
function p.getSpecialAttackByID(ID)
  local result = Shared.clone(ItemData.SpecialAttacks[ID + 1])
  if result ~= nil then
    result.id = ID
  end
   return result
   return result
end
end
Line 107: Line 97:
   local result = item[StatName]
   local result = item[StatName]
   --Special Overrides:
   --Special Overrides:
   if StatName == 'stabAttackBonus' then
  -- Equipment stats first
    if item.attackBonus == nil then  
   if Shared.contains(ItemData.EquipmentStatKeys, StatName) and item.equipmentStats ~= nil then
      result = nil
     result = item.equipmentStats[StatName]
     else
   elseif StatName == 'isTwoHanded' then
      result = item.attackBonus[1]
     if item.validSlots ~= nil and item.occupiesSlots ~= nil then
    end
       result = Shared.contains(item.validSlots, 'Weapon') and Shared.contains(item.occupiesSlots, 'Shield')
   elseif StatName == 'slashAttackBonus' then
     if item.attackBonus == nil then  
       result = nil
     else
     else
       result = item.attackBonus[2]
       result = false
     end
     end
   elseif StatName == 'blockAttackBonus' then
   elseif string.find(StatName, '^(.+)LevelRequired$') ~= nil and item.equipRequirements ~= nil and item.equipRequirements.Level ~= nil then
     if item.attackBonus == nil then  
    local skillName = Shared.titleCase(string.match(StatName, '^(.+)LevelRequired$'))
       result = nil
     if skillName ~= nil then
    else
       local skillID = Constants.getSkillID(skillName)
      result = item.attackBonus[3]
      if skillID ~= nil then
        result = item.equipRequirements.Level[skillID]
      end
     end
     end
   elseif StatName == 'attackType' then
   elseif StatName == 'attackType' then
Line 132: Line 121:
   elseif StatName == 'completionReq' then
   elseif StatName == 'completionReq' then
     if item.ignoreCompletion == nil or not item.ignoreCompletion then
     if item.ignoreCompletion == nil or not item.ignoreCompletion then
       return 'Yes'
       result = 'Yes'
     else
     else
       return 'No'
       result = 'No'
     end
     end
  elseif StatName == 'slayerBonusXP' then
    return p._getItemModifier(item, 'increasedSkillXP', 'Slayer', false)
   end
   end
   if result == nil and ZeroIfNil then result = 0 end
   if result == nil and ZeroIfNil then result = 0 end
Line 149: Line 140:
   local item = p.getItem(ItemName)
   local item = p.getItem(ItemName)
   if item == nil then
   if item == nil then
     return "ERROR: No item named "..ItemName.." exists in the data module"
     return "ERROR: No item named "..ItemName.." exists in the data module[[Category:Pages with script errors]]"
   end
   end
   local result = p._getItemStat(item, StatName, ZeroIfNil)
   local result = p._getItemStat(item, StatName, ZeroIfNil)
Line 156: Line 147:
end
end


function p._getWeaponAttackType(item)
--Gets the value of a given modifier for a given item
   if item.type == 'Weapon' then
--asString is false by default, when true it writes the full bonus text
     return Icons.Icon({'Melee', nolink='true'})
function p._getItemModifier(item, modifier, skill, asString)
   elseif item.type == 'Ranged Weapon' then
   if asString == nil then asString = false end
     return Icons.Icon({'Ranged', type='skill', nolink='true'})
  if skill == '' then
   elseif item.type == 'Magic Staff' or item.type == 'Magic Wand' then
     skill = nil
     return Icons.Icon({'Magic', type='skill', nolink='true'})
   elseif type(skill) == 'string' then
     skill = Constants.getSkillID(skill)
  end
 
  local result = 0
 
   if item.modifiers ~= nil and item.modifiers[modifier] ~= nil then
    if type(item.modifiers[modifier]) == 'table' then
      for i, subVal in Shared.skpairs(item.modifiers[modifier]) do
        if subVal[1] == skill then
          result = subVal[2]
          break
        end
      end
    else
      result = item.modifiers[modifier]
    end
  end
 
  if asString then
     if skill ~= nil then
      return Constants._getModifierText(modifier, {skill, result})
    else
      return Constants._getModifierText(modifier, result)
    end
   else
   else
     return "Invalid"
     return result
   end
   end
end
end


function p.hasCombatStats(item)
  if item.isEquipment or (item.validSlots == nil and item.equipmentStats ~= nil) then
    -- Ensure at least one stat has a non-zero value
    for statName, statVal in pairs(item.equipmentStats) do
      if statVal ~= 0 then return true end
    end
  end
  return false
end
function p.getItemModifier(frame)
  local itemName = frame.args ~= nil and frame.args[1] or frame[1]
  local modName = frame.args ~= nil and frame.args[2] or frame[2]
  local skillName = frame.args ~= nil and frame.args[3] or frame[3]
  local asString = frame.args ~= nil and frame.args[4] or frame[4]
  if asString ~= nil then
    if string.upper(asString) == 'FALSE' then
    asString = false
    else
    asString = true
    end
  end
  local item = p.getItem(itemName)
  if item == nil then
    return "ERROR: No item named "..itemName.." exists in the data module[[Category:Pages with script errors]]"
  end
  return p._getItemModifier(item, modName, skillName, asString)
end
function p._getWeaponAttackType(item)
  if item.isEquipment == true and (item.validSlots ~= nil and Shared.contains(item.validSlots, 'Weapon')) or
  (item.occupiesSlots ~= nil  and Shared.contains(item.occupiesSlots, 'Weapon')) then
    if Shared.contains({'melee', 'ranged', 'magic'}, item.attackType) then
      local iconType = item.attackType ~= 'melee' and 'skill' or nil
      return Icons.Icon({Shared.titleCase(item.attackType), type=iconType, nolink='true'})
    end
  end
  return 'Invalid'
end


function p.getWeaponAttackType(frame)
function p.getWeaponAttackType(frame)
Line 173: Line 229:
   local item = p.getItem(itemName)
   local item = p.getItem(itemName)
   if item == nil then
   if item == nil then
     return "ERROR: No item named "..ItemName.." exists in the data module"
     return "ERROR: No item named "..ItemName.." exists in the data module[[Category:Pages with script errors]]"
   end
   end
   return p._getWeaponAttackType(item)
   return p._getWeaponAttackType(item)
Line 182: Line 238:
   local tiers = {'I', 'II', 'III', 'IV'}
   local tiers = {'I', 'II', 'III', 'IV'}


   local result = '{| class="wikitable"'
   local resultPart = {}
   result = result..'\r\n!Potion!!Tier!!Charges!!Effect'
  table.insert(resultPart, '{| class="wikitable"')
   table.insert(resultPart, '\r\n!Potion!!Tier!!Charges!!Effect')


   local tier1potion = p.getItem(potionName..' I')
   local tier1potion = p.getItem(potionName..' I')
  if tier1potion == nil then
    return 'ERROR: No potion named "' .. potionName .. '" was found[[Category:Pages with script errors]]'
  end
   for i, tier in pairs(tiers) do
   for i, tier in pairs(tiers) do
     local tierName = potionName..' '..tier
     local tierName = potionName..' '..tier
     local potion = p.getItemByID(tier1potion.id + i - 1)
     local potion = p.getItemByID(tier1potion.id + i - 1)
     if potion ~= nil then
     if potion ~= nil then
       result = result..'\r\n|-'
       table.insert(resultPart, '\r\n|-')
       result = result..'\r\n|'..Icons.Icon({tierName, type='item', notext='true', size='60'})
       table.insert(resultPart, '\r\n|'..Icons.Icon({tierName, type='item', notext=true, size='60'}))
       result = result..'||'..'[['..tierName..'|'..tier..']]'
       table.insert(resultPart, '||'..Icons.Icon({tierName, tier, type='item', noicon=true}))
       result = result..'||'..potion.potionCharges..'||'..potion.description
       table.insert(resultPart, '||'..potion.potionCharges..'||'..potion.description)
     end
     end
   end
   end


   result = result..'\r\n|}'
   table.insert(resultPart, '\r\n|}')
   return result
   return table.concat(resultPart)
end
 
function p.getEquipmentSlotName(id)
  for slotName, i in Shared.skpairs(Constants.equipmentSlot) do
    if i == id then
      return slotName
    end
  end
  return 'Invalid'
end
end


function p._getOtherItemBoxText(item)
function p._getOtherItemBoxText(item)
   result = ''
   resultPart = {}
   --For equipment, show the slot they go in
   --For equipment, show the slot they go in
   if item.equipmentSlot ~= nil then
   if item.validSlots ~= nil then
     result = result.."\r\n|-\r\n|'''Equipment Slot:''' "..p.getEquipmentSlotName(item.equipmentSlot)
     table.insert(resultPart, "\r\n|-\r\n|'''Equipment Slot:''' "..table.concat(item.validSlots, ', '))
    if item.isPassiveItem then
      result = result..', Passive'
    end
   end
   end
   --For weapons with a special attack, show the details
   --For weapons with a special attack, show the details
   if item.hasSpecialAttack then
   if item.hasSpecialAttack then
     local spAtt = p.getSpecialAttackByID(item.specialAttackID)
     table.insert(resultPart, "\r\n|-\r\n|'''Special Attack:'''")
    result = result.."\r\n|-\r\n|'''Special Attack:'''"
     for i, spAtt in ipairs(item.specialAttacks) do
     result = result..'\r\n* '..spAtt.chance..'% chance for '..spAtt.name..':'
      table.insert(resultPart, '\r\n* ' .. spAtt.defaultChance .. '% chance for ' .. spAtt.name .. ':')
    result = result..'\r\n** '..spAtt.description
      table.insert(resultPart, '\r\n** ' .. spAtt.description)
    end
   end
   end
   --For potions, show the number of charges
   --For potions, show the number of charges
   if item.potionCharges ~= nil then
   if item.potionCharges ~= nil then
     result = result.."\r\n|-\r\n|'''Charges:''' "..item.potionCharges
     table.insert(resultPart, "\r\n|-\r\n|'''Charges:''' "..item.potionCharges)
   end
   end
   --For food, show how much it heals for
   --For food, show how much it heals for
   if item.healsFor ~= nil then
   if item.healsFor ~= nil then
     result = result.."\r\n|-\r\n|'''Heals for:''' "..Icons.Icon({"Hitpoints", type="skill", notext="true"})..' '..(item.healsFor * 10)
     table.insert(resultPart, "\r\n|-\r\n|'''Heals for:''' "..Icons.Icon({"Hitpoints", type="skill", notext="true"})..' '..(item.healsFor * 10))
   end
   end
   --For Prayer Points, show how many you get
   --For Prayer Points, show how many you get
   if item.prayerPoints ~= nil then
   if item.prayerPoints ~= nil then
     result = result.."\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
   end
   return result
  --For items with modifiers, show what those are
  if item.modifiers ~= nil and Shared.tableCount(item.modifiers) > 0 then
    table.insert(resultPart, "\r\n|-\r\n|'''Modifiers:'''\r\n"..Constants.getModifiersText(item.modifiers, true))
  end
   return table.concat(resultPart)
end
end


Line 245: Line 298:
   local item = p.getItem(itemName)
   local item = p.getItem(itemName)
   local asList = false
   local asList = false
   if frame.args ~= nil then  
   if frame.args ~= nil then
     asList = frame.args.asList ~= nil and frame.args.asList ~= '' and frame.args.asList ~= 'false'
     asList = frame.args.asList ~= nil and frame.args.asList ~= '' and frame.args.asList ~= 'false'
   end
   end
   if item == nil then
   if item == nil then
     return "ERROR: No item named "..itemName.." exists in the data module"
     return "ERROR: No item named "..itemName.." exists in the data module[[Category:Pages with script errors]]"
   end
   end


Line 256: Line 309:


function p._getItemCategories(item)
function p._getItemCategories(item)
   local result = ''
   local resultPart = {}
   if item.category ~= nil then result = result..'[[Category:'..item.category..']]' end
   if item.category ~= nil then table.insert(resultPart, '[[Category:'..item.category..']]') end
   if item.type ~= nil then result = result..'[[Category:'..item.type..']]' end
   if item.type ~= nil then table.insert(resultPart, '[[Category:'..item.type..']]') end
   if item.tier ~= nil then result = result..'[[Category:'..Shared.titleCase(item.tier)..' '..item.type..']]' end
   if item.tier ~= nil then table.insert(resultPart, '[[Category:'..Shared.titleCase(item.tier)..' '..item.type..']]') end
   if item.hasSpecialAttack then result = result..'[[Category:Items With Special Attacks]]' end
   if item.hasSpecialAttack then table.insert(resultPart, '[[Category:Items With Special Attacks]]') end
   if item.isPassiveItem then result = result..'[[Category:Passive Items]]' end
   if item.validSlots ~= nil then
   if item.chanceToDoubleLoot ~= nil and item.chanceToDoubleLoot > 0 then result = result..'[[Category:Double Loot Chance Items]]' end
    local slotRemap = {
   return result
      ['Passive'] = 'Passive Items',
      ['Summon1'] = 'Summoning Familiars',
      ['Summon2'] = ''
    }
    for i, slotName in ipairs(item.validSlots) do
      local slotRemapName = slotName
      if slotRemap[slotName] ~= nil then slotRemapName = slotRemap[slotName] end
      if slotRemapName ~= '' then table.insert(resultPart, '[[Category:' .. slotRemapName .. ']]') end
    end
  end
   if item.modifiers ~= nil then
    local modsDL = {
      'increasedChanceToDoubleLootCombat',
      'decreasedChanceToDoubleLootCombat',
      'increasedChanceToDoubleLootThieving',
      'decreasedChanceToDoubleLootThieving',
      'increasedChanceToDoubleItemsGlobal',
      'decreasedChanceToDoubleItemsGlobal'
    }
    for modName, val in pairs(item.modifiers) do
      if Shared.contains(modsDL, modName) then
        table.insert(resultPart, '[[Category:Double Loot Chance Items]]')
        break
      end
    end
  end
   return table.concat(resultPart)
end
end


Line 270: Line 349:
   local item = p.getItem(itemName)
   local item = p.getItem(itemName)
   if item == nil then
   if item == nil then
     return "ERROR: No item named "..itemName.." exists in the data module"
     return "ERROR: No item named "..itemName.." exists in the data module[[Category:Pages with script errors]]"
   end
   end


Line 279: Line 358:
   local skillName = frame.args ~= nil and frame.args[1] or frame
   local skillName = frame.args ~= nil and frame.args[1] or frame
   local cape = p.getItem(skillName..' Skillcape')
   local cape = p.getItem(skillName..' Skillcape')
   local result = '{| class="wikitable"\r\n'
   local resultPart = {}
   result = result..'!Skillcape!!Name!!Effect'
  table.insert(resultPart, '{| class="wikitable"\r\n')
   result = result..'\r\n|-\r\n|'..Icons.Icon({cape.name, type='item', size='60', notext=true})
   table.insert(resultPart, '!Skillcape!!Name!!Effect')
  result = result..'||[['..cape.name..']]||'..cape.description
   table.insert(resultPart, '\r\n|-\r\n|'..Icons.Icon({cape.name, type='item', size='60', notext=true}))
  result = result..'\r\n|}'
   table.insert(resultPart, '||'..Icons.Icon({cape.name, type='item', noicon=true})..'||'..cape.description)
  return result
   table.insert(resultPart, '\r\n|}')
end
   return table.concat(resultPart)
 
function p.getShopSkillcapeTable()
   local result = ''
 
  local capeList = {}
  for i, item in pairs(ItemData.Items) do
    if Shared.contains(item.name, 'Skillcape') or item.name == 'Cape of Completion' then
      table.insert(capeList, item)
    end
  end
 
  result = result..'\r\n{|class="wikitable sortable"'
  result = result..'\r\n!colspan="2" style="width:200px"|Cape'
  result = result..'!!Description!!style="width:120px"|Price'
 
  --Sort the table by cost and then name
  table.sort(capeList, function(a, b)
                        if a.buysFor == b.buysFor then
                          return a.name < b.name
                        else
                          return a.sellsFor < b.buysFor
                        end
                      end)
  for i, thisItem in pairs(capeList) do
    result = result..'\r\n|-\r\n|'..Icons.Icon({thisItem.name, type='item', size='50', notext=true})
    result = result..'||[['..thisItem.name..']]'
    result = result..'\r\n||'..thisItem.description
    result = result..'||style="text-align:left" data-sort-value="'..thisItem.buysFor..'"'
    result = result..'|'..Icons.GP(thisItem.buysFor)
   end
  result = result..'\r\n|}'
 
   return result
end
end


function p.getItemGrid(frame)
function p.getItemGrid(frame)
   result = '{|'
   local resultPart = {}
  table.insert(resultPart, '{|')
   for i, item in Shared.skpairs(ItemData.Items) do
   for i, item in Shared.skpairs(ItemData.Items) do
     if i % 17 == 1 then
     if i % 17 == 1 then
       result = result..'\r\n|-\r\n|'
       table.insert(resultPart, '\r\n|-\r\n|')
     else
     else
       result = result..'||'
       table.insert(resultPart, '||')
     end
     end
     result = result..'style="padding:3px"|'..Icons.Icon({item.name, type='item', notext=true, size='40'})
     table.insert(resultPart, 'style="padding:3px"|'..Icons.Icon({item.name, type='item', notext=true, size='40'}))
   end
   end
   result = result..'\r\n|}'
   table.insert(resultPart, '\r\n|}')
   return result
   return table.concat(resultPart)
end
end


function p.getSpecialAttackTable(frame)
function p.getSpecialAttackTable(frame)
   local spAttTable = {}
   local spAttTable = {}
 
 
   for i, item in Shared.skpairs(ItemData.Items) do
   for i, item in Shared.skpairs(ItemData.Items) do
     if item.hasSpecialAttack then
     if item.hasSpecialAttack then
       if spAttTable[item.specialAttackID] == nil then spAttTable[item.specialAttackID] = {sortName=item.name, Icons = {}} end
       for i, spAtt in ipairs(item.specialAttacks) do
      table.insert(spAttTable[item.specialAttackID].Icons, Icons.Icon({item.name, type='item'}))
        if spAttTable[spAtt.id] == nil then spAttTable[spAtt.id] = {sortName=item.name, defn = spAtt, Icons = {}} end
        table.insert(spAttTable[spAtt.id].Icons, Icons.Icon({item.name, type='item'}))
      end
     end
     end
   end
   end


   local result = '{|class="wikitable sortable stickyHeader"'
   local resultPart = {}
   result = result..'\r\n|-class="headerRow-0"'
  table.insert(resultPart, '{|class="wikitable sortable stickyHeader"')
   result = result..'\r\n!style="min-width:180px"|Weapon(s)!!Name!!Chance!!Effect'
   table.insert(resultPart, '\r\n|-class="headerRow-0"')
   table.insert(resultPart, '\r\n!style="min-width:180px"|Weapon(s)!!Name!!Chance!!Effect')
   for i, spAttData in Shared.skpairs(spAttTable) do
   for i, spAttData in Shared.skpairs(spAttTable) do
     local spAtt = p.getSpecialAttackByID(i)
     local spAtt = spAttData.defn
     table.sort(spAttData.Icons, function(a, b) return a < b end)
     table.sort(spAttData.Icons, function(a, b) return a < b end)
     result = result..'\r\n|-'
     table.insert(resultPart, '\r\n|-')
     result = result..'\r\n|data-sort-value="'..spAttData.sortName..'"|'..table.concat(spAttData.Icons, '<br/>')
     table.insert(resultPart, '\r\n|data-sort-value="'..spAttData.sortName..'"|'..table.concat(spAttData.Icons, '<br/>'))
     result = result..'||'..spAtt.name..'||data-sort-value="'..spAtt.chance..'"|'..spAtt.chance..'%'
     table.insert(resultPart, '||'..spAtt.name..'||data-sort-value="'..spAtt.defaultChance..'"|'..spAtt.defaultChance..'%')
     result = result..'||'..spAtt.description
     table.insert(resultPart, '||'..spAtt.description)
   end
   end
   result = result..'\r\n|}'
   table.insert(resultPart, '\r\n|}')


   return result
   return table.concat(resultPart)
end
end


return p
return p