Module:Items

From Melvor Idle
Revision as of 22:11, 1 March 2021 by Falterfire (talk | contribs) (Bolding category names from getOtherItemBoxText)
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Lua module for generating various item tables. Pulls data from Module:GameData/data


--This module contains all sorts of functions for getting data on items
--Several functions related to use tables can be found at Module:Items/UseTables
--Functions related to source tables can be found at Module:Items/SourceTables
--Other functions moved to Module:Items/ComparisonTables

local p = {}

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

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

p.EasterEggs = {'Amulet of Calculated Promotion', 'Clue Chasers Insignia', '8', 'Lemon'}
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
p.GemTable = {["Topaz"] = {name = 'Topaz', id = 128, chance = 50}, 
                  ["Sapphire"] = {name = "Sapphire", id = 129, chance = 17.5}, 
                  ["Ruby"] = {name = "Ruby", id = 130, chance = 17.5}, 
                  ["Emerald"] = {name = "Emerald", id = 131, chance = 10}, 
                  ["Diamond"] = {name = "Diamond", id = 132, chance = 5}}
--The base chance to receive a gem while mining
p.GemChance = .01
--The number of different fishing junk items
p.junkCount = 8
--Items (aside from bars & gems) which can be created via Alt Magic
local AltMagicProducts = {'Rune Essence', 'Bones', 'Holy Dust'}
--The kinds of gloves with cost & charges
p.GloveTable = {['Cooking Gloves'] = {cost=50000, charges=500},
                    ['Mining Gloves'] = {cost=75000, charges=500},
                    ['Smithing Gloves'] = {cost=100000, charges=500},
                    ['Thieving Gloves'] = {cost=100000, charges=500},
                    ['Gem Gloves'] = {cost=500000, charges=2000}}


p.specialFishWt = 6722
p.specialFishLoot = {{128, 2000}, {129, 1600}, {130, 1400}, {131, 1000}, {132, 400}, {667, 10}, {668, 10}, {902, 1}, {670, 1}, {669, 50}, {120, 250}}

function p.buildSpecialFishingTable()
  --This shouldn't ever be included in a page
  --This is for generating the above 'specialFishLoot' variable if it ever needs to change
  --To re-run, edit the module, type in "console.log(p.buildSpecialFishingTable())" and copy+paste the result as the new value of the variable
  --Also gives you the total fishing weight for saving time later
  local lootArray = {}
  local totalWt = 0

  for i, item in pairs(ItemData.Items) do
    if item.fishingCatchWeight ~= nil then
      totalWt = totalWt + item.fishingCatchWeight
      table.insert(lootArray, '{'..(i - 1)..', '..item.fishingCatchWeight..'}')
    end
  end

  local result = 'p.specialFishWt = '..totalWt..'\r\n'
  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
end

function p.getItemByID(ID)
  local result = Shared.clone(ItemData.Items[ID + 1])
  if result ~= nil then
    result.id = ID
  end
  return result
end

function p.getItem(name)
  local result = nil
  name = string.gsub(name, "%%27", "'")
  name = string.gsub(name, "'", "'")
  name = string.gsub(name, "'", "'")
  for i, item in pairs(ItemData.Items) do
    local itemName = string.gsub(item.name, '#', '')
    if(name == itemName) then
      result = Shared.clone(item)
      --Make sure every item has an id, and account for Lua being 1-index
      result.id = i - 1
      break
    end
  end
  return result
end

function p.getItems(checkFunc)
  local result = {}
  for i, item in pairs(ItemData.Items) do
    if checkFunc(item) then
      local newItem = Shared.clone(item)
      newItem.id = i - 1
      table.insert(result, newItem)
    end
  end
  return result
end

function p._getItemStat(item, StatName, ZeroIfNil)
  local result = item[StatName]
  --Special Overrides:
  if StatName == 'stabAttackBonus' then
    if item.attackBonus == nil then 
      result = nil
    else
      result = item.attackBonus[1]
    end
  elseif StatName == 'slashAttackBonus' then
    if item.attackBonus == nil then 
      result = nil
    else
      result = item.attackBonus[2]
    end
  elseif StatName == 'blockAttackBonus' then
    if item.attackBonus == nil then 
      result = nil
    else
      result = item.attackBonus[3]
    end
  elseif StatName == 'attackType' then
    result = p._getWeaponAttackType(item)
  elseif StatName == 'description' then
    result = item.description
    if result == nil or result == '' then result = 'No Description' end
  elseif StatName == 'completionReq' then
    if item.ignoreCompletion == nil or not item.ignoreCompletion then
      return 'Yes'
    else
      return 'No'
    end
  end
  if result == nil and ZeroIfNil then result = 0 end
  return result
end

function p.getItemStat(frame)
  local args = frame.args ~= nil and frame.args or frame
  local ItemName = args[1]
  local StatName = args[2]
  local ZeroIfNil = args.ForceZero ~= nil and args.ForceZero ~= '' and args.ForceZero ~= 'false'
  local formatNum = args.formatNum ~= nil and args.formatNum ~= '' and args.formatNum ~= 'false'
  local item = p.getItem(ItemName)
  if item == nil then
    return "ERROR: No item named "..ItemName.." exists in the data module"
  end
  local result = p._getItemStat(item, StatName, ZeroIfNil)
  if formatNum then result = Shared.formatnum(result) end
  return result
end

function p._getWeaponAttackType(item)
  if item.type == 'Weapon' then
    return Icons.Icon({'Melee', nolink='true'})
  elseif item.type == 'Ranged Weapon' then
    return Icons.Icon({'Ranged', type='skill', nolink='true'})
  elseif item.type == 'Magic Staff' or item.type == 'Magic Wand' then
    return Icons.Icon({'Magic', type='skill', nolink='true'})
  else
    return "Invalid"
  end
end


function p.getWeaponAttackType(frame)
  local itemName = frame.args ~= nil and frame.args[1] or frame
  local item = p.getItem(itemName)
  if item == nil then
    return "ERROR: No item named "..ItemName.." exists in the data module"
  end
  return p._getWeaponAttackType(item)
end

function p.getPotionTable(frame)
  local potionName = frame.args ~= nil and frame.args[1] or frame
  local tiers = {'I', 'II', 'III', 'IV'}

  local result = '{| class="wikitable"'
  result = result..'\r\n!Potion!!Tier!!Charges!!Effect'

  local tier1potion = p.getItem(potionName..' I')
  for i, tier in pairs(tiers) do
    local tierName = potionName..' '..tier
    local potion = p.getItemByID(tier1potion.id + i - 1)
    if potion ~= nil then
      result = result..'\r\n|-'
      result = result..'\r\n|'..Icons.Icon({tierName, type='item', notext='true', size='60'})
      result = result..'||'..'[['..tierName..'|'..tier..']]'
      result = result..'||'..potion.potionCharges..'||'..potion.description
    end
  end

  result = result..'\r\n|}'
  return result
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

function p._getOtherItemBoxText(item)
  result = ''
  --For equipment, show the slot they go in
  if item.equipmentSlot ~= nil then
    result = result.."\r\n|-\r\n|'''Equipment Slot:''' "..p.getEquipmentSlotName(item.equipmentSlot)
  end
  --For weapons with a special attack, show the details
  if item.hasSpecialAttack then
    local spAtt = p.getSpecialAttackByID(item.specialAttackID)
    result = result.."\r\n|-\r\n|'''Special Attack:'''"
    result = result..'\r\n* '..spAtt.chance..'% chance for '..spAtt.name..':'
    result = result..'\r\n** '..spAtt.description
  end
  --For potions, show the number of charges
  if item.potionCharges ~= nil then
    result = result.."\r\n|-\r\n|'''Charges:''' "..item.potionCharges
  end
  --For food, show how much it heals for
  if item.healsFor ~= nil then
    result = result.."\r\n|-\r\n|'''Heals for:''' "..Icons.Icon({"Hitpoints", type="skill", notext="true"})..' '..(item.healsFor * 10)
  end
  --For Prayer Points, show how many you get
  if item.prayerPoints ~= nil then
    result = result.."\r\n|-\r\n|'''"..Icons.Icon({'Prayer', type='skill'}).." Points:''' "..item.prayerPoints
  end
  return result
end

function p.getOtherItemBoxText(frame)
  local itemName = frame.args ~= nil and frame.args[1] or frame
  local item = p.getItem(itemName)
  local asList = false
  if frame.args ~= nil then 
    asList = frame.args.asList ~= nil and frame.args.asList ~= '' and frame.args.asList ~= 'false'
  end
  if item == nil then
    return "ERROR: No item named "..itemName.." exists in the data module"
  end

  return p._getOtherItemBoxText(item, asList)
end

function p._getItemCategories(item)
  local result = ''
  if item.category ~= nil then result = result..'[[Category:'..item.category..']]' end
  if item.type ~= nil then result = result..'[[Category:'..item.type..']]' end
  if item.tier ~= nil then result = result..'[[Category:'..Shared.titleCase(item.tier)..' '..item.type..']]' end
  if item.hasSpecialAttack then result = result..'[[Category:Items With Special Attacks]]' end
  if item.isPassiveItem then result = result..'[[Category:Passive Items]]' end
  if item.chanceToDoubleLoot ~= nil and item.chanceToDoubleLoot > 0 then result = result..'[[Category:Double Loot Chance Items]]' end
  return result
end

function p.getItemCategories(frame)
  local itemName = frame.args ~= nil and frame.args[1] or frame
  local item = p.getItem(itemName)
  if item == nil then
    return "ERROR: No item named "..itemName.." exists in the data module"
  end

  return p._getItemCategories(item)
end

function p.getSkillcapeTable(frame)
  local skillName = frame.args ~= nil and frame.args[1] or frame
  local cape = p.getItem(skillName..' Skillcape')
  local result = '{| class="wikitable"\r\n'
  result = result..'!Skillcape!!Name!!Effect'
  result = result..'\r\n|-\r\n|'..Icons.Icon({cape.name, type='item', size='60', notext=true})
  result = result..'||[['..cape.name..']]||'..cape.description
  result = result..'\r\n|}'
  return result
end

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

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

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

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

  return result
end

return p