4,951
edits
Falterfire (talk | contribs) (Added nolink qualifier to getWeaponAttackType) |
Falterfire (talk | contribs) (Tweaks to the getEquipmentTable code) |
||
(12 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
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 SkillData = mw.loadData('Module:Skills/data') | ||
local Constants = mw.loadData('Module:Constants/data') | |||
local Shared = require('Module:Shared') | local Shared = require('Module:Shared') | ||
local Icons = require('Module:Icons') | local Icons = require('Module:Icons') | ||
local EasterEggs = {'Amulet of Calculated Promotion', 'Clue Chasers Insignia', '8', 'Lemon'} | |||
local OtherShopItems = {'Cooking Gloves', 'Mining Gloves', 'Gem Gloves', 'Smithing Gloves', 'Thieving Gloves'} | |||
function p.getItemByID(ID) | function p.getItemByID(ID) | ||
Line 192: | Line 197: | ||
result = result..'\r\n|}' | result = result..'\r\n|}' | ||
return result | |||
end | |||
function p._getItemSources(item) | |||
local result = nil | |||
local lineArray = {} | |||
--Alright, time to go through all the ways you can get an item... | |||
--First up: Can we kill somebody and take theirs? | |||
local killStr = '' | |||
for i, monster in pairs(MonsterData.Monsters) do | |||
if monster.lootTable ~= nil then | |||
for j, loot in pairs(monster.lootTable) do | |||
if loot[1] == item.id then | |||
if string.len(killStr) > 0 then | |||
killStr = killStr..','..Icons.Icon({monster.name, type="monster", notext="true"}) | |||
else | |||
killStr = killStr..'Killing: '..Icons.Icon({monster.name, type="monster", notext="true"}) | |||
end | |||
end | |||
end | |||
end | |||
end | |||
if string.len(killStr) > 0 then table.insert(lineArray, killStr) end | |||
--Next: Can we find it in a box? | |||
--While we're here, check for upgrades, cooking, and growing | |||
local lootStr = '' | |||
local upgradeStr = '' | |||
local cookStr = '' | |||
local burnStr = '' | |||
local growStr = '' | |||
for i, item2 in pairs(ItemData) do | |||
if item2.dropTable ~= nil then | |||
for j, loot in pairs(item2.dropTable) do | |||
if loot[1] == item.id then | |||
if string.len(lootStr) > 0 then | |||
lootStr = lootStr..','..Icons.Icon({item2.name, type="item", notext="true"}) | |||
else | |||
lootStr = lootStr..'Opening: '..Icons.Icon({item2.name, type="item", notext="true"}) | |||
end | |||
end | |||
end | |||
end | |||
if item2.trimmedItemID == item.id then | |||
if string.len(upgradeStr) > 0 then | |||
upgradeStr = upgradeStr..','..Icons.Icon({item2.name, type="item", notext="true"}) | |||
else | |||
upgradeStr = upgradeStr..'Upgrading: '..Icons.Icon({item2.name, type="item", notext="true"}) | |||
end | |||
end | |||
if item2.cookedItemID == item.id then | |||
if string.len(cookStr) > 0 then | |||
cookStr = cookStr..','..Icons.Icon({item2.name, type="item", notext="true"}) | |||
else | |||
cookStr = cookStr..'Cooking: '..Icons.Icon({item2.name, type="item", notext="true"}) | |||
end | |||
end | |||
if item2.burntItemID == item.id then | |||
if string.len(burnStr) > 0 then | |||
burnStr = burnStr..','..Icons.Icon({item2.name, type="item", notext="true"}) | |||
else | |||
burnStr = burnStr..'Burning: '..Icons.Icon({item2.name, type="item", notext="true"}) | |||
end | |||
end | |||
if item2.grownItemID == item.id then | |||
if string.len(growStr) > 0 then | |||
growStr = growStr..','..Icons.Icon({item2.name, type="item", notext="true"}) | |||
else | |||
growStr = growStr..'Growing: '..Icons.Icon({item2.name, type="item", notext="true"}) | |||
end | |||
end | |||
end | |||
if string.len(lootStr) > 0 then table.insert(lineArray, lootStr) end | |||
if string.len(upgradeStr) > 0 then table.insert(lineArray, upgradeStr) end | |||
if string.len(cookStr) > 0 then table.insert(lineArray, cookStr) end | |||
if string.len(burnStr) > 0 then table.insert(lineArray, burnStr) end | |||
if string.len(growStr) > 0 then table.insert(lineArray, growStr) end | |||
--Next: Can we take it from somebody else -without- killing them? | |||
local thiefStr = '' | |||
for i, npc in pairs(SkillData.Thieving) do | |||
if npc.lootTable ~= nil then | |||
for j, loot in pairs(npc.lootTable) do | |||
if loot[1] == item.id then | |||
if string.len(thiefStr) > 0 then | |||
thiefStr = thiefStr..','..Icons.Icon({npc.name, type="item", notext="true"}) | |||
else | |||
thiefStr = thiefStr..'Pickpocketing: '..Icons.Icon({npc.name, type="item", notext="true"}) | |||
end | |||
end | |||
end | |||
end | |||
end | |||
if string.len(thiefStr) > 0 then table.insert(lineArray, thiefStr) end | |||
--If all else fails, I guess we should check if we can make it ourselves | |||
--SmithCheck: | |||
if item.smithingLevel ~= nil then | |||
table.insert(lineArray, Icons._SkillReq("Smithing", item.smithingLevel)) | |||
end | |||
--CraftCheck: | |||
if item.craftingLevel ~= nil then | |||
table.insert(lineArray, Icons._SkillReq("Crafting", item.craftingLevel)) | |||
end | |||
--FletchCheck: | |||
if item.fletchingLevel ~= nil then | |||
table.insert(lineArray, Icons._SkillReq("Fletching", item.fletchingLevel)) | |||
end | |||
--RunecraftCheck: | |||
if item.runecraftingLevel ~= nil then | |||
table.insert(lineArray, Icons._SkillReq("Runecrafting", item.runecraftingLevel)) | |||
end | |||
--MineCheck: | |||
if item.miningLevel ~= nil then | |||
table.insert(lineArray, Icons._SkillReq("Mining", item.miningLevel)) | |||
end | |||
--FishCheck: | |||
if (item.category == "Fishing" and (item.type == "Junk" or item.type == "Special")) then | |||
table.insert(lineArray, Icons._SkillReq("Fishing", 1)) | |||
elseif item.fishingLevel ~= nil then | |||
table.insert(lineArray, Icons._SkillReq("Fishing", item.fishingLevel)) | |||
end | |||
--HerbCheck: | |||
if item.herbloreMasteryID ~= nil then | |||
local potionData = SkillData.Herblore.ItemData[item.herbloreMasteryID + 1].herbloreLevel | |||
table.insert(lineArray, Icons._SkillReq("Herblore", potionData)) | |||
end | |||
--Finally there are some weird exceptions: | |||
--Coal can be acquired via firemaking | |||
if item.name == "Coal Ore" then | |||
table.insert(lineArray, Icons._SkillReq("Firemaking", 1)) | |||
end | |||
--Gems can be acquired from both mining & fishing | |||
if item.type == 'Gem' then | |||
table.insert(lineArray, Icons._SkillReq("Fishing", 1)) | |||
table.insert(lineArray, Icons._SkillReq("Mining", 1)) | |||
end | |||
--Tokens are from the appropriate skill | |||
if item.isToken then | |||
for skill, id in pairs(Constants.skill) do | |||
if id == item.skill then | |||
table.insert(lineArray, Icons._SkillReq(skill, 1)) | |||
end | |||
end | |||
end | |||
--Shop items (including special items like gloves that aren't otherwise listed) | |||
if item.slayerCost ~= nil or item.buysFor ~= nil or Shared.contains(OtherShopItems, item.name) then | |||
table.insert(lineArray, '[[Shop]]') | |||
end | |||
--Easter Eggs (manual list 'cause don't have a better way to do that) | |||
if Shared.contains(EasterEggs, item.name) then | |||
table.insert(lineArray, '[[Easter Eggs]]') | |||
end | |||
return table.concat(lineArray, "<br/>") | |||
end | |||
function p.getItemSources(frame) | |||
local itemName = frame.args ~= nil and frame[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._getItemSources(item) | |||
end | |||
function p.getEquipmentTable(frame) | |||
local args = frame.args ~= nil and frame.args or frame | |||
local type = args.type | |||
local tier = args.tier | |||
local slotStr = args.slot | |||
local ammoTypeStr = args.ammoType | |||
local category = args.category ~= nil and args.category or 'Combat' | |||
--Find out what Ammo Type we're working with | |||
local ammoType = nil | |||
if ammoTypeStr ~= nil then | |||
if ammoTypeStr == "Arrows" then | |||
ammoType = 0 | |||
elseif ammoTypeStr == 'Bolts' then | |||
ammoType = 1 | |||
elseif ammoTypeStr == 'Javelins' then | |||
ammoType = 2 | |||
elseif ammoTypeStr == 'Throwing Knives' then | |||
ammoType = 3 | |||
end | |||
end | |||
--Find out what slot we're working with | |||
local slot = nil | |||
if slotStr ~= nil then | |||
slot = Constants.equipmentSlot[slotStr] | |||
end | |||
mw.log("Type = "..(type ~= nil and type or '')..", Slot = "..(slot ~= nil and slot or '')..", AmmoType = "..(ammoType ~= nil and ammoType or '')) | |||
--Getting some lists set up here that will be used later | |||
--First, the list of columns used by both weapons & armour | |||
local statColumns = {'slashAttackBonus', 'stabAttackBonus','blockAttackBonus','rangedAttackBonus', 'magicAttackBonus', 'strengthBonus', 'rangedStrengthBonus', 'magicDamageBonus', 'defenceBonus', 'rangedDefenceBonus', 'magicDefenceBonus'} | |||
--Then the lists for just weapons/just armour | |||
local weaponStatColumns = {'attackLevelRequired', 'rangedLevelRequired', 'magicLevelRequired'} | |||
local armourStatColumns = {'damageReduction', 'defenceLevelRequired', 'rangedLevelRequired', 'magicLevelRequired'} | |||
--Then the list of weapon types | |||
local weaponTypes = {'Magic Staff', 'Magic Wand', 'Ranged Weapon', 'Weapon'} | |||
local isWeaponType = Shared.contains(weaponTypes, type) | |||
--Alright, let's start the table by building the shared header | |||
local result = '{| class="wikitable sortable stickyHeader"\r\n|-class="headerRow-0"' | |||
if isWeaponType then | |||
--Weapons have an extra column here for Attack Speed | |||
result = result..'\r\n!colspan="3"|' | |||
else | |||
result = result..'\r\n!colspan="2"|' | |||
end | |||
result = result..'\r\n!colspan="5"style="padding:0 0.5em 0 0.5em;"|Attack Bonus' | |||
result = result..'\r\n!colspan="2"style="padding:0 0.5em 0 0.5em;"|Strength Bonus' | |||
result = result..'\r\n!colspan="1"style="padding:0 0.5em 0 0.5em;"|% Damage Bonus' | |||
result = result..'\r\n!colspan="3"style="padding:0 0.5em 0 0.5em;"|Defence Bonus' | |||
if isWeaponType then | |||
--Weapons have an extra columns here for "Two Handed?" | |||
result = result..'\r\n!colspan="1"|' | |||
else | |||
--Only armour pieces have DR right now, so ignore that column for weapons | |||
result = result..'\r\n!colspan="1"style="padding:0 0.5em 0 0.5em;"|Damage Reduction' | |||
end | |||
result = result..'\r\n!colspan="3"style="padding:0 0.5em 0 0.5em;"|Levels Required' | |||
result = result..'\r\n!colspan="1"|' | |||
--One header row down, one to go | |||
result = result..'\r\n|-class="headerRow-1"' | |||
result = result..'\r\n!style="padding:0 1em 0 0.5em;"|Item' | |||
result = result..'\r\n!style="padding:0 1em 0 0.5em;"|Name' | |||
--Weapons have Attack Speed here | |||
if isWeaponType then | |||
result = result..'\r\n!style="padding:0 1em 0 0.5em;"|Attack Speed' | |||
end | |||
--Attack bonuses | |||
result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Attack', type='skill', notext='true'}) | |||
result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Strength', type='skill', notext='true'}) | |||
result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Defence', type='skill', notext='true'}) | |||
result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Ranged', type='skill', notext='true'}) | |||
result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Magic', type='skill', notext='true'}) | |||
--Strength bonuses | |||
result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Strength', type='skill', notext='true'}) | |||
result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Ranged', type='skill', notext='true'}) | |||
result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Magic', type='skill', notext='true'}) | |||
--Defence bonuses | |||
result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Defence', type='skill', notext='true'}) | |||
result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Ranged', type='skill', notext='true'}) | |||
result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Magic', type='skill', notext='true'}) | |||
--Damage Reduction/Defence Req for armour, 2-handed/Attack Req for weapons | |||
if isWeaponType then | |||
result = result..'\r\n!style="padding:0 1em 0 0.5em;"|Two Handed?' | |||
result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Attack', type='skill', notext='true'}) | |||
else | |||
result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Defence', type='skill', notext='true'}) | |||
result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Defence', type='skill', notext='true'}) | |||
end | |||
--Then Ranged/Magic requirements | |||
result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Ranged', type='skill', notext='true'}) | |||
result = result..'\r\n!style="padding:0 1em 0 0.5em;"|'..Icons.Icon({'Magic', type='skill', notext='true'}) | |||
--And finally Sources | |||
result = result..'\r\n!style="padding:0 1em 0 0.5em;"|Sources' | |||
--And with all the header out of the way, finally time to actually build the table itself. | |||
local itemList = {} | |||
for i, itemBase in pairs(ItemData) do | |||
local item = Shared.clone(itemBase) | |||
item.id = i - 1 | |||
local listItem = false | |||
if isWeaponType then | |||
listItem = item.type == type and item.category == category | |||
if ammoType ~= nil then listItem = listItem and item.ammoTypeRequired == ammoType end | |||
else | |||
--Now for handling armour | |||
if type == "Armour" or type == "Melee" then | |||
listItem = item.defenceLevelRequired ~= nil or (item.category == 'Combat' and item.type == 'Armour') | |||
elseif type == "Ranged Armour" or type == "Ranged" then | |||
listItem = item.rangedLevelRequired ~= nil or (item.category == 'Combat' and item.type == 'Ranged Armour') | |||
elseif type == "Magic Armour" or type == "Magic" then | |||
listItem = item.magicLevelRequired ~= nil or (item.category == 'Combat' and item.type == 'Magic Armour') | |||
else | |||
listItem = item.type == type and item.category ~= 'Combat' | |||
end | |||
if ammoType ~= nil then listItem = listItem and item.ammoType == ammoType end | |||
if slot ~= nil then listItem = listItem and item.equipmentSlot == slot end | |||
end | |||
if listItem then | |||
table.insert(itemList, item) | |||
end | |||
end | |||
table.sort(itemList, function(a, b) return a.id < b.id end) | |||
for i, item in pairs(itemList) do | |||
if isWeaponType then | |||
--Building rows for weapons | |||
result = result..'\r\n|-' | |||
result = result..'\r\n|style ="text-align: left;padding: 0 0 0 0;"|'..Icons.Icon({item.name, type='item', size=50, notext=true}) | |||
result = result..'\r\n|style ="text-align: left;padding: 0 0.5em 0 0.5em;"|[['..item.name..']]' | |||
result = result..'\r\n| style ="text-align: right;padding: 0 0.5em 0 0;" |'..Shared.formatnum(item.attackSpeed) | |||
for j, statName in pairs(statColumns) do | |||
local statValue = p._getItemStat(item, statName, true) | |||
result = result..'\r\n| style ="text-align: right;padding: 0 0.5em 0 0;' | |||
if statValue > 0 then | |||
result = result..'background-color:lightgreen;' | |||
elseif statValue < 0 then | |||
result = result..'background-color:lightpink;' | |||
end | |||
result = result..'"|'..Shared.formatnum(statValue) | |||
if statName == 'magicDamageBonus' or statName == 'damageReduction' then result = result..'%' end | |||
end | |||
--That's the first list out of the way, now for 2-Handed | |||
result = result..'\r\n| style ="text-align: right;"|' | |||
if item.isTwoHanded then result = result..'Yes' else result = result..'No' end | |||
--Now the weapon exclusive columns | |||
for j, statName in pairs(weaponStatColumns) do | |||
local statValue = p._getItemStat(item, statName, true) | |||
result = result..'\r\n| style ="text-align: right;padding: 0 0.5em 0 0;' | |||
result = result..'"|'..Shared.formatnum(statValue) | |||
if statName == 'magicDamageBonus' or statName == 'damageReduction' then result = result..'%' end | |||
end | |||
--Finally, the Sources | |||
result = result..'\r\n| style ="text-align: right;white-space: nowrap;padding: 0 0.5em 0 0.5em;" |' | |||
result = result..p._getItemSources(item) | |||
else | |||
--Building rows for armour | |||
result = result..'\r\n|-' | |||
result = result..'\r\n|style ="text-align: left;padding: 0 0 0 0;"|'..Icons.Icon({item.name, type='item', size=50, notext=true}) | |||
result = result..'\r\n|style ="text-align: left;padding: 0 0.5em 0 0.5em;"|[['..item.name..']]' | |||
for j, statName in pairs(statColumns) do | |||
local statValue = p._getItemStat(item, statName, true) | |||
result = result..'\r\n| style ="text-align: right;padding: 0 0.5em 0 0;' | |||
if statValue > 0 then | |||
result = result..'background-color:lightgreen;' | |||
elseif statValue < 0 then | |||
result = result..'background-color:lightpink;' | |||
end | |||
result = result..'"|'..Shared.formatnum(statValue) | |||
if statName == 'magicDamageBonus' or statName == 'damageReduction' then result = result..'%' end | |||
end | |||
--That's the first list out of the way, now for armour specific things | |||
for j, statName in pairs(armourStatColumns) do | |||
local statValue = p._getItemStat(item, statName, true) | |||
result = result..'\r\n| style ="text-align: right;padding: 0 0.5em 0 0;' | |||
if j == 1 then | |||
if statValue > 0 then | |||
result = result..'background-color:lightgreen;' | |||
elseif statValue < 0 then | |||
result = result..'background-color:lightpink;' | |||
end | |||
end | |||
result = result..'"|'..Shared.formatnum(statValue) | |||
if statName == 'magicDamageBonus' or statName == 'damageReduction' then result = result..'%' end | |||
end | |||
--Finally, the Sources | |||
result = result..'\r\n| style ="text-align: right;white-space: nowrap;padding: 0 0.5em 0 0.5em;" |' | |||
result = result..p._getItemSources(item) | |||
end | |||
end | |||
result = result..'\r\n|}' | |||
return result | return result | ||
end | end | ||
return p | return p |