卡厄思
梦
境
菜单
首页
回到首页
WIKI工具
全站样式
全站JS
修改导航栏
测试
沙盒
可视化管理器
战斗员管理器
卡牌管理器
伙伴管理器
装备管理器
词典管理器
图鉴
战斗员
伙伴
装备
怪物卡牌
中立卡牌
赛季卡牌·施工中
事件·施工中
小工具
节奏榜生成器
搜索
链入页面
相关更改
特殊页面
页面信息
最近更改
登录
模块
查看“︁卡牌”︁的源代码
←
模块:卡牌
因为以下原因,您没有权限编辑该页面:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
local p = {} -- 安全获取嵌套表数据 local function safeGet(tbl, key, default) if tbl and tbl[key] ~= nil then return tbl[key] end return default or "" end -- 颜色映射表 local COLOR_MAP = { ["白"] = { bgColor = "#ffffff", textColor = "#333333" }, ["蓝"] = { bgColor = "#4a90e2", textColor = "white" }, ["紫"] = { bgColor = "#9b59b6", textColor = "white" }, ["金"] = { bgColor = "#f1c40f", textColor = "#333333" } } -- 计算名称缩放比例 local function calculateNameScale(name) local length = mw.ustring.len(name) -- 基准是5个字符以内 if length <= 5 then return "1" elseif length <= 7 then return "0.9" elseif length <= 9 then return "0.8" elseif length <= 11 then return "0.7" else return "0.6" end end -- 处理描述文本 local function processDescription(frame, description) if not description or description == "" then return "" end -- 处理换行符 description = description:gsub("\r?\n", "<br>") -- 处理图标:{{图标名称}} 转换为对应图片 description = description:gsub("{{(.-)}}", function(iconName) return string.format('[[File:icon_%s.png|16px|link=|style="vertical-align: -3px; margin: 0 1px;"]]', iconName) end) -- 处理高亮文本:<hl>文本</hl> 转换为金色 description = description:gsub("<hl>(.-)</hl>", function(text) return string.format('<span style="color: #f1c832; font-weight: bold; text-shadow: 0 0 2px rgba(241, 200, 50, 0.5);">%s</span>', text) end) return frame:preprocess(description) end -- 生成卡牌HTML样式组件 local function buildStyleComponents(cardData, cardName, baseCardData) local color = safeGet(cardData, "稀有度", "白") local colorStyle = COLOR_MAP[color] or COLOR_MAP["白"] local attribute = safeGet(cardData, "属性", "虚无") local cardDeck = safeGet(cardData, "卡组", "起始卡牌") local ap = safeGet(cardData, "AP", "") local originalAP = baseCardData and safeGet(baseCardData, "AP", ap) or ap -- 决定AP的发光颜色 local apGlowColor = "#4a90e2" -- 默认蓝色 if baseCardData and ap ~= originalAP then if ap == "X" then apGlowColor = "#4a90e2" -- X值保持默认蓝色 elseif tonumber(ap) and tonumber(originalAP) then if tonumber(ap) < tonumber(originalAP) then apGlowColor = "#51f651" -- 绿色(AP降低) else apGlowColor = "#f65151" -- 红色(AP增加) end end end -- 检查原卡牌与当前卡牌的机制变化(将"无"视为空字符串) local mechanism = safeGet(cardData, "机制", "") local originalMechanism = baseCardData and safeGet(baseCardData, "机制", "") or mechanism -- 将"无"视为空字符串 if mechanism == "无" then mechanism = "" end if originalMechanism == "无" then originalMechanism = "" end local mechanismChanged = baseCardData and mechanism ~= "" and originalMechanism == "" return { color = color, colorStyle = colorStyle, attribute = attribute, ap = ap, apGlowColor = apGlowColor, cardType = safeGet(cardData, "类型", ""), art = safeGet(cardData, "art", "start_1041_01.png"), mechanism = mechanism, mechanismChanged = mechanismChanged } end -- 构建卡牌HTML local function buildCardHTML(frame, cardName, cardData, baseCardData, characterName) if not cardData then return string.format("找不到卡牌数据: %s", cardName or "未指定") end local style = buildStyleComponents(cardData, cardName, baseCardData) local description = processDescription(frame, safeGet(cardData, "描述", "")) -- 获取衍生卡牌信息 local derivedCards = safeGet(cardData, "衍生卡牌", "") local deckType = safeGet(cardData, "卡组", "") -- 生成数据属性 local dataAttrs = string.format('data-card-name="%s" data-character="%s" data-deck-type="%s" data-derived-cards="%s"', cardName or "", characterName or "", deckType or "", derivedCards or "") -- 处理机制文本(当机制为"无"或空时不显示) local mechanismHTML = "" if style.mechanism and style.mechanism ~= "" then local mechanismColor = style.mechanismChanged and "#b5f651" or "#f6c478" mechanismHTML = string.format('<div style="color: %s; margin-bottom: 4px;">[%s]</div>', mechanismColor, style.mechanism:gsub("、", "/")) end -- 计算名称缩放比例 local nameScale = calculateNameScale(cardName) -- 使用字符串拼接优化HTML生成 local htmlParts = { string.format('<div class="game-card" %s style="display: inline-block; vertical-align: top; position: relative; width: 168px; height: 230px; overflow: hidden; margin: 0px; cursor: pointer;">', dataAttrs), } -- 根据类型判断使用哪种布局 if style.cardType == "状态异常" then -- 状态异常卡牌的特殊布局 table.insert(htmlParts, string.format('<div style="position: absolute; top: 5px; left: 5px;">[[File:%s|150px|link=]]</div>', style.art)) table.insert(htmlParts, string.format('<div style="position: absolute; top: 0px; left: 0px;">[[File:card_状态异常_%s.png|159px|link=]]</div>', style.attribute)) -- AP值 table.insert(htmlParts, string.format('<div style="position: absolute; left: 24px; top: 4px; color: white; font-weight: bold; text-shadow: 0 0 10px %s,0 0 20px %s, 0 0 30px %s, 0 0 40px %s; font-size: 32px;">%s</div>', style.apGlowColor, style.apGlowColor, style.apGlowColor, style.apGlowColor, style.ap)) table.insert(htmlParts, string.format('<div style="position: absolute; left: 25px; top: 34px; color: white; font-weight: bold; text-shadow: 0 0 10px %s,0 0 20px %s, 0 0 30px %s, 0 0 40px %s;">—</div>', style.apGlowColor, style.apGlowColor, style.apGlowColor, style.apGlowColor)) -- 卡牌名称(使用transform缩放) table.insert(htmlParts, string.format('<div style="position: absolute; left: 50px; top: 13px; width: 105px; transform-origin: left center; transform: scaleX(%s);"><span style="color: %s; font-size: 16px; white-space: nowrap;">%s</span></div>', nameScale, style.colorStyle.textColor, cardName)) -- 卡牌类型 table.insert(htmlParts, string.format('<div style="position: absolute; left: 48px; top: 30px;">[[File:icon_card_%s.png|18px|link=]]</div>', style.cardType)) table.insert(htmlParts, string.format('<div style="position: absolute; left: 68px; top: 33px; color: white; font-size:14px">%s</div>', style.cardType)) -- 顶层蒙版 table.insert(htmlParts, '<div style="position: absolute; left: 0px; bottom: 0px;">[[File:card_顶层蒙版.png|168px|link=]]</div>') else -- 普通卡牌的布局 -- 背景图片层 table.insert(htmlParts, string.format('<div style="position: absolute; top: 1px; left: 12px;">[[File:%s|151px|link=]]</div>', style.art)) table.insert(htmlParts, '<div style="position: absolute; top: 1px; left: 12px;">[[File:card_黑色蒙版.png|151px|link=]]</div>') -- 颜色条 table.insert(htmlParts, string.format('<div style="position: absolute; top: 21px; left: 10px; width: 148px; height: 8px; background-color: %s;"></div>', style.colorStyle.bgColor)) -- AP值 table.insert(htmlParts, string.format('<div style="position: absolute; left: 24px; top: 4px; color: white; font-weight: bold; text-shadow: 0 0 10px %s,0 0 20px %s, 0 0 30px %s, 0 0 40px %s; font-size: 32px;">%s</div>', style.apGlowColor, style.apGlowColor, style.apGlowColor, style.apGlowColor, style.ap)) table.insert(htmlParts, string.format('<div style="position: absolute; left: 25px; top: 34px; color: white; font-weight: bold; text-shadow: 0 0 10px %s,0 0 20px %s, 0 0 30px %s, 0 0 40px %s;">—</div>', style.apGlowColor, style.apGlowColor, style.apGlowColor, style.apGlowColor)) -- 卡牌名称(使用transform缩放) table.insert(htmlParts, string.format('<div style="position: absolute; left: 50px; top: 13px; width: 105px; transform-origin: left center; transform: scaleX(%s);"><span style="color: %s; font-size: 16px; white-space: nowrap;">%s</span></div>', nameScale, style.colorStyle.textColor, cardName)) -- 卡牌类型 table.insert(htmlParts, string.format('<div style="position: absolute; left: 48px; top: 30px;">[[File:icon_card_%s.png|18px|link=]]</div>', style.cardType)) table.insert(htmlParts, string.format('<div style="position: absolute; left: 68px; top: 33px; color: white; font-size:14px">%s</div>', style.cardType)) -- 边框 table.insert(htmlParts, string.format('<div style="position: absolute; top: 0px; left: 1px;">[[File:card_属性边框_%s.png|160px|link=]]</div>', style.attribute)) -- 稀有度 table.insert(htmlParts, string.format('<div style="position: absolute; top: 10px; left: 0px;">[[File:card_稀有度_%s.png|22px|link=]]</div>', style.color)) table.insert(htmlParts, string.format('<div style="position: absolute; top: 2px; right: 4px;">[[File:card_稀有度_边框_%s.png|11px|link=]]</div>', style.color)) -- 顶层蒙版 table.insert(htmlParts, '<div style="position: absolute; left: 0px; bottom: 0px;">[[File:card_顶层蒙版.png|168px|link=]]</div>') end -- 描述文本(包含机制)- 对所有类型都显示 table.insert(htmlParts, '<div style="position: absolute; bottom: 7px; left: 15px; width: 144px; height: 100px; font-size: 12px; color: white; line-height: 13px; display: flex; justify-content: center; align-items: center; text-align: center;">') table.insert(htmlParts, '<div style="line-height: 13px;">') table.insert(htmlParts, mechanismHTML) table.insert(htmlParts, description) table.insert(htmlParts, '</div>') table.insert(htmlParts, '</div>') table.insert(htmlParts, '</div>') return table.concat(htmlParts) end -- 获取基础卡牌数据(用于对比) local function getBaseCardData(cardName) local data = mw.loadData("模块:卡牌数据") return data[cardName] end -- 主函数:显示卡牌 function p.displayCard(frame) local args = frame.args local cardName = args[1] or args["name"] local characterName = args[2] or args["character"] or "" local deckType = args[3] or args["deck"] or "" if not cardName then return "错误:未指定卡牌名称" end -- 优先从角色专属数据加载 local cardData = nil local baseCardData = nil if characterName ~= "" then local charDataModule = "模块:卡牌数据/" .. characterName local success, charData = pcall(mw.loadData, charDataModule) if success then -- 根据卡组类型查找 if deckType ~= "" and charData[deckType] then cardData = charData[deckType][cardName] else -- 遍历所有卡组查找 for _, deck in pairs(charData) do if type(deck) == "table" and deck[cardName] then cardData = deck[cardName] break end end end end -- 如果是变体卡牌,获取基础卡牌数据 if cardData then baseCardData = getBaseCardData(cardName) end end -- 如果没有找到专属数据,从通用数据加载 if not cardData then local data = mw.loadData("模块:卡牌数据") cardData = data[cardName] end if not cardData then return string.format("错误:找不到卡牌 '%s' 的数据", cardName) end return buildCardHTML(frame, cardName, cardData, baseCardData, characterName) end -- 批量显示卡牌 function p.displayCards(frame) local args = frame.args local cardList = args[1] or args["cards"] or "" local characterName = args[2] or args["character"] or "" local columns = tonumber(args[3] or args["columns"]) or 5 if cardList == "" then return "错误:未指定卡牌列表" end -- 解析卡牌列表 local cards = {} for card in mw.text.gsplit(cardList, ",") do card = mw.text.trim(card) if card ~= "" then table.insert(cards, card) end end if #cards == 0 then return "错误:卡牌列表为空" end -- 构建HTML local html = {} table.insert(html, '<div style="display: flex; flex-wrap: wrap; gap: 10px;">') for i, cardName in ipairs(cards) do -- 获取卡牌数据 local cardData = nil local baseCardData = nil if characterName ~= "" then local charDataModule = "模块:卡牌数据/" .. characterName local success, charData = pcall(mw.loadData, charDataModule) if success then for _, deck in pairs(charData) do if type(deck) == "table" and deck[cardName] then cardData = deck[cardName] break end end end if cardData then baseCardData = getBaseCardData(cardName) end end if not cardData then local data = mw.loadData("模块:卡牌数据") cardData = data[cardName] end if cardData then table.insert(html, buildCardHTML(frame, cardName, cardData, baseCardData, characterName)) else table.insert(html, string.format('<div style="color: red;">找不到卡牌: %s</div>', cardName)) end -- 添加换行 if i % columns == 0 and i < #cards then table.insert(html, '</div><div style="display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px;">') end end table.insert(html, '</div>') return table.concat(html) end -- 显示角色的所有卡牌 function p.displayCharacterCards(frame) local args = frame.args local characterName = args[1] or args["character"] local deckType = args[2] or args["deck"] or "all" local columns = tonumber(args[3] or args["columns"]) or 5 if not characterName then return "错误:未指定角色名称" end local charDataModule = "模块:卡牌数据/" .. characterName local success, charData = pcall(mw.loadData, charDataModule) if not success then return string.format("错误:找不到角色 '%s' 的卡牌数据", characterName) end -- 收集要显示的卡牌 local cardsToDisplay = {} if deckType == "all" then -- 显示所有卡组 local deckOrder = {"起始卡牌", "基础卡牌", "高级卡牌", "其他卡牌"} for _, dName in ipairs(deckOrder) do if charData[dName] then for cardName, cardData in pairs(charData[dName]) do table.insert(cardsToDisplay, {name = cardName, data = cardData, deck = dName}) end end end else -- 显示特定卡组 if charData[deckType] then for cardName, cardData in pairs(charData[deckType]) do table.insert(cardsToDisplay, {name = cardName, data = cardData, deck = deckType}) end else return string.format("错误:角色 '%s' 没有 '%s' 卡组", characterName, deckType) end end -- 排序(可选:按稀有度、AP值等排序) table.sort(cardsToDisplay, function(a, b) return a.name < b.name end) -- 构建HTML local html = {} table.insert(html, '<div style="display: flex; flex-wrap: wrap; gap: 10px;">') for i, card in ipairs(cardsToDisplay) do local baseCardData = getBaseCardData(card.name) table.insert(html, buildCardHTML(frame, card.name, card.data, baseCardData, characterName)) if i % columns == 0 and i < #cardsToDisplay then table.insert(html, '</div><div style="display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px;">') end end table.insert(html, '</div>') return table.concat(html) end -- 搜索卡牌 function p.searchCards(frame) local args = frame.args local searchTerm = args[1] or args["search"] or "" local searchType = args[2] or args["type"] or "name" -- name, description, mechanism local columns = tonumber(args[3] or args["columns"]) or 5 if searchTerm == "" then return "错误:未指定搜索词" end searchTerm = mw.ustring.lower(searchTerm) local data = mw.loadData("模块:卡牌数据") local results = {} for cardName, cardData in pairs(data) do local match = false if searchType == "name" then match = mw.ustring.find(mw.ustring.lower(cardName), searchTerm) ~= nil elseif searchType == "description" then local desc = safeGet(cardData, "描述", "") match = mw.ustring.find(mw.ustring.lower(desc), searchTerm) ~= nil elseif searchType == "mechanism" then local mech = safeGet(cardData, "机制", "") match = mw.ustring.find(mw.ustring.lower(mech), searchTerm) ~= nil elseif searchType == "all" then local nameMatch = mw.ustring.find(mw.ustring.lower(cardName), searchTerm) ~= nil local descMatch = mw.ustring.find(mw.ustring.lower(safeGet(cardData, "描述", "")), searchTerm) ~= nil local mechMatch = mw.ustring.find(mw.ustring.lower(safeGet(cardData, "机制", "")), searchTerm) ~= nil match = nameMatch or descMatch or mechMatch end if match then table.insert(results, {name = cardName, data = cardData}) end end if #results == 0 then return "没有找到符合条件的卡牌" end -- 排序 table.sort(results, function(a, b) return a.name < b.name end) -- 构建HTML local html = {} table.insert(html, string.format('<div>找到 %d 张卡牌:</div>', #results)) table.insert(html, '<div style="display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px;">') for i, result in ipairs(results) do table.insert(html, buildCardHTML(frame, result.name, result.data, nil, "")) if i % columns == 0 and i < #results then table.insert(html, '</div><div style="display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px;">') end end table.insert(html, '</div>') return table.concat(html) end return p
该页面使用的模板:
模块:卡牌/doc
(
查看源代码
)
返回
模块:卡牌
。