卡厄思
梦
境
菜单
首页
回到首页
WIKI工具
全站样式
全站JS
修改导航栏
测试
沙盒
可视化管理器
战斗员管理器
卡牌管理器
伙伴管理器
装备管理器
词典管理器
图鉴
战斗员
伙伴
装备
怪物卡牌
中立卡牌
词典
小工具
配队模拟器
节奏榜生成器
搜索
链入页面
相关更改
特殊页面
页面信息
最近更改
登录
模块
查看“︁卡牌”︁的源代码
←
模块:卡牌
因为以下原因,您没有权限编辑该页面:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
local p = {} -- 使用官方参数解析器,自动合并父/子 frame 参数、去空白与空值 local getArgs = require('Module:Arguments').getArgs -- 渲染模块 local displayModule = require('Module:卡牌/display') -- 安全的错误输出 local function err(msg) return '<span style="color: red;">' .. mw.text.encode(msg) .. '</span>' end -- 标题截断:超过 maxLen 个字符用 ... 截断(按 Unicode 计数,兼容中英文) local function ellipsisTitle(s, maxLen) s = tostring(s or '') local ulen = mw.ustring.len(s) if ulen > (maxLen or 5) then return mw.ustring.sub(s, 1, maxLen or 5) .. '...' end return s end -- 解析 dict 字段(简化版:只支持顿号分隔的纯文本或{{词典|名称}}) local function parseDictTokens(dictStr) local s = tostring(dictStr or '') if s == '' then return {}, false end local tokens = {} local hasTemplate = false -- 标记是否包含词典模板 -- 1. 先提取所有 {{词典|机制}} 形式 for token in s:gmatch('{{%s*词典%s*|%s*([^}|]+)%s*}}') do token = mw.text.trim(token or '') if token ~= '' then table.insert(tokens, {text = token, isTemplate = true}) hasTemplate = true end end -- 2. 移除所有词典模板,得到剩余纯文本 local plainText = s:gsub('{{%s*词典%s*|%s*[^}]*}}', '') -- 3. 解析纯文本(只支持中文顿号、分隔) for token in plainText:gmatch('([^、]+)') do token = mw.text.trim(token or '') if token ~= '' then table.insert(tokens, {text = token, isTemplate = false}) end end -- 去重,保持顺序 local seen, out = {}, {} for _, t in ipairs(tokens) do if not seen[t.text] then seen[t.text] = true table.insert(out, t) end end return out, hasTemplate end -- 加载 模块:词典/data local dictData = nil do local ok, dictModule = pcall(mw.loadData, 'Module:词典/data') if ok and type(dictModule) == 'table' then if type(dictModule.dictionary) == 'table' then dictData = dictModule.dictionary else dictData = dictModule end end end -- 根据 tokens 生成词典条目数组(只查询标记为模板的) local function buildDictEntries(tokens) if not tokens or #tokens == 0 then return nil end local entries = {} for _, token in ipairs(tokens) do -- 只为带模板的token查询词典数据 if token.isTemplate then local desc = nil local d = dictData and dictData[token.text] if type(d) == 'table' then if d[1] and type(d[1]) == 'table' then desc = d[1]["描述"] or d[1].desc elseif type(d["描述"]) == 'string' then desc = d["描述"] elseif type(d.desc) == 'string' then desc = d.desc end end table.insert(entries, { key = token.text, desc = desc }) end end return #entries > 0 and entries or nil end -- 合并 base 数据与变体数据 local function mergeCardData(baseData, variantData, opts) if not baseData then return nil end local merged = {} -- 浅拷贝 base for k, v in pairs(baseData) do merged[k] = v end -- 清空衍生卡牌信息 if opts and opts.clearSubUnlessSpecified then merged.sub = nil end -- 覆盖变体数据 if variantData then for k, v in pairs(variantData) do merged[k] = v end end return merged end -- 根据 base AP 与目标 AP 文本计算发光样式 -- 返回: 'blue' | 'red' | 'green' | 'gray' local function calcApStyle(apText, baseApText, isVariant) local text = apText ~= nil and tostring(apText) or '' if not isVariant then return 'blue' end if text == 'X' then return 'blue' end local n = tonumber(text) local baseN = baseApText ~= nil and tonumber(baseApText) or nil if n and baseN then if n > baseN then return 'red' elseif n < baseN then return 'green' else return 'blue' end end -- 其他内容(非数值且非X)不发光 return 'gray' end -- 将单张卡牌的数据转换为 cardInfo 结构(在此完成词典解析) -- opts: -- isVariant: boolean -- baseApText: string|number -- baseDictStr: string function p.parseCardData(cardData, moduleName, cardName, moduleInfo, opts) if not cardData then return nil end local ego = "" if moduleInfo and moduleInfo.ego then ego = moduleInfo.ego elseif cardData.ego then ego = cardData.ego end -- 展示名称:优先 displayname,否则使用卡牌名 local displayTitle = (cardData.displayname and mw.text.trim(tostring(cardData.displayname)) ~= '' and cardData.displayname) or cardName or '' -- 截断后的展示名称(仅用于卡牌图片上的可视显示,不影响其他逻辑/搜索) local displayTitleShort = ellipsisTitle((displayTitle ~= '' and displayTitle) or cardName, 5) -- AP 文本与样式 local apText = cardData.ap ~= nil and tostring(cardData.ap) or '' local isVariant = opts and opts.isVariant or false local baseApText = opts and opts.baseApText or nil local apStyle = calcApStyle(apText, baseApText, isVariant) -- 词典解析 local rawDictStr = cardData.dict or "" local dictStr = mw.text.trim(rawDictStr) local dictTokens local dictEntries local dictColor = "default" local hasTemplate = false if isVariant then local baseDictStr = opts and opts.baseDictStr or "" baseDictStr = mw.text.trim(baseDictStr) if dictStr == "空" then dictTokens = {} dictEntries = nil hasTemplate = false elseif dictStr ~= "" and dictStr ~= baseDictStr then dictTokens, hasTemplate = parseDictTokens(dictStr) dictEntries = buildDictEntries(dictTokens) dictColor = "green" else dictTokens, hasTemplate = parseDictTokens(dictStr) dictEntries = buildDictEntries(dictTokens) dictColor = "default" end else end local cardInfo = { moduleName = moduleName or "", cardName = cardName or "", displayTitle = displayTitle or "", displayTitleShort = displayTitleShort or "", art = cardData.art or "", ego = ego or "", rarity = cardData.rarity or "", apText = apText, apStyle = apStyle, cardType = cardData.type or "", desc = cardData.desc_global or "", dict = dictStr, dictTokens = dictTokens, dictEntries = dictEntries, dictColor = dictColor, hasTemplate = hasTemplate, group = cardData.group or "", tag = cardData.tag or "", hasInspiration = false, inspirationVariants = {}, hasGodInspiration = false, godInspirationGroups = nil, godInspirationGroupOrder = nil } return cardInfo end -- 解析衍生卡牌列表(支持递归) function p.parseSubCardData(subCardNames, dataModule, moduleInfo) if not subCardNames or not dataModule then return nil end local subCards = {} for subName in string.gmatch(subCardNames, '([^,]+)') do subName = mw.text.trim(subName) if subName ~= "" then local subCardData = dataModule[subName] if subCardData and subCardData.base then local parsedCard = p.parseCardData(subCardData.base, "", subName, moduleInfo, { isVariant = false }) if parsedCard then if subCardData.base.sub then parsedCard.subCards = p.parseSubCardData(subCardData.base.sub, dataModule, moduleInfo) end table.insert(subCards, parsedCard) end end end end if #subCards == 0 then return nil end return subCards end -- 收集全部灵光一闪变体 local function collectInspirationVariants(baseData, cardDataWrapper, moduleName, cardName, moduleInfo, dataModule) local variants = {} if not cardDataWrapper.var or not cardDataWrapper.var.inspiration then return variants end for i, inspData in ipairs(cardDataWrapper.var.inspiration) do local mergedData = mergeCardData(baseData, inspData, { clearSubUnlessSpecified = true }) if mergedData then local variantInfo = p.parseCardData(mergedData, moduleName, cardName, moduleInfo, { isVariant = true, baseApText = baseData.ap, baseDictStr = baseData.dict or "" }) if variantInfo then if mergedData.sub then variantInfo.subCards = p.parseSubCardData(mergedData.sub, dataModule, moduleInfo) end table.insert(variants, variantInfo) end end end return variants end -- 收集全部神光一闪变体 local function collectGodInspirationVariants(baseData, cardDataWrapper, moduleName, cardName, moduleInfo, dataModule) local godGroups = {} local groupOrder = {} if not cardDataWrapper.var or not cardDataWrapper.var.god_inspiration then return godGroups, groupOrder end local fixedOrder = { "circen", "diallos", "nihilum", "secred", "vitor" } for _, groupName in ipairs(fixedOrder) do local groupList = cardDataWrapper.var.god_inspiration[groupName] if type(groupList) == "table" and #groupList > 0 then local list = {} for _, godVar in ipairs(groupList) do local mergedData = mergeCardData(baseData, godVar, { clearSubUnlessSpecified = true }) if mergedData then local variantInfo = p.parseCardData(mergedData, moduleName, cardName, moduleInfo, { isVariant = true, baseApText = baseData.ap, baseDictStr = baseData.dict or "" }) if variantInfo then if mergedData.sub then variantInfo.subCards = p.parseSubCardData(mergedData.sub, dataModule, moduleInfo) end table.insert(list, variantInfo) end end end if #list > 0 then godGroups[groupName] = list table.insert(groupOrder, groupName) end end end return godGroups, groupOrder end -- 主入口 function p.main(frame) local args = getArgs(frame, { removeBlank = true }) local moduleName = args[1] local cardName = args[2] local variantType = args[3] local variantParam = args[4] local variantIndex = args[5] if not moduleName or moduleName == "" then return err("错误: 未指定模块名") end if not cardName or cardName == "" then return err("错误: 未指定卡牌名") end local success, dataModule = pcall(require, 'Module:卡牌/' .. moduleName) if not success or not dataModule then return err('错误: 找不到模块 "Module:卡牌/' .. moduleName .. '"') end local moduleInfo = dataModule.info or {} local cardDataWrapper = dataModule[cardName] if not cardDataWrapper then return err('错误: 在模块 "' .. moduleName .. '" 中找不到卡牌 "' .. cardName .. '"') end local baseData = cardDataWrapper.base if not baseData then return err('错误: 卡牌 "' .. cardName .. '" 没有 base 数据') end local finalCardData = baseData local isVariantFlag = false if variantType then variantType = mw.text.trim(variantType) if variantType == "灵光一闪" then if not cardDataWrapper.var or not cardDataWrapper.var.inspiration then return err('错误: 卡牌 "' .. cardName .. '" 没有灵光一闪变体') end local inspIndex = tonumber(variantParam) if not inspIndex or inspIndex < 1 or inspIndex > #cardDataWrapper.var.inspiration then return err('错误: 灵光一闪变体索引 "' .. tostring(variantParam) .. '" 无效') end finalCardData = mergeCardData(baseData, cardDataWrapper.var.inspiration[inspIndex], { clearSubUnlessSpecified = true }) isVariantFlag = true elseif variantType == "神光一闪" then if not cardDataWrapper.var or not cardDataWrapper.var.god_inspiration then return err('错误: 卡牌 "' .. cardName .. '" 没有神光一闪变体') end local characterName = variantParam if not characterName or characterName == "" then return err("错误: 未指定战斗员") end local godInspData = cardDataWrapper.var.god_inspiration[characterName] if not godInspData then return err('错误: 找不到战斗员 "' .. characterName .. '" 的神光一闪') end local godIndex = tonumber(variantIndex) if not godIndex or godIndex < 1 or godIndex > #godInspData then return err('错误: 神光一闪变体索引 "' .. tostring(variantIndex) .. '" 无效') end finalCardData = mergeCardData(baseData, godInspData[godIndex], { clearSubUnlessSpecified = true }) isVariantFlag = true else return err('错误: 未知变体类型 "' .. variantType .. '"') end end if not finalCardData then return err("错误: 最终卡牌数据为空") end local cardInfo = p.parseCardData(finalCardData, moduleName, cardName, moduleInfo, { isVariant = isVariantFlag, baseApText = baseData and baseData.ap or nil, baseDictStr = baseData and baseData.dict or "" }) if not cardInfo then return err("错误: 解析卡牌数据失败") end -- 灵光一闪按钮集合 if not variantType and cardDataWrapper.var and cardDataWrapper.var.inspiration and (baseData.isinspiration == 1) then cardInfo.hasInspiration = true cardInfo.inspirationVariants = collectInspirationVariants(baseData, cardDataWrapper, moduleName, cardName, moduleInfo, dataModule) end -- 神光一闪按钮集合 local godFlag = (baseData.isgod_god_inspiration == 1) or (baseData.isgod_inspiration == 1) if not variantType and godFlag and cardDataWrapper.var and cardDataWrapper.var.god_inspiration then local godGroups, order = collectGodInspirationVariants(baseData, cardDataWrapper, moduleName, cardName, moduleInfo, dataModule) if godGroups and order and next(godGroups) then cardInfo.hasGodInspiration = true cardInfo.godInspirationGroups = godGroups cardInfo.godInspirationGroupOrder = order end end -- 主卡牌的衍生牌 local subCardInfo = nil if finalCardData.sub then subCardInfo = p.parseSubCardData(finalCardData.sub, dataModule, moduleInfo) end return displayModule.render(cardInfo, subCardInfo) end function p.batch(frame) local args = getArgs(frame, { removeBlank = false }) local html = {} -- 开始包裹容器 table.insert(html, '<div style="display:flex;gap:10px;flex-wrap:wrap;">') -- 遍历所有参数组 local i = 1 while args[i] do local moduleName = args[i] local cardName = args[i+1] local variantType = args[i+2] or nil local variantParam = args[i+3] or nil local variantIndex = args[i+4] or nil if moduleName and cardName then -- 构造子 frame 调用 p.main local subFrame = { args = {moduleName, cardName, variantType, variantParam, variantIndex}, getParent = function() return frame end } table.insert(html, p.main(subFrame)) end i = i + 5 -- 每组5个参数(模块名,卡牌名,变体类型,变体参数,变体索引) end -- 结束包裹容器 table.insert(html, '</div>') return table.concat(html, '') end return p
该页面使用的模板:
模块:卡牌/doc
(
查看源代码
)
返回
模块:卡牌
。