Mobius Final Fantasy Wiki
Advertisement

Documentation for this module may be created at Module:Autoability/doc

-- ----------------------------------------------------------------------------
-- Imports
-- ----------------------------------------------------------------------------
local getArgs = require("Module:Arguments").getArgs
local yesno = require("Module:Yesno")
local quote = require("Module:Quote")._quote
local cargo = require("Module:Cargo")

local p = {}
local lang = mw.language.new('en')
-- -------------------------------------------------------------------------
-- Strings
-- -------------------------------------------------------------------------
local i18n = {
    CELR = "Cumulative effect limit reached.",
    inf = "∞",
    icons = {
        red = "File:Icon Auto-Abilities Red.png",
        blue = "File:Icon Auto-Abilities Blue.png",
        green = "File:Icon Auto-Abilities Green.png",
        yellow = "File:Icon Auto-Abilities Yellow.png",
    },
    -- Called "Category" ingame. Refer to skill card filter in deck editor.
    categories = {
        red = "Multi-Skill",
        blue = "Auto-Skill",
        green = "Enhance/Resist",
        yellow = "Attributes",
    },
    errors = {
        minimum_not_numeric = "Provided minimum value is not a number (%s)",
        minimum_not_unique = "Provided minimum value is not unique (%s)",
    }
}

local styles = {
    clear = {
        ["clear"] = "both",
        ["height"] = "5px",
    },
    infobox = {
        ["float"] = "right",
        ["position"] = "relative",
        ["width"] = "250px",
        ["background"] = "#FFF",
        ["font-size"] = ".923em",
        ["border"] = "1px solid #AAA",
        ["margin"] = "0 0 1em 1em",
        ["padding"] = "0",
    },
    heading = {
        ["font-weight"] = "700",
        ["text-align"] = "center",
        ["border"] = "1px solid rgba(0,0,0,0.25)",
        ["border-bottom-width"] = "0",
        ["position"] = "relative",
        ["z-index"] = "1",
        ["margin"] = "-1px -1px 5px!important",
        ["font-size"] = "1.417em!important",
        ["color"] = "#fff!important",
        ["background-color"] = "#444",
        ["text-shadow"] = "rgba(0,0,0,0.75) 0 0 .25em",
        ["line-height"] = "1.176em",
        ["font-size-adjust"] = ".43",
        ["padding"] = ".5em!important",
    },
    wrapper = {
        ["clear"] = "both",
        ["padding"] = "0",
    },
    dt = {
        ["float"] = "left",
        ["text-align"] = "right",
        ["width"] = "78px",
        ["line-height"] = "1em",
        ["font-weight"] = "700",
        ["clear"] = "left",
        ["border-right"] = "2px solid #999",
        ["margin"] = "0 -2px 0 0",
        ["padding"] = "2px 8px 2px 3px",
        ["line-height"] = "1.667em",
    },
    dd = {
        ["float"] = "left",
        ["width"] = "125px",
        ["font-weight"] = "400",
        ["border-left"] = "2px solid #999",
        ["margin"] = "0",
        ["padding"] = "2px 7px",
        ["line-height"] = "1.667em",
    },
}

function p.parse_min_infos(info, minimum, maximum)
    local infos = info or ""
    if infos == "" then
        infos = {}
    elseif type(infos) == "string" then
        infos = mw.text.split(infos, "%s*;%s*")
    end
    for i=#infos,1,-1 do
        if infos[i] ~= "" then break end
        infos[i] = nil
    end
    local mins = minimum or ""
    if mins == "" then
        mins = {}
    elseif type(mins) == "string" then
        mins = mw.text.split(mins, "%s*;%s*")
    end
    for i=#mins,1,-1 do
        if mins[i] ~= "" then break end
        mins[i] = nil
    end

    if #mins == 0 and #infos == 0 then
        return {}
    elseif #mins == #infos then
        local keys = {}
        local items = {}
        for i,min in ipairs(mins) do
            local key = tonumber(min)
            if not key then
                error(string.format(i18n.errors.minimum_not_numeric, min))
            end
            if key <= maximum then
                keys[#keys+1] = key
                -- Ensure that all keys are unique.
                if items[key] then
                    error(string.format(i18n.errors.minimum_not_unique, min))
                end
                items[key] = infos[i]
            end
        end
        table.sort(keys)
        local min_infos = {}
        for i=1,#keys do
            local from = keys[i]
            local to = keys[i+1]
            if to then
                to = to - 1
            else
                to = maximum
            end
            local v = mw.text.trim(items[from])
            if v:sub(-#i18n.CELR) == i18n.CELR then -- v:endswith(i18n.CELR)
                v = mw.text.trim(v:sub(1, -#i18n.CELR - 1))
            end
            if from == maximum then
                v = v.." "..i18n.CELR
            end
            min_infos[i] = {info=mw.text.trim(v), from=from, to=to}
        end
        return min_infos
    elseif #mins == 0 then
        -- Minimum is empty, assume that infos is sorted.
        -- "", "A;B;C" = [A,B,C].
        -- "", "A;C;B" = [A,C,B].
        local min_infos = {}
        for i,v in ipairs(infos) do
            min_infos[#min_infos+1] = {info=v}
        end
        return min_infos
    elseif #infos == 0 then
        -- No description provided. What to do?
        return {}
    elseif #mins < #infos then
        -- There are not enough minimums provided. What to do?
        return {}
    elseif #infos < #mins then
        -- There are not enough descriptions provided. What to do?
        return {}
    end
end

-- Implements {{autoability}}
function p.infobox(frame)
    local args = getArgs(frame)
    
    local name = args.name or mw.title.getCurrentTitle().fullText
    local id = (args.id or name):lower():gsub("%W+", "_")
    local color = args.color or ""
    local icon = i18n.icons[color:lower()]
    local category = i18n.categories[color:lower()]
    local category_icon = icon and ("[["..icon.."|link=|16px]] "..category)
    local is_rewards_based = yesno(args.rewards_based, false)
    local value_type = (args.value_type or ""):lower()
    local is_value_hidden = yesno(args.hide_value, false)
    local info = args.info or args.description or ""
    local minimum = args.minimum or ""
    local maximum = tonumber(args.maximum) or math.huge
    local min_infos = p.parse_min_infos(info, minimum, maximum)
    
    -- Build view
    local content = mw.html.create("div")
    content
        :addClass("infobox auto-ability"):addClass(color)
        :css(styles.infobox)
        :tag("p")
            :addClass("heading")
            :css(styles.heading)
            :wikitext(name)
            :done()
        :tag("div")
            :addClass("wrapper")
            :css(styles.wrapper)
            :tag("dl")
                :tag("dt")
                    :css(styles.dt)
                    :wikitext("Value type")
                    :done()
                :tag("dd")
                    :css(styles.dd)
                    :wikitext(lang:ucfirst(value_type))
                    :done()
                :tag("dt")
                    :css(styles.dt)
                    :wikitext("Hidden value")
                    :done()
                :tag("dd")
                    :css(styles.dd)
                    :wikitext(is_value_hidden and "Yes" or "No")
                    :done()
                :tag("dt")
                    :css(styles.dt)
                    :wikitext("Category")
                    :done()
                :tag("dd")
                    :css(styles.dd)
                    :wikitext(category_icon)
                    :done()
                :tag("dt")
                    :css(styles.dt)
                    :wikitext("Main only")
                    :done()
                :tag("dd")
                    :css(styles.dd)
                    :wikitext(is_rewards_based and "Yes" or "No")
                    :done()
                :tag("dt")
                    :css(styles.dt)
                    :wikitext("Maximum")
                    :done()
                :tag("dd")
                    :css(styles.dd)
                    :wikitext(maximum == math.huge and i18n.inf or maximum)
                    :done()
                :done()
            :tag("div")
                :addClass("clear")
                :css(styles.clear)
                :done()
            :done()
    
    local quotation = mw.html.create("")
    for _,row in ipairs(min_infos) do
        local from = row.from
        local to = row.to
        if to and from == to then
            to = nil
        end
        if to and to == math.huge then
            to = "&#8734;"
        end
        local interval = table.concat({from, to}, "~")
        if interval ~= "" then
        	interval = mw.html.create("small")
        		:wikitext("'''["..interval.."]:''' ")
        		:done()
        else
        	interval = nil
        end
        local info = row.info
        quotation
            :tag("p")
                :node(interval)
                :wikitext(info)
                :done():newline()
    end
    local description_box = quote{
        text = tostring(quotation),
        source = "In-game description",
    }
    mw.logObject(quotation)
    
    local infobox = mw.html.create("")
        :node(content)
        :node(description_box)
    
    local out = tostring(infobox)

    -- ------------------------------------------------------------------------
    -- Category handling 
    -- ------------------------------------------------------------------------
    local cats = {}
    if category then
        cats[#cats+1] = lang:ucfirst(category:lower()) .. " auto-abilities"
    end
    if is_rewards_based then
        cats[#cats+1] = "Rewards-based auto-abilities"
    end
    if maximum and maximum < math.huge then
        cats[#cats+1] = "Auto-abilities with cumulative effect limits"
    end
    for i, cat in ipairs(cats) do
        cats[i] = string.format("[[Category:%s]]", cat)
    end
    out = out..table.concat(cats)
    
    -- ------------------------------------------------------------------------
    -- Store cargo data
    -- ------------------------------------------------------------------------
    --[[cargo.store("autoabilities", {
        id = id,
        name = name,
        color = color,
        icon = icon,
        category = category,
        is_rewards_based = is_rewards_based and 1 or 0,
        value_type = value_type,
        is_value_hidden = is_value_hidden and 1 or 0,
        maximum = maximum,
    })]]
    for _,row in ipairs(min_infos) do
        local from = row.from
        local to = row.to or maximum
        to = math.min(to + 1, maximum)
        local info = row.info
        --[[cargo.attach("autoabilities_min_infos", {
            from = from,
            to = to,
            info = info,
        })]]
        mw.log(from, to, info)
    end
    --mw.log(out)
    return out
end

function p.test()
    p.infobox{
        name = "Crystal Seeker",
        description = [[Ever so slightly raises the chance to obtain crystals as drops.;
        Slightly raises the chance to obtain crystals as drops.;
        Raises the chance to obtain crystals as drops.;]],
        minimum = [[5; 15; 40]],
        value_type = "number",
        hide_value = "n",
        color = "blue",
    }
    p.infobox{
        name = "Crystal Seeker",
        description = [[Ever so slightly raises the chance to obtain crystals as drops.;
        Slightly raises the chance to obtain crystals as drops.;
        Raises the chance to obtain crystals as drops.;]],
        minimum = [[5; 15; 40]],
        maximum = 100,
        value_type = "number",
        hide_value = "n",
        color = "blue",
    }
    p.infobox{
        name = "Job Change Recast",
        description = [[
        Job Change recast: 4 turns. ;
        Job Change recast: 3 turns. ;
        Job Change recast: 2 turns. Cumulative effect limit reached. ;]],
        minimum = [[0; 1; 2]],
        --maximum = "2",
        value_type = "number",
        hide_value = "y",
        color = "blue",
    }
    p.infobox{
        name = "Job Change Recast",
        description = [[
        Job Change recast: 4 turns. ;
        Job Change recast: 3 turns. ;
        Job Change recast: 2 turns. ;]],
        minimum = [[0; 1; 2]],
        maximum = "2",
        value_type = "number",
        hide_value = "y",
        color = "blue",
    }
end

return p
Advertisement