蒙纳多研究本部
菜单
导航
首页
最近更改
随机页面
翻译查询
乐园数据管理室
送行者的收集手册
搜索
链入页面
相关更改
特殊页面
页面信息
最近更改
帮助
登录
模块
查看“︁GemData”︁的源代码
←
模块:GemData
因为以下原因,您没有权限编辑该页面:
您请求的操作仅限属于该用户组的用户执行:
用户
您必须确认您的电子邮件地址才能编辑页面。请通过
参数设置
设置并确认您的电子邮件地址。
您可以查看和复制此页面的源代码。
-- 模块:GemData —— 宝珠数据层(唯一 xbdb 访问入口,仿 ArtsData/source 决策11 架构) -- 数据来源(全部运行时在线取,零硬编码名单): -- bdat_common.BTL_skilllist 宝珠技能定义(attach=0/1/2 归属、I~X 数值、money、rvs_caption) -- bdat_common.ITM_dropcrystallist 掉落结晶(skill1/skill2 引用 → 「真实宝珠」过滤锚点) -- 注意:row_id 越界会整页 500 且 pcall 无效(ArtsData/source 已知坑),所以本模块 -- 只对"表全量行数范围内的 id"发调用;行数上限写死为安全护栏(非数据名单)。 local p = {} local post = require("Module:RequestHelper").post local function num(v) if v == nil then return 0 end return tonumber(v) or 0 end -- ====== 安全护栏(实现细节,非游戏数据) ====== local SKILLLIST_MAX_ID = 98 -- BTL_skilllist 行数上限(超出即 500,必须前置拦截) local DROPCRYSTAL_MAX_ID = 820 -- ITM_dropcrystallist 行数上限 local cache = {} -- 基础取数(带护栏 + 记忆化) local function fetch(table, id, maxId) local n = tonumber(id) if not n or n < 1 or n > maxId then return nil end local key = table .. ":" .. n if cache[key] == nil then local ok, data = pcall(post, table, n) if not ok or type(data) ~= "table" or (data.row_id == nil and data.__id == nil) then cache[key] = false return nil end cache[key] = data end return cache[key] or nil end function p.fetchSkill(id) return fetch("bdat_common.BTL_skilllist", id, SKILLLIST_MAX_ID) end function p.fetchDropCrystal(id) return fetch("bdat_common.ITM_dropcrystallist", id, DROPCRYSTAL_MAX_ID) end -- 「真实宝珠」判定(数据驱动,无名单): -- 掉落结晶表 skill1/skill2 引用到的技能 = 游戏内真实存在的宝珠。 -- 未被引用的(力量弱化/杂质等占位、内部削弱条目)自然出局。 -- 首次调用时全表扫描 820 行 dropcrystallist 并构建引用集合(同一解析内记忆化)。 -- ⚠️ 线上 xbdb 返回的 skill1/skill2 是「内嵌完整技能对象」(含 row_id),不是裸数字 id。 -- 所以这里做两形态兼容:对象 → 取 .row_id;数字 → 直接用。 local refSet = nil function p.referencedSkills() if refSet ~= nil then return refSet end refSet = {} for id = 1, DROPCRYSTAL_MAX_ID do local dc = p.fetchDropCrystal(id) if dc then for _, k in ipairs({ "skill1", "skill2" }) do local v = dc[k] if type(v) == "table" then v = tonumber(v.row_id) -- 线上形态:内嵌对象 else v = tonumber(v) -- 防御形态:裸 id end if v and v >= 1 and v <= SKILLLIST_MAX_ID then refSet[v] = true end end end end return refSet end -- 共用宝珠列表(attach=0 且 被结晶引用 → 线上实测 13 条) -- ⚠️ 过滤口径修正(线上快照复算结论):只用「被 ITM_dropcrystallist 引用」这一条过滤, -- 不要叠加 money>0 —— money=0 的条目里有两个真实宝珠(武器·命中上升 #69、防具·填充时间缩短 #45) -- 会被误杀;而 attach=0 中被过滤掉的恰好全是 负面占位(16/32/48/64/80/96)+杂质(98)+共用版 -- 无法战斗抗性(97,防具版 #27 才是可装备的),一条不多一条不少。 -- 返回 { {id=..., data={...}}, ... } 按 id 升序 function p.sharedGems() return p.gemsByAttach(0) end -- 通用分类列表:attachValue = 0(共用) / 1(武器) / 2(防具) function p.gemsByAttach(attachValue) local refs = p.referencedSkills() local out = {} for id = 1, SKILLLIST_MAX_ID do if refs[id] then local s = p.fetchSkill(id) if s and tonumber(s.attach) == attachValue then out[#out + 1] = { id = id, data = s } end end end table.sort(out, function(a, b) return a.id < b.id end) return out end -- 单宝珠取数(含归属校验) function p.getGem(id) local s = p.fetchSkill(id) if not s then return nil end local refs = p.referencedSkills() if not refs[tonumber(id)] then return nil end return s end -- 数值单位(带不带 %)判定 —— percent_* 字段全为 0,不可用,改用 val_type: -- val_type = 1 → 固定值(力量/以太/敏捷等能力珠),不带 % -- val_type = 0 → 百分比(EXP/AP/最大HP/迷彩等),带 % -- 已知例外:#13 拔刀士气(val_type=0 但士气是 0~100 气槽的固定点数,不带 %) -- 规则经旧页面 13 条全量对齐验证(13/13);武器/防具珠上线后如发现新例外, -- 在此表追加(这是语义修正表,不是数据名单——数据本身不可靠,旧页面是锚点)。 local NO_PERCENT_EXCEPTIONS = { [13] = true, -- 拔刀士气:战斗开始时士气提升(士气为固定点数) } function p.hasPercent(data) local id = tonumber(data.row_id or data.__id) if NO_PERCENT_EXCEPTIONS[id] then return false end return num(data.val_type) == 0 end -- 数值插值:等级 r(1..10 → E..S),在 lower_X..upper_X 区间内 -- 游戏内宝珠等级 I~X 对应字段 E,D,C,B,A,S 只有 6 档锚点, -- 10 级向 6 锚点的映射采用天幻逐级值验证过的线性插值(锚点处取精确值)。 -- 锚点映射:I=E, III=D, V=C, VII=B, IX=A, X=S(偶数级取相邻锚点中点,四舍五入) local RANK_KEYS = { "E", "D", "C", "B", "A", "S" } function p.valueAtRank(data, rank) local anchors = { [1] = "E", [3] = "D", [5] = "C", [7] = "B", [9] = "A", [10] = "S" } local key = anchors[rank] if not key then -- 偶数级:取左右锚点均值 local lo = anchors[rank - 1] or "E" local hi = anchors[rank + 1] or "S" local lv = tonumber(data["lower_" .. lo] or 0) local hv = tonumber(data["lower_" .. hi] or 0) return math.floor((lv + hv) / 2 + 0.5) end return tonumber(data["lower_" .. key] or 0) end p.RANK_KEYS = RANK_KEYS p.SKILLLIST_MAX_ID = SKILLLIST_MAX_ID return p
该页面使用的模板:
模块:GemData/doc
(
查看源代码
)
返回
模块:GemData
。