12,787
edits
(Further fixes) |
m (Fix typo) |
||
(24 intermediate revisions by 2 users not shown) | |||
Line 5: | Line 5: | ||
local GameData = require('Module:GameData') | local GameData = require('Module:GameData') | ||
local SkillData = GameData.skillData | local SkillData = GameData.skillData | ||
local Common = require('Module:Common') | |||
local Attacks = require('Module:Attacks') | local Attacks = require('Module:Attacks') | ||
local Icons = require('Module:Icons') | local Icons = require('Module:Icons') | ||
Line 10: | Line 11: | ||
p.spellBooks = { | p.spellBooks = { | ||
{ id = 'standard', dataID = 'standardSpells', name = 'Standard Magic', imgType = 'spell' }, | |||
{ id = 'ancient', dataID = 'ancientSpells', name = 'Ancient Magick', imgType = 'spell' }, | |||
{ id = 'archaic', dataID = 'archaicSpells', name = 'Archaic Magick', imgType = 'spell' }, | |||
{ id = 'curse', dataID = 'curseSpells', name = 'Curse', imgType = 'curse' }, | |||
{ id = 'aurora', dataID = 'auroraSpells', name = 'Aurora', imgType = 'aurora' }, | |||
{ id = 'altMagic', dataID = 'altSpells', name = 'Alt. Magic', imgType = 'spell', dataBySkill = true } | |||
} | } | ||
p.spellBookIndex = {} | p.spellBookIndex = {} | ||
for i, spellBook in ipairs(p.spellBooks) do | for i, spellBook in ipairs(p.spellBooks) do | ||
p.spellBookIndex[spellBook.id] = i | |||
end | end | ||
function p.getSpellBookID(sectionName) | function p.getSpellBookID(sectionName) | ||
if sectionName == 'Spell' or sectionName == 'Standard' then | |||
return 'standard' | |||
elseif sectionName == 'Ancient' then | |||
return 'ancient' | |||
elseif sectionName == 'Archaic' then | |||
return 'archaic' | |||
elseif sectionName == 'Curse' then | |||
return 'curse' | |||
elseif sectionName == 'Aurora' then | |||
return 'aurora' | |||
elseif Shared.contains({'Alt Magic', 'Alt. Magic', 'Alternative Magic'}, sectionName) then | |||
return 'altMagic' | |||
else | |||
return sectionName | |||
end | |||
end | end | ||
-- Retrieves all spells within the given spellbook | -- Retrieves all spells within the given spellbook | ||
function p.getSpellsBySpellBook(spellBookID) | function p.getSpellsBySpellBook(spellBookID) | ||
if type(spellBookID) == 'string' then | |||
local spellBook = GameData.getEntityByID(p.spellBooks, spellBookID) | |||
if spellBook ~= nil then | |||
if spellBook.dataBySkill then | |||
-- Data is part of the Magic skill object | |||
local magicData = GameData.getSkillData('melvorD:Magic') | |||
if magicData ~= nil then | |||
return magicData[spellBook.dataID] | |||
end | |||
else | |||
-- Data is at the root of GameData | |||
return GameData.rawData[spellBook.dataID] | |||
end | |||
end | |||
end | |||
end | end | ||
Line 64: | Line 65: | ||
name = Shared.fixPagename(name) | name = Shared.fixPagename(name) | ||
for i, spellBook in ipairs(p.spellBooks) do | |||
if spellBookID == nil or spellBookID == spellBook.id then | |||
local spells = p.getSpellsBySpellBook(spellBook.id) | |||
local spell = GameData.getEntityByName(spells, name) | |||
if spell ~= nil then | |||
return spell | |||
end | |||
end | |||
end | |||
end | end | ||
Line 78: | Line 79: | ||
local spellBookID = p.getSpellBookID(spellType) | local spellBookID = p.getSpellBookID(spellType) | ||
if spellType == nil or spellBookID ~= nil then | |||
for i, spellBook in ipairs(p.spellBooks) do | |||
if spellType == nil or spellBookID == spellBook.id then | |||
if spellBook.dataBySkill then | |||
return GameData.getEntityByID(p.getSpellsBySpellBook(spellBook.id), id) | |||
else | |||
return GameData.getEntityByID(spellBook.dataID, id) | |||
end | |||
end | |||
end | |||
end | |||
end | |||
--Returns the expansion icon for the spell if it has one | |||
function p.getExpansionIcon(frame) | |||
local spellName = frame.args ~= nil and frame.args[1] or frame | |||
local spell = p.getSpell(spellName) | |||
if spell == nil then | |||
return Shared.printError('No spell named "' .. spellName .. '" exists in the data module') | |||
end | |||
return Icons.getExpansionIcon(spell.id) | |||
end | end | ||
function p.getTypeString(spellType) | function p.getTypeString(spellType) | ||
local spellBookID = p.getSpellBookID(spellType) | |||
if spellBookID ~= nil then | |||
local spellBook = GameData.getEntityByID(p.spellBooks, spellBookID) | |||
if spellBook ~= nil then | |||
return spellBook.name | |||
end | |||
end | |||
end | end | ||
function p._getSpellIconType(spell) | function p._getSpellIconType(spell) | ||
local spellBook = GameData.getEntityByID(p.spellBooks, spell.spellBook) | |||
if spellBook == nil then | |||
-- Pick a suitable default | |||
return 'spell' | |||
else | |||
return spellBook.imgType | |||
end | |||
end | |||
function p.getSpellIconType(frame) | |||
local spellName = frame.args ~= nil and frame.args[1] or frame | |||
local spell = p.getSpell(spellName) | |||
if spell == nil then | |||
return 'spell' | |||
else | |||
return p._getSpellIconType(spell) | |||
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 | ||
local imgType = p._getSpellIconType(spell) | |||
return Icons.Icon({spell.name, type=imgType, notext=true, size=size}) | |||
end | end | ||
function p._getSpellRequirements(spell) | function p._getSpellRequirements(spell) | ||
-- All spells have a Magic level requirement | |||
local extraReqs = { | |||
{ ['type'] = 'SkillLevel', ['skillID'] = 'melvorD:Magic', ['level'] = spell.level } | |||
} | |||
if spell.requiredItemID ~= nil then | |||
table.insert(extraReqs, { ['type'] = 'SlayerItem', ['itemID'] = spell.requiredItemID }) | |||
end | |||
local resultPart = {} | |||
for i, reqs in ipairs({ extraReqs, spell.requirements }) do | |||
local reqStr = Common.getRequirementString(reqs) | |||
if reqStr ~= nil then | |||
table.insert(resultPart, reqStr) | |||
end | |||
end | |||
if Shared.tableIsEmpty(resultPart) then | |||
return 'None' | |||
else | |||
return table.concat(resultPart, '<br/>') | |||
end | |||
end | end | ||
local function formatRuneList(runes) | local function formatRuneList(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.quantity})) | |||
end | |||
end | |||
return table.concat(runeList, ', ') | |||
end | |||
function p._getSpellItems(spell) | |||
if type(spell.fixedItemCosts) == 'table' then | |||
local resultPart = {} | |||
for i, req in ipairs(spell.fixedItemCosts) do | |||
local item = Items.getItemByID(req.id) | |||
if item ~= nil then | |||
table.insert(resultPart, Icons.Icon({item.name, type='item', qty = req.quantity})) | |||
end | |||
end | |||
return table.concat(resultPart, '<br/>') | |||
else | |||
return '' | |||
end | |||
end | |||
function p.getSpellItems(frame) | |||
local spellName = frame.args ~= nil and frame.args[1] or frame | |||
local spell = p.getSpell(spellName) | |||
if spell == nil then | |||
return Shared.printError('No spell named "' .. spellName .. '" exists in the data module') | |||
end | |||
return p._getSpellItems(spell) | |||
end | end | ||
Line 176: | Line 216: | ||
local spell = p.getSpell(spellName) | local spell = p.getSpell(spellName) | ||
if spell == nil then | if spell == nil then | ||
return | return Shared.printError('No spell named "' .. spellName .. '" exists in the data module') | ||
end | end | ||
return p._getSpellRunes(spell) | return p._getSpellRunes(spell) | ||
Line 183: | Line 223: | ||
-- Generates description template data. See: altMagic.js, description() | -- Generates description template data. See: altMagic.js, description() | ||
function p._getSpellTemplateData(spell) | function p._getSpellTemplateData(spell) | ||
local templateData = nil | |||
if spell.spellBook == 'altMagic' then | |||
if spell.produces ~= nil then | |||
-- Item produced varies depending on items consumed | |||
if spell.produces == 'Bar' then | |||
templateData = { | |||
["barAmount"] = spell.productionRatio, | |||
["oreAmount"] = spell.specialCost.quantity | |||
} | |||
elseif spell.produces == 'GP' then | |||
templateData = { | |||
["percent"] = spell.productionRatio * 100 | |||
} | |||
else | |||
local itemProduced = Items.getItemByID(spell.produces) | |||
local spellNS, spellLocalID = GameData.getLocalID(spell.id) | |||
if itemProduced ~= nil and itemProduced.prayerPoints ~= nil and type(spell.fixedItemCosts) == 'table' and Shared.tableCount(spell.fixedItemCosts) == 1 and spellNS ~= 'melvorAoD' then | |||
-- Item produced is a bone and spell is not from AoD (logic from altMagic.js) | |||
local costItem = Items.getItemByID(spell.fixedItemCosts[1].id) | |||
if costItem ~= nil then | |||
templateData = { | |||
["itemName"] = costItem.name, | |||
["qty1"] = spell.fixedItemCosts[1].quantity, | |||
["qty2"] = itemProduced.prayerPoints | |||
} | |||
end | |||
end | |||
end | |||
end | |||
if templateData == nil then | |||
templateData = { | |||
["amount"] = spell.productionRatio, | |||
["percent"] = spell.productionRatio * 100, | |||
["specialCostQty"] = spell.specialCost.quantity | |||
} | |||
if type(spell.fixedItemCosts) == 'table' then | |||
for i, fixedCost in ipairs(spell.fixedItemCosts) do | |||
local item = Items.getItemByID(fixedCost.id) | |||
if item ~= nil then | |||
templateData['fixedItemName' .. (i - 1)] = item.name | |||
templateData['fixedItemQty' .. (i - 1)] = fixedCost.quantity | |||
end | |||
end | |||
end | |||
end | |||
end | |||
return (templateData or {}) | |||
end | end | ||
function p._getSpellDescription(spell) | function p._getSpellDescription(spell, inline) | ||
if inline == nil then inline = false end | |||
local connector = inline and '<br/>' or ' and ' | |||
if spell.description ~= nil then | if spell.description ~= nil then | ||
return Shared.applyTemplateData(spell.description, p._getSpellTemplateData(spell)) | |||
elseif spell.modifiers ~= nil or spell.targetModifiers ~= nil then | |||
local resultPart = {} | |||
if spell.modifiers ~= nil then | |||
table.insert(resultPart, Constants.getModifiersText(spell.modifiers, false)) | |||
end | |||
if spell.targetModifiers ~= nil then | |||
local targetModText = Constants.getModifiersText(spell.targetModifiers, false, inline) | |||
if inline then | |||
table.insert(resultPart, targetModText) | |||
else | |||
table.insert(resultPart, 'Enemies are inflicted with:<br/>' .. targetModText) | |||
end | |||
end | |||
return table.concat(resultPart, connector) | |||
elseif spell.specialAttackID ~= nil or spell.specialAttack ~= nil then | |||
local spAtt = Attacks.getAttackByID(spell.specialAttackID or spell.specialAttack) | |||
if spAtt ~= nil then | |||
return spAtt.description | |||
end | |||
elseif spell.spellBook == 'standard' then | |||
return 'Combat spell with a max hit of ' .. Shared.formatnum(spell.maxHit * 10) | |||
else | |||
return '' | |||
end | |||
end | end | ||
Line 267: | Line 316: | ||
elseif stat == 'type' then | elseif stat == 'type' then | ||
return p.getTypeString(spell.spellBook) | return p.getTypeString(spell.spellBook) | ||
elseif stat == 'spellDamage' then | |||
if spell.maxHit ~= nil then | |||
return spell.maxHit * 10 | |||
else | |||
return 0 | |||
end | |||
end | end | ||
return spell[stat] | return spell[stat] | ||
Line 276: | Line 331: | ||
local spell = p.getSpell(spellName) | local spell = p.getSpell(spellName) | ||
if spell == nil then | if spell == nil then | ||
return | return Shared.printError('No spell named "' .. spellName .. '" exists in the data module') | ||
end | end | ||
return p._getSpellStat(spell, statName) | return p._getSpellStat(spell, statName) | ||
Line 285: | Line 340: | ||
local spell = p.getSpell(spellName) | local spell = p.getSpell(spellName) | ||
if spell == nil then | if spell == nil then | ||
return | return Shared.printError('No spell named "' .. spellName .. '" exists in the data module') | ||
end | end | ||
local result = '' | local result = '' | ||
--11/01/22: Added Spell Damage for standard & archaic spells | |||
if spell.spellBook == 'standard' or spell.spellBook == 'archaic' then | |||
result = result.."\r\n|-\r\n|'''Spell Damage:''' "..p._getSpellStat(spell, 'spellDamage') | |||
end | |||
--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') | ||
Line 306: | Line 365: | ||
local spell = p.getSpell(spellName) | local spell = p.getSpell(spellName) | ||
if spell == nil then | if spell == nil then | ||
return | return Shared.printError('No spell named "' .. spellName .. '" exists in the data module') | ||
end | end | ||
return p._getSpellCategories(spell) | return p._getSpellCategories(spell) | ||
Line 312: | Line 371: | ||
function p._getAltSpellCostText(spell) | function p._getAltSpellCostText(spell) | ||
if spell.specialCost ~= nil then | |||
local costType = spell.specialCost.type | |||
if costType == nil or costType == 'None' then | |||
if type(spell.fixedItemCosts) == 'table' then | |||
local costText = {} | |||
for i, itemCost in ipairs(spell.fixedItemCosts) do | |||
local item = Items.getItemByID(itemCost.id) | |||
if item ~= nil then | |||
table.insert(costText, Icons.Icon({item.name, type='item', qty=itemCost.quantity})) | |||
end | |||
end | |||
if not Shared.tableIsEmpty(costText) then | |||
return table.concat(costText, ', ') | |||
end | |||
else | |||
return nil | |||
end | |||
else | |||
local qty = Shared.formatnum(spell.specialCost.quantity) | |||
local typeString = { | |||
['AnyItem'] = qty .. ' of any item', | |||
['BarIngredientsWithCoal'] = qty .. ' x required ores for the chosen bar', | |||
['BarIngredientsWithoutCoal'] = qty .. ' x required ores (except ' .. Icons.Icon({'Coal Ore', type='item'}) .. ') for the chosen bar', | |||
['JunkItem'] = qty .. ' of any [[Fishing#Junk|Junk]] item', | |||
['SuperiorGem'] = qty .. ' of any superior gem', | |||
['AnyNormalFood'] = qty .. ' x non-perfect food' | |||
} | |||
return typeString[costType] | |||
end | |||
end | |||
end | end | ||
function p.getSpellsProducingItem(itemID) | function p.getSpellsProducingItem(itemID) | ||
-- Only need to check Alt. Magic spells | |||
local spellList = {} | |||
-- Classify whether the item fits into various categories | |||
local isBar, isShard, isGem, isSuperiorGem, isPerfectFood = false, false, false, false, false | |||
local item = Items.getItemByID(itemID) | |||
if item ~= nil then | |||
isBar = not Shared.tableIsEmpty(GameData.getEntities(SkillData.Smithing.recipes, | |||
function(recipe) | |||
return recipe.categoryID == 'melvorD:Bars' and recipe.productID == item.id | |||
end)) | |||
isShard = GameData.getEntityByProperty(SkillData.Magic.randomShards, 'itemID', item.id) ~= nil | |||
isGem = GameData.getEntityByProperty('randomGems', 'itemID', itemID) ~= nil | |||
--Runestone can't be created by Alt Magic spells that make random superior gems. | |||
isSuperiorGem = item.type == 'Superior Gem' and item.id ~= SkillData.Mining.runestoneItemID | |||
if item.healsFor ~= nil then | |||
-- Item is food, but is it a product of perfect cooking? | |||
local cookData = GameData.getSkillData('melvorD:Cooking') | |||
if cookData ~= nil and cookData.recipes ~= nil then | |||
isPerfectFood = GameData.getEntityByProperty(cookData.recipes, 'perfectCookID', itemID) ~= nil | |||
end | |||
end | |||
end | |||
for i, spell in ipairs(p.getSpellsBySpellBook('altMagic')) do | |||
local includeSpell = false | |||
if spell.produces ~= nil then | |||
if spell.produces == itemID then | |||
includeSpell = true | |||
else | |||
includeSpell = ((isBar and spell.produces == 'Bar') or | |||
(isShard and spell.produces == 'RandomShards') or | |||
(isGem and spell.produces == 'RandomGem') or | |||
(isSuperiorGem and spell.produces == 'RandomSuperiorGem') or | |||
(isPerfectFood and spell.produces == 'PerfectFood')) | |||
end | |||
if includeSpell then | |||
table.insert(spellList, spell) | |||
end | |||
end | |||
end | |||
table.sort(spellList, function(a, b) return a.level < b.level end) | |||
return spellList | return spellList | ||
end | end | ||
Line 394: | Line 456: | ||
includeConsumes = false | includeConsumes = false | ||
end | end | ||
local runeKeys = { 'runesRequired', 'runesRequiredAlt' } | |||
local spellList = {} | |||
-- Initialize some vars & only populate if we're including resource consumptions | |||
local isJunkItem, isSuperiorGem, isNormalFood, isCoal, isBarIngredient = false, false, false, false, false | |||
if includeConsumes then | |||
local thisItem = Items.getItemByID(itemID) | |||
local junkItemIDs = GameData.getSkillData('melvorD:Fishing').junkItemIDs | |||
isJunkItem = Shared.contains(junkItemIDs, itemID) | |||
isSuperiorGem = thisItem.type == 'Superior Gem' | |||
if thisItem.healsFor ~= nil then | |||
-- Item is food, but is it from cooking & is it normal or perfect? | |||
local cookData = GameData.getSkillData('melvorD:Cooking') | |||
if cookData ~= nil and cookData.recipes ~= nil then | |||
isNormalFood = GameData.getEntityByProperty(cookData.recipes, 'productID', itemID) ~= nil | |||
end | |||
end | |||
isCoal = itemID == 'melvorD:Coal_Ore' | |||
if not isCoal then | |||
-- Don't need to check if the item is another bar ingredient if we already know it is coal | |||
local smithingRecipes = GameData.getSkillData('melvorD:Smithing').recipes | |||
for i, recipe in ipairs(smithingRecipes) do | |||
if recipe.categoryID == 'melvorD:Bars' then | |||
for k, itemCost in ipairs(recipe.itemCosts) do | |||
if itemCost.id == itemID then | |||
isBarIngredient = true | |||
break | |||
end | |||
end | |||
if isBarIngredient then | |||
break | |||
end | |||
end | |||
end | |||
end | |||
end | |||
-- Find applicable spells | |||
for i, spellBook in ipairs(p.spellBooks) do | |||
local spells = p.getSpellsBySpellBook(spellBook.id) | |||
for j, spell in ipairs(spells) do | |||
local foundSpell = false | |||
-- Check runes first | |||
for k, runeKey in ipairs(runeKeys) do | |||
if spell[runeKey] ~= nil then | |||
for m, req in ipairs(spell[runeKey]) do | |||
if req.id == itemID then | |||
foundSpell = true | |||
break | |||
end | |||
end | |||
end | |||
if foundSpell then | |||
break | |||
end | |||
end | |||
if includeConsumes and not foundSpell then | |||
-- Check items consumed by the spell | |||
-- Fixed costs first, as that is a well-defined list of item IDs | |||
if spell.fixedItemCosts ~= nil then | |||
for k, itemCost in ipairs(spell.fixedItemCosts) do | |||
if itemCost.id == itemID then | |||
foundSpell = true | |||
break | |||
end | |||
end | |||
end | |||
if not foundSpell and spell.specialCost ~= nil then | |||
local costType = spell.specialCost.type | |||
foundSpell = (isJunkItem and costType == 'JunkItem') or | |||
(isSuperiorGem and costType == 'AnySuperiorGem') or | |||
(isNormalFood and costType == 'AnyNormalFood') or | |||
((isCoal or isBarIngredient) and costType == 'BarIngredientsWithCoal') or | |||
(isBarIngredient and costType == 'BarIngredientsWithoutCoal') | |||
end | |||
end | |||
if foundSpell then | |||
table.insert(spellList, spell) | |||
end | |||
end | |||
end | |||
table.sort(spellList, function(a, b) | |||
if a.spellBook ~= b.spellBook then | |||
return p.spellBookIndex[a.spellBook] < p.spellBookIndex[b.spellBook] | |||
else | |||
return a.level < b.level | |||
end | |||
end) | |||
return spellList | return spellList | ||
end | end | ||
Line 493: | Line 555: | ||
function p.getSpellTypeLink(spellBookID) | function p.getSpellTypeLink(spellBookID) | ||
if spellBookID == 'standard' then | |||
return Icons.Icon({'Standard Magic', 'Standard', img='Standard', type='spellType'}) | return Icons.Icon({'Standard Magic', 'Standard', img='Standard', type='spellType'}) | ||
elseif spellBookID == 'ancient' then | |||
return Icons.Icon({'Ancient Magicks', 'Ancient', img='Ancient', type='spellType'}) | |||
elseif spellBookID == 'archaic' then | |||
return Icons.Icon({'Archaic Magicks', 'Archaic', img='Archaic', type='spellType'}) | |||
elseif spellBookID == 'curse' then | |||
return Icons.Icon({'Curses', 'Curse', img='Curse', type='spellType'}) | return Icons.Icon({'Curses', 'Curse', img='Curse', type='spellType'}) | ||
elseif spellBookID == 'aurora' then | |||
return Icons.Icon({'Auroras', 'Aurora', img='Aurora', type='spellType'}) | return Icons.Icon({'Auroras', 'Aurora', img='Aurora', type='spellType'}) | ||
elseif spellBookID == 'altMagic' then | |||
return Icons.Icon({'Alt. Magic', type='skill'}) | return Icons.Icon({'Alt. Magic', type='skill'}) | ||
end | end | ||
Line 509: | Line 571: | ||
end | end | ||
function p. | function p._getSpellHeader(includeTypeColumn, includeItems, includeDamage, includeExperience) | ||
local resultPart = {} | |||
table.insert(resultPart, '{|class="wikitable sortable"\n!colspan="2"| Spell') | |||
if includeTypeColumn then | |||
table.insert(resultPart, 'Spellbook') | |||
table.insert( | end | ||
table.insert( | table.insert(resultPart, 'Requirements') | ||
if includeDamage then | |||
table.insert(resultPart, 'Spell Dmg') | |||
end | |||
table.insert(resultPart, 'style="width:275px"| Description') | |||
if includeExperience then | |||
table.insert(resultPart, 'XP') | |||
end | |||
table.insert(resultPart, 'style="min-width:90px"| Runes') | |||
if includeItems then | |||
table.insert(resultPart, 'Item Cost') | |||
end | |||
return table.concat(resultPart, '\n! ') | |||
end | |||
function p._getSpellRow(spell, includeTypeColumn, includeItems, includeDamage, includeExperience) | |||
local spellBookIdx = p.spellBookIndex[spell.spellBook] | |||
local spellBook = p.spellBooks[spellBookIdx] | |||
local rowPart = {'\n|-\n|data-sort-value="' .. spell.name .. '"| '} | |||
table.insert(rowPart, Icons.Icon({spell.name, type=spellBook.imgType, notext=true, size=50})) | |||
table.insert(rowPart, '|| ' .. Icons.getExpansionIcon(spell.id) .. Icons.Icon({spell.name, type=spellBook.imgType, noicon=true})) | |||
if includeTypeColumn then | if includeTypeColumn then | ||
table.insert(rowPart, '||data-sort-value="' .. spellBookIdx .. '"| ' .. p.getSpellTypeLink(spell.spellBook)) | table.insert(rowPart, '||data-sort-value="' .. spellBookIdx .. '"| ' .. p.getSpellTypeLink(spell.spellBook)) | ||
end | end | ||
table.insert(rowPart, '||data-sort-value="' .. spell.level .. '"| ' .. p._getSpellRequirements(spell)) | |||
--11/01/22: Added base damage if requested | |||
if includeDamage then | |||
local dmg = p._getSpellStat(spell, 'spellDamage') | |||
table.insert(rowPart, (dmg > 0 and '||style="text-align:right"| ' .. dmg or '||class="table-na"| N/A')) | |||
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 | ||
table.insert(rowPart, '|| ' .. p._getSpellStat(spell, 'description')) | table.insert(rowPart, '|| ' .. p._getSpellStat(spell, 'description')) | ||
--1/4/22: haha just kidding. Now we're also getting delay between attacks for spells with special attacks | --1/4/22: haha just kidding. Now we're also getting delay between attacks for spells with special attacks | ||
local spAttID = spell.specialAttackID or spell.specialAttack | |||
local spAtt = Attacks.getAttackByID( | if spAttID ~= nil then | ||
local spAtt = Attacks.getAttackByID(spAttID) | |||
local interval = spAtt.attackInterval | local interval = spAtt.attackInterval | ||
local hits = spAtt.attackCount ~= nil and spAtt.attackCount or 1 | |||
if interval ~= nil and hits > 1 then | |||
table.insert(rowPart, '<br/>(' .. Shared.round(interval / 1000, 2, 2) .. 's delay between attacks.') | |||
if hits > 2 then | if hits > 2 then | ||
table.insert(rowPart, ' ' .. Shared.round(interval * (hits - 1) / 1000, 2, 2) .. 's total duration.') | table.insert(rowPart, ' ' .. Shared.round(interval * (hits - 1) / 1000, 2, 2) .. 's total duration.') | ||
Line 535: | Line 625: | ||
end | end | ||
end | end | ||
if spell. | if includeExperience then | ||
table.insert(rowPart, '|| ' .. | local xp = spell.baseExperience | ||
table.insert(rowPart, ((xp == nil or xp == 0) and '||class="table-na"| N/A' or '||style="text-align:right"| ' .. xp)) | |||
end | end | ||
table.insert(rowPart, '||style="text-align:center"| ' .. p._getSpellRunes(spell)) | table.insert(rowPart, '||style="text-align:center"| ' .. p._getSpellRunes(spell)) | ||
if includeItems then | |||
table.insert(rowPart, '||style="text-align:center"| ' .. p._getSpellItems(spell)) | |||
end | |||
return table.concat(rowPart) | return table.concat(rowPart) | ||
end | end | ||
function p. | function p._getSpellTable(spellList, includeTypeColumn) | ||
if type(spellList) == 'table' and not Shared.tableIsEmpty(spellList) then | |||
local includeSpellbook, includeItems, includeDamage, includeExperience = false, false, false, false | |||
if type(includeTypeColumn) == 'boolean' then | |||
includeSpellbook = includeTypeColumn | |||
end | |||
-- Check to see what columns are required | |||
for i, spell in ipairs(spellList) do | |||
if not includeItems and p._getSpellItems(spell) ~= '' then | |||
includeItems = true | |||
end | |||
if not includeExperience and spell.spellBook == 'altMagic' then | |||
includeExperience = true | |||
end | |||
if not includeDamage and (spell.spellBook == 'archaic' or spell.spellBook == 'standard') then | |||
includeDamage = true | |||
end | |||
end | |||
local spellListSorted = Shared.shallowClone(spellList) | |||
table.sort(spellListSorted, function(a, b) return a.level < b.level end) | |||
local resultPart = {p._getSpellHeader(includeSpellbook, includeItems, includeDamage, includeExperience)} | |||
for i, spell in ipairs(spellListSorted) do | |||
table.insert(resultPart, p._getSpellRow(spell, includeSpellbook, includeItems, includeDamage, includeExperience)) | |||
end | |||
table.insert(resultPart, '\n|}') | |||
return table.concat(resultPart) | |||
end | |||
end | |||
function p.getSpellTableFromList(frame) | |||
local args = frame.args ~= nil and frame.args or frame | |||
local spellListText = args[1] | |||
local includeSpellbook = args.includeSpellbook ~= nil and string.lower(args.includeSpellbook) == 'true' | |||
local spellNames = Shared.splitString(spellListText, ',') | |||
local spellList = {} | |||
for i, spellName in ipairs(spellNames) do | |||
local spell = p.getSpell(spellName) | |||
if spell == nil then | |||
return Shared.printError('No spell named "' .. spellName .. '" exists in the data module') | |||
else | |||
table.insert(spellList, spell) | |||
end | |||
end | |||
return p._getSpellTable(spellList, includeSpellbook) | |||
end | |||
function p.getSpellBookTable(frame) | |||
local spellBook = frame.args ~= nil and frame.args[1] or frame[1] | |||
spellBook = p.getSpellBookID(spellBook) | |||
return p._getSpellTable(p.getSpellsBySpellBook(spellBook), false) | |||
end | end | ||
-- Included below for backwards compatibility | -- Included below for backwards compatibility | ||
function p.getStandardSpellsTable(frame) | function p.getStandardSpellsTable(frame) | ||
return p._getSpellTable(p.getSpellsBySpellBook('standard'), false) | |||
end | end | ||
function p.getAncientTable(frame) | function p.getAncientTable(frame) | ||
return p._getSpellTable(p.getSpellsBySpellBook('ancient'), false) | |||
end | end | ||
function p.getCurseTable(frame) | function p.getCurseTable(frame) | ||
return p._getSpellTable(p.getSpellsBySpellBook('curse'), false) | |||
end | end | ||
function p.getAuroraTable(frame) | function p.getAuroraTable(frame) | ||
return p._getSpellTable(p.getSpellsBySpellBook('aurora'), false) | |||
end | end | ||
function p.getAltSpellsTable(frame) | function p.getAltSpellsTable(frame) | ||
return p._getSpellTable(p.getSpellsBySpellBook('altMagic'), false) | |||
end | end | ||
return p | return p |