Mobius Final Fantasy Wiki
mNo edit summary
No edit summary
 
(7 intermediate revisions by 2 users not shown)
Line 1: Line 1:
local p = {}
+
local p = {}
  +
local mArguments -- lazy load
  +
local mOrb = require("Module:Orb")._main
  +
local mLink = require("Module:Link")._main
   
util = require( 'Module:Utils' )
+
local util = require( 'Module:Utils' )
box = require( 'Module:Infobox' )
+
local box = require( 'Module:Infobox' )
style = require( 'Module:Infobox/CSS' )
+
local style = require( 'Module:Infobox/CSS' )
auto = require( 'Module:AutoAbilities' )
+
local auto = require( 'Module:AutoAbilities' )
COLS = "2"
+
local COLS = "2"
skills = {}
+
local skills = {}
 
local lang = mw.getContentLanguage()
 
local lang = mw.getContentLanguage()
 
local title = mw.title.getCurrentTitle()
 
local title = mw.title.getCurrentTitle()
Line 13: Line 16:
   
 
function p.main( frame )
 
function p.main( frame )
  +
mArguments = require("Module:Arguments")
local pframe = frame:getParent()
 
local args = pframe.args
+
local args = mArguments.getArgs(frame)
local config = frame.args
 
   
 
local autocat = false
 
local autocat = false
Line 23: Line 25:
 
end
 
end
 
local jobtype = lang:lc(args.type or '')
 
local jobtype = lang:lc(args.type or '')
  +
if jobtype == "healer" then jobtype = "support" end
 
local isMaterial = jobtype == "material"
 
local isMaterial = jobtype == "material"
local isScroll = mw.ustring.find(PAGENAME, "(scroll)", 1, true) ~= nil
+
local isScroll = (mw.ustring.find(PAGENAME, "(scroll)", 1, true) or mw.ustring.find(PAGENAME, "(Scroll)", 1, true)) ~= nil
 
local ability = args.ability or ''
 
local ability = args.ability or ''
 
local hasAbility = ability ~= "" and lang:lc(ability) ~= "none" and lang:lc(ability) ~= "n/a"
 
local hasAbility = ability ~= "" and lang:lc(ability) ~= "none" and lang:lc(ability) ~= "n/a"
Line 70: Line 73:
 
['type'] = "group", n = 3, ['bbottom'] = true,
 
['type'] = "group", n = 3, ['bbottom'] = true,
 
{ "<div style='font-size:15px;'>'''Orbs'''</div>" .. p.orbs( v.orbs ) },
 
{ "<div style='font-size:15px;'>'''Orbs'''</div>" .. p.orbs( v.orbs ) },
{ "<div style='font-size:15px;'>'''Range'''</div>" .. v.range },
+
{ "<div style='font-size:15px;'>'''Range'''</div>" .. (v.range or "") },
{ "<div style='font-size:15px;'>'''Max Lv.'''</div>" .. v.maxlv },
+
{ "<div style='font-size:15px;'>'''Max Lv.'''</div>" .. (v.maxlv or "") },
 
}
 
}
 
html[#html+1] = {
 
html[#html+1] = {
 
['type'] = "group", n = 3,
 
['type'] = "group", n = 3,
{ "<div style='font-size:15px;'>'''Attack'''</div>" .. v.attack },
+
{ "<div style='font-size:15px;'>'''Attack'''</div>" .. (v.attack or "") },
{ "<div style='font-size:15px;'>'''Break Power'''</div>" .. v.breakpower },
+
{ "<div style='font-size:15px;'>'''Break Power'''</div>" .. (v.breakpower or "") },
{ "<div style='font-size:15px;'>'''Crit Chance'''</div>" .. v.crit },
+
{ "<div style='font-size:15px;'>'''Crit Chance'''</div>" .. (v.crit or "") },
 
}
 
}
 
end
 
end
Line 123: Line 126:
 
:css( 'margin', "10px 10px 20px 20px" )
 
:css( 'margin', "10px 10px 20px 20px" )
 
:css( "width", "300px" )
 
:css( "width", "300px" )
  +
:css( "float", "right" )
 
:wikitext( p.tabber( frame ) )
 
:wikitext( p.tabber( frame ) )
 
:allDone()
 
:allDone()
Line 146: Line 150:
 
sarah = '[[Category:Ranger Cards]][[Category:Sarah Cards]]',
 
sarah = '[[Category:Ranger Cards]][[Category:Sarah Cards]]',
 
monk = '[[Category:Monk Cards]]',
 
monk = '[[Category:Monk Cards]]',
support = '[[Category:Healer Cards]][[Category:Support Cards]]',
+
support = '[[Category:Support Cards]]',
healer = '[[Category:Healer Cards]][[Category:Support Cards]]',
+
healer = '[[Category:Support Cards]]',
 
material = '[[Category:Material Cards]]',
 
material = '[[Category:Material Cards]]',
 
}
 
}
Line 169: Line 173:
 
-- TODO: Allow overrides. Such as if it's expecting augment or ES, but "none" is specified?
 
-- TODO: Allow overrides. Such as if it's expecting augment or ES, but "none" is specified?
 
-- TODO: Check if Meia scrolls have only "Meia Synchro"?
 
-- TODO: Check if Meia scrolls have only "Meia Synchro"?
if jobtype ~= "meia" and isScroll then
+
if isScroll then
 
-- Scrolls do not have augment, don't track.
 
-- Scrolls do not have augment, don't track.
 
-- Scrolls do not have extra skills, don't track.
 
-- Scrolls do not have extra skills, don't track.
else -- May contain Meia scrolls.
+
else
 
local stars = mw.text.split(args.star or '', "%s*//%s*")
 
local stars = mw.text.split(args.star or '', "%s*//%s*")
 
local augments = mw.text.split(args.augment or '', "%s*//%s*")
 
local augments = mw.text.split(args.augment or '', "%s*//%s*")
Line 336: Line 340:
 
name = 'Monk'
 
name = 'Monk'
 
elseif t == 'support' or t == 'healer' then
 
elseif t == 'support' or t == 'healer' then
icon = 'File:All_Icon.png'
+
icon = 'File:Support_Icon.png'
 
name = 'Support'
 
name = 'Support'
 
elseif t == 'material' then
 
elseif t == 'material' then
Line 358: Line 362:
 
function p.orbs( orb )
 
function p.orbs( orb )
 
local data = mw.text.split( orb, "x" )
 
local data = mw.text.split( orb, "x" )
  +
local icon = mOrb(data[1])
return "{{Orb|" .. data[1] .. "}} x" .. mw.text.trim( data[2] )
+
local text = "x" .. mw.text.trim( data[2] )
  +
return icon .. " " .. text
 
end
 
end
   
 
-- Format element
 
-- Format element
 
function p.element( element )
 
function p.element( element )
local elmt = "{{Orb|" .. element .. "}} "
+
local icon = mOrb(element)
elmt = elmt .. util.colorText( lang:ucfirst( element ), element )
+
local text = util.colorText( lang:ucfirst( element ), element )
return elmt
+
return icon .. " " .. text
 
end
 
end
   
Line 397: Line 403:
 
skills[i] = ""
 
skills[i] = ""
 
end
 
end
div:css( "position", "relative" ):wikitext( "{{link|" .. text .. "}}" ):node( span )
+
div:css( "position", "relative" ):wikitext( mLink{text} ):node( span )
 
es:node (div )
 
es:node (div )
 
end
 
end

Latest revision as of 08:20, 28 October 2021


local p = {}
local mArguments -- lazy load
local mOrb = require("Module:Orb")._main
local mLink = require("Module:Link")._main

local util = require( 'Module:Utils' )
local box = require( 'Module:Infobox' )
local style = require( 'Module:Infobox/CSS' )
local auto = require( 'Module:AutoAbilities' )
local COLS = "2"
local skills = {}
local lang = mw.getContentLanguage()
local title = mw.title.getCurrentTitle()
local NAMESPACE = title.namespace
local PAGENAME = title.text

function p.main( frame )
	mArguments = require("Module:Arguments")
  local args = mArguments.getArgs(frame)

  local autocat = false
  local cats = {}
  if NAMESPACE == 0 or args.demospace == 'main' then
    autocat = true
  end
  local jobtype = lang:lc(args.type or '')
  if jobtype == "healer" then jobtype = "support" end
  local isMaterial = jobtype == "material"
  local isScroll = (mw.ustring.find(PAGENAME, "(scroll)", 1, true) or mw.ustring.find(PAGENAME, "(Scroll)", 1, true)) ~= nil
  local ability = args.ability or ''
  local hasAbility = ability ~= "" and lang:lc(ability) ~= "none" and lang:lc(ability) ~= "n/a"
  
  t = p.parseArgs( args )
  boxes = {}
  -- Remove margin of the table
  style['table'].margin = "0"

  for i, v in ipairs(t) do
    html = {}
    -- Set box colors
    p.color( lang:lc(v.element) )
    html = {
      [1] = {
        ['bbottom'] = false,
        { p.image( v.image ), attr = { colspan = COLS } }
      },
      [2] = {
        { "Job Type", css = style.th },
        { p.formatJobtype(v['type']), css = style.td }
      },
      [3] = {
        { "Element", css = style.th },
        { p.element( v.element ), css = style.td }
      },
    }
    if not isMaterial then
	  -- Only non-material cards create skillseeds.
      html[#html+1] = {
        { "Skillseeds", css = style.th },
        { p.formatSeed( v.seeds ), css = style.td }
      }
    end
    if hasAbility then
      html[#html+1] = {
        ['type'] = "section",
        { "Ability", css = style.section, attr = {colspan='2'} }
      }
      html[#html+1] = {
        { "Name", css = style.th },
        { p.abilityLink( v.ability ), css = style.td }
      }
      html[#html+1] = {
        ['type'] = "group", n = 3, ['bbottom'] = true,
        { "<div style='font-size:15px;'>'''Orbs'''</div>" .. p.orbs( v.orbs ) },
        { "<div style='font-size:15px;'>'''Range'''</div>" .. (v.range or "") },
        { "<div style='font-size:15px;'>'''Max Lv.'''</div>" .. (v.maxlv or "") },
      }
      html[#html+1] = {
        ['type'] = "group", n = 3,
        { "<div style='font-size:15px;'>'''Attack'''</div>" .. (v.attack or "") },
        { "<div style='font-size:15px;'>'''Break Power'''</div>" .. (v.breakpower or "") },
        { "<div style='font-size:15px;'>'''Crit Chance'''</div>" .. (v.crit or "") },
      }
    end
    if (v.extraskills ~= "" and v.extraskills ~= nil) or next(skills) ~= nil then
      html[#html+1] = {
        ['type'] = "section",
        { "Extra Skills", css = style.section, attr = { colspan = COLS } }
      }
      html[#html+1] = {
        { p.extraSkills( v.extraskills ), attr = { colspan = COLS } }
      }
    end
    if v.auto ~= "" and v.auto ~= nil then
      html[#html+1] = {
        ['type'] = "section",
        { "Auto-Abilities", css = style.section, attr = { colspan = COLS } }
      }
      html[#html+1] = {
        { p.autoAbilities( v.auto ), attr = { colspan = COLS } }
      }
    end
    if v.augment ~= "" and v.augment ~= nil then
      -- TODO: Utilize the plus (+) symbolizing Fast Learner cards.
      local star, plus = string.match(v.star, '(-?%d+)(%+?)')
      star = tonumber( star ) + 1
      html[#html+1] = {
        ['type'] = "section",
        { "Augment to " .. util.stars( star ), css = style.section, attr = { colspan = COLS } }
      }
      html[#html+1] = {
        { p.augment( v.augment ), attr = { colspan = COLS } }
      }
    end

    boxes[i] = box.build ( util.sortTable(html), style, COLS )
  end
  
  -- the root html node
  local root = mw.html.create()

  -- tabbed infoboxes
  local tabs = mw.html.create( 'div' )
  tabs
    :addClass( 'cardtabs' )
  	:css( 'margin', "10px 10px 20px 20px" )
	:css( "width", "300px" )
	:css( "float", "right" )
    :wikitext( p.tabber( frame ) )
    :allDone()
  root:node(tabs)

  -- description quote
  local info = args.info or args.description or ''
  if info ~= '' then
    local quote_node = mw.html.create()
    local quote = frame:expandTemplate{title="quote", args={info, "In-game description"}}
    quote_node:newline():wikitext(quote)
    root:node(quote_node)
  end

  -- auto category
  if autocat then
    cats[#cats+1] = '[[Category:Ability cards]]'
    local jobtype_cats = {
      warrior = '[[Category:Warrior Cards]]',
      mage = '[[Category:Mage Cards]]',
      meia = '[[Category:Mage Cards]][[Category:Meia Cards]]',
      ranger = '[[Category:Ranger Cards]]',
      sarah = '[[Category:Ranger Cards]][[Category:Sarah Cards]]',
      monk = '[[Category:Monk Cards]]',
      support = '[[Category:Support Cards]]',
      healer = '[[Category:Support Cards]]',
      material = '[[Category:Material Cards]]',
    }
    cats[#cats+1] = jobtype_cats[jobtype] or ''
    local ele = lang:lc(args.element or '')
    local ele_cats = {
      none = '[[Category:Non-Elemental]]',
      fire = '[[Category:Fire Element]]',
      water = '[[Category:Water Element]]',
      wind = '[[Category:Wind Element]]',
      earth = '[[Category:Earth Element]]',
      light = '[[Category:Light Element]]',
      dark = '[[Category:Dark Element]]',
      life = '[[Category:Life Element]]',
      prismatic = '[[Category:Prismatic Element]]',
    }
    cats[#cats+1] = ele_cats[ele] or ''
    if hasAbility then
      local abis = mw.text.split(ability, '%s*//%s*')
      cats[#cats+1] = '[[Category:'.. abis[#abis] ..' Cards]]'
      -- TODO: Allow overrides. Such as if it's expecting augment or ES, but "none" is specified?
      -- TODO: Check if Meia scrolls have only "Meia Synchro"?
      if isScroll then
        -- Scrolls do not have augment, don't track.
        -- Scrolls do not have extra skills, don't track.
      else
        local stars = mw.text.split(args.star or '', "%s*//%s*")
        local augments = mw.text.split(args.augment or '', "%s*//%s*")
        local extras = mw.text.split(args.extraskills or '', "%s*//%s*")
        local hasAugment = true
        local hasExtra = true
        for i=1,#stars do
          local s=stars[i] or ''
          local a=augments[i-1] or ''
          local e=extras[i] or ''
          mw.log(string.format('"%s", "%s", "%s"', s,a,e), 'augment:', hasAugment, 'extra:', hasExtra)
          if i > 1 and hasAugment and s ~= "" and a=="" then
            hasAugment = false
          end
          if hasExtra and s ~= "" and e == "" then
            hasExtra = false
          end
        end
        if not hasAugment and not isScroll then
          -- Expected augment but found some missing.
          -- Scrolls do not have augment, don't track.
          cats[#cats+1] = '[[Category:Cards without augment]]'
        end
        if not hasExtra then
          -- Expected extra skill but found some missing.
          cats[#cats+1] = '[[Category:Cards without extra skill]]'
        end
      end
    end
    local auto = args.auto or ''
    if auto == '' and not isScroll and not isMaterial then
      cats[#cats+1] = '[[Category:Cards without auto-abilities]]'
    end
    root:wikitext(table.concat(cats,""))
  end

  return tostring( root )
end

function p.tabber( frame )
  local param = ""
  for i, box in ipairs( boxes ) do
    param = param .. t[i].star .. "=" .. box
    if i == #boxes then break end
    param = param .. "|-|"
  end
  return frame:extensionTag( 'tabber', param )
end

--[[ frame.args are named parameters with several values separated
by a // separator. This function creates tables of key, values.
Example : star = "1 // 2 // 3"; job = "Mage"; attack = "10 // 20 // 30"
gives {
    { star = 1, job = "Mage", attack = "10" }
    { star = 2, job = "Mage", attack = "20" }
    { star = 3, job = "Mage", attack = "30" }
  }
]]
function p.parseArgs( args )
  local t = {}
  local n = 1
  for k, v in pairs( args ) do
    params = mw.text.split( v, "%s*//%s*" )
    if #params > n then n = #params end
    for i=1, #params do
      if not t[i] then t[i] = {} end
      t[i][k] = mw.text.trim( params[i] )
    end
  end
  --[[ if a value is lacking, get the previous one
  except for image, extraskills, upgrade mats ]]
  for k, v in pairs( args ) do
    if ( k ~= 'extraskills' and k ~= 'image' and k ~= 'augment' ) then
      for i=1, n do
        if not t[i][k] then t[i][k] = t[i-1][k] end
      end
    end
  end
  return t
end

-- Change box colors based on the element 
function p.color( element )
  if element == "fire" then
    style.th['background-color'] = "#f44336"
    style.section['background-color'] = "#b71c1c"
    style.color.color = "#f44336"
  elseif element == "water" then
    style.th['background-color'] = "#448aff"
    style.section['background-color'] = "#0d47a1"
    style.color.color = "#2196f3"
  elseif element == "earth" then
    style.th['background-color'] = "#795548"
    style.section['background-color'] = "#3e2723"
    style.color.color = "#795548"
  elseif element == "wind" then
    style.th['background-color'] = "#8bc34a"
    style.th.color = "#212121"
    style.section['background-color'] = "#33691e"
    style.color.color = "#8bc34a"
  elseif element == "dark" then
    style.th['background-color'] = "#673ab7"
    style.section['background-color'] = "#311b92"
    style.color.color = "#673ab7"
  elseif element == "light" then
    style.th['background-color'] = "#ffff8d"
    style.th.color = "#212121"
    style.section['background-color'] = "#f57f17"
    style.color.color = "#ffc107"
  elseif element == "life" then
    style.th['background-color'] = "#f48fb1"
    style.th.color = "#212121"
    style.section['background-color'] = "#d81b60"
    style.color.color = "#f06292"
  elseif element == "prismatic" then
    style.th['background-color'] = "#cddc39"
    style.section['background-color'] = "#0d47a1"
  end
end

-- Format image, displays title if no image
function p.image( img )
  if ( img ~= nil and img ~= "" ) then
    return "[[File:" .. img .. "|300px]]"
  else
    local div = mw.html.create( 'div' )
    div  :wikitext( util.cleanTitle( mw.title.getCurrentTitle().text ) )
      :css( { ['font-size'] = "20px", ['background-color'] = "#212121", 
      color = "white", ['text-align'] = "center" } )
      :css( style.td )
    return tostring( div )
  end
end

-- Format skillseeds display
function p.formatSeed( data )
  local data = data or ""
  if data == "" then return "" end
  data = mw.text.trim(data)
  local elmnt = {}
  for v in mw.text.gsplit( data, "%s*,%s*" ) do
    local ele, qty = string.match(v, '(%a-)%s*x%s*(%d+)')
    elmnt[#elmnt+1] = string.format("%s x %s", p.seed( ele ), qty)
  end
  local seeds = table.concat(elmnt, " ")
  return seeds
end

function p.formatJobtype( jobtype )
  local t = lang:lc( jobtype )
  local icon, name
  if t == 'warrior' then
    icon = 'File:Warrior_Icon.png'
    name = 'Warrior'
  elseif t == 'mage' then
    icon = 'File:Mage_Icon.png'
    name = 'Mage'
  elseif t == 'ranger' then
    icon = 'File:Ranger_Icon.png'
    name = 'Ranger'
  elseif t == 'monk' then
    icon = 'File:Monk_Icon.png'
    name = 'Monk'
  elseif t == 'support' or t == 'healer' then
    icon = 'File:Support_Icon.png'
    name = 'Support'
  elseif t == 'material' then
    icon = 'File:Material_Icon.png'
    name = 'Material'
  elseif t == 'meia' then
    icon = 'File:Meia_Icon.png'
    name = 'Mage'
  else
    return jobtype
  end
  return '[[' .. icon .. '|link=|x20px]]&nbsp;' .. name
end

function p.seed(elmt)
  local elmt = elmt or ''
  return "[[File:Seed_" .. mw.text.trim(elmt) .. ".png|link=|x20px]]"
end

-- Format orbs
function p.orbs( orb )
  local data = mw.text.split( orb, "x" )
  local icon = mOrb(data[1])
  local text = "x" .. mw.text.trim( data[2] )
  return icon .. " " .. text
end

-- Format element
function p.element( element )
  local icon = mOrb(element)
  local text = util.colorText( lang:ucfirst( element ), element )
  return icon .. " " .. text
end

-- Add element color to ability name
function p.abilityLink( name )
  local name = name or ""
  if name == '' then return '' end
  local span = mw.html.create( 'span' )
  span:css( style.color ):wikitext( name )
  return "[[" .. name .. "|" .. tostring(span) .. "]]"
end

-- Format extra skills display
function p.extraSkills( data )
  local es = mw.html.create( 'div' )
  es:css( style.td )
  if ( data ~= nil and data ~= "" ) then
    for v in mw.text.gsplit( data, ";" ) do
      table.insert( skills, v )
    end
  end
  for i, v in ipairs( skills ) do
    local skill = util.explode( ' ', mw.text.trim(v), 2 )
    local span = mw.html.create( 'span' )
    span:css( { position = "absolute", right = "0", ["padding-left"] = "15px" } )
    span:wikitext( "A.Lv. " .. skill[1] )
    local div = mw.html.create( 'div' )
    local text = skill[2]
    if text:sub( 1, 1 ) == "*" then
      text = text:sub( 2 )
      skills[i] = ""
    end
    div:css( "position", "relative" ):wikitext( mLink{text} ):node( span )
    es:node (div )
  end
  -- Clean skills table by removing empty string
  local n, skillsNew = 1, {}
  for i, v in ipairs( skills ) do
    if v ~= "" then
      skillsNew[n] = v
      n = n + 1
    end
  end
  skills = skillsNew
  return tostring(es)
end

-- Format auto abilities
function p.autoAbilities( data )
  local formatString = auto._formatString or auto.formatString
  local data = data or ""
  local div = mw.html.create( 'div' )
  local text = ""
  local abilities = mw.text.split( data, "%s*,%s*" )
  for i, v in ipairs( abilities ) do
    text = text .. "<div>" .. formatString( v ) .. "</div>"
  end
  div:css( style.td ):wikitext( text )
  return tostring( div )
end

-- Format upgrade mats
function p.augment( data )
  local data = data or ""
  local div = mw.html.create( 'div' )
  local text = ""
  local mats = mw.text.split( data, "%s*,%s*" )
  for i, v in ipairs( mats ) do
    local mat = mw.text.split( v, "x" )
    local title = "{{MaterialLink|" .. util.cleanTitle( util.trim(mat[1]) ) .. "}}"
    if mat[2] then
      text = text .. "<div>" .. title .. " x" .. mat[2] .. "</div>"
    else
      text = text .. "<div>" .. title .. "</div>"
    end
  end
  div:css( style.td ):wikitext( text )
  return tostring( div )
end

return p