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

De Wiki Gla
Ir para navegação Ir para pesquisar
m
Etiqueta: Reversão manual
m
 
(5 revisões intermediárias pelo mesmo usuário não estão sendo mostradas)
Linha 10: Linha 10:
     general_item    = { en = "General Item", pt = "Item geral" },
     general_item    = { en = "General Item", pt = "Item geral" },
     special_item    = { en = "Special Item", pt = "Item especial" },
     special_item    = { en = "Special Item", pt = "Item especial" },
    mission_item    = { en = "Mission Item", pt = "Item de Missão" },
     currency        = { en = "Currency", pt = "Moeda" },
     currency        = { en = "Currency", pt = "Moeda" },
     cosmetic        = { en = "Cosmetic", pt = "Cosmético" },
     cosmetic        = { en = "Cosmetic", pt = "Cosmético" },
Linha 146: Linha 147:


--[[
--[[
   Passivas no tooltip: definidas aqui (Módulo:Item), não no Widget:Item.
   Tooltip codificada (data-tip). Widget:Item decodifica no hover.
  Widget:Item só carrega CSS/JS do hover. Atualizar a lógica = editar ESTE módulo na wiki.
 
  ItemDB precisa de passive1 (e opcionalmente passive2) com pt/en.
  equipment_special = true é o fluxo oficial do editor; se a flag faltar mas houver
  texto em passive1/2, ainda exibimos (ItemDB antigo / cópia incompleta).
]]
]]
local function shouldShowPassiveBlock(item, passive1, passive2)
local function shouldShowPassiveBlock(item, passive1, passive2)
Linha 172: Linha 168:
     -- flag ausente (nil): ainda há texto de passiva → mostrar
     -- flag ausente (nil): ainda há texto de passiva → mostrar
     return f == nil
     return f == nil
end
--[[
  Tooltip codificada: corpo vazio no HTML + data-tip (base64 UTF-8).
  Widget:Item decodifica no hover e limpa no mouseout.
]]
local function base64_encode(data)
    local b = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
    return ((data:gsub(".", function(x)
        local r, byte = "", x:byte()
        for i = 8, 1, -1 do
            r = r .. (byte % 2 ^ i - byte % 2 ^ (i - 1) > 0 and "1" or "0")
        end
        return r
    end) .. "0000"):gsub("%d%d%d?%d?%d?%d?", function(x)
        if #x < 6 then return "" end
        local c = 0
        for i = 1, 6 do
            c = c + (x:sub(i, i) == "1" and 2 ^ (6 - i) or 0)
        end
        return b:sub(c + 1, c + 1)
    end) .. ({ "", "==", "=" })[#data % 3 + 1])
end
local function encodePayload(obj)
    local json = mw.text.jsonEncode(obj)
    return "b64:" .. base64_encode(json)
end
local function encodeIconPayload(image, w, h)
    return encodePayload({
        i = image,
        w = w,
        h = h,
    })
end
local function buildTooltipPayload(item, lang)
    lang = normalizeLang(lang)
    local nome = Item.getName(item, lang)
    local desc = Item.getDesc(item, lang)
    local catLabel = Item.getCategoryLabel(item, lang)
    local value = Item.getValue(item)
    local level = Item.getLevel(item)
    local passive1 = getPassiveLine(item, "passive1", lang)
    local passive2 = getPassiveLine(item, "passive2", lang)
    local showPassives = shouldShowPassiveBlock(item, passive1, passive2)
    local payload = {
        n = nome or "",
        c = catLabel or "",
        sp = showPassives and 1 or 0,
    }
    if level then
        payload.lv = (lang == "pt") and ("Nível: " .. tostring(level))
            or ("Level: " .. tostring(level))
    end
    if showPassives then
        if passive1 then payload.p1 = passive1 end
        if passive2 then payload.p2 = passive2 end
    elseif desc then
        payload.d = desc
    end
    if value then
        payload.v = "$" .. formatDots(value)
    end
    return payload
end
function Item.renderTooltip(item, lang)
    if not item then return "" end
    local encoded = encodePayload(buildTooltipPayload(item, lang))
    local tip = mw.html.create("div")
        :addClass("item-tooltip")
        :addClass("item-tooltip-enc")
        :attr("data-tip", encoded)
    tip:tag("div"):addClass("item-tooltip-body")
    tip:tag("div"):addClass("item-tooltip-arrow")
    return tostring(tip)
end
function Item.tooltip(frame)
    -- Via API parse (#invoke direto): parâmetros em frame.args
    -- Via predefinição pai: parâmetros em getParent().args
    local direct = frame.args or {}
    local parent = frame:getParent().args or {}
    local key = mw.text.trim(direct.key or direct[1] or parent.key or parent[1] or "")
    local lang = direct.lang or parent.lang or DEFAULT_LANG
    if key == "" then return "" end
    local item = Item.resolve(key)
    if not item then return "" end
    return Item.renderTooltip(item, lang)
end
end


Linha 179: Linha 271:
     if not item then return "" end
     if not item then return "" end


    local nome    = Item.getName(item, lang)
     local image   = Item.getImage(item)
    local desc    = Item.getDesc(item, lang)
     local w, h   = Item.getSpriteSize(item)
     local image   = Item.getImage(item)
     local catLabel = Item.getCategoryLabel(item, lang)
    local value    = Item.getValue(item)
    local level   = Item.getLevel(item)


    local w, h    = Item.getSpriteSize(item)
     local wrapper = mw.html.create("div")
 
     local wrapper = mw.html.create("div")
         :addClass("item-wrapper")
         :addClass("item-wrapper")
         :css("width", w .. "px")
         :css("width", w .. "px")
Linha 195: Linha 281:
     if image and mw.text.trim(image) ~= "" then
     if image and mw.text.trim(image) ~= "" then
         wrapper:tag("span")
         wrapper:tag("span")
             :wikitext(string.format("[[Arquivo:%s|%dx%dpx|link=]]", image, w, h))
             :addClass("item-icon")
            :attr("data-i", encodeIconPayload(image, w, h))
            :css("width", w .. "px")
            :css("height", h .. "px")
     else
     else
         wrapper:tag("span")
         wrapper:tag("span")
             :addClass("item-icon-placeholder")
             :addClass("item-icon-placeholder")
            :attr("title", nome)
             :wikitext("")
             :wikitext("")
     end
     end
Linha 213: Linha 301:


     if options.showTooltip ~= false then
     if options.showTooltip ~= false then
         -- div (não span): descrições em wikitext podem virar <p>/blocos; span+bloco
         wrapper:wikitext(Item.renderTooltip(item, lang))
        -- quebra o DOM e os próximos .item-wrapper acabam dentro do tooltip.
        local tip  = wrapper:tag("div"):addClass("item-tooltip")
        local body = tip:tag("div"):addClass("item-tooltip-body")
 
        body:tag("div"):addClass("item-tooltip-name"):wikitext(nome)
 
        if catLabel then
            body:tag("div"):addClass("item-tooltip-cat"):wikitext(catLabel)
        end
 
        local passive1 = getPassiveLine(item, "passive1", lang)
        local passive2 = getPassiveLine(item, "passive2", lang)
        local showPassives = shouldShowPassiveBlock(item, passive1, passive2)
        local hasDetails = level or showPassives or (desc and not showPassives) or value
        if hasDetails then
            body:tag("div"):addClass("item-tooltip-sep")
        end
 
        if level then
            local lvlFull = (lang == "pt") and ("Nível: " .. tostring(level))
                or ("Level: " .. tostring(level))
            body:tag("div"):addClass("item-tooltip-level"):wikitext(lvlFull)
        end
 
        if showPassives then
            local passWrap = body:tag("div"):addClass("item-tooltip-passives")
            if passive1 then
                local row = passWrap:tag("div"):addClass("item-tooltip-passive-row")
                row:tag("span"):addClass("item-tooltip-passive-badge"):wikitext("2")
                row:tag("span"):addClass("item-tooltip-passive-text"):wikitext(passive1)
            end
            if passive2 then
                local row = passWrap:tag("div"):addClass("item-tooltip-passive-row")
                row:tag("span"):addClass("item-tooltip-passive-badge"):wikitext("5")
                row:tag("span"):addClass("item-tooltip-passive-text"):wikitext(passive2)
            end
        elseif desc then
            body:tag("div"):addClass("item-tooltip-desc"):wikitext(desc)
        end
 
        if value then
            local footer = body:tag("div"):addClass("item-tooltip-footer")
            footer:tag("span"):addClass("item-tooltip-val")
                :wikitext("$" .. formatDots(value))
        end
 
        tip:tag("div"):addClass("item-tooltip-arrow")
     end
     end



Edição atual tal como às 22h12min de 28 de maio de 2026

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

local Item = {}
local ItemDB = require("Módulo:ItemDB")

local DEFAULT_LANG = "pt-br"
local FALLBACK_LANG = "en"
local DEFAULT_FRAME_SIZE = 32

-- Categorias alinhadas ao jogo (ItemDB / editor). Sem duplicata coin/currency nem gem_currency.
local CATEGORY_LABELS = {
    general_item    = { en = "General Item", pt = "Item geral" },
    special_item    = { en = "Special Item", pt = "Item especial" },
    mission_item    = { en = "Mission Item", pt = "Item de Missão" },
    currency        = { en = "Currency", pt = "Moeda" },
    cosmetic        = { en = "Cosmetic", pt = "Cosmético" },
    weapon          = { en = "Weapon", pt = "Arma" },
    head            = { en = "Head", pt = "Cabeça" },
    body            = { en = "Body", pt = "Corpo" },
    legs            = { en = "Legs", pt = "Perna" },
    accessory       = { en = "Accessory", pt = "Acessório" },
    emblem          = { en = "Emblem", pt = "Emblema" },
    ship_style      = { en = "Ship Style", pt = "Estilo de navio" },
    costume         = { en = "Costume", pt = "Traje" },
    navigation      = { en = "Navigation", pt = "Navegação" },
    consumable      = { en = "Consumable", pt = "Consumível" },
    gem             = { en = "Gem", pt = "Gema" },
    crystal         = { en = "Crystal", pt = "Cristal" },
    awakening_stone = { en = "Awakening Stone", pt = "Pedra do Despertar" },
    headstone       = { en = "Headstone", pt = "Lápide" },
    den_den_mushi   = { en = "Den Den Mushi", pt = "Den Den Mushi" },
}

local function normalizeLang(lang)
    local lg = mw.ustring.lower(mw.text.trim(tostring(lang or DEFAULT_LANG)))
    lg = lg:gsub("_", "-")
    if lg == "" then return "pt" end
    if lg == "pt" or lg == "pt-br" then return "pt" end
    if lg == "en" or lg == "en-us" or lg == "en-gb" then return "en" end
    return lg
end

local function formatDots(n)
    local s = tostring(n)
    local pos = #s % 3
    if pos == 0 then pos = 3 end
    local parts = { s:sub(1, pos) }
    for i = pos + 1, #s, 3 do
        parts[#parts + 1] = s:sub(i, i + 2)
    end
    return table.concat(parts, ".")
end

local function normalizeForMatch(s)
    if not s then return "" end
    return mw.ustring.lower(mw.text.trim(tostring(s)))
end

local function isBerriesItem(item)
    if not item then return false end

    local image = normalizeForMatch(item.image)
    if image ~= "" and image:find("berr", 1, true) then
        return true
    end

    local namePt = item.names and normalizeForMatch(item.names.pt) or ""
    local nameEn = item.names and normalizeForMatch(item.names.en) or ""
    if namePt:find("berr", 1, true) or nameEn:find("berr", 1, true) then
        return true
    end

    if item.aliases and type(item.aliases) == "table" then
        for _, alias in ipairs(item.aliases) do
            local norm = normalizeForMatch(alias)
            if norm:find("berr", 1, true) then
                return true
            end
        end
    end

    return item.category == "currency"
end

function Item.resolve(query)
    if not query or query == "" then return nil end
    return ItemDB.get(query)
end

function Item.getName(item, lang)
    if not item or not item.names then return "" end
    lang = normalizeLang(lang)
    return item.names[lang]
        or item.names[FALLBACK_LANG]
        or item.names.pt
        or item.image or ""
end

function Item.getDesc(item, lang)
    if not item or not item.desc then return nil end
    lang = normalizeLang(lang)
    return item.desc[lang]
        or item.desc[FALLBACK_LANG]
        or item.desc.pt
end

function Item.getValue(item)
    if not item then return nil end
    return item.value
end

function Item.getLevel(item)
    if not item then return nil end
    return item.level
end

function Item.getImage(item)
    if not item then return nil end
    return item.image
end

function Item.getSpriteSize(item)
    if item and item.sprite then
        return item.sprite.frameWidth or DEFAULT_FRAME_SIZE,
            item.sprite.frameHeight or DEFAULT_FRAME_SIZE
    end
    return DEFAULT_FRAME_SIZE, DEFAULT_FRAME_SIZE
end

function Item.getCategoryLabel(item, lang)
    if not item or not item.category then return nil end
    local entry = CATEGORY_LABELS[item.category]
    if not entry then return nil end
    lang = normalizeLang(lang)
    return entry[lang] or entry[FALLBACK_LANG] or entry.pt or nil
end

local function getPassiveLine(item, key, lang)
    if not item or not item[key] or type(item[key]) ~= "table" then return nil end
    local p = item[key]
    lang = normalizeLang(lang)
    local function pick(lg)
        local t = p[lg]
        if t and mw.text.trim(tostring(t)) ~= "" then return mw.text.trim(tostring(t)) end
        return nil
    end
    return pick(lang) or pick(DEFAULT_LANG) or pick(FALLBACK_LANG)
end

--[[
  Tooltip codificada (data-tip). Widget:Item decodifica no hover.
]]
local function shouldShowPassiveBlock(item, passive1, passive2)
    if not (passive1 or passive2) then
        return false
    end
    local f = item and item.equipment_special
    if f == false then
        return false
    end
    if f == true or f == 1 then
        return true
    end
    if type(f) == "string" then
        local s = mw.ustring.lower(mw.text.trim(f))
        if s == "true" or s == "1" then
            return true
        end
    end
    -- flag ausente (nil): ainda há texto de passiva → mostrar
    return f == nil
end

--[[
  Tooltip codificada: corpo vazio no HTML + data-tip (base64 UTF-8).
  Widget:Item decodifica no hover e limpa no mouseout.
]]
local function base64_encode(data)
    local b = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
    return ((data:gsub(".", function(x)
        local r, byte = "", x:byte()
        for i = 8, 1, -1 do
            r = r .. (byte % 2 ^ i - byte % 2 ^ (i - 1) > 0 and "1" or "0")
        end
        return r
    end) .. "0000"):gsub("%d%d%d?%d?%d?%d?", function(x)
        if #x < 6 then return "" end
        local c = 0
        for i = 1, 6 do
            c = c + (x:sub(i, i) == "1" and 2 ^ (6 - i) or 0)
        end
        return b:sub(c + 1, c + 1)
    end) .. ({ "", "==", "=" })[#data % 3 + 1])
end

local function encodePayload(obj)
    local json = mw.text.jsonEncode(obj)
    return "b64:" .. base64_encode(json)
end

local function encodeIconPayload(image, w, h)
    return encodePayload({
        i = image,
        w = w,
        h = h,
    })
end

local function buildTooltipPayload(item, lang)
    lang = normalizeLang(lang)
    local nome = Item.getName(item, lang)
    local desc = Item.getDesc(item, lang)
    local catLabel = Item.getCategoryLabel(item, lang)
    local value = Item.getValue(item)
    local level = Item.getLevel(item)
    local passive1 = getPassiveLine(item, "passive1", lang)
    local passive2 = getPassiveLine(item, "passive2", lang)
    local showPassives = shouldShowPassiveBlock(item, passive1, passive2)

    local payload = {
        n = nome or "",
        c = catLabel or "",
        sp = showPassives and 1 or 0,
    }

    if level then
        payload.lv = (lang == "pt") and ("Nível: " .. tostring(level))
            or ("Level: " .. tostring(level))
    end
    if showPassives then
        if passive1 then payload.p1 = passive1 end
        if passive2 then payload.p2 = passive2 end
    elseif desc then
        payload.d = desc
    end
    if value then
        payload.v = "$" .. formatDots(value)
    end

    return payload
end

function Item.renderTooltip(item, lang)
    if not item then return "" end

    local encoded = encodePayload(buildTooltipPayload(item, lang))
    local tip = mw.html.create("div")
        :addClass("item-tooltip")
        :addClass("item-tooltip-enc")
        :attr("data-tip", encoded)

    tip:tag("div"):addClass("item-tooltip-body")
    tip:tag("div"):addClass("item-tooltip-arrow")
    return tostring(tip)
end

function Item.tooltip(frame)
    -- Via API parse (#invoke direto): parâmetros em frame.args
    -- Via predefinição pai: parâmetros em getParent().args
    local direct = frame.args or {}
    local parent = frame:getParent().args or {}
    local key = mw.text.trim(direct.key or direct[1] or parent.key or parent[1] or "")
    local lang = direct.lang or parent.lang or DEFAULT_LANG
    if key == "" then return "" end
    local item = Item.resolve(key)
    if not item then return "" end
    return Item.renderTooltip(item, lang)
end

function Item.renderOne(item, qty, lang, options)
    options = options or {}
    lang = normalizeLang(lang)
    if not item then return "" end

    local image   = Item.getImage(item)
    local w, h    = Item.getSpriteSize(item)

    local wrapper = mw.html.create("div")
        :addClass("item-wrapper")
        :css("width", w .. "px")
        :css("height", h .. "px")

    if image and mw.text.trim(image) ~= "" then
        wrapper:tag("span")
            :addClass("item-icon")
            :attr("data-i", encodeIconPayload(image, w, h))
            :css("width", w .. "px")
            :css("height", h .. "px")
    else
        wrapper:tag("span")
            :addClass("item-icon-placeholder")
            :wikitext("")
    end

    if qty and options.showCount ~= false then
        local countSpan = wrapper:tag("span"):addClass("item-count")
        local isBerries = isBerriesItem(item)
        if not isBerries then
            countSpan:tag("span"):addClass("item-count-x"):wikitext("x")
        end
        countSpan:wikitext(tostring(qty))
    end

    if options.showTooltip ~= false then
        wrapper:wikitext(Item.renderTooltip(item, lang))
    end

    return tostring(wrapper)
end

function Item.renderLine(itemList, lang, options)
    options = options or {}
    lang = normalizeLang(lang)
    if not itemList or #itemList == 0 then return "" end

    local container = mw.html.create("div")
        :addClass("reward-items")

    for _, entry in ipairs(itemList) do
        container:wikitext(Item.renderOne(entry.item, entry.qty, lang, options))
    end

    return tostring(container)
end

return Item