立《特性》概念:局内加强物品统一命名为「特性」,两种形态收敛为枚举值 + 文档/称谓/数据层标识符统一
- 新增 design/gdd/systems/冒险循环/特性.md(概念唯一定义文档) 定义=一次冒险内角色自身得到的提升(不是持有物);作用范围、生命周期、 获取途径(战场奖励/商店·训练)、关联与边界五要素齐全;数值一律指路表不入正文 - 02-系统清单:冒险循环补行 + 命名对照表补 ADVENTURE_FEATURE - registry entities.yaml:新增 feature 概念条目(owner/referenced_by)+ adventure_table 字段名同步 - 数据层标识符 112 处换名(值零变更):BONUS_IDS→FEATURE_KINDS、bonus_token_count→feature_quota、 bonus_value→feature_value、token_*/bonus_*_flat→feature_quota_*/feature_value_* - 称谓统一 94 处:旧称「流派件/数值件/本关强化」→ 特性 + 形态修饰语(规则改写型/属性加成型) - 两张 schema 顶部加概念指路注释,代码可直接查到定义文档 - 06-待办清单:BD 分层条目现状改写 + 新增「命名统一后续」条目(relic 词族与类名对齐待实施) 未动:类名与文件名(Godot .uid/.tscn 引用需跑测试自证)、断点存档键(兼容)
This commit is contained in:
1 parent
d0a3c6bbfa
commit
5cf7f4b6ae
29 files changed
+378
-202
No files matched your search
@@ -45,6 +45,7 @@
|
||||
| `关卡节点图生成.md` | 单关节点图的逐局随机来源:图模板池、抽签与实例化(实施排队 ADR-0007 裁决后) | 设计草案·拍板点全落文 |
|
||||
| `冒险结构.md` | 整局冒险的关卡序列、失败与大奖励 | 已定稿·自旧体系迁移 |
|
||||
| `难度曲线与Boss.md` | 难度曲线、期望值带与 Boss 设计 | 已定稿·自旧体系迁移 |
|
||||
| `特性.md` | 一次冒险内角色自身得到的提升(规则改写型 / 属性加成型两种形态) | 已实现·2026-10-05 新立定义 |
|
||||
|
||||
### 跨局循环(`systems/跨局循环/`)
|
||||
|
||||
@@ -96,6 +97,7 @@
|
||||
| 冒险循环 | 关卡节点图生成 | `NODE_MAP_GENERATION` | —(新立无旧代号) |
|
||||
| 冒险循环 | 冒险结构 | `ADVENTURE_STRUCTURE` | c2 |
|
||||
| 冒险循环 | 难度曲线与Boss | `DIFFICULTY_CURVE` | c3 |
|
||||
| 冒险循环 | 特性 | `ADVENTURE_FEATURE` | —(新立无旧代号) |
|
||||
| 跨局循环 | 元进度 | `META_PROGRESS` | c4 |
|
||||
| 表现与支撑 | HUD框架 | `HUD_FRAMEWORK` | d1 |
|
||||
| 表现与支撑 | 数据配置 | `DATA_CONFIG` | d2 |
|
||||
@@ -126,3 +128,4 @@
|
||||
| v1.0 | 2026-09-27 | 节点图生成立项批(用户拍板立项——06 条目「关卡内结构随机生成」随批改状态):`systems/冒险循环/` 新建 `关卡节点图生成.md` 设计草案 v0.1(图模板/模板池/抽签三概念、三级台阶路线、MC 测量对账条款、五拍板点);文档树补行 + 命名对照表补 `NODE_MAP_GENERATION` 行 |
|
||||
| v1.1 | 2026-09-27 | 关卡画面 UX spec 建档(关卡画面 UX 批):`ux/` 表补 `level-map.md` 行——选路枢纽三停点布局、GP 常驻徽章、交互映射与 AC 成文,三项设计提案挂 06 待拍板 |
|
||||
| v1.2 | 2026-10-03 | R3 清账批(gdd_lint 分域随批):四处状态单元格日期批注迁出——敌人系统行事件见敌人系统.md 版本历史 v0.5(技能池批);元进度行见本表 v0.8;camp/shop 行=两文 v1.0 落文(2026-09-30 三裁决执行批);语义零变更 |
|
||||
| v1.3 | 2026-10-05 | 立《特性》:一次冒险内角色自身得到的提升——此前按内部分类被叫成三个名字(规则类称"流派件"、属性类称"数值件"、界面称"本关强化"),现收敛为一个对象的两种形态枚举;文档树冒险循环补行 + 命名对照表补 `ADVENTURE_FEATURE` 行 |
|
||||
+10
-4
@@ -27,17 +27,17 @@
|
||||
|
||||
#### 冒险 BD 两类加强物品获取同渠道、纯概率差(用户口径:获取途径须区分开,2026-10-04 提问登记)
|
||||
|
||||
**现状**:BD 分层口径(用户定):基础 BD(账号级,局外天赋树+同调装配)与冒险 BD(局内一次冒险的构筑)两层;冒险 BD 的加强物品两类——**流派件**(机制件,改规则、带流派标签与档位激活,构筑核心,真正改变局内强度)与**数值件**(属性加成,UI 呈现名「本关强化」,写统一加算区;账本实为冒险域、关间不清零)。现行两类**共用同一获取渠道**:三选一(奖励节点+通关)+ 商店货架 + 格面令牌同属 98 张固定配额池(普通 70/稀有 25/罕见 3),流派件只占稀有/罕见档(与数值大件混编),商店仅「货架零流派件挤掉一张普通卡」保底——获取途径与条件完全相同、仅概率不同,构筑核心的获取节奏纯看脸。
|
||||
**现状**:BD 分层口径(用户定):基础 BD(账号级,局外天赋树+同调装配)与冒险 BD(局内一次冒险的构筑)两层;冒险 BD 的加强物 = **特性**(2026-10-05 定名,定义见 [特性](systems/冒险循环/特性.md)):规则改写型(改规则、带流派标签与档位激活,构筑核心)与属性加成型(属性加成,写统一加算区;账本实为冒险域、关间不清零)两种形态。旧称「流派件 / 数值件 / 本关强化」一律作废。现行两类**共用同一获取渠道**:三选一(奖励节点+通关)+ 商店货架 + 格面令牌同属 98 张固定配额池(普通 70/稀有 25/罕见 3),规则改写型只占稀有/罕见档(与属性大件混编),商店仅「货架零规则改写型挤掉一张普通卡」保底——获取途径与条件完全相同、仅概率不同,构筑核心的获取节奏纯看脸。
|
||||
|
||||
**用户期望改动**:将两类的获取途径区分开,流派件获取节奏不依赖纯概率。已呈四备选(均未拍板):① Boss/精英击杀后流派件**专属三选一**,流派件整体退出共享池〔我方推荐:确定性最高,杀戮尖塔/以撒/哈迪斯参照系全支持,与钥石逐杀 Boss 节奏同构;代价=令牌池配额回收+商店保底改向+MC 锚换代〕;② 行为条件投放(累计玩法行为定向出件,防滚雪球工程量大);③ 计步保底(每 N 奖励面必含流派件,改动最小只缓解不根除);④ 双池分离(每面必见流派件,决策密度过强,不推荐)。
|
||||
**用户期望改动**:将两种形态的获取途径区分开(规则改写型走战场奖励、属性加成型走商店训练),规则改写型的获取节奏不依赖纯概率。已呈四备选(均未拍板):① Boss/精英击杀后规则改写型**专属三选一**,规则改写型整体退出共享池〔我方推荐:确定性最高,杀戮尖塔/以撒/哈迪斯参照系全支持,与钥石逐杀 Boss 节奏同构;代价=令牌池配额回收+商店保底改向+MC 锚换代〕;② 行为条件投放(累计玩法行为定向出件,防滚雪球工程量大);③ 计步保底(每 N 奖励面必含规则改写型,改动最小只缓解不根除);④ 双池分离(每面必见规则改写型,决策密度过强,不推荐)。
|
||||
|
||||
**归属**:[node-reward](ux/node-reward.md)(令牌池与奖励面)+ [冒险结构](systems/冒险循环/冒险结构.md)(商店货架保底);与上条「双层 BD 延期与备选内容总登记」二期件组相关但不同面。
|
||||
|
||||
**状态**:待讨论(2026-10-04 用户提问登记,后续展开)
|
||||
|
||||
#### 内部分类禁写入玩家可见面——流派件呈现三处违规待改(2026-10-04 用户立意登记)
|
||||
#### 内部分类禁写入玩家可见面——特性呈现三处违规待改(2026-10-04 用户立意登记)
|
||||
|
||||
**现状**:用户立意(方向已明确):流派/数值等内部分类**不得写进玩家可见的道具名称、介绍词或界面**——玩家可根据效果自行推断类别,游戏不得直接点破。查证实态:26 件流派件 display_name 全风味名(奥术余烬/贯穿射击/矿工的执拗等,合规,符合 2026-09-29 playnote 既有批评);**违规三处**(均系迭代 12 呈现补齐批所落,承载用户「局内奖励选了什么看不到」反馈——缺口承载需求仍成立,撤的只是分类字样):① 三选一+商店流派件卡面第二行印流派名(`battle_narrator.gd` relic_card_text,「奥术余烬 · 魔法」式);② 战斗屏 C 区列表标题「流派件」+逐流派聚合行「魔法 ×2 · 档一」(`hero_info_panel_view.gd` + `hud_presenter.gd` relic_holdings_lines);③ 关卡选择页复用同一聚合文案(`level_map_screen.gd`)。**边界**:效果摘要行(「普攻附加必中伤害」)保留——那是件本身在做什么,是玩家推断归类的依据。
|
||||
**现状**:用户立意(方向已明确):形态(规则改写型/属性加成型)等内部分类**不得写进玩家可见的名称、介绍词或界面**——玩家可根据效果自行推断类别,游戏不得直接点破。查证实态:26 项规则改写型特性的 display_name 全风味名(奥术余烬/贯穿射击/矿工的执拗等,合规,符合 2026-09-29 playnote 既有批评);**违规三处**(均系迭代 12 呈现补齐批所落,承载用户「局内奖励选了什么看不到」反馈——缺口承载需求仍成立,撤的只是分类字样):① 三选一+商店特性卡面第二行印流派名(`battle_narrator.gd` relic_card_text,「奥术余烬 · 魔法」式);② 战斗屏 C 区列表标题(现为「特性」)+逐流派聚合行「魔法 ×2 · 档一」(`hero_info_panel_view.gd` + `hud_presenter.gd` relic_holdings_lines);③ 关卡选择页复用同一聚合文案(`level_map_screen.gd`)。**边界**:效果摘要行(「普攻附加必中伤害」)保留——那是件本身在做什么,是玩家推断归类的依据。
|
||||
|
||||
**连带裁点**:档位激活(同标签 2 件档一/4 件档二)若完全不呈现,玩家只能靠悟——三路待裁:甲=纯隐藏、机制照跑(以撒套装式,最贴用户「流派是玩家挖掘出来的」原则);乙=档位达成那一刻给一次性风味反馈、不点破流派名;丙=连档位机制一起退役。
|
||||
|
||||
@@ -45,6 +45,12 @@
|
||||
|
||||
**状态**:方向已明确(禁写类别),违规改法与档位呈现三路待讨论(2026-10-04 登记,后续展开)
|
||||
|
||||
#### 特性命名统一后续——代码标识符与文件名的对齐(2026-10-05 立)
|
||||
|
||||
**现状**:概念已统一为「特性」(定义见 [特性](systems/冒险循环/特性.md))。本期完成三件——① 定义文档落位;② 称谓统一(代码注释与玩家可见文案,94 处);③ 数据层标识符统一(`adventure_table.gd` / `adventure.tres` 的常量与字段整体换到 feature_* 词族,112 处,值零变更)。**未完三件**:① 规则改写型那套的 relic 词族(RelicTable / relics.tres / relic_id / _relics)与统一词族对齐——文件名与 class_name 改名须同步 Godot `.uid` 与 `.tscn` 引用,非文本层可自证;② 运行层标识符(`_bonus_deck` / `bonus` 加算区 / `_bonus_taken` / `pick_bonus` / BonusInteractController / BonusPickOverlay)换名;③ 断点与存档键(`bonus_deck` / `bonus_taken` / `bonus_pending` / `bonus_result` / `bonus_aux_carry`)为存档兼容沿用历史名,是否随存档版本迁移一并换名待定。
|
||||
|
||||
**状态**:待实施——须在可跑冒烟的迭代批次内完成(本会话按测试执行两入口铁规零测试,改名无法自证)
|
||||
|
||||
#### 棋盘战斗键盘/手柄输入(2026-10-04 用户提问登记,排期 Beta)
|
||||
|
||||
**现状**:战斗棋盘操作现行唯一输入 = 鼠标——左键已开格 = 移动 / 未开格 = 挖掘,右键 = 封印(旗一次性承诺,无拔旗),悬停承载合法性反馈(可挖域微光 + BFS 路径点迹);全仓无 InputEventKey/JoypadButton 处理,project.godot 无自定义 InputMap 动作。**可行性已核(2026-10-04):可做**——分发接缝现成,board_view `action_requested(cell, kind)`(kind ∈ {dig, move, flag_place, flag_pull})是唯一出口,键盘/手柄作第二输入前端产出同款信号即可,规则引擎合法性校验零改动(非法目标两条路径同拦);Godot InputMap 原生支持键盘与手柄(十字键/摇杆)绑定同一动作,与鼠标并存不冲突。用户期望操作形态:十字方向移动;挖掘/封印各一独立键;方向控制选定 8 向挖掘或封印目标(斜向 = 双方向键组合)——8 向恰与现行可挖域(8 向相邻未开格)同集,十字移动与立绘 4 向既有裁决一致;键盘移动语义 = 逐格步进(现行点击 = 任意已开格 BFS 全程,逐格为等价交互变体)。连带设计点(实施批先裁):① 键盘模式需屏上光标格承载现行悬停反馈(无鼠标 hover,合法性指示改挂光标);② 键盘默认键位与手柄键位映射待定;③ 弹层界面(结算/三选一/商店/设置等)现行全鼠标,手柄全覆盖需焦点导航——本条范围 = 棋盘战斗操作,界面焦点导航是否同批待裁;④ 键位自定义是否进设置面待裁。
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
# 特性(Feature)
|
||||
|
||||
> 一次冒险之内,角色**自身得到提升**的载体。它不是包里的东西,而是角色本人的变化——这点决定了它和持有物是两类完全不同的概念,下面的「关联与边界」一节写了怎么区分。
|
||||
>
|
||||
> 同一个概念下有**两种形态**:改写规则的,和抬高属性的。它们是同一个对象的形态枚举值(`form`:规则改写型 / 属性加成型),不是两类东西。
|
||||
>
|
||||
> 状态:**已实现**(2026-10-04 双层 BD 实施批落地)。本文件是特性的唯一定义文档。
|
||||
>
|
||||
> 数值纪律:本文件只写概念、取值域与指路;每件加多少、效果是什么一律不进正文,事实源是 `game/data/tables/relics.tres` 与 `game/data/tables/adventure.tres`。
|
||||
|
||||
## 设计目的
|
||||
|
||||
一次冒险要走三关,如果走完时角色和开局毫无区别,中途的每一次取舍就都不算数了。特性就是那个把"这一局玩成了什么样"落下来的东西:让玩家在冒险过程中不断变强,且每一局变强的方向不同。
|
||||
|
||||
它同时要和跨冒险的成长隔开:永久保留的东西是[魔法道具](../排雷循环/魔法道具.md)(带在身上的物品)与[元进度](../跨局循环/元进度.md)(账号级的树),特性只在当局存在,冒险收束即清零——它不是"你的存档变强了",而是"这一次下矿的你变强了"。
|
||||
|
||||
**为什么定为"自身提升"而不是"获得物品"**:一旦把它当成捡到的东西,就和魔法道具(持有物)在玩家心里混成一团——而两者的接入方式、生命周期、获取条件都不同。定为自身的提升,边界一句话就能说清:**带在自己身上的是特性,拿在手里的是魔法道具**。
|
||||
|
||||
## 系统范围
|
||||
|
||||
| 负责 | 不负责 |
|
||||
|---|---|
|
||||
| 特性的定义与形态枚举 | 每件效果怎么接入结算——归挂点所属文档([战斗结算](../战斗循环/战斗结算.md)、[行动经济](../排雷循环/行动经济.md)、[地形变异](../排雷循环/地形变异.md)) |
|
||||
| 生命周期边界:何时出现、何时生效、何时清零 | 卡面排版与界面呈现细则——见 [HUD框架](../表现与支撑/HUD框架.md) |
|
||||
| 获取途径的口径与约束 | 魔法道具与元进度——归上表两份文档 |
|
||||
| 与相邻概念的边界 | 格面资源、关卡节点、商店本身的规则——归各自所属文档 |
|
||||
|
||||
## 在核心循环中的位置
|
||||
|
||||
```
|
||||
【关内】排雷推理 → 战斗结算 → 通关 ──┐
|
||||
├─→ 得到一项特性 ─→ 后续关卡带着它继续
|
||||
奖励节点・商店 ┘
|
||||
```
|
||||
|
||||
特性处在「一次冒险」这一层:它不是一场战斗里的临时状态,也不跨冒险留存。上游是两个获取口,下游是之后所有关卡的排雷与结算——拿到了,下一关就开始生效。
|
||||
|
||||
## 核心规则
|
||||
|
||||
### 1. 形态枚举(form)
|
||||
|
||||
特性只有一个名词;需要区分时才描述它的形态,不给形态另起名字。
|
||||
|
||||
| 形态 | 它改的是什么 | 落在哪里 | 事实源 |
|
||||
|---|---|---|---|
|
||||
| `rule` 规则改写型 | 改规则本身:在结算管线的某个挂点上给自己加一条规则;同一标签的持有件数达到阈值时发生质变 | 各结算段挂点;标签与档位由求值服务统一算 | `relics.tres`(逐项定义) |
|
||||
| `stat` 属性加成型 | 改数值:把自己某项属性抬高,直接改写角色的基础数字 | 冒险加算区(攻击 / 生命上限 / 护甲 / 行动点四轴)、钱包与即时恢复 | `adventure.tres`(配额与值) |
|
||||
|
||||
两种形态的共性:都在当局获得、当局携带、当局失效;都不写账号进度——出现与否由抽取决定,玩家的账号强弱不影响它出现在哪一局。
|
||||
|
||||
**为什么是同一个对象的两种枚举而不是两个东西**:它们共用一份获取流程、一份持有集、一份生命周期。分成两个名字只会让读者以为有两套系统,而实际上代码里只有一个持有集。
|
||||
|
||||
### 2. 作用对象与范围
|
||||
|
||||
- **作用对象**:角色本人,以及角色参与的结算过程。特性不改敌人、不改棋盘生成、不改关卡内容。
|
||||
- **时间范围**:整局冒险。两种形态都自获得起对本局剩余所有关卡生效;属性加成型写入加算区后,关与关之间不清零。
|
||||
- **归属范围**:不进账号永久进度,不带到下一次冒险。
|
||||
|
||||
### 3. 生命周期
|
||||
|
||||
```
|
||||
未获得 → 进入候选池 → 作为候选出现 → 选定 → 持有 → 生效 →(冒险收束)清零
|
||||
↑ ↓
|
||||
断点恢复 持有集持续累积
|
||||
```
|
||||
|
||||
| 阶段 | 说明 |
|
||||
|---|---|
|
||||
| 候选池构建 | 冒险开局时一次建成。两种形态的候选**现同处一个令牌池**:属性加成型按配额铺开,规则改写型按定义表的有效行铺开。 |
|
||||
| 出现 | 玩家在两个获取口之一看到若干候选(三选一的形式),看不到整个池。 |
|
||||
| 选定 | 玩家选定一项后,它从池中剔除,此后任何获取口都不会再见。 |
|
||||
| 持有与生效 | 进入持有集后立即生效,跨关携带。规则改写型按同一标签的持有项数决定处于哪一档。 |
|
||||
| 清零 | 冒险以任一结局收束时整集清空;下次开局重建。 |
|
||||
| 断点恢复 | 进行中的冒险把持有集与剩余候选池一并写入断点,续玩后恢复到同一状态(断点里的键名沿用历史形态,不随本次改名变动)。 |
|
||||
|
||||
### 4. 获取途径
|
||||
|
||||
| 获取口 | 说明 | 目标渠道分工(尚未实施) |
|
||||
|---|---|---|
|
||||
| 战场奖励 | 每关通关给一次三选一(最终关不给——提升只对后续关卡有意义,最终关没有后续);关卡节点图上的奖励节点同样给一次三选一,与之共用同一个候选池。 | 规则改写型今后主要从这里出 |
|
||||
| 商店 | 花局内金币购买在架的特性;同一种至多一张,买走即从在架令牌移除。 | 属性加成型今后主要从这里出,口径是**训练** |
|
||||
|
||||
**关于商店口径的说明**:商店这一侧走的叙事是「**训练**」——花代价向某位师父学习、借某种卷轴修炼、或把战斗攒下的钱换成一身本领。它不是买一个东西回来,而是把钱换成自己的本领,所以落到命名空间上和奖励那一侧完全相同:都是往同一个持有集里加一项特性。
|
||||
|
||||
**在册事项**:现行两个获取口完全共用同一个候选池,两种形态出现条件一样、只有出现概率不同。用户已决定把两种形态按渠道分开(规则改写型走战场奖励,属性加成型走商店训练),四个备选方案与执行批次登记在 [06-待办清单](../../06-待办清单.md) 的 BD 分层条目下,本文件不复制。**本文件 4 节表格里的渠道分工写的是目标状态,尚未实施。**
|
||||
|
||||
### 5. 关联与边界
|
||||
|
||||
| 相邻概念 | 关系(只写关系,不写对方的规则) |
|
||||
|---|---|
|
||||
| [魔法道具](../排雷循环/魔法道具.md) | 最需要分清的一对:**魔法道具是拿在手里的物品,特性是角色自身的变化**。两者互不相通——特性永不进同调位,魔法道具永不进当局随机渠道。魔法道具跨冒险保留,特性当局清零。 |
|
||||
| [元进度](../跨局循环/元进度.md)(树) | 树管账号永久的规则与容量,特性管当局构筑,两层互不代替。 |
|
||||
| [战斗结算](../战斗循环/战斗结算.md) | 规则改写型的挂点位于结算管线的各段;挂点清单与语义归结算文档。 |
|
||||
| [行动经济](../排雷循环/行动经济.md)、[地形变异](../排雷循环/地形变异.md) | 部分挂点落在行动点结转与地形处理上,语义归各自文档。 |
|
||||
| [地图战斗资源](../战斗循环/地图战斗资源.md)(格面资源) | 无关:格面资源是单格的一次性产出,不进持有集。 |
|
||||
| [关卡节点地图](关卡节点地图.md)、商店 | 是获取口的载体,不是特性的属性。 |
|
||||
| [存档序列化](../表现与支撑/存档序列化.md) | 断点负载记录持有集与剩余候选池;键名与版本迁移策略归存档文档。 |
|
||||
|
||||
## 依赖与输出
|
||||
|
||||
| 类型 | 内容 |
|
||||
|---|---|
|
||||
| 依赖(概念) | 角色、结算管线、行动点、地形、关卡节点地图、局内金币钱包 |
|
||||
| 依赖(数据) | `relics.tres`(规则改写型定义行)、`adventure.tres`(属性加成型配额与值)、`shop.tres`(货架取舍) |
|
||||
| 输出(对外) | 持有集、生效中的形态投影、剩余候选池、档位求值结果 |
|
||||
| 明确边界 | 不写账号进度、不改敌人与关卡内容、不承载具体数值 |
|
||||
|
||||
## P0 最小闭环 / P1・P2 后置
|
||||
|
||||
- **P0(已实现)**:两种形态可定义 → 进入候选池 → 在两个获取口之一被选中 → 当局生效 → 收束清零。
|
||||
- **P1 后置**:两种形态按渠道分开(见第 4 节的在册事项);两项合成高阶项;同一标签收集到四项以上的后期表达。
|
||||
- **P2 后置**:商店里的攻击类型转换服务;喂雷流派是否保留(尚未拍板,登记在 [06-待办清单](../../06-待办清单.md))。
|
||||
|
||||
## 调参表
|
||||
|
||||
数值所有权归 [难度曲线与Boss](难度曲线与Boss.md);本文件只列参数与取值域,**不列现行值**。
|
||||
|
||||
| 参数 | 取值域 | 事实源 |
|
||||
|---|---|---|
|
||||
| 规则改写型定义行(标识 / 显示名 / 稀有度 / 标签 / 挂点 / 效果字典) | 各字段封闭枚举,行键白名单封闭 | `game/data/tables/relics.tres` |
|
||||
| 属性加成型种类 | 封闭词表:攻击 / 生命上限 / 护甲 / 金币 / 行动点 / 恢复 | `game/data/schemas/adventure_table.gd` |
|
||||
| 属性加成型稀有度档位 | 封闭三档(普通 / 稀有 / 罕见);三档配额是结构锚,改总量须重新拍板而非调参 | 同上 |
|
||||
| 各形态种类 × 档位的配额与值 | 整数 | `game/data/tables/adventure.tres` |
|
||||
| 一次三选一的候选展示数 | [1,6] | 同上 |
|
||||
|
||||
## 验收标准
|
||||
|
||||
1. 两种形态走同一套获取流程,代码里只有一个表示"已持有特性"的集合。
|
||||
2. 一次冒险内获得的特性在之后任何关卡都生效;开新冒险后持有集为空。
|
||||
3. 一项被选定的特性不再出现在任何后续获取口。
|
||||
4. 每个标签至少有一项挂在排雷侧的结算触发点上(防止规则改写型沦为纯战斗数值)。
|
||||
5. 玩家可见的文案不出现形态名与内部分类标签——只写效果,归类让玩家自己推断。
|
||||
6. 文档与代码里提到它时只有"特性"这一个名字;需要区分形态时用"规则改写型/属性加成型"描述,不得另造称呼。
|
||||
|
||||
## 待办
|
||||
|
||||
全部待办单点登记于 [06-待办清单](../../06-待办清单.md)(BD 分层条目、呈现三处待改条目),本节不复制。
|
||||
|
||||
## 版本历史
|
||||
|
||||
| 版本 | 日期 | 变更 |
|
||||
|---|---|---|
|
||||
| v1.0 | 2026-10-05 | 首次为本概念立定义文档。此前它按内部分类被叫成三个名字,各处互相冲突的定义以本文档为准:统一名词"特性",把原先分开称呼的两类收敛为形态枚举;把性质定为「角色自身得到提升」而非「获得物品」,以此与魔法道具(持有物)划清。 |
|
||||
@@ -216,7 +216,7 @@ HUD框架站在玩家与全部玩法系统之间:挖掘期它是输入的翻
|
||||
| [地图战斗资源](../战斗循环/地图战斗资源.md) | 已开格的奖励身份常读;未开格类型微光(英雄周围 8 格内的未开格显示资源类型——概念定义见本篇「未开格类型微光」节) |
|
||||
| [魔法道具](../排雷循环/魔法道具.md) | 库存条常读;使用交互与目标拾取;板级叠加层信息呈现 |
|
||||
| [棋盘生成](../排雷循环/棋盘生成.md) | 零合法板的诚实告知(数据面经战斗结算上抛,本系统只管提示形态) |
|
||||
| [地形变异](../排雷循环/地形变异.md) | 全局作用域型三层预告(2026-10-04 首发批——语义正主=地形变异 §全局作用域型):①开战横幅一行(板级变异非空时显示;减动效=静态驻留,轮横幅先例同款双态)②HUD 常驻角标(C 区战斗全程可见防中局遗忘,空态整节隐藏=流派件段先例;摆位 provisional)③帮助手册一行(零交互教学,承载=玩法帮助文案块);数据面经呈现快照 board_variants 投影(核心→呈现唯一读取面),普通图三层恒空态零打扰 |
|
||||
| [地形变异](../排雷循环/地形变异.md) | 全局作用域型三层预告(2026-10-04 首发批——语义正主=地形变异 §全局作用域型):①开战横幅一行(板级变异非空时显示;减动效=静态驻留,轮横幅先例同款双态)②HUD 常驻角标(C 区战斗全程可见防中局遗忘,空态整节隐藏=特性段先例;摆位 provisional)③帮助手册一行(零交互教学,承载=玩法帮助文案块);数据面经呈现快照 board_variants 投影(核心→呈现唯一读取面),普通图三层恒空态零打扰 |
|
||||
|
||||
## P0 最小闭环
|
||||
|
||||
@@ -300,6 +300,6 @@ HUD框架站在玩家与全部玩法系统之间:挖掘期它是输入的翻
|
||||
| v0.10 | 2026-09-26 | 渲染技术注记(战斗舞台 Node2D 迁移批 Phase B,代码实装同批;上位裁决 ADR-0006):B 区战斗舞台 Node2D 化——BattleStageView 内部由 PanelContainer+Control 站桩改为 Control 壳 + SubViewportContainer + SubViewport + Node2D 世界(StageWorld/StandeeBody),类名/setter 面/公共方法契约不变、调用点零改造;状态图标行与悬停 tooltip 保留 Control 载体挂壳层(伴随件);C6 字体注入挂点复用(set_world_font);三区布局与性能预算(同屏 draw calls < 200)不变;占位表现等价平移(时序常量逐字对照——等价证明=git 提交 7f24b64,文件已按生命周期条款退役) |
|
||||
| v0.11 | 2026-09-27 | 关卡画面 UX spec 建档([level-map](../../ux/level-map.md),关卡画面 UX 批——用户拍板立项):义务清单「关卡节点地图」行挂屏级 spec 指针;屏级权威行与不负责表改按屏分治口径(战斗屏 = battle.md / 关卡画面 = level-map.md)。文档面零机制改动 |
|
||||
| v0.12 | 2026-09-30 | **未开格类型微光概念收口批(用户裁决落位)**:新增「未开格类型微光」节=全项目唯一正主定义(五要素——作用对象=英雄周围 8 格内的未开格〔与可挖域同圈〕/信息内容=只类型不泄雷安/生命周期=入圈亮出圈灭开格灭/关联边界/实装状态=契约定稿〔样张 v2〕游戏内待实施批);核心规则章六节改七节;呈现义务来源清单「地图战斗资源」行补微光指路;验收标准补微光呈现线。背景:该概念此前只活在 06 登记与 art-bible 复述,「常显/全部未开格」无范围表述酿成理解事故(2026-09-30 用户纠正口径),本批落位正主、他文只许指路 |
|
||||
| v0.13 | 2026-10-04 | **地形变异三层预告义务批(全局作用域变异首发批——迭代 14 ③号卡,代码同批)**:呈现义务来源清单补「地形变异」行(开战横幅一行〔减动效=静态驻留,轮横幅先例同款双态〕+ C 区常驻角标〔空态整节隐藏=流派件段先例,摆位 provisional〕+ 帮助手册一行〔零交互教学〕);验收标准补三层预告线(普通图恒空态零打扰);数据面走呈现快照 board_variants 投影(核心→呈现唯一读取面)。语义正主=地形变异.md §全局作用域型,本文只锁呈现承载 |
|
||||
| v0.13 | 2026-10-04 | **地形变异三层预告义务批(全局作用域变异首发批——迭代 14 ③号卡,代码同批)**:呈现义务来源清单补「地形变异」行(开战横幅一行〔减动效=静态驻留,轮横幅先例同款双态〕+ C 区常驻角标〔空态整节隐藏=特性段先例,摆位 provisional〕+ 帮助手册一行〔零交互教学〕);验收标准补三层预告线(普通图恒空态零打扰);数据面走呈现快照 board_variants 投影(核心→呈现唯一读取面)。语义正主=地形变异.md §全局作用域型,本文只锁呈现承载 |
|
||||
| v0.14 | 2026-10-03 | **视野迷雾实施批落籍注记(迭代 11 第④批)**:迷雾节补「实施状态」注记(四裁决逐条对账:纯呈现两态逐位一致/暗淡记忆态灰显可读/LIGHT_RADIUS=8 参数化〔提灯 +2 插值位预留未接〕/类型微光仍贴身 8 邻格);实装状态行「待实施批」改「已实装」;验收标准迷雾行去「待实施批落地后验收」括注转正式验收。机制定义零改动(定义一句话/作用范围/生命周期/关联边界/配套拍板全段原样);黑暗区域渲染规格落 art-bible §6.5(v3.5) |
|
||||
| v0.13 | 2026-09-30 | **视野迷雾概念落位批(用户拍板立项)**:新增「视野迷雾」节=正主定义(菱形灯光区+黑暗边界;区外已开格=暗淡记忆态灰显可读、区外未开格=全黑;灯光半径起步=微光环 8 格同圈;纯呈现层,与已退役雾格无关);验收标准补迷雾线;配套拍板随节登记(魔法提灯灯甲外扩 +2 格、类型微光不随视野扩、初始展开收窄后置 Alpha 差异化批)。实施待主线编卡 |
|
||||
@@ -105,7 +105,7 @@
|
||||
- 攻击值 + 修正来源角标(战斗在消费、且站桩上无展示)
|
||||
- 护甲 AC(2026-09-26 二轮拍板补入——我方 AC 的唯一展示面;掷点判定轴,受击侧可读性)
|
||||
- 魔法道具槽(**已实装**:四槽两步交互,详见 [node-reward.md](node-reward.md)——随身战斗用道具的唯一展示面)
|
||||
- 本关强化列表(**预留**——锻造/大奖励/关卡奖励节点获得的属性提升;与战斗内状态效果分区呈现,防「战斗结束被清」误读)
|
||||
- 特性列表(**预留**——锻造/大奖励/关卡奖励节点获得的属性提升;与战斗内状态效果分区呈现,防「战斗结束被清」误读)
|
||||
- **D 区扫雷图 · AP 条**
|
||||
- AP 点阵 + 停手按钮(现行)
|
||||
- **RAP 读数(点阵+数字)**——自 C 区迁入,置于弃图刷新按钮旁(2026-09-26 拍板:RAP 唯一消费口 = 弃图刷新,资源数字贴消费按钮)
|
||||
@@ -120,7 +120,7 @@
|
||||
| 区 | 位置与尺寸 | 内容 |
|
||||
|---|---|---|
|
||||
| **B 战斗画面** | 全宽 × 252px | 主角站桩立绘(左)+ 兑现演出区(中)+ 敌人站桩立绘 ×1–3(右)——**全站桩形态(2026-09-20 用户拍板,敌人卡形态待办裁决收口):主角与敌人均为无框立绘+底座,零卡片**;主角与敌人站桩 = **HP 与状态效果的唯一展示面(2026-09-26 信息归属拍板)**;底部结算明细带(24px 摘要 / 结算期 84px 实时流);顶部中央轮次·阶段指示 |
|
||||
| **C 角色信息** | 左下 240px × 548px | 攻击值(含修正显示)、护甲 AC;魔法道具槽(预留)、本关强化列表(预留)——HP 条/RAP 池/状态效果槽/立绘占位/钱包行退役(2026-09-26 信息归属拍板:HP 与状态唯一展示面 = B 区站桩;RAP 迁 D 区 AP 条;GP/钥石迁出战斗屏) |
|
||||
| **C 角色信息** | 左下 240px × 548px | 攻击值(含修正显示)、护甲 AC;魔法道具槽(预留)、特性列表(预留)——HP 条/RAP 池/状态效果槽/立绘占位/钱包行退役(2026-09-26 信息归属拍板:HP 与状态唯一展示面 = B 区站桩;RAP 迁 D 区 AP 条;GP/钥石迁出战斗屏) |
|
||||
| **D 扫雷图** | 中下 ~1036px × 548px(原右下面板删除后横向加宽,吸收其宽度) | 顶部 AP 条(44px:左——AP 点阵 + 停手按钮;中——RAP 点阵+数字〔自 C 区迁入,贴弃图刷新按钮,2026-09-26 拍板〕;右——图例按钮 + 弃图刷新按钮〔雷图右上角,2026-09-12 拍板〕);棋盘主体(居中,格 36–45px 见方);toast 槽(上缘内侧) |
|
||||
|
||||
> 布局为 B/C/D 三区——关卡进度条不在战斗屏(节点链进度常驻关卡画面,见 Navigation Position;字母不重编沿用 B/C/D)。
|
||||
@@ -147,7 +147,7 @@
|
||||
| B | 结算明细回看 | 模态 overlay | 完整流水逐行(现行 9 类行协议;未生效类行聚合计数) | 关闭 | battle_log_view.gd 改造 |
|
||||
| C | 攻击数据框 | 直角细线数据框 | 攻击值 + 修正来源角标 + 护甲 AC(AC 二轮拍板 2026-09-26 补入——我方 AC 唯一展示面;原「HP/攻击/RAP 显示」——HP 与 RAP 随信息归属拍板迁出本组件) | 只读 | HUDView 拆分 |
|
||||
| C | 魔法道具槽(已实装:四槽两步交互,详见 [node-reward.md](node-reward.md)) | 图标槽 ×4 | 随身战斗用道具的唯一展示面;库存已随迭代 7 落地(C 区四槽+关卡域库存),清库反馈呈现待批 | 悬停 tooltip(道具语义) | 新建(随魔法道具批,已落地) |
|
||||
| C | 本关强化列表(预留) | 列表/图标行 | 锻造/大奖励/关卡奖励节点获得的属性提升——中循环数据,因改变战斗数学且无其他展示面准入战斗屏;与战斗内状态效果(B 区站桩)分区,防「战斗结束被清」误读 | 只读 | 新建 |
|
||||
| C | 特性列表(预留) | 列表/图标行 | 锻造/大奖励/关卡奖励节点获得的属性提升——中循环数据,因改变战斗数学且无其他展示面准入战斗屏;与战斗内状态效果(B 区站桩)分区,防「战斗结束被清」误读 | 只读 | 新建 |
|
||||
| D | AP 条 | 点阵 + 按钮组 | 本轮 AP 点阵、停手按钮(左)、**RAP 点阵+数字(自 C 区迁入 2026-09-26——RAP 唯一消费口 = 弃图刷新,资源数字贴消费按钮;RAP 清零可见反馈〔行动经济〕载体随迁)**、弃图刷新按钮(右端·雷图右上角;RAP−8 · 本轮剩 N 次——上限 2 次已随行动经济 2026-09-12 修订生效) | 点击提交意图 | HUDView 拆分 |
|
||||
| D | BoardView | 网格 | 棋盘全部格态 + 小人 + 旗 + 变异纹带 + 奖励身份 icon(已开格;绘制优先级 数字>小人>旗>奖励徽章>变异纹带>底色——徽章不进数字区,样张验收项) | 左/右键意图提交 | ✅ board_view.gd 迁移 |
|
||||
| D | 悬停预承诺光标 | 光标态 | 移动/挖/旗三语义光标 + 目标格边框高亮 | 自动 | 新建(排雷玩法×6③) |
|
||||
@@ -204,7 +204,7 @@
|
||||
│ │ 魔法道具槽(预留) │ │ │ │AP不足·剩0点 │ 12 12 1 ░ 2 ▓▓ ▓▓ │ │
|
||||
│ │ ◇ ◇ ◇ ◇ │ │ │ └──────────────────┘ 12 █ 1 1 2 ▓▓ ▓▓ │ │
|
||||
│ ├──────────────────┤ │ │ 1 2 2 🚩 █ 2 1 1 ▓▓ 👫 1 1 ░ │ │
|
||||
│ │ 本关强化(预留) │ │ │ ░ 1 ▓▓ 👫 1 1 ░ ▓▓ 1 1 ░ ░ 2 │ │
|
||||
│ │ 特性列表(预留) │ │ │ ░ 1 ▓▓ 👫 1 1 ░ ▓▓ 1 1 ░ ░ 2 │ │
|
||||
│ │ 锻造+2攻 │ │ │ ▓▓ 1 1 ░ ░ 2 ▓▓ │ │
|
||||
│ │ (空态=隐藏) │ │ │ ( █=可挖域微光 👫=小人) │ │
|
||||
│ └──────────────────┘ │ └─────────────────────────────────────────────────┘ │
|
||||
@@ -440,7 +440,7 @@
|
||||
| 2026-09-23 | 实现注记(棋盘 Node2D 迁移批 Phase A,代码实装同批;上位裁决 ADR-0006):棋盘渲染 Node2D 化(BoardView = Control 壳 + SubViewportContainer + SubViewport + Node2D 世界,信号/click_cell/_cells 契约保持,新增 push_input 端到端输入探针);格尺寸公式锚点不变(set_cell_area = floor((min(宽,高) − 预留 − (N−1)×格间距) / N) 单点可调),布局与交互语义零改动 |
|
||||
| 2026-09-26 | 实现注记(战斗舞台 Node2D 迁移批 Phase B,代码实装同批;上位裁决 ADR-0006):B 区战斗画面 Node2D 化(BattleStageView = Control 壳 + SubViewportContainer + SubViewport + Node2D 世界,站桩本体 StandeeBody 世界精灵;set_enemies/clear_enemies/on_step_row_fx/gray_all_enemies 等 setter 面签名保持,弹道落点锚点=壳层口径 world_to_shell 单点);状态图标行与悬停 tooltip 保留 Control 载体挂壳层;三区布局尺寸零改动(B 区外框 252px 逐位) |
|
||||
| 2026-09-26 | **封印紫批**(用户拍板):插旗呈现色 旗朱 #C63D22 → 封印紫 #7C3AA8(色相 ≈267°,避开禁入带)——旗字形/已承诺封印框/旗化暴击弹道随批换色;拒绝边框闪语义归危险红;Boss 节点描边归紫赤本色。修订记录历史行旗朱字样系当时口径留痕不改 |
|
||||
| 2026-09-26 | **战斗屏信息归属批(用户 2026-09-26 三轮纠偏后拍板;代码实装另批——hero_info_panel_view.gd / hud_presenter.gd 改造 + 探针断言迁移,登记待办)**:立两条信息归属原则并全屏贯行——①循环口径原则(战斗屏只展小循环内被消费、影响当下决策的数据;中/大循环资源不得入侵)②单一展示面原则(同一信息全屏唯一展示面;单位本体已承载的信息数据框不重复;资源数字贴唯一消费口)。随拍板落地:① B 区站桩 = HP 与状态效果唯一展示面——C 区 HP 条/HP 文字/立绘占位/状态效果槽×4 退役(重复展示;证据链 = hud_presenter.gd 同一 s.hero.hp/s.hero_effects 双投喂 B/C 两区);② RAP 读数(点阵+数字)迁 D 区 AP 条、置弃图刷新按钮旁(RAP 唯一消费口 = 弃图刷新——就近原则);③ C 区状态槽悬停 tooltip 职责并入 B 区站桩状态小图标;④ GP(中循环)/钥石(大循环)迁出战斗屏,去向挂 OQ14;⑤ C 区改「攻击数据框 + 魔法道具槽(预留)+ 本关强化列表(预留)」——预留区来自魔法道具与关卡内属性提升的既有立项;⑥ 空态/清零反馈/悬停交互/AC/§13 义务表载体同步改写。**批内遗留两项待拍板(OQ13/14)**:护甲 AC 是否补入 C 区数据框;GP/钥石去向 |
|
||||
| 2026-09-26 | **战斗屏信息归属批(用户 2026-09-26 三轮纠偏后拍板;代码实装另批——hero_info_panel_view.gd / hud_presenter.gd 改造 + 探针断言迁移,登记待办)**:立两条信息归属原则并全屏贯行——①循环口径原则(战斗屏只展小循环内被消费、影响当下决策的数据;中/大循环资源不得入侵)②单一展示面原则(同一信息全屏唯一展示面;单位本体已承载的信息数据框不重复;资源数字贴唯一消费口)。随拍板落地:① B 区站桩 = HP 与状态效果唯一展示面——C 区 HP 条/HP 文字/立绘占位/状态效果槽×4 退役(重复展示;证据链 = hud_presenter.gd 同一 s.hero.hp/s.hero_effects 双投喂 B/C 两区);② RAP 读数(点阵+数字)迁 D 区 AP 条、置弃图刷新按钮旁(RAP 唯一消费口 = 弃图刷新——就近原则);③ C 区状态槽悬停 tooltip 职责并入 B 区站桩状态小图标;④ GP(中循环)/钥石(大循环)迁出战斗屏,去向挂 OQ14;⑤ C 区改「攻击数据框 + 魔法道具槽(预留)+ 特性列表(预留)」——预留区来自魔法道具与关卡内属性提升的既有立项;⑥ 空态/清零反馈/悬停交互/AC/§13 义务表载体同步改写。**批内遗留两项待拍板(OQ13/14)**:护甲 AC 是否补入 C 区数据框;GP/钥石去向 |
|
||||
| 2026-09-26 | **信息归属二轮拍板(用户 2026-09-26,OQ13/14 收口)**:① 我方护甲 AC 补入 C 区攻击数据框(唯一展示面——布局表/组件清单/线框图同步);② GP/钥石去向定案:GP = 关卡画面常驻总量 + 战斗结算画面总量+增量,钥石 = 结算画面 + 营地(具体呈现归对应 UX spec 批次);③ 敌方 AC 展示面挂起——用户口径「敌方 AC 无任何展示」与现行代码冲突(standee_view.gd 底库名字行渲染「名字·护甲·AC%d」,系敌人技能池批克制对策可读性义务),证据链已呈报待终裁,本 spec 暂不改敌人站桩行 |
|
||||
| 2026-09-26 | **敌方 AC 展示终裁收口(用户 2026-09-26 终裁)**:敌方 AC 数值全屏退役(任何区不直接展示)、护甲类型改图标方式展示(形状+色相双通道,终稿图标资产归美术批)、敌人站桩底座下名字行退回纯名字+护甲类型图标;旧「克制对策可读性义务」降级承载——类型保留、数值退役。终裁理由(用户口径):HP 信息已足够,攻防数值不直接写上;护甲类型图标保留克制对策可读性。同步改写:信息归属树敌人站桩行、Component Inventory 敌人站桩立绘行、OQ13。**代码实装说明**:`standee_view.gd` 改造(站桩名字行去 AC 数值 + 护甲类型图标化)由并行代码批执行,本批只做文档同步 |
|
||||
| 2026-09-27 | **UX 文档欠账处置批(用户四项拍板:player-journey 不建 / accessibility 不另立改指 HUD框架 / node-reward 改挂魔法道具内容重定批 / level-clear 建档 design/gdd/ux/level-clear.md)**:① 删 §Player Context ⚠️ player-journey 未建注记,OQ1 改收口注记;② §Accessibility 头、§Transitions 减动效行、OQ2 改指 HUD框架「可访问性基线」节 + 设置与本地化待设计清单 #1(tools/doc_link_known.txt 欠账行随之清空);③ 导航残留修正——§Navigation Position 图胜利分支、§Entry/Exit 离开表、§Interaction Map 胜利 overlay 行改按现行代码实态(胜利后返回关卡画面选路;节点覆盖层 = 关卡画面域、落地奖励/恢复节点时开出;胜利/失败 overlay 组件锚 battle_end_overlay.gd)——原「胜利 → 节点奖励/恢复覆盖层」系停点前移批前残留;④ OQ3 过期陈述更正(interaction-patterns.md 2026-09-12 已建成)、OQ8 改收口注记。本批只动文档面,代码零改动 |
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
|
||||
**布局决策 3 —— 放弃冒险二次确认(2026-09-27 拍板)**:放弃 = 整局冒险终结,不可逆(pattern 7 破坏性确认)。首击转入确认态(按钮文案变「再点一次确认放弃——不可逆」,危险红边框脉冲约 3 秒,超时回落),二击才提交。代价语义(已获大奖励保留、同失败结算)常驻按钮文案。
|
||||
|
||||
**布局决策 4 —— 底部状态栏(2026-09-27 拍板,原提案为顶栏 HP 读数)**:底栏作为状态展示——生命、属性、本关已选加成三项常读;顶栏保持关卡名 + GP 两件。单一展示面注记:与 [battle.md](battle.md) C 区「本关强化列表(预留)」为不同屏的不同展示面——两屏循环口径各自独立(选路规划消费 vs 战斗内决策消费),不构成同屏重复。
|
||||
**布局决策 4 —— 底部状态栏(2026-09-27 拍板,原提案为顶栏 HP 读数)**:底栏作为状态展示——生命、属性、本关已选加成三项常读;顶栏保持关卡名 + GP 两件。单一展示面注记:与 [battle.md](battle.md) C 区「特性列表(预留)」为不同屏的不同展示面——两屏循环口径各自独立(选路规划消费 vs 战斗内决策消费),不构成同屏重复。
|
||||
|
||||
### ASCII Wireframe
|
||||
|
||||
|
||||
@@ -574,6 +574,20 @@ entities:
|
||||
mvp_content: L1 全行(切片转正——7 节点链〔单链特例,合法图形态〕、rest_heal_pct=30);L2 全行已落地(2026-09-17 分支节点图批——首张分支图:9 节点〔入口 0 → 中间三层 2/3/2 → Boss 8〕、真实岔路 4 处、奖励点+恢复点各 1、战斗节点 6 + Boss;行值 provisional 归 难度曲线与Boss v0.7;首页直入口已退役〔2026-09-23 用户拍板〕);**L3 全行已落地(2026-09-20 第三关内容批——「第三层 · 灰矮人矿城」:九节点图复用 L2 同模板〔6 战 + Boss + 奖励 + 恢复、真实岔路 4 处〕,行值全 provisional 归 难度曲线与Boss;测试直入口已退役〔2026-09-23〕)**;2026-09-20 GP+商店房批 rewiring:L2/L3 图版 Boss 重编号 8→9、各新增 (8, shop, next[9]) 商店房节点(Boss 前一位必经位),L1 零改动,图合法性六检零新增——必经位由冒烟断言承载;**2026-09-21 冒险结构实现批:三关正式序列生效**(首页「开始冒险」= L1→L2→L3 连探,AdventureRunner 编排——大奖励/生命账本/GP 冒险账本/主种子归冒险结构层,冒烟断言在案)**
|
||||
referenced_by: [冒险结构, 关卡节点地图, 难度曲线与Boss, 棋盘生成, 数据配置]
|
||||
|
||||
- name: feature
|
||||
type: concept
|
||||
owner: design/gdd/systems/冒险循环/特性.md
|
||||
attributes:
|
||||
definition: 一次冒险之内角色自身得到的提升。它不是持有物——带在自己身上的是特性,拿在手里的是魔法道具;两者由此分开
|
||||
form: 封闭枚举 {rule, stat}。rule 规则改写型——在结算管线的某个挂点上给自己加一条规则,同标签持有项数达阈值时质变;stat 属性加成型——抬自己的某项属性数值,写入冒险加算区。两者同属一个对象、共用一份持有集与一份生命周期,是形态枚举而非两个系统
|
||||
scope: 作用对象 = 角色本人与其参与的结算(不改敌人、不改棋盘生成、不改关卡内容);时间范围 = 整局冒险,跨关携带、关间不清零;归属范围 = 不进账号永久进度,不带到下一次冒险
|
||||
lifecycle: 候选池构建(冒险开局一次)→ 在两个获取口之一出现(三选一形式)→ 选定(自池中剔除不再复现)→ 持有生效(跨关携带)→ 冒险以任一结局收束时整集清零;断点记录持有集与剩余候选池
|
||||
acquisition: 两个获取口——战场奖励(每关通关一次,最终关不给;关卡节点图奖励节点共用同一候选池)与商店(花局内金币,口径为「训练」)。**现行两口共用同一候选池**,两形态按渠道分离已定尚未实施,登记于 06-待办清单 BD 分层条目
|
||||
boundary: 特性永不进同调位,魔法道具永不进当局随机渠道;与元进度天赋树两层互不代位
|
||||
data_sources: relics.tres(rule 形态逐项定义)/ adventure.tres(stat 形态配额与值)/ shop.tres(货架取舍)
|
||||
naming_note: 2026-10-05 命名统一——此前按内部分类被叫成三个名字(规则类称「流派件」、属性类称「数值件」、界面称「本关强化」),现统一为「特性」,需要区分时以形态修饰语描述,不另造称呼
|
||||
referenced_by: [冒险结构, 关卡节点地图, 战斗结算, 行动经济, 地形变异, HUD框架, 魔法道具, 元进度, 数据配置]
|
||||
|
||||
- name: adventure_table
|
||||
type: schema_data
|
||||
owner: design/gdd/systems/冒险循环/冒险结构.md
|
||||
@@ -582,11 +596,12 @@ entities:
|
||||
fields: |
|
||||
退役两字段(迭代 10 奖励重构批,2026-09-30 用户拍板):level_clear_hp_bonus(「血回满+上限提升」件随大奖励三件套退役——回血改 clear_heal_pct 部分回血、上限提升改三选一件值列)、keystone_per_level(钥石退役出大奖励改 Boss/精英击杀掉落)。
|
||||
clear_heal_pct: int [0,100](knob 默认 20——非末关通关部分回血回复生效上限的百分比,封顶上限不回满、满血回 0 合法;难度上压方向,带重扫义务归 难度曲线与Boss)
|
||||
bonus_attack_flat / bonus_max_hp_flat / bonus_armor_flat: int [0,999](三选一属性件兑付值——加算区攻击/生命上限/护甲轴累加,经覆盖值通道;值锚与上调约束归 难度曲线与Boss)
|
||||
bonus_gp_amount: int [0,999](GP 袋件定额入钱包);bonus_ap_flat: int [0,10](AP 件每场战斗首轮行动点基线增量);bonus_aux_item_count: int [1,9](魔法道具件授予件数)
|
||||
**2026-10-05 命名统一批**:本表的属性加成型特性字段与常量整体换名(旧 → 新)——BONUS_IDS → FEATURE_KINDS、bonus_token_count() → feature_quota()、bonus_value() → feature_value()、bonus_candidate_count → feature_candidate_count、token_{kind}_{tier} → feature_quota_{kind}_{tier}、bonus_*_flat/_amount(_large) → feature_value_{kind}_{tier};值零变更(句柄改称不改数),断点附随键名沿用历史形态不动(存档兼容)。换名动因见 特性 条目。
|
||||
feature_value_attack_common / feature_value_max_hp_common / feature_value_armor_common: int [0,999](三选一属性加成型特性兑付值——加算区攻击/生命上限/护甲轴累加,经覆盖值通道;值锚与上调约束归 难度曲线与Boss)
|
||||
feature_value_gp_common: int [0,999](GP 袋件定额入钱包);feature_value_ap_rarest: int [0,10](AP 件每场战斗首轮行动点基线增量);bonus_aux_item_count: int [1,9](魔法道具件授予件数)
|
||||
~~bonus_weight_*(E-S 加权洗牌权重族)~~ / ~~bonus_cap_*(种类次数上限族)~~:**v2.2 令牌池换代退役(迭代 12 TP0——2026-10-03 追认 b 实施批;洗牌改令牌 Fisher-Yates、池消耗即上限)**
|
||||
token_{kind}_{tier}: int [0,99](**TP0 令牌配额族**——kind×tier 计数:attack 18/5 · max_hp 17/5 · armor 17/5 · gp 18/5 · heal 0/5 · ap 0/0/3〔common/rare/rarest〕;未列组合=0;档位结构锚 70/25/3=98 张入 schema validate 硬断言〔罕见档原列「道具件 2」随 aux_item 池种退役收窄——台账自决披露项〕)
|
||||
bonus_attack_flat_large / bonus_max_hp_flat_large / bonus_armor_flat_large / bonus_gp_amount_large: int [0,999](稀有档大数值对——+2/+10/+2/50);bonus_heal_flat: int [0,999](恢复件 +6 当即回血——新入池种类 rare 档);MC 策略 316-f(autoplay 1 级最稀有/2 级最左)随批落地
|
||||
feature_quota_{kind}_{tier}: int [0,99](**TP0 令牌配额族**——kind×tier 计数:attack 18/5 · max_hp 17/5 · armor 17/5 · gp 18/5 · heal 0/5 · ap 0/0/3〔common/rare/rarest〕;未列组合=0;档位结构锚 70/25/3=98 张入 schema validate 硬断言〔罕见档原列「道具件 2」随 aux_item 池种退役收窄——台账自决披露项〕)
|
||||
feature_value_attack_rare / feature_value_max_hp_rare / feature_value_armor_rare / feature_value_gp_rare: int [0,999](稀有档大数值对——+2/+10/+2/50);feature_value_heal_rare: int [0,999](恢复件 +6 当即回血——新入池种类 rare 档);MC 策略 316-f(autoplay 1 级最稀有/2 级最左)随批落地
|
||||
transitional_sync_slots: int [0,9](同调位过渡读数源,默认 1——道具持有上限;正主 = attunement_growth.tres 里程碑谓词表,同调实施批落地后切换读数源)
|
||||
mvp_content: 单行全局默认值即 MVP 行(provisional 归 曲线调参批——迭代 10 扩列批注)
|
||||
extension_reserve: 大奖励形态扩列位已消费(迭代 10 奖励重构批落地三选一/攻击型——本键使命完成退役;冒险结构 OQ2 收口)
|
||||
|
||||
@@ -80,8 +80,8 @@ var _save_manager = null # 断点承载注入(迭代 8 卡①
|
||||
var _resume_bp := {} # 续玩快照暂存(resume_adventure → _start_current_level 单跳传递)
|
||||
# ---- 三选一停点态(迭代 10 奖励重构批)----
|
||||
var _bonus_taken := {} # 件获取次数计数(kind 维度派生账本——断点附随件与摘要读数承载;池库存正主=_bonus_deck)
|
||||
var _bonus_deck: Array = [] # 令牌池(TP0 v2.2——持久多重集,元素 {"kind","tier"};洗牌抽候选/选中踢池未选回池/池耗即枯竭;商店货架同库共账;迭代 12 T1 起机制件带=relic 令牌随表追加)
|
||||
var _relics: Array[String] = [] # 流派件持有集(迭代 12 T1——局内随机渠道获得、冒险级跨关携带、收束清零;🔴 层级纪律承载面:不入同调位不入局外树)
|
||||
var _bonus_deck: Array = [] # 令牌池(TP0 v2.2——持久多重集,元素 {"kind","tier"};洗牌抽候选/选中踢池未选回池/池耗即枯竭;商店货架同库共账;迭代 12 T1 起规则改写型特性带=relic 令牌随表追加)
|
||||
var _relics: Array[String] = [] # 特性持有集(迭代 12 T1——局内随机渠道获得、冒险级跨关携带、收束清零;🔴 层级纪律承载面:不入同调位不入局外树)
|
||||
var _tree_rules: Array = [] # 树 rule 键集(迭代 12 T10——Fork 激活侧 effects 透传;下传 enc.tree_rules 消费面)
|
||||
var _bonus_pending := {} # 停点态:{"candidates": Array, "payload": Dictionary, "chosen"/"incoming": 替换在途}——空 = 无停点
|
||||
var _bonus_result := {} # 已兑付待推进态(bonus_resolved 载荷副本——中断续玩不重兑付)
|
||||
@@ -128,8 +128,8 @@ func start_adventure(seed_val: int, params: Dictionary = {}) -> bool:
|
||||
_attunement = params.get("attunement", []) if params.get("attunement", []) is Array else [] # additive(迭代 11 第①批 T5)
|
||||
_attune_refresh_y = maxi(0, int(params.get("attune_refresh_y", 0))) # additive(迭代 11 第①批 T5b——Y 冒险周期池)
|
||||
_seed_attune_charges() # 迭代 11 第①批 T6——冒险开始充能账本按装备主动件重置(每冒险充能语义)
|
||||
# 流派件开局注入(迭代 12 T7——MC 成型画像载体:params.relics_seed 非空=开局持有集〔七流派
|
||||
# 各 2 件档一成型——测量面专用;真实局流派件只走局内随机渠道,红线②层级纪律不破〕)
|
||||
# 特性开局注入(迭代 12 T7——MC 成型画像载体:params.relics_seed 非空=开局持有集〔七流派
|
||||
# 各 2 件档一成型——测量面专用;真实局规则改写型特性只走局内随机渠道,红线②层级纪律不破〕)
|
||||
var relic_seed: Array = params.get("relics_seed", []) if params.get("relics_seed", []) is Array else []
|
||||
_tree_rules = params.get("tree_rules", []) if params.get("tree_rules", []) is Array else [] # 迭代 12 T10——A/B 面 rule 键集
|
||||
if not relic_seed.is_empty():
|
||||
@@ -190,7 +190,7 @@ func resume_adventure(bp: Dictionary, params: Dictionary = {}) -> bool:
|
||||
rtok["relic_id"] = String(tok.get("relic_id", ""))
|
||||
restored.append(rtok)
|
||||
_bonus_deck = restored
|
||||
# 流派件持有集还原(迭代 12 T1——缺键 = 旧版断点防御空集)
|
||||
# 特性持有集还原(迭代 12 T1——缺键 = 旧版断点防御空集)
|
||||
_relics = []
|
||||
for r in (bp.get("relics", []) as Array):
|
||||
_relics.append(String(r))
|
||||
@@ -267,14 +267,14 @@ func _reset_bonus_state() -> void:
|
||||
_node_bonus_pending = {}
|
||||
|
||||
|
||||
# 令牌池构建(TP0 v2.2——按表 kind×tier 配额展开为持久多重集;构建序确定 = BONUS_IDS×TIERS 逐层,
|
||||
# 随机性只发生在洗牌消费 reward_pick 封闭流的时刻。迭代 12 T1:机制件带=relic 活行每件 1 张追加
|
||||
# 令牌池构建(TP0 v2.2——按表 kind×tier 配额展开为持久多重集;构建序确定 = FEATURE_KINDS×TIERS 逐层,
|
||||
# 随机性只发生在洗牌消费 reward_pick 封闭流的时刻。迭代 12 T1:规则改写型特性带=relic 活行每件 1 张追加
|
||||
# (rarity common/rare→稀有令牌档、rarest→罕见令牌档——relic 永不入普通档;空表=零追加零扰动))
|
||||
func _build_bonus_deck() -> Array:
|
||||
var deck: Array = []
|
||||
for kind in db.adventure.BONUS_IDS:
|
||||
for kind in db.adventure.FEATURE_KINDS:
|
||||
for tier in db.adventure.TIERS:
|
||||
for i in int(db.adventure.bonus_token_count(String(kind), String(tier))):
|
||||
for i in int(db.adventure.feature_quota(String(kind), String(tier))):
|
||||
deck.append({"kind": String(kind), "tier": String(tier)})
|
||||
for row in db.relic_rows():
|
||||
var rtier := "rarest" if String(row.get("rarity", "")) == "rarest" else "rare"
|
||||
@@ -282,7 +282,7 @@ func _build_bonus_deck() -> Array:
|
||||
return deck
|
||||
|
||||
|
||||
# 令牌唯一身份(抽签去重/兑付匹配共用——数值件=kind,机制件=relic_id;同档多张不同 relic 可同屏)
|
||||
# 令牌唯一身份(抽签去重/兑付匹配共用——属性加成型特性=kind,规则改写型特性=relic_id;同档多张不同 relic 可同屏)
|
||||
func _token_identity(tok: Dictionary) -> String:
|
||||
if String(tok.get("kind", "")) == "relic":
|
||||
return "relic:" + String(tok.get("relic_id", ""))
|
||||
@@ -337,7 +337,7 @@ func continue_to_next_level() -> bool:
|
||||
|
||||
# ---- 提升三选一(迭代 10 奖励重构批——选择停点零自动推进、重复兑付被拒;兑付恰一件、未选项零生效)----
|
||||
|
||||
# 候选令牌匹配(身份键恒等——数值件 kind+tier、机制件 relic_id;迭代 12 T1 机制件带)
|
||||
# 候选令牌匹配(身份键恒等——属性加成型特性 kind+tier、规则改写型特性 relic_id;迭代 12 T1 规则改写型特性带)
|
||||
func _find_token(candidates: Array, kind: String, tier: String, relic_id: String = "") -> Dictionary:
|
||||
for t in candidates:
|
||||
var tok: Dictionary = t as Dictionary
|
||||
@@ -351,7 +351,7 @@ func _find_token(candidates: Array, kind: String, tier: String, relic_id: String
|
||||
|
||||
# 玩家点选兑付(呈现层/冒烟/自动模拟确认入口):令牌 ∈ 停点候选(身份键精确匹配——relic 件
|
||||
# 另须 relic_id)。属性件写加算区、AP 件写第四轴、GP 件走钱包「奖励入账」入口、恢复件当即回血、
|
||||
# relic 件入流派件持有集(🔴 层级纪律:只走局内随机渠道)、道具件受同调位约束(随池种退役不可达)。
|
||||
# relic 件入特性持有集(🔴 层级纪律:只走局内随机渠道)、道具件受同调位约束(随池种退役不可达)。
|
||||
# 消费=选中令牌踢池(未选回池由「抽签不摘牌、兑付才摘牌」语义承载——TP0 v2.2)。
|
||||
func pick_bonus(kind: String, tier: String = "", relic_id: String = "") -> bool:
|
||||
if state != "running" or _bonus_pending.is_empty():
|
||||
@@ -361,7 +361,7 @@ func pick_bonus(kind: String, tier: String = "", relic_id: String = "") -> bool:
|
||||
if _find_token(candidates, kind, tier, relic_id).is_empty():
|
||||
push_error("[冒险结构] pick_bonus 拒绝——令牌不在候选: %s|%s|%s" % [kind, tier, relic_id])
|
||||
return false
|
||||
var value: int = int(db.adventure.bonus_value(kind, tier))
|
||||
var value: int = int(db.adventure.feature_value(kind, tier))
|
||||
var hp_before := int(ledger.get("hero_hp", 0))
|
||||
if kind == "aux_item":
|
||||
return _pick_aux_item(value) # 道具件分派通关渠道(持有容器 = 跨关携带——与节点渠道分轨;池种退役后不可达)
|
||||
@@ -435,7 +435,7 @@ func _consume_deck_token(kind: String, tier: String, relic_id: String = "") -> b
|
||||
return false
|
||||
|
||||
|
||||
# 流派件持有集读面(效果接线/求值/摘要唯一取数口——副本防外部改写)
|
||||
# 特性持有集读面(效果接线/求值/摘要唯一取数口——副本防外部改写)
|
||||
func relics_held() -> Array:
|
||||
return _relics.duplicate()
|
||||
|
||||
@@ -457,10 +457,10 @@ func pool_stock(kind: String) -> int:
|
||||
# 写加算区+账本+摘牌(与奖励三选一真单点——买一件=奖励面少一件的库存语义由同库成立)。
|
||||
# 未知 kind 拒绝(货架词表封闭的前置防御)。
|
||||
func _consume_pool_purchase(kind: String, tier: String) -> bool:
|
||||
if not db.adventure.BONUS_IDS.has(kind):
|
||||
if not db.adventure.FEATURE_KINDS.has(kind):
|
||||
push_error("[冒险结构] 商店购买消费拒绝——件不在池词表: %s" % kind)
|
||||
return false
|
||||
return _apply_bonus_pick(kind, tier, int(db.adventure.bonus_value(kind, tier)))
|
||||
return _apply_bonus_pick(kind, tier, int(db.adventure.feature_value(kind, tier)))
|
||||
|
||||
|
||||
# 终局池快照(_settle 清账前调用——_reset_bonus_state 会重置 _bonus_taken,摘要 additive 键
|
||||
@@ -552,7 +552,7 @@ func apply_node_bonus(kind: String, tier: String = "", relic_id: String = "") ->
|
||||
if _find_token(candidates, kind, tier, relic_id).is_empty():
|
||||
push_error("[冒险结构] apply_node_bonus 拒绝——令牌不在候选: %s|%s|%s" % [kind, tier, relic_id])
|
||||
return false
|
||||
var value: int = int(db.adventure.bonus_value(kind, tier))
|
||||
var value: int = int(db.adventure.feature_value(kind, tier))
|
||||
if kind == "aux_item":
|
||||
return _apply_node_aux(value) # 道具件分派节点渠道(持有容器 = 关卡域库存——与通关渠道分轨;池种退役后不可达)
|
||||
if not _apply_bonus_pick(kind, tier, value, relic_id):
|
||||
@@ -573,7 +573,7 @@ func _apply_node_aux(count: int) -> bool:
|
||||
var records: Array = []
|
||||
if _runner != null and _runner.aux_inventory != null:
|
||||
records = _runner.aux_inventory.holding_records()
|
||||
# 迭代 11 第①批 T7——守卫随过渡键退役拆除(BONUS_IDS 已除名 aux_item,本分支不可达;
|
||||
# 迭代 11 第①批 T7——守卫随过渡键退役拆除(FEATURE_KINDS 已除名 aux_item,本分支不可达;
|
||||
# 替换子交互路由随容量闸一并退役——能力件容量闸正主 = 营地装配面满位禁选)
|
||||
if _runner != null:
|
||||
for iid in picked:
|
||||
@@ -739,7 +739,7 @@ func _draw_bonus_candidates() -> Array:
|
||||
if ident.begins_with("relic:"):
|
||||
cand["relic_id"] = String((tok as Dictionary).get("relic_id", ""))
|
||||
out.append(cand)
|
||||
if out.size() >= int(db.adventure.bonus_candidate_count):
|
||||
if out.size() >= int(db.adventure.feature_candidate_count):
|
||||
break
|
||||
return out
|
||||
|
||||
@@ -828,7 +828,7 @@ func _start_current_level() -> bool:
|
||||
if ok:
|
||||
_runner.set_attunement(_attunement) # 迭代 11 第①批 T5——同调装配下传(enc 携带进战斗结算)
|
||||
_runner.set_attune_charges(attune_charges) # 迭代 11 第①批 T6——充能账本下传(能力件骑库存面注入)
|
||||
_runner.set_relics(_relics) # 迭代 12 T1——流派件持有集下传(begin_battle enc.relics 求值面)
|
||||
_runner.set_relics(_relics) # 迭代 12 T1——特性持有集下传(begin_battle enc.relics 求值面)
|
||||
_runner.set_tree_rules(_tree_rules) # 迭代 12 T10——树 rule 键集下传(A/B 面消费)
|
||||
if _shop_mode == "pool":
|
||||
# 商店共享池注入(迭代 11 第②批 T3——库存账本引用+消费 handler 双下传;legacy 模式零注入零扰动)
|
||||
@@ -908,7 +908,7 @@ func _settle(result: String) -> void:
|
||||
"aux_cleared_last": _last_aux_cleared, # additive 扩签(迭代 7 T4——末关清空反馈;非末关走 bonus 载荷)
|
||||
"keystone_drops": _keystone_drops.duplicate(true), # additive 扩签(迭代 10——逐杀掉落明细;settle 入账明细/复盘归因数据源)
|
||||
"pool_stock": _pool_stock_snapshot(), # additive 扩签(迭代 11 第②批 T5——终局池读数:清账前快照,商店买走 vs 奖励领走 vs 枯竭的终局面)
|
||||
"relics": _relics.duplicate(), # additive 扩签(迭代 12 T1——流派件终局持有集:清账前快照,成型判读取数面)
|
||||
"relics": _relics.duplicate(), # additive 扩签(迭代 12 T1——特性终局持有集:清账前快照,成型判读取数面)
|
||||
}
|
||||
# 败退明细(数值验证工具取数面 2026-09-22——tools/balance_verifier.py 止步节点分布数据源;
|
||||
# 仅失败局附加,键缺省 = 未败退,既有五件事消费方零感知)
|
||||
@@ -941,7 +941,7 @@ func _forward_choices_presented(candidates: Array) -> void:
|
||||
|
||||
|
||||
# ---- 断点快照(迭代 8 卡①——七字段拍板面+恢复必需附随件)----
|
||||
# 七字段(拍板面):关卡序号/节点位/生命/本关加成区/GP 钱包/商店已购档/已抽模板;
|
||||
# 七字段(拍板面):关卡序号/节点位/生命/属性加成区/GP 钱包/商店已购档/已抽模板;
|
||||
# 附随件(续玩正确性必需,随批注记):主种子+取数计数器(rng 快照契约回填——续接原时间线)、
|
||||
# 钥石累计(大奖励中途值——终局摘要五件事不失真)、已到节点序(呈现层图条重建)、道具库存
|
||||
# (奖励节点已选件——防静默丢失)。注入缺省 null = 整面静默(模拟/冒烟零扰动)。
|
||||
@@ -976,7 +976,7 @@ func _snapshot_breakpoint() -> void:
|
||||
"aux_items": aux_items,
|
||||
"bonus_taken": _bonus_taken.duplicate(true), # 三选一件获取次数(kind 维度派生账本——断点附随件与读数承载)
|
||||
"bonus_deck": _bonus_deck.duplicate(true), # 令牌池余库(TP0 v2.2——池消耗即上限,续玩余库逐枚还原)
|
||||
"relics": _relics.duplicate(), # 流派件持有集(迭代 12 T1——局内随机渠道获得态续玩防丢失)
|
||||
"relics": _relics.duplicate(), # 特性持有集(迭代 12 T1——局内随机渠道获得态续玩防丢失)
|
||||
"bonus_pending": _bonus_pending.duplicate(true), # 三选一停点态(空 = 无停点——选择停点可中断契约)
|
||||
"bonus_result": _bonus_result.duplicate(true), # 已兑付待推进态(空 = 无——中断续玩不重兑付)
|
||||
"bonus_aux_carry": _bonus_aux_carry.duplicate(true), # 道具件跨关携带(注入前中断防静默丢失)
|
||||
|
||||
@@ -72,7 +72,7 @@ var attunement: Array = [] # 装备中同调件 item_id 集
|
||||
var _attune_charges_ref: Dictionary = {} # 充能账本共享引用(迭代 11 第①批 T6——use_aux 消费直改)
|
||||
var _attune_bank := 0 # 掘进蓄能积点(battle 域——每 charge_n 安全格 +1 点)
|
||||
var _attune_safe_seen := 0 # 掘进蓄能 battle 域安全开格计数
|
||||
# 流派件运行态(迭代 12 T2——relic 持有集经 enc.relics 注入;求值旗注 damage_controller.relic_flags;
|
||||
# 特性运行态(迭代 12 T2——relic 持有集经 enc.relics 注入;求值旗注 damage_controller.relic_flags;
|
||||
# 魔矢每战首次计数 battle 域。空集=零扰动)
|
||||
var _relic_first_dig_used := false
|
||||
var _relic_combo := 0 # 矿脉直觉连击计数(battle 域——safe +1/mine 清零)
|
||||
@@ -94,7 +94,7 @@ func _attune_mag(item_id: String) -> int:
|
||||
return int(_attune_row(item_id).get("magnitude", 0))
|
||||
|
||||
|
||||
# 流派件求值(迭代 12 T2——持有集 × relic_table → damage_controller.relic_flags 注入面):
|
||||
# 特性求值(迭代 12 T2——持有集 × relic_table → damage_controller.relic_flags 注入面):
|
||||
# rider_flat = Σ rider 件 value(奥术余烬 +1 / 魔能共鸣 +2);magic 档一(≥2 件)rider +1、
|
||||
# 档二(≥4 件)rider 可暴击;clamp 两件直调键;first_dig_spell 旗(魔能共鸣第二效果——魔矢值
|
||||
# = 件 effects.value)。空集/空表 = 零旗零扰动。
|
||||
@@ -247,7 +247,7 @@ func begin_battle(enc: Dictionary) -> bool:
|
||||
_attune_safe_seen = 0
|
||||
_damage.attune_venom = _attune_mag("venom_edge") if _attune_has("venom_edge") else 0
|
||||
_reward_economy.luck_bias = _attune_mag("luck_coin") if _attune_has("luck_coin") else 0
|
||||
# 流派件运行态注入(迭代 12 T2 魔法流——enc.relics 携带持有集;RelicsEngine 求值后注伤害控制器
|
||||
# 特性运行态注入(迭代 12 T2 魔法流——enc.relics 携带持有集;RelicsEngine 求值后注伤害控制器
|
||||
# relic_flags;空集/空表=零扰动。魔矢每战首次开格计数同步归零)
|
||||
_relic_flags_for((enc.get("relics", []) as Array))
|
||||
_relic_first_dig_used = false
|
||||
@@ -680,7 +680,7 @@ func set_aux_unlocked(ids: Dictionary) -> void:
|
||||
|
||||
func _grant_routed(snap: Dictionary, polarity: String, source_class: String, cell: Vector2i, ri: int, highlight: String = "", label_suffix: String = "") -> bool:
|
||||
# 迭代 11 第①批 T7——aux 授予分支随掉落/停点渠道退役拆除(reward 词表第十型 aux_item 保留但零投放:
|
||||
# 无 aux 行入池、BONUS_IDS 词表已除名);剩余类型走极性字典路由。
|
||||
# 无 aux 行入池、FEATURE_KINDS 词表已除名);剩余类型走极性字典路由。
|
||||
var row: Dictionary = _reward_economy.polarity_row(String(snap.get("cell_type", "")), polarity)
|
||||
if row.is_empty():
|
||||
_fatal("极性字典缺行: %s %s" % [String(snap.get("cell_type", "")), polarity])
|
||||
|
||||
@@ -27,7 +27,7 @@ const TABLE_MANIFEST := {
|
||||
"aux_items": "aux_items.tres", # 迭代 7 T1 魔法道具内容批(AuxItemTable 六行——定义表 Rule 4 豁免;罗盘 retired/失义件 deferred 标记见 schema 头注)
|
||||
"adventure": "adventure.tres", # 冒险结构实现批 2026-09-21(AdventureTable 建表——大奖励与钥石行值单点)
|
||||
"attunement_growth": "attunement_growth.tres", # 迭代 11 第①批 同调实施批 T1(AttunementGrowthTable 单行全局——同调位里程碑谓词表;单行先例 Rule 4 豁免)
|
||||
"relics": "relics.tres", # 迭代 12 T1 双层 BD 机制件基建(RelicTable 定义表 Rule 4 豁免——AuxItemTable 先例;空表合法态=主时间线零扰动)
|
||||
"relics": "relics.tres", # 迭代 12 T1 双层 BD 规则改写型特性基建(RelicTable 定义表 Rule 4 豁免——AuxItemTable 先例;空表合法态=主时间线零扰动)
|
||||
}
|
||||
|
||||
var action_economy: ActionEconomyTable
|
||||
@@ -154,7 +154,7 @@ func relic_row(relic_id: String) -> Dictionary:
|
||||
return relics.row_by_id(relic_id) if relics != null else {}
|
||||
|
||||
|
||||
# 机制件带令牌构建源(池接线——adventure_runner._build_bonus_deck 消费;行 rarity→投放档映射)
|
||||
# 规则改写型特性带令牌构建源(池接线——adventure_runner._build_bonus_deck 消费;行 rarity→投放档映射)
|
||||
func relic_rows() -> Array:
|
||||
return relics.rows if relics != null else []
|
||||
|
||||
|
||||
@@ -99,18 +99,18 @@ func cross_validate(loaded: Dictionary, push_diag: Callable) -> void:
|
||||
for e in validate_skill_pool_links(skt, en, loaded.get("status_effects")):
|
||||
push_diag.call("error", e.category, e.message)
|
||||
# ⑥ 商店货架 × 冒险共享池跨表校验(M-4 迭代 11 第②批 T1——次数上限域):
|
||||
# pool_shelf kind 须命中 adventure.BONUS_IDS 且为有限库存种(cap ∈ [1,99]——gp 无上限种/牌库外种
|
||||
# 入货架 = 库存账本无锚,加载致命;gp 袋负交易切边/机制件三轴切边由 ShopTable 词表封闭另拦)
|
||||
# pool_shelf kind 须命中 adventure.FEATURE_KINDS 且为有限库存种(cap ∈ [1,99]——gp 无上限种/牌库外种
|
||||
# 入货架 = 库存账本无锚,加载致命;gp 袋负交易切边/规则改写型特性三轴切边由 ShopTable 词表封闭另拦)
|
||||
var adv = loaded.get("adventure")
|
||||
var shp = loaded.get("shop")
|
||||
if adv != null and shp != null:
|
||||
for row in shp.pool_shelf:
|
||||
var kind: String = String(row.get("kind_id", ""))
|
||||
if not adv.BONUS_IDS.has(kind):
|
||||
push_diag.call("error", "shelf_dangling_kind", "ShopTable.pool_shelf kind %s 不在 AdventureTable.BONUS_IDS(共享池牌库外种)" % kind)
|
||||
if not adv.FEATURE_KINDS.has(kind):
|
||||
push_diag.call("error", "shelf_dangling_kind", "ShopTable.pool_shelf kind %s 不在 AdventureTable.FEATURE_KINDS(共享池牌库外种)" % kind)
|
||||
continue
|
||||
# TP0 令牌池——货架件须为有限令牌种(配额 >0;种类次数上限退役后库存=剩余令牌数)
|
||||
var quota := int(adv.bonus_token_count(kind, adv.TIER_COMMON)) + int(adv.bonus_token_count(kind, adv.TIER_RARE)) + int(adv.bonus_token_count(kind, adv.TIER_RAREST))
|
||||
var quota := int(adv.feature_quota(kind, adv.TIER_COMMON)) + int(adv.feature_quota(kind, adv.TIER_RARE)) + int(adv.feature_quota(kind, adv.TIER_RAREST))
|
||||
if quota < 1:
|
||||
push_diag.call("error", "shelf_zero_quota", "ShopTable.pool_shelf kind %s 令牌配额为 0(牌库空种入货架 = 库存无锚)" % kind)
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ var _outcomes := {} # ticket_id → "redeemed"/"zero"/"voided"(
|
||||
var _seq := 0 # 流水号
|
||||
var _halted := false # 主角倒下终止旗(死亡事件置位——flush 余单作废)
|
||||
var _hero_ac_override := -1 # 主角护甲等级合流入参(begin_battle 显式设定——-1 = 表值兜底,口径同战斗编排器)
|
||||
# 流派件求值旗(迭代 12 T2——begin_battle 编排器经 RelicsEngine 求值后注入;空字典=零扰动。
|
||||
# 特性求值旗(迭代 12 T2——begin_battle 编排器经 RelicsEngine 求值后注入;空字典=零扰动。
|
||||
# rider_flat=英雄侧必中附加值〔奥术余烬族〕/rider_crit=档二 rider 可暴击/first_dig_spell=每战首次
|
||||
# 开安全格追加魔法矢〔消费在编排器授予段〕/clamp_magic_light·clamp_magic_heavy=克制点直调)
|
||||
var relic_flags: Dictionary = {}
|
||||
@@ -418,7 +418,7 @@ func _counter_delta(attack_type: String, armor: String) -> int:
|
||||
return int(row.get(armor, 0))
|
||||
|
||||
|
||||
# 克制点直调(迭代 12 T2 魔法流/T4 穿刺流 clamp_modifier 件——克制矩阵查表值后的流派件调整;
|
||||
# 克制点直调(迭代 12 T2 魔法流/T4 穿刺流 clamp_modifier 件——克制矩阵查表值后的特性调整;
|
||||
# 空旗=0 零扰动):魔网织者=magic vs magic(矩阵罚 −1 → 0/正);湛蓝誓约=magic vs heavy(+1 → +2);
|
||||
# 猎手刺剑=pierce vs light(+1——对轻甲敌穿刺提升,对重甲无增益=正负双修)。hero_attack 与
|
||||
# board_typed 两消费面同享。
|
||||
|
||||
@@ -589,7 +589,7 @@ func set_attunement(ids: Array) -> void:
|
||||
_attunement = ids.duplicate()
|
||||
|
||||
|
||||
# 流派件持有集注入(迭代 12 T1——AdventureRunner._start_current_level 唯一调用方;begin_battle
|
||||
# 特性持有集注入(迭代 12 T1——AdventureRunner._start_current_level 唯一调用方;begin_battle
|
||||
# enc.relics 携带进战斗求值;**共享引用不复制**——关内奖励节点兑付的 relic 须当关后续战斗生效
|
||||
# (attune_charges 共享账本同款);空集=零扰动)
|
||||
var _relics: Array = []
|
||||
@@ -599,7 +599,7 @@ func set_relics(ids: Array) -> void:
|
||||
_relics = ids
|
||||
|
||||
|
||||
# 流派件持有集读面(迭代 12 呈现补齐——HUD C 区流派件段数据源)
|
||||
# 特性持有集读面(迭代 12 呈现补齐——HUD C 区特性段数据源)
|
||||
func relics_held() -> Array:
|
||||
return _relics.duplicate()
|
||||
|
||||
@@ -776,7 +776,7 @@ func _shop_draw_shelf() -> void:
|
||||
_shop_shelf.append(tok)
|
||||
if _shop_shelf.size() >= 3:
|
||||
break
|
||||
# 商店保底(迭代 12 T6——「本关变异交互件必刷」简化口径:货架零流派件时**挤掉最后一张普通卡**
|
||||
# 商店保底(迭代 12 T6——「本关变异交互件必刷」简化口径:货架零特性时**挤掉最后一张普通卡**
|
||||
# 换吞噬流件〔地形交互件广义映射——按关变异精细绑定归数值批,台账披露待追认〕;占位制货架恒
|
||||
# ≤3;池内无 devour 令牌=不保底合法态)
|
||||
var has_relic := false
|
||||
@@ -831,10 +831,10 @@ func shop_shelf() -> Array:
|
||||
var tier := String((tok as Dictionary).get("tier", ""))
|
||||
var row: Dictionary = db.shop_pool_row(kind)
|
||||
var display := String(row.get("display_name", kind))
|
||||
var value := int(db.adventure.bonus_value(kind, tier))
|
||||
var value := int(db.adventure.feature_value(kind, tier))
|
||||
if row.is_empty() and kind == "relic":
|
||||
var rrow: Dictionary = db.relic_row(String(tok.get("relic_id", "")))
|
||||
display = String(rrow.get("display_name", "流派件"))
|
||||
display = String(rrow.get("display_name", "特性"))
|
||||
value = 0
|
||||
out.append({
|
||||
"kind_id": kind,
|
||||
|
||||
@@ -13,9 +13,13 @@
|
||||
class_name AdventureTable
|
||||
extends Resource
|
||||
|
||||
## 概念指路:本表的属性加成型特性,与 relics.tres 的规则改写型特性,同属一个对象——
|
||||
## 「特性」(一次冒险内角色自身得到的提升)。定义见 design/gdd/systems/冒险循环/特性.md。
|
||||
## 两者是它的形态枚举(form = rule / stat),不是两个系统;本表承载 stat 形态的配额与值。
|
||||
## (2026-10-05 命名统一:旧称「数值件」→ 属性加成型特性;常量与字段随之前缀 feature_*。)
|
||||
## 三选一提升池 kind 词表(封闭——断点附随件与牌库剔除态依赖它;扩件走本表+registry 修订)。
|
||||
## aux_item 池种退役(迭代 11 第①批 T7——同调批出池);heal 恢复件新入池(v2.2 令牌池追认 b)。
|
||||
const BONUS_IDS: Array[String] = ["attack", "max_hp", "armor", "gp", "ap", "heal"]
|
||||
const FEATURE_KINDS: Array[String] = ["attack", "max_hp", "armor", "gp", "ap", "heal"]
|
||||
## 令牌档位词表(v2.2 三档位——稀有度命名对齐 MC 策略判读序 316-f:1 级最稀有=rarest 优先)
|
||||
const TIERS: Array[String] = ["common", "rare", "rarest"]
|
||||
const TIER_COMMON := "common"
|
||||
@@ -30,62 +34,62 @@ const TIER_QUOTAS := {"common": 70, "rare": 25, "rarest": 3}
|
||||
@export var clear_heal_pct: int = 20 # [0,100] knob——回复生效上限的百分比,封顶上限不回满
|
||||
|
||||
# —— 三选一候选数(2026-10-02 修复批 T2 魔法数结构化)——
|
||||
@export var bonus_candidate_count: int = 3 # [1,6] knob——令牌洗牌不放回抽取张数上界
|
||||
@export var feature_candidate_count: int = 3 # [1,6] knob——令牌洗牌不放回抽取张数上界
|
||||
|
||||
# —— 令牌配额(kind × tier 计数;未列组合 = 0——heal 只入稀有/ap 只入罕见,v2.2 档位构成)——
|
||||
@export var token_attack_common: int = 18 # [0,99]
|
||||
@export var token_attack_rare: int = 5 # [0,99]
|
||||
@export var token_max_hp_common: int = 17 # [0,99]
|
||||
@export var token_max_hp_rare: int = 5 # [0,99]
|
||||
@export var token_armor_common: int = 17 # [0,99]
|
||||
@export var token_armor_rare: int = 5 # [0,99]
|
||||
@export var token_gp_common: int = 18 # [0,99]
|
||||
@export var token_gp_rare: int = 5 # [0,99]
|
||||
@export var token_heal_rare: int = 5 # [0,99]——恢复件(新入池种类,当即回血)
|
||||
@export var token_ap_rarest: int = 3 # [0,99]——AP 件(罕见档;道具件 2 席位随池种退役收窄)
|
||||
@export var feature_quota_attack_common: int = 18 # [0,99]
|
||||
@export var feature_quota_attack_rare: int = 5 # [0,99]
|
||||
@export var feature_quota_max_hp_common: int = 17 # [0,99]
|
||||
@export var feature_quota_max_hp_rare: int = 5 # [0,99]
|
||||
@export var feature_quota_armor_common: int = 17 # [0,99]
|
||||
@export var feature_quota_armor_rare: int = 5 # [0,99]
|
||||
@export var feature_quota_gp_common: int = 18 # [0,99]
|
||||
@export var feature_quota_gp_rare: int = 5 # [0,99]
|
||||
@export var feature_quota_heal_rare: int = 5 # [0,99]——恢复件(新入池种类,当即回血)
|
||||
@export var feature_quota_ap_rarest: int = 3 # [0,99]——AP 件(罕见档;道具件 2 席位随池种退役收窄)
|
||||
|
||||
# —— 令牌件值(小/大数值对——v2.2 追认 b 定稿:20/50、+1/+2、+1/+2、+5/+10、恢复+6、AP+1)——
|
||||
@export var bonus_attack_flat: int = 1 # [0,999] knob——小增伤
|
||||
@export var bonus_attack_flat_large: int = 2 # [0,999] knob——大增伤
|
||||
@export var bonus_max_hp_flat: int = 5 # [0,999] knob——小生命
|
||||
@export var bonus_max_hp_flat_large: int = 10 # [0,999] knob——大生命
|
||||
@export var bonus_armor_flat: int = 1 # [0,999] knob——小护甲
|
||||
@export var bonus_armor_flat_large: int = 2 # [0,999] knob——大护甲
|
||||
@export var bonus_gp_amount: int = 20 # [0,999] knob——小GP
|
||||
@export var bonus_gp_amount_large: int = 50 # [0,999] knob——大GP
|
||||
@export var bonus_heal_flat: int = 6 # [0,999] knob——恢复(当即回血,封顶生效上限)
|
||||
@export var bonus_ap_flat: int = 1 # [0,10] knob——AP 件每场战斗首轮行动点基线增量
|
||||
@export var feature_value_attack_common: int = 1 # [0,999] knob——小增伤
|
||||
@export var feature_value_attack_rare: int = 2 # [0,999] knob——大增伤
|
||||
@export var feature_value_max_hp_common: int = 5 # [0,999] knob——小生命
|
||||
@export var feature_value_max_hp_rare: int = 10 # [0,999] knob——大生命
|
||||
@export var feature_value_armor_common: int = 1 # [0,999] knob——小护甲
|
||||
@export var feature_value_armor_rare: int = 2 # [0,999] knob——大护甲
|
||||
@export var feature_value_gp_common: int = 20 # [0,999] knob——小GP
|
||||
@export var feature_value_gp_rare: int = 50 # [0,999] knob——大GP
|
||||
@export var feature_value_heal_rare: int = 6 # [0,999] knob——恢复(当即回血,封顶生效上限)
|
||||
@export var feature_value_ap_rarest: int = 1 # [0,10] knob——AP 件每场战斗首轮行动点基线增量
|
||||
|
||||
|
||||
## 令牌配额读数(未列 kind×tier 组合 = 0——heal 无普通档/ap 无普通稀有档按 v2.2 构成)
|
||||
func bonus_token_count(kind: String, tier: String) -> int:
|
||||
func feature_quota(kind: String, tier: String) -> int:
|
||||
match [kind, tier]:
|
||||
["attack", TIER_COMMON]: return token_attack_common
|
||||
["attack", TIER_RARE]: return token_attack_rare
|
||||
["max_hp", TIER_COMMON]: return token_max_hp_common
|
||||
["max_hp", TIER_RARE]: return token_max_hp_rare
|
||||
["armor", TIER_COMMON]: return token_armor_common
|
||||
["armor", TIER_RARE]: return token_armor_rare
|
||||
["gp", TIER_COMMON]: return token_gp_common
|
||||
["gp", TIER_RARE]: return token_gp_rare
|
||||
["heal", TIER_RARE]: return token_heal_rare
|
||||
["ap", TIER_RAREST]: return token_ap_rarest
|
||||
["attack", TIER_COMMON]: return feature_quota_attack_common
|
||||
["attack", TIER_RARE]: return feature_quota_attack_rare
|
||||
["max_hp", TIER_COMMON]: return feature_quota_max_hp_common
|
||||
["max_hp", TIER_RARE]: return feature_quota_max_hp_rare
|
||||
["armor", TIER_COMMON]: return feature_quota_armor_common
|
||||
["armor", TIER_RARE]: return feature_quota_armor_rare
|
||||
["gp", TIER_COMMON]: return feature_quota_gp_common
|
||||
["gp", TIER_RARE]: return feature_quota_gp_rare
|
||||
["heal", TIER_RARE]: return feature_quota_heal_rare
|
||||
["ap", TIER_RAREST]: return feature_quota_ap_rarest
|
||||
return 0
|
||||
|
||||
|
||||
## 令牌件值(kind × tier;v2.2 数值对——小/大两档)
|
||||
func bonus_value(kind: String, tier: String = TIER_COMMON) -> int:
|
||||
func feature_value(kind: String, tier: String = TIER_COMMON) -> int:
|
||||
match [kind, tier]:
|
||||
["attack", TIER_COMMON]: return bonus_attack_flat
|
||||
["attack", TIER_RARE]: return bonus_attack_flat_large
|
||||
["max_hp", TIER_COMMON]: return bonus_max_hp_flat
|
||||
["max_hp", TIER_RARE]: return bonus_max_hp_flat_large
|
||||
["armor", TIER_COMMON]: return bonus_armor_flat
|
||||
["armor", TIER_RARE]: return bonus_armor_flat_large
|
||||
["gp", TIER_COMMON]: return bonus_gp_amount
|
||||
["gp", TIER_RARE]: return bonus_gp_amount_large
|
||||
["heal", TIER_RARE]: return bonus_heal_flat
|
||||
["ap", TIER_RAREST]: return bonus_ap_flat
|
||||
["attack", TIER_COMMON]: return feature_value_attack_common
|
||||
["attack", TIER_RARE]: return feature_value_attack_rare
|
||||
["max_hp", TIER_COMMON]: return feature_value_max_hp_common
|
||||
["max_hp", TIER_RARE]: return feature_value_max_hp_rare
|
||||
["armor", TIER_COMMON]: return feature_value_armor_common
|
||||
["armor", TIER_RARE]: return feature_value_armor_rare
|
||||
["gp", TIER_COMMON]: return feature_value_gp_common
|
||||
["gp", TIER_RARE]: return feature_value_gp_rare
|
||||
["heal", TIER_RARE]: return feature_value_heal_rare
|
||||
["ap", TIER_RAREST]: return feature_value_ap_rarest
|
||||
return 0
|
||||
|
||||
|
||||
@@ -101,8 +105,8 @@ func tier_rank(tier: String) -> int:
|
||||
## 档位令牌总数(货架/校验读面)
|
||||
func tier_total(tier: String) -> int:
|
||||
var total := 0
|
||||
for kind in BONUS_IDS:
|
||||
total += bonus_token_count(kind, tier)
|
||||
for kind in FEATURE_KINDS:
|
||||
total += feature_quota(kind, tier)
|
||||
return total
|
||||
|
||||
|
||||
@@ -115,18 +119,18 @@ func validate() -> Array:
|
||||
var errs: Array[Dictionary] = []
|
||||
if clear_heal_pct < 0 or clear_heal_pct > 100:
|
||||
errs.append({"category": "domain", "message": "clear_heal_pct 越域 [0,100]: %d" % clear_heal_pct})
|
||||
for kind in BONUS_IDS:
|
||||
for kind in FEATURE_KINDS:
|
||||
for tier in TIERS:
|
||||
var c := bonus_token_count(kind, tier)
|
||||
var c := feature_quota(kind, tier)
|
||||
if c < 0 or c > 99:
|
||||
errs.append({"category": "domain", "message": "token_count(%s,%s) 越域 [0,99]: %d" % [kind, tier, c]})
|
||||
var v := bonus_value(kind, tier)
|
||||
var v := feature_value(kind, tier)
|
||||
if v < 0 or v > 999:
|
||||
errs.append({"category": "domain", "message": "bonus_value(%s,%s) 越域 [0,999]: %d" % [kind, tier, v]})
|
||||
errs.append({"category": "domain", "message": "feature_value(%s,%s) 越域 [0,999]: %d" % [kind, tier, v]})
|
||||
for tier in TIERS:
|
||||
var total := tier_total(tier)
|
||||
if total != int(TIER_QUOTAS.get(tier, -1)):
|
||||
errs.append({"category": "domain", "message": "档位配额结构失锚(v2.2 追认 b——%s 应=%d 实=%d;改总量须重裁)" % [tier, int(TIER_QUOTAS.get(tier, -1)), total]})
|
||||
if bonus_candidate_count < 1 or bonus_candidate_count > 6:
|
||||
errs.append({"category": "domain", "message": "bonus_candidate_count 越域 [1,6]: %d" % bonus_candidate_count})
|
||||
if feature_candidate_count < 1 or feature_candidate_count > 6:
|
||||
errs.append({"category": "domain", "message": "feature_candidate_count 越域 [1,6]: %d" % feature_candidate_count})
|
||||
return errs
|
||||
@@ -13,8 +13,8 @@
|
||||
# requires Array[node_id](显式前置——父开子脉内链)/ effects Dictionary(stat 四线 flat:
|
||||
# atk/max_hp/hit/armor_class;rule 键封闭 RULE_KEYS)/ fork_group/fork_side(a/b——同组互斥、
|
||||
# 营地免费切换)。
|
||||
# 🔴 层级纪律(任务书红线 2):局外树只放全局规则件——effects 禁流派标签(relic 流派件永不入树,
|
||||
# archetype 键出域=加载致命);流派件只走局内随机渠道。
|
||||
# 🔴 层级纪律(任务书红线 2):局外树只放全局规则件——effects 禁流派标签(relic 特性永不入树,
|
||||
# archetype 键出域=加载致命);规则改写型特性只走局内随机渠道。
|
||||
# A/B 只放规则面(定稿 1.3——全树互斥面 ≤10-15% 首期 4 组);两侧「不同强非强弱」MC 验差 <~3pp(T10)。
|
||||
# 彩蛋 ≤3(定稿 1.4——点满某脉某排免费觉醒;发现率 <5% 改灰色预告——T10 追认单呈报)。
|
||||
class_name MetaTreeTable
|
||||
@@ -76,9 +76,9 @@ func validate() -> Array:
|
||||
for ek in fx.keys():
|
||||
if not (STAT_KEYS.has(String(ek)) or RULE_KEYS.has(String(ek))):
|
||||
errs.append({"category": "zero_flat", "message": "%s effects 键出域(四线/rule 词表封闭): %s" % [nid, String(ek)]})
|
||||
# 🔴 层级纪律:局外树禁流派件(archetype 键出域=加载致命)
|
||||
# 🔴 层级纪律:局外树禁规则改写型特性(archetype 键出域=加载致命)
|
||||
if fx.has("archetype"):
|
||||
errs.append({"category": "load_bearing", "message": "%s effects 含 archetype(🔴 层级纪律——流派件禁入局外树)" % nid})
|
||||
errs.append({"category": "load_bearing", "message": "%s effects 含 archetype(🔴 层级纪律——特性禁入局外树)" % nid})
|
||||
# A/B 互斥对结构:fork 行必带 fork_group+side;同组恰 a/b 各一
|
||||
if kind == "fork":
|
||||
var fg := String(row.get("fork_group", ""))
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||||
# Validation Question: 七核心流派各 ≥3 件入局内随机渠道后,标签+档位激活引擎能否机械判「成型」、
|
||||
# 机制件带能否挂进令牌池稀有/罕见档随机投放(P0——迭代 12 双层 BD 实施批 T1)
|
||||
# 规则改写型特性带能否挂进令牌池稀有/罕见档随机投放(P0——迭代 12 双层 BD 实施批 T1)
|
||||
# Date: 2026-10-04(双层 BD 实施批 T1——任务书五裁定稿;设计权威 双层BD体系-整合定稿-2026-10-03 v3)
|
||||
# 数据配置 RelicTable schema(双层BD/机制件 回填 owner 批末落文;行 = Dictionary 键 relic_id,Rule 4 豁免
|
||||
# 概念指路:本表的规则改写型特性,与 adventure.tres 的属性加成型特性,同属一个对象——
|
||||
# 「特性」(一次冒险内角色自身得到的提升)。定义见 design/gdd/systems/冒险循环/特性.md。
|
||||
# 两者是它的形态枚举(form = rule / stat),不是两个系统;本表承载 rule 形态的逐项定义。
|
||||
# (2026-10-05 命名统一:旧称「流派件」→ 规则改写型特性;表名与 relic_id 沿用历史命名,
|
||||
# 与统一词族对齐归后续批次——见 06-待办清单「命名统一」条目。)
|
||||
# 数据配置 RelicTable schema(特性·规则改写型定义表;行 = Dictionary 键 relic_id,Rule 4 豁免
|
||||
# 定义表——AuxItemTable 先例)。
|
||||
# 行字段:relic_id 主键 / display_name / rarity ∈ {common, rare, rarest}(对齐令牌池三档命名——
|
||||
# 投放档映射:common/rare→稀有令牌档、rarest→罕见令牌档;relic 令牌永不入普通档=「挂稀有/罕见档」
|
||||
@@ -12,7 +17,7 @@
|
||||
# 仅校验键域不禁纯增益(专项论证件以 positive_only 批注登记,人工清单呈报)。
|
||||
# 档位激活(整合定稿 设计工具 1——以撒套装/小骨铭文):同标签计数 ≥2→档一(流派核心规则)/≥4→档二
|
||||
# (完全体);散件单体保底=每件效果独立生效,档位只做质变(反例 B-2)——引擎纯函数 RelicsEngine。
|
||||
# 🔴 层级纪律(任务书红线 2):流派件只走局内随机渠道(三选一/商店/格面)——本表行永不入同调位
|
||||
# 🔴 层级纪律(任务书红线 2):规则改写型特性只走局内随机渠道(三选一/商店/格面)——本表行永不入同调位
|
||||
# (aux_items 表)/局外树(T8 节点表);扫雷触发点铁律:每流派 ≥1 行 hook ∈ MINE_HOOKS(加载校验,
|
||||
# 违反=红线①触碰面)。
|
||||
class_name RelicTable
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
# 现价公式 = base_price + price_level_bonus(关卡) + price_increment × 该商品已购档数(已购档数在 冒险结构)。
|
||||
# price_level_bonus = 关级定价加值行(level_index 连续从 1 递增)。
|
||||
# pool_shelf = 共享池货架行(M-4 迭代 11 第②批 T1——任务书 v1.3 P1 共享池/P4 ceil):键 kind_id 词表
|
||||
# 封闭 = 四切边后种(SHELF_KINDS:attack/max_hp/armor/ap——GP 袋负交易切边、机制件三轴 doctrine 切边);
|
||||
# 封闭 = 四切边后种(SHELF_KINDS:attack/max_hp/armor/ap——GP 袋负交易切边、规则改写型特性三轴 doctrine 切边);
|
||||
# 库存=上限即库存(账本在 冒险结构 _bonus_taken 单点共享,行族不记库存);price_a/price_b = 乘法价格
|
||||
# 因子(公式 ceil(base × b^(关序−1) × A^(本次进店已购次数)),provisional 投值——P5 甲研究拍板后置追认)。
|
||||
# products 行族 + 加法定价随 legacy 模式(shop=off 对照承载)保留,退役归 off 锚换代批。
|
||||
|
||||
@@ -5,27 +5,27 @@
|
||||
[resource]
|
||||
script = ExtResource("1")
|
||||
clear_heal_pct = 20
|
||||
bonus_candidate_count = 3
|
||||
token_attack_common = 18
|
||||
token_attack_rare = 5
|
||||
token_max_hp_common = 17
|
||||
token_max_hp_rare = 5
|
||||
token_armor_common = 17
|
||||
token_armor_rare = 5
|
||||
token_gp_common = 18
|
||||
token_gp_rare = 5
|
||||
token_heal_rare = 5
|
||||
token_ap_rarest = 3
|
||||
bonus_attack_flat = 1
|
||||
bonus_attack_flat_large = 2
|
||||
bonus_max_hp_flat = 5
|
||||
bonus_max_hp_flat_large = 10
|
||||
bonus_armor_flat = 1
|
||||
bonus_armor_flat_large = 2
|
||||
bonus_gp_amount = 20
|
||||
bonus_gp_amount_large = 50
|
||||
bonus_heal_flat = 6
|
||||
bonus_ap_flat = 1
|
||||
feature_candidate_count = 3
|
||||
feature_quota_attack_common = 18
|
||||
feature_quota_attack_rare = 5
|
||||
feature_quota_max_hp_common = 17
|
||||
feature_quota_max_hp_rare = 5
|
||||
feature_quota_armor_common = 17
|
||||
feature_quota_armor_rare = 5
|
||||
feature_quota_gp_common = 18
|
||||
feature_quota_gp_rare = 5
|
||||
feature_quota_heal_rare = 5
|
||||
feature_quota_ap_rarest = 3
|
||||
feature_value_attack_common = 1
|
||||
feature_value_attack_rare = 2
|
||||
feature_value_max_hp_common = 5
|
||||
feature_value_max_hp_rare = 10
|
||||
feature_value_armor_common = 1
|
||||
feature_value_armor_rare = 2
|
||||
feature_value_gp_common = 20
|
||||
feature_value_gp_rare = 50
|
||||
feature_value_heal_rare = 6
|
||||
feature_value_ap_rarest = 1
|
||||
|
||||
; TP0 令牌池换代(2026-10-03,node-reward v2.2 追认 b 落地):三选一池 = 固定配额令牌池——
|
||||
; 普通 70/稀有 25/罕见 3 = 98 张(罕见档原列「道具件 2」随 aux_item 池种退役收窄——台账自决披露项);
|
||||
|
||||
@@ -411,5 +411,5 @@ rows = [{
|
||||
; ≥ 4×(row−1));锻造脉 3 节点收编 forge_levels(钥石付价=现行迁移零痛);钥石脉=工坊解锁收编
|
||||
; (free 迁移点亮)+刷新升级移植;同调脉 socket 3(钥石=规则面首站)+Fork 4 对(A/B 集中同调脉
|
||||
; 营地免费切换——effects 首期两 rule 键真实接线余组 stat 面 provisional);彩蛋 1(锻造满排觉醒)。
|
||||
; 🔴 层级纪律:局外树只放全局规则件——零 archetype 键(schema 校验强制);流派件只走局内随机渠道。
|
||||
; 🔴 层级纪律:局外树只放全局规则件——零 archetype 键(schema 校验强制);规则改写型特性只走局内随机渠道。
|
||||
; 数值全 provisional 归 M-4 数值批;A/B 两侧差 <~3pp 验收=T10 MC。
|
||||
@@ -260,15 +260,15 @@ rows = [{
|
||||
}
|
||||
}]
|
||||
|
||||
; 双层 BD 实施批(2026-10-04):机制件表——行 = 流派件定义
|
||||
; 双层 BD 实施批(2026-10-04):规则改写型特性表——行 = 特性定义
|
||||
; (relic_id/display_name/rarity/archetype/hook/effects)。
|
||||
; T2 魔法流四件(整合定稿 §2.3 S1):奥术余烬〔普通·rider+1 必中附加〕/魔网织者〔稀有·magic vs
|
||||
; magic 克制罚修正〕/湛蓝誓约〔稀有·magic vs heavy 克制加成〕/魔能共鸣〔罕见锚点·rider+2+每战首次
|
||||
; 开格奥术矢——「每关首次」字面落地为「每战首次」台账披露待追认〕;magic 档一(≥2 件)rider+1 /
|
||||
; 档二(≥4 件)rider 可暴击——引擎 tiers_for 承载。T3-T6 逐流派续填(flag 4/pierce 4/normal 4/
|
||||
; dig 4/charge 3/devour 4——整合定稿 §2.3 七流派件面)。
|
||||
; dig 4/charge 3/devour 4——整合定稿 §2.3 七流派的件面)。
|
||||
; 稀有度→投放档映射:common/rare → 稀有令牌档、rarest → 罕见令牌档(relic 永不入普通令牌档
|
||||
; ——「机制件带挂稀有/罕见档」追认 b 接线口径,普通档 70 张纯数值维持)。
|
||||
; 🔴 层级纪律:本表行永不入同调位(aux_items)/局外树(T8 节点表)——流派件只走局内随机渠道。
|
||||
; ——「规则改写型特性带挂稀有/罕见档」追认 b 接线口径,普通档 70 张纯数值维持)。
|
||||
; 🔴 层级纪律:本表行永不入同调位(aux_items)/局外树(T8 节点表)——规则改写型特性只走局内随机渠道。
|
||||
; 数值全 provisional 归 M-4 数值批;effects 键白名单封闭(零裸 flat 同族护栏)。
|
||||
|
||||
@@ -94,7 +94,7 @@ price_b = 1.1
|
||||
;(用户拍板骨架先行、数值整体后置,行值归 难度曲线与Boss)。
|
||||
; GP 商店房重构批(M-4 迭代 11 第②批 T1,2026-10-03——任务书 v1.3 全裁 P1 共享池/P4 ceil/P5 甲):
|
||||
; pool_shelf 行族 = 共享池货架(kind_id 词表封闭四切边后种 attack/max_hp/armor/ap——GP 袋负交易切边、
|
||||
; 机制件三轴 doctrine 切边;库存=上限即库存,账本在 冒险结构 _bonus_taken 单点共享,行族不记库存);
|
||||
; 规则改写型特性三轴 doctrine 切边;库存=上限即库存,账本在 冒险结构 _bonus_taken 单点共享,行族不记库存);
|
||||
; 价格公式换代(pool 模式)= ceil(base_price × b^(关序−1) × A^(本次进店已购次数)),price_a=1.8/price_b=1.1
|
||||
; provisional 投值(零人工令改 provisional+后置追认,原 P5 甲研究拍板后置);products 行族 + 加法定价
|
||||
; 随 legacy 模式(shop=off 对照承载)保留不退役,退役归 off 锚换代批。货架行值全部 provisional 归
|
||||
|
||||
@@ -131,11 +131,11 @@ static func bonus_result_text(result: Dictionary) -> String:
|
||||
return "已选择:%s\n其余选项已丢弃(不可反悔)" % name
|
||||
|
||||
|
||||
# 流派件卡片文案(迭代 12 T1;2026-10-04 呈现补强——第三行=hook 效果摘要,用户反馈「不知道件是
|
||||
# 特性卡片文案(迭代 12 T1;2026-10-04 呈现补强——第三行=hook 效果摘要,用户反馈「不知道件是
|
||||
# 干嘛的」缺口承载;摘要=静态映射表 provisional 文案归代拍板白名单「件文案微调」)
|
||||
static func relic_card_text(row: Dictionary) -> String:
|
||||
if row.is_empty() or String(row.get("relic_id", "")) == "":
|
||||
return "流派件\n???"
|
||||
return "特性\n???"
|
||||
var arch_names := {"magic": "魔法", "pierce": "穿刺", "normal": "普攻", "dig": "开格",
|
||||
"flag": "标旗", "charge": "蓄力", "devour": "吞噬"}
|
||||
var arch := String(arch_names.get(String(row.get("archetype", "")), "流派"))
|
||||
@@ -167,7 +167,7 @@ static func relic_card_text(row: Dictionary) -> String:
|
||||
var summary := String(summaries.get(String(row.get("hook", "")), ""))
|
||||
if summary != "":
|
||||
return "%s · %s\n%s" % [String(row.get("display_name", row.get("relic_id", ""))), arch, summary]
|
||||
return "流派件 · %s\n%s" % [arch, String(row.get("display_name", row.get("relic_id", "")))]
|
||||
return "特性 · %s\n%s" % [arch, String(row.get("display_name", row.get("relic_id", "")))]
|
||||
|
||||
|
||||
# Boss 胜利战斗总结结算行(settlement-summary v1.1——钥石增量行;组合根拼 GP 行后追加)
|
||||
|
||||
@@ -127,9 +127,9 @@ func _bonus_card_texts(candidates: Array, aux_detail: Array = []) -> Array:
|
||||
elif kind == "aux_item":
|
||||
var iid := String(aux_detail[aux_i]) if aux_i < aux_detail.size() else ""
|
||||
aux_i += 1
|
||||
text = Narrator.bonus_card_text(kind, tier, int(db.adventure.bonus_value(kind, tier)), _aux_card_line(iid))
|
||||
text = Narrator.bonus_card_text(kind, tier, int(db.adventure.feature_value(kind, tier)), _aux_card_line(iid))
|
||||
else:
|
||||
text = Narrator.bonus_card_text(kind, tier, int(db.adventure.bonus_value(kind, tier)))
|
||||
text = Narrator.bonus_card_text(kind, tier, int(db.adventure.feature_value(kind, tier)))
|
||||
out.append({"id": cid, "text": text})
|
||||
return out
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ extends RefCounted
|
||||
# HP/状态效果单投喂 B 区站桩(原 B/C 双投喂为重复展示——信息归属拍板单一展示面原则)
|
||||
static func refresh(stage: BattleStageView, info: HeroInfoPanelView, ap_bar: ApBarView,
|
||||
settlement, runner, level_active: bool, db, refresh_remaining: int) -> void:
|
||||
# 本关强化列表(v3.5 迭代 9 卡⑫ 2026-09-30——runner 统一加算区投影:商店购买与关卡大奖励
|
||||
# 特性列表(v3.5 迭代 9 卡⑫ 2026-09-30——runner 统一加算区投影:商店购买与关卡大奖励
|
||||
# 共账本〔level_runner bonus{atk,max_hp,armor_class}〕;空加算=整节隐藏〔视图内空态纪律〕。
|
||||
# 呈现只读投影零核心触碰;行文格式=代拍板白名单项)
|
||||
if runner != null and level_active:
|
||||
@@ -34,7 +34,7 @@ static func refresh(stage: BattleStageView, info: HeroInfoPanelView, ap_bar: ApB
|
||||
info.set_level_bonuses(lines)
|
||||
else:
|
||||
info.set_level_bonuses([])
|
||||
# 流派件持有投影(迭代 12 呈现补齐 2026-10-04——用户反馈「局内奖励选了什么看不到」:
|
||||
# 特性持有投影(迭代 12 呈现补齐 2026-10-04——用户反馈「局内奖励选了什么看不到」:
|
||||
# 逐流派聚合行+成型档位;常驻可读+空态隐藏。档位求值=RelicsEngine 纯函数直调)
|
||||
if runner != null and level_active:
|
||||
info.set_relic_holdings(relic_holdings_lines(db, runner.relics_held()))
|
||||
@@ -46,7 +46,7 @@ static func refresh(stage: BattleStageView, info: HeroInfoPanelView, ap_bar: ApB
|
||||
return
|
||||
var s: Dictionary = settlement.presentation_snapshot()
|
||||
# 地形变异常驻角标投影(全局作用域变异首发批 2026-10-04——板级变异快照 → 文案行;
|
||||
# 空态隐藏=流派件段先例;战斗全程常驻防中局遗忘)
|
||||
# 空态隐藏=特性段先例;战斗全程常驻防中局遗忘)
|
||||
info.set_board_variants(board_variant_lines(db, s.get("board_variants", [])))
|
||||
var hero: Dictionary = s.hero
|
||||
if hero.is_empty() or not bool(hero.get("alive", false)):
|
||||
@@ -93,7 +93,7 @@ static func _refresh_economy(ap_bar: ApBarView, s: Dictionary, db, refresh_remai
|
||||
ap_bar.set_stop_enabled(bool(s.hero.get("alive", false)) and digging)
|
||||
|
||||
|
||||
# 流派件持有聚合文案(迭代 12 呈现补齐——战斗 C 区与关卡选择页两处共用;空持有=空数组)
|
||||
# 特性持有聚合文案(迭代 12 呈现补齐——战斗 C 区与关卡选择页两处共用;空持有=空数组)
|
||||
static func relic_holdings_lines(db, held: Array) -> Array[String]:
|
||||
var rlines: Array[String] = []
|
||||
if db == null or db.relics == null or (db.relics.rows as Array).is_empty() or held.is_empty():
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||||
# 实现 GDD:design/ux/battle.md(C 区角色信息 240×548——2026-09-26 信息归属拍板精简:
|
||||
# 攻击(+修正来源角标)/护甲 AC 数据框 + 魔法道具槽(预留)+ 本关强化列表(预留)。
|
||||
# 攻击(+修正来源角标)/护甲 AC 数据框 + 魔法道具槽(预留)+ 特性列表(预留)。
|
||||
# HP 条/立绘占位/状态效果槽/RAP 池/GP/钥石退役——HP 与状态唯一展示面 = B 区站桩(同一数据
|
||||
# hud_presenter 双投喂 B/C 两区的重复展示);RAP 迁 D 区 AP 条(贴弃图刷新消费口);
|
||||
# GP(中循环)/钥石(大循环)迁出战斗屏)。
|
||||
@@ -19,9 +19,9 @@ var item_slots: HBoxContainer # 魔法道具槽(迭代 7 T4 接
|
||||
var _slot_panels: Array = [] # 槽 PanelContainer 引用(选中高亮/置灰重刷)
|
||||
var _selected_handle := 0 # 选中态(0=无;组合根回写维持单源)
|
||||
var _slot_handles: Array = [] # 槽位→handle 映射(set_aux_inventory 刷新)
|
||||
var _bonus_section: VBoxContainer # 本关强化(预留——空态隐藏,接线归大奖励/锻造呈现批)
|
||||
var _bonus_section: VBoxContainer # 特性(预留——空态隐藏,接线归大奖励/锻造呈现批)
|
||||
var _bonus_list: VBoxContainer
|
||||
var _relic_section: VBoxContainer # 流派件持有段(迭代 12 呈现补齐——空态隐藏)
|
||||
var _relic_section: VBoxContainer # 特性持有段(迭代 12 呈现补齐——空态隐藏)
|
||||
var _relic_list: VBoxContainer
|
||||
var _board_variant_section: VBoxContainer # 地形变异常驻角标(全局作用域变异首发批——空态隐藏)
|
||||
var _board_variant_list: VBoxContainer
|
||||
@@ -70,19 +70,19 @@ func _init() -> void:
|
||||
item_slots.add_child(slot)
|
||||
_slot_panels.append(slot)
|
||||
|
||||
# 流派件持有段(迭代 12 呈现补齐 2026-10-04——三选一流派件兑付后常驻可读:逐流派聚合行+成型档位;
|
||||
# 特性持有段(迭代 12 呈现补齐 2026-10-04——三选一特性兑付后常驻可读:逐流派聚合行+成型档位;
|
||||
# 空态整节隐藏。用户试玩反馈「局内奖励选了什么看不到」缺口承载;2026-10-04 二次反馈上移——
|
||||
# 构筑核心信息优先级高于临时强化,且防 C 区下部裁切不可见)
|
||||
_relic_section = VBoxContainer.new()
|
||||
_relic_section.add_theme_constant_override("separation", 4)
|
||||
_relic_section.visible = false
|
||||
col.add_child(_relic_section)
|
||||
_relic_section.add_child(UiKit.label("流派件", 16, true))
|
||||
_relic_section.add_child(UiKit.label("特性", 16, true))
|
||||
_relic_list = VBoxContainer.new()
|
||||
_relic_list.add_theme_constant_override("separation", 2)
|
||||
_relic_section.add_child(_relic_list)
|
||||
# 地形变异常驻角标(全局作用域变异首发批 2026-10-04——Boss 图整图型战斗全程可见防中局遗忘;
|
||||
# 空态整节隐藏=流派件段先例;摆位/文案 provisional 归 HUD 框架批与本地化批)
|
||||
# 空态整节隐藏=特性段先例;摆位/文案 provisional 归 HUD 框架批与本地化批)
|
||||
_board_variant_section = VBoxContainer.new()
|
||||
_board_variant_section.add_theme_constant_override("separation", 4)
|
||||
_board_variant_section.visible = false
|
||||
@@ -91,13 +91,13 @@ func _init() -> void:
|
||||
_board_variant_list = VBoxContainer.new()
|
||||
_board_variant_list.add_theme_constant_override("separation", 2)
|
||||
_board_variant_section.add_child(_board_variant_list)
|
||||
# 本关强化(预留):锻造/大奖励/关卡奖励节点的属性提升——中循环数据因改变战斗数学准入;
|
||||
# 特性(预留):锻造/大奖励/关卡奖励节点的属性提升——中循环数据因改变战斗数学准入;
|
||||
# 与战斗内状态效果(B 区站桩,随战斗消散)分区,防「战斗结束被清」误读;空态整节隐藏
|
||||
_bonus_section = VBoxContainer.new()
|
||||
_bonus_section.add_theme_constant_override("separation", 4)
|
||||
_bonus_section.visible = false
|
||||
col.add_child(_bonus_section)
|
||||
_bonus_section.add_child(UiKit.label("本关强化", 16, true))
|
||||
_bonus_section.add_child(UiKit.label("特性", 16, true))
|
||||
_bonus_list = VBoxContainer.new()
|
||||
_bonus_list.add_theme_constant_override("separation", 2)
|
||||
_bonus_section.add_child(_bonus_list)
|
||||
@@ -113,7 +113,7 @@ func set_armor(ac: int) -> void:
|
||||
_armor_label.text = "护甲 AC %d" % ac
|
||||
|
||||
|
||||
# 流派件持有段(迭代 12 呈现补齐):lines = 聚合文案行(「魔法 ×2 · 档一」式)——空数组 = 整节隐藏
|
||||
# 特性持有段(迭代 12 呈现补齐):lines = 聚合文案行(「魔法 ×2 · 档一」式)——空数组 = 整节隐藏
|
||||
func set_relic_holdings(lines: Array) -> void:
|
||||
for c2 in _relic_list.get_children():
|
||||
_relic_list.remove_child(c2)
|
||||
@@ -135,7 +135,7 @@ func set_board_variants(lines: Array) -> void:
|
||||
_board_variant_section.visible = not lines.is_empty()
|
||||
|
||||
|
||||
# 本关强化列表(预留接线面):lines = 文案行数组(如「锻造 +2 攻击」)——空数组 = 整节隐藏
|
||||
# 特性列表(预留接线面):lines = 文案行数组(如「锻造 +2 攻击」)——空数组 = 整节隐藏
|
||||
func set_level_bonuses(lines: Array) -> void:
|
||||
for c in _bonus_list.get_children():
|
||||
_bonus_list.remove_child(c)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
# 悬停预承诺(描边加粗+指针)后点击提交;press_candidate 探针入口改走图上命中同路径
|
||||
# ③ 放弃冒险二次确认(布局决策 3)——首击转确认态(文案+危险红脉冲约 3 秒超时回落),二击提交
|
||||
# ④ 顶栏语境:关卡名(level_row.display_name)+ GP 常驻徽章(2026-09-26 二轮拍板去向落地面)
|
||||
# ⑤ 底部状态栏(布局决策 4):生命/属性/本关加成三组常读(零加成隐藏),放弃按钮右端异位
|
||||
# ⑤ 底部状态栏(布局决策 4):生命/属性/特性三组常读(零加成隐藏),放弃按钮右端异位
|
||||
# 关卡画面(独立屏,Level Map Screen——2026-09-28 形态升格批 M-2 迭代 3 T2:原 RouteOverlay 模态
|
||||
# 覆盖层升格独立屏,spec level-map.md 形态章节同批改写):全屏不透明独占呈现——激活期战斗屏宿主
|
||||
# 由组合根整体隐藏(非暗幕半透、零透出)。零自动推进的玩家停点语义不变:唯一前进通道 =
|
||||
@@ -56,7 +56,7 @@ var _hp_bar: Control
|
||||
var _attr_value: Label
|
||||
var _bonus_row: HBoxContainer
|
||||
var _bonus_value: Label
|
||||
var _relic_value: Label # 流派件持有行(迭代 12 呈现补齐——组合根投喂聚合文案)
|
||||
var _relic_value: Label # 特性持有行(迭代 12 呈现补齐——组合根投喂聚合文案)
|
||||
var _cand_ids: Array[int] = [] # 本停点候选 id 集(图上命中合法集)
|
||||
var _content_size := Vector2(620, 240) # 图内容包络(open_choices 按图拟合——画布 min 尺寸随它)
|
||||
var _hover_id := -1 # 悬停预承诺候选(-1 = 无)
|
||||
@@ -118,13 +118,13 @@ func _init() -> void:
|
||||
_canvas.draw.connect(_draw_graph.bind(_canvas))
|
||||
_canvas.gui_input.connect(_on_canvas_input)
|
||||
box.add_child(_canvas)
|
||||
# 底部状态栏(布局决策 4:生命/属性/本关加成三组 + 放弃按钮右端异位)
|
||||
# 底部状态栏(布局决策 4:生命/属性/特性三组 + 放弃按钮右端异位)
|
||||
var bottom := HBoxContainer.new()
|
||||
bottom.add_theme_constant_override("separation", 10)
|
||||
box.add_child(bottom)
|
||||
bottom.add_child(_status_box("生命", true))
|
||||
bottom.add_child(_status_box("属性", false))
|
||||
# 本关加成框(零加成隐藏——spec 布局决策 4)
|
||||
# 特性框(零加成隐藏——spec 布局决策 4)
|
||||
_bonus_row = HBoxContainer.new()
|
||||
_bonus_row.add_theme_constant_override("separation", 10)
|
||||
var bonus_box := PanelContainer.new()
|
||||
@@ -132,11 +132,11 @@ func _init() -> void:
|
||||
_bonus_row.add_child(bonus_box)
|
||||
var bonus_inner := VBoxContainer.new()
|
||||
bonus_box.add_child(bonus_inner)
|
||||
var bonus_cap := UiKit.label("本关加成", 12, false, UiKit.WARM_SOFT)
|
||||
var bonus_cap := UiKit.label("特性", 12, false, UiKit.WARM_SOFT)
|
||||
bonus_inner.add_child(bonus_cap)
|
||||
_bonus_value = UiKit.label("", 15, true, UiKit.WARM)
|
||||
bonus_inner.add_child(_bonus_value)
|
||||
# 流派件持有行(迭代 12 呈现补齐 2026-10-04——用户反馈关卡选择页看不到局内奖励;组合根投喂)
|
||||
# 特性持有行(迭代 12 呈现补齐 2026-10-04——用户反馈关卡选择页看不到局内奖励;组合根投喂)
|
||||
_relic_value = UiKit.label("", 13, false, UiKit.WARM_SOFT)
|
||||
_relic_value.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
bonus_inner.add_child(_relic_value)
|
||||
@@ -189,7 +189,7 @@ func _draw_hp_bar(bar: Control) -> void:
|
||||
|
||||
|
||||
# 放弃入口可见性(组合根在冒险启动时开、默认关——语义对象 = 整局冒险)
|
||||
# 流派件持有投影(迭代 12 呈现补齐——组合根投喂聚合文案;空文案=行隐藏)
|
||||
# 特性持有投影(迭代 12 呈现补齐——组合根投喂聚合文案;空文案=行隐藏)
|
||||
func set_relic_holdings(text: String) -> void:
|
||||
_relic_value.text = text
|
||||
|
||||
@@ -324,7 +324,7 @@ func _refresh_status() -> void:
|
||||
if ac_bonus > 0:
|
||||
parts.append("AC +%d" % ac_bonus)
|
||||
_bonus_value.text = " · ".join(parts)
|
||||
# 流派件持有行可见性(与加成行并框——任一非空整框显示;文案归组合根 set_relic_holdings)
|
||||
# 特性持有行可见性(与加成行并框——任一非空整框显示;文案归组合根 set_relic_holdings)
|
||||
_bonus_row.visible = not parts.is_empty() or _relic_value.text != ""
|
||||
|
||||
|
||||
|
||||
@@ -42,8 +42,8 @@ func _initialize() -> void:
|
||||
var shop_mode := "off"
|
||||
if args.size() >= 6 and args[5] in ["off", "on"]:
|
||||
shop_mode = args[5]
|
||||
# 流派件/树分层开关(迭代 12 T7/T10——off=基线;formed=成型画像开局注入七流派各 2 件档一成型集
|
||||
# 〔测量面专用 params.relics_seed——真实局流派件只走局内随机渠道〕;ab_a/ab_b=Fork posture 两侧
|
||||
# 特性/树分层开关(迭代 12 T7/T10——off=基线;formed=成型画像开局注入七流派各 2 件档一成型集
|
||||
# 〔测量面专用 params.relics_seed——真实局规则改写型特性只走局内随机渠道〕;ab_a/ab_b=Fork posture 两侧
|
||||
# rule 键集——A/B 面两侧差 <~3pp 验收载体)
|
||||
var relic_mode := "off"
|
||||
if args.size() >= 7 and args[6] in ["off", "formed", "ab_a", "ab_b"]:
|
||||
|
||||
@@ -134,7 +134,7 @@ static func run_adventure(db, seed_val: int, atk_pct: int, hp_pct: int, collect_
|
||||
"log_path": "", "policy": policy, "refreshes": 0, "mine_hits": 0, "mine_dmg": 0,
|
||||
"visited_ids": [], "choices": 0, "last_battle_enemies": [],
|
||||
"summary": {}, "wallet_events": [], "encounter_max_hp_seq": [], "reward_events": [],
|
||||
"relic_mode": String(relic.get("mode", "off")), # 流派件分层开关(迭代 12 T7——off=316-f 通用竞争/on=成型画像优先捕捞 relic)
|
||||
"relic_mode": String(relic.get("mode", "off")), # 特性分层开关(迭代 12 T7——off=316-f 通用竞争/on=成型画像优先捕捞 relic)
|
||||
"shop_gp_seq": [], # 商店房到达余额序(逐关 1 次——GP 跨关延续验收取数面)
|
||||
"prng": _policy_rng(seed_val), "mine_slips": 0, "skip_digs": 0, "shop_buys": 0,
|
||||
"adv": true, # v3 档位行为开关(选路评分/失误注入/商店购买只挂冒险测量面——单关夹具保持旧语义零扰动)
|
||||
@@ -156,7 +156,7 @@ static func run_adventure(db, seed_val: int, atk_pct: int, hp_pct: int, collect_
|
||||
if not attune.is_empty():
|
||||
adv_params["attunement"] = attune.get("equipped", [])
|
||||
adv_params["attune_refresh_y"] = int(attune.get("refresh_y", 0))
|
||||
# 流派件注入(迭代 12 T7——formed 画像=开局注入七流派各 2 件档一成型集;测量面专用)
|
||||
# 特性注入(迭代 12 T7——formed 画像=开局注入七流派各 2 件档一成型集;测量面专用)
|
||||
if relic.has("seed_ids"):
|
||||
adv_params["relics_seed"] = relic.get("seed_ids", [])
|
||||
# 树规则键注入(迭代 12 T10——A/B 面读数载体:fork 激活侧 effects rule 键集透传)
|
||||
@@ -185,7 +185,7 @@ static func run_adventure(db, seed_val: int, atk_pct: int, hp_pct: int, collect_
|
||||
# 终局池读数(迭代 11 第②批 T5——摘要 additive 键 pool_stock:_settle 清账前快照,
|
||||
# 商店买走 vs 奖励领走 vs 枯竭的终局面;事后读 adr.pool_stock 会被收束清账重置=满库假象)
|
||||
st["pool_stock"] = (st.get("summary", {}).get("pool_stock", {}) as Dictionary).duplicate(true)
|
||||
st["relics"] = (st.get("summary", {}).get("relics", []) as Array).duplicate() # 流派件终局持有集(迭代 12 T1——摘要 additive 键清账前快照,同 pool_stock 模式)
|
||||
st["relics"] = (st.get("summary", {}).get("relics", []) as Array).duplicate() # 特性终局持有集(迭代 12 T1——摘要 additive 键清账前快照,同 pool_stock 模式)
|
||||
st.log_path = logger.log_path()
|
||||
if own_session:
|
||||
logger.close_session()
|
||||
@@ -268,7 +268,7 @@ static func _on_adventure_bonus(payload: Dictionary, st: Dictionary, adr) -> voi
|
||||
# 三选一确定性选件(TP0 316-f——1 级优先度=最稀有〔档位最高 rarest>rare>common〕、2 级=最左;
|
||||
# 候选并列同档取最左=稳定序保证。空候选/未知档位 = 回退最左防御口径。
|
||||
# 成型画像(迭代 12 T7——relic 模式 on:候选含 relic 令牌时优先在 relic 集内按 316-f 择一
|
||||
# 〔贪心捕捞→流派件入局→成型画像全流派覆盖——R3 乙单锚承载〕;off=relic 与数值件同规则竞争)
|
||||
# 〔贪心捕捞→特性入局→成型画像全流派覆盖——R3 乙单锚承载〕;off=relic 与属性加成型特性同规则竞争)
|
||||
static func _pick_token(candidates: Array, relic_mode: String = "off") -> Dictionary:
|
||||
var pool: Array = candidates
|
||||
if relic_mode == "on":
|
||||
|
||||
+25
-25
@@ -220,12 +220,12 @@ func _smoke_adventure_table() -> void:
|
||||
check(int(_db.adventure.tier_total(tier)) == int(_db.adventure.TIER_QUOTAS[tier]),
|
||||
"档位配额结构锚(v2.2 追认 b):%s = %d 张" % [tier, int(_db.adventure.TIER_QUOTAS[tier])])
|
||||
check(int(_db.adventure.deck_total()) == 98, "令牌池总量 = 98 张(普通 70/稀有 25/罕见 3——罕见档随道具件池种退役收窄)")
|
||||
check(int(_db.adventure.bonus_value("gp", "common")) == 20 and int(_db.adventure.bonus_value("gp", "rare")) == 50
|
||||
and int(_db.adventure.bonus_value("attack", "common")) == 1 and int(_db.adventure.bonus_value("attack", "rare")) == 2
|
||||
and int(_db.adventure.bonus_value("max_hp", "common")) == 5 and int(_db.adventure.bonus_value("max_hp", "rare")) == 10
|
||||
and int(_db.adventure.bonus_value("armor", "common")) == 1 and int(_db.adventure.bonus_value("armor", "rare")) == 2,
|
||||
check(int(_db.adventure.feature_value("gp", "common")) == 20 and int(_db.adventure.feature_value("gp", "rare")) == 50
|
||||
and int(_db.adventure.feature_value("attack", "common")) == 1 and int(_db.adventure.feature_value("attack", "rare")) == 2
|
||||
and int(_db.adventure.feature_value("max_hp", "common")) == 5 and int(_db.adventure.feature_value("max_hp", "rare")) == 10
|
||||
and int(_db.adventure.feature_value("armor", "common")) == 1 and int(_db.adventure.feature_value("armor", "rare")) == 2,
|
||||
"数值对(v2.2):小GP 20/大GP 50 · 小增伤 +1/大 +2 · 小生命 +5/大 +10 · 小护甲 +1/大 +2")
|
||||
check(int(_db.adventure.bonus_value("heal", "rare")) == 6 and int(_db.adventure.bonus_value("ap", "rarest")) == 1,
|
||||
check(int(_db.adventure.feature_value("heal", "rare")) == 6 and int(_db.adventure.feature_value("ap", "rarest")) == 1,
|
||||
"恢复件 +6 当即回血(新入池种类,rare 档)· AP +1(rarest 档)")
|
||||
check(_db.attunement_growth != null and int(_db.attunement_slot_cap()) == 3
|
||||
and Attunement.slots(_db, null) == 0,
|
||||
@@ -349,7 +349,7 @@ func _smoke_adventure() -> void:
|
||||
var cand_ok := picks.size() == 2
|
||||
var ks_gain_ok := picks.size() == 2
|
||||
var resolve_ok := level_resolves.size() == 2
|
||||
var max_flat := int(_db.adventure.bonus_max_hp_flat)
|
||||
var max_flat := int(_db.adventure.feature_value_max_hp_common)
|
||||
var heal_pct := int(_db.adventure.clear_heal_pct)
|
||||
var hp_acc := 0 # max_hp 件累加(回血封顶断言的生效上限推导——TP0 起按兑付令牌实值,大小档分别计)
|
||||
var ks_prefix := 0
|
||||
@@ -384,7 +384,7 @@ func _smoke_adventure() -> void:
|
||||
var r: Dictionary = level_resolves[i]
|
||||
var rk := String(r.get("picked", ""))
|
||||
var rt := String(r.get("tier", ""))
|
||||
if _smoke_find_token(p.get("candidates", []) as Array, rk, rt).is_empty() or int(r.get("value", -1)) != int(_db.adventure.bonus_value(rk, rt)):
|
||||
if _smoke_find_token(p.get("candidates", []) as Array, rk, rt).is_empty() or int(r.get("value", -1)) != int(_db.adventure.feature_value(rk, rt)):
|
||||
resolve_ok = false
|
||||
if rk == "max_hp":
|
||||
hp_acc += int(r.get("value", max_flat))
|
||||
@@ -397,7 +397,7 @@ func _smoke_adventure() -> void:
|
||||
var exp_base := maxi(1, int(round(float(int(_db.hero.max_hp)) * k)))
|
||||
# 模拟档 v3.4 商店贪心购血(数值修复批)合法抬升——上限窗口 = 基础 + 加算区 3 件 + 购血余量;
|
||||
# TP0 数值对后 max_hp 件有大生命 +10(rare 档)——上界按大件最坏构成 3×10+购血 15=+45(TP0 放宽)
|
||||
var hp_ceiling := maxi(1, int(round(float(int(_db.hero.max_hp) + 3 * int(_db.adventure.bonus_value("max_hp", "rare")) + 15) * k)))
|
||||
var hp_ceiling := maxi(1, int(round(float(int(_db.hero.max_hp) + 3 * int(_db.adventure.feature_value("max_hp", "rare")) + 15) * k)))
|
||||
var seq_ok := seq.size() > 0 and int(seq[0]) == exp_base
|
||||
for v in (seq as Array):
|
||||
if int(v) < exp_base or int(v) > hp_ceiling:
|
||||
@@ -592,22 +592,22 @@ func _smoke_adventure() -> void:
|
||||
a13.present_node_bonus(ncands13, ndraw.get("aux_detail", []) as Array)
|
||||
a13.present_node_bonus([{"kind": "gp", "tier": "common"}])
|
||||
var gp13 := int(a13.ledger.get("gp", 0))
|
||||
check(a13.apply_node_bonus("gp", "common") and int(a13.ledger.get("gp", 0)) == gp13 + int(_db.adventure.bonus_value("gp", "common")),
|
||||
"奖励节点 GP 件入账(钱包「奖励入账」收口——+%d)" % int(_db.adventure.bonus_value("gp", "common")))
|
||||
check(a13.apply_node_bonus("gp", "common") and int(a13.ledger.get("gp", 0)) == gp13 + int(_db.adventure.feature_value("gp", "common")),
|
||||
"奖励节点 GP 件入账(钱包「奖励入账」收口——+%d)" % int(_db.adventure.feature_value("gp", "common")))
|
||||
check(a13._node_bonus_pending.is_empty(), "节点停点态兑付后清零(恰一次语义同构)")
|
||||
var s10: Dictionary = a10.summary
|
||||
check(String(s10.get("result", "")) == "abandoned" and not bool(s10.get("cleared", true)),
|
||||
"放弃摘要:abandoned · 未打穿(已获大奖励不追回——同失败型结算)")
|
||||
|
||||
|
||||
# ---- 双层 BD 机制件基建冒烟(迭代 12 T1——relic_table/档位激活引擎/机制件带池接线)----
|
||||
# ---- 双层 BD 规则改写型特性基建冒烟(迭代 12 T1——relic_table/档位激活引擎/规则改写型特性带池接线)----
|
||||
|
||||
func _smoke_relics() -> void:
|
||||
print("--- 机制件基建(relic_table · 档位激活引擎 · 机制件带接线)---")
|
||||
print("--- 规则改写型特性基建(relic_table · 档位激活引擎 · 规则改写型特性带接线)---")
|
||||
# ① 现行表牌库构成:七流派 27 件全量入池——98 数值令牌+27 relic 令牌(批次一铺量完成)
|
||||
check(_db.relics != null and (_db.relics.rows as Array).size() == 27, "relic_table 已加载(七流派 27 件全量——批次一 T2-T6 铺量完成)")
|
||||
var a_r0 = load("res://core/adventure_runner.gd").new(_db, _fresh_rng(71))
|
||||
check(a_r0.start_adventure(71, {"first_script": true}), "机制件带场景:冒险启动(seed 71)")
|
||||
check(a_r0.start_adventure(71, {"first_script": true}), "规则改写型特性带场景:冒险启动(seed 71)")
|
||||
var relic_tokens := 0
|
||||
var rarest_tokens := 0
|
||||
for t in a_r0._bonus_deck:
|
||||
@@ -616,7 +616,7 @@ func _smoke_relics() -> void:
|
||||
if String((t as Dictionary).get("tier", "")) == "rarest":
|
||||
rarest_tokens += 1
|
||||
check(relic_tokens == 27 and rarest_tokens == 6 and a_r0._bonus_deck.size() == 125,
|
||||
"机制件带入池:27 件(rare 档 21 + rarest 锚点 6)——牌库 98+27=125")
|
||||
"规则改写型特性带入池:27 件(rare 档 21 + rarest 锚点 6)——牌库 98+27=125")
|
||||
check(_db.relics.validate().is_empty(), "relic_table.validate 零违例(有行流派扫雷端铁律——magic first_dig_spell 在案)")
|
||||
# ② 档位激活引擎(纯函数直测——构造表 4 件 magic + 1 件 flag + 1 件 rarest 锚点)
|
||||
var rt := RelicTable.new()
|
||||
@@ -638,17 +638,17 @@ func _smoke_relics() -> void:
|
||||
var hooks := RelicsEngine.hooks_for(["m1", "f1"], rt)
|
||||
check(hooks.size() == 2 and String(hooks[0].get("hook", "")) == "hero_attack_rider",
|
||||
"挂点投影:表序稳定(同集合→同投影)")
|
||||
# ③ 机制件带接线(临时表注入——relic 令牌入牌库/兑付入持有集/踢池/断点往返;测试尾还原现行表)
|
||||
# ③ 规则改写型特性带接线(临时表注入——relic 令牌入牌库/兑付入持有集/踢池/断点往返;测试尾还原现行表)
|
||||
var live_rows: RelicTable = _db.relics
|
||||
_db.relics = rt
|
||||
var a_r = load("res://core/adventure_runner.gd").new(_db, _fresh_rng(72))
|
||||
check(a_r.start_adventure(72, {"first_script": true}), "机制件带场景:冒险启动(seed 72——注入 5 行临时表)")
|
||||
check(a_r.start_adventure(72, {"first_script": true}), "规则改写型特性带场景:冒险启动(seed 72——注入 5 行临时表)")
|
||||
var deck_relic := 0
|
||||
for t in a_r._bonus_deck:
|
||||
if String((t as Dictionary).get("kind", "")) == "relic":
|
||||
deck_relic += 1
|
||||
check(deck_relic == 5 and a_r._bonus_deck.size() == 103,
|
||||
"机制件带入池:5 行 relic 每件 1 张(common/rare→稀有档 rarest→罕见档)——牌库 98+5=103")
|
||||
"规则改写型特性带入池:5 行 relic 每件 1 张(common/rare→稀有档 rarest→罕见档)——牌库 98+5=103")
|
||||
var relic_seen: Dictionary = {}
|
||||
for i in 60:
|
||||
for t in a_r._draw_bonus_candidates():
|
||||
@@ -726,13 +726,13 @@ func _smoke_relics() -> void:
|
||||
"深挖钻头=开掘 +1 AP/每 4 格深层产出(R4 甲非信息税对价)· 蓄力三件=层值 1/减伤 1/层/满层 ×2")
|
||||
check(orch.action_economy.relic_ap_carry and orch.action_economy.relic_dig_extra == 1,
|
||||
"蓄力/钻头 action_economy 注入(ap_carry 改写停手转存 + 付费开掘对价注入——关着 false/0 零扰动)")
|
||||
# ⑦c 流派件持有呈现段(2026-10-04 用户反馈补齐——C 区「流派件」节:聚合行+成型档位;空态隐藏)
|
||||
# ⑦c 特性持有呈现段(2026-10-04 用户反馈补齐——C 区「特性」节:聚合行+成型档位;空态隐藏)
|
||||
var panel = load("res://presentation/views/hero_info_panel_view.gd").new()
|
||||
panel.set_relic_holdings([])
|
||||
check(not panel._relic_section.visible, "流派件段空态隐藏(视图空态纪律同本关强化段)")
|
||||
check(not panel._relic_section.visible, "特性段空态隐藏(视图空态纪律同特性段)")
|
||||
panel.set_relic_holdings(["魔法 ×2 · 档一", "开格 ×1 · 散件"])
|
||||
check(panel._relic_section.visible and panel._relic_list.get_child_count() == 2,
|
||||
"流派件段持有呈现(聚合行+成型档位常驻可读——「局内奖励选了什么看不到」缺口承载)")
|
||||
"特性段持有呈现(聚合行+成型档位常驻可读——「局内奖励选了什么看不到」缺口承载)")
|
||||
# ⑦b 深挖钻头付费开掘回归(2026-10-04 试玩缺陷修复——对价挂付费侧):AP=1 降级照常开格
|
||||
# (用户实测「AP=1 无法开格只能标旗」的回归闸);AP=2 付全价积付费计数(深层产出配额取数面)。
|
||||
var ae_dd = load("res://core/action_economy.gd").new(_db)
|
||||
@@ -3773,8 +3773,8 @@ func _smoke_shop_pool() -> void:
|
||||
var val0: int = int(a8.bonus.get(String(val_map[kind]), -999))
|
||||
check(r8.buy_pool_item(kind), "购买受理(pool 口——%s|%s)" % [kind, tier])
|
||||
check(int(r8.gp) == gp0 - int(buy_c.get("price", 0)), "钱包扣现价(%d → %d)" % [gp0, int(r8.gp)])
|
||||
check(int(a8.bonus.get(String(val_map[kind]), -999)) == val0 + int(_db.adventure.bonus_value(kind, tier)),
|
||||
"加算区 +令牌档位件值(池件=奖励件本体——%s|%s %+d)" % [kind, tier, int(_db.adventure.bonus_value(kind, tier))])
|
||||
check(int(a8.bonus.get(String(val_map[kind]), -999)) == val0 + int(_db.adventure.feature_value(kind, tier)),
|
||||
"加算区 +令牌档位件值(池件=奖励件本体——%s|%s %+d)" % [kind, tier, int(_db.adventure.feature_value(kind, tier))])
|
||||
check(int(a8._bonus_taken.get(kind, 0)) == taken0 + 1, "共享池账本 -1(跨渠道单点——taken %d → %d)" % [taken0, int(a8._bonus_taken.get(kind, 0))])
|
||||
# A 链:同visit 第二购现价 = ceil(base×b^(l2−1)×A^1)(货架已全重抽——新卡新价同公式)
|
||||
var second: Dictionary = {}
|
||||
@@ -3788,7 +3788,7 @@ func _smoke_shop_pool() -> void:
|
||||
check(int(second.get("price", -1)) == expect_p2,
|
||||
"A 链爬价 = ceil(base×b^(关序−1)×A^1)(进店第 2 购——%d)" % expect_p2)
|
||||
check(r8.buy_pool_item(String(second.get("kind_id", ""))), "同 visit 第二购受理(A 链软闸在价不在限)")
|
||||
# ④ 切边零入店(白-box 重抽 40 次——GP 袋/机制件永不在架;重抽消费 shop_draw 签,场景尾不回写主时间线)
|
||||
# ④ 切边零入店(白-box 重抽 40 次——GP 袋/规则改写型特性永不在架;重抽消费 shop_draw 签,场景尾不回写主时间线)
|
||||
var cut_seen := false
|
||||
for i in 40:
|
||||
r8._shop_draw_shelf()
|
||||
@@ -3839,7 +3839,7 @@ func _smoke_shop_pool() -> void:
|
||||
for k in ps.keys():
|
||||
var quota := 0
|
||||
for tier in _db.adventure.TIERS:
|
||||
quota += int(_db.adventure.bonus_token_count(String(k), tier))
|
||||
quota += int(_db.adventure.feature_quota(String(k), tier))
|
||||
if int(ps[k]) < 0 or int(ps[k]) > quota:
|
||||
ps_ok = false
|
||||
check(ps_ok, "终局池余量在域 [0,配额](%s)" % str(ps))
|
||||
@@ -4430,7 +4430,7 @@ func _smoke_save() -> void:
|
||||
and int(bp.get("hero_hp", -1)) == 13, "断点七字段往返:关卡序号/节点位/生命")
|
||||
var bp_bonus: Dictionary = bp.get("bonus", {})
|
||||
check(int(bp_bonus.get("atk", -1)) == 2 and int(bp_bonus.get("max_hp", -1)) == 5
|
||||
and int(bp_bonus.get("armor_class", -1)) == 1, "断点七字段往返:本关加成区")
|
||||
and int(bp_bonus.get("armor_class", -1)) == 1, "断点七字段往返:属性加成区")
|
||||
check(int(bp.get("gp", -1)) == 17, "断点七字段往返:GP 钱包")
|
||||
var bp_shop: Dictionary = bp.get("shop_purchased", {})
|
||||
check(int(bp_shop.get("hp_small", -1)) == 2 and int(bp_shop.get("atk_small", -1)) == 1,
|
||||
|
||||
Reference in new issue
Block a user