Module:Items/SourceTables: Difference between revisions

Resolve issue with dungeon sources when dungeons had more than one reward. Also fix indentation oddities
(Remove redundant item source overrides)
(Resolve issue with dungeon sources when dungeons had more than one reward. Also fix indentation oddities)
Line 152: Line 152:
--If this is a perfect item, need to find the original
--If this is a perfect item, need to find the original
if item2.perfectItem == item.id and item2.recipeRequirements ~= nil then
if item2.perfectItem == item.id and item2.recipeRequirements ~= nil then
for j, reqSet in pairs(item2.recipeRequirements) do
for j, reqSet in pairs(item2.recipeRequirements) do
skill = 'Cooking'
skill = 'Cooking'
lvl = item2.cookingLevel
lvl = item2.cookingLevel
xp = item2.cookingXP
xp = item2.cookingXP
req = reqSet
req = reqSet
qty = item2.cookingQty
qty = item2.cookingQty
time = item2.cookingInterval / 1000
time = item2.cookingInterval / 1000
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
table.insert(tables, p.buildCreationTable(skill, lvl, xp, req, qty, time))
end
end
end
end
end
end
end
end
Line 174: Line 174:
local item = Items.getItemByID(cost.id)
local item = Items.getItemByID(cost.id)
if item.type == 'Shard' then
if item.type == 'Shard' then
table.insert(ShardCostArray, Icons.Icon({item.name, type='item', notext=true, qty=cost.qty}))
table.insert(ShardCostArray, Icons.Icon({item.name, type='item', notext=true, qty=cost.qty}))
end
end
end
end
Line 188: Line 188:
local item = Items.getItemByID(cost.id)
local item = Items.getItemByID(cost.id)
if item.type ~= 'Shard' then
if item.type ~= 'Shard' then
  local sellPrice = math.max(item.sellsFor, 20)
local sellPrice = math.max(item.sellsFor, 20)
  table.insert(nonShardArray, Icons.Icon({item.name, type='item', notext=true, qty=math.max(1, math.floor(recipeGPCost / sellPrice))}))
table.insert(nonShardArray, Icons.Icon({item.name, type='item', notext=true, qty=math.max(1, math.floor(recipeGPCost / sellPrice))}))
end
end
else
else
if cost.id == -4 then
if cost.id == -4 then
  table.insert(nonShardArray, Icons.GP(recipeGPCost))
table.insert(nonShardArray, Icons.GP(recipeGPCost))
elseif cost.id == -5 then
elseif cost.id == -5 then
  table.insert(nonShardArray, Icons.SC(recipeGPCost))
table.insert(nonShardArray, Icons.SC(recipeGPCost))
end
end
end
end
Line 286: Line 286:
end
end
if gpCost ~= nil and gpCost > 0 then
if gpCost ~= nil and gpCost > 0 then
table.insert(resultPart, '<br/>')
table.insert(resultPart, '<br/>')
table.insert(resultPart, Icons.GP(gpCost))
table.insert(resultPart, Icons.GP(gpCost))
end
end
else
else
table.insert(resultPart, req)
table.insert(resultPart, req)
end
end
end
end
Line 322: Line 322:
--First up: Can we kill somebody and take theirs?
--First up: Can we kill somebody and take theirs?
local killStrPart = {}
local killStrPart = {}
local dungeonStrPart = {}
for i, monster in ipairs(MonsterData.Monsters) do
for i, monster in ipairs(MonsterData.Monsters) do
local isDrop, isBones = false, false
local isDrop = false
if monster.bones == item.id and Monsters.getMonsterBones(monster) ~= nil then
if monster.bones == item.id and Monsters.getMonsterBones(monster) ~= nil then
-- Item is a bone, and is either a shard from God dungeons or dropped by a non-boss monster with a loot table
-- Item is a bone, and is either a shard from God dungeons or dropped by a non-boss monster with a loot table
isDrop = true
isDrop = true
isBones = true
elseif monster.lootTable ~= nil then
elseif monster.lootTable ~= nil then
-- If the monster has a loot table, check if the item we are looking for is in there
-- If the monster has a loot table, check if the item we are looking for is in there
-- Dungeon exclusive monsters don't count as they are either:
for j, loot in ipairs(monster.lootTable) do
--  - A monster before the boss, which doesn't drop anything except shards (checked above)
    if loot[1] == item.id then
--  - A boss monster, whose drops are accounted for in data from Areas instead
  isDrop = true
for j, loot in ipairs(monster.lootTable) do
  break
if loot[1] == item.id and not Monsters._isDungeonOnlyMonster(monster) then
  end
isDrop = true
break
end
end
end
end
end
if isDrop then
if isDrop then
if not isBones and Monsters._isDungeonOnlyMonster(monster) then
-- Item drops when the monster is killed
-- For dungeon exclusive monsters, loot is only rolled when they are the last
table.insert(killStrPart, Icons.Icon({monster.name, type='monster', notext=true}))
-- monster within that dungeon (unless it is a shard)
end
if monster.isBoss then
end
local areaList = Areas.getMonsterAreas(monster.id)
-- Is the item dropped from any dungeon?
for k, area in ipairs(areaList) do
local dungeonStrPart = {}
if area.type == 'dungeon' and area.monsters[#area.monsters] == monster.id then
local dungeonList = Areas.getAreas(function(area) return area.type == 'dungeon' and type(area.rewards) == 'table' and Shared.contains(area.rewards, item.id) end)
table.insert(dungeonStrPart, Icons.Icon({area.name, type='dungeon', notext=true}))
if dungeonList ~= nil then
end
for i, dungeon in ipairs(dungeonList) do
end
table.insert(dungeonStrPart, Icons.Icon({dungeon.name, type='dungeon', notext=true}))
end
else
-- Item is not an end of dungeon reward, and drops when the monster is killed
table.insert(killStrPart, Icons.Icon({monster.name, type='monster', notext=true}))
end
end
end
end
end
-- Is the item dropped from a cycle of the Impending Darkness event?
-- Is the item dropped from a cycle of the Impending Darkness event?
for i, eventItemID in ipairs(Areas.eventData.rewards) do
for i, eventItemID in ipairs(Areas.eventData.rewards) do
if item.id == eventItemID then
if item.id == eventItemID then
local dungPrefix = (i == Shared.tableCount(Areas.eventData.rewards) and '' or i .. ' ' .. (i == 1 and 'cycle' or 'cycles') .. ' of ')
local dungPrefix = (i == Shared.tableCount(Areas.eventData.rewards) and '' or i .. ' ' .. (i == 1 and 'cycle' or 'cycles') .. ' of ')
table.insert(dungeonStrPart, dungPrefix .. Icons.Icon({'Impending Darkness Event', type='dungeon', notext=true}))
table.insert(dungeonStrPart, dungPrefix .. Icons.Icon({'Impending Darkness Event', type='dungeon', notext=true}))
break
break
end
end
Line 390: Line 386:
count1 = count1 + 1
count1 = count1 + 1
if string.len(lootStr) > 0 then
if string.len(lootStr) > 0 then
  lootStr = lootStr..','
lootStr = lootStr..','
  --if count1 % 3 == 1 and count1 > 1 then lootStr = lootStr..'<br/>' end
--if count1 % 3 == 1 and count1 > 1 then lootStr = lootStr..'<br/>' end
  lootStr = lootStr..Icons.Icon({item2.name, type="item", notext="true"})
lootStr = lootStr..Icons.Icon({item2.name, type="item", notext="true"})
else
else
  lootStr = lootStr..'Opening: '..Icons.Icon({item2.name, type="item", notext="true"})
lootStr = lootStr..'Opening: '..Icons.Icon({item2.name, type="item", notext="true"})
end
end
end
end
Line 400: Line 396:
end
end
if item2.trimmedItemID == item.id then
if item2.trimmedItemID == item.id then
count2 = count2 + 1
count2 = count2 + 1
if string.len(upgradeStr) > 0 then
if string.len(upgradeStr) > 0 then
upgradeStr = upgradeStr..','
upgradeStr = upgradeStr..','
--if count2 % 3 == 1 and count2 > 1 then upgradeStr = upgradeStr..'<br/>' end
--if count2 % 3 == 1 and count2 > 1 then upgradeStr = upgradeStr..'<br/>' end
upgradeStr = upgradeStr..Icons.Icon({item2.name, type="item", notext="true"})
upgradeStr = upgradeStr..Icons.Icon({item2.name, type="item", notext="true"})
else
else
table.insert(categoryArray, '[[Category:Upgraded Items]]')
table.insert(categoryArray, '[[Category:Upgraded Items]]')
upgradeStr = upgradeStr..'Upgrading: '..Icons.Icon({item2.name, type="item", notext="true"})
upgradeStr = upgradeStr..'Upgrading: '..Icons.Icon({item2.name, type="item", notext="true"})
end
end
end
end
if item2.grownItemID == item.id then
if item2.grownItemID == item.id then
if string.len(growStr) > 0 then
if string.len(growStr) > 0 then
growStr = growStr..','..Icons.Icon({item2.name, type="item", notext="true"})
growStr = growStr..','..Icons.Icon({item2.name, type="item", notext="true"})
else
else
table.insert(categoryArray, '[[Category:Harvestable Items]]')
table.insert(categoryArray, '[[Category:Harvestable Items]]')
growStr = growStr..'Growing: '..Icons.Icon({item2.name, type="item", notext="true"})
growStr = growStr..'Growing: '..Icons.Icon({item2.name, type="item", notext="true"})
end
end
end
end
if item2.perfectItem == item.id and item2.cookingLevel ~= nil then
if item2.perfectItem == item.id and item2.cookingLevel ~= nil then
Line 574: Line 570:
--Also handling Signet Ring things here
--Also handling Signet Ring things here
if item.name == 'Gold Topaz Ring' then
if item.name == 'Gold Topaz Ring' then
table.insert(lineArray, 'Any non-combat action if not worn (Instead of '..Icons.Icon({"Signet Ring Half (a)", type="item"})..')')
table.insert(lineArray, 'Any non-combat action if not worn (Instead of '..Icons.Icon({"Signet Ring Half (a)", type="item"})..')')
table.insert(lineArray, 'Killing any monster if not worn (Instead of '..Icons.Icon({"Signet Ring Half (b)", type="item"})..')')
table.insert(lineArray, 'Killing any monster if not worn (Instead of '..Icons.Icon({"Signet Ring Half (b)", type="item"})..')')
elseif item.name == 'Signet Ring Half (a)' then
elseif item.name == 'Signet Ring Half (a)' then
table.insert(lineArray, 'Any non-combat action while wearing '..Icons.Icon({'Gold Topaz Ring', type='item'}))
table.insert(lineArray, 'Any non-combat action while wearing '..Icons.Icon({'Gold Topaz Ring', type='item'}))
elseif item.name == 'Signet Ring Half (b)' then
elseif item.name == 'Signet Ring Half (b)' then
table.insert(lineArray, 'Killing any monster while wearing '..Icons.Icon({'Gold Topaz Ring', type='item'}))
table.insert(lineArray, 'Killing any monster while wearing '..Icons.Icon({'Gold Topaz Ring', type='item'}))
Line 630: Line 626:
table.insert(rowPart, '\r\n|colspan="2" ')
table.insert(rowPart, '\r\n|colspan="2" ')
else
else
local fraction = Shared.fraction(weight, totalWeight)
local fraction = Shared.fraction(weight, totalWeight)
if Shared.contains(fraction, '%.') then
if Shared.contains(fraction, '%.') then
--If fraction contains decimals, something screwy happened so just show only percentage
--If fraction contains decimals, something screwy happened so just show only percentage
--(happens sometimes with the rare thieving items)
--(happens sometimes with the rare thieving items)
table.insert(rowPart, '\r\n|colspan="2" ')
table.insert(rowPart, '\r\n|colspan="2" ')
else
else
table.insert(rowPart, '\r\n|style="text-align: right;" data-sort-value="' .. chance .. '"| ' .. Shared.fraction(weight, totalWeight) .. '\r\n|')
table.insert(rowPart, '\r\n|style="text-align: right;" data-sort-value="' .. chance .. '"| ' .. Shared.fraction(weight, totalWeight) .. '\r\n|')
end
end
Line 664: Line 660:
totalWt = 1
totalWt = 1
elseif monster.lootTable ~= nil then
elseif monster.lootTable ~= nil then
-- If the monster has a loot table, check if the item we are looking for is in there
-- If the monster has a loot table, check if the item we are looking for is in there
-- Dungeon exclusive monsters don't count as they are either:
--  - A monster before the boss, which doesn't drop anything except shards (checked above)
--  - A boss monster, whose drops are accounted for in data from Areas instead
for j, loot in ipairs(monster.lootTable) do
for j, loot in ipairs(monster.lootTable) do
totalWt = totalWt + loot[2]
totalWt = totalWt + loot[2]
if loot[1] == item.id then
if loot[1] == item.id and not Monsters._isDungeonOnlyMonster(monster) then
wt = loot[2]
wt = loot[2]
qty = loot[3]
qty = loot[3]
Line 675: Line 674:
local lootChance = monster.lootChance ~= nil and monster.bones ~= item.id and monster.lootChance or 100
local lootChance = monster.lootChance ~= nil and monster.bones ~= item.id and monster.lootChance or 100


if wt > 0 and lootChance > 0 then
if wt > 0 and lootChance > 0 then
if not Shared.contains(item.name, 'Shard') and Monsters._isDungeonOnlyMonster(monster) then
-- Item drops when the monster is killed
-- For dungeon exclusive monsters, loot is only rolled when they are the last
table.insert(dropRows, {source = Icons.Icon({monster.name, type='monster'}), type = '[[Monster]]', minqty = minqty, qty = qty, weight = wt * lootChance, totalWeight = totalWt * 100})
-- monster within that dungeon (unless it is a shard)
if monster.isBoss then
local areaList = Areas.getMonsterAreas(monster.id)
for k, area in ipairs(areaList) do
  if area.type == 'dungeon' and area.monsters[#area.monsters] == monster.id then
table.insert(dropRows, {source = Icons.Icon({area.name, type='dungeon'}), type = '[[Dungeon]]', minqty = minqty, qty = qty, weight = wt * lootChance, totalWeight = totalWt * 100})
end
end
end
else
-- Item is not an end of dungeon reward, and drops when the monster is killed
table.insert(dropRows, {source = Icons.Icon({monster.name, type='monster'}), type = '[[Monster]]', minqty = minqty, qty = qty, weight = wt * lootChance, totalWeight = totalWt * 100})
end
end
end
end
-- Is the item dropped from any dungeon?
local dungeonList = Areas.getAreas(function(area) return area.type == 'dungeon' and type(area.rewards) == 'table' and Shared.contains(area.rewards, item.id) end)
if dungeonList ~= nil then
for i, dungeon in ipairs(dungeonList) do
table.insert(dropRows, {source = Icons.Icon({dungeon.name, type='dungeon'}), type = '[[Dungeon]]', minqty = 1, qty = 1, weight = 1, totalWeight = 1})
end
end
end
-- Is the item dropped from a cycle of the Impending Darkness event?
-- Is the item dropped from a cycle of the Impending Darkness event?
Line 737: Line 730:
else
else
sourceTxt = Icons.Icon({thiefRow.npc, type='thieving'})
sourceTxt = Icons.Icon({thiefRow.npc, type='thieving'})
end
end
table.insert(dropRows, {source = sourceTxt, type = thiefType, minqty = thiefRow.minQty, qty = thiefRow.maxQty, weight = thiefRow.wt, totalWeight = thiefRow.totalWt})
table.insert(dropRows, {source = sourceTxt, type = thiefType, minqty = thiefRow.minQty, qty = thiefRow.maxQty, weight = thiefRow.wt, totalWeight = thiefRow.totalWt})
end
end


Line 772: Line 765:


table.sort(dropRows, function(a, b)
table.sort(dropRows, function(a, b)
              if a.weight / a.totalWeight == b.weight / b.totalWeight then
if a.weight / a.totalWeight == b.weight / b.totalWeight then
                return a.minqty + a.qty > b.minqty + b.qty
return a.minqty + a.qty > b.minqty + b.qty
              else
else
                return a.weight / a.totalWeight > b.weight / b.totalWeight
return a.weight / a.totalWeight > b.weight / b.totalWeight
              end
end
            end)
end)
for i, data in pairs(dropRows) do
for i, data in pairs(dropRows) do
table.insert(resultPart, buildRow(data.source, data.type, data.minqty, data.qty, data.weight, data.totalWeight))
table.insert(resultPart, buildRow(data.source, data.type, data.minqty, data.qty, data.weight, data.totalWeight))
Line 843: Line 836:
else
else
if string.len(oreString) > 0 then oreString = oreString..', ' end
if string.len(oreString) > 0 then oreString = oreString..', ' end
oreString = oreString..Icons.Icon({thisMat.name, type='item', notext='true', qty=mat.qty})
oreString = oreString..Icons.Icon({thisMat.name, type='item', notext='true', qty=mat.qty})
end
end
end
end