卡牌:修订间差异
来自卡厄思梦境WIKI
无编辑摘要 |
无编辑摘要 |
||
| 第1行: | 第1行: | ||
local p = {} | local p = {} | ||
-- 配置常量 | |||
local CONFIG = { | |||
DEFAULT_ART = "start_1041_01.png", | |||
DEFAULT_COLOR = "白", | |||
DEFAULT_ATTRIBUTE = "虚无", | |||
DEFAULT_DECK = "起始卡牌", | |||
CARD_WIDTH = 168, | |||
CARD_HEIGHT = 230, | |||
} | |||
-- 颜色映射表 | -- 颜色映射表 | ||
local | 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 function | local function safeGet(data, field, default) | ||
if not | return data and data[field] or default | ||
return | end | ||
-- 处理描述文本中的模板 | |||
local function processDescription(frame, description) | |||
if not description or description == "" then | |||
return description | |||
end | end | ||
local success, result = pcall(function() | |||
return frame:preprocess(description) | |||
end) | |||
local | |||
-- | return success and result or description | ||
local | end | ||
-- 生成卡牌HTML样式组件 | |||
local function buildStyleComponents(cardData, cardName) | |||
local color = safeGet(cardData, "稀有度", CONFIG.DEFAULT_COLOR) | |||
local colorStyle = COLOR_MAP[color] or COLOR_MAP[CONFIG.DEFAULT_COLOR] | |||
local attribute = safeGet(cardData, "属性", CONFIG.DEFAULT_ATTRIBUTE) | |||
local cardDeck = safeGet(cardData, "卡组", CONFIG.DEFAULT_DECK) | |||
local borderStyle = cardDeck == "起始卡牌" and "normal" or "unique" | |||
return { | |||
color = color, | |||
colorStyle = colorStyle, | |||
attribute = attribute, | |||
borderStyle = borderStyle, | |||
ap = safeGet(cardData, "AP", ""), | |||
cardType = safeGet(cardData, "类型", ""), | |||
art = safeGet(cardData, "art", CONFIG.DEFAULT_ART) | |||
} | |||
end | |||
-- 构建卡牌HTML | |||
local function buildCardHTML(frame, cardName, cardData) | |||
if not cardData then | |||
return string.format("找不到卡牌数据: %s", cardName or "未指定") | |||
end | end | ||
local style = buildStyleComponents(cardData, cardName) | |||
local | local description = processDescription(frame, safeGet(cardData, "描述", "")) | ||
return | -- 使用字符串拼接优化HTML生成 | ||
local htmlParts = { | |||
string.format('<div style="position: relative; width: %dpx; height: %dpx; overflow: hidden;">', | |||
CONFIG.CARD_WIDTH, CONFIG.CARD_HEIGHT), | |||
-- 背景图片层 | |||
string.format('<div style="position: absolute; top: 1px; left: 12px;">[[File:%s|151px|link=]]</div>', style.art), | |||
'<div style="position: absolute; top: 1px; left: 12px;">[[File:card_黑色蒙版.png|151px|link=]]</div>', | |||
-- 颜色条 | |||
string.format('<div style="position: absolute; top: 20px; left: 10px; width: 148px; height: 10px; background-color: %s;"></div>', | |||
style.colorStyle.bgColor), | |||
-- AP值 | |||
string.format('<div style="position: absolute; left: 23px; top: 4px; color: white; font-weight: bold; text-shadow: 0 0 10px #4a90e2,0 0 20px #4a90e2, 0 0 30px #4a90e2, 0 0 40px #4a90e2; font-size: 32px;">%s</div>', | |||
style.ap), | |||
'<div style="position: absolute; left: 25px; top: 34px; color: white; font-weight: bold; text-shadow: 0 0 10px #4a90e2,0 0 20px #4a90e2, 0 0 30px #4a90e2, 0 0 40px #4a90e2;">—</div>', | |||
-- 卡牌名称和类型 | |||
string.format('<div style="position: absolute; left: 50px; top: 13px; color: %s; font-size:16px">%s</div>', | |||
style.colorStyle.textColor, cardName), | |||
string.format('<div style="position: absolute; left: 48px; top: 30px;">[[File:icon_card_%s.png|18px|link=]]</div>', | |||
style.cardType), | |||
string.format('<div style="position: absolute; left: 68px; top: 33px; color: white; font-size:14px">%s</div>', | |||
style.cardType), | |||
-- 边框和稀有度 | |||
string.format('<div style="position: absolute; top: 0px; left: 1px;">[[File:card_属性边框_%s_%s.png|160px|link=]]</div>', | |||
style.attribute, style.borderStyle), | |||
string.format('<div style="position: absolute; top: 10px; left: 0px;">[[File:card_稀有度_%s.png|22px|link=]]</div>', | |||
style.color), | |||
string.format('<div style="position: absolute; top: 2px; right: 4px;">[[File:card_稀有度_边框_%s.png|11px|link=]]</div>', | |||
style.color), | |||
-- 描述文本 | |||
'<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;">', | |||
string.format('<div>%s</div>', description), | |||
'</div>', | |||
'</div>' | |||
} | |||
return table.concat(htmlParts) | |||
end | end | ||
| 第82行: | 第112行: | ||
local function mergeCardData(baseData, overrideData) | local function mergeCardData(baseData, overrideData) | ||
local result = {} | local result = {} | ||
for k, v in pairs(baseData) do | for k, v in pairs(baseData or {}) do | ||
result[k] = v | result[k] = v | ||
end | end | ||
for k, v in pairs(overrideData) do | for k, v in pairs(overrideData or {}) do | ||
result[k] = v | result[k] = v | ||
end | end | ||
| 第91行: | 第121行: | ||
end | end | ||
-- | -- 获取并显示所有默认卡牌 | ||
local function | local function displayAllDefaultCards(frame, characterModule) | ||
-- | local cards = characterModule.card or {} | ||
if | local cardOrder = characterModule.cardOrder or {} | ||
return | local displayedCards = {} | ||
-- 按cardOrder顺序遍历 | |||
for orderIndex, name in ipairs(cardOrder) do | |||
local cardArray = cards[name] | |||
if cardArray and #cardArray > 0 then | |||
-- 只显示第一张卡牌 | |||
table.insert(displayedCards, { | |||
name = name, | |||
data = cardArray[1], | |||
order = orderIndex | |||
}) | |||
end | |||
end | |||
-- 生成HTML | |||
local htmlParts = {} | |||
for i, cardInfo in ipairs(displayedCards) do | |||
table.insert(htmlParts, buildCardHTML(frame, cardInfo.name, cardInfo.data)) | |||
if i < #displayedCards then | |||
table.insert(htmlParts, "<br><br>") | |||
end | |||
end | |||
return table.concat(htmlParts) | |||
end | |||
-- 处理特定卡牌请求 | |||
local function handleSpecificCard(frame, cardName, cardData, deckFilter, cardIndex) | |||
local baseCard = cardData[1] | |||
-- 如果没有指定卡组筛选,返回基础卡牌 | |||
if deckFilter == "" then | |||
return buildCardHTML(frame, cardName, baseCard) | |||
end | |||
-- 筛选指定卡组的卡牌 | |||
local filteredCards = {} | |||
for _, card in ipairs(cardData) do | |||
if card["卡组"] == deckFilter then | |||
table.insert(filteredCards, card) | |||
end | |||
end | |||
if #filteredCards == 0 then | |||
return string.format("找不到卡组 '%s' 的卡牌: %s", deckFilter, cardName) | |||
end | |||
-- 如果指定了索引,返回特定卡牌 | |||
if cardIndex > 0 and cardIndex <= #filteredCards then | |||
local mergedCard = mergeCardData(baseCard, filteredCards[cardIndex]) | |||
return buildCardHTML(frame, cardName, mergedCard) | |||
end | end | ||
-- | -- 否则返回该卡组的所有卡牌 | ||
local | local htmlParts = {} | ||
for | for i, card in ipairs(filteredCards) do | ||
table.insert( | local mergedCard = mergeCardData(baseCard, card) | ||
table.insert(htmlParts, buildCardHTML(frame, cardName, mergedCard)) | |||
if i < #filteredCards then | |||
table.insert(htmlParts, "<br><br>") | |||
end | |||
end | end | ||
return | return table.concat(htmlParts) | ||
end | end | ||
-- | -- 主函数 | ||
function p.main(frame) | function p.main(frame) | ||
local args = frame.args | local args = frame.args | ||
| 第115行: | 第200行: | ||
local cardIndex = tonumber(args[4]) or 0 | local cardIndex = tonumber(args[4]) or 0 | ||
-- | -- 加载战斗员模块 | ||
local characterModule | local success, characterModule = pcall(require, "模块:卡牌/" .. characterName) | ||
if not success or not characterModule then | if not success or not characterModule then | ||
return "找不到战斗员卡牌数据模块: 模块:卡牌/" | return string.format("找不到战斗员卡牌数据模块: 模块:卡牌/%s", characterName) | ||
end | end | ||
-- | -- 如果没有指定卡牌名,显示所有默认卡牌 | ||
if cardName == "" then | if cardName == "" then | ||
return displayAllDefaultCards(frame, characterModule) | |||
end | end | ||
local cardData = | -- 获取指定卡牌数据 | ||
local cardData = (characterModule.card or {})[cardName] | |||
if not cardData then | if not cardData then | ||
return "找不到卡牌: " | return string.format("找不到卡牌: %s", cardName) | ||
end | end | ||
return handleSpecificCard(frame, cardName, cardData, deckFilter, cardIndex) | |||
end | end | ||
-- | -- 元表设置,支持直接调用战斗员名称作为方法 | ||
setmetatable(p, { | setmetatable(p, { | ||
__index = function(t, characterName) | __index = function(t, characterName) | ||
return function(frame) | return function(frame) | ||
frame.args = { | |||
[1] = characterName, | [1] = characterName, | ||
[2] = | [2] = frame.args[1] or "", | ||
[3] = | [3] = frame.args[2] or "", | ||
[4] = | [4] = frame.args[3] or 0 | ||
} | } | ||
return p.main(frame) | return p.main(frame) | ||
end | end | ||
2025年9月27日 (六) 17:32的版本
此模块的文档可以在模块:卡牌/doc创建
local p = {}
-- 配置常量
local CONFIG = {
DEFAULT_ART = "start_1041_01.png",
DEFAULT_COLOR = "白",
DEFAULT_ATTRIBUTE = "虚无",
DEFAULT_DECK = "起始卡牌",
CARD_WIDTH = 168,
CARD_HEIGHT = 230,
}
-- 颜色映射表
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 function safeGet(data, field, default)
return data and data[field] or default
end
-- 处理描述文本中的模板
local function processDescription(frame, description)
if not description or description == "" then
return description
end
local success, result = pcall(function()
return frame:preprocess(description)
end)
return success and result or description
end
-- 生成卡牌HTML样式组件
local function buildStyleComponents(cardData, cardName)
local color = safeGet(cardData, "稀有度", CONFIG.DEFAULT_COLOR)
local colorStyle = COLOR_MAP[color] or COLOR_MAP[CONFIG.DEFAULT_COLOR]
local attribute = safeGet(cardData, "属性", CONFIG.DEFAULT_ATTRIBUTE)
local cardDeck = safeGet(cardData, "卡组", CONFIG.DEFAULT_DECK)
local borderStyle = cardDeck == "起始卡牌" and "normal" or "unique"
return {
color = color,
colorStyle = colorStyle,
attribute = attribute,
borderStyle = borderStyle,
ap = safeGet(cardData, "AP", ""),
cardType = safeGet(cardData, "类型", ""),
art = safeGet(cardData, "art", CONFIG.DEFAULT_ART)
}
end
-- 构建卡牌HTML
local function buildCardHTML(frame, cardName, cardData)
if not cardData then
return string.format("找不到卡牌数据: %s", cardName or "未指定")
end
local style = buildStyleComponents(cardData, cardName)
local description = processDescription(frame, safeGet(cardData, "描述", ""))
-- 使用字符串拼接优化HTML生成
local htmlParts = {
string.format('<div style="position: relative; width: %dpx; height: %dpx; overflow: hidden;">',
CONFIG.CARD_WIDTH, CONFIG.CARD_HEIGHT),
-- 背景图片层
string.format('<div style="position: absolute; top: 1px; left: 12px;">[[File:%s|151px|link=]]</div>', style.art),
'<div style="position: absolute; top: 1px; left: 12px;">[[File:card_黑色蒙版.png|151px|link=]]</div>',
-- 颜色条
string.format('<div style="position: absolute; top: 20px; left: 10px; width: 148px; height: 10px; background-color: %s;"></div>',
style.colorStyle.bgColor),
-- AP值
string.format('<div style="position: absolute; left: 23px; top: 4px; color: white; font-weight: bold; text-shadow: 0 0 10px #4a90e2,0 0 20px #4a90e2, 0 0 30px #4a90e2, 0 0 40px #4a90e2; font-size: 32px;">%s</div>',
style.ap),
'<div style="position: absolute; left: 25px; top: 34px; color: white; font-weight: bold; text-shadow: 0 0 10px #4a90e2,0 0 20px #4a90e2, 0 0 30px #4a90e2, 0 0 40px #4a90e2;">—</div>',
-- 卡牌名称和类型
string.format('<div style="position: absolute; left: 50px; top: 13px; color: %s; font-size:16px">%s</div>',
style.colorStyle.textColor, cardName),
string.format('<div style="position: absolute; left: 48px; top: 30px;">[[File:icon_card_%s.png|18px|link=]]</div>',
style.cardType),
string.format('<div style="position: absolute; left: 68px; top: 33px; color: white; font-size:14px">%s</div>',
style.cardType),
-- 边框和稀有度
string.format('<div style="position: absolute; top: 0px; left: 1px;">[[File:card_属性边框_%s_%s.png|160px|link=]]</div>',
style.attribute, style.borderStyle),
string.format('<div style="position: absolute; top: 10px; left: 0px;">[[File:card_稀有度_%s.png|22px|link=]]</div>',
style.color),
string.format('<div style="position: absolute; top: 2px; right: 4px;">[[File:card_稀有度_边框_%s.png|11px|link=]]</div>',
style.color),
-- 描述文本
'<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;">',
string.format('<div>%s</div>', description),
'</div>',
'</div>'
}
return table.concat(htmlParts)
end
-- 合并卡牌数据
local function mergeCardData(baseData, overrideData)
local result = {}
for k, v in pairs(baseData or {}) do
result[k] = v
end
for k, v in pairs(overrideData or {}) do
result[k] = v
end
return result
end
-- 获取并显示所有默认卡牌
local function displayAllDefaultCards(frame, characterModule)
local cards = characterModule.card or {}
local cardOrder = characterModule.cardOrder or {}
local displayedCards = {}
-- 按cardOrder顺序遍历
for orderIndex, name in ipairs(cardOrder) do
local cardArray = cards[name]
if cardArray and #cardArray > 0 then
-- 只显示第一张卡牌
table.insert(displayedCards, {
name = name,
data = cardArray[1],
order = orderIndex
})
end
end
-- 生成HTML
local htmlParts = {}
for i, cardInfo in ipairs(displayedCards) do
table.insert(htmlParts, buildCardHTML(frame, cardInfo.name, cardInfo.data))
if i < #displayedCards then
table.insert(htmlParts, "<br><br>")
end
end
return table.concat(htmlParts)
end
-- 处理特定卡牌请求
local function handleSpecificCard(frame, cardName, cardData, deckFilter, cardIndex)
local baseCard = cardData[1]
-- 如果没有指定卡组筛选,返回基础卡牌
if deckFilter == "" then
return buildCardHTML(frame, cardName, baseCard)
end
-- 筛选指定卡组的卡牌
local filteredCards = {}
for _, card in ipairs(cardData) do
if card["卡组"] == deckFilter then
table.insert(filteredCards, card)
end
end
if #filteredCards == 0 then
return string.format("找不到卡组 '%s' 的卡牌: %s", deckFilter, cardName)
end
-- 如果指定了索引,返回特定卡牌
if cardIndex > 0 and cardIndex <= #filteredCards then
local mergedCard = mergeCardData(baseCard, filteredCards[cardIndex])
return buildCardHTML(frame, cardName, mergedCard)
end
-- 否则返回该卡组的所有卡牌
local htmlParts = {}
for i, card in ipairs(filteredCards) do
local mergedCard = mergeCardData(baseCard, card)
table.insert(htmlParts, buildCardHTML(frame, cardName, mergedCard))
if i < #filteredCards then
table.insert(htmlParts, "<br><br>")
end
end
return table.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
-- 加载战斗员模块
local success, characterModule = pcall(require, "模块:卡牌/" .. characterName)
if not success or not characterModule then
return string.format("找不到战斗员卡牌数据模块: 模块:卡牌/%s", characterName)
end
-- 如果没有指定卡牌名,显示所有默认卡牌
if cardName == "" then
return displayAllDefaultCards(frame, characterModule)
end
-- 获取指定卡牌数据
local cardData = (characterModule.card or {})[cardName]
if not cardData then
return string.format("找不到卡牌: %s", cardName)
end
return handleSpecificCard(frame, cardName, cardData, deckFilter, cardIndex)
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