模块:CardData
来自夜幕之下
更多操作
此模块的文档可以在模块:CardData/doc创建
-- Module:CardData
-- 从 Directus API 获取「夜幕之下」卡片数据并渲染
-- 用法:{{#invoke:CardData|render|复仇童谣}}
local p = {}
-- ==============================
-- 配置
-- ==============================
local API_BASE = "https://data.saltedkiss.org/items/cards"
-- 需要获取的字段,去掉所有 user 相关信息
local FIELDS = table.concat({
"stylename",
"rarity",
"character.name",
"profession.name",
"desire.name",
"skill_normal_attack.name",
"skill_normal_attack.type",
"skill_normal_attack.weapon",
"skill_normal_attack.description",
"skill_normal_attack.levels.*",
"skill_passive.name",
"skill_passive.type",
"skill_passive.trigger_type",
"skill_passive.trigger_value",
"skill_passive.description",
"skill_passive.levels.*",
"skill_ultimate.name",
"skill_ultimate.type",
"skill_ultimate.desire_cost",
"skill_ultimate.description",
"skill_ultimate.levels.*",
"feats.stages"
}, ",")
-- ==============================
-- 内部函数:通过卡名获取数据
-- ==============================
local function fetchCardByName(name)
local url = API_BASE
.. "?fields=" .. FIELDS
.. "&filter[stylename][_eq]=" .. mw.uri.encode(name)
-- 发起 HTTP 请求
local ok, result = pcall(mw.http.get, url)
if not ok or not result then
return nil, "HTTP 请求失败,请检查 $wgAllowExternalReqs 是否开启"
end
-- 解析 JSON
local ok2, data = pcall(mw.text.jsonDecode, result)
if not ok2 or not data then
return nil, "JSON 解析失败"
end
if not data.data or #data.data == 0 then
return nil, "找不到卡片:" .. name
end
return data.data[1]
end
-- ==============================
-- 内部函数:安全取值(避免 nil 报错)
-- ==============================
local function safe(val, fallback)
if val ~= nil and val ~= "" then
return tostring(val)
end
return fallback or "—"
end
-- ==============================
-- 内部函数:渲染单个技能区块
-- ==============================
local function renderSkill(skill)
if not skill then return "" end
local lines = {}
table.insert(lines, "; " .. safe(skill.name))
table.insert(lines, ": 类型:" .. safe(skill.type))
-- 普通攻击有武器
if skill.weapon then
table.insert(lines, ": 武器:" .. safe(skill.weapon))
end
-- 被动有触发条件
if skill.trigger_type then
table.insert(lines, ": 触发:" .. safe(skill.trigger_type) .. " × " .. safe(skill.trigger_value))
end
-- 终结技有欲望消耗
if skill.desire_cost then
table.insert(lines, ": 欲望消耗:" .. safe(skill.desire_cost))
end
table.insert(lines, ": " .. safe(skill.description))
-- 升级数值
if skill.levels and #skill.levels > 0 then
for _, lv in ipairs(skill.levels) do
table.insert(lines, ":; 升级效果:" .. safe(lv.name))
if lv.levels then
table.insert(lines, ":: " .. table.concat(lv.levels, " / "))
end
end
end
return table.concat(lines, "\n")
end
-- ==============================
-- 内部函数:渲染觉醒区块
-- ==============================
local function renderFeats(feats)
if not feats or #feats == 0 then return "" end
local lines = {}
table.insert(lines, "=== 觉醒 ===")
for _, feat in ipairs(feats) do
if feat.stages then
for _, stage in ipairs(feat.stages) do
local stageName = stage.extra_name or ("觉醒 " .. tostring(stage.stage))
table.insert(lines, "; " .. stageName)
-- 属性加成
if stage.stat_boosts then
for _, boost in ipairs(stage.stat_boosts) do
table.insert(lines, ": " .. safe(boost.type) .. " +" .. safe(boost.value))
end
end
-- 技能效果
if stage.value then
for _, v in ipairs(stage.value) do
table.insert(lines, ": " .. safe(v.description))
end
end
end
end
end
return table.concat(lines, "\n")
end
-- ==============================
-- 对外入口:render
-- ==============================
function p.render(frame)
-- 支持 {{#invoke:CardData|render|卡名}} 或 {{#invoke:CardData|render|name=卡名}}
local name = frame.args[1] or frame.args.name
if not name or name == "" then
return '<span style="color:red">错误:请提供卡片名称,例如 {{#invoke:CardData|render|复仇童谣}}</span>'
end
name = mw.text.trim(name)
local card, err = fetchCardByName(name)
if not card then
return '<span style="color:red">错误:' .. (err or "未知错误") .. '</span>'
end
-- 开始拼装输出
local lines = {}
-- 基本信息
table.insert(lines, "== " .. card.stylename .. " ==")
table.insert(lines, "; 稀有度:" .. safe(card.rarity))
table.insert(lines, "; 角色:" .. safe(card.character and card.character.name))
table.insert(lines, "; 职业:" .. safe(card.profession and card.profession.name))
table.insert(lines, "; 欲望:" .. safe(card.desire and card.desire.name))
-- 技能
table.insert(lines, "=== 普通攻击 ===")
table.insert(lines, renderSkill(card.skill_normal_attack))
table.insert(lines, "=== 被动技能 ===")
table.insert(lines, renderSkill(card.skill_passive))
table.insert(lines, "=== 终结技 ===")
table.insert(lines, renderSkill(card.skill_ultimate))
-- 觉醒
table.insert(lines, renderFeats(card.feats))
return table.concat(lines, "\n")
end
return p