feat(shop): 货架 C 购买次数进局内存档(schema 2→3)

只存次数不存加成——加成是派生物,回读时经 _apply_attr_purchases 重建。
这也躲开了 E3-① 记录的坑:_modifiers 是 Array[Dictionary],而 JSON 回读的
无类型 Array 直接 = 赋值是运行时类型错误,必须 .assign();存派生源头则不涉及。

回读顺序:attr_purchases 必须早于 load_save_data。后者设 hp,而重建加成会经
_recompute_attrs 触发 hp = minf(hp, hp_max);顺序颠倒会拿未加成的 hp_max 去钳,
静默吞血(hp_max 可买到 180 后即可复现)。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-03 11:27:23 +08:00
co-authored by Claude Opus 5
parent f8e02b0a0b
commit 900eaea697
+8 -1
View File
@@ -7,7 +7,7 @@
## - NOTIFICATION_WM_CLOSE_REQUEST 尽力写最后一笔 ## - NOTIFICATION_WM_CLOSE_REQUEST 尽力写最后一笔
extends Node extends Node
const SCHEMA_VERSION: int = 2 # v2:新增 wandCore/deck/bench)持久化 const SCHEMA_VERSION: int = 3 # v3:新增 attr_purchases(货架 C 属性购买次数)
const PATH_A: String = "user://run_a.json" const PATH_A: String = "user://run_a.json"
const PATH_B: String = "user://run_b.json" const PATH_B: String = "user://run_b.json"
@@ -63,6 +63,9 @@ func load_run() -> Dictionary:
func apply_run(data: Dictionary) -> void: func apply_run(data: Dictionary) -> void:
if data.is_empty(): if data.is_empty():
return return
# 必须早于 load_save_data:后者设 hp,而 _apply_attr_purchases 会经 _recompute_attrs
# 触发 hp = minf(hp, hp_max)。顺序颠倒会拿未加成的 hp_max 去钳,静默吞血。
ShopManager.apply_attr_purchases_save(data.get("attr_purchases", {}))
PlayerStats.load_save_data(data.get("player_stats", {})) PlayerStats.load_save_data(data.get("player_stats", {}))
WaveManager.current_wave = int(data.get("wave_num", 0)) WaveManager.current_wave = int(data.get("wave_num", 0))
var shop_seed: int = int(data.get("shop_seed", 0)) var shop_seed: int = int(data.get("shop_seed", 0))
@@ -90,6 +93,7 @@ func _collect_run_data() -> Dictionary:
"wave_num": WaveManager.current_wave, "wave_num": WaveManager.current_wave,
"shop_seed": ShopManager.get_shop_seed(), "shop_seed": ShopManager.get_shop_seed(),
"player_stats": PlayerStats.get_save_data(), "player_stats": PlayerStats.get_save_data(),
"attr_purchases": ShopManager.get_attr_purchases_save(),
} }
if is_instance_valid(_wand_provider) and _wand_provider.has_method("get_wand_save_data"): if is_instance_valid(_wand_provider) and _wand_provider.has_method("get_wand_save_data"):
d["wand"] = _wand_provider.get_wand_save_data() d["wand"] = _wand_provider.get_wand_save_data()
@@ -115,4 +119,7 @@ func _migrate_run(data: Dictionary) -> Dictionary:
if ver < 2: if ver < 2:
# v1→v2: 旧档无 wand 字段;apply_run 检测缺失即保留默认法杖,无需补字段 # v1→v2: 旧档无 wand 字段;apply_run 检测缺失即保留默认法杖,无需补字段
data["schema_version"] = 2 data["schema_version"] = 2
if ver < 3:
# v2→v3: 旧档无 attr_purchasesapply_run 的 data.get(..., {}) 已处理缺失,无需补字段
data["schema_version"] = 3
return data return data