Add rank, friends, fishing, and camp treasure with T2 studio models and skill presentation.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
udx
2026-10-21 23:01:31 +08:00
co-authored by Cursor
parent 89e0fa246f
commit 079313fb06
677 changed files with 395371 additions and 9692 deletions
@@ -0,0 +1,40 @@
# 火喵/岩团团技能闭环样例
2026-10-21完成独立样例。五敌人 Studio 模型已替换正式 PrototypeArena;本页的新技能逻辑则在独立验收场景运行。主线仍是 battleRules=2,未接 battle.begin/battle.events,未重启或部署开发服,未改变旧在途挑战、账号或奖励协议。
## 已完成
- `AIServer/src/combat_slice.hpp/.cpp`:纯 C++ 逻辑内核;50ms整数 tick,千分之一血量/攻击、毫米位置。实现施法通道、主动技能优先、前摇/释放/后摇、冷却、投射物、伤害/护盾、过期、死亡与取消。无 Unity、墙上时钟、数据库依赖;当前只编入独立 combat_slice_tests 目标,未编入线上 aiserver。
- `Config/Combat/skill_slice.json`:隔离样例配置;岩团团前排、火喵后排、三个小角怪。敌人血量为原配置×2以覆盖护盾与近战,属于验收场景参数,不是20关的新平衡。原玩法和技能 proposal 的冻结副本保存在 trace 中,校验其内容及 SHA256。
- `AIClient/Assets/Bundles/Combat/SkillSlice/trace.json`:由 C++ 导出,219为最后 tick、366事件、36次施法、12颗火球、30次唯一命中。客户端只播放事件,不再计算该样例的伤害。`Tools/export_skill_slice.py` 先保存输入原始字节到 `Tools/output/skill_slice_inputs/`,回执 `export.json` 记录输入及轨迹哈希;验证/Play回执绑定同一轨迹哈希,最新配置变化不会混入旧轨迹。
- `SkillSlicePlayer.cs`:前摇、释放、到达和血量变化使用同一播放时钟;原 Attack 按各角色制作配方的 attackImpact 分段采样,火球在到达事件才扣血。拱形弹道仅影响外观;逻辑到达 tick 不变。已经释放的火球不因施法者死亡而撤回;释放前死亡取消。
- 持久化 `SkillSlice.prefab`:五实体的模型/Muzzle/Animator绑定,5类特效、24个池实例、8个技能音源;复用现有敌人反馈池。蓄力按 castId、护盾按 entityId、火球按实例租约清理。音效开关、暂停/恢复、1×/2×、低帧率过期声音跳过、结束/禁用清理已实现。
- 五条 TangoFlux 音效:FireCharge 0.48s、FireLaunch 0.28s、FireHit 0.40s、RockHit 0.32s、Shield 0.65s。按项目指南英文提示、2秒原稿、50步、guidance4.5、并发≤2生成,再裁切/淡入淡出。实际 seed/请求/任务ID/哈希以 `Doc/Design/Sound/BattleSkills/Slice/generation.json` 为准;原始计划 seed 保留在计划表中,没有冒称与生成请求相同。
## 验证与查看
- C++ 30项断言:起手无伤害、延迟到达、同 tick 零前摇护盾、动作互斥、后摇、冷却边界、死亡前取消、释放后存续、丢失目标不换目标、唯一死亡、护盾刷新不叠加、过期、元素防御、确定性与输入边界。
- `Tools/verify_skill_slice.py`:事件顺序/唯一命中/火球到达 tick/冻结输入哈希、五条音效源稿及输出哈希、格式、起音、尾部淡出和零削波通过。人工听感未由自动检查代替;试听 `Doc/Design/Sound/BattleSkills/Slice/preview.wav`。
- Unity实际 Play:火球到达前后血量检查通过;1×、2×、0.73秒低帧率步进的最终血量、护盾、位置、死亡/离场状态与 C++ 一致;暂停不前进、静音、重复结束、禁用清理通过。回执 `assets.json`、`play.json`、`validation.json`。
- 直接打开 `Assets/Bundles/Scenes/Review/SkillSlice_Review.unity` 后 Play 可看独立样例。它不会载入账号或发奖励;结束后保持结果,重进 Play 可重播。未覆盖当前 Boot 场景。
- 截图 `Assets/Screenshots/skill_slice_fireball.png`、`skill_slice_shield.png`。截图为暂停时刻,粒子额外推进30ms刷新几何,仅供视觉检查,不推进逻辑时钟。
## 复现
```powershell
cmake --build AIServer/build-g1 --config Release --target combat_slice_tests
python Tools/export_skill_slice.py
python Tools/verify_skill_slice.py
python Tools/validate_skill_design.py
```
Unity经Pipeline依次运行 `BuildSkillSlice.Build`、`VerifySkillSlice.Assets`;Play中运行 `VerifySkillSlice.Play`,结束后停止。TangoFlux重制入口为 `Tools/generate_skill_slice_sfx.py`,有效源稿按请求哈希复用。
## 后续接入边界
完整25技能、治疗/减速、多路波次、trace分页和网络协议兼容仍待实现;不能把独立样例视为 battleRules=3 主线迁移完成。下一阶段将该内核接入服务端授权战斗与冻结配置,客户端加载权威轨迹,覆盖10伙伴/20关平衡及旧挑战恢复后再切换规则。当前计划音效清单为5/9已生成,Heal/Slow/Lightning/EnemyHit仍待制作。TangoFlux权重依项目指南为非商业研究用途,保留许可核查边界,未宣称商用放行。
## 权威技能协议与正式战场接入(2026-10-21)
后续已将独立样例推广到正式技能协议与全关战场,见 [../Runtime/Production.md](../Runtime/Production.md)。本页保留独立样例的原始制作记录;正式配置、分页、恢复与客户端入口以Runtime文档为准。
+9
View File
@@ -0,0 +1,9 @@
{
"status": "pass",
"prefab": "Assets/Bundles/Combat/SkillSlice/SkillSlice.prefab",
"actors": 5,
"effectKinds": 5,
"poolInstances": 24,
"voices": 8,
"audioClips": 5
}
+27
View File
@@ -0,0 +1,27 @@
{
"status": "exported",
"inputs": [
{
"source": "Config/Gameplay/greenfield.json",
"snapshot": "Tools/output/skill_slice_inputs/greenfield.json",
"field": "frozenGameplay",
"sourceSha256": "2787887803fd365816e0d7d3f3a06386daddb1bbf08d0e7e40a9ec5393d6d5e2",
"payloadSha256": "5c2229d1c4701d889b239ff036966bd1dab872eeccf202c0e1726f5d7a6a32a4"
},
{
"source": "Config/Combat/skill_system_v1.proposal.json",
"snapshot": "Tools/output/skill_slice_inputs/skill_system_v1.proposal.json",
"field": "skillDefinitions",
"sourceSha256": "9749629b3914ec9135389f2f6ccaffb072010c26feb7d2680e90ae9f4994fc6c",
"payloadSha256": "5b64a277ee3d246e864f20285406ec8087756a6d7ae4a66c0779377c6e594df6"
},
{
"source": "Config/Combat/skill_slice.json",
"snapshot": "Tools/output/skill_slice_inputs/skill_slice.json",
"field": "scenario",
"sourceSha256": "2af74ebfca1dd556b5512efcc18983aa99a3ebca34b0f22776dc4aef1b178607",
"payloadSha256": "5e429157decd5ad6a1ef7d3c16f9cc08498942ff09c29450d85dbf841b7c0de8"
}
],
"traceSha256": "cb5e34b8c625d58700cff87aec357764f475bb1db19208a006320eb209124827"
}
@@ -0,0 +1,23 @@
[
{
"name": "Vfx_Skill_Fireball",
"count": 1,
"position": "(200.00, 1.80, 0.08)",
"bounds": "Center: (199.99, 1.79, 0.11), Extents: (0.32, 0.32, 0.32)",
"layer": 30
},
{
"name": "BrightCore",
"count": 1,
"position": "(200.00, 1.80, 0.08)",
"bounds": "Center: (200.03, 1.82, 0.07), Extents: (0.14, 0.14, 0.14)",
"layer": 30
},
{
"name": "Vfx_Skill_Shield",
"count": 1,
"position": "(200.00, 0.80, 0.48)",
"bounds": "Center: (199.99, 0.81, 0.45), Extents: (1.46, 1.46, 1.46)",
"layer": 30
}
]
@@ -0,0 +1,23 @@
[
{
"name": "Vfx_Skill_FireHit",
"count": 14,
"position": "(200.00, 0.80, 0.77)",
"bounds": "Center: (200.01, 0.81, 0.76), Extents: (0.18, 0.17, 0.16)",
"layer": 30
},
{
"name": "ImpactRing",
"count": 1,
"position": "(200.00, 0.80, 0.77)",
"bounds": "Center: (200.01, 0.76, 0.78), Extents: (1.31, 1.31, 1.31)",
"layer": 30
},
{
"name": "Vfx_Skill_Shield",
"count": 1,
"position": "(200.00, 0.80, 0.48)",
"bounds": "Center: (200.00, 0.77, 0.48), Extents: (1.46, 1.46, 1.46)",
"layer": 30
}
]
+19
View File
@@ -0,0 +1,19 @@
{
"status": "pass",
"traceSha256": "cb5e34b8c625d58700cff87aec357764f475bb1db19208a006320eb209124827",
"authoritativeCppTrace": true,
"productionRulesChanged": false,
"events": 366,
"won": true,
"pause": true,
"speed2": true,
"lowFrameRate": true,
"arrivalDamage": true,
"finalStateExact": true,
"mute": true,
"disableCleanup": true,
"liveSounds": 44,
"fireballScreenshot": true,
"shieldScreenshot": true,
"networkAccountWrites": false
}
@@ -0,0 +1,49 @@
{
"status": "pass",
"events": 366,
"casts": 36,
"projectiles": 12,
"hits": 30,
"deaths": 3,
"traceSha256": "cb5e34b8c625d58700cff87aec357764f475bb1db19208a006320eb209124827",
"frozenInputs": {
"Config/Gameplay/greenfield.json": "2787887803fd365816e0d7d3f3a06386daddb1bbf08d0e7e40a9ec5393d6d5e2",
"Config/Combat/skill_system_v1.proposal.json": "9749629b3914ec9135389f2f6ccaffb072010c26feb7d2680e90ae9f4994fc6c",
"Config/Combat/skill_slice.json": "2af74ebfca1dd556b5512efcc18983aa99a3ebca34b0f22776dc4aef1b178607"
},
"currentSourceChanged": [],
"audio": [
{
"id": "Sfx_FireCharge",
"seconds": 0.48,
"rmsDb": -14.407821284878423,
"clippedSamples": 0
},
{
"id": "Sfx_FireLaunch",
"seconds": 0.28,
"rmsDb": -14.786814954199185,
"clippedSamples": 0
},
{
"id": "Sfx_FireHit",
"seconds": 0.4,
"rmsDb": -12.397172372455682,
"clippedSamples": 0
},
{
"id": "Sfx_RockHit",
"seconds": 0.32,
"rmsDb": -17.7350875982902,
"clippedSamples": 0
},
{
"id": "Sfx_Shield",
"seconds": 0.65,
"rmsDb": -14.618990028368117,
"clippedSamples": 0
}
],
"subjectiveListening": "not_asserted",
"productionIntegrated": false
}