奇物批T3+T4:relic_*→feat_*词族全换(feat_table.gd/feats.tres/feats_engine.gd三文件改名+.uid+feat_flags/feat_id/feat_row等全token+config_db注册键feats两端+entities.yaml换代注记——kind值relic/身份前缀relic:/relics存档键/摘要键按数据契约保留);T4渠道白名单过滤(_draw_curio_candidates(channel):通关渠道只出专长/节点渠道零专长——过滤式不拆池,TIER_QUOTAS锚零改动,devour货架保底随渠道定位退役,迁移保feat_id,pick_curio测试feat_id透传;冒烟773/0+run_all 16全绿+断点往返PASS)
This commit is contained in:
1 parent
8e2694de49
commit
6812ebbb73
24 files changed
+385
-384
No files matched your search
@@ -124,8 +124,8 @@ static func bonus_card_text(id: String, tier: String, value: int, treasure_line:
|
||||
# 三选一兑付反馈行(选中件效果 + 丢弃提示;tier 缺省普通档——旧载荷防御口径)
|
||||
static func bonus_result_text(result: Dictionary) -> String:
|
||||
var name := ""
|
||||
if String(result.get("picked", "")) == "relic" and String(result.get("relic_id", "")) != "":
|
||||
name = relic_card_text({"relic_id": String(result.get("relic_id", "")), "display_name": String(result.get("relic_name", "")), "archetype": String(result.get("relic_archetype", ""))}).replace("\n", " · ")
|
||||
if String(result.get("picked", "")) == "relic" and String(result.get("feat_id", "")) != "":
|
||||
name = feat_card_text({"feat_id": String(result.get("feat_id", "")), "display_name": String(result.get("feat_name", "")), "archetype": String(result.get("feat_archetype", ""))}).replace("\n", " · ")
|
||||
else:
|
||||
name = bonus_card_text(String(result.get("picked", "")), String(result.get("tier", "")), int(result.get("value", 0))).replace("\n", " · ")
|
||||
return "已选择:%s\n其余选项已丢弃(不可反悔)" % name
|
||||
@@ -133,8 +133,8 @@ static func bonus_result_text(result: Dictionary) -> String:
|
||||
|
||||
# 特性卡片文案(迭代 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", "")) == "":
|
||||
static func feat_card_text(row: Dictionary) -> String:
|
||||
if row.is_empty() or String(row.get("feat_id", "")) == "":
|
||||
return "特性\n???"
|
||||
var arch_names := {"magic": "魔法", "pierce": "穿刺", "normal": "普攻", "dig": "开格",
|
||||
"flag": "标旗", "charge": "蓄力", "devour": "吞噬"}
|
||||
@@ -166,8 +166,8 @@ 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 · %s\n%s" % [String(row.get("display_name", row.get("feat_id", ""))), arch, summary]
|
||||
return "特性 · %s\n%s" % [arch, String(row.get("display_name", row.get("feat_id", "")))]
|
||||
|
||||
|
||||
# Boss 胜利战斗总结结算行(settlement-summary v1.1——钥石增量行;组合根拼 GP 行后追加)
|
||||
@@ -176,7 +176,7 @@ static func bonus_keystone_line(payload: Dictionary) -> String:
|
||||
|
||||
|
||||
# 奖励节点三选一头部行(迭代 10 追加批——与通关三选一共享同池;node-reward.md v2)
|
||||
static func node_bonus_header() -> String:
|
||||
static func node_curio_header() -> String:
|
||||
return "关卡奖励点\n从提升池抽三选一(与通关三选一同池同权重同上限):\n选择一件带走:"
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||||
# 提升三选一与替换子交互控制器(迭代 13 T4/D4——二期家族① 自 main.gd 迁出;规范 1.1 单一职责):
|
||||
# 三选一停点编排(presented→pick→confirm/refresh→resolved→continue)+ 同调位替换子态
|
||||
#(presented→chosen)+ TP0 令牌池卡片文案装配("kind|tier|relic_id" 复合键)+ 工坊显示名投影。
|
||||
#(presented→chosen)+ TP0 令牌池卡片文案装配("kind|tier|feat_id" 复合键)+ 工坊显示名投影。
|
||||
# 装配纪律(ADR-0001,仿 treasure_interact_controller 先例):信号连接不在此发生——curio_overlay
|
||||
# 四信号与 adventure 两信号由组合根接至本类 on_* 入口;模态栈/演播后排窗/呈现刷新/终局面/
|
||||
# 推进失败 fatal 经组合根回调注入;adventure/runner 随局更替——现值回调注入;兑付写调用唯一
|
||||
@@ -96,7 +96,7 @@ func present_node_curio() -> void:
|
||||
var node_draw: Dictionary = adventure.node_curio_candidates()
|
||||
var node_cands: Array = node_draw.get("candidates", []) as Array
|
||||
_open_modal.call(curio_overlay)
|
||||
curio_overlay.open_pick(Narrator.node_bonus_header(), _bonus_card_texts(node_cands, node_draw.get("aux_detail", []) as Array))
|
||||
curio_overlay.open_pick(Narrator.node_curio_header(), _curio_card_texts(node_cands, node_draw.get("aux_detail", []) as Array))
|
||||
adventure.present_node_curio(node_cands, node_draw.get("aux_detail", []) as Array)
|
||||
curio_overlay.set_refresh_info(adventure.attune_refresh_left()) # 迭代 11 第①批 T5b——刷新余量投喂
|
||||
|
||||
@@ -105,25 +105,25 @@ func present_node_curio() -> void:
|
||||
func show_pick() -> void:
|
||||
var payload: Dictionary = _pending_curio
|
||||
_open_modal.call(curio_overlay)
|
||||
curio_overlay.open_pick(Narrator.curio_pick_header(payload), _bonus_card_texts(payload.get("candidates", []) as Array, payload.get("aux_detail", []) as Array))
|
||||
curio_overlay.open_pick(Narrator.curio_pick_header(payload), _curio_card_texts(payload.get("candidates", []) as Array, payload.get("aux_detail", []) as Array))
|
||||
var adventure = _adventure_get.call()
|
||||
curio_overlay.set_refresh_info(adventure.attune_refresh_left() if adventure != null else 0) # 迭代 11 第①批 T5b——刷新余量投喂
|
||||
_refresh_presentations.call()
|
||||
|
||||
|
||||
func _bonus_card_texts(candidates: Array, treasure_detail: Array = []) -> Array:
|
||||
# TP0 令牌池——候选 = {"kind","tier"} 令牌字典;卡片 id = "kind|tier|relic_id" 复合键(同 kind
|
||||
func _curio_card_texts(candidates: Array, treasure_detail: Array = []) -> Array:
|
||||
# TP0 令牌池——候选 = {"kind","tier"} 令牌字典;卡片 id = "kind|tier|feat_id" 复合键(同 kind
|
||||
# 大小两档/同档多 relic 可同屏,kind 单键不构成唯一身份),确认回程拆键(on_pick_confirmed)
|
||||
var out: Array = []
|
||||
var treasure_i := 0
|
||||
for tok in candidates:
|
||||
var kind := String((tok as Dictionary).get("kind", ""))
|
||||
var tier := String((tok as Dictionary).get("tier", ""))
|
||||
var rid := String((tok as Dictionary).get("relic_id", ""))
|
||||
var rid := String((tok as Dictionary).get("feat_id", ""))
|
||||
var cid := "%s|%s|%s" % [kind, tier, rid]
|
||||
var text := ""
|
||||
if kind == "relic":
|
||||
text = Narrator.relic_card_text(db.relic_row(rid))
|
||||
text = Narrator.feat_card_text(db.feat_row(rid))
|
||||
elif kind == "treasure_item":
|
||||
var iid := String(treasure_detail[treasure_i]) if treasure_i < treasure_detail.size() else ""
|
||||
treasure_i += 1
|
||||
@@ -167,7 +167,7 @@ func on_refresh() -> void:
|
||||
return
|
||||
if _curio_context == "reward_node":
|
||||
var st: Dictionary = adventure.node_curio_pending_state()
|
||||
curio_overlay.open_pick(Narrator.node_bonus_header(), _bonus_card_texts(st.get("candidates", []) as Array, st.get("aux_detail", []) as Array))
|
||||
curio_overlay.open_pick(Narrator.node_curio_header(), _curio_card_texts(st.get("candidates", []) as Array, st.get("aux_detail", []) as Array))
|
||||
curio_overlay.set_refresh_info(adventure.attune_refresh_left())
|
||||
|
||||
|
||||
@@ -175,7 +175,7 @@ func on_pick_confirmed(item_id: String) -> void:
|
||||
var adventure = _adventure_get.call()
|
||||
if adventure == null:
|
||||
return
|
||||
# TP0 令牌池——卡片 id "kind|tier|relic_id" 拆键(缺 | = 旧载荷防御归普通档;relic 三段)
|
||||
# TP0 令牌池——卡片 id "kind|tier|feat_id" 拆键(缺 | = 旧载荷防御归普通档;relic 三段)
|
||||
var parts := item_id.split("|")
|
||||
var kind := parts[0]
|
||||
var tier := parts[1] if parts.size() > 1 else ""
|
||||
|
||||
@@ -35,11 +35,11 @@ static func refresh(stage: BattleStageView, info: HeroInfoPanelView, ap_bar: ApB
|
||||
else:
|
||||
info.set_level_bonuses([])
|
||||
# 特性持有投影(迭代 12 呈现补齐 2026-10-04——用户反馈「局内奖励选了什么看不到」:
|
||||
# 逐流派聚合行+成型档位;常驻可读+空态隐藏。档位求值=RelicsEngine 纯函数直调)
|
||||
# 逐流派聚合行+成型档位;常驻可读+空态隐藏。档位求值=FeatsEngine 纯函数直调)
|
||||
if runner != null and level_active:
|
||||
info.set_relic_holdings(relic_holdings_lines(db, runner.relics_held()))
|
||||
info.set_feat_holdings(feat_holdings_lines(db, runner.feats_held()))
|
||||
else:
|
||||
info.set_relic_holdings([])
|
||||
info.set_feat_holdings([])
|
||||
if settlement == null:
|
||||
info.set_board_variants([]) # 战斗域角标出战斗即隐(首发批 2026-10-04——空态纪律)
|
||||
_refresh_out_of_battle(stage, info, ap_bar, runner, level_active, db)
|
||||
@@ -94,18 +94,18 @@ static func _refresh_economy(ap_bar: ApBarView, s: Dictionary, db, refresh_remai
|
||||
|
||||
|
||||
# 特性持有聚合文案(迭代 12 呈现补齐——战斗 C 区与关卡选择页两处共用;空持有=空数组)
|
||||
static func relic_holdings_lines(db, held: Array) -> Array[String]:
|
||||
static func feat_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():
|
||||
if db == null or db.feats == null or (db.feats.rows as Array).is_empty() or held.is_empty():
|
||||
return rlines
|
||||
var arch_names := {"magic": "魔法", "pierce": "穿刺", "normal": "普攻", "dig": "开格",
|
||||
"flag": "标旗", "charge": "蓄力", "devour": "吞噬"}
|
||||
var counts := {}
|
||||
for rid in held:
|
||||
var rrow: Dictionary = db.relic_row(String(rid))
|
||||
var rrow: Dictionary = db.feat_row(String(rid))
|
||||
var arch := String(rrow.get("archetype", ""))
|
||||
counts[arch] = int(counts.get(arch, 0)) + 1
|
||||
var tiers: Dictionary = RelicsEngine.tiers_for(held, db.relics)
|
||||
var tiers: Dictionary = FeatsEngine.tiers_for(held, db.feats)
|
||||
for arch in counts.keys():
|
||||
var tier := int(tiers.get(arch, 0))
|
||||
var tier_text := "档二" if tier >= 2 else ("档一" if tier == 1 else "散件")
|
||||
|
||||
@@ -570,7 +570,7 @@ func _on_battle_end_continue() -> void:
|
||||
if _settlement_stop_pending:
|
||||
_settlement_stop_pending = false
|
||||
_enter_level_screen()
|
||||
level_screen.set_relic_holdings(" · ".join(HudPresenter.relic_holdings_lines(db, runner.relics_held())))
|
||||
level_screen.set_feat_holdings(" · ".join(HudPresenter.feat_holdings_lines(db, runner.feats_held())))
|
||||
level_screen.open_choices(_pending_candidates, runner)
|
||||
_pending_candidates = []
|
||||
_refresh_presentations()
|
||||
@@ -856,7 +856,7 @@ func _on_choices_presented(candidates: Array) -> void:
|
||||
_refresh_presentations()
|
||||
return
|
||||
_enter_level_screen()
|
||||
level_screen.set_relic_holdings(" · ".join(HudPresenter.relic_holdings_lines(db, runner.relics_held())))
|
||||
level_screen.set_feat_holdings(" · ".join(HudPresenter.feat_holdings_lines(db, runner.feats_held())))
|
||||
level_screen.open_choices(candidates, runner)
|
||||
_refresh_presentations()
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@ var _selected_handle := 0 # 选中态(0=无;组合根回写
|
||||
var _slot_handles: Array = [] # 槽位→handle 映射(set_treasure_inventory 刷新)
|
||||
var _curio_section: VBoxContainer # 特性(预留——空态隐藏,接线归大奖励/锻造呈现批)
|
||||
var _curio_list: VBoxContainer
|
||||
var _relic_section: VBoxContainer # 特性持有段(迭代 12 呈现补齐——空态隐藏)
|
||||
var _relic_list: VBoxContainer
|
||||
var _feat_section: VBoxContainer # 特性持有段(迭代 12 呈现补齐——空态隐藏)
|
||||
var _feat_list: VBoxContainer
|
||||
var _board_variant_section: VBoxContainer # 地形变异常驻角标(全局作用域变异首发批——空态隐藏)
|
||||
var _board_variant_list: VBoxContainer
|
||||
|
||||
@@ -73,14 +73,14 @@ func _init() -> void:
|
||||
# 特性持有段(迭代 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_list = VBoxContainer.new()
|
||||
_relic_list.add_theme_constant_override("separation", 2)
|
||||
_relic_section.add_child(_relic_list)
|
||||
_feat_section = VBoxContainer.new()
|
||||
_feat_section.add_theme_constant_override("separation", 4)
|
||||
_feat_section.visible = false
|
||||
col.add_child(_feat_section)
|
||||
_feat_section.add_child(UiKit.label("特性", 16, true))
|
||||
_feat_list = VBoxContainer.new()
|
||||
_feat_list.add_theme_constant_override("separation", 2)
|
||||
_feat_section.add_child(_feat_list)
|
||||
# 地形变异常驻角标(全局作用域变异首发批 2026-10-04——Boss 图整图型战斗全程可见防中局遗忘;
|
||||
# 空态整节隐藏=特性段先例;摆位/文案 provisional 归 HUD 框架批与本地化批)
|
||||
_board_variant_section = VBoxContainer.new()
|
||||
@@ -114,14 +114,14 @@ func set_armor(ac: int) -> void:
|
||||
|
||||
|
||||
# 特性持有段(迭代 12 呈现补齐):lines = 聚合文案行(「魔法 ×2 · 档一」式)——空数组 = 整节隐藏
|
||||
func set_relic_holdings(lines: Array) -> void:
|
||||
for c2 in _relic_list.get_children():
|
||||
_relic_list.remove_child(c2)
|
||||
func set_feat_holdings(lines: Array) -> void:
|
||||
for c2 in _feat_list.get_children():
|
||||
_feat_list.remove_child(c2)
|
||||
c2.queue_free()
|
||||
for line in lines:
|
||||
var l2 := UiKit.label(String(line), 16, false, COL_INK)
|
||||
_relic_list.add_child(l2)
|
||||
_relic_section.visible = not lines.is_empty()
|
||||
_feat_list.add_child(l2)
|
||||
_feat_section.visible = not lines.is_empty()
|
||||
|
||||
|
||||
# 地形变异常驻角标(首发批 2026-10-04):lines = 文案行(板级变异 display_name+体感短语)——空数组 = 整节隐藏
|
||||
|
||||
@@ -57,7 +57,7 @@ var _hp_bar: Control
|
||||
var _attr_value: Label
|
||||
var _bonus_row: HBoxContainer
|
||||
var _bonus_value: Label
|
||||
var _relic_value: Label # 特性持有行(迭代 12 呈现补齐——组合根投喂聚合文案)
|
||||
var _feat_value: Label # 特性持有行(迭代 12 呈现补齐——组合根投喂聚合文案)
|
||||
var _cand_ids: Array[int] = [] # 本停点候选 id 集(图上命中合法集)
|
||||
var _content_size := Vector2(620, 240) # 图内容包络(open_choices 按图拟合——画布 min 尺寸随它)
|
||||
var _hover_id := -1 # 悬停预承诺候选(-1 = 无)
|
||||
@@ -121,7 +121,7 @@ func _init() -> void:
|
||||
box.add_child(_canvas)
|
||||
# 底部状态栏(M5 合并单条:亮米面板一站读齐=头像+生命+属性+本关加成/流派件——demo ④;
|
||||
# 道具槽不摆=道具读数无关卡画面成文出口(读快照私域越权),随 runner 出口批补——台账 352 注记;
|
||||
# _hp_value/_attr_value/_bonus_value/_relic_value 投喂键全部保留)
|
||||
# _hp_value/_attr_value/_bonus_value/_feat_value 投喂键全部保留)
|
||||
var bottom := PanelContainer.new()
|
||||
bottom.add_theme_stylebox_override("panel",
|
||||
UiKit.panel_flat(Color8(240, 228, 200), UiKit.CAMP_HEADER_BAND, 0, 2, Vector4(12, 6, 12, 6)))
|
||||
@@ -166,9 +166,9 @@ func _init() -> void:
|
||||
_bonus_value = UiKit.label("", 15, true, UiKit.WARM)
|
||||
bonus_inner.add_child(_bonus_value)
|
||||
# 特性持有行(迭代 12 呈现补齐 2026-10-04——用户反馈关卡选择页看不到局内奖励;组合根投喂)
|
||||
_relic_value = UiKit.label("", 13, false, UiKit.WARM_SOFT)
|
||||
_relic_value.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
bonus_box.add_child(_relic_value)
|
||||
_feat_value = UiKit.label("", 13, false, UiKit.WARM_SOFT)
|
||||
_feat_value.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
bonus_box.add_child(_feat_value)
|
||||
var spacer := Control.new()
|
||||
spacer.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
strip.add_child(spacer)
|
||||
@@ -205,8 +205,8 @@ func _draw_hp_bar(bar: Control) -> void:
|
||||
|
||||
# 放弃入口可见性(组合根在冒险启动时开、默认关——语义对象 = 整局冒险)
|
||||
# 特性持有投影(迭代 12 呈现补齐——组合根投喂聚合文案;空文案=行隐藏)
|
||||
func set_relic_holdings(text: String) -> void:
|
||||
_relic_value.text = text
|
||||
func set_feat_holdings(text: String) -> void:
|
||||
_feat_value.text = text
|
||||
|
||||
|
||||
func set_abandon_available(v: bool) -> void:
|
||||
@@ -339,8 +339,8 @@ func _refresh_status() -> void:
|
||||
if ac_bonus > 0:
|
||||
parts.append("AC +%d" % ac_bonus)
|
||||
_bonus_value.text = " · ".join(parts)
|
||||
# 特性持有行可见性(与加成行并框——任一非空整框显示;文案归组合根 set_relic_holdings)
|
||||
_bonus_row.visible = not parts.is_empty() or _relic_value.text != ""
|
||||
# 特性持有行可见性(与加成行并框——任一非空整框显示;文案归组合根 set_feat_holdings)
|
||||
_bonus_row.visible = not parts.is_empty() or _feat_value.text != ""
|
||||
|
||||
|
||||
# ---- 图上命中(布局决策 2——唯一提交通道;探针 press_candidate 同路径) ----
|
||||
|
||||
Reference in new issue
Block a user