模块:卡牌
来自卡厄思梦境WIKI
此模块的文档可以在模块:卡牌/doc创建
local p = {}
-- 颜色映射表(保持不变但添加快速查找)
local COLOR_MAP = {
["白"] = { bgColor = "rgba(249, 249, 249, 0.5)", textColor = "white" },
["蓝"] = { bgColor = "rgba(115, 236, 254, 0.5)", textColor = "#7de5ff" },
["橙"] = { bgColor = "rgba(254, 199, 109, 0.5)", textColor = "#ffee75" },
["彩"] = { bgColor = "rgba(201, 88, 241, 0.5)", textColor = "#eba2fc" }
}
local DEFAULT_COLOR = COLOR_MAP["白"]
-- 优化:减少函数调用,内联简单操作
local function safeGet(data, field, default)
local value = data and data[field]
return (value ~= nil and value ~= "") and value or default
end
-- 优化:添加缓存避免重复处理
local descriptionCache = {}
local function processDescription(frame, description)
if not description or description == "" then
return ""
end
-- 检查缓存
if descriptionCache[description] then
return descriptionCache[description]
end
local success, result = pcall(function()
return frame:preprocess(description)
end)
local processed = success and result or description
descriptionCache[description] = processed
return processed
end
-- 优化:预构建HTML片段,减少字符串操作
local function buildImageTag(filename, size, extraStyle)
extraStyle = extraStyle or ""
return string.format('[[File:%s|%spx|link=]]', filename, size)
end
-- 优化:合并样式计算,减少重复代码
local function calculateCardStyle(cardData, baseCardData)
local color = safeGet(cardData, "稀有度", "白")
local colorStyle = COLOR_MAP[color] or DEFAULT_COLOR
local ap = safeGet(cardData, "AP", "")
local originalAP = baseCardData and safeGet(baseCardData, "AP", ap) or ap
-- AP发光颜色计算
local apGlowColor = "#4a90e2"
if baseCardData and ap ~= originalAP and ap ~= "X" then
local apNum, origNum = tonumber(ap), tonumber(originalAP)
if apNum and origNum then
apGlowColor = apNum < origNum and "#51f651" or "#f65151"
end
end
-- 机制变化检测
local mechanism = safeGet(cardData, "机制", "")
local originalMechanism = baseCardData and safeGet(baseCardData, "机制", "") or mechanism
mechanism = mechanism == "无" and "" or mechanism
originalMechanism = originalMechanism == "无" and "" or originalMechanism
return {
color = color,
colorStyle = colorStyle,
attribute = safeGet(cardData, "属性", "虚无"),
cardType = safeGet(cardData, "类型", ""),
art = safeGet(cardData, "art", ""),
ap = ap,
apGlowColor = apGlowColor,
mechanism = mechanism,
mechanismChanged = baseCardData and mechanism ~= "" and originalMechanism == ""
}
end
-- 优化:使用局部变量减少表查找
local format = string.format
local insert = table.insert
local concat = table.concat
-- 优化:模板化HTML生成
-- 修复后的 buildCardHTML 函数中的HTML生成部分
local function buildCardHTML(frame, cardName, cardData, baseCardData, characterName)
if not cardData then
return format('<div style="color:red;">找不到卡牌: %s</div>', cardName or "未指定")
end
local style = calculateCardStyle(cardData, baseCardData)
local description = processDescription(frame, safeGet(cardData, "描述", ""))
-- 数据属性
local dataAttrs = format(
'data-card-name="%s" data-character="%s" data-deck-type="%s" data-derived-cards="%s"',
cardName or "",
characterName or "",
safeGet(cardData, "卡组", ""),
safeGet(cardData, "衍生卡牌", "")
)
-- 机制HTML(优化:提前判断避免无用字符串生成)
local mechanismHTML = ""
if style.mechanism ~= "" then
local mechanismColor = style.mechanismChanged and "#b5f651" or "#f6c478"
mechanismHTML = format(
'<div style="color: %s; margin-bottom: 4px;">[%s]</div>',
mechanismColor,
style.mechanism:gsub("、", "/")
)
end
-- AP显示(复用格式字符串)
local apShadow = format(
"0 0 10px %s,0 0 20px %s, 0 0 30px %s, 0 0 40px %s",
style.apGlowColor, style.apGlowColor, style.apGlowColor, style.apGlowColor
)
local html = {}
-- 容器开始
insert(html, 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
-- 状态异常布局(使用 [=[ ]=] 避免冲突)
insert(html, format([=[
<div style="position: absolute; top: 5px; left: 5px;">%s</div>
<div style="position: absolute; top: 0px; left: 0px;">%s</div>
<div style="position: absolute; left: 24px; top: 4px; color: white; font-weight: bold; text-shadow: %s; font-size: 32px;">%s</div>
<div style="position: absolute; left: 25px; top: 34px; color: white; font-weight: bold; text-shadow: %s;">—</div>
<div style="position: absolute; left: 50px; top: 13px; color: %s; font-size:16px">%s</div>
<div style="position: absolute; left: 48px; top: 30px;">%s</div>
<div style="position: absolute; left: 68px; top: 33px; color: white; font-size:14px">%s</div>
<div style="position: absolute; left: 0px; bottom: 0px;">[[File:card_顶层蒙版.png|168px|link=]]</div>]=],
buildImageTag(style.art, 150),
buildImageTag(format("card_状态异常_%s.png", style.attribute), 159),
apShadow, style.ap,
apShadow,
style.colorStyle.textColor, cardName,
buildImageTag(format("icon_card_%s.png", style.cardType), 18),
style.cardType
))
else
-- 普通卡牌布局(使用 [=[ ]=] 避免冲突)
insert(html, format([=[
<div style="position: absolute; top: 1px; left: 12px;">%s</div>
<div style="position: absolute; top: 1px; left: 12px;">[[File:card_黑色蒙版.png|151px|link=]]</div>
<div style="position: absolute; top: 21px; left: 10px; width: 148px; height: 8px; background-color: %s;"></div>
<div style="position: absolute; left: 24px; top: 4px; color: white; font-weight: bold; text-shadow: %s; font-size: 32px;">%s</div>
<div style="position: absolute; left: 25px; top: 34px; color: white; font-weight: bold; text-shadow: %s;">—</div>
<div style="position: absolute; left: 50px; top: 13px; color: %s; font-size:16px">%s</div>
<div style="position: absolute; left: 48px; top: 30px;">%s</div>
<div style="position: absolute; left: 68px; top: 33px; color: white; font-size:14px">%s</div>
<div style="position: absolute; top: 0px; left: 1px;">%s</div>
<div style="position: absolute; top: 10px; left: 0px;">%s</div>
<div style="position: absolute; top: 2px; right: 4px;">%s</div>
<div style="position: absolute; left: 0px; bottom: 0px;">[[File:card_顶层蒙版.png|168px|link=]]</div>]=],
buildImageTag(style.art, 151),
style.colorStyle.bgColor,
apShadow, style.ap,
apShadow,
style.colorStyle.textColor, cardName,
buildImageTag(format("icon_card_%s.png", style.cardType), 18),
style.cardType,
buildImageTag(format("card_属性边框_%s.png", style.attribute), 160),
buildImageTag(format("card_稀有度_%s.png", style.color), 22),
buildImageTag(format("card_稀有度_边框_%s.png", style.color), 11)
))
end
-- 描述区域(使用 [=[ ]=] 避免冲突)
insert(html, format([=[
<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;">
<div style="line-height: 13px;">%s%s</div>
</div>
</div>]=], mechanismHTML, description))
return concat(html)
end
-- 批量生成卡牌HTML
local function displayAllDefaultCards(frame, characterModule, characterName)
local cards = characterModule.card or {}
local cardOrder = characterModule.cardOrder or {}
if #cardOrder == 0 then
return "<div>没有找到卡牌顺序信息</div>"
end
local htmlParts = {}
for _, name in ipairs(cardOrder) do
local cardArray = cards[name]
if cardArray and #cardArray > 0 then
insert(htmlParts, buildCardHTML(frame, name, cardArray[1], nil, characterName))
end
end
return concat(htmlParts)
end
local function handleSpecificCard(frame, cardName, cardData, deckFilter, cardIndex, characterName)
local baseCard = cardData[1]
if deckFilter == "" then
return buildCardHTML(frame, cardName, baseCard, nil, characterName)
end
-- 筛选卡组
local filteredCards = {}
for _, card in ipairs(cardData) do
if card["卡组"] == deckFilter then
insert(filteredCards, card)
end
end
if #filteredCards == 0 then
return format('<div style="color:orange;">找不到卡组 "%s" 的卡牌: %s</div>', deckFilter, cardName)
end
-- 合并数据函数
local function mergeData(base, override)
local result = {}
for k, v in pairs(base) do result[k] = v end
for k, v in pairs(override) do result[k] = v end
return result
end
-- 特定索引
if cardIndex > 0 and cardIndex <= #filteredCards then
return buildCardHTML(frame, cardName, mergeData(baseCard, filteredCards[cardIndex]), baseCard, characterName)
end
-- 所有卡牌
local htmlParts = {}
for _, card in ipairs(filteredCards) do
insert(htmlParts, buildCardHTML(frame, cardName, mergeData(baseCard, card), baseCard, characterName))
end
return concat(htmlParts)
end
-- 主函数
function p.main(frame)
local args = frame.args
local characterName = args[1] or ""
local cardName = args[2] or ""
local deckFilter = args[3] or ""
local cardIndex = tonumber(args[4]) or 0
-- 失败
if characterName == "" then
return '<div style="color:red;">请指定战斗员名称</div>'
end
-- 加载模块
local success, characterModule = pcall(require, "模块:卡牌/" .. characterName)
if not success or not characterModule then
return format('<div style="color:red;">找不到战斗员: %s</div>', characterName)
end
-- 显示所有卡牌
if cardName == "" then
return displayAllDefaultCards(frame, characterModule, characterName)
end
-- 显示特定卡牌
local cardData = (characterModule.card or {})[cardName]
if not cardData then
return format('<div style="color:red;">找不到卡牌: %s</div>', cardName)
end
return handleSpecificCard(frame, cardName, cardData, deckFilter, cardIndex, characterName)
end
-- 元表设置
setmetatable(p, {
__index = function(t, characterName)
return function(frame)
frame.args = {
[1] = characterName,
[2] = frame.args[1] or "",
[3] = frame.args[2] or "",
[4] = frame.args[3] or 0
}
return p.main(frame)
end
end
})
return p