 joywayerandClaude Opus 5
|
69ddcddba6
|
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>
|
2026-07-31 11:32:10 +08:00 |
|
 joywayerandClaude Opus 5
|
61445caad7
|
docs(plan): Task4 补两条约束——不做热重载 + inverse 的 hard 语义相反需在 UI 体现
remove_modifiers_from 在无命中时提前返回,不是强制重新同步原语,故热重载不能
指望它;本页与其它设计器页一致,保存后提示重启生效即可。
inverse 下 hard 是下限、0 表示钳到 0,与 hybrid/add_int 的「0 = 不钳制」相反,
设计师填 0 期待「不限制」会得到相反结果,提示文案需体现。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-31 11:32:01 +08:00 |
|
 joywayerandClaude Opus 5
|
af9c94db25
|
fix(attr): add_modifier 补校验、hp 随 hp_max 调和、reset_for_run 清加成
评审 Changes needed 的三个 Important + 五条 Minor:
1. add_modifier 补 attr_id / mode 校验。AttributeFormula 的注释明文把校验委托
给本函数("仅由 PlayerStats.add_modifier 构造…此处不做防御性校验"),而它
原先不守任何门:打错的 attr_id 会永远堆在 _modifiers 里、永不被读到、零诊断。
Task 3 的 add_modifier("cpu_limit",…) 若打成 "cpu_limits" 即 MAX_OPS=0,
所有法术静默执行零步。
2. _recompute_attrs 补 hp = minf(hp, hp_max)。hp_max 改动前事实上不可变,现在
是可动派生值而 hp 从不调和:买 +100 hp_max、血 180/200、卖掉 → 显示 180/100、
get_hp_percent 返回 1.8、heal 静默失效。
3. reset_for_run 清 _modifiers 并重算,且必须早于 hp = hp_max,否则 hp 用陈旧
的 hp_max 播种。今天 "core" 靠 _rebuild_wand 自愈,但货架 C 的购买会跨局白嫖。
Minor:_ATTR_PATH → ATTRIBUTES_JSON 并上移(_PATH 后缀在本项目专指 user:// 路径,
同类 autoload 一律 XXX_JSON);_mods_for 返回 Array[Dictionary];加载器逐条守卫
畸形值("move_speed": 200 会让 Dictionary 赋值硬崩);remove_modifiers_from 无
命中时提前返回不空发 stats_changed;货架 C 提示并入 get_save_data 并补记回读须
用 .assign()(无类型 Array 赋给 Array[Dictionary] 是运行时错误)。
_recompute_attrs 的空定义分支用 assert 而非 push_error:Task 3 接线后每次换杖/
换牌/购买都触发重算,无条件报错一局刷上百行、反而埋掉根因;assert 在 release
被编译掉且开发期首次调用即中断。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-31 11:24:30 +08:00 |
|
 joywayerandClaude Opus 5
|
8c95cdcbe3
|
docs(plan): Task3 的 MAX_OPS 接线加 cpu_limit=0 守卫
Task 2 代码质量评审建议:cpu_limit=0 的后果是所有法术静默零步,症状离根因极远。
spell_evaluator 的读取点是该故障唯一可观测处,能同时兜住 attributes.json 缺失
与 add_modifier 的 attr_id 打错两种上游失败——根因处的报错够不到这两种。
maxi(...,1) 使故障下游戏仍可玩而非完全瘫痪。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-31 11:22:23 +08:00 |
|
 joywayerandClaude Opus 5
|
a4a4f613f4
|
feat(attr): attributes.json + PlayerStats 属性框架;删孤儿字段 armor/resistance
PlayerStats 只负责加载定义、持有加成列表、把公式结果写进静态类型裸字段,
不含任何公式(公式在 AttributeFormula)。读取端零开销以满足热路径纪律
(move_speed 每物理帧被 player_manager 读)。
armor/resistance 零消费方且不在 numerical_design §1.1 权威属性表内,属实现
先于设计的残留,删除;真要做玩家侧减伤时按货架 C 属性词条立项(见 spec §2.6)。
hp_max/cpu_limit 现为派生值,从存档字段移除——回读会覆盖公式结果。
旧存档相应键忽略即可,无需提升 schema 版本(hp_max 全项目从无写入方、
cpu_limit 从未被读取)。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-31 11:07:59 +08:00 |
|
 joywayerandClaude Opus 5
|
f86d6cd20e
|
docs(plan): 记录 CACHE_MODE_IGNORE 为验证 class_name 脚本的首选手段 + 加回填步骤
Task 1 实测发现:改完源码后经全局类名直调会拿到**过时结果**(返回修复前的
数值),是假通过陷阱——编辑器持有的已编译类是旧的。正确手段是
ResourceLoader.load(path, "GDScript", CACHE_MODE_IGNORE),它保留 class_name
原样且走引擎自己的编译器,故顺带证明静态类型标注真能被引擎编译。
另记 var x := <Variant 方法调用> 在 4.7.1 是无行号的编译错误而非警告。
新增 Task5 Step8:回填计划为实际执行版并勾复选框——归航那期踩过
「计划里留着过时代码和失效断言」的坑。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-31 11:04:44 +08:00 |
|
 joywayerandClaude Opus 5
|
9e3cbf8e5a
|
fix(attr): pct 越界因子变负会静默给出错数,钳到 0 并 push_error
因子 (1±v) 可为负;单条负因子被末尾 maxf(0.0,…) 掩盖,两条负因子相乘
则变回正数 —— 得到一个无报错、看起来合理、实则错误的值。实测 hybrid
base 200 两条 pct=-1.5 得 50.0(应 0.0);inverse 两条 pct=2.0 得 1.0,
延迟纹丝不动(应钳到 hard)。这条路径不需要畸形 JSON,货架 C 传个越界
value 即可触发,而本文件是所有未来平衡的必经之地。
顺带:hard 的语义因 combine 而异(inverse 是下限、0.0 不表示不钳制),
从行尾注释提升进 compute() 文档块并在 inverse 分支点明与 hybrid 相反;
补 mods 的构造契约说明;两处下界 0 加注释;ri→floored、
_COMBINE_NAMES→_COMBINE_BY_NAME;查表与循环变量补静态类型。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-31 11:02:44 +08:00 |
|
 joywayerandClaude Opus 5
|
cd3618c066
|
docs(plan): 补 Step3b 断言 push_error + 订正绕缓存法在类注册后失效
Task 1 评审实测发现两处计划缺陷:
① 断言 ④ 的数字部分对「add_int 拒 pct」是空的——删掉整个拒绝块 ④ 仍返回 13.0,
因为 ADD_INT 的 match 分支不读 pct_prod。拒绝行为唯一可观测证据是 push_error,
补 Step 3b 用唯一标记值 + get_editor_errors 单独断言。
② GDScript.new()+source_code+reload() 在该类被注册为全局类之后同样报
hides a global script class——Task 1 首次运行因尚未注册才侥幸通过,
后续任务照抄会失败。改为先剥离 class_name 行,或直接调已注册的全局类。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-31 10:53:17 +08:00 |
|
 joywayerandClaude Opus 5
|
ecf765d03e
|
feat(attr): AttributeFormula 公式模块——hybrid 连乘 / inverse 反向下限 / add_int 拒 pct
公式集中于单一纯静态模块,无状态零依赖,故可脱离游戏进程单元断言。
乘算用连乘而非线性求和:三条 +20% 得 ×1.728 而非 ×1.6,避免后期线性失控。
add_int 对离散预算拒绝 pct 并 push_error,而非静默取整掩盖配置错误。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-31 10:46:20 +08:00 |
|
 joywayerandClaude Opus 5
|
9bc51795c4
|
docs(plan): E3-① 玩家属性系统逐任务实现计划(6 任务 · 公式先 TDD 后接线)
Task1 AttributeFormula 纯函数(先跑断言看失败再实现)/ Task2 attributes.json +
PlayerStats 框架 + 删孤儿字段 / Task3 四处接线 / Task4 设计器属性页 /
Task5 运行时验收 + 权威文档订正。
自审修掉两处:
① Task1 的断言原用 lambda 闭包累加 fails —— GDScript 闭包对 int 按值捕获,
fails += 1 传不回外层,FAILS 会恒为 0、断言全空。改为 Array 逐条收集。
② Task4 原只写「要求」不写代码。已核对 designer_ui.gd 的真实签名
(spin/opt/load_json/save_json 等)并写出完整可抄的实现,避免实现者照
猜测签名写。
另补:hp_max/cpu_limit 转为派生值后必须从存档字段移除,否则回读覆盖公式结果;
并在代码注释里留下货架 C 需持久化 _modifiers 而非派生值的提示。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-31 10:42:18 +08:00 |
|
 joywayerandClaude Opus 5
|
d3c5edb1cb
|
docs(spec): E3-① 玩家属性系统设计——公式模块 + 修三条死数据 + 范围裁剪
范围按权威文档裁剪:路线图原写的属性名(暴击/急速/范围/吸血/减伤)是拟稿推测,
不存在于任何权威文档;numerical_design §1.1 定义的 11 个属性才是权威。
本期只做「框架 + 修既有死线」,排除 attunement×4(新玩法维度)、luck(暴击链是死的)、
recharge_speed_mod(充能系统压根不存在)。
加成不做简单叠加:每属性在 JSON 声明 combine 公式——hybrid 连乘、
inverse 反向且下限钳制、add_int 拒绝 pct。公式集中在独立的 AttributeFormula
纯静态模块,无状态零依赖,故公式正确性可脱离游戏进程单元断言。
自审修正:法杖 cpu_limit 改为以加成来源接入而非调用点相加——否则 hard 上限
只钳制玩家那一份,法杖份额加在钳制之后可使总值越界;顺带使加成层从第一天
就有真实消费者。
move_speed 取既成事实 200 并订正权威表的 300:该值从未被任何代码读取过,
而 200 自 S0 沿用并已围绕它调校 20 波内容——与归航定价那次相反,
「以权威为准」要看那条权威有没有被实践检验过。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-31 10:32:41 +08:00 |
|
 joywayerandClaude Opus 5
|
e651072b9b
|
docs: 订正归航手感论证的运动学错误 + 记录定价越权与用户决策
【spec §2.0】原论证只算转弯半径就断言「急转的敌人能甩掉」,从未拿它对照敌人
实际速度 —— 明写此错,并补上缺的那一步运动学核算:跟踪横向速度 v、距离 d 的
目标所需角速度 ω≈v/d,故跟丢条件是 d < v/ω_max(近距离判据)。代入实际数值
(敌 45~140 px/s、弹 ~350 px/s) 重列强度表,标出发版值 1.5、给出各档对最快敌人
的跟丢距离。说明中远距离不是区分点(1.5 与 3.0 余量分别近 5 倍/10 倍,都能可靠
命中),真实失手方式是【近距离过冲】——目标坐进转弯圈内、几何上无法收敛,
而这正是 1.5 想要的手感。叠加表按 1.5 递增重列,堆到必中仍是合法 build 收益。
【spec §2.8】承认原「与 pierce/bounce 对齐」的论证绕过了权威:那两个词条本身
就不在定价表里,拿两个未定价条目互相对齐等于自建平行标准。而
numerical_design.md 确实给 homing 定过价(Tier 3 / Mana 40),且该表是活的权威——
其 Mana 列与 spells.json 每个已实现条目精确吻合,仅 homing 一行偏离。记录用户
决策及其取舍:这个词条能卖同族价,是因为它被调到了同族强度。
【numerical_design.md】homing 行按 P6-N2/N25 同样风格标注:原行删除线保留可
追溯(不抹掉「曾判定为 Tier 3」这个记录),表下补注说明 Homing Force 语义已废
(实现为最大转向角速度 rad/s,与 5.0 不同量纲不可比)、Mana 40 被同族标准取代、
实际发版 homing 1.5 / Mana 8 / 商店 18,并链接 spec。
【architecture_design.md】§4.2 冷数据注释的示例值 3.0 → 1.5(含转弯半径 233px)。
【plan】Task 1 Step 5/6 的 JSON 与断言期望值同步为 1.5;验收⑧(Step 6/6b)重跑
并更新为 folded=3.00 / e2e_2stack=3.000 / e2e_1stack=1.500;Step 8b 补设计器
往返与 SpinBox 格点确认输出。新增顶部醒目段落说明【机制测试①②③④⑦里的 3.0
是测试局部值、与发版值刻意解耦】——平衡调整不应导致机制测试失败,不要为了
数字一致去改它们;唯一应随发版值走的是⑧。Step 7 注明平衡调整不影响性能守卫
(强度只进转向数学,不参与决定 query_circle 频率的任何分支),未重跑。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-30 18:13:58 +08:00 |
|
 joywayerandClaude Opus 5
|
4b12ffbfb1
|
fix(homing): modifier_homing 强度 3.0 → 1.5 rad/s,使 8 蓝同族定价名副其实
发版前平衡复核发现 3.0 rad/s 名不副实:spec §2.0 声称「急转的敌人能甩掉」,
但只算了转弯半径、从未对照敌人实际速度。敌人 45~140 px/s vs 子弹 350 px/s,
400px 接近过程(~1.14s)里最快敌人只需约 0.38 rad 航向修正,而 3.0 rad/s 可转
3.4 rad —— 余量近 10 倍,实际是「稳定命中」而非「中度制导」。
1.5 rad/s → 转弯半径 233px,对最快敌人(140px/s)在 93px 内跟丢(d < v/ω),
贴脸急转真能甩掉,兑现原批准的设计意图。
mana_cost / shop_cost 不动(8 / 18,与 pierce/bounce 同族)。选「降强度」而非
「抬价到 numerical_design.md 原定的 Tier 3 / Mana 40」,因后者会牵动整条 Tier 3
定价与玩家蓝池预算,属另一次立项。
实测:单层 e2e=1.500、两层折叠 e2e=3.000、设计器往返无损(1.5 正落在
SpinBox step=0.05 格点)、商店池仍可抽。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-30 18:13:26 +08:00 |
|
 joywayerandClaude Opus 5
|
a119ec9ab1
|
docs(arch): 补删 ProjectileDef.reset() 里遗留的 homing_force 赋值
上一提交删了声明与注释、漏了 31 行后 reset() 内的赋值,
导致同一代码块自相矛盾(注释声明该字段不存在,正文仍在赋值)。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-30 17:47:56 +08:00 |
|
 joywayerandClaude Opus 5
|
3e45ef0059
|
docs: 计划回填实际执行的验收脚本 + 订正权威文档自相矛盾处 + 性能数字改区间
【计划 Task 4】原稿四个脚本有缺陷,照它复跑会得到假失败与空通过,现已替换为
实际执行并通过的版本,每处旁注「原脚本为何有缺陷」,并勾上完成的复选框:
- Step 2 敌人摆位 (400,200) 距原点 447px 已出 homing_range=400,实测 FAILS=1;
这是测试摆位错误而非实现缺陷(精确距离过滤行为正确)。改到 (300,150)。
- Step 6 内联复刻了折叠逻辑与商店谓词——在测自己;改调真实 _apply_modifier
与 ShopManager._available_pool(),另补 compile_wand→execute_compiled 端到端。
- Step 7 无墙钟起搏,40 帧全停在退避窗内、守卫沦为空断言;且几何让子弹直穿
敌人簇,多计约 1.5ms 碰撞开销。改为 60fps 起搏 + spec §5.2 环形摆位,
frame1 与稳态峰值分开报。
- Step 8 只对源码 grep 字符串,不是往返;改为真实实例化 spell_tab 对真实
spells.json 做 8 条 type-1 的回读→写回比对。
回溯表补「观测方式」列,标出⑥是唯一一条状态推断而非直接观测。
【architecture_design.md】同一文档内自相矛盾:
- CastStats 块 homing_force(「归航强度,向最近敌人偏转」)与 §4.2 新写的
「最大转向角速度 + 锁定式目标」冲突 → 订正为 homing_add(弧度/秒);
顺带订正确证过的 pierce_add / bounce_add(原写 *_count)。该块其余字段
仍有既有漂移,加 ⚠️ 注明未核对、以 cast_stats.gd 为准,不扩大改动范围。
- ProjectileDef 的 homing_force 删除——projectile_def.gd 无任何 homing 字段,
归航冷数据由 _push_projectile 直接写入 BulletManager。
- §4.2 bounce 协同散文补上实际存在的 if cold.has("homing_strength") 前置守卫。
- get_nearest_pos 代码片段:_enemy_count → _active_count(前者不存在)、
未命中返回值 Vector2.ZERO → origin、删除不存在的 _visible_flags 过滤。
【spec】
- §4 第⑥条措辞「不触发 query_circle」字面为假(_check_collision 每帧无条件
发一次),改为「不因归航触发」,并写明这是唯一一条间接验证及其封闭性论证。
- §5.5 峰值改为区间表述(① 4~5ms / ② 5~7ms @1500),注明编辑器/调试构建、
运行间离散(同场景三次得 5.61/5.09/7.29ms),判定回归看是否出现周期性复发
尖峰与是否越过 16.67ms,勿拿单值比对;并记录几何对测量的影响。
- §5.4 勘误:「1493 个互异到期值」不可能成立(jitter 只能产出约 200 个整数值,
同帧失败又共用同一 now),复测为跨度 223ms / 222 个互异值,结论不变。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-30 17:33:16 +08:00 |
|
 joywayerandClaude Opus 5
|
4b09cd1064
|
fix(homing): 抖动公式的整数除法加 @warning_ignore,消掉 INTEGER_DIVISION 告警
(bullet_idx * HOMING_RETRY_MS) / maxi(1, _active_count) 的截断是有意的 ——
抖动只需毫秒粒度的偏移,小数部分丢弃即所需语义。加注解让编辑器面板对
项目文件保持零告警,使验收标准⑩「无告警」真正成立。
行为不变(注解为编译期),复测:①②③ FAILS=0 / ah=0.25000 / max_step=0.050000
/ 速率 350.0000;1500 弹同帧集体失败的到期时刻跨度 223ms、222 个互异值,抖动照常生效。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-30 17:32:43 +08:00 |
|
 joywayerandClaude Opus 5
|
14136b1223
|
docs: 退役 P6-N2/P6-N25 并订正 §4.2 归航设计——删除快照的连带订正
E1-③ 归航实现删除了 _enemy_pos_snapshot 与 EnemyManager.fill_pos_snapshot
(锁定式目标需 entity_id,快照按槽位存位置不含 id),权威文档随之失准,一并订正:
- docs/README.md:P6-N25(快照须为类成员)与 P6-N2(Homing 弹共用快照)双双失去
约束对象,改为删除线 + ⚠️ 已退役(2026-07-30) 并指向 spec §2.4/§2.7。不删条目,
避免编号规范留下悬空引用。
- architecture_design.md §4.2:homing 伪代码整段改写为实际算法——冷数据
homing_strength(弧度/秒)/homing_range/homing_target_id、发射不解析目标首帧惰性
锁定、仅目标失效时经 _find_nearest_unvisited 重选、wrapf 最短转向 + clampf 限
角速度 + rotated() 保速率、空场守卫、失败退避+抖动、bounce 协同改写目标并撤销
退避键。性能数字一律指向 spec §5,不另起一套。
- 冷数据字段表 homing_force → homing_strength/homing_range/homing_target_id。
- EnemyManager API:fill_pos_snapshot 换成实际存在的 get_pos_by_id(含哨兵约定);
get_nearest_pos 与自动瞄准改为「直接扫描 SoA」,原文称与 homing 快照共用属误述。
- S0 性能表 EnemyManagerCs 行标注该实测含已删除的 fill_pos_snapshot(保留历史数字)。
- MinionManager.fill_pos_snapshot 标注为未实现提案,并纠正其「供 homing 用」的注释。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-30 17:01:56 +08:00 |
|
 joywayerandClaude Opus 5
|
d498097005
|
docs(roadmap): E1-③ 子弹归航完成,勾除现状项 + 记录快照删除这一有意偏离
「现状」归航行与切分列表第 3 项改为完成态,格式对齐已完成的 ①②。
显式记录与本文档原方案的偏离:未消费 _enemy_pos_snapshot 而是删除之 ——
锁定式目标需 entity_id,而快照按槽位存位置、不含 id,结构上支撑不了该语义。
另记退避 + 抖动这一同期落地的性能措施(详见 spec §5)。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-30 16:54:13 +08:00 |
|
 joywayerandClaude Opus 5
|
df81e9eafa
|
style(homing): 设计器 homing 标签补单位提示「弧度/秒」
3.0 这个值形似 0~1 的强度系数,不标单位易被误读为「归航强度」而调错量级。
文件内已有括号提示先例(如「n(每 n 次)」)。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-30 16:40:11 +08:00 |
|
 joywayerandClaude Opus 5
|
55f96e1a1c
|
feat(homing): 设计器 MODIFIER 表单加 homing 字段,并补上期遗漏的 bounce 字段
bounce 自上期起一直掉在「其它(JSON)」逃生舱,违反 CLAUDE.md 字段化规范,
与 homing 同处 schema,一并补上。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-30 16:30:10 +08:00 |
|
 joywayerandClaude Opus 5
|
ffc75acead
|
docs(spec): §5.6 触发条件改为弹数阈值 + 新增 §5.7 退避墙钟不免疫时间缩放
§5.6:把重新立项的触发条件从场景描述改为可直接计算的弹数阈值 —— 成本严格线性于
「同帧创建且首次选目标全部失败的归航弹数」约 9.5µs/颗,附 200/500/1000/1750 颗的
对照表,约 1750 颗为理论击穿点(MAX_BULLETS=2048 故容量内可达)。并注明 visited
类场景因 visited_targets 线性扫描,实测高于线性外推,实际击穿点更低。
§5.7 新增潜在项(休眠,不修):退避基于 Time.get_ticks_msec() 是墙钟,不受
Engine.time_scale 影响,而 TimeManager 正是为慢动作/冻结时间 Core 驱动 time_scale 的。
grep 确认 set_time_scale 当前零调用方,故今日无害;若落地 0.2× 慢动作,200ms 只跨
约 2.4 个物理帧而非 12,抖动摊薄失效,且表现为慢动作期间掉帧。
记录替代方案(触发时再实施):改用物理帧计数 HOMING_RETRY_FRAMES=12,免疫时间缩放、
略便宜、消除 ms↔帧量纲错配;项目已有现成的 TimeManager.game_tick 且注释明写不受
time_scale 影响,正合用。触发条件为 set_time_scale 出现第一个调用方。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-30 16:26:36 +08:00 |
|
 joywayerandClaude Opus 5
|
28f4047096
|
fix(homing): bounce 协同路径遗留过期退避键,使子弹对着尸体转向且拒绝重新锁定
homing_target_id 有两个写入方,不变式「homing_retry_at 只在目标无效时才有意义」
只在其中一方成立:_apply_homing 重选成功时会 erase 该键,bounce 那行不会。
后果是一颗 bounce+homing 子弹若先经历过一次重选失败、再弹跳到 next_id、而 next_id
随即死亡(弹跳目标是刚打过的敌人,随即死亡是常态),它会对着尸体继续转向,并在
残留退避窗口内(最多 400ms ≈ 24 帧)拒绝重新锁定,哪怕 50px 外就有活敌人。
这恰好废掉了那行 bounce 协同代码存在的意义。
修法与重选成功路径对称,补一行 cold.erase("homing_retry_at")。运行时复现确认:
阶段1 重选失败 -> retry_at 存在=true, tgt=-1
F bounce 后: tgt=3 (expect 3) retry_key_still_present=false (修前 true)
F 目标死亡后能否立刻重选: tgt=4 重选成功=true (修前被残留退避压住停在 3)
另两处:
- 调用方守卫注释的「省约 87%」改为 64% —— 87% 出自代理微基准推算,已被真实
端到端实测(2.107→1.812ms)推翻,热路径里挂陈旧乐观数字会误导后来人判断该守卫去留。
- jitter 取模的 6 行不可达性论证压缩为一行(运算保留作索引越界兜底,成本为零)。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-30 16:26:17 +08:00 |
|
 joywayerandClaude Opus 5
|
4ef8012b6e
|
docs: 首帧锁定尖峰决策为「接受」+ Task4 Step7 改为两场景单帧峰值回归守卫
spec §5.6:残余的首帧尖峰(1500 弹同帧创建且首次选目标全失败时 16~22ms)
决策接受不处理——触发条件是三个苛刻条件的合取属合成最坏情况、一次性不复发、
压下它需牺牲「首次锁定即时」的手感或改变归航/bounce 语义。附重新立项触发条件。
plan Task4 Step7:原只测「敌人全在射程外」,补上评审发现的更严重场景
「射程内全在 visited」(visited 只增不减故为永久状态);指标由 60 帧均值
改为单帧峰值——退避把成本摊成 1 重选帧 + 11 退避帧,均值会掩盖尖峰,
而帧预算 16.67ms 下尖峰才是玩家可见的。性质由决策关卡降级为回归守卫。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-30 16:15:01 +08:00 |
|
 joywayerandClaude Opus 5
|
5cc40e72e8
|
docs(spec): §5 补「朴素退避会同步而非打散」二次发现 + 抖动方案 + 单帧峰值对比
新增 §5.4「二次发现」:固定退避下尖峰每 12 帧复发(附逐帧耗时序列证据),
根因是同帧失败的子弹到期时刻相同、被退避锁进同相;这与「退避能摊薄尖峰」的
直觉相反,且摊薄均值会掩盖它 —— 后来人写类似退避/重试逻辑会踩同一个坑,故写清。
含抖动实现、为何用占比式而非 bullet_idx % 窗口宽度、HOMING_RETRY_MS 一值两用的理由。
§5.5 抖动前后单帧峰值对比表(稳态峰值全部回到帧预算内,超预算帧数 0/39)。
§5.6 记录残余:初次锁定帧(1500 弹 16.2/22.0ms)非退避问题,而是「首次锁定即时」
手感属性的直接结果,压下它需牺牲手感,属设计决策,未擅自处理。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-30 16:13:00 +08:00 |
|
 joywayerandClaude Opus 5
|
71240931af
|
perf(homing): 退避到期时刻加抖动,消除每 12 帧复发的集体重试尖峰
二次发现:固定 200ms 退避并没有消除尖峰,只是让它变成周期性复发。按真实 60fps
起搏复测,1500 弹 visited 场景逐帧耗时在第 1/13/25/37 帧稳定出现 ~21ms,永不衰减:
21.9 2.8 2.9 ... 3.1 | 21.8 2.8 ... | 21.0 2.9 ... | 20.9 3.7 3.9 3.8
根因是朴素退避会把子弹锁进同相而非打散 —— 同帧失败的子弹拿到同一个 now,到期时刻
完全相同,一个退避周期后又整齐地一起重试;同波齐射本就天然同相,此后再无机会错开。
摊薄后的均值数字恰恰掩盖了这一点。
修法是抖动到期时刻,铺满 [200,400) ms ≈ 恰好一个退避周期 ≈ 12 帧。
用「bullet_idx 在活跃弹数中的占比」而非 bullet_idx % HOMING_RETRY_MS:后者在弹数少于
窗口宽度时只铺开 _active_count 毫秒(20 颗弹 → 20ms ≈ 1.2 帧,等于没打散)。
实测打散质量:1500 颗同帧集体失败 → 互异到期值 1493 个、覆盖 14 帧、单帧最多 120 颗
(理想 125)。
单帧峰值(60fps 起搏 40 帧,稳态即排除初次锁定帧):
① 全射程外 1500 13.6~15.7ms 复发 → 4.40ms 300 3.2ms → 0.92ms
② 全 visited 1500 20.9~21.9ms 复发 → 5.61ms 300 4.6ms → 1.15ms
稳态超 16.67ms 的帧数均为 0/39。
首次锁定即时的行为未受影响(抖动只作用于失败后的重试),速率守恒、单帧转角上限、
退避窗口内零查询、到期后重试成功并 erase 键,断言全绿。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-30 16:12:40 +08:00 |
|
 joywayerandClaude Opus 5
|
3bf04c9fc0
|
docs(spec): R-H1 由「暂不实现」改为「已实测触发并启用」,补两种病态状态实测数据
如实记录:
- 原风险分析只预见「敌人全在射程外」,漏掉「射程内敌人全在 visited_targets 里」——
后者经 bounce+homing 组合是该子弹的永久状态而非瞬态,且成本更高,是本次发现;
原文把 R-H1 定性为瞬态尖峰不准确。
- 实测两种场景在 300 弹规模已达 3.14 / 4.34 ms,越过本节自定的 2.0 ms 触发线,
故方案 3(0.2s 退避)随 Task 2 落地,摊薄约 12×。
- 残余未收敛项另立 §5.4:1500 弹摊薄后仍 3.9 / 4.5 ms,且退避会使同波齐射的
子弹同步重试、留下 15.9 / 22.2 ms 单帧尖峰;错帧方案待决策,本次未擅自扩大范围。
§2.4 补一句指向 §5,避免「一生只查 1–2 次」与失败路径重试自相矛盾。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-30 16:04:03 +08:00 |
|
 joywayerandClaude Opus 5
|
c9786eba50
|
fix(bullet): _swap_and_pop 回收末尾子弹时遗留冷数据,被下一颗复用槽位的子弹继承
pre-existing bug(非本期归航引入):冷数据的搬移与擦除都写在 if idx != last 分支内,
故 idx == last(回收最后一颗子弹)时它的 _bullet_contexts[idx] 被原样留在该 key 上,
下一颗复用该槽位的普通子弹会继承整份冷数据。运行时已复现:
after recycle: active=0 ctx_keys=[0]
plain bullet idx=0 inherits_cold=true cold={"homing_strength":3.0,...,"pierce_remaining":7}
归航之前症状只是一次隐形的多余穿透,故长期未被发现;归航把它放大成肉眼可见的
「普通子弹拐弯追敌」,且继承 homing 的幽灵弹会持续走重选路径付出查询开销。
修法是把 erase 移出该 if(缺键时 erase 为安全 no-op),idx != last 的搬移行为一行不改。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-30 16:02:39 +08:00 |
|
 joywayerandClaude Opus 5
|
2f9cb76308
|
perf(homing): 重选失败退避 0.2s + homing 判别提到调用方
评审实测发现两种病态状态下重选会每帧无限重试,query_circle(r=400) 进入热路径:
① 敌人在场但全在 homing_range 外;② 射程内敌人全在 visited_targets 里
(bounce+homing 打空小簇后是该子弹的永久状态,原 spec 风险分析漏掉了这种)。
1500 弹实测 15.8ms / 22.0ms,300 弹 3.1ms / 4.3ms,均越过 spec §5 的 2.0ms 触发线,
故 spec §5 记录的逃生方案(方案 3)提前落地:重选失败写 homing_retry_at 时间戳,
HOMING_RETRY_MS(200ms) 内直行不再查询,60fps 下摊薄约 12×。
首次锁定不受影响(无该键时 get 返回 0 必小于 now),手感不回退;
重选成功即 erase 该键,恢复零查询稳态。
homing 判别 _bullet_contexts[i].has("homing_strength") 提到 _gd_integrate 调用方:
带冷数据但不归航的子弹(纯 pierce/bounce/状态/荷载,真实 build 里占多数)不再
为发现自己不归航而付一次完整函数调用 —— 1500 纯 pierce 弹实测 2.107→1.812ms。
_apply_homing 内的 strength <= 0.0 早退保留作防御性下限。
同步订正两处失准注释:_find_nearest_unvisited 现也是归航选目标器;
_apply_homing 文档注释补齐失败路径的重试/退避策略。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-30 16:01:31 +08:00 |
|
 joywayerandClaude Opus 5
|
b3b04fcbda
|
feat(homing): bullet_manager 受限角速度转向 + 锁定式目标重选 + bounce 协同; 删除无人消费的位置快照
_apply_homing 在位置积分前把速度矢量朝目标旋转,单帧转角上限 strength*delta,
rotated() 保持速率不变;wrapf 取最短转向方向。
目标仅在失效或首帧时经 _find_nearest_unvisited 重选,配 get_active_count()==0
空场守卫,避免 query_circle(r=400) 进入每帧热路径。
bounce 命中重定向时改写 homing_target_id,由 bounce 选目标 homing 追上去。
删除 _enemy_pos_snapshot 及 EnemyManager.fill_pos_snapshot(全项目唯一调用方)。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-30 15:40:55 +08:00 |
|
 joywayerandClaude Opus 5
|
0a6f0e95d5
|
style(homing): 评审抛光——JSON 列对齐 + 注释精度(无行为变更)
1. spells.json: modifier_homing 的 description 补一空格对齐到第 72 列,
与相邻 type 1 条目一致,避免错位被复制传播。
2. cast_stats.gd: homing_add 注释改用全角括号与相邻行统一;措辞明确为
「最大转向角速度」——按 spec §2.1 该值是 clampf 上界而非实际角速度,
原措辞可能误导调平衡的人设错值。
3. spell_evaluator.gd: 分支快照注释点明 pierce_add 是已知 pre-existing
遗漏而非笔误,防止后来人把「10 字段」误读为「全部字段」。
4. spell_evaluator.gd: 归航冷数据块加注 homing_range 同 bounce_range/
bounce_decay 仅从 ACTION meta 读取,MODIFIER 覆盖静默失效(一致行为,
非回归),省掉后来人一次 debug。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-30 15:35:56 +08:00 |
|
 joywayerandClaude Opus 5
|
5663dedc12
|
feat(homing): CastStats.homing_add + 修饰器折叠 + 发射写归航冷数据 + 分支快照; modifier_homing 词条
homing_add 为 float(角速度,弧度/秒),镜像 bounce_add 的 int 累加路径。
发射时不解析目标,homing_target_id 留 -1 由 bullet_manager 首帧惰性获取,
使 spell_evaluator 不必接触 SpatialGrid。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-30 15:24:17 +08:00 |
|
 joywayerandClaude Opus 5
|
364ebe4c62
|
docs(plan): E1-③ 子弹归航逐任务实现计划(5 任务 · 含 wrapf 跨 ±π 判据与 R-H1 性能守卫)
Task0 建分支 / Task1 法术 VM 侧 / Task2 bullet_manager 转向+删死快照 /
Task3 设计器字段(含补漏的 bounce)/ Task4 MCP 运行时验收。
验收脚本全部用确定性数值断言:单帧转角上限、速率守恒、跨 ±π 的最短转向
(该摆位下有无 wrapf 会给出符号相反的结果,是有效判据)、目标失效重选、
空场直行、bounce 协同改写 homing_target_id、两层折叠 6.0。
Task4 Step7 实测 spec R-H1 病态场景(50 敌全在射程外 + 300 归航弹),
超 2ms/帧则按 spec §5 启用失败退避逃生方案。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-30 13:51:18 +08:00 |
|
 joywayerandClaude Opus 5
|
049d1dda1b
|
docs(spec): E1-③ 子弹归航设计——受限角速度中度制导 + 锁定式目标 + 删除无人消费的位置快照
手感定位为中度制导:homing_strength 即最大转向角速度(rad/s),
单层词条 3.0(350 速度下转弯半径 117px),rotated() 保持速率不变。
目标策略为发射后锁定,仅在目标死亡(get_pos_by_id 返回哨兵)或首帧时
经 _find_nearest_unvisited 重选,配 get_active_count()==0 空场守卫,
避免 query_circle(r=400, 约196格且每次新建数组)进入每帧热路径。
与 bounce 协同:bounce 命中重定向时改写 homing_target_id,
由 bounce 选目标、homing 追上去;复用 visited 过滤规避"绕已命中敌打转"死循环。
偏离路线图原文:锁定语义需 entity_id,而 _enemy_pos_snapshot 按槽位存位置
不含 id,无法支撑,故快照连同 EnemyManager.fill_pos_snapshot 一并删除
(全项目唯一调用方),净减每帧 O(敌人数) 开销。
顺带补设计器 MODIFIER schema 遗漏的 bounce 字段(现掉在 JSON 逃生舱里)。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-07-30 13:36:42 +08:00 |
|
joywayer
|
d6061d0f50
|
更新mcp client
|
2026-07-30 11:41:08 +08:00 |
|
 joywayerandClaude Opus 4.8
|
04e8cf9c09
|
docs(spec): 明确 bounce+pierce 组合语义——visited 持续使每敌至多命中一次(刻意,非bug)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
2026-07-24 15:28:31 +08:00 |
|
 joywayerandClaude Opus 4.8
|
bf9bea78d8
|
docs(roadmap): E1-② 子弹弹跳完成,勾除现状项 + 修正 Step3 为确定性速度判据
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
2026-07-24 15:21:26 +08:00 |
|
 joywayerandClaude Opus 4.8
|
3eb6049b39
|
feat(bounce): bullet_manager 命中弹跳分支(优先于pierce)+跳过已访问+_find_nearest_unvisited 寻的
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
2026-07-24 15:11:16 +08:00 |
|
 joywayerandClaude Opus 4.8
|
6b910697a9
|
feat(bounce): CastStats.bounce_add + 修饰器折叠 + 发射写弹跳冷数据 + 分支快照; modifier_bounce 词条
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
2026-07-24 15:00:27 +08:00 |
|
joywayer
|
e5cf6089ed
|
docs(spec): 弹跳补充——命中循环跳过已访问敌人(防密集群重复命中)
|
2026-07-24 14:56:49 +08:00 |
|
joywayer
|
9403f80aa4
|
docs(plan): E1-② 子弹弹跳逐任务实现计划(3 任务·含密集群跳过已访问·SpatialGrid.insert 实测)
|
2026-07-24 14:56:37 +08:00 |
|
 joywayerandClaude Opus 4.8
|
4a86ffb2c4
|
docs(spec): E1-② 子弹弹跳设计——镜像 pierce 管线 + 命中弹向最近未命中敌+伤害递减
缺失功能路线图 E1 子计划②。冷数据 bounce_remaining/visited_targets/decay/range;
CastStats.bounce_add + _apply_modifier 折叠 + _push_projectile 写 cold(含分支快照);
_check_collision 弹跳分支(bounce优先于pierce)+_find_nearest_unvisited;modifier_bounce 词条。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
2026-07-24 14:44:53 +08:00 |
|
 joywayerandClaude Opus 4.8
|
cd5f4d5892
|
docs(roadmap): E1-① 元素抗性完成,勾除现状项(含 DOT 抗性已知限制→E2)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
2026-07-24 12:12:32 +08:00 |
|
 joywayerandClaude Opus 4.8
|
a17e3aa2af
|
feat(resist): 设计器敌人页增元素抗性网格(6×5) + _save 写 resistances(全0省略)
主表下方加 6原型×5元素(火/冰/雷/毒/奥) SpinBox 网格(-0.9~0.9);_save 汇总
非零抗性写入 resistances,全0则省略键。读写往返 MCP 实测 FAILS=0
(读种子 fire0.5/ice-0.5,写非零、零值省略、负值保留)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
2026-07-24 12:08:11 +08:00 |
|
 joywayerandClaude Opus 4.8
|
fe1d1f690f
|
feat(resist): EnemyManager 元素抗性加载+命中查表;enemies.json Fast 种子抗火弱冰
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
2026-07-24 11:51:53 +08:00 |
|
joywayer
|
abe057edf8
|
docs(plan): E1-① 元素抗性逐任务实现计划(3 任务 · lambda-MCP 实测)
|
2026-07-24 11:49:51 +08:00 |
|
 joywayerandClaude Opus 4.8
|
e87e453abf
|
docs(spec): E1-① 元素抗性设计——apply_damage_from_context 查表 + enemies.json resistances + 弱点(负抗)
缺失功能路线图 E1 子计划①。元素链路已通,仅补敌人抗性数据+命中查表:
enemies.json 每型可选 resistances{元素名:-0.9~0.9},EnemyManager 按 ctx.damage_type
查表传入 calc_damage(0,res);护甲不动;物理无抗性;设计器加抗性网格。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
2026-07-24 11:45:28 +08:00 |
|
 joywayerandClaude Opus 4.8
|
83dc1196ae
|
docs(roadmap): E6-a 玩家无敌帧完成,勾除现状项
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
2026-07-24 09:32:02 +08:00 |
|
 joywayerandClaude Opus 4.8
|
e490e6075a
|
feat(iframe): 设计器平衡页增 player_iframe_sec 栏;_save 改合并式修复丢键
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
2026-07-24 09:27:28 +08:00 |
|
 joywayerandClaude Opus 4.8
|
f204b919ff
|
feat(iframe): 无敌期间玩家节点 8Hz 方波闪烁反馈
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
2026-07-24 09:23:01 +08:00 |
|
 joywayerandClaude Opus 4.8
|
23644bb40b
|
feat(iframe): PlayerStats.take_damage 时间戳门控无敌窗口 + 复活 PLAYER_DAMAGED emit;移除死订阅
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
2026-07-24 09:18:54 +08:00 |
|