模块:Tbox
来自蒙纳多研究本部
此模块的文档可以在模块:Tbox/doc创建
-- 模块:Tbox —— 宝箱渲染层(列表 / 单箱 infobox / SMW 注解)
--
-- 用法:
-- {{#invoke:Tbox|list}} 全部 20 个宝箱(按地图分组)
-- {{#invoke:Tbox|list|map=ma1202}} 指定地图
-- {{#invoke:Tbox|list|mapName=监狱岛}} 按地图中文名
-- {{#invoke:Tbox|infobox|id=7}} 单个宝箱信息框
-- {{#invoke:Tbox|whereItem|代达罗斯}} 反向查询:某物品出自哪些宝箱(SMW)
--
-- 数据来源:模块:TboxData(硬编码快照)。
-- 待 XB1DEData 注册 FLD_tboxlist / Gimlist 后,把 TboxData 换成实时取数即可,
-- 本模块对外接口完全不变。
--
-- 地图:本期不启用。XB1DEWikiMap 目前只认 mine/collection/enemy 三种图层
-- (渲染器选择器 `.xb1map-${mode}`),宝箱图层需站长加 REST 端点后才能挂载。
local p = {}
local data = require("Module:TboxData")
-- ====== SMW 属性(需先在 wiki 上建好属性页,见《上线流程》) ======
-- 属性:Tbox编号 Number — FLD_tboxlist.__id
-- 属性:Tbox地图 Text — 地图中文名
-- 属性:Tbox地标 Text — 最近地标
-- 属性:Tbox物品 Text — 箱内物品(顿号连接,仅展示)
-- 属性:Tbox物品名 Text — 箱内物品(多值,供 #ask 反查)
-- 属性:Tbox物品数 Number — 箱内物品件数
-- 属性:Tbox坐标X Number
-- 属性:Tbox坐标Y Number
-- 属性:Tbox坐标Z Number
local seen = {} -- 同一次页面解析内防重复注解
-- 物品名 → 站内页面。存在则加链接,不存在则纯文本(避免红链)。
-- 现状:50 个物品里 36 个已有「物品:」页;宝珠/战技教学书类尚无独立页。
local function itemLink(name)
local t = mw.title.new("物品:" .. name)
if t and t.exists then
return "[[" .. t.fullText .. "|" .. name .. "]]"
end
return name
end
-- ====== SMW 注解:每个宝箱一个 subobject ======
-- 依据《SMW踩坑记录》§13:多实体必须用 subobject,不能用 #set
-- (#set 会把整页箱子的值堆进同一属性,无法回答「哪一箱有这把武器」)
local function annotate(c)
if seen[c.id] then return end
seen[c.id] = true
local smw = mw.smw
if smw == nil then return end -- SMW 不可用时静默跳过,页面照常渲染
local items = c.items or {}
local sub = {
["Tbox编号"] = c.id,
["Tbox地图"] = c.mapName or "",
["Tbox地标"] = c.landmark or "",
["Tbox坐标X"] = c.x,
["Tbox坐标Y"] = c.y,
["Tbox坐标Z"] = c.z,
["Tbox物品数"] = #items,
}
if #items > 0 then
local arr = {}
for i, n in ipairs(items) do arr[i] = n end
sub["Tbox物品名"] = arr -- 多值属性,供反查
sub["Tbox物品"] = table.concat(arr, "、")
end
smw.subobject(sub)
end
-- ====== 物品单元格 ======
local function itemCell(c)
local names = c.items or {}
if #names == 0 then return "<i>(无记录)</i>" end
local out = {}
for _, n in ipairs(names) do
table.insert(out, itemLink(n))
end
return table.concat(out, "<br>")
end
-- ====== 列表(按地图分组) ======
function p.list(frame)
local args = frame.args
local wantMap = args.map
local wantName = args.mapName
local byMap = data.byMap()
local out = {}
for _, mapId in ipairs(data.mapOrder) do
local grp = byMap[mapId]
if grp
and (wantMap == nil or wantMap == mapId)
and (wantName == nil or wantName == grp.name) then
table.insert(out, '<h3>' .. grp.name .. '</h3>')
table.insert(out, '<table class="wikitable xbtable" style="text-align:left;">')
table.insert(out, "<tr><th>最近地标</th><th>内容</th></tr>")
for _, c in ipairs(grp.list) do
annotate(c)
table.insert(out, "<tr>")
table.insert(out, "<td>" .. (c.landmark or "—") .. "</td>")
table.insert(out, "<td>" .. itemCell(c) .. "</td>")
table.insert(out, "</tr>")
end
table.insert(out, "</table>")
end
end
if #out == 0 then
return "<i>未找到匹配的宝箱。</i>"
end
return table.concat(out, "\n")
end
-- ====== 单个宝箱 infobox ======
function p.infobox(frame)
local id = tonumber(frame.args.id or frame.args[1])
local c = data.get(id)
if not c then
return "<i>未找到宝箱 #" .. tostring(id) .. "</i>"
end
annotate(c)
local out = {}
table.insert(out, '<table class="wikitable xbtable" style="text-align:left;">')
table.insert(out, '<tr><th colspan="2">宝箱 #' .. c.id .. '(' .. c.mapName .. ')</th></tr>')
table.insert(out, "<tr><th>最近地标</th><td>" .. (c.landmark or "—") ..
(c.dist and ("(约 " .. string.format("%.0f", c.dist) .. ")") or "") .. "</td></tr>")
table.insert(out, '<tr><th>坐标</th><td><code>' ..
string.format("%.1f, %.1f, %.1f", c.x, c.y, c.z) .. "</code></td></tr>")
table.insert(out, "<tr><th>内容</th><td>" .. itemCell(c) .. "</td></tr>")
table.insert(out, '<tr><th>gimID</th><td>' .. c.gimID .. "</td></tr>")
table.insert(out, "</table>")
return table.concat(out, "\n")
end
-- ====== 反向查询:某物品出自哪些宝箱 ======
-- 用法:{{#invoke:Tbox|whereItem|代达罗斯}} 或 |物品名=代达罗斯
function p.whereItem(frame)
local name = frame.args["物品名"] or frame.args[1]
if not name or name == "" then
return "<i>请指定物品名</i>"
end
local smw = mw.smw
if smw == nil then return "<i>SMW 不可用</i>" end
local res = smw.ask {
"[[Tbox物品名::" .. name .. "]]",
"?Tbox地图",
"?Tbox地标",
"?Tbox编号",
mainlabel = "宝箱",
}
if not res or #res == 0 then
return "<i>没有宝箱记录包含「" .. name .. "」。</i>"
end
local out = { '<table class="wikitable xbtable">',
"<tr><th>宝箱</th><th>地图</th><th>最近地标</th></tr>" }
for _, r in ipairs(res) do
table.insert(out, "<tr><td>" .. tostring(r[1] or "?") ..
"</td><td>" .. tostring(r["Tbox地图"] or "?") ..
"</td><td>" .. tostring(r["Tbox地标"] or "?") .. "</td></tr>")
end
table.insert(out, "</table>")
return table.concat(out, "\n")
end
return p