Mudanças entre as edições de "Módulo:Info"

De Wiki Gla
Ir para navegação Ir para pesquisar
m (Adicionado suporte aos parâmetros |noback= e |back= para controlar comportamento de transformações)
m (teste de weapon1)
Linha 398: Linha 398:
         end
         end
     end
     end
    return mw.text.jsonEncode(obj)
end
-- Weapon (com WM, sem subskills)
function p.weapon(frame)
    local a = safeArgs(frame)
    local lang = trim((a.lang or (frame:getParent() and frame:getParent().args.lang) or "pt"):lower())
    local char = trim(a.char or (frame:getParent() and frame:getParent().args.nome) or "")
    if char == "" then
        char = resolveCharFromFrames(frame, a)
    end
    local data = requireCharacterModule(char) or {}
    local name, desc_i18n = nil, {}
    -- Se vier WM, busca no módulo (data.weapon.order[WM] -> data.weapon.skills[key])
    if a.WM and trim(a.WM) ~= "" then
        local wm = tonumber(a.WM) or 0
        local weaponData = data.weapon or {}
        local order = weaponData.order or {}
        local key = order[wm] or ""
        local wk = (weaponData.skills or {})[key] or {}
        name = trim(wk.name or key or "")
        if type(wk.desc) == "table" then
            local langs = { "pt", "en", "es", "pl" }
            for _, code in ipairs(langs) do
                local d = wk.desc[code]
                if d and trim(d) ~= "" then
                    desc_i18n[code] = colorize(d)
                end
            end
        elseif wk.desc and trim(wk.desc) ~= "" then
            desc_i18n["pt"] = colorize(wk.desc)
        end
    else
        -- Sem WM: permite setar name e desc pelos args
        name = trim(a.name or "")
        if trim(a.desc_pt or "") ~= "" then desc_i18n["pt"] = colorize(a.desc_pt) end
        if trim(a.desc_en or "") ~= "" then desc_i18n["en"] = colorize(a.desc_en) end
        if trim(a.desc_es or "") ~= "" then desc_i18n["es"] = colorize(a.desc_es) end
        if trim(a.desc_pl or "") ~= "" then desc_i18n["pl"] = colorize(a.desc_pl) end
    end
    local function nz(v)
        v = v or ""
        return (trim(v) ~= "" and v or nil)
    end
    local chosen = desc_i18n[lang] or desc_i18n["pt"] or ""
    local obj = {
        icon = (trim(a.icon or "") ~= "" and a.icon or "Nada.png"),
        level = (trim(a.level or "") ~= "" and a.level or "NIVEL"),
        energy = nz(a.energy),
        powerpve = nz(a.powerpve),
        powerpvp = nz(a.powerpvp),
        cooldown = nz(a.cooldown),
        video = a.video or "",
        name = name
    }
    if chosen ~= "" then
        obj.desc = chosen
    end
    if next(desc_i18n) ~= nil then
        obj.desc_i18n = desc_i18n
        obj.descPt = desc_i18n.pt
        obj.descEn = desc_i18n.en
        obj.descEs = desc_i18n.es
        obj.descPl = desc_i18n.pl
    end
    -- Armas NÃO têm subskills: não empacotar subs/suborder


     return mw.text.jsonEncode(obj)
     return mw.text.jsonEncode(obj)

Edição das 20h47min de 12 de outubro de 2025

A documentação para este módulo pode ser criada em Módulo:Info/doc

-- Módulo:Info — resolve metadados e skills (com Subskill e cores inline)
local p = {}

-- ===== util =====
local function trim(s)
    return (tostring(s or ""):gsub("^%s+", ""):gsub("%s+$", ""))
end
local function safeArgs(node)
    return (node and node.args) or {}
end

local function requireCharacterModule(charName)
    charName = trim(charName)
    if charName == "" then
        return nil
    end
    local ok, data = pcall(function()
        return require("Módulo:" .. charName)
    end)
    if ok and type(data) == "table" then
        return data
    end
    charName = charName:gsub(" ", "_")
    ok, data = pcall(function()
        return require("Módulo:" .. charName)
    end)
    if ok and type(data) == "table" then
        return data
    end
    return nil
end

-- Separa uma sequência de {} (JSONs colados) em uma tabela de chunks
local function collectJsonObjects(s)
    s = tostring(s or "")
    local out = {}
    for chunk in s:gmatch("%b{}") do
        table.insert(out, chunk)
    end
    return out
end

--------------------------------------------------------------------------------
-- I18N: rótulos de atributos + "Nível"
--------------------------------------------------------------------------------
local I18N = {
    pt = {
        level = "Nível",
        power = "Poder",
        power_pvp = "Poder PvP",
        energy = "Energia",
        energy_cost = "Energia",
        energy_gain = "Energia",
        cooldown = "Recarga"
    },
    en = {
        level = "Level",
        power = "Power",
        power_pvp = "Power PvP",
        energy = "Energy",
        energy_cost = "Energy",
        energy_gain = "Energy",
        cooldown = "Cooldown"
    },
    es = {
        level = "Nivel",
        power = "Poder",
        power_pvp = "Poder PvP",
        energy = "Energía",
        energy_cost = "Energía",
        energy_gain = "Energía",
        cooldown = "Enfriamiento"
    },
    pl = {
        level = "Poziom",
        power = "Moc",
        power_pvp = "Moc PvP",
        energy = "Energia",
        energy_cost = "Energia",
        energy_gain = "Energia",
        cooldown = "Odnawianie"
    }
}

local function resolveCharFromFrames(frame, a)
    a = a or {}
    if frame and frame.getParent then
        local parent = frame:getParent()
        if parent and parent.args then
            if parent.args.nome and trim(parent.args.nome) ~= "" then
                return trim(parent.args.nome)
            end
            for k, v in pairs(parent.args) do
                if type(k) == "string" and k:match("^class") and trim(v) ~= "" then
                    return trim(v)
                end
            end
        end
    end
    if a.nome and trim(a.nome) ~= "" then
        return trim(a.nome)
    end
    if a.char and trim(a.char) ~= "" then
        return trim(a.char)
    end
    local title = mw.title.getCurrentTitle()
    return title and trim(title.text) or ""
end

-- mapa de cores (inline!)
local COLOR = {
    debuff = "#ff5252",
    ms = "#5bc0de",
    hp = "#70d86b",
    atk = "#ffd166",
    def = "#c0a9ff",
    sec = "#ffcc00"
}

-- substitui {{atk:}}, {{def:}}, {{ms:}}, {{hp:}}, {{sec:}}, {{debuff:}} por <span style="color:#hex">…</span>
local function colorize(txt)
    if not txt or txt == "" then
        return ""
    end
    return (tostring(txt):gsub("{{%s*(%a+)%s*:%s*([^}]+)%s*}}", function(tag, inner)
        tag = tag:lower()
        local hex = COLOR[tag]
        if not hex then
            return "{{" .. tag .. ":" .. inner .. "}}"
        end
        return string.format('<span style="color:%s;">%s</span>', hex, trim(inner))
    end))
end

-- ===== API =====

-- Tier textual (i18n)
function p.getTier(frame)
    local a = safeArgs(frame)
    local char = trim(frame.args[1] or a.nome)
    if char == "" then
        char = resolveCharFromFrames(frame, a)
    end
    local data = requireCharacterModule(char) or {}
    local lang = trim((a.lang or (frame:getParent() and frame:getParent().args.lang) or "pt"):lower())
    if data.tier_i18n and data.tier_i18n[lang] then
        return data.tier_i18n[lang]
    end
    return trim(data.tier or "")
end

-- Tags textuais (i18n)
function p.getTags(frame)
    local a = safeArgs(frame)
    local char = trim(frame.args[1] or a.nome)
    if char == "" then
        char = resolveCharFromFrames(frame, a)
    end
    local data = requireCharacterModule(char) or {}
    local lang = trim((a.lang or (frame:getParent() and frame:getParent().args.lang) or "pt"):lower())
    local tags = (data.tags_i18n and data.tags_i18n[lang]) or data.tags or {}
    if type(tags) ~= "table" then
        return trim(tags or "")
    end
    return trim(table.concat(tags, " / "))
end

-- Skill (com M)
function p.skill(frame)
    local a = safeArgs(frame)
    local lang = trim((a.lang or (frame:getParent() and frame:getParent().args.lang) or "pt"):lower())
    local char = trim(a.char or (frame:getParent() and frame:getParent().args.nome) or "")
    if char == "" then
        char = resolveCharFromFrames(frame, a)
    end
    local data = requireCharacterModule(char) or {}

    local name, desc_i18n = nil, {}
    if a.M and trim(a.M) ~= "" then
        local m = tonumber(a.M) or 0
        local order = data.order or {}
        local key = order[m] or ""
        local sk = (data.skills or {})[key] or {}
        name = trim(sk.name or key or "")
        if type(sk.desc) == "table" then
            local langs = { "pt", "en", "es", "pl" }
            for _, code in ipairs(langs) do
                local d = sk.desc[code]
                if d and trim(d) ~= "" then
                    desc_i18n[code] = colorize(d)
                end
            end
        elseif sk.desc and trim(sk.desc) ~= "" then
            desc_i18n["pt"] = colorize(sk.desc)
        end
    end

    local function nz(v)
        v = v or ""
        return (trim(v) ~= "" and v or nil)
    end

    local chosen = desc_i18n[lang] or desc_i18n["pt"] or ""

    local obj = {
        icon = (trim(a.icon or "") ~= "" and a.icon or "Nada.png"),
        level = (trim(a.level or "") ~= "" and a.level or "NIVEL"),
        energy = nz(a.energy),
        powerpve = nz(a.powerpve),
        powerpvp = nz(a.powerpvp),
        cooldown = nz(a.cooldown),
        video = a.video or "",
        name = name,
        noback = (trim(a.noback or "") == "yes" or trim(a.noback or "") == "true") and true or nil
    }

    if chosen ~= "" then
        obj.desc = chosen
    end
    if next(desc_i18n) ~= nil then
        obj.desc_i18n = desc_i18n
        obj.descPt = desc_i18n.pt
        obj.descEn = desc_i18n.en
        obj.descEs = desc_i18n.es
        obj.descPl = desc_i18n.pl
    end

    -- empacota subskills vindas via |subs= (cada {{Subskill}} vira um objeto JSON)
    do
        local subsPacked = a.subs or ""
        local subsArr = {}
        for _, chunk in ipairs(collectJsonObjects(subsPacked)) do
            local ok, sk = pcall(mw.text.jsonDecode, chunk)
            if ok and type(sk) == "table" then
                table.insert(subsArr, sk)
            end
        end
        -- se não vier via |subs=, tenta obter do módulo (suborder/subskills)
        if #subsArr == 0 and a.M and tonumber(a.M) then
            local m = tonumber(a.M)
            local order = (data and data.order) or {}
            local key = order[m] or ""
            local sk = (data and data.skills and data.skills[key]) or {}
            local suborder = type(sk) == "table" and sk.suborder or nil
            local subskills = type(sk) == "table" and sk.subskills or nil
            if type(suborder) == "table" and type(subskills) == "table" then
                for _, n in ipairs(suborder) do
                    local sub = subskills[n]
                    if type(sub) == "table" then
                        local subObj = {
                            n = n,
                            name = n,
                            icon = sub.icon or "",
                            level = sub.level or "",
                            video = sub.video or "",
                            energy = sub.energy,
                            powerpve = sub.powerpve,
                            powerpvp = sub.powerpvp,
                            cooldown = sub.cooldown,
                            desc_i18n = sub.desc,
                            descPt = sub.desc and sub.desc.pt or nil,
                            descEn = sub.desc and sub.desc.en or nil,
                            descEs = sub.desc and sub.desc.es or nil,
                            descPl = sub.desc and sub.desc.pl or nil
                        }
                        -- nested subs do módulo (sub.suborder/sub.subskills)
                        if type(sub.suborder) == "table" and type(sub.subskills) == "table" then
                            local nested = {}
                            for _, nn in ipairs(sub.suborder) do
                                local s2 = sub.subskills[nn]
                                if type(s2) == "table" then
                                    table.insert(nested, {
                                        n = nn,
                                        name = nn,
                                        icon = s2.icon or "",
                                        level = s2.level or "",
                                        video = s2.video or "",
                                        energy = s2.energy,
                                        powerpve = s2.powerpve,
                                        powerpvp = s2.powerpvp,
                                        cooldown = s2.cooldown,
                                        desc_i18n = s2.desc,
                                        descPt = s2.desc and s2.desc.pt or nil,
                                        descEn = s2.desc and s2.desc.en or nil,
                                        descEs = s2.desc and s2.desc.es or nil,
                                        descPl = s2.desc and s2.desc.pl or nil
                                    })
                                end
                            end
                            if #nested > 0 then subObj.subs = nested end
                        end
                        table.insert(subsArr, subObj)
                    end
                end
            end
        end
        if #subsArr > 0 then
            obj.subs = subsArr
        end

        -- suborder do módulo (se existir pra esta skill M)
        if a.M and tonumber(a.M) then
            local m = tonumber(a.M)
            local order = (data and data.order) or {}
            local key = order[m] or ""
            local sk = (data and data.skills and data.skills[key]) or {}
            if type(sk) == "table" and type(sk.suborder) == "table" then
                obj.suborder = sk.suborder
            end
        end
    end

    return mw.text.jsonEncode(obj)
end

-- Emote (sem M)
function p.emote(frame)
    local a = safeArgs(frame)
    local obj = {
        name = "Emote",
        desc = "",
        icon = (trim(a.icon or "") ~= "" and a.icon or "Nada.png"),
        level = (trim(a.level or "") ~= "" and a.level or "NIVEL"),
        video = a.video or ""
    }
    return mw.text.jsonEncode(obj)
end

-- Subskill (nome n EXATO do suborder; agrega desc_i18n do módulo + atributos locais)
function p.subskill(frame)
    local a = safeArgs(frame)
    local lang = trim((a.lang or (frame:getParent() and frame:getParent().args.lang) or "pt"):lower())
    local n = trim(a.n or "")
    if n == "" then
        return mw.text.jsonEncode({})
    end

    local char = trim(a.char or (frame:getParent() and frame:getParent().args.nome) or "")
    if char == "" then
        char = resolveCharFromFrames(frame, a)
    end
    local data = requireCharacterModule(char) or {}

    local desc_i18n = {}
    for _, key in ipairs(data.order or {}) do
        local sk = (data.skills or {})[key]
        if type(sk) == "table" and type(sk.subskills) == "table" then
            local sub = sk.subskills[n]
            if sub then
                local langs = { "pt", "en", "es", "pl" }
                for _, code in ipairs(langs) do
                    local d = sub.desc and sub.desc[code]
                    if d and trim(d) ~= "" then
                        desc_i18n[code] = colorize(d)
                    end
                end
                break
            end
        end
    end

    local function nz(v)
        v = v or "";
        return (trim(v) ~= "" and v or nil)
    end
    local obj = {
        name = n,
        icon = (trim(a.icon or "") ~= "" and a.icon or "Nada.png"),
        level = (trim(a.level or "") ~= "" and a.level or "NIVEL"),
        video = a.video or "",
        energy = nz(a.energy),
        powerpve = nz(a.powerpve),
        powerpvp = nz(a.powerpvp),
        cooldown = nz(a.cooldown),
        back = (trim(a.back or "") == "yes" or trim(a.back or "") == "true") and true or nil
    }

    if next(desc_i18n) ~= nil then
        obj.desc_i18n = desc_i18n
        obj.descPt = desc_i18n.pt
        obj.descEn = desc_i18n.en
        obj.descEs = desc_i18n.es
        obj.descPl = desc_i18n.pl
    end

    -- Nested subs support: allow |subs= inside a subskill
    do
        local subsPacked = a.subs or ""
        local subsArr = {}
        for _, chunk in ipairs(collectJsonObjects(subsPacked)) do
            local ok, sub = pcall(mw.text.jsonDecode, chunk)
            if ok and type(sub) == "table" then
                table.insert(subsArr, sub)
            end
        end
        if #subsArr > 0 then
            obj.subs = subsArr
        end
    end

    return mw.text.jsonEncode(obj)
end

-- Weapon (com WM, sem subskills)
function p.weapon(frame)
    local a = safeArgs(frame)
    local lang = trim((a.lang or (frame:getParent() and frame:getParent().args.lang) or "pt"):lower())
    local char = trim(a.char or (frame:getParent() and frame:getParent().args.nome) or "")
    if char == "" then
        char = resolveCharFromFrames(frame, a)
    end
    local data = requireCharacterModule(char) or {}

    local name, desc_i18n = nil, {}

    -- Se vier WM, busca no módulo (data.weapon.order[WM] -> data.weapon.skills[key])
    if a.WM and trim(a.WM) ~= "" then
        local wm = tonumber(a.WM) or 0
        local weaponData = data.weapon or {}
        local order = weaponData.order or {}
        local key = order[wm] or ""
        local wk = (weaponData.skills or {})[key] or {}
        name = trim(wk.name or key or "")
        if type(wk.desc) == "table" then
            local langs = { "pt", "en", "es", "pl" }
            for _, code in ipairs(langs) do
                local d = wk.desc[code]
                if d and trim(d) ~= "" then
                    desc_i18n[code] = colorize(d)
                end
            end
        elseif wk.desc and trim(wk.desc) ~= "" then
            desc_i18n["pt"] = colorize(wk.desc)
        end
    else
        -- Sem WM: permite setar name e desc pelos args
        name = trim(a.name or "")
        if trim(a.desc_pt or "") ~= "" then desc_i18n["pt"] = colorize(a.desc_pt) end
        if trim(a.desc_en or "") ~= "" then desc_i18n["en"] = colorize(a.desc_en) end
        if trim(a.desc_es or "") ~= "" then desc_i18n["es"] = colorize(a.desc_es) end
        if trim(a.desc_pl or "") ~= "" then desc_i18n["pl"] = colorize(a.desc_pl) end
    end

    local function nz(v)
        v = v or ""
        return (trim(v) ~= "" and v or nil)
    end

    local chosen = desc_i18n[lang] or desc_i18n["pt"] or ""

    local obj = {
        icon = (trim(a.icon or "") ~= "" and a.icon or "Nada.png"),
        level = (trim(a.level or "") ~= "" and a.level or "NIVEL"),
        energy = nz(a.energy),
        powerpve = nz(a.powerpve),
        powerpvp = nz(a.powerpvp),
        cooldown = nz(a.cooldown),
        video = a.video or "",
        name = name
    }

    if chosen ~= "" then
        obj.desc = chosen
    end
    if next(desc_i18n) ~= nil then
        obj.desc_i18n = desc_i18n
        obj.descPt = desc_i18n.pt
        obj.descEn = desc_i18n.en
        obj.descEs = desc_i18n.es
        obj.descPl = desc_i18n.pl
    end

    -- Armas NÃO têm subskills: não empacotar subs/suborder

    return mw.text.jsonEncode(obj)
end

-- Gambis: expandir tier/tags via token "tierNome", "tagsNome"
function p.expandTier(frame)
    local token = trim(frame.args[1] or "")
    local nome = trim(frame.args[2] or (frame:getParent() and frame:getParent().args.nome) or "")
    if token == "" then
        return ""
    end
    if token:lower():sub(1, 4) ~= "tier" then
        return token
    end
    local char = nome ~= "" and nome or token:match("^tier(.+)$") or ""
    if char == "" then
        local title = mw.title.getCurrentTitle()
        char = title and trim(title.text) or ""
    end
    local data = requireCharacterModule(char) or {}
    local lang = trim((frame.args.lang or "pt"):lower())
    if data.tier_i18n and data.tier_i18n[lang] then
        return data.tier_i18n[lang]
    end
    return trim(data.tier or "")
end

function p.expandTags(frame)
    local token = trim(frame.args[1] or "")
    local nome = trim(frame.args[2] or (frame:getParent() and frame:getParent().args.nome) or "")
    if token == "" then
        return ""
    end
    if token:lower():sub(1, 4) ~= "tags" then
        return token
    end
    local char = nome ~= "" and nome or token:match("^tags(.+)$") or ""
    if char == "" then
        local title = mw.title.getCurrentTitle()
        char = title and trim(title.text) or ""
    end
    local data = requireCharacterModule(char) or {}
    local arr = (data.tags_i18n and data.tags_i18n.pt) or data.tags
    if type(arr) == "table" then
        return table.concat(arr, " / ")
    end
    return trim(arr or "")
end

return p