Module:Magic: Difference between revisions
From Melvor Idle
Falterfire (talk | contribs) (Fixed some mistakes with new getting spells) |
Falterfire (talk | contribs) (Okay for real this should be a fix for standard magic spell linking) |
||
(25 intermediate revisions by 3 users not shown) | |||
Line 2: | Line 2: | ||
local MagicData = mw.loadData('Module:Magic/data') | local MagicData = mw.loadData('Module:Magic/data') | ||
local SkillData = mw.loadData('Module:Skills/data') | |||
local Areas = require('Module:CombatAreas') | |||
local Shared = require('Module:Shared') | local Shared = require('Module:Shared') | ||
local Icons = require('Module:Icons') | local Icons = require('Module:Icons') | ||
local Items = require('Module:Items') | |||
local Constants = require('Module:Constants') | |||
function processSpell(section, index) | function processSpell(section, index) | ||
local result = Shared.clone(MagicData[section][index]) | |||
result.id = index - 1 | |||
result.type = section | |||
return result | |||
end | end | ||
function p.getSpell(name, type) | function p.getSpell(name, type) | ||
local section = type | |||
if type == 'Spell' or type == 'Standard' then | |||
section = 'Spells' | |||
elseif type == 'Curse' then | |||
section = 'Curses' | |||
elseif type == 'Aurora' then | |||
section = 'Auroras' | |||
elseif type == 'Alt Magic' or type == 'Alternative Magic' then | |||
section = 'AltMagic' | |||
end | |||
name = Shared.fixPagename(name) | |||
if section == nil then | |||
for i, section in Shared.skpairs(MagicData) do | |||
for j, spell in Shared.skpairs(section) do | |||
if spell.name == name then | |||
return processSpell(i, j) | |||
end | |||
end | |||
end | |||
elseif section ~= nil and MagicData[section] ~= nil then | |||
for i, spell in Shared.skpairs(MagicData[section]) do | |||
if spell.name == name then | |||
return processSpell(section, i) | |||
end | |||
end | |||
else | |||
return nil | |||
end | |||
end | end | ||
function p.getSpellByID(type, id) | function p.getSpellByID(type, id) | ||
local section = type | |||
if type == nil or type == 'Spell' or type == 'Standard' then | |||
section = 'Spells' | |||
elseif type == 'Curse' then | |||
section = 'Curses' | |||
elseif type == 'Aurora' then | |||
section = 'Auroras' | |||
elseif type == 'Alt Magic' or type == 'Alternative Magic' then | |||
section = 'AltMagic' | |||
end | |||
if MagicData[section] ~= nil then | |||
return processSpell(section, id + 1) | |||
else | |||
return nil | |||
end | |||
end | |||
function p.getTypeString(type) | |||
if type == 'Auroras' then | |||
return 'Aurora' | |||
elseif type == 'Curses' then | |||
return 'Curse' | |||
elseif type == 'AltMagic' then | |||
return 'Alt. Magic' | |||
elseif type == 'Spells' then | |||
return "Combat Spell" | |||
elseif type == 'Ancient' then | |||
return 'Ancient Magick' | |||
end | |||
end | |||
function p._getSpellIcon(spell, size) | |||
if size == nil then size = 50 end | |||
if spell.type == 'Auroras' then | |||
return Icons.Icon({spell.name, type='aurora', notext=true, size=size}) | |||
elseif spell.type == 'Curses' then | |||
return Icons.Icon({spell.name, type='curse', notext=true, size=size}) | |||
else | |||
return Icons.Icon({spell.name, type='spell', notext=true, size=size}) | |||
end | |||
end | |||
function p._getSpellRequirements(spell) | |||
local result = '' | |||
result = result..Icons._SkillReq('Magic', spell.level) | |||
if spell.requiredItem ~= nil and spell.requiredItem >= 0 then | |||
local reqItem = Items.getItemByID(spell.requiredItem) | |||
result = result..'<br/>'..Icons.Icon({reqItem.name, type='item', notext=true})..' equipped' | |||
end | |||
if spell.requiredDungeonCompletion ~= nil then | |||
local dung = Areas.getAreaByID('dungeon', spell.requiredDungeonCompletion[1]) | |||
result = result..'<br/>'..Icons.Icon({dung.name, type='dungeon', notext=true, qty=spell.requiredDungeonCompletion[2]})..' Clears' | |||
end | |||
return result | |||
end | |||
function p._getSpellRunes(spell) | |||
local formatRuneList = function(runes) | |||
local runeList = {} | |||
for i, req in ipairs(runes) do | |||
local rune = Items.getItemByID(req.id) | |||
if rune ~= nil then | |||
table.insert(runeList, Icons.Icon({rune.name, type='item', notext=true, qty=req.qty})) | |||
end | |||
end | |||
return table.concat(runeList, ', ') | |||
end | |||
if type(spell.runesRequired) == 'table' then | |||
local resultPart = {} | |||
table.insert(resultPart, formatRuneList(spell.runesRequired)) | |||
if spell.runesRequiredAlt ~= nil and not Shared.tablesEqual(spell.runesRequired, spell.runesRequiredAlt) then | |||
table.insert(resultPart, "<br/>'''OR'''<br/>" .. formatRuneList(spell.runesRequiredAlt)) | |||
end | |||
return table.concat(resultPart) | |||
else | |||
return '' | |||
end | |||
end | |||
function p.getSpellRunes(frame) | |||
local spellName = frame.args ~= nil and frame.args[1] or frame | |||
local spell = p.getSpell(spellName) | |||
if spell == nil then | |||
return "ERROR: No spell named "..spellName.." exists in the data module" | |||
end | |||
return p._getSpellRunes(spell) | |||
end | |||
function p._getSpellDescription(spell) | |||
local result = '' | |||
if spell.description ~= nil then | |||
if p.getSpellTypeIndex(spell.type) == 4 and string.find(spell.description, "<br>") ~= nil then | |||
result = string.sub(spell.description, 0, string.find(spell.description, "<br>")-1) | |||
else | |||
result = spell.description | |||
end | |||
elseif (spell.modifiers ~= nil or spell.enemyModifiers ~= nil) then | |||
if spell.modifiers ~= nil then | |||
local playerModText = Constants.getModifiersText(spell.modifiers, false) | |||
result = playerModText | |||
end | |||
if spell.enemyModifiers ~= nil then | |||
local enemyModText = Constants.getModifiersText(spell.enemyModifiers, false) | |||
result = result .. (string.len(result) > 0 and '<br/>' or '') .. 'Enemies are inflicted with:<br/>' .. enemyModText | |||
end | |||
elseif spell.type == 'Spells' then | |||
result = 'Combat spell with a max hit of '..(spell.maxHit * 10) | |||
end | |||
return result | |||
end | |||
function p._getSpellStat(spell, stat) | |||
if stat == 'bigIcon' then | |||
return p._getSpellIcon(spell, 250) | |||
elseif stat == 'description' then | |||
return p._getSpellDescription(spell) | |||
elseif stat == 'icon' then | |||
return p._getSpellIcon(spell) | |||
elseif stat == 'requirements' then | |||
return p._getSpellRequirements(spell) | |||
elseif stat == 'runes' then | |||
return p._getSpellRunes(spell) | |||
elseif stat == 'type' then | |||
return p.getTypeString(spell.type) | |||
end | |||
return spell[stat] | |||
end | |||
function p.getSpellStat(frame) | |||
local spellName = frame.args ~= nil and frame.args[1] or frame[1] | |||
local statName = frame.args ~= nil and frame.args[2] or frame[2] | |||
local spell = p.getSpell(spellName) | |||
if spell == nil then | |||
return "ERROR: No spell named "..spellName.." found" | |||
end | |||
return p._getSpellStat(spell, statName) | |||
end | |||
function p.getOtherSpellBoxText(frame) | |||
local spellName = frame.args ~= nil and frame.args[1] or frame | |||
local spell = p.getSpell(spellName) | |||
if spell == nil then | |||
return "ERROR: No spell named "..spellName.." found" | |||
end | |||
local result = '' | |||
--8/20/21: Changed to using the new getSpellDescription function | |||
result = result.."\r\n|-\r\n|'''Description:'''<br/>"..p._getSpellStat(spell, 'description') | |||
return result | |||
end | |||
function p._getSpellCategories(spell) | |||
local result = '[[Category:Spells]]' | |||
result = result..'[[Category:'..p.getTypeString(spell.type)..']]' | |||
return result | |||
end | |||
function p.getSpellCategories(frame) | |||
local spellName = frame.args ~= nil and frame.args[1] or frame | |||
local spell = p.getSpell(spellName) | |||
if spell == nil then | |||
return "ERROR: No spell named "..spellName.." found" | |||
end | |||
return p._getSpellCategories(spell) | |||
end | |||
-- If includeConsumes = true, then checks for Alt Magic spell resource consumptions as well as | |||
-- the rune cost of spells | |||
function p.getSpellsForItem(itemID, includeConsumes) | |||
if type(includeConsumes) ~= 'boolean' then | |||
includeConsumes = false | |||
end | |||
-- The superheat table is built later as & when needed | |||
local superheatCosts, coalID = nil, nil | |||
local spellList = {} | |||
for secName, secArray in pairs(MagicData) do | |||
for i, spell in ipairs(secArray) do | |||
local foundSpell = false | |||
for j, req in pairs(spell.runesRequired) do | |||
if req.id == itemID then | |||
foundSpell = true | |||
break | |||
end | |||
end | |||
if not foundSpell and spell.runesRequiredAlt ~= nil then | |||
for j, req in pairs(spell.runesRequiredAlt) do | |||
if req.id == itemID then | |||
foundSpell = true | |||
break | |||
end | |||
end | |||
end | |||
if includeConsumes and not foundSpell and spell.consumes ~= nil and spell.consumes > 0 then | |||
-- The consumes property of Alt Magic spells is as follows: | |||
-- 0 = Any item | |||
-- 1 = Junk item | |||
-- 2 = Superheat/ores with Coal | |||
-- 3 = Superheat/ores without Coal | |||
-- 4 = Nothing | |||
-- 5 = Coal ore | |||
-- We ignore 4 (no resource consumption) and 0 (as this would flag every item unhelpfully) | |||
-- Determine the coal ID for the first time if we need it | |||
if coalID == nil and Shared.contains({2, 3, 5}, spell.consumes) then | |||
local coalItem = Items.getItem('Coal Ore') | |||
if coalItem ~= nil then | |||
coalID = coalItem.id | |||
end | |||
end | |||
if spell.consumes == 1 and Shared.contains(SkillData.Fishing.JunkItems, itemID) then | |||
foundSpell = true | |||
elseif spell.consumes == 2 or spell.consumes == 3 then | |||
if superheatCosts == nil then | |||
-- Initialize the superheatItems table | |||
superheatCosts = {} | |||
for j, recipe in ipairs(SkillData.Smithing.Recipes) do | |||
if recipe.category == 0 then | |||
-- Bar recipe | |||
for k, itemCost in ipairs(recipe.itemCosts) do | |||
if itemCost.id ~= coalID then | |||
superheatCosts[itemCost.id] = true | |||
end | |||
end | |||
end | |||
end | |||
end | |||
local ignoreCoal = (spell.consumes == 3) | |||
if superheatCosts[itemID] or (not ignoreCoal and itemID == coalID) then | |||
foundSpell = true | |||
end | |||
elseif spell.consumes == 5 and itemID == coalID then | |||
foundSpell = true | |||
end | |||
end | |||
if foundSpell then | |||
table.insert(spellList, processSpell(secName, i)) | |||
end | |||
end | |||
end | |||
table.sort(spellList, function(a, b) | |||
if a.type ~= b.type then | |||
return p.getSpellTypeIndex(a.type) < p.getSpellTypeIndex(b.type) | |||
else | |||
return a.level < b.level | |||
end | |||
end) | |||
return spellList | |||
end | |||
-- The below function is included for backwards compatibility | |||
function p.getSpellsForRune(runeID) | |||
return p.getSpellsForItem(runeID, false) | |||
end | |||
function p.getSpellTypeIndex(type) | |||
if type == 'Spells' then | |||
return 0 | |||
elseif type == 'Curses' then | |||
return 1 | |||
elseif type == 'Auroras' then | |||
return 2 | |||
elseif type == 'Ancient' then | |||
return 3 | |||
elseif type == 'AltMagic' then | |||
return 4 | |||
end | |||
return -1 | |||
end | |||
function p.getSpellTypeLink(type) | |||
if type == 'Spells' then | |||
return Icons.Icon({'Standard Magic', 'Standard', img='Standard', type='spellType'}) | |||
elseif type == 'Curses' then | |||
return Icons.Icon({'Curses', 'Curse', img='Curse', type='spellType'}) | |||
elseif type == 'Auroras' then | |||
return Icons.Icon({'Auroras', 'Aurora', img='Aurora', type='spellType'}) | |||
elseif type == 'Ancient' then | |||
return Icons.Icon({'Ancient Magicks', 'Ancient', img='Ancient', type='spellType'}) | |||
elseif type == 'AltMagic' then | |||
return Icons.Icon({'Alt. Magic', type='skill'}) | |||
end | |||
return '' | |||
end | |||
function p._getSpellRow(spell, includeTypeColumn) | |||
local rowTxt = '\r\n|-\r\n|data-sort-value="'..spell.name..'"|' | |||
if spell.type == 'Auroras' then | |||
rowTxt = rowTxt..Icons.Icon({spell.name, type='aurora', notext=true, size=50}) | |||
elseif spell.type == 'Curses' then | |||
rowTxt = rowTxt..Icons.Icon({spell.name, type='curse', notext=true, size=50}) | |||
else | |||
rowTxt = rowTxt..Icons.Icon({spell.name, type='spell', notext=true, size=50}) | |||
end | |||
rowTxt = rowTxt..'||'..Icons.Icon({spell.name, type='spell', noicon=true}) | |||
rowTxt = rowTxt..'||data-sort-value="'..spell.level..'"|'..Icons._SkillReq('Magic', spell.level) | |||
--Handle required items/dungeon clears | |||
if spell.requiredItem ~= nil and spell.requiredItem >= 0 then | |||
local reqItem = Items.getItemByID(spell.requiredItem) | |||
rowTxt = rowTxt..'<br/>'..Icons.Icon({reqItem.name, type='item', notext=true})..' equipped' | |||
end | |||
if spell.requiredDungeonCompletion ~= nil then | |||
local dung = Areas.getAreaByID('dungeon', spell.requiredDungeonCompletion[1]) | |||
rowTxt = rowTxt..'<br/>'..Icons.Icon({dung.name, type='dungeon', notext=true, qty=spell.requiredDungeonCompletion[2]})..' Clears' | |||
end | |||
if includeTypeColumn then | |||
rowTxt = rowTxt..'||data-sort-value="'..p.getSpellTypeIndex(spell.type)..'"|' | |||
rowTxt = rowTxt..p.getSpellTypeLink(spell.type) | |||
end | |||
--8/20/21: Changed to just getting the spell's description outright | |||
rowTxt = rowTxt..'||'..p._getSpellStat(spell, 'description') | |||
--1/4/22: haha just kidding. Now we're also getting delay between attacks for spells with special attacks | |||
if spell.specialAttack ~= nil then | |||
local spAtt = spell.specialAttack | |||
local interval = spAtt.attackInterval ~= nil and spAtt.attackInterval or -1 | |||
if interval ~= -1 then | |||
local hits = spAtt.attackCount ~= nil and spAtt.attackCount or 1 | |||
rowTxt = rowTxt..'<br/>(' | |||
rowTxt = rowTxt..Shared.round(interval / 1000, 2, 2)..'s delay between attacks.' | |||
if hits > 2 then | |||
rowTxt = rowTxt..' '..Shared.round(interval * (hits - 1) / 1000, 2, 2)..'s total duration.' | |||
end | |||
rowTxt = rowTxt..')' | |||
end | |||
end | |||
if p.getSpellTypeIndex(spell.type) == 4 then | |||
rowTxt = rowTxt..'||'..spell.baseExperience | |||
end | |||
rowTxt = rowTxt..'||style="text-align:center"|' | |||
rowTxt = rowTxt..p._getSpellRunes(spell) | |||
return rowTxt | |||
end | |||
function p.getStandardSpellsTable(frame) | |||
local result = '{|class="wikitable sortable"\r\n!colspan="2"|Spell' | |||
result = result..'!!Requirements' | |||
result = result..'!!style="width:275px"|Description' | |||
result = result..'!!Runes' | |||
local spellList = {} | |||
for i, spell in Shared.skpairs(MagicData.Spells) do | |||
local rowTxt = p._getSpellRow(processSpell('Spells', i), false) | |||
result = result..rowTxt | |||
end | |||
result = result..'\r\n|}' | |||
return result | |||
end | |||
function p.getCurseTable(frame) | |||
local result = '{|class="wikitable sortable"\r\n!colspan="2"|Spell' | |||
result = result..'!!Requirements' | |||
result = result..'!!style="width:275px"|Description' | |||
result = result..'!!Runes' | |||
local spellList = {} | |||
for i, spell in Shared.skpairs(MagicData.Curses) do | |||
local rowTxt = p._getSpellRow(processSpell('Curses', i), false) | |||
result = result..rowTxt | |||
end | |||
result = result..'\r\n|}' | |||
return result | |||
end | |||
function p.getAuroraTable(frame) | |||
local result = '{|class="wikitable sortable"\r\n!colspan="2"|Spell' | |||
result = result..'!!Requirements' | |||
result = result..'!!style="width:275px"|Description' | |||
result = result..'!!Runes' | |||
for i, spell in Shared.skpairs(MagicData.Auroras) do | |||
local rowTxt = p._getSpellRow(processSpell('Auroras', i), false) | |||
result = result..rowTxt | |||
end | |||
result = result..'\r\n|}' | |||
return result | |||
end | |||
function p.getAncientTable(frame) | |||
local result = '{|class="wikitable sortable"\r\n!colspan="2"|Spell' | |||
result = result..'!!Requirements' | |||
result = result..'!!style="width:275px"|Description' | |||
result = result..'!!Runes' | |||
for i, spell in Shared.skpairs(MagicData.Ancient) do | |||
local rowTxt = p._getSpellRow(processSpell('Ancient', i), false) | |||
result = result..rowTxt | |||
end | |||
result = result..'\r\n|}' | |||
return result | |||
end | |||
function p.getAltSpellsTable(frame) | |||
local result = '{|class="wikitable sortable"\r\n!colspan="2"|Spell' | |||
result = result..'!!Requirements' | |||
result = result..'!!style="width:275px"|Description' | |||
result = result..'!!Experience' | |||
result = result..'!!Runes' | |||
local spellList = {} | |||
for i, spell in Shared.skpairs(MagicData.AltMagic) do | |||
local rowTxt = p._getSpellRow(processSpell('AltMagic', i), false) | |||
result = result..rowTxt | |||
end | |||
result = result..'\r\n|}' | |||
return result | |||
end | end | ||
return p | return p |
Revision as of 20:40, 10 May 2022
Data pulled from Module:GameData/data
local p = {}
local MagicData = mw.loadData('Module:Magic/data')
local SkillData = mw.loadData('Module:Skills/data')
local Areas = require('Module:CombatAreas')
local Shared = require('Module:Shared')
local Icons = require('Module:Icons')
local Items = require('Module:Items')
local Constants = require('Module:Constants')
function processSpell(section, index)
local result = Shared.clone(MagicData[section][index])
result.id = index - 1
result.type = section
return result
end
function p.getSpell(name, type)
local section = type
if type == 'Spell' or type == 'Standard' then
section = 'Spells'
elseif type == 'Curse' then
section = 'Curses'
elseif type == 'Aurora' then
section = 'Auroras'
elseif type == 'Alt Magic' or type == 'Alternative Magic' then
section = 'AltMagic'
end
name = Shared.fixPagename(name)
if section == nil then
for i, section in Shared.skpairs(MagicData) do
for j, spell in Shared.skpairs(section) do
if spell.name == name then
return processSpell(i, j)
end
end
end
elseif section ~= nil and MagicData[section] ~= nil then
for i, spell in Shared.skpairs(MagicData[section]) do
if spell.name == name then
return processSpell(section, i)
end
end
else
return nil
end
end
function p.getSpellByID(type, id)
local section = type
if type == nil or type == 'Spell' or type == 'Standard' then
section = 'Spells'
elseif type == 'Curse' then
section = 'Curses'
elseif type == 'Aurora' then
section = 'Auroras'
elseif type == 'Alt Magic' or type == 'Alternative Magic' then
section = 'AltMagic'
end
if MagicData[section] ~= nil then
return processSpell(section, id + 1)
else
return nil
end
end
function p.getTypeString(type)
if type == 'Auroras' then
return 'Aurora'
elseif type == 'Curses' then
return 'Curse'
elseif type == 'AltMagic' then
return 'Alt. Magic'
elseif type == 'Spells' then
return "Combat Spell"
elseif type == 'Ancient' then
return 'Ancient Magick'
end
end
function p._getSpellIcon(spell, size)
if size == nil then size = 50 end
if spell.type == 'Auroras' then
return Icons.Icon({spell.name, type='aurora', notext=true, size=size})
elseif spell.type == 'Curses' then
return Icons.Icon({spell.name, type='curse', notext=true, size=size})
else
return Icons.Icon({spell.name, type='spell', notext=true, size=size})
end
end
function p._getSpellRequirements(spell)
local result = ''
result = result..Icons._SkillReq('Magic', spell.level)
if spell.requiredItem ~= nil and spell.requiredItem >= 0 then
local reqItem = Items.getItemByID(spell.requiredItem)
result = result..'<br/>'..Icons.Icon({reqItem.name, type='item', notext=true})..' equipped'
end
if spell.requiredDungeonCompletion ~= nil then
local dung = Areas.getAreaByID('dungeon', spell.requiredDungeonCompletion[1])
result = result..'<br/>'..Icons.Icon({dung.name, type='dungeon', notext=true, qty=spell.requiredDungeonCompletion[2]})..' Clears'
end
return result
end
function p._getSpellRunes(spell)
local formatRuneList = function(runes)
local runeList = {}
for i, req in ipairs(runes) do
local rune = Items.getItemByID(req.id)
if rune ~= nil then
table.insert(runeList, Icons.Icon({rune.name, type='item', notext=true, qty=req.qty}))
end
end
return table.concat(runeList, ', ')
end
if type(spell.runesRequired) == 'table' then
local resultPart = {}
table.insert(resultPart, formatRuneList(spell.runesRequired))
if spell.runesRequiredAlt ~= nil and not Shared.tablesEqual(spell.runesRequired, spell.runesRequiredAlt) then
table.insert(resultPart, "<br/>'''OR'''<br/>" .. formatRuneList(spell.runesRequiredAlt))
end
return table.concat(resultPart)
else
return ''
end
end
function p.getSpellRunes(frame)
local spellName = frame.args ~= nil and frame.args[1] or frame
local spell = p.getSpell(spellName)
if spell == nil then
return "ERROR: No spell named "..spellName.." exists in the data module"
end
return p._getSpellRunes(spell)
end
function p._getSpellDescription(spell)
local result = ''
if spell.description ~= nil then
if p.getSpellTypeIndex(spell.type) == 4 and string.find(spell.description, "<br>") ~= nil then
result = string.sub(spell.description, 0, string.find(spell.description, "<br>")-1)
else
result = spell.description
end
elseif (spell.modifiers ~= nil or spell.enemyModifiers ~= nil) then
if spell.modifiers ~= nil then
local playerModText = Constants.getModifiersText(spell.modifiers, false)
result = playerModText
end
if spell.enemyModifiers ~= nil then
local enemyModText = Constants.getModifiersText(spell.enemyModifiers, false)
result = result .. (string.len(result) > 0 and '<br/>' or '') .. 'Enemies are inflicted with:<br/>' .. enemyModText
end
elseif spell.type == 'Spells' then
result = 'Combat spell with a max hit of '..(spell.maxHit * 10)
end
return result
end
function p._getSpellStat(spell, stat)
if stat == 'bigIcon' then
return p._getSpellIcon(spell, 250)
elseif stat == 'description' then
return p._getSpellDescription(spell)
elseif stat == 'icon' then
return p._getSpellIcon(spell)
elseif stat == 'requirements' then
return p._getSpellRequirements(spell)
elseif stat == 'runes' then
return p._getSpellRunes(spell)
elseif stat == 'type' then
return p.getTypeString(spell.type)
end
return spell[stat]
end
function p.getSpellStat(frame)
local spellName = frame.args ~= nil and frame.args[1] or frame[1]
local statName = frame.args ~= nil and frame.args[2] or frame[2]
local spell = p.getSpell(spellName)
if spell == nil then
return "ERROR: No spell named "..spellName.." found"
end
return p._getSpellStat(spell, statName)
end
function p.getOtherSpellBoxText(frame)
local spellName = frame.args ~= nil and frame.args[1] or frame
local spell = p.getSpell(spellName)
if spell == nil then
return "ERROR: No spell named "..spellName.." found"
end
local result = ''
--8/20/21: Changed to using the new getSpellDescription function
result = result.."\r\n|-\r\n|'''Description:'''<br/>"..p._getSpellStat(spell, 'description')
return result
end
function p._getSpellCategories(spell)
local result = '[[Category:Spells]]'
result = result..'[[Category:'..p.getTypeString(spell.type)..']]'
return result
end
function p.getSpellCategories(frame)
local spellName = frame.args ~= nil and frame.args[1] or frame
local spell = p.getSpell(spellName)
if spell == nil then
return "ERROR: No spell named "..spellName.." found"
end
return p._getSpellCategories(spell)
end
-- If includeConsumes = true, then checks for Alt Magic spell resource consumptions as well as
-- the rune cost of spells
function p.getSpellsForItem(itemID, includeConsumes)
if type(includeConsumes) ~= 'boolean' then
includeConsumes = false
end
-- The superheat table is built later as & when needed
local superheatCosts, coalID = nil, nil
local spellList = {}
for secName, secArray in pairs(MagicData) do
for i, spell in ipairs(secArray) do
local foundSpell = false
for j, req in pairs(spell.runesRequired) do
if req.id == itemID then
foundSpell = true
break
end
end
if not foundSpell and spell.runesRequiredAlt ~= nil then
for j, req in pairs(spell.runesRequiredAlt) do
if req.id == itemID then
foundSpell = true
break
end
end
end
if includeConsumes and not foundSpell and spell.consumes ~= nil and spell.consumes > 0 then
-- The consumes property of Alt Magic spells is as follows:
-- 0 = Any item
-- 1 = Junk item
-- 2 = Superheat/ores with Coal
-- 3 = Superheat/ores without Coal
-- 4 = Nothing
-- 5 = Coal ore
-- We ignore 4 (no resource consumption) and 0 (as this would flag every item unhelpfully)
-- Determine the coal ID for the first time if we need it
if coalID == nil and Shared.contains({2, 3, 5}, spell.consumes) then
local coalItem = Items.getItem('Coal Ore')
if coalItem ~= nil then
coalID = coalItem.id
end
end
if spell.consumes == 1 and Shared.contains(SkillData.Fishing.JunkItems, itemID) then
foundSpell = true
elseif spell.consumes == 2 or spell.consumes == 3 then
if superheatCosts == nil then
-- Initialize the superheatItems table
superheatCosts = {}
for j, recipe in ipairs(SkillData.Smithing.Recipes) do
if recipe.category == 0 then
-- Bar recipe
for k, itemCost in ipairs(recipe.itemCosts) do
if itemCost.id ~= coalID then
superheatCosts[itemCost.id] = true
end
end
end
end
end
local ignoreCoal = (spell.consumes == 3)
if superheatCosts[itemID] or (not ignoreCoal and itemID == coalID) then
foundSpell = true
end
elseif spell.consumes == 5 and itemID == coalID then
foundSpell = true
end
end
if foundSpell then
table.insert(spellList, processSpell(secName, i))
end
end
end
table.sort(spellList, function(a, b)
if a.type ~= b.type then
return p.getSpellTypeIndex(a.type) < p.getSpellTypeIndex(b.type)
else
return a.level < b.level
end
end)
return spellList
end
-- The below function is included for backwards compatibility
function p.getSpellsForRune(runeID)
return p.getSpellsForItem(runeID, false)
end
function p.getSpellTypeIndex(type)
if type == 'Spells' then
return 0
elseif type == 'Curses' then
return 1
elseif type == 'Auroras' then
return 2
elseif type == 'Ancient' then
return 3
elseif type == 'AltMagic' then
return 4
end
return -1
end
function p.getSpellTypeLink(type)
if type == 'Spells' then
return Icons.Icon({'Standard Magic', 'Standard', img='Standard', type='spellType'})
elseif type == 'Curses' then
return Icons.Icon({'Curses', 'Curse', img='Curse', type='spellType'})
elseif type == 'Auroras' then
return Icons.Icon({'Auroras', 'Aurora', img='Aurora', type='spellType'})
elseif type == 'Ancient' then
return Icons.Icon({'Ancient Magicks', 'Ancient', img='Ancient', type='spellType'})
elseif type == 'AltMagic' then
return Icons.Icon({'Alt. Magic', type='skill'})
end
return ''
end
function p._getSpellRow(spell, includeTypeColumn)
local rowTxt = '\r\n|-\r\n|data-sort-value="'..spell.name..'"|'
if spell.type == 'Auroras' then
rowTxt = rowTxt..Icons.Icon({spell.name, type='aurora', notext=true, size=50})
elseif spell.type == 'Curses' then
rowTxt = rowTxt..Icons.Icon({spell.name, type='curse', notext=true, size=50})
else
rowTxt = rowTxt..Icons.Icon({spell.name, type='spell', notext=true, size=50})
end
rowTxt = rowTxt..'||'..Icons.Icon({spell.name, type='spell', noicon=true})
rowTxt = rowTxt..'||data-sort-value="'..spell.level..'"|'..Icons._SkillReq('Magic', spell.level)
--Handle required items/dungeon clears
if spell.requiredItem ~= nil and spell.requiredItem >= 0 then
local reqItem = Items.getItemByID(spell.requiredItem)
rowTxt = rowTxt..'<br/>'..Icons.Icon({reqItem.name, type='item', notext=true})..' equipped'
end
if spell.requiredDungeonCompletion ~= nil then
local dung = Areas.getAreaByID('dungeon', spell.requiredDungeonCompletion[1])
rowTxt = rowTxt..'<br/>'..Icons.Icon({dung.name, type='dungeon', notext=true, qty=spell.requiredDungeonCompletion[2]})..' Clears'
end
if includeTypeColumn then
rowTxt = rowTxt..'||data-sort-value="'..p.getSpellTypeIndex(spell.type)..'"|'
rowTxt = rowTxt..p.getSpellTypeLink(spell.type)
end
--8/20/21: Changed to just getting the spell's description outright
rowTxt = rowTxt..'||'..p._getSpellStat(spell, 'description')
--1/4/22: haha just kidding. Now we're also getting delay between attacks for spells with special attacks
if spell.specialAttack ~= nil then
local spAtt = spell.specialAttack
local interval = spAtt.attackInterval ~= nil and spAtt.attackInterval or -1
if interval ~= -1 then
local hits = spAtt.attackCount ~= nil and spAtt.attackCount or 1
rowTxt = rowTxt..'<br/>('
rowTxt = rowTxt..Shared.round(interval / 1000, 2, 2)..'s delay between attacks.'
if hits > 2 then
rowTxt = rowTxt..' '..Shared.round(interval * (hits - 1) / 1000, 2, 2)..'s total duration.'
end
rowTxt = rowTxt..')'
end
end
if p.getSpellTypeIndex(spell.type) == 4 then
rowTxt = rowTxt..'||'..spell.baseExperience
end
rowTxt = rowTxt..'||style="text-align:center"|'
rowTxt = rowTxt..p._getSpellRunes(spell)
return rowTxt
end
function p.getStandardSpellsTable(frame)
local result = '{|class="wikitable sortable"\r\n!colspan="2"|Spell'
result = result..'!!Requirements'
result = result..'!!style="width:275px"|Description'
result = result..'!!Runes'
local spellList = {}
for i, spell in Shared.skpairs(MagicData.Spells) do
local rowTxt = p._getSpellRow(processSpell('Spells', i), false)
result = result..rowTxt
end
result = result..'\r\n|}'
return result
end
function p.getCurseTable(frame)
local result = '{|class="wikitable sortable"\r\n!colspan="2"|Spell'
result = result..'!!Requirements'
result = result..'!!style="width:275px"|Description'
result = result..'!!Runes'
local spellList = {}
for i, spell in Shared.skpairs(MagicData.Curses) do
local rowTxt = p._getSpellRow(processSpell('Curses', i), false)
result = result..rowTxt
end
result = result..'\r\n|}'
return result
end
function p.getAuroraTable(frame)
local result = '{|class="wikitable sortable"\r\n!colspan="2"|Spell'
result = result..'!!Requirements'
result = result..'!!style="width:275px"|Description'
result = result..'!!Runes'
for i, spell in Shared.skpairs(MagicData.Auroras) do
local rowTxt = p._getSpellRow(processSpell('Auroras', i), false)
result = result..rowTxt
end
result = result..'\r\n|}'
return result
end
function p.getAncientTable(frame)
local result = '{|class="wikitable sortable"\r\n!colspan="2"|Spell'
result = result..'!!Requirements'
result = result..'!!style="width:275px"|Description'
result = result..'!!Runes'
for i, spell in Shared.skpairs(MagicData.Ancient) do
local rowTxt = p._getSpellRow(processSpell('Ancient', i), false)
result = result..rowTxt
end
result = result..'\r\n|}'
return result
end
function p.getAltSpellsTable(frame)
local result = '{|class="wikitable sortable"\r\n!colspan="2"|Spell'
result = result..'!!Requirements'
result = result..'!!style="width:275px"|Description'
result = result..'!!Experience'
result = result..'!!Runes'
local spellList = {}
for i, spell in Shared.skpairs(MagicData.AltMagic) do
local rowTxt = p._getSpellRow(processSpell('AltMagic', i), false)
result = result..rowTxt
end
result = result..'\r\n|}'
return result
end
return p