Module:Magic: Difference between revisions

Added delay/duration information to spell tables (should only affect ancient magicks)
(Fix issue with generation of curse table)
(Added delay/duration information to spell tables (should only affect ancient magicks))
Line 10: Line 10:


function processSpell(section, index)
function processSpell(section, index)
  local result = Shared.clone(MagicData[section][index])
local result = Shared.clone(MagicData[section][index])
  result.id = index - 1
result.id = index - 1
  result.type = section
result.type = section
  return result
return result
end
end


function p.getSpell(name, type)
function p.getSpell(name, type)
  local section = type
local section = type
  if type == 'Spell' or type == 'Standard' then
if type == 'Spell' or type == 'Standard' then
    section = 'Spells'
section = 'Spells'
  elseif type == 'Curse' then
elseif type == 'Curse' then
    section = 'Curses'
section = 'Curses'
  elseif type == 'Aurora' then
elseif type == 'Aurora' then
    section = 'Auroras'
section = 'Auroras'
  elseif type == 'Alt Magic' or type == 'Alternative Magic' then
elseif type == 'Alt Magic' or type == 'Alternative Magic' then
    section='AltMagic'
section='AltMagic'
  end
end
 
  name = Shared.fixPagename(name)
name = Shared.fixPagename(name)
  if section == nil then
if section == nil then
    for i, section in Shared.skpairs(MagicData) do
for i, section in Shared.skpairs(MagicData) do
      for j, spell in Shared.skpairs(section) do
for j, spell in Shared.skpairs(section) do
        if spell.name == name then
if spell.name == name then
          return processSpell(i, j)
return processSpell(i, j)
        end
end
      end
end
    end
end
  elseif section ~= nil and MagicData[section] ~= nil then
elseif section ~= nil and MagicData[section] ~= nil then
    for i, spell in Shared.skpairs(MagicData[section]) do
for i, spell in Shared.skpairs(MagicData[section]) do
      if spell.name == name then
if spell.name == name then
        return processSpell(section, i)
return processSpell(section, i)
      end
end
    end
end
  else
else
    return nil
return nil
  end
end
end
end


function p.getSpellByID(type, id)
function p.getSpellByID(type, id)
  local section = type
local section = type
  if type == nil or type == 'Spell' or type == 'Standard' then
if type == nil or type == 'Spell' or type == 'Standard' then
    section = 'Spells'
section = 'Spells'
  elseif type == 'Curse' then
elseif type == 'Curse' then
    section = 'Curses'
section = 'Curses'
  elseif type == 'Aurora' then
elseif type == 'Aurora' then
    section = 'Auroras'
section = 'Auroras'
  elseif type == 'Alt Magic' or type == 'Alternative Magic' then
elseif type == 'Alt Magic' or type == 'Alternative Magic' then
    section='AltMagic'
section='AltMagic'
  end
end
 
  if MagicData[section] ~= nil then
if MagicData[section] ~= nil then
    return processSpell(section, id + 1)
return processSpell(section, id + 1)
  else
else
    return nil
return nil
  end
end
end
end


function p.getTypeString(type)
function p.getTypeString(type)
  if type == 'Auroras' then
if type == 'Auroras' then
    return 'Aurora'
return 'Aurora'
  elseif type == 'Curses' then
elseif type == 'Curses' then
    return 'Curse'
return 'Curse'
  elseif type == 'AltMagic' then
elseif type == 'AltMagic' then
    return 'Alt. Magic'
return 'Alt. Magic'
  elseif type == 'Spells' then
elseif type == 'Spells' then
    return "Combat Spell"
return "Combat Spell"
  elseif type == 'Ancient' then
elseif type == 'Ancient' then
    return 'Ancient Magick'
return 'Ancient Magick'
  end
end
end
end


function p._getSpellIcon(spell, size)
function p._getSpellIcon(spell, size)
  if size == nil then size = 50 end
if size == nil then size = 50 end
  if spell.type == 'Auroras' then
if spell.type == 'Auroras' then
    return Icons.Icon({spell.name, type='aurora', notext=true, size=size})
return Icons.Icon({spell.name, type='aurora', notext=true, size=size})
  elseif spell.type == 'Curses' then
elseif spell.type == 'Curses' then
    return Icons.Icon({spell.name, type='curse', notext=true, size=size})
return Icons.Icon({spell.name, type='curse', notext=true, size=size})
  else
else
    return Icons.Icon({spell.name, type='spell', notext=true, size=size})
return Icons.Icon({spell.name, type='spell', notext=true, size=size})
  end
end
end
end


function p._getSpellRequirements(spell)
function p._getSpellRequirements(spell)
  local result = ''
local result = ''
  result = result..Icons._SkillReq('Magic', spell.level)
result = result..Icons._SkillReq('Magic', spell.level)
  if spell.requiredItem ~= nil and spell.requiredItem >= 0 then
if spell.requiredItem ~= nil and spell.requiredItem >= 0 then
    local reqItem = Items.getItemByID(spell.requiredItem)
local reqItem = Items.getItemByID(spell.requiredItem)
    result = result..'<br/>'..Icons.Icon({reqItem.name, type='item', notext=true})..' equipped'
result = result..'<br/>'..Icons.Icon({reqItem.name, type='item', notext=true})..' equipped'
  end
end
  if spell.requiredDungeonCompletion ~= nil then
if spell.requiredDungeonCompletion ~= nil then
    local dung = Areas.getAreaByID('dungeon', spell.requiredDungeonCompletion[1])
local dung = Areas.getAreaByID('dungeon', spell.requiredDungeonCompletion[1])
    result = result..'<br/>'..Icons.Icon({dung.name, type='dungeon', notext=true, qty=spell.requiredDungeonCompletion[2]})..' Clears'
result = result..'<br/>'..Icons.Icon({dung.name, type='dungeon', notext=true, qty=spell.requiredDungeonCompletion[2]})..' Clears'
  end
end
  return result
return result
end
end


function p._getSpellRunes(spell)
function p._getSpellRunes(spell)
  local result = ''
local result = ''
  for i, req in Shared.skpairs(spell.runesRequired) do
for i, req in Shared.skpairs(spell.runesRequired) do
    local rune = Items.getItemByID(req.id)
local rune = Items.getItemByID(req.id)
    if i > 1 then result = result..', ' end
if i > 1 then result = result..', ' end
    result = result..Icons.Icon({rune.name, type='item', notext=true, qty=req.qty})
result = result..Icons.Icon({rune.name, type='item', notext=true, qty=req.qty})
  end
end
  if spell.runesRequiredAlt ~= nil and not Shared.tablesEqual(spell.runesRequired, spell.runesRequiredAlt) then
if spell.runesRequiredAlt ~= nil and not Shared.tablesEqual(spell.runesRequired, spell.runesRequiredAlt) then
    result = result.."<br/>'''OR'''<br/>"
result = result.."<br/>'''OR'''<br/>"
    for i, req in pairs(spell.runesRequiredAlt) do
for i, req in pairs(spell.runesRequiredAlt) do
      local rune = Items.getItemByID(req.id)
local rune = Items.getItemByID(req.id)
      if i > 1 then result = result..', ' end
if i > 1 then result = result..', ' end
      result = result..Icons.Icon({rune.name, type='item', notext=true, qty=req.qty})
result = result..Icons.Icon({rune.name, type='item', notext=true, qty=req.qty})
    end
end
  end
end
  return result
return result
end
end


function p.getSpellRunes(frame)
function p.getSpellRunes(frame)
  local spellName = frame.args ~= nil and frame.args[1] or frame
local spellName = frame.args ~= nil and frame.args[1] or frame
  local spell = p.getSpell(spellName)
local spell = p.getSpell(spellName)
  if spell == nil then
if spell == nil then
    return "ERROR: No spell named "..spellName.." exists in the data module"
return "ERROR: No spell named "..spellName.." exists in the data module"
  end
end
  return p._getSpellRunes(spell)
return p._getSpellRunes(spell)
end
end


function p._getSpellDescription(spell)
function p._getSpellDescription(spell)
  local result = ''
local result = ''
  if spell.description ~= nil then
if spell.description ~= nil then
    if p.getSpellTypeIndex(spell.type) == 4 and string.find(spell.description, "<br>") ~= 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)
result = string.sub(spell.description, 0, string.find(spell.description, "<br>")-1)
    else
else
      result = spell.description
result = spell.description
    end
end
  elseif (spell.modifiers ~= nil or spell.enemyModifiers ~= nil) then
elseif (spell.modifiers ~= nil or spell.enemyModifiers ~= nil) then
  if spell.modifiers ~= nil then
if spell.modifiers ~= nil then
  local playerModText = Constants.getModifiersText(spell.modifiers, false)
local playerModText = Constants.getModifiersText(spell.modifiers, false)
  result = playerModText
result = playerModText
  end
end
  if spell.enemyModifiers ~= nil then
if spell.enemyModifiers ~= nil then
  local enemyModText = Constants.getModifiersText(spell.enemyModifiers, false)
local enemyModText = Constants.getModifiersText(spell.enemyModifiers, false)
  result = result .. (string.len(result) > 0 and '<br/>' or '') .. 'Enemies are inflicted with:<br/>' .. enemyModText
result = result .. (string.len(result) > 0 and '<br/>' or '') .. 'Enemies are inflicted with:<br/>' .. enemyModText
  end
end
  elseif spell.type == 'Spells' then
elseif spell.type == 'Spells' then
    result = 'Combat spell with a max hit of '..(spell.maxHit * 10)
result = 'Combat spell with a max hit of '..(spell.maxHit * 10)
  end
end


  return result
return result
end
end


function p._getSpellStat(spell, stat)
function p._getSpellStat(spell, stat)
  if stat == 'bigIcon' then
if stat == 'bigIcon' then
    return p._getSpellIcon(spell, 250)
return p._getSpellIcon(spell, 250)
  elseif stat == 'description' then
elseif stat == 'description' then
    return p._getSpellDescription(spell)
return p._getSpellDescription(spell)
  elseif stat == 'icon' then
elseif stat == 'icon' then
    return p._getSpellIcon(spell)
return p._getSpellIcon(spell)
  elseif stat == 'requirements' then
elseif stat == 'requirements' then
    return p._getSpellRequirements(spell)
return p._getSpellRequirements(spell)
  elseif stat == 'runes' then
elseif stat == 'runes' then
    return p._getSpellRunes(spell)
return p._getSpellRunes(spell)
  elseif stat == 'type' then
elseif stat == 'type' then
    return p.getTypeString(spell.type)
return p.getTypeString(spell.type)
  end
end
  return spell[stat]
return spell[stat]
end
end


function p.getSpellStat(frame)
function p.getSpellStat(frame)
  local spellName = frame.args ~= nil and frame.args[1] or frame[1]
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 statName = frame.args ~= nil and frame.args[2] or frame[2]
  local spell = p.getSpell(spellName)
local spell = p.getSpell(spellName)
  if spell == nil then
if spell == nil then
    return "ERROR: No spell named "..spellName.." found"
return "ERROR: No spell named "..spellName.." found"
  end
end
  return p._getSpellStat(spell, statName)
return p._getSpellStat(spell, statName)
end
end


function p.getOtherSpellBoxText(frame)
function p.getOtherSpellBoxText(frame)
  local spellName = frame.args ~= nil and frame.args[1] or frame
local spellName = frame.args ~= nil and frame.args[1] or frame
  local spell = p.getSpell(spellName)
local spell = p.getSpell(spellName)
  if spell == nil then
if spell == nil then
    return "ERROR: No spell named "..spellName.." found"
return "ERROR: No spell named "..spellName.." found"
  end
end


  local result = ''
local result = ''


  --8/20/21: Changed to using the new getSpellDescription function
--8/20/21: Changed to using the new getSpellDescription function
  result = result.."\r\n|-\r\n|'''Description:'''<br/>"..p._getSpellStat(spell, 'description')
result = result.."\r\n|-\r\n|'''Description:'''<br/>"..p._getSpellStat(spell, 'description')


  return result
return result
end
end


function p._getSpellCategories(spell)
function p._getSpellCategories(spell)
  local result = '[[Category:Spells]]'
local result = '[[Category:Spells]]'
  result = result..'[[Category:'..p.getTypeString(spell.type)..']]'
result = result..'[[Category:'..p.getTypeString(spell.type)..']]'
  return result
return result
end
end


function p.getSpellCategories(frame)
function p.getSpellCategories(frame)
  local spellName = frame.args ~= nil and frame.args[1] or frame
local spellName = frame.args ~= nil and frame.args[1] or frame
  local spell = p.getSpell(spellName)
local spell = p.getSpell(spellName)
  if spell == nil then
if spell == nil then
    return "ERROR: No spell named "..spellName.." found"
return "ERROR: No spell named "..spellName.." found"
  end
end
  return p._getSpellCategories(spell)
return p._getSpellCategories(spell)
end
end


function p.getSpellsForRune(runeID)
function p.getSpellsForRune(runeID)
  local spellList = {}
local spellList = {}
  for secName, secArray in Shared.skpairs(MagicData) do
for secName, secArray in Shared.skpairs(MagicData) do
    for i, spell in pairs(secArray) do
for i, spell in pairs(secArray) do
      local foundSpell = false
local foundSpell = false
      for j, req in pairs(spell.runesRequired) do
for j, req in pairs(spell.runesRequired) do
        if req.id == runeID then
if req.id == runeID then
          table.insert(spellList, processSpell(secName, i))
table.insert(spellList, processSpell(secName, i))
          foundSpell = true
foundSpell = true
          break
break
        end
end
      end
end
      if spell.runesRequiredAlt ~= nil and not foundSpell then
if spell.runesRequiredAlt ~= nil and not foundSpell then
        for j, req in pairs(spell.runesRequiredAlt) do
for j, req in pairs(spell.runesRequiredAlt) do
          if req.id == runeID then
if req.id == runeID then
            table.insert(spellList, processSpell(secName, i))
table.insert(spellList, processSpell(secName, i))
            break
break
          end
end
        end
end
      end
end
    end
end
  end
end
  table.sort(spellList, function(a, b)  
table.sort(spellList, function(a, b)  
              if a.type ~= b.type then
if a.type ~= b.type then
                return p.getSpellTypeIndex(a.type) < p.getSpellTypeIndex(b.type)
return p.getSpellTypeIndex(a.type) < p.getSpellTypeIndex(b.type)
              else
else
                return a.level < b.level
return a.level < b.level
              end
end
            end)
end)
  return spellList
return spellList
end
end


function p.getSpellTypeIndex(type)
function p.getSpellTypeIndex(type)
  if type == 'Spells' then
if type == 'Spells' then
    return 0
return 0
  elseif type == 'Curses' then
elseif type == 'Curses' then
    return 1
return 1
  elseif type == 'Auroras' then
elseif type == 'Auroras' then
    return 2
return 2
  elseif type == 'Ancient' then
elseif type == 'Ancient' then
    return 3
return 3
  elseif type == 'AltMagic' then
elseif type == 'AltMagic' then
    return 4
return 4
  end
end
  return -1
return -1
end
end


function p.getSpellTypeLink(type)
function p.getSpellTypeLink(type)
  if type == 'Spells' then
if type == 'Spells' then
    return Icons.Icon({'Magic', 'Standard', img='Standard', type='spellType'})
return Icons.Icon({'Magic', 'Standard', img='Standard', type='spellType'})
  elseif type == 'Curses' then
elseif type == 'Curses' then
    return Icons.Icon({'Curses', 'Curse', img='Curse', type='spellType'})
return Icons.Icon({'Curses', 'Curse', img='Curse', type='spellType'})
  elseif type == 'Auroras' then
elseif type == 'Auroras' then
    return Icons.Icon({'Auroras', 'Aurora', img='Aurora', type='spellType'})
return Icons.Icon({'Auroras', 'Aurora', img='Aurora', type='spellType'})
  elseif type == 'Ancient' then
elseif type == 'Ancient' then
    return Icons.Icon({'Ancient Magicks', 'Ancient', img='Ancient', type='spellType'})
return Icons.Icon({'Ancient Magicks', 'Ancient', img='Ancient', type='spellType'})
  elseif type == 'AltMagic' then
elseif type == 'AltMagic' then
    return Icons.Icon({'Alt. Magic', type='skill'})
return Icons.Icon({'Alt. Magic', type='skill'})
  end
end
  return ''
return ''
end
end


function p._getSpellRow(spell, includeTypeColumn)
function p._getSpellRow(spell, includeTypeColumn)
  local rowTxt = '\r\n|-\r\n|data-sort-value="'..spell.name..'"|'
local rowTxt = '\r\n|-\r\n|data-sort-value="'..spell.name..'"|'
  if spell.type == 'Auroras' then
if spell.type == 'Auroras' then
    rowTxt = rowTxt..Icons.Icon({spell.name, type='aurora', notext=true, size=50})
rowTxt = rowTxt..Icons.Icon({spell.name, type='aurora', notext=true, size=50})
  elseif spell.type == 'Curses' then
elseif spell.type == 'Curses' then
    rowTxt = rowTxt..Icons.Icon({spell.name, type='curse', notext=true, size=50})
rowTxt = rowTxt..Icons.Icon({spell.name, type='curse', notext=true, size=50})
  else
else
    rowTxt = rowTxt..Icons.Icon({spell.name, type='spell', notext=true, size=50})
rowTxt = rowTxt..Icons.Icon({spell.name, type='spell', notext=true, size=50})
  end
end
  rowTxt = rowTxt..'||'..Icons.Icon({spell.name, type='spell', noicon=true})
rowTxt = rowTxt..'||'..Icons.Icon({spell.name, type='spell', noicon=true})
  rowTxt = rowTxt..'||data-sort-value="'..spell.level..'"|'..Icons._SkillReq('Magic', spell.level)
rowTxt = rowTxt..'||data-sort-value="'..spell.level..'"|'..Icons._SkillReq('Magic', spell.level)
  --Handle required items/dungeon clears
--Handle required items/dungeon clears
  if spell.requiredItem ~= nil and spell.requiredItem >= 0 then
if spell.requiredItem ~= nil and spell.requiredItem >= 0 then
    local reqItem = Items.getItemByID(spell.requiredItem)
local reqItem = Items.getItemByID(spell.requiredItem)
    rowTxt = rowTxt..'<br/>'..Icons.Icon({reqItem.name, type='item', notext=true})..' equipped'
rowTxt = rowTxt..'<br/>'..Icons.Icon({reqItem.name, type='item', notext=true})..' equipped'
  end
end
  if spell.requiredDungeonCompletion ~= nil then
if spell.requiredDungeonCompletion ~= nil then
    local dung = Areas.getAreaByID('dungeon', spell.requiredDungeonCompletion[1])
local dung = Areas.getAreaByID('dungeon', spell.requiredDungeonCompletion[1])
    rowTxt = rowTxt..'<br/>'..Icons.Icon({dung.name, type='dungeon', notext=true, qty=spell.requiredDungeonCompletion[2]})..' Clears'
rowTxt = rowTxt..'<br/>'..Icons.Icon({dung.name, type='dungeon', notext=true, qty=spell.requiredDungeonCompletion[2]})..' Clears'
  end
end


  if includeTypeColumn then
if includeTypeColumn then
    rowTxt = rowTxt..'||data-sort-value="'..p.getSpellTypeIndex(spell.type)..'"|'
rowTxt = rowTxt..'||data-sort-value="'..p.getSpellTypeIndex(spell.type)..'"|'
    rowTxt = rowTxt..p.getSpellTypeLink(spell.type)
rowTxt = rowTxt..p.getSpellTypeLink(spell.type)
  end
end
  --8/20/21: Changed to just getting the spell's description outright
--8/20/21: Changed to just getting the spell's description outright
  rowTxt = rowTxt..'||'..p._getSpellStat(spell, 'description')
rowTxt = rowTxt..'||'..p._getSpellStat(spell, 'description')
  if p.getSpellTypeIndex(spell.type) == 4 then
--1/4/22: haha just kidding. Now we're also getting delay between attacks for spells with special attacks
    rowTxt = rowTxt..'||'..spell.magicXP
if spell.specialAttack ~= nil then
  end
local spAtt = spell.specialAttack
  rowTxt = rowTxt..'||style="text-align:center"|'
local interval = spAtt.attackInterval ~= nil and spAtt.attackInterval or -1
  rowTxt = rowTxt..p._getSpellRunes(spell)
if interval ~= -1 then
  return rowTxt
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 / 1000, 2, 2)..'s total duration.'
end
rowTxt = rowTxt..')'
end
end
if p.getSpellTypeIndex(spell.type) == 4 then
rowTxt = rowTxt..'||'..spell.magicXP
end
rowTxt = rowTxt..'||style="text-align:center"|'
rowTxt = rowTxt..p._getSpellRunes(spell)
return rowTxt
end
end


function p.getStandardSpellsTable(frame)
function p.getStandardSpellsTable(frame)
  local result = '{|class="wikitable sortable"\r\n!colspan="2"|Spell'
local result = '{|class="wikitable sortable"\r\n!colspan="2"|Spell'
  result = result..'!!Requirements'
result = result..'!!Requirements'
  result = result..'!!style="width:275px"|Description'
result = result..'!!style="width:275px"|Description'
  result = result..'!!Runes'
result = result..'!!Runes'
  local spellList = {}
local spellList = {}
  for i, spell in Shared.skpairs(MagicData.Spells) do
for i, spell in Shared.skpairs(MagicData.Spells) do
    local rowTxt = p._getSpellRow(processSpell('Spells', i), false)
local rowTxt = p._getSpellRow(processSpell('Spells', i), false)
    result = result..rowTxt
result = result..rowTxt
  end
end
  result = result..'\r\n|}'
result = result..'\r\n|}'
  return result
return result
end
end


function p.getCurseTable(frame)
function p.getCurseTable(frame)
  local result = '{|class="wikitable sortable"\r\n!colspan="2"|Spell'
local result = '{|class="wikitable sortable"\r\n!colspan="2"|Spell'
  result = result..'!!Requirements'
result = result..'!!Requirements'
  result = result..'!!style="width:275px"|Description'
result = result..'!!style="width:275px"|Description'
  result = result..'!!Runes'
result = result..'!!Runes'
  local spellList = {}
local spellList = {}
  for i, spell in Shared.skpairs(MagicData.Curses) do
for i, spell in Shared.skpairs(MagicData.Curses) do
    local rowTxt = p._getSpellRow(processSpell('Curses', i), false)
local rowTxt = p._getSpellRow(processSpell('Curses', i), false)
    result = result..rowTxt
result = result..rowTxt
  end
end
  result = result..'\r\n|}'
result = result..'\r\n|}'
  return result
return result
end
end


function p.getAuroraTable(frame)
function p.getAuroraTable(frame)
  local result = '{|class="wikitable sortable"\r\n!colspan="2"|Spell'
local result = '{|class="wikitable sortable"\r\n!colspan="2"|Spell'
  result = result..'!!Requirements'
result = result..'!!Requirements'
  result = result..'!!style="width:275px"|Description'
result = result..'!!style="width:275px"|Description'
  result = result..'!!Runes'
result = result..'!!Runes'
  for i, spell in Shared.skpairs(MagicData.Auroras) do
for i, spell in Shared.skpairs(MagicData.Auroras) do
    local rowTxt = p._getSpellRow(processSpell('Auroras', i), false)
local rowTxt = p._getSpellRow(processSpell('Auroras', i), false)
    result = result..rowTxt
result = result..rowTxt
  end
end
  result = result..'\r\n|}'
result = result..'\r\n|}'
  return result
return result
end
end


function p.getAncientTable(frame)
function p.getAncientTable(frame)
  local result = '{|class="wikitable sortable"\r\n!colspan="2"|Spell'
local result = '{|class="wikitable sortable"\r\n!colspan="2"|Spell'
  result = result..'!!Requirements'
result = result..'!!Requirements'
  result = result..'!!style="width:275px"|Description'
result = result..'!!style="width:275px"|Description'
  result = result..'!!Runes'
result = result..'!!Runes'
  for i, spell in Shared.skpairs(MagicData.Ancient) do
for i, spell in Shared.skpairs(MagicData.Ancient) do
    local rowTxt = p._getSpellRow(processSpell('Ancient', i), false)
local rowTxt = p._getSpellRow(processSpell('Ancient', i), false)
    result = result..rowTxt
result = result..rowTxt
  end
end
  result = result..'\r\n|}'
result = result..'\r\n|}'
  return result
return result
end
end


function p.getAltSpellsTable(frame)
function p.getAltSpellsTable(frame)
  local result = '{|class="wikitable sortable"\r\n!colspan="2"|Spell'
local result = '{|class="wikitable sortable"\r\n!colspan="2"|Spell'
  result = result..'!!Requirements'
result = result..'!!Requirements'
  result = result..'!!style="width:275px"|Description'
result = result..'!!style="width:275px"|Description'
  result = result..'!!Experience'
result = result..'!!Experience'
  result = result..'!!Runes'
result = result..'!!Runes'
  local spellList = {}
local spellList = {}
  for i, spell in Shared.skpairs(MagicData.AltMagic) do
for i, spell in Shared.skpairs(MagicData.AltMagic) do
    local rowTxt = p._getSpellRow(processSpell('AltMagic', i), false)
local rowTxt = p._getSpellRow(processSpell('AltMagic', i), false)
    result = result..rowTxt
result = result..rowTxt
  end
end
  result = result..'\r\n|}'
result = result..'\r\n|}'
  return result
return result
end
end


return p
return p