Mobius Final Fantasy Wiki
Register
mNo edit summary
(accept Meia, Sarah, and Sophie jobtypes, and map them to the general archetype (mage, ranger, monk).)
Line 6: Line 6:
 
local white = '☆'
 
local white = '☆'
 
local multis = {1.0, 1.1, 1.2, 1.3, 1.4, 1.7, 2.0, 2.3, 2.6, 3.0}
 
local multis = {1.0, 1.1, 1.2, 1.3, 1.4, 1.7, 2.0, 2.3, 2.6, 3.0}
  +
  +
local jobtype_icon_paths = {
  +
warrior = "Warrior Icon.png",
  +
mage = "Mage Icon.png",
  +
ranger = "Ranger Icon.png",
  +
monk = "Monk Icon.png",
  +
meia = "Mage Icon.png",
  +
sarah = "Ranger Icon.png",
  +
sophie = "Monk Icon.png",
  +
}
   
 
local function round(n)
 
local function round(n)
Line 32: Line 42:
 
local function jobtype_icon(s)
 
local function jobtype_icon(s)
 
local s = mw.ustring.lower(s or '')
 
local s = mw.ustring.lower(s or '')
  +
local filepath = jobtype_icon_paths[s]
if (s == 'warrior' or
 
  +
if filepath then
s == 'mage' or
 
 
return string.format('[[File:%s|20x20px|link=]]', filepath)
s == 'ranger' or
 
s == 'monk') then
 
return string.format('[[File:%s_Icon.png|20x20px|link=]]', s)
 
 
end
 
end
 
end
 
end

Revision as of 09:55, 18 December 2018

Tests

YesY All tests passed.

Name Expected Actual
YesY testFastSupportLevels
YesY testFastWarriorLevels
YesY testNormalSupportLevels
YesY testNormalWarriorLevels

local getArgs = require("Module:Arguments").getArgs
local yesno = require("Module:Yesno")

local p = {}
local black = '★'
local white = '☆'
local multis = {1.0, 1.1, 1.2, 1.3, 1.4, 1.7, 2.0, 2.3, 2.6, 3.0}

local jobtype_icon_paths = {
	warrior = "Warrior Icon.png",
	mage = "Mage Icon.png",
	ranger = "Ranger Icon.png",
	monk = "Monk Icon.png",
	meia = "Mage Icon.png",
	sarah = "Ranger Icon.png",
	sophie = "Monk Icon.png",
}

local function round(n)
  return math.floor(n + 0.5)
end

local function count_stars(s)
  local total = tonumber(s)
  local _, b_count, w_coun
  if s == nil then return 0 end
  if total == nil then
    _, b_count = string.gsub(s, black, '')
    _, w_count = string.gsub(s, white, '')
    total = b_count + w_count * 10
  end
  return total
end

local function number_to_stars(n)
  local total = tonumber(n)
  local w_count = math.floor(total / 10)
  local b_count = total % 10
  return string.rep(white, w_count) .. string.rep(black, b_count)
end

local function jobtype_icon(s)
  local s = mw.ustring.lower(s or '')
  local filepath = jobtype_icon_paths[s]
  if filepath then
    return string.format('[[File:%s|20x20px|link=]]', filepath)
  end
end

function p.ultimate(frame)
  local args = getArgs(frame,{
    wrappers = "Template:Ultimate ability stat"
  })
  return p._ultimate(args)
end

function p._ultimate(args)
  local gauge = {160, 155, 150, 140, 135, 130, 125, 110, 100, 80}
  local name = args.name
  local jobtype = args.jobtype or args.type
  local info = args.info or args.description
  local atk = args.atk or args.attack
  atk = tonumber(string.match(atk or '', '(%d+)%%?')) or 0
  local brk = args.brk or args.breakpower
  brk = tonumber(string.match(brk or '', '(%d+)%%?')) or 0
  local const_atk = yesno(args.const_attack, false)
  local const_brk = yesno(args.const_breakpower, false)
  local critchance = args.critchance
  local extra = args.extra
  
  local total = count_stars(critchance)
  local critstars = number_to_stars(total)
  
  local tbl = {
    {"Lv", "Ultimate Gauge", "Attack", "Break Power", "Crit Chance"}
  }
  for lv=1,10 do
    local m = multis[lv]
    local atk_n = atk * m
    local brk_n = brk * m

    if const_atk then atk_n = atk end
    if const_brk then brk_n = brk end
    local row = {
      lv,
      gauge[lv],
      atk_n .. "%",
      brk_n .. "%",
      string.format("%s (%d%%)", critstars, total * 5)
    }
    tbl[#tbl+1] = row
  end

  local root = mw.html.create('')
  root
    :wikitext(jobtype_icon(jobtype))
    :tag('b')
      :wikitext(name)
      :done()
    :newline()
    :tag("div")
      :cssText("font-style:italic")
      :wikitext('"' .. (info or '???') .. '"')
      :done()
    :newline()
  local wikitable = root:tag('table')
  :addClass('wikitable')
  for i,row in ipairs(tbl) do
    local tr = wikitable:tag('tr')
    local tagname = (i == 1) and 'th' or 'td'
    for j,col in ipairs(row) do
      tr
        :tag(tagname)
        :wikitext(col)
        :done()
    end
    tr:done():newline()
  end
  wikitable:done():newline()
  if extra then
    root:tag('b')
      :wikitext('Added Effects: ')
    root:wikitext(extra)
  end
  return tostring(root)
end

function p._main(args)
  local args = args
  local rarity = args.rarity
  local atk = args.atk or args.attack
  local brk = args.brk or args.breakpower
  local crit = args.crit or args.critchance
  local const_atk = yesno(args.const_attack, false)
  local const_brk = yesno(args.const_breakpower, false)
  local has_cooldown = yesno(args.has_cooldown, false)
  if rarity == nil then
    mw.log('ability stat: "rarity" argument is null or empty')
    return ''
  end
  local cooldowns = {8, 7, 6, 5, 4, 3, 2, 2, 1, 1}
  
  local fast = false
  local rarities = {}
  for a,b in string.gmatch(rarity, '(-?%d+)(%+?)') do
    a = tonumber(a)
    if a < 1 or 5 < a then
      error("Rarity outside the range of 1~5: "..a..b)
    elseif b == '+' then
      fast = true
    end
    rarities[a] = true
  end
  atk = tonumber(atk) or 0
  brk = tonumber(brk) or 0
  local total = count_stars(crit)
  local critstars = number_to_stars(total)
  local crit_n = string.format("%s (%d%%)", critstars, total*5)
  -- If attack is 0, then it's a support ability.
  -- If break is 0, then it's a support ability.
  local support = atk == 0 or brk == 0
  local show_atk = atk > 0
  local show_brk = brk > 0
  local show_cooldown = support or (fast and not crit) or has_cooldown
  local show_crit = crit ~= nil and total >= 0
  
  local columns = {}
  local rows = {}
  local level
  local m, c -- y = mx + c
  if support then
    m = 1
    c = 1
  else
    m = 2
    c = 0
  end
  local levels = {}
  if fast then
    for rarity=1,5 do
      local has_rarity = rarities[rarity]
      if has_rarity then
        levels[#levels+1] = rarity * m + c
      end
    end
  else
    local max_rarity = 0 -- largest rarity
    for i=1,5 do
      if rarities[i] and max_rarity < i then
        max_rarity = i
      end
    end
    for level=1, max_rarity * m + c do
      levels[#levels+1] = level
    end
  end
  table.insert(columns, 'ALv.')
  if show_atk then table.insert(columns, 'Attack') end
  if show_brk then table.insert(columns, 'Break Power') end
  if show_crit then table.insert(columns, 'Crit Chance') end
  if show_cooldown then table.insert(columns, 'Cooldown') end
  for i,level in ipairs(levels) do
    local row = {}
    local m = multis[level]
    row[#row+1] = level
    if show_atk then
      local atk_n = atk
      if not const_atk then atk_n = round(atk * m) end
      row[#row+1] = atk_n
    end
    if show_brk then
      local brk_n = brk
      if not const_brk then brk_n = round(brk * m) end
      row[#row+1] = brk_n
    end
    if show_crit then
      row[#row+1] = crit_n
    end
    if show_cooldown then
      local cooldown = cooldowns[level]
      row[#row+1] = cooldown
    end
    rows[#rows+1] = row
  end

  local wikitable, tr
  
  wikitable = mw.html.create('table'):addClass('wikitable'):newline()
  tr = mw.html.create('tr')
  for i,th in ipairs(columns) do
    tr:tag('th'):wikitext(th)
  end
  wikitable:node(tr):newline()
  for i,row in ipairs(rows) do
    tr = mw.html.create('tr')
    for j,td in ipairs(row) do
      tr:tag('td'):wikitext(td)
    end
    wikitable:node(tr):newline()
  end
  return tostring(wikitable)
end

function p.main(frame)
  local args = getArgs(frame,{
    wrappers = "Template:Ability stat"
  })
  return p._main(args)
end

function p._test()
  local args = {
    {rarity="4+",attack="450",breakpower="1",critchance="0",has_cooldown="n"},
  }
  for i,v in ipairs(args) do
    mw.log(i, p._main(v))
  end
end

return p