summer-engine 3.0.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (413) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +27 -5
  3. package/.codex-plugin/plugin.json +28 -6
  4. package/.cursor-plugin/plugin.json +27 -5
  5. package/.factory-plugin/plugin.json +27 -5
  6. package/.opencode/plugins/summer.js +1 -1
  7. package/CHANGELOG.md +120 -0
  8. package/README.md +22 -7
  9. package/assets/audit/scene_audit.gd +4136 -0
  10. package/assets/seeing/seeing_probe.gd +1873 -0
  11. package/dist/cli/commands/setup.js +6 -19
  12. package/dist/cli/commands/skills.js +57 -32
  13. package/dist/core/api-client.d.ts +9 -1
  14. package/dist/core/api-client.js +21 -4
  15. package/dist/core/capabilities/agent-playbook.js +46 -0
  16. package/dist/core/capabilities/audit/accept.d.ts +55 -0
  17. package/dist/core/capabilities/audit/accept.js +147 -0
  18. package/dist/core/capabilities/audit/args.d.ts +95 -0
  19. package/dist/core/capabilities/audit/args.js +89 -0
  20. package/dist/core/capabilities/audit/audit.d.ts +56 -0
  21. package/dist/core/capabilities/audit/audit.js +287 -0
  22. package/dist/core/capabilities/audit/frame.d.ts +14 -0
  23. package/dist/core/capabilities/audit/frame.js +35 -0
  24. package/dist/core/capabilities/audit/gaps.d.ts +96 -0
  25. package/dist/core/capabilities/audit/gaps.js +257 -0
  26. package/dist/core/capabilities/audit/judge.d.ts +162 -0
  27. package/dist/core/capabilities/audit/judge.js +1134 -0
  28. package/dist/core/capabilities/audit/math.d.ts +110 -0
  29. package/dist/core/capabilities/audit/math.js +263 -0
  30. package/dist/core/capabilities/audit/summary.d.ts +74 -0
  31. package/dist/core/capabilities/audit/summary.js +212 -0
  32. package/dist/core/capabilities/board.d.ts +31 -0
  33. package/dist/core/capabilities/board.js +43 -0
  34. package/dist/core/capabilities/camera-view.d.ts +4 -2
  35. package/dist/core/capabilities/camera-view.js +6 -3
  36. package/dist/core/capabilities/connect-signal.d.ts +85 -0
  37. package/dist/core/capabilities/connect-signal.js +285 -0
  38. package/dist/core/capabilities/engine-fallbacks.d.ts +5 -0
  39. package/dist/core/capabilities/engine-fallbacks.js +5 -0
  40. package/dist/core/capabilities/engine-ops.d.ts +5 -1
  41. package/dist/core/capabilities/engine-ops.js +0 -3
  42. package/dist/core/capabilities/engine-receipt.d.ts +12 -0
  43. package/dist/core/capabilities/engine-receipt.js +26 -0
  44. package/dist/core/capabilities/file-read.d.ts +64 -0
  45. package/dist/core/capabilities/file-read.js +325 -0
  46. package/dist/core/capabilities/game-task-plan.js +4 -2
  47. package/dist/core/capabilities/grep.d.ts +60 -0
  48. package/dist/core/capabilities/grep.js +190 -0
  49. package/dist/core/capabilities/inspect-node.d.ts +56 -0
  50. package/dist/core/capabilities/inspect-node.js +225 -0
  51. package/dist/core/capabilities/inspect-resource.d.ts +61 -0
  52. package/dist/core/capabilities/inspect-resource.js +376 -0
  53. package/dist/core/capabilities/math3d.d.ts +28 -0
  54. package/dist/core/capabilities/math3d.js +88 -0
  55. package/dist/core/capabilities/motion-generation.d.ts +62 -0
  56. package/dist/core/capabilities/motion-generation.js +138 -0
  57. package/dist/core/capabilities/placement-batch.d.ts +102 -0
  58. package/dist/core/capabilities/placement-batch.js +483 -0
  59. package/dist/core/capabilities/placement-math.d.ts +70 -0
  60. package/dist/core/capabilities/placement-math.js +209 -0
  61. package/dist/core/capabilities/placement-script.d.ts +42 -0
  62. package/dist/core/capabilities/placement-script.js +1096 -0
  63. package/dist/core/capabilities/placement.d.ts +485 -0
  64. package/dist/core/capabilities/placement.js +1731 -0
  65. package/dist/core/capabilities/project-context.d.ts +33 -2
  66. package/dist/core/capabilities/project-context.js +87 -4
  67. package/dist/core/capabilities/replace-node.d.ts +91 -0
  68. package/dist/core/capabilities/replace-node.js +423 -0
  69. package/dist/core/capabilities/runtime-control.d.ts +20 -4
  70. package/dist/core/capabilities/runtime-control.js +67 -2
  71. package/dist/core/capabilities/scene-batch.d.ts +63 -0
  72. package/dist/core/capabilities/scene-batch.js +394 -0
  73. package/dist/core/capabilities/scene-readback.d.ts +36 -0
  74. package/dist/core/capabilities/scene-readback.js +54 -0
  75. package/dist/core/capabilities/seeing/args.d.ts +348 -0
  76. package/dist/core/capabilities/seeing/args.js +178 -0
  77. package/dist/core/capabilities/seeing/candidates.d.ts +127 -0
  78. package/dist/core/capabilities/seeing/candidates.js +282 -0
  79. package/dist/core/capabilities/seeing/math.d.ts +134 -0
  80. package/dist/core/capabilities/seeing/math.js +269 -0
  81. package/dist/core/capabilities/seeing/probe.d.ts +62 -0
  82. package/dist/core/capabilities/seeing/probe.js +188 -0
  83. package/dist/core/capabilities/seeing/scoring.d.ts +235 -0
  84. package/dist/core/capabilities/seeing/scoring.js +639 -0
  85. package/dist/core/capabilities/seeing/seeing.d.ts +233 -0
  86. package/dist/core/capabilities/seeing/seeing.js +1341 -0
  87. package/dist/core/capabilities/seeing/shot-store.d.ts +52 -0
  88. package/dist/core/capabilities/seeing/shot-store.js +204 -0
  89. package/dist/core/capabilities/surface-snap-mesh.d.ts +88 -0
  90. package/dist/core/capabilities/surface-snap-mesh.js +425 -0
  91. package/dist/core/capabilities/surface-snap.d.ts +77 -0
  92. package/dist/core/capabilities/surface-snap.js +461 -0
  93. package/dist/core/capabilities/tool-dispatch.js +231 -72
  94. package/dist/core/capabilities/tscn.d.ts +85 -0
  95. package/dist/core/capabilities/tscn.js +391 -0
  96. package/dist/core/capabilities/world-snapshot.d.ts +58 -0
  97. package/dist/core/capabilities/world-snapshot.js +150 -0
  98. package/dist/core/capability-skew.d.ts +5 -5
  99. package/dist/core/capability-skew.js +14 -6
  100. package/dist/core/headless/worker-engine-client.d.ts +1 -1
  101. package/dist/core/headless/worker-engine-client.js +2 -2
  102. package/dist/core/library-read.d.ts +37 -5
  103. package/dist/core/library-read.js +264 -33
  104. package/dist/core/library-search.d.ts +2 -2
  105. package/dist/core/skills-registry.d.ts +9 -1
  106. package/dist/core/skills-registry.js +25 -2
  107. package/dist/installer/agent-config.d.ts +9 -4
  108. package/dist/installer/agent-config.js +194 -392
  109. package/dist/installer/agent-table.d.ts +119 -0
  110. package/dist/installer/agent-table.js +619 -0
  111. package/dist/installer/setup.js +4 -2
  112. package/dist/installer/skill-locations.d.ts +8 -17
  113. package/dist/installer/skill-locations.js +22 -101
  114. package/dist/installer/version-check.d.ts +5 -1
  115. package/dist/installer/version-check.js +38 -28
  116. package/dist/mcp/server.js +9 -3
  117. package/dist/mcp/tools/asset-tools.js +21 -3
  118. package/dist/mcp/tools/audit-tools.d.ts +23 -0
  119. package/dist/mcp/tools/audit-tools.js +60 -0
  120. package/dist/mcp/tools/debug-tools.js +3 -1
  121. package/dist/mcp/tools/file-tools.js +17 -4
  122. package/dist/mcp/tools/generate-tools.js +74 -66
  123. package/dist/mcp/tools/library-tools.js +2 -0
  124. package/dist/mcp/tools/perception-tools.js +6 -19
  125. package/dist/mcp/tools/placement-tools.d.ts +24 -0
  126. package/dist/mcp/tools/placement-tools.js +91 -0
  127. package/dist/mcp/tools/project-tools.js +18 -15
  128. package/dist/mcp/tools/scene-tools.js +71 -83
  129. package/dist/mcp/tools/seeing-tools.d.ts +24 -0
  130. package/dist/mcp/tools/seeing-tools.js +64 -0
  131. package/dist/mcp/tools/spatial-tools.js +17 -9
  132. package/dist/mcp/tools/visual-tools.js +59 -7
  133. package/gemini-extension.json +26 -4
  134. package/integrations/README.md +48 -19
  135. package/integrations/amp/README.md +12 -0
  136. package/integrations/amp/manifest-target.json +3 -0
  137. package/integrations/antigravity/README.md +12 -0
  138. package/integrations/antigravity/manifest-target.json +3 -0
  139. package/integrations/claude-desktop/README.md +12 -0
  140. package/integrations/claude-desktop/manifest-target.json +3 -0
  141. package/integrations/cline/README.md +8 -9
  142. package/integrations/cline-cli/README.md +12 -0
  143. package/integrations/cline-cli/manifest-target.json +3 -0
  144. package/integrations/copilot-jetbrains/README.md +12 -0
  145. package/integrations/copilot-jetbrains/manifest-target.json +3 -0
  146. package/integrations/crush/README.md +12 -0
  147. package/integrations/crush/manifest-target.json +3 -0
  148. package/integrations/github-copilot/README.md +8 -8
  149. package/integrations/goose/README.md +12 -0
  150. package/integrations/goose/manifest-target.json +3 -0
  151. package/integrations/grok-build/README.md +12 -0
  152. package/integrations/grok-build/manifest-target.json +3 -0
  153. package/integrations/hermes/README.md +12 -0
  154. package/integrations/hermes/manifest-target.json +3 -0
  155. package/integrations/junie/README.md +12 -0
  156. package/integrations/junie/manifest-target.json +3 -0
  157. package/integrations/kilo-code/README.md +6 -10
  158. package/integrations/kimi-code/README.md +12 -0
  159. package/integrations/kimi-code/manifest-target.json +3 -0
  160. package/integrations/kiro/README.md +12 -0
  161. package/integrations/kiro/manifest-target.json +3 -0
  162. package/integrations/lm-studio/README.md +8 -8
  163. package/integrations/mistral-vibe/README.md +12 -0
  164. package/integrations/mistral-vibe/manifest-target.json +3 -0
  165. package/integrations/opencode/README.md +9 -12
  166. package/integrations/qoder/README.md +12 -0
  167. package/integrations/qoder/manifest-target.json +3 -0
  168. package/integrations/qwen-code/README.md +12 -0
  169. package/integrations/qwen-code/manifest-target.json +3 -0
  170. package/integrations/roo-code/README.md +8 -7
  171. package/integrations/rovo-dev/README.md +12 -0
  172. package/integrations/rovo-dev/manifest-target.json +3 -0
  173. package/integrations/trae/README.md +12 -0
  174. package/integrations/trae/manifest-target.json +3 -0
  175. package/integrations/visual-studio/README.md +12 -0
  176. package/integrations/visual-studio/manifest-target.json +3 -0
  177. package/integrations/vscode-copilot/README.md +9 -9
  178. package/integrations/warp/README.md +12 -0
  179. package/integrations/warp/manifest-target.json +3 -0
  180. package/integrations/windsurf/README.md +8 -9
  181. package/integrations/zed/README.md +12 -0
  182. package/integrations/zed/manifest-target.json +3 -0
  183. package/library/references/mcp-tools-reference/mcp-tools-reference.md +59 -15
  184. package/library/references/mcp-tools-reference/resource.yaml +1 -1
  185. package/library/references/summer-folder/resource.yaml +1 -1
  186. package/library/references/summer-folder/summer-folder.md +1 -1
  187. package/library/skills/3d-lighting/SKILL.md +1 -1
  188. package/library/skills/README.md +264 -0
  189. package/library/skills/adaptive-music/SKILL.md +1 -1
  190. package/library/skills/agent-playtesting/SKILL.md +1 -1
  191. package/library/skills/ai-characters-in-games/SKILL.md +220 -0
  192. package/library/skills/ai-characters-in-games/resource.yaml +30 -0
  193. package/library/skills/ambient-bed/SKILL.md +1 -1
  194. package/library/skills/animated-loop/SKILL.md +1 -1
  195. package/library/skills/animation-tree/SKILL.md +1 -1
  196. package/library/skills/art-direction/SKILL.md +1 -1
  197. package/library/skills/asset-strategy/SKILL.md +2 -1
  198. package/library/skills/asset-strategy/resource.yaml +2 -1
  199. package/library/skills/audio-direction/SKILL.md +1 -1
  200. package/library/skills/auto-fire-targeting/SKILL.md +1 -1
  201. package/library/skills/brainstorm-game/SKILL.md +1 -1
  202. package/library/skills/brainstorming/SKILL.md +1 -1
  203. package/library/skills/browse-templates/SKILL.md +3 -3
  204. package/library/skills/browse-templates/resource.yaml +1 -1
  205. package/library/skills/camera-rigs/SKILL.md +128 -0
  206. package/library/skills/camera-rigs/resource.yaml +29 -0
  207. package/library/skills/celeste-momentum-platforming/SKILL.md +1 -1
  208. package/library/skills/character-animation-wiring/SKILL.md +1 -1
  209. package/library/skills/character-model/SKILL.md +1 -1
  210. package/library/skills/character-movement/SKILL.md +326 -0
  211. package/library/skills/character-movement/references/default-third-person-controller.gd +201 -0
  212. package/library/skills/character-movement/references/default-third-person-verification-probe.gd +154 -0
  213. package/library/skills/character-movement/references/movement-3d.md +136 -0
  214. package/library/skills/character-movement/references/platformer-feel.md +83 -0
  215. package/library/skills/character-movement/resource.yaml +40 -0
  216. package/library/skills/character-portrait/SKILL.md +1 -1
  217. package/library/skills/cinematic-cutscene/SKILL.md +1 -1
  218. package/library/skills/combat-basics/SKILL.md +159 -0
  219. package/library/skills/combat-basics/references/projectiles-and-aoe.md +100 -0
  220. package/library/skills/combat-basics/resource.yaml +34 -0
  221. package/library/skills/concept-art/SKILL.md +1 -1
  222. package/library/skills/create-asset-sheet/SKILL.md +1 -1
  223. package/library/skills/debug/SKILL.md +1 -1
  224. package/library/skills/debugging-game-feel/SKILL.md +1 -1
  225. package/library/skills/design-level/SKILL.md +1 -1
  226. package/library/skills/design-mechanic/SKILL.md +1 -1
  227. package/library/skills/design-npc/SKILL.md +1 -1
  228. package/library/skills/diagnosing-perf-regressions/SKILL.md +1 -1
  229. package/library/skills/dispatching-parallel-agents/SKILL.md +1 -1
  230. package/library/skills/driving-the-editor-ui/SKILL.md +1 -1
  231. package/library/skills/environment-kit/SKILL.md +1 -1
  232. package/library/skills/export-and-ship/SKILL.md +1 -1
  233. package/library/skills/fabricating-assets/SKILL.md +1 -1
  234. package/library/skills/facial-and-lipsync/SKILL.md +1 -1
  235. package/library/skills/fps-controller/SKILL.md +9 -7
  236. package/library/skills/fps-controller/resource.yaml +4 -1
  237. package/library/skills/game-feel/SKILL.md +1 -1
  238. package/library/skills/gameskill/SKILL.md +1 -1
  239. package/library/skills/gdscript-patterns/SKILL.md +1 -1
  240. package/library/skills/generate-motion/SKILL.md +9 -9
  241. package/library/skills/generate-motion/resource.yaml +2 -1
  242. package/library/skills/godogen-visual-proof-game-generation/SKILL.md +1 -1
  243. package/library/skills/headless-scripting/SKILL.md +1 -1
  244. package/library/skills/in-game-purchases/SKILL.md +254 -0
  245. package/library/skills/in-game-purchases/resource.yaml +29 -0
  246. package/library/skills/instantiate-asset-pack/SKILL.md +1 -1
  247. package/library/skills/investigating-bugs/SKILL.md +1 -1
  248. package/library/skills/lumera-single-image-scene-reconstruction/SKILL.md +1 -1
  249. package/library/skills/make-game/SKILL.md +25 -3
  250. package/library/skills/make-game/references/2d-platformer-polish.md +93 -0
  251. package/library/skills/make-game/references/2d-platformer.md +117 -0
  252. package/library/skills/make-game/references/2d-rpg-content.md +234 -0
  253. package/library/skills/make-game/references/2d-rpg.md +241 -0
  254. package/library/skills/make-game/references/2d-survivors-progression.md +201 -0
  255. package/library/skills/make-game/references/2d-survivors.md +237 -0
  256. package/library/skills/make-game/references/3d-fps-systems.md +216 -0
  257. package/library/skills/make-game/references/3d-fps.md +177 -0
  258. package/library/skills/make-game/references/3d-horror-systems.md +186 -0
  259. package/library/skills/make-game/references/3d-horror.md +201 -0
  260. package/library/skills/make-game/references/3d-third-person-systems.md +220 -0
  261. package/library/skills/make-game/references/3d-third-person.md +215 -0
  262. package/library/skills/make-game/resource.yaml +6 -1
  263. package/library/skills/multiplayer/SKILL.md +150 -0
  264. package/library/skills/multiplayer/resource.yaml +33 -0
  265. package/library/skills/multiplayer-movement/SKILL.md +510 -0
  266. package/library/skills/multiplayer-movement/files.md +501 -0
  267. package/library/skills/multiplayer-movement/resource.yaml +30 -0
  268. package/library/skills/multiplayer-project/SKILL.md +521 -0
  269. package/library/skills/multiplayer-project/files.md +448 -0
  270. package/library/skills/multiplayer-project/resource.yaml +36 -0
  271. package/library/skills/multiplayer-publish/SKILL.md +229 -0
  272. package/library/skills/multiplayer-publish/export-errors.md +89 -0
  273. package/library/skills/multiplayer-publish/resource.yaml +28 -0
  274. package/library/skills/multiplayer-state/SKILL.md +438 -0
  275. package/library/skills/multiplayer-state/files.md +592 -0
  276. package/library/skills/multiplayer-state/resource.yaml +35 -0
  277. package/library/skills/multiplayer-testing/SKILL.md +236 -0
  278. package/library/skills/multiplayer-testing/resource.yaml +39 -0
  279. package/library/skills/music-track/SKILL.md +1 -1
  280. package/library/skills/navigate-summer/SKILL.md +1 -1
  281. package/library/skills/new-project/SKILL.md +1 -1
  282. package/library/skills/organic-model/SKILL.md +1 -1
  283. package/library/skills/pixel-art/SKILL.md +1 -1
  284. package/library/skills/play/SKILL.md +1 -1
  285. package/library/skills/playtesting-a-feature/SKILL.md +1 -1
  286. package/library/skills/procedural-animation/SKILL.md +2 -2
  287. package/library/skills/procedural-animation/resource.yaml +1 -1
  288. package/library/skills/prop-model/SKILL.md +1 -1
  289. package/library/skills/psx-retro-rendering/SKILL.md +1 -1
  290. package/library/skills/realtime-wet-surfaces/SKILL.md +2 -2
  291. package/library/skills/remote-deploy/SKILL.md +1 -1
  292. package/library/skills/retarget/SKILL.md +1 -1
  293. package/library/skills/running-in-the-cloud/SKILL.md +1 -1
  294. package/library/skills/save-load/SKILL.md +156 -0
  295. package/library/skills/save-load/resource.yaml +27 -0
  296. package/library/skills/scene-composition/SKILL.md +1 -1
  297. package/library/skills/scene-hierarchy-design/SKILL.md +1 -1
  298. package/library/skills/scene-scripting/SKILL.md +1 -1
  299. package/library/skills/scene-to-level/SKILL.md +1 -1
  300. package/library/skills/skill-create/SKILL.md +1 -1
  301. package/library/skills/skill-improve/SKILL.md +1 -1
  302. package/library/skills/skill-test/SKILL.md +1 -1
  303. package/library/skills/skintokens-auto-rigging/SKILL.md +1 -1
  304. package/library/skills/skybox-panorama/SKILL.md +1 -1
  305. package/library/skills/sound-effect/SKILL.md +1 -1
  306. package/library/skills/spatial-placement/SKILL.md +134 -3
  307. package/library/skills/spatial-placement/references/kit-placement-tools.md +364 -0
  308. package/library/skills/spatial-placement/resource.yaml +16 -2
  309. package/library/skills/sprite-sheet/SKILL.md +1 -1
  310. package/library/skills/summer-analytics/SKILL.md +147 -0
  311. package/library/skills/summer-analytics/resource.yaml +28 -0
  312. package/library/skills/summer-friends/SKILL.md +226 -0
  313. package/library/skills/summer-friends/resource.yaml +28 -0
  314. package/library/skills/summer-leaderboards/SKILL.md +231 -0
  315. package/library/skills/summer-leaderboards/resource.yaml +30 -0
  316. package/library/skills/summer-match-results/SKILL.md +286 -0
  317. package/library/skills/summer-match-results/resource.yaml +32 -0
  318. package/library/skills/summer-matchmaking/SKILL.md +301 -0
  319. package/library/skills/summer-matchmaking/resource.yaml +32 -0
  320. package/library/skills/summer-parties/SKILL.md +253 -0
  321. package/library/skills/summer-parties/resource.yaml +30 -0
  322. package/library/skills/summer-player-data/SKILL.md +322 -0
  323. package/library/skills/summer-player-data/resource.yaml +30 -0
  324. package/library/skills/summer-store/SKILL.md +271 -0
  325. package/library/skills/summer-store/resource.yaml +29 -0
  326. package/library/skills/summer-world-chat/SKILL.md +195 -0
  327. package/library/skills/summer-world-chat/resource.yaml +30 -0
  328. package/library/skills/summer-world-saves/SKILL.md +284 -0
  329. package/library/skills/summer-world-saves/resource.yaml +29 -0
  330. package/library/skills/text-to-motion/SKILL.md +99 -0
  331. package/library/skills/text-to-motion/prompts-and-controls.md +34 -0
  332. package/library/skills/text-to-motion/resource.yaml +41 -0
  333. package/library/skills/text-to-motion/rigging-for-text-motion.md +54 -0
  334. package/library/skills/tileable-texture/SKILL.md +1 -1
  335. package/library/skills/trailer-shot/SKILL.md +1 -1
  336. package/library/skills/tune-performance/SKILL.md +1 -1
  337. package/library/skills/ui-basics/SKILL.md +10 -1
  338. package/library/skills/ui-graphics/SKILL.md +1 -1
  339. package/library/skills/use-widget-asset/SKILL.md +1 -1
  340. package/library/skills/using-summer/SKILL.md +2 -2
  341. package/library/skills/using-summer/resource.yaml +2 -2
  342. package/library/skills/vehicle-model/SKILL.md +1 -1
  343. package/library/skills/verification-before-completion/SKILL.md +1 -1
  344. package/library/skills/verifying-scenes/SKILL.md +76 -2
  345. package/library/skills/verifying-scenes/resource.yaml +13 -2
  346. package/library/skills/vfx-dissolve/SKILL.md +1 -1
  347. package/library/skills/vfx-fire/SKILL.md +1 -1
  348. package/library/skills/vfx-hit-spark/SKILL.md +1 -1
  349. package/library/skills/vfx-lightning/SKILL.md +1 -1
  350. package/library/skills/vfx-magic-glow/SKILL.md +1 -1
  351. package/library/skills/vfx-muzzle-flash/SKILL.md +1 -1
  352. package/library/skills/vfx-smoke/SKILL.md +1 -1
  353. package/library/skills/vfx-water-ripple/SKILL.md +1 -1
  354. package/library/skills/voice-line/SKILL.md +1 -1
  355. package/library/skills/web-and-touch-input/SKILL.md +38 -0
  356. package/library/skills/web-and-touch-input/resource.yaml +28 -0
  357. package/library/skills/web-compatibility-look/SKILL.md +62 -0
  358. package/library/skills/web-compatibility-look/resource.yaml +30 -0
  359. package/library/skills/world-building-3d/SKILL.md +8 -1
  360. package/library/skills/world-building-3d/references/spatial-tools.md +1 -1
  361. package/library/skills/world-building-3d/resource.yaml +2 -1
  362. package/library/skills/writing-plans/SKILL.md +1 -1
  363. package/library/skills/writing-skills/SKILL.md +1 -1
  364. package/library/templates/3d-lan-multiplayer-starter/resource.yaml +2 -2
  365. package/library/tools/attach-to-surface/resource.yaml +142 -0
  366. package/library/tools/batch/resource.yaml +9 -3
  367. package/library/tools/connect-ports/resource.yaml +120 -0
  368. package/library/tools/connect-signal/resource.yaml +3 -2
  369. package/library/tools/debug-views/resource.yaml +94 -0
  370. package/library/tools/frame-nodes/resource.yaml +104 -0
  371. package/library/tools/frame-shot/resource.yaml +134 -0
  372. package/library/tools/generate-motion/resource.yaml +44 -9
  373. package/library/tools/get-board/resource.yaml +50 -0
  374. package/library/tools/get-project-context/resource.yaml +13 -2
  375. package/library/tools/grep/resource.yaml +77 -0
  376. package/library/tools/inspect-asset/resource.yaml +71 -0
  377. package/library/tools/inspect-node/resource.yaml +9 -2
  378. package/library/tools/inspect-resource/resource.yaml +16 -5
  379. package/library/tools/instantiate-scene/resource.yaml +27 -2
  380. package/library/tools/measure/resource.yaml +96 -0
  381. package/library/tools/place-adjacent/resource.yaml +113 -0
  382. package/library/tools/play/resource.yaml +15 -2
  383. package/library/tools/raycast/resource.yaml +101 -0
  384. package/library/tools/read-file/resource.yaml +36 -2
  385. package/library/tools/read-library/resource.yaml +2 -2
  386. package/library/tools/repeat-along/resource.yaml +129 -0
  387. package/library/tools/replace-node/resource.yaml +11 -5
  388. package/library/tools/scene-audit/resource.yaml +144 -0
  389. package/library/tools/screenshot/resource.yaml +13 -2
  390. package/library/tools/search-assets/resource.yaml +18 -0
  391. package/library/tools/shot-sheet/resource.yaml +110 -0
  392. package/library/tools/snap-to-surface/resource.yaml +4 -1
  393. package/library/tools/world-snapshot/resource.yaml +24 -3
  394. package/library/tools/zoom/resource.yaml +105 -0
  395. package/package.json +3 -3
  396. package/registry/generated/aliases.json +17 -3
  397. package/registry/generated/counts.json +3 -3
  398. package/registry/generated/gemini-extension.json +26 -4
  399. package/registry/generated/index.json +2154 -469
  400. package/registry/generated/marketplace.claude.json +2 -2
  401. package/registry/generated/plugin.claude.json +27 -5
  402. package/registry/generated/plugin.codex.json +28 -6
  403. package/registry/generated/plugin.cursor.json +27 -5
  404. package/registry/generated/plugin.factory.json +27 -5
  405. package/registry/generated/skills-index.md +264 -0
  406. package/registry/generated/skills-registry.json +901 -206
  407. package/registry/generated/templates-registry.json +2 -2
  408. package/library/skills/host-authoritative-state/SKILL.md +0 -332
  409. package/library/skills/host-authoritative-state/resource.yaml +0 -28
  410. package/library/skills/peer-to-peer-multiplayer/SKILL.md +0 -373
  411. package/library/skills/peer-to-peer-multiplayer/resource.yaml +0 -28
  412. package/library/skills/setup-multiplayer/SKILL.md +0 -336
  413. package/library/skills/setup-multiplayer/resource.yaml +0 -28
@@ -0,0 +1,177 @@
1
+ # 3D FPS - Core
2
+
3
+ First-person shooter blueprint: player hierarchy, mouse look, movement feel,
4
+ and level setup. Shooting, weapons, interaction, and HUD live in
5
+ `3d-fps-systems.md`.
6
+
7
+ Rule for Summer Engine builds: scene operations (.tscn) go through the scene
8
+ tools (`summer_add_node` / `summer_set_prop` / `summer_set_resource_property`,
9
+ or one `summer_batch`, always with `scenePath`); script files (.gd) go through
10
+ `summer_write_file` / `summer_replace_text`. Never cross the streams. For a
11
+ production controller with air control and external velocity, see the
12
+ `fps-controller` skill.
13
+
14
+ ## Minimum playable base (build this first)
15
+
16
+ Level with ground + light + WorldEnvironment, the player scene below, mouse
17
+ look + WASD + jump. Prove "walk around and look" before any weapon exists.
18
+
19
+ ## Player hierarchy (non-negotiable)
20
+
21
+ ```
22
+ Player (CharacterBody3D, group "player", collision_mask 6)
23
+ StandingShape (CollisionShape3D, capsule r 0.35 h 1.8, at y 0.9)
24
+ CrouchingShape (CollisionShape3D, capsule r 0.35 h 1.0, at y 0.5, disabled)
25
+ Head (Node3D, y 1.5) # receives PITCH
26
+ Camera3D (fov 70)
27
+ WeaponHolder (Node3D, (0.2, -0.15, -0.4))
28
+ InteractionRay (RayCast3D, target (0,0,-2.5), mask 4)
29
+ ShootRay (RayCast3D, target (0,0,-100), mask 6)
30
+ CeilingCheck (RayCast3D, at y 1, target (0,1,0), mask 2)
31
+ ```
32
+
33
+ Why this exact shape:
34
+
35
+ - Yaw rotates the Player ROOT, pitch rotates Head. Rotating the camera on
36
+ both axes causes gimbal lock and drift.
37
+ - Camera under Head inherits both rotations; WeaponHolder under Camera makes
38
+ weapons track the view exactly.
39
+ - Two collision shapes for crouch, toggled via `disabled`. Resizing one
40
+ shape at runtime glitches physics.
41
+ - Short InteractionRay (2.5m) and long ShootRay (100m) are separate rays with
42
+ separate masks.
43
+
44
+ Collision layers: 1 Player, 2 Environment, 3 Interactable, 4 Enemy. ShootRay
45
+ mask 6 = Environment + Enemy (never the player). InteractionRay mask 4 =
46
+ Interactable only.
47
+
48
+ Input map before any scripts: move_forward/back/left/right, jump (Space),
49
+ sprint (Shift), crouch (C), shoot (LMB), aim (RMB), reload (R), interact (E),
50
+ weapon_1/2/3, pause (Escape).
51
+
52
+ ## Controller script
53
+
54
+ Tuning baseline: walk 5.0, sprint 8.0, crouch 2.5, acceleration 10.0, jump
55
+ 4.5, mouse sensitivity 0.002, FOV 70 default / 80 sprint / 50 aim.
56
+
57
+ ```gdscript
58
+ func _ready() -> void:
59
+ Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
60
+
61
+ func _unhandled_input(event: InputEvent) -> void:
62
+ if event.is_action_pressed("ui_cancel"):
63
+ Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
64
+ return
65
+ if event is InputEventMouseButton and event.pressed \
66
+ and Input.mouse_mode == Input.MOUSE_MODE_VISIBLE:
67
+ Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
68
+ get_viewport().set_input_as_handled()
69
+ return
70
+ if event is InputEventMouseMotion:
71
+ rotate_y(-event.relative.x * mouse_sensitivity)
72
+ head.rotate_x(-event.relative.y * mouse_sensitivity)
73
+ head.rotation.x = clampf(head.rotation.x, deg_to_rad(-85.0), deg_to_rad(85.0))
74
+ ```
75
+
76
+ Mouse capture is mandatory or look does not work; the Escape release +
77
+ click-to-recapture pair is mandatory or the player cannot quit.
78
+
79
+ Movement (in `_physics_process`, never `_process`):
80
+
81
+ ```gdscript
82
+ func _handle_movement(delta: float) -> void:
83
+ var input_dir := Input.get_vector("move_left", "move_right", "move_forward", "move_back")
84
+ var direction := (transform.basis * Vector3(input_dir.x, 0.0, input_dir.y)).normalized()
85
+ if direction:
86
+ velocity.x = lerpf(velocity.x, direction.x * current_speed, acceleration * delta)
87
+ velocity.z = lerpf(velocity.z, direction.z * current_speed, acceleration * delta)
88
+ else:
89
+ velocity.x = lerpf(velocity.x, 0.0, acceleration * delta)
90
+ velocity.z = lerpf(velocity.z, 0.0, acceleration * delta)
91
+ if is_on_floor() and Input.is_action_just_pressed("jump") and not is_crouching:
92
+ velocity.y = jump_velocity
93
+ ```
94
+
95
+ Gravity from project settings, not a magic number:
96
+ `velocity.y -= ProjectSettings.get_setting("physics/3d/default_gravity") * delta`
97
+ when not on floor. Then `move_and_slide()`.
98
+
99
+ ### Sprint + stamina
100
+
101
+ Sprint only while pressing sprint, moving (velocity > 0.5), not crouching,
102
+ and stamina > 0. Drain 20/s, regen 15/s to 100. Sprinting also pushes FOV to
103
+ 80 (lerp at 5.0/delta), aim pulls to 50 - the FOV lerp is a big part of feel.
104
+
105
+ ### Crouch
106
+
107
+ Toggle: swap which CollisionShape3D is disabled, lerp `head.position.y`
108
+ between 1.5 and 0.8 at 8.0/delta. Standing up first checks
109
+ `ceiling_check.is_colliding()` - refuse to stand under low geometry.
110
+ Crouching cancels sprint and blocks jump.
111
+
112
+ ### Headbob + footsteps
113
+
114
+ ```gdscript
115
+ func _handle_headbob(delta: float) -> void:
116
+ var speed := Vector2(velocity.x, velocity.z).length()
117
+ if speed < 0.5 or not is_on_floor():
118
+ camera.position.y = lerpf(camera.position.y, 0.0, 5.0 * delta)
119
+ camera.position.x = lerpf(camera.position.x, 0.0, 5.0 * delta)
120
+ return
121
+ headbob_time += delta * (14.0 if is_sprinting else 10.0)
122
+ var intensity := 0.05 if is_sprinting else 0.03
123
+ var bob_y := sin(headbob_time) * intensity
124
+ camera.position.y = bob_y
125
+ camera.position.x = sin(headbob_time * 0.5) * intensity * 0.5
126
+ if headbob_last_y >= 0.0 and bob_y < 0.0:
127
+ _play_footstep() # sine crossing zero downward = foot plants
128
+ headbob_last_y = bob_y
129
+ ```
130
+
131
+ The lerp-to-zero branch when stopped is required - without it the camera
132
+ freezes mid-bob. The zero-crossing footstep trigger syncs audio to motion
133
+ for free.
134
+
135
+ ## Level scene
136
+
137
+ The real level comes from real assets, not primitives: route the need through
138
+ the `asset-strategy` skill (`summer_search_assets`, then `summer_import_asset` /
139
+ `summer_import_asset_by_id`), import a ready location or kit that fits, and build
140
+ gameplay inside it; weapons and props should share its style. A PlaneMesh ground
141
+ is only the walk-test blockout and for pieces no asset covers — never the
142
+ shipped level when a real one is available.
143
+
144
+ Blockout minimum: Node3D root + WorldEnvironment + ground (StaticBody3D with
145
+ BoxShape3D collision AND a PlaneMesh visual - a MeshInstance3D alone has no
146
+ collision) + DirectionalLight3D at (-45, 30, 0) with shadows + the player
147
+ instance at (0, 1, 0).
148
+
149
+ Environment presets:
150
+
151
+ - Outdoor: ProceduralSkyMaterial sky, angled DirectionalLight3D with
152
+ shadows, ambient from sky.
153
+ - Indoor: no sky (custom color background), Omni/SpotLights per room, low
154
+ ambient, SSAO on, optional fog.
155
+
156
+ ## Build order
157
+
158
+ 1. Input map + collision layer names.
159
+ 2. Player scene per the hierarchy above (MCP), controller script (files).
160
+ 3. Level: blockout ground, light, environment. Walk test.
161
+ 4. Swap the blockout for an imported location + props (`asset-strategy`).
162
+ 5. Hitscan shooting + one weapon + crosshair (`3d-fps-systems.md`).
163
+ 6. Interaction (door, pickup), HUD, then weapon roster.
164
+
165
+ ## Traps
166
+
167
+ - Mouse look on the Camera directly - split yaw (root) / pitch (Head) or
168
+ you get gimbal lock.
169
+ - Movement in `_process` - variable framerate stutter. CharacterBody3D
170
+ moves in `_physics_process` only.
171
+ - Forgetting `MOUSE_MODE_CAPTURED` (look does nothing) or the Escape
172
+ release (player trapped).
173
+ - Camera at y 0 - you see from your feet. Head height is 1.5-1.7.
174
+ - Level geometry without StaticBody3D collision - the player falls through
175
+ anything that is only a MeshInstance3D.
176
+ - One resized collision shape for crouch instead of two toggled shapes.
177
+ - ShootRay mask including the Player layer - you shoot yourself; mask 6.
@@ -0,0 +1,186 @@
1
+ # 3D Horror - Systems
2
+
3
+ The dread machinery on top of `3d-horror.md`: the tension-driven atmosphere
4
+ controller, the stalker AI, procedural audio, interactables, and the escape
5
+ objective chain.
6
+
7
+ ## Atmosphere controller (tension in, dread out)
8
+
9
+ One Node3D in the level reads `GameManager.tension_level` and escalates
10
+ three channels. It auto-discovers OmniLights from a sibling "Lights" node
11
+ and creates 4 roaming AudioStreamPlayer3D emitters (Ambient bus, max
12
+ distance 20).
13
+
14
+ ### Flickering lights
15
+
16
+ Per-frame chance `0.005 * (1.0 + tension)` per light. A flicker is a tween
17
+ of 2-5 random off/on cycles (off 0.02-0.08s at energy 0-0.3, on 0.02-0.1s
18
+ at 50-100%), then restore. Random durations - regular flicker reads as a
19
+ broken script, not a broken light.
20
+
21
+ ### Positional ambient sounds
22
+
23
+ Every 15-45s (interval shrinks to half at max tension), one emitter
24
+ teleports to a random point around the player
25
+ (x/z +-15, y 0-5 - behind walls, above the ceiling) and plays from a pool
26
+ that GROWS with tension:
27
+
28
+ - base: door close, pipe stress, wind vent
29
+ - tension > 0.3: + creature whisper
30
+ - tension > 0.5: + distant scream
31
+ - tension > 0.7: + creature growl
32
+
33
+ Random volume -12..-4 dB and pitch 0.7-1.3 so nothing repeats exactly.
34
+
35
+ ### Tension events
36
+
37
+ Every 30s at base, down to ~12s at max tension, pick one of FIVE:
38
+ 0 = flicker all lights, 1 = audio stinger + tension +0.05, 2 = brief
39
+ darkness, 3 = extra ambient sound, 4 = NOTHING. The nothing case is
40
+ deliberate - a scare that never comes after buildup is the horror.
41
+
42
+ Brief darkness: tween all lights to energy 0.05 over 0.5s, hold a random
43
+ 0.5-2s, restore over 0.3s, tension +0.08. Save original energies first.
44
+
45
+ ## Stalker AI
46
+
47
+ A solid-black unshaded capsule (CapsuleMesh r 0.2 h 2.2, albedo 0.01 -
48
+ reads as a silhouette in any lighting). Mesh and collision built at
49
+ runtime, no assets. Core mechanic: it only moves when you are NOT looking.
50
+
51
+ ```gdscript
52
+ func _process_showing(delta: float) -> void:
53
+ look_at(Vector3(player.global_position.x, global_position.y, player.global_position.z))
54
+ var to_me := (global_position - player.global_position).normalized()
55
+ var player_fwd := -player.global_transform.basis.z.normalized()
56
+ var angle := rad_to_deg(acos(clampf(player_fwd.dot(to_me), -1.0, 1.0)))
57
+ if angle < 20.0:
58
+ # player looking directly: freeze and stare back
59
+ stare_timer += delta
60
+ if stare_timer >= stare_time: # 2.0s of being watched
61
+ _disappear()
62
+ else:
63
+ stare_timer = 0.0
64
+ var dir := (player.global_position - global_position).normalized()
65
+ dir.y = 0.0
66
+ velocity = dir * approach_speed # 1.5 m/s
67
+ move_and_slide()
68
+ if global_position.distance_to(player.global_position) < catch_distance: # 1.5m
69
+ AudioManager.play_sfx(ProceduralAudio.get_creature_screech(), 0.0)
70
+ GameManager.set_state(GameManager.GameState.GAME_OVER)
71
+ ```
72
+
73
+ Pacing rules (tuned, keep them):
74
+
75
+ - First appearance at 15s - the player needs time to find the flashlight.
76
+ - Reappear interval starts 18s, shrinks 15% per appearance, floor 8s:
77
+ `reappear_interval = maxf(reappear_interval * 0.85, 8.0)`.
78
+ - Spawn selection: from a hand-placed spawn-point list, pick the FARTHEST
79
+ point that is between 6m and 18m from the player. Under 6m is unfair -
80
+ no time to react.
81
+ - On appear: whisper from its own 3D emitter + low-pitched stinger
82
+ (pitch 0.5-0.8) + tension +0.1.
83
+ - Fully idle while `GameManager.is_reading_note` or state != PLAYING -
84
+ notes are safe rooms.
85
+ - After `stare_time` of being watched it vanishes (visible = false) and
86
+ the wait timer restarts. Player-facing check is a dot-product cone of
87
+ 20 degrees, not a raycast - cheap and good enough.
88
+
89
+ ## Procedural audio
90
+
91
+ `ProceduralAudio` is a static class generating every sound from math into
92
+ cached AudioStreamWAVs - zero audio files; swap in recordings later
93
+ without touching call sites. Catalog: footsteps (4 variations),
94
+ door open/close/locked, ambient drone (detuned 40Hz sines, looping),
95
+ tension hit (sub boom + metallic ring), pickup chime, creature
96
+ whisper/growl/screech, heartbeat, distant scream, water drip, machinery
97
+ hum, wind vent, fluorescent buzz, pipe stress, radio static.
98
+
99
+ Generation pattern all sounds follow (16-bit, 22050 Hz):
100
+
101
+ ```gdscript
102
+ static func _generate_example() -> void:
103
+ var num_samples := int(duration * SAMPLE_RATE)
104
+ var samples := PackedByteArray()
105
+ samples.resize(num_samples * 2)
106
+ for s in num_samples:
107
+ var t := float(s) / SAMPLE_RATE
108
+ var envelope := exp(-t * 3.0)
109
+ var value := sin(t * 440.0 * TAU) * envelope * 0.3
110
+ var sample := clampi(int(value * 16000), -32768, 32767)
111
+ samples[s * 2] = sample & 0xFF
112
+ samples[s * 2 + 1] = (sample >> 8) & 0xFF
113
+ _stream = AudioStreamWAV.new()
114
+ _stream.format = AudioStreamWAV.FORMAT_16_BITS
115
+ _stream.mix_rate = SAMPLE_RATE
116
+ _stream.data = samples
117
+ # looping sounds: loop_mode = LOOP_FORWARD, loop_begin = 0, loop_end = num_samples
118
+ ```
119
+
120
+ Recipes that matter: creature sounds = low fundamentals (30Hz growl) +
121
+ inharmonic partials; whispers/screams = filtered noise; drones = slightly
122
+ detuned sine pairs (beating); always exponential envelopes.
123
+
124
+ ## Interactables
125
+
126
+ Same duck-typed interface as 3d-fps: `interact(player)` +
127
+ `get_interaction_prompt() -> String`, found by the InteractionRay (mask 4).
128
+
129
+ ### HorrorDoor
130
+
131
+ Node3D rotating on Y, hinge at the parent origin (mesh offset
132
+ (0.5, 1.4, 0)), lerp `rotation.y` toward target at open_speed. Opens away
133
+ from the player (approach-side check). Horror-specific exports:
134
+
135
+ - `required_key`: locked until `GameManager.has_item(key)`; unlocking
136
+ consumes the key. Locked interaction plays a rattle - +-2 degree shake
137
+ tween + locked sound. Prompt: "Locked" / "Unlock" / "Open" / "Close".
138
+ - `auto_close_delay`: door closes itself behind the player (room traps).
139
+ - `creepy_auto_open`: opens by itself ONCE after a delay - cheapest scare
140
+ in the kit.
141
+
142
+ ### InteractableItem
143
+
144
+ RigidBody3D with `freeze = true`, bob + rotate idle (randomized phase),
145
+ per-type runtime mesh + OmniLight3D glow:
146
+
147
+ | Type | Effect | Visual |
148
+ |---|---|---|
149
+ | KEY | `add_item(item_id)` | gold box, warm glow |
150
+ | FLASHLIGHT | `player.pickup_flashlight()` | gray cylinder, amber glow |
151
+ | NOTE | `open_note(id, text)` - NOT consumed | paper-white flat box |
152
+ | BATTERY | battery +30 (cap 100) | dark blue box, blue glow |
153
+
154
+ Everything except notes `queue_free()`s on pickup.
155
+
156
+ ### EscapeZone
157
+
158
+ Area3D (mask 1) at the exit with a green OmniLight beacon. On player
159
+ enter: with the exit key -> `set_state(ESCAPED)`; without it -> open a
160
+ note ("The door is chained from the outside. I need a key.") - the
161
+ rejection delivers story instead of a dead trigger.
162
+
163
+ ## Objective chain
164
+
165
+ The loop is explore -> find -> unlock -> escape:
166
+
167
+ 1. Spawn in entry area, find flashlight.
168
+ 2. Main hall, Note 1 hints at the storage key.
169
+ 3. Side corridor -> office -> storage key.
170
+ 4. Storage room (locked) -> exit key.
171
+ 5. Back corridor (darkest) -> escape zone with exit key -> ESCAPED.
172
+
173
+ The whole chain is data: `required_key` on doors, `item_id` on pickups,
174
+ `required_key` on the EscapeZone, and note texts for direction. Re-theme a
175
+ level by editing strings, not code. Keys live in dead ends so the stalker
176
+ gets backtracking time; notes double as the hint system - no quest UI.
177
+
178
+ ## Escalation timeline (why it works)
179
+
180
+ Minute 1: quiet, base ambient sounds, flashlight secured. Minute 2-3:
181
+ first stalker appearance, whispers join the pool. Mid-game: battery
182
+ pressure, screams, shorter stalker gaps, brief-darkness events. Endgame:
183
+ tension near 1.0 - vignette closed in, breathing sway, growls, stalker
184
+ every 8s, in the darkest corridor with the exit key. All of it falls out
185
+ of one passive float plus event spikes; tune the drain rate, the
186
+ reappear floor, and ambient intervals - not scripted scares.
@@ -0,0 +1,201 @@
1
+ # 3D Horror - Core
2
+
3
+ First-person horror blueprint: game state, the vulnerable-player controller,
4
+ flashlight mechanics, level building, lighting, and the minimal HUD. The
5
+ stalker AI, tension/atmosphere system, procedural audio, and interactables
6
+ live in `3d-horror-systems.md`.
7
+
8
+ The player scene reuses the 3d-fps hierarchy and controller (yaw on root,
9
+ pitch on Head, two crouch shapes, headbob) - see `3d-fps.md`. This file
10
+ covers what horror changes.
11
+
12
+ ## Design law: vulnerability
13
+
14
+ No weapon, ever. The flashlight is the only tool. The moment the player can
15
+ fight back it becomes an action game. No health bar, no minimap, no kill
16
+ counter - the HUD shows only battery, interaction prompt, and notes.
17
+
18
+ ## Minimum playable base (build this first)
19
+
20
+ One dark room + flashlight pickup + a locked door + the key that opens it.
21
+ Prove "dark, need the light, find key, open door" before any AI or
22
+ atmosphere exists.
23
+
24
+ ## Autoloads
25
+
26
+ Two: GameManager and AudioManager, both `process_mode = PROCESS_MODE_ALWAYS`.
27
+
28
+ GameManager is the single source of truth:
29
+
30
+ ```gdscript
31
+ enum GameState { MENU, PLAYING, PAUSED, GAME_OVER, ESCAPED }
32
+
33
+ var inventory: Array[String] = []
34
+ var notes_found: Array[String] = []
35
+ var has_flashlight: bool = false
36
+ var flashlight_battery: float = 100.0
37
+ var doors_unlocked: Array[String] = []
38
+ var tension_level: float = 0.0 # 0 calm .. 1 max
39
+ var is_reading_note: bool = false
40
+ ```
41
+
42
+ - `set_state()` pauses the tree for PAUSED/GAME_OVER/ESCAPED, unpauses on
43
+ PLAYING, and force-closes any open note on leaving PLAYING.
44
+ - Tension rises passively 0.005/sec while PLAYING; systems spike it via
45
+ `increase_tension(amount)`. Everything atmospheric reads this one float.
46
+ - Note reading is a modal state: while `is_reading_note`, the player
47
+ controller AND the stalker both stand down (safe reading).
48
+ - Inventory is just string ids: `add_item` / `has_item` / `remove_item`;
49
+ `open_note(id, text)` / `close_note()` emit signals the HUD listens to.
50
+
51
+ AudioManager: 8 pooled AudioStreamPlayers on an "SFX" bus, dedicated
52
+ ambient + music players on an "Ambient" bus, buses created at runtime via
53
+ `AudioServer.add_bus()` if missing. `play_ambient` crossfades from -40dB.
54
+ Bus separation is mandatory - you cannot balance or add reverb/low-pass
55
+ later without it.
56
+
57
+ ## Player controller (horror deltas from 3d-fps)
58
+
59
+ - Walk 3.0 / sprint 5.0 / crouch 1.5 (slow = vulnerable; FPS-speed movement
60
+ kills dread).
61
+ - gravity_multiplier 1.5 - heavier, grounded.
62
+ - ALL input gated on `GameManager.current_state == PLAYING` in both
63
+ `_unhandled_input` and `_physics_process` - frozen during notes, pause,
64
+ game over.
65
+ - Extra child under Camera3D: Flashlight (SpotLight3D at (0.15, -0.1, -0.1),
66
+ hidden until picked up) + FlashlightDust (GPUParticles3D).
67
+ - Input map adds `flashlight` (F); no shoot/aim/reload.
68
+ - Footsteps route through the procedural audio footstep with random pitch.
69
+
70
+ ### Flashlight (the core mechanic)
71
+
72
+ ```gdscript
73
+ func _handle_flashlight_drain(delta: float) -> void:
74
+ if not flashlight_on:
75
+ return
76
+ GameManager.flashlight_battery -= flashlight_drain_rate * delta / 60.0 # 15%/min, ~6.5 min life
77
+ GameManager.flashlight_battery = maxf(GameManager.flashlight_battery, 0.0)
78
+ if GameManager.flashlight_battery < 15.0:
79
+ # dual-sine = irregular organic flicker, not a metronome
80
+ var flicker := sin(Time.get_ticks_msec() * 0.03) * sin(Time.get_ticks_msec() * 0.07)
81
+ flashlight.light_energy = lerpf(0.3, 1.2, (flicker + 1.0) * 0.5)
82
+ else:
83
+ flashlight.light_energy = 1.5
84
+ if GameManager.flashlight_battery <= 0.0:
85
+ flashlight_on = false
86
+ flashlight.visible = false
87
+ ```
88
+
89
+ Toggle refuses until `GameManager.has_flashlight`. Battery pickups restore
90
+ +30. Drain rate is the game's difficulty dial.
91
+
92
+ Dust in the beam: GPUParticles3D (60 particles, 4s life, box emission
93
+ 2x1.5x5 in front of camera, tiny unshaded spheres radius 0.008, alpha ramp
94
+ peaking at 0.08). Emits only while the flashlight is visible. Reads as
95
+ volumetrics at a fraction of the cost.
96
+
97
+ ### Breathing (fear you can feel)
98
+
99
+ ```gdscript
100
+ func _handle_breathing(delta: float) -> void:
101
+ var target := 0.0
102
+ if stamina < 30.0:
103
+ target += (1.0 - stamina / 30.0) * 0.5
104
+ target += GameManager.tension_level * 0.3
105
+ breathing_intensity = lerpf(breathing_intensity, target, 2.0 * delta)
106
+ if breathing_intensity > 0.05:
107
+ var t := Time.get_ticks_msec() * 0.001
108
+ camera.rotation.x += sin(t * 1.5) * breathing_intensity * 0.003
109
+ camera.rotation.z = lerpf(camera.rotation.z,
110
+ sin(t * 2.0) * breathing_intensity * 0.002, 3.0 * delta)
111
+ ```
112
+
113
+ Involuntary camera sway from low stamina + high tension. Subtle numbers -
114
+ resist cranking them.
115
+
116
+ ## Level building (library first, primitives last)
117
+
118
+ The level comes from real assets: route it through the `asset-strategy` skill
119
+ (`summer_search_assets`, then `summer_import_asset` / `summer_import_asset_by_id`)
120
+ and look for a ready horror location (an abandoned house, a haunted forest, a
121
+ modular horror-house kit) plus period props, keeping one coherent style. Import
122
+ the location that fits and build gameplay inside it. Do NOT grey-box a level a
123
+ real asset already provides.
124
+
125
+ Runtime primitive geometry (BoxMesh/PlaneMesh + StaticBody3D, collision
126
+ layer 2) is only for what the imported assets lack: interior partitions the
127
+ imported location does not have, trigger volumes, blockers. When you do need
128
+ it: WALL_HEIGHT 3.5, WALL_THICKNESS 0.15, helpers `_floor(center, size)`,
129
+ `_ceiling`, `_wall_x(z, x0, x1)` / `_wall_z(x, z0, z1)`, `_prop_box(pos,
130
+ size, mat)`. Materials: dark desaturated albedo (floor 0.12/0.11/0.1, walls
131
+ 0.18/0.17/0.15), roughness 0.85.
132
+
133
+ Layout formula:
134
+
135
+ 1. Entry area - well-lit, flashlight pickup here.
136
+ 2. Main hall - central hub, multiple exits, player keeps returning.
137
+ 3. Side corridors - long, narrow, dim; stalker territory.
138
+ 4. Dead-end rooms - keys and notes; forced backtracking.
139
+ 5. Back corridor - darkest, highest tension.
140
+ 6. Final area - escape zone at the far end, exit key behind at least one
141
+ locked door.
142
+
143
+ ## Atmosphere rendering settings
144
+
145
+ WorldEnvironment is half the horror:
146
+
147
+ - Sky near-black (top 0.02/0.02/0.05); ambient color 0.03/0.03/0.05 at
148
+ energy 0.5 - the player MUST need the flashlight.
149
+ - Tonemap ACES, white 6.0. SSAO on (radius 2, intensity 3 - darkens
150
+ corners). SSIL on (radius 3, intensity 0.5). Glow subtle (0.3 / bloom 0.1).
151
+ - Fog density 0.02 dark; volumetric fog density 0.06, anisotropy 0.7 -
152
+ this is what makes the flashlight beam a visible cone.
153
+
154
+ Lighting rules: OmniLights energy 0.4-0.8 (main hall 1.2 max), ALL with
155
+ `shadow_enabled = true` (the stalker casts a shadow before you see it).
156
+ Give each area a distinct temperature - entry warm (0.6, 0.5, 0.3),
157
+ corridors cool (0.3, 0.4, 0.35), lab sickly green (0.3, 0.6, 0.4) - it is
158
+ navigation AND variety without textures.
159
+
160
+ Collision layers: 1 Player, 2 Environment, 3 Interactable, 4 Enemy.
161
+
162
+ ## HUD (minimal by design)
163
+
164
+ ```
165
+ HUD (CanvasLayer)
166
+ Crosshair (centered dot)
167
+ InteractionPrompt (Label, bottom center, "[E] Open")
168
+ BatteryContainer (top left, HIDDEN until flashlight found)
169
+ BatteryBar (ProgressBar; red <20%, yellow <50%, blue else)
170
+ NoteBackdrop (fullscreen black, 72% alpha)
171
+ NotePanel (centered note text)
172
+ Vignette (fullscreen; alpha = 0.2 + tension * 0.4)
173
+ ```
174
+
175
+ Wire to GameManager signals (`note_opened/closed`, `game_state_changed`).
176
+ Note UX detail: 0.35s cooldown after opening before close input is
177
+ accepted - otherwise the same interact press that opened the note closes
178
+ it. HUD hides entirely when state is not PLAYING.
179
+
180
+ ## Build order
181
+
182
+ 1. Autoloads + input map + layers.
183
+ 2. Player from 3d-fps base, horror speeds, state gating.
184
+ 3. One room + WorldEnvironment settings + flashlight pickup + drain.
185
+ 4. Doors/keys/notes + escape zone (`3d-horror-systems.md`).
186
+ 5. Atmosphere controller, then the stalker LAST - it only lands once the
187
+ world already feels wrong.
188
+
189
+ ## Traps
190
+
191
+ - Giving the player any weapon, health bar, or combat UI.
192
+ - Ambient energy above 0.5 - no darkness, no battery economy, no fear.
193
+ - Constant jump scares. The template leans on anticipation; one of its
194
+ five tension events is deliberately NOTHING.
195
+ - Stalker always visible - players habituate; long gaps are intentional.
196
+ - Constant music. Silence scares; use the drone + rare stingers, save
197
+ music for peaks and safe rooms.
198
+ - Identical rooms - distinct color temperature per area or players get
199
+ lost and bored simultaneously.
200
+ - Skipping audio buses - SFX through SFX bus, ambience through Ambient,
201
+ or mixing and wall-muffling effects become impossible later.