docs(attr): 补记货架 C 的回读顺序陷阱;畸形条目报错说明整文件已拒绝

纯注释改动,无行为变更。

1. get_save_data 的货架 C 文档块补回读顺序:_modifiers 必须先 assign +
   _recompute_attrs(),再赋 hp。反过来会让新加的 hp = minf(hp, hp_max) 拿
   未加成的 hp_max 去钳,静默吞血(评审复现:回读 hp=180/100 → 换杖重算后
   100/100,丢 80 HP)。今天不可达(hp_max 恒 100),但持久化 _modifiers 一
   落地即活,而这个文档块正是那位实现者会读的地方。

2. 畸形条目的 push_error 补「整个文件已拒绝加载」——守卫是 return,一个坏
   条目会让四个属性全部退回声明默认值,原文案读起来像只影响那一个键。

3. ATTRIBUTES_JSON 补「数据源」分区横幅,与文件自身风格一致。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-31 11:32:10 +08:00
co-authored by Claude Opus 5
parent 61445caad7
commit 69ddcddba6
+4 -1
View File
@@ -5,6 +5,7 @@ extends Node
signal stats_changed signal stats_changed
signal leveled_up(new_level: int) signal leveled_up(new_level: int)
# ── 数据源 ────────────────────────────────────────────
const ATTRIBUTES_JSON: String = "res://data/attributes.json" const ATTRIBUTES_JSON: String = "res://data/attributes.json"
# ── HP ─────────────────────────────────────────────── # ── HP ───────────────────────────────────────────────
@@ -152,6 +153,8 @@ func reset_for_run() -> void:
## · source == "core" 的那条**不要**持久化——它在换杖时由 combat_manager._rebuild_wand 重建。 ## · source == "core" 的那条**不要**持久化——它在换杖时由 combat_manager._rebuild_wand 重建。
## · 回读须用 _modifiers.assign(...)JSON.parse_string / data.get(..., []) 产出的是无类型 ## · 回读须用 _modifiers.assign(...)JSON.parse_string / data.get(..., []) 产出的是无类型
## Array,直接 `=` 赋给 Array[Dictionary] 会运行时类型错误。 ## Array,直接 `=` 赋给 Array[Dictionary] 会运行时类型错误。
## · 回读顺序:_modifiers 必须先 assign + _recompute_attrs(),再赋 hp。反过来会让
## _recompute_attrs 的 hp = minf(hp, hp_max) 拿未加成的 hp_max 去钳,静默吞血。
func get_save_data() -> Dictionary: func get_save_data() -> Dictionary:
return {"hp": hp, "gold": gold, "xp": xp, "level": level} return {"hp": hp, "gold": gold, "xp": xp, "level": level}
@@ -176,7 +179,7 @@ func _load_attr_definitions() -> void:
# 逐条守卫:畸形条目(如 "move_speed": 200)会让 _compute_attr 的 Dictionary 赋值硬崩 # 逐条守卫:畸形条目(如 "move_speed": 200)会让 _compute_attr 的 Dictionary 赋值硬崩
for k in parsed: for k in parsed:
if not (parsed[k] is Dictionary): if not (parsed[k] is Dictionary):
push_error("PlayerStats: attributes.json 的「%s」应为对象" % k) push_error("PlayerStats: attributes.json 的「%s」应为对象,整个文件已拒绝加载" % k)
return return
_attr_def = parsed _attr_def = parsed