Difference between revisions of "Module:Spellbook"

From CrawlWiki
Jump to: navigation, search
(Add spellbook_info to get infobox and flavour.)
m (book_rarity was removed in 0.27)
 
(4 intermediate revisions by one other user not shown)
Line 4: Line 4:
 
local spell_data = mw.loadData('Module:Table of spells')
 
local spell_data = mw.loadData('Module:Table of spells')
  
local function table_keys_sorted(t)
+
local function table_keys_sorted(t, f)
 
   local keys = {}
 
   local keys = {}
 
   for k in pairs(t) do
 
   for k in pairs(t) do
 
     table.insert(keys, k)
 
     table.insert(keys, k)
 
   end
 
   end
   table.sort(keys)
+
   table.sort(keys, f)
 
   return keys
 
   return keys
 
end
 
end
  
local function spell_school_link(school)
+
local function format_schools(frame, schools, no_link_for)
  local skill = nil
 
  if school == 'Poison' or school == 'Air' or school == 'Fire' or
 
    school == 'Ice' or school == 'Earth' then
 
    skill = school .. ' Magic'
 
  elseif school:sub(-1) ~= 'y' and school:sub(-1) ~= 's' then
 
    -- "Necromancy" isn't pluralised as a skill,
 
    -- and "Hexes" and "Charms" are already
 
    -- pluralized as a magic school.  The others
 
    -- are singular as a school, plural as a skill.
 
    skill = school .. 's'
 
  end
 
 
 
  if skill ~= nil then
 
    return '[[' .. skill .. '|' .. school .. ']]'
 
  else
 
    return '[[' .. school .. ']]'
 
  end
 
end
 
 
 
local function format_schools(schools, no_link_for)
 
 
   local ret = ''
 
   local ret = ''
   for school in pairs(schools) do
+
   for _, school in ipairs(table_keys_sorted(schools)) do
 
     if school == no_link_for then
 
     if school == no_link_for then
 
       ret = ret .. school .. '/'
 
       ret = ret .. school .. '/'
 
     else
 
     else
       ret = ret .. spell_school_link(school) .. '/'
+
       ret = ret ..
 +
        frame:expandTemplate{title = 'schoollink', args = {school}} .. '/'
 
     end
 
     end
 
   end
 
   end
 
   return ret:sub(1, -2)
 
   return ret:sub(1, -2)
 +
end
 +
 +
local function main_school(book)
 +
  local schools = {}
 +
  local num_spells = 0
 +
  for _,name in pairs(book.spells) do
 +
    num_spells = num_spells + 1
 +
    for school in pairs(spell_data[name]['schools']) do
 +
      if schools[school] == nil then
 +
        schools[school] = 1
 +
      else
 +
        schools[school] = schools[school] + 1
 +
      end
 +
    end
 +
  end
 +
 +
  local found = nil
 +
  for school,count in pairs(schools) do
 +
    if count == num_spells then
 +
      if found ~= nil then return nil end
 +
      found = school
 +
    end
 +
  end
 +
  if found ~= nil then
 +
    return found
 +
  end
 +
  for school,count in pairs(schools) do
 +
    if count == num_spells - 1 then
 +
      if found ~= nil then return nil end
 +
      found = school
 +
    end
 +
  end
 +
  return found
 
end
 
end
  
Line 50: Line 64:
 
     return ''
 
     return ''
 
   end
 
   end
   book = book:gsub("^Book of", "book of")
+
   book = book:gsub('^Book of', 'book of')
 
   local result = [==[{| cellpadding="5" border="1"
 
   local result = [==[{| cellpadding="5" border="1"
 
|- align="center"
 
|- align="center"
Line 56: Line 70:
 
]==]
 
]==]
 
   local letters = 'abcdefghijklmnopqrstuvwxyz'
 
   local letters = 'abcdefghijklmnopqrstuvwxyz'
   for i,name in pairs(book_data[book].spells) do
+
   for i,name in ipairs(book_data[book].spells) do
 
     result = result .. '|-\n| [[File:' .. name:lower() .. '.png]] || ' ..
 
     result = result .. '|-\n| [[File:' .. name:lower() .. '.png]] || ' ..
 
       letters:sub(i, i) .. ' - [[' .. name .. ']] || ' ..
 
       letters:sub(i, i) .. ' - [[' .. name .. ']] || ' ..
       format_schools(spell_data[name].schools) .. ' || ' ..
+
       format_schools(frame, spell_data[name].schools) .. ' || ' ..
 
       spell_data[name].level .. '\n'
 
       spell_data[name].level .. '\n'
 
   end
 
   end
Line 73: Line 87:
 
   local school = frame.args[2]
 
   local school = frame.args[2]
 
   if school == '' then school = nil end
 
   if school == '' then school = nil end
   local result = "'''[[" .. book:gsub("^%l", string.upper) .. "]]''': "
+
   local result = "'''[[" .. book:gsub('^%l', string.upper) .. "]]''': "
 
   local spell_list = {}
 
   local spell_list = {}
   book = book:gsub("^Book of", "book of")
+
   book = book:gsub('^Book of', 'book of')
   for _,name in pairs(book_data[book].spells) do
+
   for _,name in ipairs(book_data[book].spells) do
 
     if school == nil or spell_data[name]['schools'][school] then
 
     if school == nil or spell_data[name]['schools'][school] then
 
       table.insert(spell_list, '[['.. name .. ']]')
 
       table.insert(spell_list, '[['.. name .. ']]')
Line 83: Line 97:
 
   result = result .. table.concat(spell_list, ', ')
 
   result = result .. table.concat(spell_list, ', ')
 
   return result
 
   return result
 +
end
 +
 +
local function compare_books(a, b)
 +
  return a:lower():gsub('^book of ', ''):gsub('^a ', ''):gsub('^the ', '') <
 +
    b:lower():gsub('^book of ', ''):gsub('^a ', ''):gsub('^the ', '')
 
end
 
end
  
Line 94: Line 113:
 
     ret = ret .. ';Main Texts\n'
 
     ret = ret .. ';Main Texts\n'
 
     for book in string.gmatch(primary_books, '[^,]+') do
 
     for book in string.gmatch(primary_books, '[^,]+') do
       ret = ret .. ':' .. frame:expandTemplate{title = 'spellbook2', args = {book, school}} .. '\n'
+
       ret = ret .. ':' ..
       done[book:gsub("^Book of", "book of")] = true
+
        frame:expandTemplate{title = 'spellbook2', args = {book, school}} ..
 +
        '\n'
 +
       done[book:gsub('^Book of', 'book of')] = true
 
     end
 
     end
 
   end
 
   end
Line 112: Line 133:
 
   if next(found) ~= nil then
 
   if next(found) ~= nil then
 
     ret = ret .. ';Other Texts\n'
 
     ret = ret .. ';Other Texts\n'
    -- TODO: ignore "the" while sorting
+
     for _,book in ipairs(table_keys_sorted(found, compare_books)) do
     for _,book in ipairs(table_keys_sorted(found)) do
+
       ret = ret .. ':' ..
       ret = ret .. ':' .. frame:expandTemplate{title = 'spellbook2', args = {book, school}} .. '\n'
+
        frame:expandTemplate{title = 'spellbook2', args = {book, school}} ..
 +
        '\n'
 
     end
 
     end
 
   end
 
   end
Line 123: Line 145:
 
function p.spellbook_info(frame)
 
function p.spellbook_info(frame)
 
   local name = frame.args[1]
 
   local name = frame.args[1]
   if not name or name == "" then
+
   if not name or name == '' then
 
     name = mw.title.getCurrentTitle().text
 
     name = mw.title.getCurrentTitle().text
 
   end
 
   end
   name = name:gsub("^Book of", "book of")
+
   name = name:gsub('^Book of', 'book of')
 
   local book = book_data[name]
 
   local book = book_data[name]
 
   if not book then
 
   if not book then
Line 133: Line 155:
  
 
   local args = {}
 
   local args = {}
   args.name = book.name:gsub("^%l", string.upper)
+
   args.name = book.name:gsub('^%l', string.upper)
  args.rarity = book.rarity
 
  
   local schools = {}
+
   local school = main_school(book)
  for _,name in pairs(book.spells) do
+
  if school ~= nil then
    for school in pairs(spell_data[name]['schools']) do
+
    args.school = school
      if schools[school] == nil then
 
        schools[school] = 1
 
      else
 
        schools[school] = schools[school] + 1
 
      end
 
    end
 
 
   end
 
   end
  for school,count in pairs(schools) do
 
    if count < #book.spells - 1 then
 
      schools[school] = nil
 
    end
 
  end
 
  args.school = format_schools(schools)
 
  
 
   local infobox = frame:expandTemplate{title = 'book', args = args}
 
   local infobox = frame:expandTemplate{title = 'book', args = args}
Line 162: Line 171:
 
   return infobox .. '\n' .. flavour
 
   return infobox .. '\n' .. flavour
 
end
 
end
 
  
 
return p
 
return p

Latest revision as of 13:40, 4 November 2021

This module generates the spellbook tables in the pages of the category Category:Book, and the lists of spells in the Book page.

Required by: Template:Spellbook and Template:Spellbook2.

Requires: Module:Table of spellbooks and Module:Table of spells


local p = {}

local book_data = mw.loadData('Module:Table of spellbooks')
local spell_data = mw.loadData('Module:Table of spells')

local function table_keys_sorted(t, f)
  local keys = {}
  for k in pairs(t) do
    table.insert(keys, k)
  end
  table.sort(keys, f)
  return keys
end

local function format_schools(frame, schools, no_link_for)
  local ret = ''
  for _, school in ipairs(table_keys_sorted(schools)) do
    if school == no_link_for then
      ret = ret .. school .. '/'
    else
      ret = ret ..
        frame:expandTemplate{title = 'schoollink', args = {school}} .. '/'
    end
  end
  return ret:sub(1, -2)
end

local function main_school(book)
  local schools = {}
  local num_spells = 0
  for _,name in pairs(book.spells) do
    num_spells = num_spells + 1
    for school in pairs(spell_data[name]['schools']) do
      if schools[school] == nil then
        schools[school] = 1
      else
        schools[school] = schools[school] + 1
      end
    end
  end

  local found = nil
  for school,count in pairs(schools) do
    if count == num_spells then
      if found ~= nil then return nil end
      found = school
    end
  end
  if found ~= nil then
    return found
  end
  for school,count in pairs(schools) do
    if count == num_spells - 1 then
      if found ~= nil then return nil end
      found = school
    end
  end
  return found
end

function p.spellbook_table(frame)
  local book = frame.args[1]
  if not book then
    return ''
  end
  book = book:gsub('^Book of', 'book of')
  local result = [==[{| cellpadding="5" border="1"
|- align="center"
! Tile || Spell || Type || Level
]==]
  local letters = 'abcdefghijklmnopqrstuvwxyz'
  for i,name in ipairs(book_data[book].spells) do
    result = result .. '|-\n| [[File:' .. name:lower() .. '.png]] || ' ..
       letters:sub(i, i) .. ' - [[' .. name .. ']] || ' ..
       format_schools(frame, spell_data[name].schools) .. ' || ' ..
       spell_data[name].level .. '\n'
  end
  result = result .. '|}\n'
  return result
end

function p.short_spell_list(frame)
  local book = frame.args[1]
  if not book then
    return ''
  end
  local school = frame.args[2]
  if school == '' then school = nil end
  local result = "'''[[" .. book:gsub('^%l', string.upper) .. "]]''': "
  local spell_list = {}
  book = book:gsub('^Book of', 'book of')
  for _,name in ipairs(book_data[book].spells) do
    if school == nil or spell_data[name]['schools'][school] then
      table.insert(spell_list, '[['.. name .. ']]')
    end
  end
  result = result .. table.concat(spell_list, ', ')
  return result
end

local function compare_books(a, b)
  return a:lower():gsub('^book of ', ''):gsub('^a ', ''):gsub('^the ', '') <
    b:lower():gsub('^book of ', ''):gsub('^a ', ''):gsub('^the ', '')
end

function p.spell_sources(frame)
  local school = frame.args[1]
  local primary_books = frame.args[2]

  local done = {}
  local ret = ''
  if primary_books ~= nil and primary_books ~= '' then
    ret = ret .. ';Main Texts\n'
    for book in string.gmatch(primary_books, '[^,]+') do
      ret = ret .. ':' ..
        frame:expandTemplate{title = 'spellbook2', args = {book, school}} ..
        '\n'
      done[book:gsub('^Book of', 'book of')] = true
    end
  end

  local found = {}
  for _,spell in pairs(spell_data) do
    if spell['schools'][school] then
      for book in pairs(spell['books']) do
        if not done[book] and not found[book] then
          found[book] = true
        end
      end
    end
  end

  if next(found) ~= nil then
    ret = ret .. ';Other Texts\n'
    for _,book in ipairs(table_keys_sorted(found, compare_books)) do
      ret = ret .. ':' ..
        frame:expandTemplate{title = 'spellbook2', args = {book, school}} ..
        '\n'
    end
  end

  return ret:sub(1, -2)
end

function p.spellbook_info(frame)
  local name = frame.args[1]
  if not name or name == '' then
    name = mw.title.getCurrentTitle().text
  end
  name = name:gsub('^Book of', 'book of')
  local book = book_data[name]
  if not book then
    return name
  end

  local args = {}
  args.name = book.name:gsub('^%l', string.upper)

  local school = main_school(book)
  if school ~= nil then
    args.school = school
  end

  local infobox = frame:expandTemplate{title = 'book', args = args}

  local flavour = book.description
  if book.quote then
    flavour = flavour .. '\n----\n' .. book.quote:gsub('\n', '<br>')
  end
  flavour = frame:expandTemplate{title = 'flavour', args = {flavour}}
  return infobox .. '\n' .. flavour
end

return p