FANDOM


p = {}
 
local getArgs = require("Dev:Arguments").getArgs
local ffwiki = require("Module:HF")
local constants = mw.loadData("Module:FFXIV Data/Constants")
local html = mw.html
 
---BEGIN DEPRECATED CODE
--Tomestones database
function p.Tomestones(frame)
    local args = getArgs(frame)
    local data = mw.loadData("Module:FFXIV Data/Tomestones")
 
    local typ = string.lower(args.type)
    local ilv = tonumber(args.ilvl)
    local tomes = {0, 0, 0}
    if data[typ] and data[typ][ilv] then
        tomes = data[typ][ilv]
    else
        tomes = {tonumber(args.tome1) or 0, tonumber(args.tome2) or 0, tonumber(args.tome3) or 0}
    end
 
    local rv = ""
    if tomes == {0, 0, 0} then return rv end
    for i, v in pairs(tomes) do
        local tdata = data.tomes[i] or ffwiki.err("Missing data in [[Module:FFXIV Data/Tomestones]], contact an admin!")
        if v > 0 then rv = rv .. "[[" .. tdata[2] .. "|25px|" .. tdata[1] .. "]] " .. v .. "<br/>" end
    end
 
    return rv
end
 
--Links database; used to generate templates
function p.Links(frame)
    local arg = getArgs(frame)[1]
    local links = mw.loadData("Module:FFXIV Data/Links")[arg]
    local categories = mw.loadData("Module:FFXIV Data/Categories")[arg]
 
    local linked = {}
    local groups = {}
    for i, v in ipairs(categories) do
        table.insert(groups, {})
    end
 
    local stdstr = "Final Fantasy XIV " .. arg
    local stdlen = string.len(stdstr .. "/")
 
    local tbl = html.create("table"):addClass("FFXIV full-width article-table")
    tbl:tag("th")
        :addClass("a")
        :attr("colspan", 2)
        :wikitext("''[[Final Fantasy XIV]]'' [[Final Fantasy XIV " .. arg .. "|" .. getArgs(frame).title .. "]]")
 
    for i, v in ipairs(links) do
        if not linked[v[1]] and string.len(v[1]) > stdlen then
            linked[v[1]] = 1
            table.insert(groups[v[2] + 1], v[1])
        end
    end
 
    for i, v in ipairs(groups) do
        if #v > 0 then
            local row = tbl:tag("tr")
            row:tag("th")
                :addClass("b")
                :attr("style","width:30%")
                :wikitext(categories[i])
            dot = 0
            local txt = ""
            for j, w in ipairs(v) do
                if dot == 1 then
                    txt = txt .. " - "
                end
                txt = txt .. "[" .. "[" .. w .. "|" .. w:sub(stdlen + 1) .. "]]"
                dot = 1
            end
            row:tag("td"):wikitext(txt)
        end
    end
    return tbl
end
---END DEPRECATED CODE
 
local function loadDb(db)
    --Safely loads a db, returning an empty table if one doesn't exist.
    local err, tbl = pcall(mw.loadData, "Module:FFXIV Data/" .. db)
    if not err then return {} else return tbl end
end
 
local function subDb(db, id)
    --Get the subdatabase corresponding to an id.
    if not id then return {} end
    local subdivision = loadDb(db).subdivision
    local subdb = 1
    for j, v in ipairs(subdivision or {}) do
        if v <= id then subdb = j end
    end
    return loadDb(db .. "/" .. tostring(subdb))
end
 
local function getId(db, name)
    return loadDb(db).index[name]
end
 
local function lookupById(db, id)
    return subDb(db, id)[id] or nil
end
 
local function lookup(db, name)
    return lookupById(db, getId(db, name))
end
 
local function lookupAll(db, startId, endId)
    local content = {}
    for id=startId,endId do
        local unit = lookupById(db, id)
        if unit then content[id] = unit end
    end
    return content
end
 
local function nameEntry(name, icon)
    local entry = name or "&mdash;"
    if icon then entry = entry .. "<br/>" .. iconById(icon) end
    return entry
end
 
local function listToList(list)
    -- Turns a Lua list (table indexed by naturals) to a <ul>
    local ul = html.create("ul")
    for j, v in ipairs(list) do
        ul:tag("td")
            :wikitext(tostring(v))
    end
    return ul
end
 
 
---------------FFXIV Editors: To make new tables, edit below this line.
--General lookup
function p.Lookup(frame)
    local args = getArgs(frame)
    --1: database name
    --2: object name or id
    --3: attr
    --4: subattr
    --5: subsubattr...
    local data
    if tonumber(args[2]) then
        data = lookupById(args[1], tonumber(args[2]))
    else
        data = lookup(args[1], args[2])
    end
    if not data then return args[2] .. " doesn't exist" end
    local j = 3
    while args[j] and data[args[j]] do
        data = data[args[j]]
        j = j + 1
    end
    return tostring(data)
end
 
 
 
--Translations
function p.TranslationsTable(frame)
    local args = getArgs(frame)
    --1: database name
    --2: start here
    --3: end here
    local db = args[1]
    local startId = args[2] or 1
    local endId = args[3] or loadDb(db).last
    local content = lookupAll(db, startId, endId)
    local romajiDb = loadDb("Romaji/" .. db)
 
    local tbl = html.create("table")
        :addClass("full-width sortable article-table translations FFXIV")
        :tag("tr")
            :addClass("a")
        :tag("th")
            :cssText("width: 25%")
            :wikitext("Japanese")
            :done()
        :tag("th")
            :cssText("width: 25%")
            :wikitext("Romaji")
            :done()
        :tag("th")
            :cssText("width: 25%")
            :wikitext("Literal")
            :done()
        :tag("th")
            :cssText("width: 25%")
            :wikitext("English")
            :allDone()
    for id=startId,endId do
        local official = content[id]
        if official then
            local romaji = romajiDb[official.name] or romajiDb[official.name_en] or {"&mdash;", "&mdash;"}
            tbl:tag("tr")
                :tag("td")
                    :addClass("b")
                    :wikitext(official.name_ja or "&mdash;")
                    :done()
                :tag("td")
                    :wikitext(romaji[1])
                    :done()
                :tag("td")
                    :wikitext(romaji[2])
                    :done()
                :tag("td")
                    :wikitext(official.name_en or official.name or "&mdash;")
                    :done()
        end
    end
    return tbl
end
 
 
 
--Icons
local function iconFile(id)
    return "File:Icon " .. tostring(id) .. " from FFXIV.png"
end
 
local function iconById(id)
    return '[[' .. iconFile(id) .. ']]'
end
 
function p.IconById(frame)
    return iconById(getArgs(frame)[1])
end
 
function p.IconByMeaning(frame)
    local args = getArgs(frame)
    local meaning = lookup(args[1], args[2])
    if not meaning or not meaning.icon then return '' end
    return '[[' .. iconFile(meaning.icon) .. (meaning.name and ('|' .. meaning.name)) .. ']]'
end
 
 
 
 
 
--Achievements
local function makeAchievementHeader()
    local tbl = html.create("table")
        :addClass("full-width sortable article-table FFXIV")
        :tag("tr")
            :addClass("a")
        :tag("th")
            :cssText("width: 25%")
            :wikitext("Name")
            :done()
        :tag("th")
            :cssText("width: 15%")
            :wikitext("Type")
            :done()
        :tag("th")
            :cssText("width: 15%")
            :wikitext("Title")
            :done()
        :tag("th")
            :cssText("width: 40%")
            :wikitext("Description")
            :done()
        :tag("th")
            :cssText("width: 5%")
            :wikitext("Patch")
            :allDone()
    return tbl
end
 
local function parseAchiData(achiData)
    if achiData then
        return html.create("tr")
            :tag("th")
                :addClass("b")
                :wikitext(nameEntry(achiData.name, achiData.icon))
                :done()
            :tag("td")
                :wikitext((achiData.kind_name or "&mdash;") .. ": " .. (achiData.category_name or "&mdash;")):done()
            :tag("td")
                :wikitext((achiData.title and (achiData.title.name or "&mdash;")) or "&mdash;"):done()
            :tag("td")
                :wikitext(achiData.help or "&mdash;")
                :done()
            :tag("td")
                :wikitext(achiData.patch.number or "&mdash;")
                :allDone()
    end
end
 
function p.AchievementTable(frame)
    local args = getArgs(frame)
    local tbl = makeAchievementHeader()
    for j, achi in ipairs(args) do
        tbl:node(parseAchiData(lookup("achievement", achi)))
    end
    return tbl
end
 
function p.AllAchievementTable(frame)
    local args = getArgs(frame)
    local tbl = makeAchievementHeader()
    for j=1,2500 do --Change for 5.x!
        local achiData = lookupById("achievement", j)
        if achiData and achiData.kind_name == args[1] and achiData.category_name == args[2] then
            tbl:node(parseAchiData(achiData))
        end
    end
    return tbl
end
 
 
 
 
 
--Enemies
function p.EnemyTable(frame)
    return ""
end
 
 
 
 
 
--Instances
local function lookupDuty(truename, attr)
    if truename and truename ~= '' then
        local inst = lookup("instance", truename)
        if inst and inst[attr] then return inst[attr] end
    end
end
 
function p.InstanceType(frame)
    local args = getArgs(frame)
    local typ = lookupDuty(args[1], "content_name")
    if typ then typ = typ:sub(1, -2)
    else typ = args[2] end
    return "[[File:FFXIV " .. typ .. " Icon.png|25px]] [[Duty#" .. typ .. "s|" .. typ .. "]]"
end
 
function p.InstanceLevel(frame)
    local args = getArgs(frame)
    local lv = lookupDuty(args[1], "level") or args[2]
    local lvSync = lookupDuty(args[1], "level_sync") or args[3]
    return lv .. "&nbsp; (Synced to " .. lvSync .. ")"
end
 
function p.InstanceILevel(frame)
    local args = getArgs(frame)
    local lv = lookupDuty(args[1], "item_level") or args[2]
    local lvSync = lookupDuty(args[1], "level_sync") or args[3]
    if lvSync then lvSync = "&nbsp; (Synced to " .. lvSync .. ")"
    else lvSync = "" end
    return lv .. lvSync
end
 
function p.InstanceTime(frame)
    local args = getArgs(frame)
    local tim = lookupDuty(args[1], "time_limit")
    if tim then tim = tim .. " minutes"
    else tim = args[2] end
    return tim
end
 
 
 
--Items
local function makeItemHeader()
    return html.create("table")
        :addClass("full-width sortable article-table FFXIV")
        :tag("tr")
            :addClass("a")
        :tag("th")
            :attr("rowspan", 2)
            :cssText("width: 20%")
            :wikitext("Name")
            :done()
        :tag("th")
            :cssText("width: 15%")
            :wikitext("Type")
            :done()
        :tag("th")
            :cssText("width: 5%")
            :wikitext("iLv")
            :done()
        :tag("th")
            :attr("rowspan", 2)
            :cssText("width: 60%")
            :wikitext("Description")
            :allDone()
        :tag("tr")
            :addClass("a")
        :tag("th")
            :wikitext("Equip")
            :done()
        :tag("th")
            :wikitext("Patch")
            :allDone()
        :tag("tr")
        :tag("th")
            :addClass("a")
            :attr("colspan", 3)
            :wikitext("Materials")
            :done()
        :tag("th")
            :addClass("a")
            :wikitext("Crafting")
            :allDone()
end
 
local function parseItemData(itemData)
    if not itemData then return end
    local tr = {}
 
    -- tr1
    tr[1] = html.create("tr")
        :tag("th")
            :attr("rowspan", 2)
            :addClass("b")
            :wikitext(nameEntry(itemData.name, itemData.icon))
            :done()
        :tag("td")
            :wikitext(itemData.category_name or "&mdash;")
            :done()
        :tag("td")
            :wikitext(itemData.level_item or "&mdash;")
            :done()
    local descr = ""
    for j, w in ipairs(constants.baseStats) do
        local v = itemData.attributes_base[w[1]]
        local vhq = itemData.attributes_base[w[1] .. "_hq"]
        if (v and v > 0) or (vhq and vhq > 0) then
            if descr ~= "" then descr = descr .. "<br/>" end
            descr = descr .. "'''" .. w[2] .. "''': " .. (v or "0")
            if vhq and (not v or vhq > v) then
                descr = descr .. " ([[File:FFXIV HQ Icon.png]] " .. vhq .. ")"
            end
        end
    end
    for j, v in ipairs(itemData.attributes_params) do 
        if v.name ~= "" then
            if descr ~= "" then descr = descr .. "<br/>" end
            descr = descr .. "'''" .. v.name .. "''': " .. (v.value or "0")
            if v.value_hq then descr = descr .. " ([[File:FFXIV HQ Icon.png]] " .. v.value_hq .. ")" end
        end
end
    if descr ~= "" then descr = "<p style=\"column-count:2\">" .. descr .. "</p>" end
    tr[1]:tag("td")
        :attr("rowspan", 2)
        :wikitext(itemData.help_en .. descr)
        :allDone()
 
    --tr2
    tr[2] = html.create("tr")
        :tag("td")
            :wikitext(((itemData.classjob_category and (itemData.classjob_category .. " ")) or "") .. (itemData.level_equip or "&mdash;"))
            :done()
        :tag("td")
            :wikitext((itemData.patch and itemData.patch.number) or "&mdash;")
            :allDone()
 
    --gathering and crafting trs
    local tableIndex = 3
 
    --crafting tr
    if itemData.craftable then
        for _____, c in ipairs(itemData.craftable) do
            conds = {}
            local ind = 1
 
            local possibleConds = mw.loadData("Module:FFXIV Data/Parameters").craftingConditions
            for k, v in pairs(possibleConds) do
                if c[k] and not c[k] == 0 then
                    conds[ind] = v
                    ind = ind + 1
                end
            end
 
            if c.craft_quantity and c.craft_quantity > 1 then
                conds[ind] = "Crafting quantity: " .. tostring(c.craft_quantity)
                ind = ind + 1
            end
 
            if c.element_name and not c.element_name == "Aspect: None" then
                conds[ind] = c.element_name
                ind = ind + 1
            end
 
            if c.masterbook and c.masterbook.name then
                conds[ind] = "Requires " .. itemLink(c.masterbook.name)
                ind = ind + 1
            end
 
            mats = {}
            ind = 1
            if c.tree then
                for _, v in ipairs(c.tree) do
                    if v.name then
                        local mat = itemLink(v.name)
                        if v.quantity and v.quantity > 1 then
                            mat = mat .. " x" .. tostring(v.quantity)
                        end
                        mats[ind] = mat
                        ind = ind + 1
                    end
                end
            end
 
            cstats = '<p style="column-count:2">'
 
            cstats = cstats .. "'''Crafter''': " .. c.classjob.abbr .. " " .. c.level_view
            if c.stars_html then cstats = cstats .. c.stars_html end
            cstats = cstats .. '<br/>'
 
            cstats = cstats .. "'''Durability''': " .. c.durability .. "<br/>"
            cstats = cstats .. "'''Craftsmanship''': " .. c.required_craftsmanship .. "<br/>"
            cstats = cstats .. "'''Control''': " .. c.required_control .. "<br/>"
            cstats = cstats .. "'''Difficulty''': " .. c.difficulty .. "<br/>"
            cstats = cstats .. "'''Quality''': " .. c.quality .. "<br/>"
 
            cstats = cstats .. '</p>'
 
            tr[tableIndex] = html.create("tr")
                :tag("td")
                    :attr("colspan","3")
                    :cssText("vertical-align:top")
                    :node(listToList(mats))
                    :done()
                :tag("td")
                    :cssText("vertical-align:top")
                    :wikitext(cstats)
                    :node(listToList(conds))
                    :allDone()
            tableIndex = tableIndex + 1
        end
    end
 
    return tr
end
 
local function lookupItemData(item)
    if tonumber(item) then return lookupById("item", item)
    else return lookup("item", item) end
end
 
local function lookupItem(item)
    return parseItemData(lookupItemData(item))
end
 
local function itemLink(item)
    local i = lookupItemData(item)
    if not i or not i.category_name then return item end
    return "[[Final Fantasy XIV items/" .. i.category_name .. "#" .. item .. "|" .. item .. "]]"
end
 
function p.LootTable(frame)
    local args = getArgs(frame)
    local tbl = makeItemHeader()
    for j, item in ipairs(args) do
        local tr = lookupItem(item)
        if tr then for j, v in ipairs(tr) do tbl:node(v) end end
    end
    return tbl
end
 
function p.AllLootTable(frame)
    local args = getArgs(frame)
    local category_name = args[1]
    local header = "The following is a list of items classified as '''" .. category_name .. "''' from ''[[Final Fantasy XIV]]''."
    local div = html.create("div")
        :wikitext(header)
        :done()
    if args[2] then header = header .. "\n\n" .. args[2] end
    local tbl = makeItemHeader()
    for i=1,28000 do --This will need to be updated in 5.x!
        local itemData = lookupById("item", i)
        if itemData and itemData.category_name == category_name then
            local tr = parseItemData(itemData)
            if tr then for j, v in ipairs(tr) do tbl:node(v) end end
        end
    end
    div:node(tbl)
    return div
end
 
 
 
 
--Quests
local function lookupQuestData(quest)
    local q
    if tonumber(quest) then q = lookupById("quest", tonumber(quest))
    else q = lookup("quest", quest) end
    return q
end
 
local function questLink(quest)
    local q = lookupQuestData(quest)
    if not q or not q.genre_name then return quest end
    return "[[Final Fantasy XIV quests/" .. q.genre_name .. "#" .. quest .. "|" .. quest .. "]]"
end
 
local function questTable(quest)
    local tbl = html.create("table"):addClass("FFXIV article-table"):cssText("float:right;width:370px"):allDone()
    if quest.icon then
        tbl:tag("tr")
            :tag("td")
                :attr("colspan", 2)
                :wikitext(iconById(quest.icon))
    end
    if quest.class_level_1 then
        tbl:tag("tr")
            :tag("th")
                :addClass("b")
                :wikitext("Level")
                :done()
            :tag("td")
                :wikitext(quest.class_level_1)
    end
    if quest.category_name then
        tbl:tag("tr")
            :tag("th")
                :addClass("b")
                :wikitext("Type")
                :done()
            :tag("td")
                :wikitext(quest.category_name)
    end
    if quest.pre_quests and quest.pre_quests ~= {} then
        local prereqs = ""
        for j, v in ipairs(quest.pre_quests) do
            if prereqs ~= "" then prereqs = prereqs .. "<br/>" end
            prereqs = prereqs .. questLink(v.name)
        end
        tbl:tag("tr")
            :tag("th")
                :addClass("b")
                :wikitext("Requires")
                :done()
            :tag("td")
                :wikitext(prereqs)
    end
    if quest.post_quests and quest.post_quests ~= {} then
        local postreqs = ""
        for j, v in ipairs(quest.post_quests) do
            if postreqs ~= "" then postreqs = postreqs .. "<br/>" end
            postreqs = postreqs .. questLink(v.name)
        end
        tbl:tag("tr")
            :tag("th")
                :addClass("b")
                :wikitext("Unlocks")
                :done()
            :tag("td")
                :wikitext(postreqs)
    end
    if quest.gil_reward or quest.exp_reward then
        local rewards = ""
        if quest.exp_reward then
            rewards = "[[File:FFXIV EXP Icon.png]] " .. quest.exp_reward .. "<br/>"
        end
        if quest.gil_reward then
            rewards = rewards .. "[[File:FFXIV Gil Icon.png]] " .. quest.gil_reward
        end
        tbl:tag("tr")
            :tag("th")
                :addClass("b")
                :wikitext("Rewards")
                :done()
            :tag("td")
                :wikitext(rewards)
    end
    if quest.npc_start then
        tbl:tag("tr")
            :tag("th")
                :addClass("b")
                :wikitext("Start NPC")
                :done()
            :tag("td")
                :wikitext(quest.npc_start.name)
    end
    if quest.npc_end then
        tbl:tag("tr")
            :tag("th")
                :addClass("b")
                :wikitext("End NPC")
                :done()
            :tag("td")
                :wikitext(quest.npc_end.name)
    end
    if quest.patch then
        tbl:tag("tr")
            :tag("th")
                :addClass("b")
                :wikitext("Patch")
                :done()
            :tag("td")
                :wikitext(quest.patch.number)
    end
    return tbl
end
 
local function questBullets(list)
    local ul = html.create("ul")
    for j, v in ipairs(list) do
        ul:tag("li"):wikitext(v.text)
    end
    return ul
end
 
local function questEntry(q)
    if q then return html.create("div"):addClass("quest"):cssText("clear:right;")
        :tag("h3")
            :wikitext(q.name)
            :done()
        :node(questTable(q))
            :done()
        :tag("h4")
            :wikitext("Journal")
            :done()
        :node(questBullets(q.text.journal))
            :allDone()
        :tag("h4")
            :wikitext("Objectives")
            :done()
        :node(questBullets(q.text.todo))
            :done() end
end
 
local function lookupQuest(quest)
    return questEntry(lookupQuestData(quest))
end
 
function p.QuestLink(frame)
    local quest = getArgs(frame)[1]
    return questLink(quest)
end
 
function p.QuestList(frame)
    local args = getArgs(frame)
    local div = html.create("div"):addClass("quests")
    for j, quest in ipairs(args) do
        q = lookupQuest(quest)
        if q then div:node(q) end
    end
    return div
end
 
function p.AllQuestsList(frame)
    local args = getArgs(frame)
    local genre_name = args[1]
    local header = "The following is a list of quests classified as '''" .. genre_name .. "''' from ''[[Final Fantasy XIV]]''."
    if args[2] then header = header .. "\n\n" .. args[2] end
    local div = html.create("div")
        :addClass("quests")
        :wikitext(header)
        :tag("h2")
            :wikitext("Quests")
            :done()
    local j = 1
    for i=65537,70000 do --This will need to be updated in 5.x!
        q = lookupById("quest", i)
        if q and q.genre_name == genre_name then div:node(questEntry(q)) end
    end
    return div
end
 
 
-----------Do not edit below this line!
return p
 
--[[Category:Final Fantasy XIV Database]]
Community content is available under CC-BY-SA unless otherwise noted.