fix: 修复审计发现的 3 个潜在 bug(CoreFeatureTag / pierce / Deck 防呆)

1. CoreFeatureTag 位运算串扰:feature_tags 实为单选枚举(游戏设计器 core_tab
   以 OptionButton 下标写入),但 spell_evaluator 用位与 `&` 判定,非 2 的幂
   常量会串扰(如 3 & 1 = 1 误判持久内存)。改为 `==` 相等判定,常量值保持
   与设计器下标一致;补充注释说明单选语义与未来多选(位标志)的迁移路径。
2. modifier_pierce_plus 空操作:MODIFIER 携带的 pierce 从未生效(可购买无效)。
   新增 CastStats.pierce_add,_apply_modifier 累加,_push_projectile 叠加到
   ACTION 自带 pierce。穿透修正现在生效。
3. 战前 Deck 防呆缺失:可带无 ACTION 卡组进战斗。新增
   CombatManager.has_castable_action();商店"下一波"按钮校验,无 ACTION 时
   显示警告并阻止进入(新增 SHOP_NEED_ACTION i18n 键,zh_CN/zh_TW/en/ja)。

静态审查通过;因本机无 Godot CLI 未经运行时验证,需在编辑器 play_scene 验收。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-20 14:46:41 +08:00
co-authored by Claude Opus 4.8
parent 675a8d4d9f
commit dc05eeada7
9 changed files with 52 additions and 4 deletions
+14
View File
@@ -13,6 +13,7 @@ var _enemy_mm: MultiMesh = null
## UI 层引用
var _hud_layer: CanvasLayer = null
var _shop_layer: CanvasLayer = null
var _shop_warn: Label = null # 防呆警告:Deck 无 ACTION 时提示
## HUD 标签
var _lbl_wave: Label = null
@@ -304,6 +305,12 @@ func _setup_shop_ui() -> void:
_close_btn.connect("pressed", _on_close_shop_pressed)
_shop_layer.add_child(_close_btn)
_shop_warn = Label.new()
_shop_warn.position = Vector2(120, 448)
_shop_warn.add_theme_color_override("font_color", Color(1.0, 0.45, 0.35))
_shop_warn.visible = false
_shop_layer.add_child(_shop_warn)
# ── HUD 刷新 ────────────────────────────────────────────────
func _refresh_hud() -> void:
@@ -348,6 +355,8 @@ func _on_stats_changed() -> void:
_refresh_shop_ui()
func _on_shop_ready(_wave: int) -> void:
if _shop_warn:
_shop_warn.visible = false
_shop_layer.visible = true
_refresh_shop_ui()
@@ -662,6 +671,11 @@ func _on_inv_bench_pressed(bi: int) -> void:
_rebuild_inventory()
func _on_close_shop_pressed() -> void:
# 防呆:Deck 无 ACTION 法术则法术塔无法开火,阻止进入战斗并提示
if not _cm.has_castable_action():
_shop_warn.text = tr("SHOP_NEED_ACTION")
_shop_warn.visible = true
return
_shop_layer.visible = false
_cm.close_shop_and_next_wave()