Mobius Final Fantasy Wiki
m (moving most autocat logic here.)
No edit summary
 
(37 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 NAMESPACE = title.namespace
  +
local PAGENAME = title.text
   
 
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
 
t = p.parseArgs( frame.args )
 
boxes = {}
 
-- Remove margin of the table
 
style['table'].margin = "0"
 
   
  +
local autocat = false
for i, v in ipairs(t) do
 
html = {}
+
local cats = {}
  +
if NAMESPACE == 0 or args.demospace == 'main' then
-- Set box colors
 
  +
autocat = true
p.color( v.element:lower() )
 
  +
end
html = {
 
  +
local jobtype = lang:lc(args.type or '')
[1] = {
 
  +
if jobtype == "healer" then jobtype = "support" end
['bbottom'] = false,
 
  +
local isMaterial = jobtype == "material"
{ p.image( v.image ), attr = { colspan = COLS } }
 
  +
local isScroll = (mw.ustring.find(PAGENAME, "(scroll)", 1, true) or mw.ustring.find(PAGENAME, "(Scroll)", 1, true)) ~= nil
},
 
  +
local ability = args.ability or ''
[2] = {
 
  +
local hasAbility = ability ~= "" and lang:lc(ability) ~= "none" and lang:lc(ability) ~= "n/a"
{ "Job Type", css = style.th },
 
  +
{ p.formatJobtype(v['type']), css = style.td }
 
  +
t = p.parseArgs( args )
},
 
[3] = {
+
boxes = {}
  +
-- Remove margin of the table
{ "Element", css = style.th },
 
  +
style['table'].margin = "0"
{ p.element( v.element ), css = style.td }
 
},
 
[4] = {
 
{ "Skillseeds", css = style.th },
 
{ p.formatSeed( v.seeds ), css = style.td }
 
},
 
[5] = {
 
['type'] = "section",
 
{ "Ability", css = style.section, attr = {colspan='2'} }
 
},
 
[6] = {
 
{ "Name", css = style.th },
 
{ p.abilityLink( v.ability ), css = style.td }
 
},
 
[7] = {
 
['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 },
 
{ "<div style='font-size:15px;'>'''Max Lv.'''</div>" .. v.maxlv },
 
},
 
[8] = {
 
['type'] = "group", n = 3,
 
{ "<div style='font-size:15px;'>'''Attack'''</div>" .. v.attack },
 
{ "<div style='font-size:15px;'>'''Break Power'''</div>" .. v.breakpower },
 
{ "<div style='font-size:15px;'>'''Crit Chance'''</div>" .. v.crit },
 
}
 
}
 
   
  +
for i, v in ipairs(t) do
if ( (v.extraskills ~= "" and v.extraskills ~= nil) or next(skills) ~= nil ) then
 
html[#html+1] = {
+
html = {}
  +
-- Set box colors
['type'] = "section",
 
  +
p.color( lang:lc(v.element) )
{ "Extra Skills", css = style.section, attr = { colspan = COLS } }
 
  +
html = {
}
 
html[#html+1] = {
+
[1] = {
  +
['bbottom'] = false,
{ p.extraSkills( v.extraskills ), attr = { colspan = COLS } }
 
  +
{ p.image( v.image ), attr = { colspan = COLS } }
}
 
  +
},
end
 
if ( v.auto ~= "" and v.auto ~= nil ) then
+
[2] = {
  +
{ "Job Type", css = style.th },
html[#html+1] = {
 
['type'] = "section",
+
{ p.formatJobtype(v['type']), css = style.td }
  +
},
{ "Auto-Abilities", css = style.section, attr = { colspan = COLS } }
 
  +
[3] = {
}
 
  +
{ "Element", css = style.th },
html[#html+1] = {
 
{ p.autoAbilities( v.auto ), attr = { colspan = COLS } }
+
{ p.element( v.element ), css = style.td }
  +
},
}
 
  +
}
end
 
  +
if not isMaterial then
if( v.augment ~= "" and v.augment ~= nil ) then
 
  +
-- Only non-material cards create skillseeds.
-- TODO: Utilize the plus (+) symbolizing Fast Learner cards.
 
  +
html[#html+1] = {
local star, plus = string.match(v.star, '(-?%d+)(%+?)')
 
  +
{ "Skillseeds", css = style.th },
star = tonumber( star ) + 1
 
  +
{ p.formatSeed( v.seeds ), css = style.td }
html[#html+1] = {
 
  +
}
['type'] = "section",
 
  +
end
{ "Augment to " .. util.stars( star ), css = style.section, attr = { colspan = COLS } }
 
  +
if hasAbility then
}
 
html[#html+1] = {
+
html[#html+1] = {
  +
['type'] = "section",
{ p.augment( v.augment ), attr = { colspan = COLS } }
 
  +
{ "Ability", css = style.section, attr = {colspan='2'} }
}
 
  +
}
end
 
  +
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 )
+
boxes[i] = box.build ( util.sortTable(html), style, COLS )
end
+
end
  +
  +
-- the root html node
  +
local root = mw.html.create()
   
  +
-- tabbed infoboxes
local tabs = mw.html.create( 'div' )
 
  +
local tabs = mw.html.create( 'div' )
tabs :css( 'margin', "10px 10px 20px 20px" )
 
  +
tabs
:attr( 'class', 'cardtabs' )
 
  +
:addClass( 'cardtabs' )
:wikitext( p.tabber( frame ) )
 
  +
:css( 'margin', "10px 10px 20px 20px" )
if mw.title.getCurrentTitle().namespace == 0 or args.demospace == 'main' then
 
  +
:css( "width", "300px" )
tabs:wikitext('[[Category:Cards]]')
 
  +
:css( "float", "right" )
local jobtype = mw.ustring.lower(args['type'] or '')
 
  +
:wikitext( p.tabber( frame ) )
local jobtype_cats = {
 
  +
:allDone()
warrior = '[[Category:Warrior Cards]]',
 
  +
root:node(tabs)
mage='[[Category:Mage Cards]]',
 
  +
meia='[[Category:Mage Cards]][[Category:Meia Cards]]',
 
  +
-- description quote
ranger='[[Category:Ranger Cards]]',
 
  +
local info = args.info or args.description or ''
sarah='[[Category:Ranger Cards]][[Category:Sarah Cards]]',
 
  +
if info ~= '' then
monk='[[Category:Monk Cards]]',
 
  +
local quote_node = mw.html.create()
support='[[Category:Healer Cards]][[Category:Support Cards]]',
 
  +
local quote = frame:expandTemplate{title="quote", args={info, "In-game description"}}
healer='[[Category:Healer Cards]][[Category:Support Cards]]',
 
  +
quote_node:newline():wikitext(quote)
material='[[Category:Material Cards]]',
 
  +
root:node(quote_node)
}
 
  +
end
tabs:wikitext(jobtype_cats[jobtype] or '')
 
  +
local element = mw.ustring.lower(args.element or '')
 
  +
-- auto category
local element_cats = {
 
  +
if autocat then
none = '[[Category:Non-Elemental]]',
 
fire = '[[Category:Fire Element]]',
+
cats[#cats+1] = '[[Category:Ability cards]]'
  +
local jobtype_cats = {
water = '[[Category:Water Element]]',
 
wind = '[[Category:Wind Element]]',
+
warrior = '[[Category:Warrior Cards]]',
earth = '[[Category:Earth Element]]',
+
mage = '[[Category:Mage Cards]]',
light = '[[Category:Light Element]]',
+
meia = '[[Category:Mage Cards]][[Category:Meia Cards]]',
dark = '[[Category:Dark Element]]',
+
ranger = '[[Category:Ranger Cards]]',
life = '[[Category:Life Element]]',
+
sarah = '[[Category:Ranger Cards]][[Category:Sarah Cards]]',
prismatic = '[[Category:Prismatic Element]]',
+
monk = '[[Category:Monk Cards]]',
  +
support = '[[Category:Support Cards]]',
}
 
  +
healer = '[[Category:Support Cards]]',
tabs:wikitext(element_cats[element] or '')
 
  +
material = '[[Category:Material Cards]]',
local auto = args.auto or ''
 
  +
}
local ability = args.ability or ''
 
  +
cats[#cats+1] = jobtype_cats[jobtype] or ''
if ability ~= '' then
 
  +
local ele = lang:lc(args.element or '')
local abilities = util.explode('//', ability)
 
  +
local ele_cats = {
tabs:wikitext('[[Category:'.. abilities[#abilities] ..' Cards]]')
 
  +
none = '[[Category:Non-Elemental]]',
end
 
  +
fire = '[[Category:Fire Element]]',
if auto == '' then
 
tabs:wikitext('[[Category:Cards without auto-abilities]]')
+
water = '[[Category:Water Element]]',
  +
wind = '[[Category:Wind Element]]',
end
 
  +
earth = '[[Category:Earth Element]]',
end
 
  +
light = '[[Category:Light Element]]',
return tostring( tabs )
 
  +
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
 
end
   
 
function p.tabber( frame )
 
function p.tabber( frame )
local param = ""
+
local param = ""
for i, box in ipairs( boxes ) do
+
for i, box in ipairs( boxes ) do
param = param .. t[i].star .. "=" .. box
+
param = param .. t[i].star .. "=" .. box
if i == #boxes then break end
+
if i == #boxes then break end
param = param .. "|-|"
+
param = param .. "|-|"
end
+
end
return frame:extensionTag( 'tabber', param )
+
return frame:extensionTag( 'tabber', param )
 
end
 
end
   
Line 154: Line 229:
 
Example : star = "1 // 2 // 3"; job = "Mage"; attack = "10 // 20 // 30"
 
Example : star = "1 // 2 // 3"; job = "Mage"; attack = "10 // 20 // 30"
 
gives {
 
gives {
{ star = 1, job = "Mage", attack = "10" }
+
{ star = 1, job = "Mage", attack = "10" }
{ star = 2, job = "Mage", attack = "20" }
+
{ star = 2, job = "Mage", attack = "20" }
{ star = 3, job = "Mage", attack = "30" }
+
{ star = 3, job = "Mage", attack = "30" }
}
+
}
 
]]
 
]]
 
function p.parseArgs( args )
 
function p.parseArgs( args )
local t = {}
+
local t = {}
local n = 1
+
local n = 1
for k, v in pairs( args ) do
+
for k, v in pairs( args ) do
params = util.explode( '//', v )
+
params = mw.text.split( v, "%s*//%s*" )
if #params > n then n = #params end
+
if #params > n then n = #params end
for i=1, #params do
+
for i=1, #params do
if not t[i] then t[i] = {} end
+
if not t[i] then t[i] = {} end
t[i][k] = mw.text.trim( params[i] )
+
t[i][k] = mw.text.trim( params[i] )
end
+
end
end
+
end
--[[ if a value is lacking, get the previous one
+
--[[ if a value is lacking, get the previous one
except for image, extraskills, upgrade mats ]]
+
except for image, extraskills, upgrade mats ]]
for k, v in pairs( args ) do
+
for k, v in pairs( args ) do
if ( k ~= 'extraskills' and k ~= 'image' and k ~= 'augment' ) then
+
if ( k ~= 'extraskills' and k ~= 'image' and k ~= 'augment' ) then
for i=1, n do
+
for i=1, n do
if not t[i][k] then t[i][k] = t[i-1][k] end
+
if not t[i][k] then t[i][k] = t[i-1][k] end
end
+
end
end
+
end
end
+
end
return t
+
return t
 
end
 
end
   
 
-- Change box colors based on the element
 
-- Change box colors based on the element
 
function p.color( element )
 
function p.color( element )
if element == "fire" then
+
if element == "fire" then
style.th['background-color'] = "#f44336"
+
style.th['background-color'] = "#f44336"
style.section['background-color'] = "#b71c1c"
+
style.section['background-color'] = "#b71c1c"
style.color.color = "#f44336"
+
style.color.color = "#f44336"
elseif element == "water" then
+
elseif element == "water" then
style.th['background-color'] = "#448aff"
+
style.th['background-color'] = "#448aff"
style.section['background-color'] = "#0d47a1"
+
style.section['background-color'] = "#0d47a1"
style.color.color = "#2196f3"
+
style.color.color = "#2196f3"
elseif element == "earth" then
+
elseif element == "earth" then
style.th['background-color'] = "#795548"
+
style.th['background-color'] = "#795548"
style.section['background-color'] = "#3e2723"
+
style.section['background-color'] = "#3e2723"
style.color.color = "#795548"
+
style.color.color = "#795548"
elseif element == "wind" then
+
elseif element == "wind" then
style.th['background-color'] = "#8bc34a"
+
style.th['background-color'] = "#8bc34a"
style.th.color = "#212121"
+
style.th.color = "#212121"
style.section['background-color'] = "#33691e"
+
style.section['background-color'] = "#33691e"
style.color.color = "#8bc34a"
+
style.color.color = "#8bc34a"
elseif element == "dark" then
+
elseif element == "dark" then
style.th['background-color'] = "#673ab7"
+
style.th['background-color'] = "#673ab7"
style.section['background-color'] = "#311b92"
+
style.section['background-color'] = "#311b92"
style.color.color = "#673ab7"
+
style.color.color = "#673ab7"
elseif element == "light" then
+
elseif element == "light" then
style.th['background-color'] = "#ffff8d"
+
style.th['background-color'] = "#ffff8d"
style.th.color = "#212121"
+
style.th.color = "#212121"
style.section['background-color'] = "#f57f17"
+
style.section['background-color'] = "#f57f17"
style.color.color = "#ffc107"
+
style.color.color = "#ffc107"
elseif element == "life" then
+
elseif element == "life" then
style.th['background-color'] = "#f48fb1"
+
style.th['background-color'] = "#f48fb1"
style.th.color = "#212121"
+
style.th.color = "#212121"
style.section['background-color'] = "#d81b60"
+
style.section['background-color'] = "#d81b60"
style.color.color = "#f06292"
+
style.color.color = "#f06292"
elseif element == "prismatic" then
+
elseif element == "prismatic" then
style.th['background-color'] = "#cddc39"
+
style.th['background-color'] = "#cddc39"
style.section['background-color'] = "#0d47a1"
+
style.section['background-color'] = "#0d47a1"
end
+
end
 
end
 
end
   
 
-- Format image, displays title if no image
 
-- Format image, displays title if no image
 
function p.image( img )
 
function p.image( img )
if ( img ~= nil and img ~= "" ) then
+
if ( img ~= nil and img ~= "" ) then
return "[[File:" .. img .. "|350px]]"
+
return "[[File:" .. img .. "|300px]]"
else
+
else
local div = mw.html.create( 'div' )
+
local div = mw.html.create( 'div' )
div :wikitext( util.cleanTitle( mw.title.getCurrentTitle().text ) )
+
div :wikitext( util.cleanTitle( mw.title.getCurrentTitle().text ) )
:css( { ['font-size'] = "20px", ['background-color'] = "#212121",
+
:css( { ['font-size'] = "20px", ['background-color'] = "#212121",
color = "white", ['text-align'] = "center" } )
+
color = "white", ['text-align'] = "center" } )
:css( style.td )
+
:css( style.td )
return tostring( div )
+
return tostring( div )
end
+
end
 
end
 
end
   
 
-- Format skillseeds display
 
-- Format skillseeds display
 
function p.formatSeed( data )
 
function p.formatSeed( data )
if not data then data = "" end
+
local data = data or ""
  +
if data == "" then return "" end
local t = util.explode( ',', data )
 
  +
data = mw.text.trim(data)
local elmnt = {}
 
  +
local elmnt = {}
for k, v in pairs(t) do
 
elmnt[k] = util.explode( 'x', mw.text.trim(v) )
+
for v in mw.text.gsplit( data, "%s*,%s*" ) do
  +
local ele, qty = string.match(v, '(%a-)%s*x%s*(%d+)')
end
 
  +
elmnt[#elmnt+1] = string.format("%s x %s", p.seed( ele ), qty)
local seeds = ''
 
  +
end
for k, v in pairs(elmnt) do
 
  +
local seeds = table.concat(elmnt, " ")
seeds = seeds .. p.seed( mw.text.trim( v[1] ) ) .." x " .. mw.text.trim( v[2] ) .. " "
 
  +
return seeds
end
 
return seeds
 
 
end
 
end
   
 
function p.formatJobtype( jobtype )
 
function p.formatJobtype( jobtype )
local t = lang:lc( jobtype )
+
local t = lang:lc( jobtype )
local icon, name
+
local icon, name
if t == 'warrior' then
+
if t == 'warrior' then
icon = 'File:Warrior_Icon.png'
+
icon = 'File:Warrior_Icon.png'
name = 'Warrior'
+
name = 'Warrior'
elseif t == 'mage' then
+
elseif t == 'mage' then
icon = 'File:Mage_Icon.png'
+
icon = 'File:Mage_Icon.png'
name = 'Mage'
+
name = 'Mage'
elseif t == 'ranger' then
+
elseif t == 'ranger' then
icon = 'File:Ranger_Icon.png'
+
icon = 'File:Ranger_Icon.png'
name = 'Ranger'
+
name = 'Ranger'
elseif t == 'monk' then
+
elseif t == 'monk' then
icon = 'File:Monk_Icon.png'
+
icon = 'File:Monk_Icon.png'
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
icon = 'File:Material_Icon.png'
+
icon = 'File:Material_Icon.png'
name = 'Material'
+
name = 'Material'
elseif t == 'meia' then
+
elseif t == 'meia' then
icon = 'File:Meia_Icon.png'
+
icon = 'File:Meia_Icon.png'
name = 'Mage'
+
name = 'Mage'
else
+
else
return jobtype
+
return jobtype
end
+
end
return '[[' .. icon .. '|link=|x20px]]&nbsp;' .. name
+
return '[[' .. icon .. '|link=|x20px]]&nbsp;' .. name
 
end
 
end
   
 
function p.seed(elmt)
 
function p.seed(elmt)
  +
local elmt = elmt or ''
return "[[File:Seed_" .. elmt .. ".png|link=|x20px]]"
 
  +
return "[[File:Seed_" .. mw.text.trim(elmt) .. ".png|link=|x20px]]"
 
end
 
end
   
 
-- Format orbs
 
-- Format orbs
 
function p.orbs( orb )
 
function p.orbs( orb )
local data = util.explode( 'x', orb )
+
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( util.startMaj( element ), element )
+
local text = util.colorText( lang:ucfirst( element ), element )
return elmt
+
return icon .. " " .. text
 
end
 
end
   
 
-- Add element color to ability name
 
-- Add element color to ability name
 
function p.abilityLink( name )
 
function p.abilityLink( name )
local span = mw.html.create( 'span' )
+
local name = name or ""
  +
if name == '' then return '' end
span:css( style.color ):wikitext( name )
 
  +
local span = mw.html.create( 'span' )
return "[[" .. name .. "|" .. tostring(span) .. "]]"
 
  +
span:css( style.color ):wikitext( name )
  +
return "[[" .. name .. "|" .. tostring(span) .. "]]"
 
end
 
end
   
 
-- Format extra skills display
 
-- Format extra skills display
 
function p.extraSkills( data )
 
function p.extraSkills( data )
local es = mw.html.create( 'div' )
+
local es = mw.html.create( 'div' )
es:css( style.td )
+
es:css( style.td )
if ( data ~= nil and data ~= "" ) then
+
if ( data ~= nil and data ~= "" ) then
for i, v in ipairs( util.explode( ';', data ) ) do
+
for v in mw.text.gsplit( data, ";" ) do
table.insert( skills, v )
+
table.insert( skills, v )
end
+
end
end
+
end
for i, v in ipairs( skills ) do
+
for i, v in ipairs( skills ) do
local skill = util.explode( ' ', mw.text.trim(v), 2 )
+
local skill = util.explode( ' ', mw.text.trim(v), 2 )
local span = mw.html.create( 'span' )
+
local span = mw.html.create( 'span' )
span:css( { position = "absolute", right = "0", ["padding-left"] = "15px" } )
+
span:css( { position = "absolute", right = "0", ["padding-left"] = "15px" } )
span:wikitext( "A.Lv. " .. skill[1] )
+
span:wikitext( "A.Lv. " .. skill[1] )
local div = mw.html.create( 'div' )
+
local div = mw.html.create( 'div' )
local text = skill[2]
+
local text = skill[2]
if text:sub( 1, 1 ) == "*" then
+
if text:sub( 1, 1 ) == "*" then
text = text:sub( 2 )
+
text = text:sub( 2 )
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
-- Clean skills table by removing empty string
+
-- Clean skills table by removing empty string
local n, skillsNew = 1, {}
+
local n, skillsNew = 1, {}
for i, v in ipairs( skills ) do
+
for i, v in ipairs( skills ) do
if v ~= "" then
+
if v ~= "" then
skillsNew[n] = v
+
skillsNew[n] = v
n = n + 1
+
n = n + 1
end
+
end
end
+
end
skills = skillsNew
+
skills = skillsNew
return tostring(es)
+
return tostring(es)
 
end
 
end
   
 
-- Format auto abilities
 
-- Format auto abilities
 
function p.autoAbilities( data )
 
function p.autoAbilities( data )
local data = data or ""
+
local formatString = auto._formatString or auto.formatString
local div = mw.html.create( 'div' )
+
local data = data or ""
local text = ""
+
local div = mw.html.create( 'div' )
  +
local text = ""
local abilities = util.explode( ',', data )
 
  +
local abilities = mw.text.split( data, "%s*,%s*" )
for i, v in ipairs( abilities ) do
 
  +
for i, v in ipairs( abilities ) do
text = text .. "<div>" .. auto.formatString( v ) .. "</div>"
 
  +
text = text .. "<div>" .. formatString( v ) .. "</div>"
end
 
  +
end
div:css( style.td ):wikitext( text )
 
  +
div:css( style.td ):wikitext( text )
return tostring( div )
 
  +
return tostring( div )
 
end
 
end
   
 
-- Format upgrade mats
 
-- Format upgrade mats
 
function p.augment( data )
 
function p.augment( data )
local data = data or ""
+
local data = data or ""
local div = mw.html.create( 'div' )
+
local div = mw.html.create( 'div' )
local text = ""
+
local text = ""
local mats = util.explode( ',', data )
+
local mats = mw.text.split( data, "%s*,%s*" )
for i, v in ipairs( mats ) do
+
for i, v in ipairs( mats ) do
local mat = util.explode( 'x', v )
+
local mat = mw.text.split( v, "x" )
local title = "{{MaterialLink|" .. util.cleanTitle( util.trim(mat[1]) ) .. "}}"
+
local title = "{{MaterialLink|" .. util.cleanTitle( util.trim(mat[1]) ) .. "}}"
if mat[2] then
+
if mat[2] then
text = text .. "<div>" .. title .. " x" .. mat[2] .. "</div>"
+
text = text .. "<div>" .. title .. " x" .. mat[2] .. "</div>"
else
+
else
text = text .. "<div>" .. title .. "</div>"
+
text = text .. "<div>" .. title .. "</div>"
end
+
end
end
+
end
div:css( style.td ):wikitext( text )
+
div:css( style.td ):wikitext( text )
return tostring( div )
+
return tostring( 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