模块

装备:修订间差异

来自卡厄思梦境WIKI

律Rhyme留言 | 贡献
无编辑摘要
律Rhyme留言 | 贡献
无编辑摘要
第1行: 第1行:
local p = {}
local p = {}
local equipmentData = mw.loadData('模块:装备/data')


-- 辅助函数:解析文本模板
local data = mw.loadData('模块:装备/data')
local function parseText(text)
 
     if not text then return "" end
local function getArgs(frame)
    -- 将{{文本|橙|内容}}转换为HTML
     local args = frame.args or {}
     text = text:gsub("{{文本|橙|([^}]+)}}", '<span style="color:#FF9900">%1</span>')
     local parent = frame:getParent()
     return text
    if parent then
        setmetatable(args, { __index = parent.args })
    end
     return args
end
end


-- 获取装备稀有度对应的背景图片
local function sanitizeId(s)
local function getRarityBg(rarity)
     s = tostring(s or '')
     local rarityMap = {
    s = mw.ustring.gsub(s, "%s+", "_")
        ["蓝"] = "bg_equipment_rarity_蓝.png",
    s = mw.ustring.gsub(s, "[%[%]{}()%c%p]", "_")
        [""] = "bg_equipment_rarity_紫.png",
     return s
        [""] = "bg_equipment_rarity_金.png"
    }
     return rarityMap[rarity] or "bg_equipment_rarity_蓝.png"
end
end


-- 获取装备类型对应的图标
local function clampLevel(level)
local function getTypeIcon(equipType, rarity)
     level = tonumber(level) or 1
     local typeMap = {
    if level < 1 then level = 1 end
        ["武器"] = "武器",
     if level > 5 then level = 5 end
        ["刀"] = "武器",
     return level
        ["装甲"] = "装甲",
        ["戒指"] = "戒指"
     }
    local mappedType = typeMap[equipType] or "武器"
     return string.format("icon_equip_%s_%s.png", mappedType, rarity)
end
end


-- 生成装备卡片
local function starIcon(level)
function p.card(frame)
     level = clampLevel(level)
     -- 修正参数获取逻辑
     return string.format("icon_star_rating_%d.png", level)
    local args = frame.args  -- 直接调用时使用frame.args
    if not args[1] and frame:getParent() then
        args = frame:getParent().args  -- 通过模板调用时使用parent.args
    end
   
    local name = args[1] or args.name
    local level = args[2] or args.level or "1"
   
    -- 调试信息
    if not name then
        local debugInfo = "参数调试信息:\n"
        debugInfo = debugInfo .. "frame.args[1]: " .. tostring(frame.args[1]) .. "\n"
        if frame:getParent() then
            debugInfo = debugInfo .. "parent.args[1]: " .. tostring(frame:getParent().args[1]) .. "\n"
        end
        return "装备不存在: 未指定装备名称\n" .. debugInfo
    end
   
     if not equipmentData[name] then
        return "装备不存在: " .. name .. " (请检查装备名称是否正确)"
    end
   
    local equip = equipmentData[name]
    local base = equip.base
    local levelData = equip[level] or equip["1"]
   
    local rarityBg = getRarityBg(base.rarity)
   
    -- 生成唯一ID用于弹窗
    local uniqueId = "equip_" .. mw.hash.hashValue('md5', name .. tostring(os.time()) .. tostring(math.random()))
   
    -- 使用单引号包裹HTML字符串,避免双引号冲突
    local html = string.format([=[
<div class="equipment-card" data-equipment="%s" data-level="%s" data-name="%s" style="position: relative; display: inline-block; width:150px; height: 230px; cursor: pointer;">
<div style="position: absolute; top: 0px; left: 0px;">[[File:%s|150px|link=]]</div>
<div style="position: absolute; top: 43px; left: 13px;">[[File:%s|124px|link=]]</div>
<div style="position: absolute; bottom: 5px; left: 5px; width: 140px; height: 35px; background-color: rgba(0,0,0,0.5); border-radius: 0px 0px 8px 8px"></div>
<div style="position: absolute; bottom: 10px; left: 20px;">[[File:icon_star_rating_%s.png|link=]]</div>
<div style="position: absolute; top: 0px; left: 0px;">[[File:equipment_顶层蒙版.png|150px|link=]]</div>
</div>]=],
        uniqueId,
        level,
        name,  -- 添加装备名称到data属性
        rarityBg,
        base.art,
        level
    )
   
    return frame:preprocess(html)
end
end


-- 生成装备弹窗内容
function p.render(frame)
function p.popup(frame)
     local args = getArgs(frame)
     -- 修正参数获取逻辑
     local name = args.name or args[1]
     local args = frame.args
    local level = clampLevel(args.level or args.lv or args[2] or 1)
     if not args[1] and frame:getParent() then
 
         args = frame:getParent().args
     if not name or not data[name] then
         return string.format("<span style='color:red'>[装备] 数据未找到:%s</span>", tostring(name or "未指定"))
     end
     end
   
    local name = args[1] or args.name
    local level = args[2] or args.level or "1"
   
    if not name or not equipmentData[name] then
        return '<div style="color: red;">装备数据不存在</div>'
    end
   
    local equip = equipmentData[name]
    local base = equip.base
    local levelData = equip[level] or equip["1"]
   
    local collectionBg = "bg_collection_rarity_" .. base.rarity .. ".png"
    local typeIcon = getTypeIcon(base.type, base.rarity)
    local valueTypeText = base.value_type == "atk" and "攻击力" or "防御力"
    local desc = parseText(levelData.desc_global)
   
    local html = string.format([=[
<div style="position: relative; display: inline-block; width:368px; height: 335px; background-color: #343434; border-radius: 9px">
<div style="position: absolute; top: 0px; left: 0px;">[[File:%s|link=]]</div>
<div style="position: absolute; top: 40px; left: 128px;">[[File:%s|124px|link=]]</div>
<div style="position: absolute; top: 167px; left: 0px; width: 368px; height: 35px; background-color: rgba(0,0,0,0.5); border-radius: 0px 0px 8px 8px"></div>
<div style="position: absolute; top: 173px; left: 128px;">[[File:icon_star_rating_%s.png|link=]]</div>
<div style="position: absolute; top: 205px; left: 5px; color: white">[[File:%s|25px|link=]]</div>
<div style="position: absolute; top: 209px; left: 33px; color: white">%s</div>
<div style="position: absolute; top: 235px; left: 9px; width: 350px; height: 35px; background-color: rgba(255,255,255,0.3); border-radius: 2px"></div>
<div style="position: absolute; top: 242px; left: 14px; color: white">%s</div>
<div style="position: absolute; top: 242px; right: 14px; color: white">%s</div>
<div style="position: absolute; top: 277px; left: 10px; right: 10px; color: white">%s</div>
</div>]=],
        collectionBg,
        base.art,
        level,
        typeIcon,
        name,
        valueTypeText,
        levelData.value,
        desc
    )
   
    return frame:preprocess(html)
end


-- 测试函数,用于检查数据是否正确加载
    local eq = data[name]
function p.test(frame)
    local base = eq.base or {}
     local result = "装备数据列表:\n"
    local rarity = base.rarity or "蓝"
     for name, _ in pairs(equipmentData) do
    local art = base.art or ""
         result = result .. "- " .. name .. "\n"
    local typ = base.type or "武器"
     end
    local valueType = base.value_type or ""
     return result
    local lvlKey = tostring(level)
end
    local lvl = eq[lvlKey] or {}
    local value = lvl.value or ""
    local desc = lvl.desc_global or ""
 
    local modalId = "equip_modal_" .. sanitizeId(name) .. "_" .. tostring(level)
 
    local root = mw.html.create('div')
 
    -- 小卡片
    local card = root:tag('div')
        :addClass('equip-card')
        :attr('data-equip-id', modalId)
        :attr('style', 'position: relative; display: inline-block; width:150px; height: 230px; cursor: pointer;')
 
    card:tag('div')
        :attr('style', 'position: absolute; top: 0px; left: 0px;')
        :wikitext(string.format('[[File:bg_equipment_rarity_%s.png|150px|link=]]', rarity))
 
    card:tag('div')
        :attr('style', 'position: absolute; top: 43px; left: 13px;')
        :wikitext(string.format('[[File:%s|124px|link=]]', art))
 
    card:tag('div')
        :attr('style', 'position: absolute; bottom: 5px; left: 5px; width: 140px; height: 35px; background-color: rgba(0,0,0,0.5); border-radius: 0px 0px 8px 8px')
 
    card:tag('div')
        :attr('style', 'position: absolute; bottom: 10px; left: 20px; ')
        :wikitext(string.format('[[File:%s|link=]]', starIcon(level)))
 
    card:tag('div')
        :attr('style', 'position: absolute; top: 0px; left: 0px;')
        :wikitext('[[File:equipment_顶层蒙版.png|150px|link=]]')
 
    -- 弹窗容器(遮罩)
     local modalContainer = root:tag('div')
        :addClass('equip-modal-container')
        :attr('id', modalId)
        :attr('style', 'display: none;')
 
    -- 点击遮罩关闭提示
    -- 弹窗内容(按给定布局)
     local modal = modalContainer:tag('div')
        :addClass('equip-modal')
        :attr('style', 'position: relative; display: inline-block; width:368px; height: 335px; background-color: #343434; border-radius: 9px')
 
    modal:tag('div')
         :attr('style', 'position: absolute; top: 0px; left: 0px;')
        :wikitext(string.format('[[File:bg_collection_rarity_%s.png|link=]]', rarity))
 
    modal:tag('div')
        :attr('style', 'position: absolute; top: 40px; left: 128px;')
        :wikitext(string.format('[[File:%s|124px|link=]]', art))
 
    modal:tag('div')
        :attr('style', 'position: absolute; top: 167px; left: 0px; width: 368px; height: 35px; background-color: rgba(0,0,0,0.5); border-radius: 0px 0px 8px 8px')
 
    modal:tag('div')
        :attr('style', 'position: absolute; top: 173px; left: 128px; ')
        :wikitext(string.format('[[File:%s|link=]]', starIcon(level)))
 
    modal:tag('div')
        :attr('style', 'position: absolute; top: 205px; left: 5px; color: white')
        :wikitext(string.format('[[File:icon_equip_%s_%s.png|25px|link=]]', typ, rarity))
 
    modal:tag('div')
        :attr('style', 'position: absolute; top: 209px; left: 33px; color: white')
        :wikitext(name)
 
    modal:tag('div')
        :attr('style', 'position: absolute; top: 235px; left: 9px; width: 350px; height: 35px; background-color: rgba(255,255,255,0.3); border-radius: 2px')
 
    modal:tag('div')
        :attr('style', 'position: absolute; top: 242px; left: 14px; color: white')
        :wikitext(valueType)
 
    modal:tag('div')
        :attr('style', 'position: absolute; top: 242px; right: 14px; color: white')
        :wikitext(tostring(value))
 
     modal:tag('div')
        :attr('style', 'position: absolute; top: 277px; left: 10px; color: white')
        :wikitext(desc)
 
     -- 关闭按钮
    modal:tag('div')
        :addClass('equip-modal-close')
        :attr('title', '关闭')
        :attr('style', 'position: absolute; top: 6px; right: 10px; color: white; font-size: 20px; line-height: 20px; cursor: pointer;')
        :wikitext('×')


-- 获取装备数据的JSON格式(供JS使用)
     return tostring(root)
function p.getDataJson(frame)
    local args = frame.args
    if not args[1] and frame:getParent() then
        args = frame:getParent().args
    end
   
    local name = args[1] or args.name
   
     if not name or not equipmentData[name] then
        return "{}"
    end
   
    local equip = equipmentData[name]
    local data = {
        name = name,
        base = equip.base,
        levels = {}
    }
   
    for i = 1, 5 do
        if equip[tostring(i)] then
            data.levels[i] = equip[tostring(i)]
        end
    end
   
    return mw.text.jsonEncode(data)
end
end


return p
return p

2025年10月17日 (五) 15:36的版本

此模块的文档可以在模块:装备/doc创建

local p = {}

local data = mw.loadData('模块:装备/data')

local function getArgs(frame)
    local args = frame.args or {}
    local parent = frame:getParent()
    if parent then
        setmetatable(args, { __index = parent.args })
    end
    return args
end

local function sanitizeId(s)
    s = tostring(s or '')
    s = mw.ustring.gsub(s, "%s+", "_")
    s = mw.ustring.gsub(s, "[%[%]{}()%c%p]", "_")
    return s
end

local function clampLevel(level)
    level = tonumber(level) or 1
    if level < 1 then level = 1 end
    if level > 5 then level = 5 end
    return level
end

local function starIcon(level)
    level = clampLevel(level)
    return string.format("icon_star_rating_%d.png", level)
end

function p.render(frame)
    local args = getArgs(frame)
    local name = args.name or args[1]
    local level = clampLevel(args.level or args.lv or args[2] or 1)

    if not name or not data[name] then
        return string.format("<span style='color:red'>[装备] 数据未找到:%s</span>", tostring(name or "未指定"))
    end

    local eq = data[name]
    local base = eq.base or {}
    local rarity = base.rarity or "蓝"
    local art = base.art or ""
    local typ = base.type or "武器"
    local valueType = base.value_type or ""
    local lvlKey = tostring(level)
    local lvl = eq[lvlKey] or {}
    local value = lvl.value or ""
    local desc = lvl.desc_global or ""

    local modalId = "equip_modal_" .. sanitizeId(name) .. "_" .. tostring(level)

    local root = mw.html.create('div')

    -- 小卡片
    local card = root:tag('div')
        :addClass('equip-card')
        :attr('data-equip-id', modalId)
        :attr('style', 'position: relative; display: inline-block; width:150px; height: 230px; cursor: pointer;')

    card:tag('div')
        :attr('style', 'position: absolute; top: 0px; left: 0px;')
        :wikitext(string.format('[[File:bg_equipment_rarity_%s.png|150px|link=]]', rarity))

    card:tag('div')
        :attr('style', 'position: absolute; top: 43px; left: 13px;')
        :wikitext(string.format('[[File:%s|124px|link=]]', art))

    card:tag('div')
        :attr('style', 'position: absolute; bottom: 5px; left: 5px; width: 140px; height: 35px; background-color: rgba(0,0,0,0.5); border-radius: 0px 0px 8px 8px')

    card:tag('div')
        :attr('style', 'position: absolute; bottom: 10px; left: 20px; ')
        :wikitext(string.format('[[File:%s|link=]]', starIcon(level)))

    card:tag('div')
        :attr('style', 'position: absolute; top: 0px; left: 0px;')
        :wikitext('[[File:equipment_顶层蒙版.png|150px|link=]]')

    -- 弹窗容器(遮罩)
    local modalContainer = root:tag('div')
        :addClass('equip-modal-container')
        :attr('id', modalId)
        :attr('style', 'display: none;')

    -- 点击遮罩关闭提示
    -- 弹窗内容(按给定布局)
    local modal = modalContainer:tag('div')
        :addClass('equip-modal')
        :attr('style', 'position: relative; display: inline-block; width:368px; height: 335px; background-color: #343434; border-radius: 9px')

    modal:tag('div')
        :attr('style', 'position: absolute; top: 0px; left: 0px;')
        :wikitext(string.format('[[File:bg_collection_rarity_%s.png|link=]]', rarity))

    modal:tag('div')
        :attr('style', 'position: absolute; top: 40px; left: 128px;')
        :wikitext(string.format('[[File:%s|124px|link=]]', art))

    modal:tag('div')
        :attr('style', 'position: absolute; top: 167px; left: 0px; width: 368px; height: 35px; background-color: rgba(0,0,0,0.5); border-radius: 0px 0px 8px 8px')

    modal:tag('div')
        :attr('style', 'position: absolute; top: 173px; left: 128px; ')
        :wikitext(string.format('[[File:%s|link=]]', starIcon(level)))

    modal:tag('div')
        :attr('style', 'position: absolute; top: 205px; left: 5px; color: white')
        :wikitext(string.format('[[File:icon_equip_%s_%s.png|25px|link=]]', typ, rarity))

    modal:tag('div')
        :attr('style', 'position: absolute; top: 209px; left: 33px; color: white')
        :wikitext(name)

    modal:tag('div')
        :attr('style', 'position: absolute; top: 235px; left: 9px; width: 350px; height: 35px; background-color: rgba(255,255,255,0.3); border-radius: 2px')

    modal:tag('div')
        :attr('style', 'position: absolute; top: 242px; left: 14px; color: white')
        :wikitext(valueType)

    modal:tag('div')
        :attr('style', 'position: absolute; top: 242px; right: 14px; color: white')
        :wikitext(tostring(value))

    modal:tag('div')
        :attr('style', 'position: absolute; top: 277px; left: 10px; color: white')
        :wikitext(desc)

    -- 关闭按钮
    modal:tag('div')
        :addClass('equip-modal-close')
        :attr('title', '关闭')
        :attr('style', 'position: absolute; top: 6px; right: 10px; color: white; font-size: 20px; line-height: 20px; cursor: pointer;')
        :wikitext('×')

    return tostring(root)
end

return p