From 9ed597b4523491a4b3b88ee5b5cdf795780dbfe8 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Fri, 2 Oct 2026 04:56:55 +0800 Subject: [PATCH] =?UTF-8?q?T17=E5=8F=8D=E9=A6=88=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=89=B9:=20=E2=91=A0debug=E8=B0=83=E7=94=9F=E5=91=BD=E4=B8=8A?= =?UTF-8?q?=E9=99=90=E5=90=8E=E5=BD=93=E5=89=8D=E8=A1=80=E4=B8=8D=E5=90=8C?= =?UTF-8?q?=E6=AD=A5bug=E4=BF=AE=E5=A4=8D=E2=80=94=E2=80=94=E5=86=92?= =?UTF-8?q?=E9=99=A9=E8=B4=A6=E6=9C=AC=E7=BD=AE=E6=BB=A1/=E9=80=9A?= =?UTF-8?q?=E5=85=B3=E5=9B=9E=E8=A1=80=E5=B0=81=E9=A1=B6=E5=8F=A3=E5=BE=84?= =?UTF-8?q?=E6=94=B9=E7=94=9F=E6=95=88=E4=B8=8A=E9=99=90=E5=90=8C=E5=BC=8F?= =?UTF-8?q?=EF=BC=88=E8=A1=A8=E5=80=BC+=E6=B0=B8=E4=B9=85=E5=BC=BA?= =?UTF-8?q?=E5=8C=96flat+=E5=8A=A0=E7=AE=97=E5=8C=BAflat=E5=90=8E=E4=B9=98?= =?UTF-8?q?TunePanel=20pct=EF=BC=8C=E4=B8=8ELevelRunner.effective=5Fmax=5F?= =?UTF-8?q?hp=E9=80=90=E5=AD=97=E5=90=8C=E6=BA=90=EF=BC=9B=E6=97=A7?= =?UTF-8?q?=E5=8F=A3=E5=BE=84=E4=B8=A4=E5=A4=84=E5=8F=AA=E7=AE=97flat?= =?UTF-8?q?=EF=BC=9A26=E2=86=92104=E6=97=B6=E5=BC=80=E5=B1=80=E8=A1=80?= =?UTF-8?q?=E4=BB=8D26/=E5=9B=9E=E8=A1=80=E5=B0=81=E9=A1=B6=E6=8C=8926?= =?UTF-8?q?=E7=AE=97=EF=BC=89+smoke=E5=9B=9E=E8=A1=80=E6=96=AD=E8=A8=80?= =?UTF-8?q?=E7=AA=97=E5=8F=A3=E5=90=8C=E6=AD=A5=C3=975=E5=8F=A3=E5=BE=84?= =?UTF-8?q?=EF=BC=88pct=3D0=E6=81=92=E7=AD=89MC=E9=94=9A=E9=9B=B6=E6=BC=82?= =?UTF-8?q?=E7=A7=BB=EF=BC=89=E2=91=A1=E7=AC=AC17=E9=A1=B9=E9=80=89?= =?UTF-8?q?=E8=B7=AF=E5=91=88=E7=8E=B0=E4=B8=A4=E4=B8=BB=E5=9B=A0=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=EF=BC=88B=E7=BA=BF=E8=B0=83=E7=A0=94=E5=AE=9A?= =?UTF-8?q?=E4=BD=8D=EF=BC=89=E2=80=94=E2=80=94=E9=80=9A=E9=81=93=E5=B9=B2?= =?UTF-8?q?=E7=BA=BFmid=5Fx=E6=8C=89=E6=BA=90y=E5=81=8F=E7=A7=BB=E6=B6=88?= =?UTF-8?q?=E5=85=B1=E7=BA=BF=E9=87=8D=E5=8F=A0+=E9=80=89=E8=B7=AF?= =?UTF-8?q?=E5=81=9C=E7=82=B9=E9=9D=9E=E5=80=99=E9=80=89=E9=80=9A=E9=81=93?= =?UTF-8?q?=E9=99=8D=E9=80=8F=E6=98=8E35%=EF=BC=88=E6=97=A7=E6=80=81?= =?UTF-8?q?=EF=BC=9A=E9=87=91=E5=B2=94=E8=B7=AF=E4=B8=8E=E7=9F=B3=E8=89=B2?= =?UTF-8?q?=E7=BB=93=E6=9E=84=E7=BD=91=E7=84=8A=E6=8E=A5=E6=88=90=E6=95=B4?= =?UTF-8?q?=E5=88=97=E5=8F=AF=E8=B5=B0=E5=81=87=E8=B1=A1=EF=BC=89=EF=BC=9B?= =?UTF-8?q?=E9=97=B8=3D=E5=86=92=E7=83=9F628/0+ui=5Fprobe/ui=5Finput/fx?= =?UTF-8?q?=E4=B8=89=E6=8E=A2=E9=92=88=E7=BB=BF=EF=BC=88ui=5Fclick=5Fprobe?= =?UTF-8?q?=20worktree=E7=8E=AF=E5=A2=83=E4=B8=8D=E7=A8=B3=E5=AE=9A?= =?UTF-8?q?=E5=8D=A1=E6=AD=BB=E6=9C=AA=E5=86=B3=EF=BC=8C=E4=B8=BB=E5=8C=BA?= =?UTF-8?q?=E5=A4=8D=E8=B7=91=E4=B8=BA=E5=87=86=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- game/core/adventure_runner.gd | 13 +++++++++++-- game/presentation/views/level_map_screen.gd | 10 ++++++++-- game/smoke/smoke_all.gd | 7 ++++--- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/game/core/adventure_runner.gd b/game/core/adventure_runner.gd index 09bc6b89..d77421c0 100644 --- a/game/core/adventure_runner.gd +++ b/game/core/adventure_runner.gd @@ -113,7 +113,7 @@ func start_adventure(seed_val: int, params: Dictionary = {}) -> bool: _base_override = _normalize_override(params.get("hero_override", {})) _first_script = bool(params.get("first_script", false)) # 缺省 = 非首次(抽签路径;真实侧由呈现层读存档布尔位传入) _aux_unlocked = params.get("aux_unlocked", {}) if params.get("aux_unlocked", {}) is Dictionary else {} # additive(迭代 7 T5) - ledger["hero_hp"] = int(db.hero.max_hp) + int(_base_override["max_hp"]) # 生命账本置满(表值+永久强化 flat——加算区刚归零) + ledger["hero_hp"] = effective_max_hp() # 生命账本置满(生效上限口径——T17 修复:含 TunePanel pct,与战斗内同源) state = "running" return _start_current_level() @@ -211,6 +211,15 @@ func set_hero_override(atk_pct: int, hp_pct: int) -> void: _runner.set_hero_override(atk_pct, hp_pct) +# 冒险账本侧生效上限(T17 修复——账本置满/回血封顶与战斗内上限同式同源): +# (表值 + 永久强化 flat + 加算区 flat)后乘 TunePanel 百分比——叠加次序与 LevelRunner.effective_max_hp +# 逐字一致。旧口径两处只算 flat 不乘 pct:调生命上限 26→104 时开局血仍 26(账本 26 / 战斗内 104)、 +# 通关 20% 回血封顶按 26 算。pct=0(模拟/冒烟默认)时乘法恒等——MC 锚零漂移。 +func effective_max_hp() -> int: + var base: int = int(db.hero.max_hp) + int(_base_override.get("max_hp", 0)) + int(bonus.get("max_hp", 0)) + return maxi(1, int(round(float(base) * (100.0 + float(_override[1])) / 100.0))) + + # 断点承载注入(迭代 8 卡①——组合根冒险开始时调用;模拟/冒烟不注入 = 断点面整体静默) func set_save_manager(sm) -> void: _save_manager = sm @@ -609,7 +618,7 @@ func _on_level_finished(payload: Dictionary) -> void: # 通关兑付(非末关恰一次;迭代 10 三层奖励框架):部分回血先行 → 加权洗牌掷 3 → 三选一停点 #(顺序即契约——回血按当刻账本与上限结算,选择停点零自动推进) var hp_before := int(ledger.get("hero_hp", 0)) - var max_eff := int(db.hero.max_hp) + int(_base_override["max_hp"]) + int(bonus.get("max_hp", 0)) + var max_eff := effective_max_hp() # T17 修复:回血封顶口径含 TunePanel pct(同战斗内上限) var heal := mini(int(floor(float(max_eff) * float(int(db.adventure.clear_heal_pct)) / 100.0)), max_eff - hp_before) ledger["hero_hp"] = hp_before + heal # 置位先于 emit(信号同步派发——处理器内立即确认时 _pending_next_level 必须已就位) diff --git a/game/presentation/views/level_map_screen.gd b/game/presentation/views/level_map_screen.gd index c11a005a..9b58f4ef 100644 --- a/game/presentation/views/level_map_screen.gd +++ b/game/presentation/views/level_map_screen.gd @@ -394,6 +394,9 @@ func _draw_graph(canvas: Control) -> void: var visited: Array = _runner.visited_ids() var cand_ids: Array = _runner.next_candidate_ids() # 连线(通道)先行画(方块覆盖其上);悬停预承诺 = 所属通道再增亮(加粗) + # T17 修复:选路停点(候选非空)非候选通道降透明——金岔路从结构网分离(干线共线重叠缺陷的 + # 视觉主因:不同源通道共用同一垂直干线,金边与石色边焊接成「整列可走」假象) + var dim_passages: bool = not cand_ids.is_empty() for node in nodes: var from: Vector2 = pos[node] for tid in _out_ids(node, nodes): @@ -403,7 +406,7 @@ func _draw_graph(canvas: Control) -> void: var to: Vector2 = pos[target] var lit: bool = _id_of(node) == current_id and cand_ids.has(tid) var hovered: bool = lit and _hover_id == tid - var col := COL_PASSAGE_LIT if lit else COL_PASSAGE + var col := COL_PASSAGE_LIT if lit else (Color(COL_PASSAGE, 0.35) if dim_passages else COL_PASSAGE) var width := 4.0 if hovered else (3.0 if lit else 2.0) # 样张 v1 冻结:2/3/4(原 1.5 取整) _draw_passage(canvas, from, to, col, width) # 房间方块 @@ -511,6 +514,9 @@ func _draw_passage(canvas: Control, from: Vector2, to: Vector2, col: Color, widt var b := to - Vector2(NODE_HALF.x, 0) if b.x < a.x: return - var mid_x := (a.x + b.x) / 2.0 + # T17 修复:垂直干线 x 按源节点 y 偏移——不同源的边不再共线重叠(旧 mid_x=中点使相邻层 + # 全部通道焊成一条干系,「金岔路+整列可走」误读的直接几何根源)。同源双边仍共线(同出发 + # 点语义正确),跨源分离度 = 源行距 × 0.2(L2 行距 ~58px → 偏移 ~12px 可辨)。 + var mid_x := (a.x + b.x) / 2.0 + (a.y - b.y) * 0.2 var pts := PackedVector2Array([a, Vector2(mid_x, a.y), Vector2(mid_x, b.y), b]) canvas.draw_polyline(pts, col, width) diff --git a/game/smoke/smoke_all.gd b/game/smoke/smoke_all.gd index e81fe505..7b8bcba4 100644 --- a/game/smoke/smoke_all.gd +++ b/game/smoke/smoke_all.gd @@ -347,13 +347,14 @@ func _smoke_adventure() -> void: var hp_before: int = int(p.get("hp_before", -1)) var hp_after: int = int(p.get("hp_after", -1)) # 模拟档 v3.4 商店贪心购血合法抬升(L2/L3 店在 Boss 前)——回血口径窗口 = 加算区件 + 购血余量 0..15 + # T17 账本口径修复随批:置满/回血封顶改生效上限口径(flat 后乘 TunePanel pct)——窗口同步 ×5(本段 pct=400) var heal_ok_i := false for extra in 16: - var m := int(_db.hero.max_hp) + hp_acc + extra + var m := int(round(float(int(_db.hero.max_hp) + hp_acc + extra) * 5.0)) if heal == mini(int(floor(float(m) * float(heal_pct) / 100.0)), m - hp_before): heal_ok_i = true break - if not heal_ok_i or hp_after != hp_before + heal or hp_after > int(_db.hero.max_hp) + hp_acc + 15: + if not heal_ok_i or hp_after != hp_before + heal or hp_after > int(round(float(int(_db.hero.max_hp) + hp_acc + 15) * 5.0)): heal_ok = false ks_prefix += int(_db.meta_boss_keystone_row(int(p.get("level_index", -1))).get("first_kill", 0)) if int(p.get("keystone_gained", -1)) != int(_db.meta_boss_keystone_row(int(p.get("level_index", -1))).get("first_kill", 0)) or int(p.get("keystone_total", -1)) != ks_prefix: @@ -486,7 +487,7 @@ func _smoke_adventure() -> void: var expect_acc: int = acc_shop + (int(_db.adventure.bonus_max_hp_flat) if picked2 == "max_hp" else 0) check(int(a8.bonus.get("max_hp", -1)) == expect_acc, "三选一属性件与商店购买同账累加(max_hp=%d = %d + 三选一%s)" % [int(a8.bonus.get("max_hp", -1)), acc_shop, picked2]) - var max_eff8 := int(_db.hero.max_hp) + int(a8.bonus["max_hp"]) + var max_eff8: int = a8.effective_max_hp() # T17 口径修复随批:账本生效上限含 TunePanel pct(a8 已 set 400) check(int(a8.ledger["hero_hp"]) <= max_eff8, "通关部分回血封顶(hp %d ≤ 生效上限 %d——血回满语义退役)" % [int(a8.ledger["hero_hp"]), max_eff8]) check(a8.continue_to_next_level(), "兑付后推进受理(下一关开始)")