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,93 @@
1
+ # 2D Platformer - Enemies, Hazards, Juice, Progression
2
+
3
+ Add these only after the core loop (run/jump/goal/death) from `2d-platformer.md`
4
+ feels good. Combat mechanics reuse the `combat-basics` skill.
5
+
6
+ ## Patrol enemy
7
+
8
+ A `CharacterBody2D` that walks, turns at ledges/walls, and hurts on contact. Ledge
9
+ detection via a downward `RayCast2D` at the front foot.
10
+
11
+ ```gdscript
12
+ extends CharacterBody2D
13
+ @export var speed: float = 60.0
14
+ var dir: float = 1.0
15
+ var gravity: float = ProjectSettings.get_setting("physics/2d/default_gravity")
16
+ @onready var ledge: RayCast2D = $LedgeCheck # points down, ahead of feet
17
+
18
+ func _physics_process(delta: float) -> void:
19
+ if not is_on_floor():
20
+ velocity.y += gravity * delta
21
+ if is_on_wall() or (is_on_floor() and not ledge.is_colliding()):
22
+ dir *= -1.0
23
+ ledge.position.x *= -1.0
24
+ $Sprite2D.flip_h = dir < 0.0
25
+ velocity.x = dir * speed
26
+ move_and_slide()
27
+ ```
28
+
29
+ Give it a hurtbox (masks PlayerHurtbox) and a Health node from `combat-basics`.
30
+
31
+ ## Stomp-to-kill
32
+
33
+ The classic platformer verb. A separate Area2D under the player masking only the
34
+ Enemies layer; on overlap, kill the enemy and bounce the player.
35
+
36
+ ```gdscript
37
+ # in player, StompArea (Area2D) child
38
+ func _on_stomp_body_entered(enemy: Node) -> void:
39
+ if velocity.y > 0.0 and enemy.has_method("die"):
40
+ enemy.die()
41
+ velocity.y = jump_velocity * 0.7 # bounce
42
+ ```
43
+
44
+ Falling (`velocity.y > 0`) distinguishes a stomp from a side hit that should damage
45
+ the player instead.
46
+
47
+ ## Hazards
48
+
49
+ - Spikes/lava: an Area2D on the Triggers layer that calls `player.die()`.
50
+ - Bounce pad: Area2D that sets `player.velocity.y = -launch_force` on enter.
51
+ - Bottomless pit: one wide killzone under the level.
52
+
53
+ ## Juice (the difference between prototype and game)
54
+
55
+ Route through a small helper so every hit feels alive:
56
+
57
+ - Hit flash: `modulate` to white, tween back over 0.06s.
58
+ - Screen shake: offset the Camera2D by decaying random noise for ~0.2s.
59
+ - Hitstop: `Engine.time_scale = 0.05` for one frame on a kill, then back to 1.0.
60
+ - Floating text: spawn a Label that rises and fades on coin/hit.
61
+ - Squash/stretch: tween the sprite `scale` to (1.2, 0.8) on land, back over 0.1s.
62
+ - Dust particles on land and on turn.
63
+
64
+ A silent, still platformer fails the 30-second bar even if every system works.
65
+
66
+ ## Progression: coins, gems, and a level goal
67
+
68
+ - Coins increment `GameManager.score`; emit `score_changed` for the HUD.
69
+ - A `level_end` Area2D (flag/door) triggers the level-complete screen with time and
70
+ coin count, then advances to the next room `.tscn`.
71
+ - Save unlocked rooms + best times via the `save-load` skill.
72
+
73
+ ## Metroidvania gating (optional)
74
+
75
+ For an interconnected map with ability gates:
76
+
77
+ - `AbilityManager` autoload: `unlocked: Dictionary`, `has(name)`, `unlock(name)`.
78
+ - Ability pickup: Area2D that calls `AbilityManager.unlock("double_jump")`.
79
+ - Ability gate: a wall/door that only opens if `AbilityManager.has("dash")`, or a
80
+ ledge only reachable with double jump.
81
+ - The player controller checks `AbilityManager.has("double_jump")` before allowing
82
+ a second air jump, `has("dash")` before a dash, etc.
83
+
84
+ Keep gating data-driven: one place lists what each ability unlocks, so designers
85
+ tune it without touching the controller.
86
+
87
+ ## Traps
88
+
89
+ - Enemies as RigidBody2D fight the player physically; use CharacterBody2D or Area2D.
90
+ - Stomp check without a `velocity.y > 0` guard kills enemies on any touch.
91
+ - Ledge raycast that does not flip with direction walks enemies off cliffs.
92
+ - Piling on juice at once (shake + hitstop + flash on every coin) reads as noise;
93
+ reserve the big feedback for kills and damage, keep coins light.
@@ -0,0 +1,117 @@
1
+ # 2D Platformer - Core
2
+
3
+ Side-scrolling platformer blueprint: architecture, the level, and the core loop.
4
+ Movement itself lives in the `character-movement` skill (base controller) and its
5
+ `../../character-movement/references/platformer-feel.md` (coyote time, jump buffer, variable height) - do
6
+ not rewrite it here; wire it in. For Celeste-grade precision movement (dash, wall
7
+ jump, climb) use `celeste-momentum-platforming` instead.
8
+
9
+ ## Minimum playable base (build this first)
10
+
11
+ Scene first (the make-game Scaffold phase): `main.tscn` with a Node2D root, a ground `StaticBody2D`
12
+ with a `CollisionShape2D`, the player, and a `Camera2D` child of the player. Prove
13
+ run + jump + land before anything else. Placeholder art is a colored
14
+ `ColorRect`/`Sprite2D`.
15
+
16
+ ## Architecture (grows into a full game)
17
+
18
+ ```
19
+ res://
20
+ scenes/
21
+ player/player.tscn
22
+ rooms/room_01.tscn # one .tscn per room/level
23
+ enemies/patrol_enemy.tscn
24
+ ui/{hud,pause_menu,main_menu,game_over}.tscn
25
+ scripts/
26
+ autoloads/
27
+ event_bus.gd # global signals, decouples systems
28
+ game_manager.gd # score, lives, current room, checkpoint
29
+ audio_manager.gd # pooled SFX + music
30
+ save_manager.gd
31
+ player/player_controller.gd
32
+ systems/{coin,checkpoint,killzone,moving_platform,one_way_platform,
33
+ crumbling_platform,bounce_pad,door,level_end}.gd
34
+ ```
35
+
36
+ Add autoloads only once the base loop works. Register in Project Settings in
37
+ dependency order: EventBus first (others reference it), then GameManager, then the
38
+ rest. All autoloads `process_mode = ALWAYS` so they survive pause.
39
+
40
+ ## Collision layers (set names in Project Settings)
41
+
42
+ | Layer | Name | Used by |
43
+ |-------|------|---------|
44
+ | 1 | World | TileMap, static platforms |
45
+ | 2 | Player | Player body |
46
+ | 3 | Enemies | Enemy bodies |
47
+ | 4 | PlayerHitbox | Sword/stomp hit area |
48
+ | 5 | EnemyHitbox | Enemy hit area |
49
+ | 6 | PlayerHurtbox | Player hurt area |
50
+ | 7 | EnemyHurtbox | Enemy hurt area |
51
+ | 8 | Collectibles | Coins, gems |
52
+ | 9 | Triggers | Doors, killzones, checkpoints |
53
+
54
+ Hitboxes mask the OPPOSING hurtbox (see the `combat-basics` skill). The stomp detector is a
55
+ separate Area under the player masking only the Enemies layer.
56
+
57
+ ## Building the level with a TileMap
58
+
59
+ Use a `TileMapLayer` (Godot 4.3+) for the solid world. Create a `TileSet`, paint
60
+ the collision polygon on the solid tiles, put the layer on the World collision
61
+ layer. The player collides with it for free - no per-tile StaticBody.
62
+
63
+ - One `TileMapLayer` for collidable terrain, a second (no collision, lower
64
+ z-index) for background decoration.
65
+ - For large levels, split into room `.tscn`s and load the current room via a
66
+ RoomManager; connect doors to `change_scene_to_file` or swap room instances.
67
+ - Parallax background: `Parallax2D` (or ParallaxBackground) layers with
68
+ `motion_scale` < 1 so distant layers move slower.
69
+
70
+ ## Moving, one-way, and crumbling platforms
71
+
72
+ These three cover most platformer level tech.
73
+
74
+ ```gdscript
75
+ # moving_platform.gd - AnimatableBody2D so riders move with it
76
+ extends AnimatableBody2D
77
+ @export var offset: Vector2 = Vector2(200, 0)
78
+ @export var duration: float = 2.0
79
+ func _ready() -> void:
80
+ var t := create_tween().set_loops().set_trans(Tween.TRANS_SINE)
81
+ t.tween_property(self, "position", position + offset, duration)
82
+ t.tween_property(self, "position", position, duration)
83
+ ```
84
+
85
+ Use `AnimatableBody2D` (not StaticBody2D) for movers - it carries the player. For
86
+ one-way platforms, enable `one_way_collision` on the platform's CollisionShape2D
87
+ so the player jumps up through and lands on top. Crumbling platform: on
88
+ `body_entered`, start a short timer, shake, then disable collision and fade out;
89
+ re-enable after a respawn delay.
90
+
91
+ ## Checkpoints and death
92
+
93
+ ```gdscript
94
+ # checkpoint.gd
95
+ extends Area2D
96
+ func _ready() -> void:
97
+ body_entered.connect(func(b):
98
+ if b.is_in_group("player"):
99
+ GameManager.checkpoint = global_position)
100
+
101
+ # killzone.gd - fall/spike death
102
+ extends Area2D
103
+ func _ready() -> void:
104
+ body_entered.connect(func(b):
105
+ if b.is_in_group("player"):
106
+ b.die()) # player respawns at GameManager.checkpoint
107
+ ```
108
+
109
+ ## Core loop checklist (the 30-second bar)
110
+
111
+ - Run + jump feels good (tuned gravity/fall multiplier, coyote + buffer).
112
+ - Coins/goal give immediate feedback: sound + pop tween + counter tick.
113
+ - Death is instant and respawns at the last checkpoint, no long reload.
114
+ - A visible goal (flag/door) ends the level with a clear result.
115
+
116
+ Enemies, hazards, juice, and metroidvania progression are in
117
+ `2d-platformer-polish.md`.
@@ -0,0 +1,234 @@
1
+ # 2D Action RPG - Content Systems
2
+
3
+ The content layer on top of `2d-rpg.md`: enemies, NPCs and dialogue, quests,
4
+ inventory, loot, perks, status effects, and save/load. Everything here talks
5
+ to the rest of the game only through EventBus and the autoloads.
6
+
7
+ ## Enemies (data-driven, five archetypes)
8
+
9
+ EnemyData resource defines stats + behavior; enemy_base.gd implements all
10
+ five behaviors and reads the data. No per-enemy scenes.
11
+
12
+ ```gdscript
13
+ enum BehaviorType { CHASE, RANGED, SWARM, TANK, BOSS }
14
+ ```
15
+
16
+ - CHASE (slime): direct pursuit, melee lunge, low knockback resistance.
17
+ - RANGED (skeleton archer): holds preferred distance, fires projectiles,
18
+ strafes at range, backs off when crowded.
19
+ - SWARM (bat): fast, random jitter movement, contact damage.
20
+ - TANK (golem): slow, high HP, knockback_resistance 0.8, ground slam with
21
+ screen shake.
22
+ - BOSS (dark mage): cycling pattern (single shot -> fan of 3 -> charge),
23
+ phase 2 at 40% HP (faster everything + aura), can summon minions. Emits
24
+ `boss_health_changed` for the HUD boss bar.
25
+
26
+ EnemyData fields that matter for tuning: max_health, contact_damage,
27
+ move_speed, detection_range 200, attack_range 35, attack_cooldown 1.2,
28
+ knockback_resistance, xp_value, gold_min/max.
29
+
30
+ EnemyDatabase registers everything in code (no .tres files):
31
+ `db.get_enemy("slime")`, `db.get_enemies_for_wave(5)` returns a
32
+ wave-appropriate mix. Built-ins: slime, skeleton_archer, bat, golem,
33
+ dark_mage.
34
+
35
+ Contract: every enemy is in the "enemies" group and exposes
36
+ `take_hit(damage: int, source_position: Vector2, is_crit: bool = false)`.
37
+ Weapons and projectiles call it directly. Death drops XP + gold orbs via
38
+ `_drop_loot()` and emits `EventBus.enemy_killed(enemy, xp_value)`.
39
+
40
+ EnemySpawner is wave-based: `wave_interval` 12s, `enemies_per_wave_base` 3,
41
+ `enemies_per_wave_growth` 1, `max_enemies` 20, `difficulty_scale` 1.08
42
+ (HP/damage multiplier per wave). `spawn_boss("dark_mage", pos)` for arenas.
43
+
44
+ ## NPCs and dialogue
45
+
46
+ DialogueData is a resource with a speaker name and a lines array. Each line
47
+ is a dictionary supporting optional keys:
48
+
49
+ ```gdscript
50
+ {
51
+ "text": "Hello!",
52
+ "speaker": "Elder", # override
53
+ "choices": [{"text": "Yes", "next": 2}], # branching
54
+ "action": "start_quest:slay_monsters",
55
+ "condition": "quest_complete:slay_monsters"
56
+ }
57
+ ```
58
+
59
+ Actions: `start_quest:<id>`, `give_item:<resource_path>`, `give_gold:<n>`,
60
+ `heal`. Conditions: `quest_complete:<id>`, `quest_active:<id>`,
61
+ `has_item:<id>`. This tiny string DSL covers most RPG dialogue needs -
62
+ resist building a graph editor.
63
+
64
+ Interaction flow (the pause dance):
65
+
66
+ ```gdscript
67
+ func interact(player: Node2D) -> void:
68
+ EventBus.dialogue_started.emit(npc_name)
69
+ GameManager.change_state(GameManager.GameState.DIALOGUE) # pauses tree
70
+ await _run_dialogue(start_index)
71
+ EventBus.dialogue_ended.emit()
72
+ GameManager.change_state(GameManager.GameState.PLAYING)
73
+ player.end_interaction()
74
+ ```
75
+
76
+ NPC = CharacterBody2D + CollisionShape2D + child Area2D named EXACTLY
77
+ "InteractionArea" on the interactions layer. Player entering shows a prompt;
78
+ interact key starts dialogue. When building NPCs in code, add the node tree
79
+ first, `add_child` it, THEN set script properties (npc_name, dialogue,
80
+ quest_to_give) - properties set before the script enters the tree can be
81
+ stomped by `_ready`.
82
+
83
+ DialogueBox: typewriter at 40 chars/sec, click skips to full text, click
84
+ again advances, choices render as buttons. Must be process_mode ALWAYS (tree
85
+ is paused during dialogue).
86
+
87
+ ## Quests
88
+
89
+ QuestData: id, title, description, objectives array
90
+ (`{"id": "kill_slimes", "description": "Kill 3 slimes", "target": 3}`),
91
+ xp_reward, gold_reward, prerequisite_quest_id.
92
+
93
+ QuestManager (autoload) API: `start_quest(data)`,
94
+ `progress_objective(quest_id, objective_id, amount = 1)`,
95
+ `is_quest_active/complete(id)`, `get_objective_progress(id, obj_id)`. When
96
+ all objectives hit target the quest auto-completes, grants rewards, and
97
+ emits `quest_completed`.
98
+
99
+ Wiring kills to quests happens in the LEVEL script, not the enemy:
100
+
101
+ ```gdscript
102
+ func _ready() -> void:
103
+ EventBus.enemy_killed.connect(_on_enemy_killed)
104
+
105
+ func _on_enemy_killed(_enemy: Node2D, _xp: int) -> void:
106
+ QuestManager.progress_objective("slay_monsters", "kill_enemies")
107
+ ```
108
+
109
+ Enemies stay dumb; levels decide what counts.
110
+
111
+ ## Inventory and items
112
+
113
+ InventoryManager (autoload): 20 item slots, 3 equipment slots (weapon,
114
+ armor, accessory), gold. `add_item()` returns false when full;
115
+ `use_item()` only works on consumables; `equip_item()` auto-routes by the
116
+ item's slot; `get_total_stat_bonus("attack")` sums equipment bonuses for the
117
+ stats pipeline; `clear()` on restart.
118
+
119
+ ItemData: ItemType (CONSUMABLE/WEAPON/ARMOR/ACCESSORY/KEY_ITEM), Rarity
120
+ (COMMON/UNCOMMON/RARE/EPIC with white/green/blue/purple colors),
121
+ `stat_bonuses: Dictionary` ("attack" -> 5), heal_amount, buy/sell price.
122
+
123
+ ## Loot
124
+
125
+ - LootTable: guaranteed gold range + guaranteed XP, then `drop_chance` roll
126
+ over weighted entries (`{"item", "weight", "min_count", "max_count"}`).
127
+ `table.roll()` returns the drops.
128
+ - PickupOrb: XP/gold orbs from dead enemies, magnet-pull within 100px,
129
+ accelerating toward the player.
130
+ - TreasureChest: interactable static body - guaranteed item + gold orbs +
131
+ a loot table roll on open.
132
+ - ItemDrop: dropped items render with a rarity glow.
133
+
134
+ ## Perks (level-up progression)
135
+
136
+ PerkData: id, name, description (supports a `{value}` token), max_level 3,
137
+ `stat_modifiers: Dictionary`, `special_effect: String` + effect_value for
138
+ non-stat perks. Built-in pool:
139
+
140
+ | ID | Effect per level |
141
+ |----|------|
142
+ | attack_up | +3 attack |
143
+ | speed_boost | +20 speed |
144
+ | thick_skin | +2 defense |
145
+ | vampirism | 3% lifesteal |
146
+ | burning_strikes | apply burn on hit |
147
+ | frost_touch | 30% slow on hit |
148
+ | critical_eye | +5% crit |
149
+ | multishot | +1 projectile |
150
+ | thorns | 20% reflect |
151
+ | regeneration | 1 HP/sec |
152
+ | xp_boost | +25% XP |
153
+ | last_stand | +50% damage below 30% HP |
154
+
155
+ PerkPool: `roll_selection(3)` (unowned or upgradable only),
156
+ `acquire_perk()`, `get_stat_bonus("attack")`, `has_effect("lifesteal")` +
157
+ `get_effect_value()`, `reset()` per run.
158
+
159
+ Level-up flow: `stats.add_xp()` true -> emit `player_leveled_up` then
160
+ `level_up_ready` -> PerkSelectionUI shows 3 cards (LEVEL_UP state pauses
161
+ tree) -> pick emits `perk_selected` -> player acquires and applies stat
162
+ modifiers via `stats.add_modifier` -> resume. Special effects (lifesteal,
163
+ thorns, multishot) are checked at their point of use via
164
+ `pool.has_effect()`, not applied as stats.
165
+
166
+ ## Status effects
167
+
168
+ StatusEffect base (Node): effect_id, duration 3s, tick_interval 1s,
169
+ max_stacks 3. Override `tick()`, `on_expire()`, `on_max_stacks()`,
170
+ `get_speed_multiplier()`. `add_stack()` refreshes duration.
171
+
172
+ EffectManager attaches to any entity: `apply_effect(BurnEffect, entity)`
173
+ handles stacking, `get_speed_multiplier()` returns the product of all active
174
+ effects (feed it into movement), `remove_effect/remove_all`.
175
+
176
+ Built-ins and their max-stack payoffs (the interesting design bit -
177
+ stacking to cap triggers a burst):
178
+
179
+ - Burn: 3 dmg per 0.5s, 5 stacks; at cap, a 15x damage burst.
180
+ - Freeze: 30% slow per stack, 3 stacks; at cap, full 2s stun.
181
+ - Poison: 2 dmg/s, 3 stacks; each new stack extends duration 2s; supports
182
+ lifesteal back to the source.
183
+
184
+ ## Juice quick reference
185
+
186
+ ```gdscript
187
+ Juice.shake(4.0) # camera shake
188
+ Juice.hitstop(0.05) # freeze frame on big hits
189
+ Juice.flash_node(enemy, Color.WHITE, 0.1)
190
+ Juice.spawn_float_text(node, "+50 XP", Color.GOLD)
191
+ Juice.spawn_hit_particles(pos, Color.RED, 6)
192
+ Juice.bounce(node, 1.2) # scale bounce
193
+ Juice.register_camera(camera) # once, from player _ready()
194
+ ```
195
+
196
+ If `register_camera` is never called, shake silently does nothing - a
197
+ classic "why is there no juice" bug.
198
+
199
+ ## HUD and notifications
200
+
201
+ HUD subscribes to EventBus only: health/energy/XP bars, level, gold, active
202
+ quest list, and a notification label (fade in, 2s hold, fade out) driven by
203
+ `EventBus.notification_requested.emit("Quest complete!", Color.GOLD)`.
204
+ HUD also owns pause and inventory toggles.
205
+
206
+ ## Audio
207
+
208
+ AudioManager: `play_music(path)` crossfades (pass false for hard cut),
209
+ `play_sfx(stream, pitch_variation)`, `play_sfx_at(stream, pos, variation)`
210
+ positional. Auto-creates Music and SFX buses if missing. Town theme in the
211
+ hub, battle music in combat areas, switch on `scene_ready`.
212
+
213
+ ## Save/load
214
+
215
+ GameManager saves to `user://savegame.cfg` (ConfigFile): current level path
216
+ + spawn position, player stats (level, XP, health, attack, defense),
217
+ inventory + equipment as resource paths, gold, quest state (active with
218
+ progress, completed ids). `save_game()` from the pause menu,
219
+ `load_game() -> bool` from Continue, `has_save()` gates the button.
220
+ `restart_game()` clears inventory, resets perks, returns to town.
221
+
222
+ Save items by resource path, not serialized objects - paths survive schema
223
+ changes; serialized Resources do not.
224
+
225
+ ## Order of content work
226
+
227
+ 1. Enemy roster (CHASE first, then RANGED; TANK/SWARM/BOSS after combat
228
+ feels right) + spawner in the forest level.
229
+ 2. Loot orbs + level-up perks (progression pull).
230
+ 3. One NPC with dialogue in town, one kill quest wired through the level.
231
+ 4. Inventory + a treasure chest + equipment stat bonuses.
232
+ 5. Status effects on weapons/perks (burning_strikes, frost_touch).
233
+ 6. Boss + dungeon kill gate, then save/load last - it serializes everything
234
+ above, so build it when the shapes are stable.
@@ -0,0 +1,241 @@
1
+ # 2D Action RPG - Core
2
+
3
+ Top-down action RPG blueprint: event-driven architecture, player controller,
4
+ stats pipeline, combat components, weapons, and area transitions. NPCs,
5
+ dialogue, quests, inventory, perks, status effects, and enemies live in
6
+ `2d-rpg-content.md`.
7
+
8
+ ## Minimum playable base (build this first)
9
+
10
+ One level extending LevelBase: player with 8-way movement + one sword swing +
11
+ dodge roll, a couple of chase enemies with `take_hit()`, HUD health bar. Prove
12
+ "move, hit enemy, get hit, see numbers" before any dialogue or quest exists.
13
+
14
+ Two rules for every scene:
15
+
16
+ - Dynamic viewport: `display/window/stretch/mode = "canvas_items"`,
17
+ `stretch/aspect = "expand"`. UI via Control anchors; compute spawn points and
18
+ bounds from `get_viewport_rect().size`, never hardcoded 1920x1080.
19
+ - Playable slice: every input gets feedback through the Juice autoload (shake,
20
+ flash, float text, hitstop). A silent build fails even if every system works.
21
+
22
+ ## Architecture: modules + EventBus
23
+
24
+ Systems NEVER reference each other directly. All cross-system communication
25
+ flows through EventBus, a global signal bus autoload. Each module can be added
26
+ or removed without breaking others.
27
+
28
+ ```
29
+ core/
30
+ autoloads/{event_bus,game_manager}.gd
31
+ levels/level_base.gd
32
+ player/{player.gd,player.tscn}
33
+ modules/
34
+ audio/audio_manager.gd
35
+ combat/{hitbox_component,hurtbox_component,knockback_component,
36
+ stats,modified_value}.gd
37
+ dialogue/{dialogue_box,dialogue_data,npc}.gd
38
+ enemies/{enemy_base,enemy_data,enemy_database,enemy_spawner}.gd
39
+ effects/{status_effect,effect_manager,burn_effect,freeze_effect,poison_effect}.gd
40
+ inventory/{inventory_manager,inventory_ui,item_data}.gd
41
+ juice/juice.gd
42
+ loot/{area_transition,item_drop,loot_table,pickup_orb,treasure_chest}.gd
43
+ progression/{perk_data,perk_database,perk_pool,perk_selection_ui}.gd
44
+ quests/{quest_data,quest_manager}.gd
45
+ weapons/{weapon_base,weapon_data,weapon_manager,projectile}.gd
46
+ weapons/weapons/{sword,bow,staff,orb}.gd
47
+ content/levels/{town,forest,dungeon}.gd
48
+ ui/{hud/hud.gd, menus/{main_menu,pause_menu,game_over}.gd}
49
+ ```
50
+
51
+ Six autoloads, in this order: EventBus, GameManager, AudioManager,
52
+ QuestManager, Juice, InventoryManager.
53
+
54
+ ### EventBus signal groups (define up front)
55
+
56
+ Player: `player_health_changed`, `player_energy_changed`, `player_died`,
57
+ `player_leveled_up`, `player_xp_gained`. Combat: `damage_dealt`,
58
+ `enemy_killed(enemy, xp_value)`, `player_attack_executed`. Interaction:
59
+ `interaction_available/unavailable`, `dialogue_started/ended`. Inventory:
60
+ `item_picked_up/used/equipped/unequipped`, `gold_changed`. Quests:
61
+ `quest_started/updated/completed`, `quest_objective_progressed`. Progression:
62
+ `level_up_ready`, `perk_selected`, `perk_applied`. Scene:
63
+ `scene_transition_started/completed`, `scene_ready`. Spawner:
64
+ `wave_started/cleared`. UI: `notification_requested(text, color)`,
65
+ `boss_health_changed`.
66
+
67
+ ## Physics layers and input
68
+
69
+ | Layer | Name |
70
+ |-------|------|
71
+ | 1 | terrain |
72
+ | 2 | player |
73
+ | 3 | enemies |
74
+ | 4 | player_hitbox |
75
+ | 5 | enemy_hitbox |
76
+ | 6 | interactions |
77
+ | 7 | pickups |
78
+
79
+ Hitbox on 4/5, hurtbox monitors the opposite side's layer.
80
+
81
+ Input map (9 actions): move_up/down/left/right (WASD + arrows + stick), attack
82
+ (LMB/Space), dodge (RMB/Shift), interact (E), pause (Esc), inventory (I).
83
+
84
+ ## GameManager: states and transitions
85
+
86
+ ```gdscript
87
+ enum GameState { MAIN_MENU, PLAYING, PAUSED, DIALOGUE, INVENTORY, LEVEL_UP, GAME_OVER }
88
+ ```
89
+
90
+ Everything except MAIN_MENU/PLAYING pauses the tree; `change_state()` handles
91
+ pause/unpause. Gate gameplay input on `GameManager.is_gameplay_active()`.
92
+
93
+ Scene transition flow (fade overlay owned by GameManager):
94
+ `transition_to_scene(path, spawn_point, spawn_direction)` -> fade to black
95
+ 0.3s -> emit `scene_transition_started` -> `change_scene_to_file` -> wait TWO
96
+ process frames -> emit `scene_ready`, state PLAYING -> fade in -> emit
97
+ `scene_transition_completed`. The player reads
98
+ `GameManager.player_spawn_point` / `player_spawn_direction` in `_ready()`.
99
+ Guard with an `_is_transitioning` flag; never call transition from inside a
100
+ transition callback.
101
+
102
+ Area transitions are trivial once this exists - an Area2D with three exports
103
+ (`target_scene`, `spawn_point`, `spawn_direction`) whose `body_entered` calls
104
+ `GameManager.transition_to_scene()`. Place at map edges and doorways.
105
+
106
+ ## Player controller
107
+
108
+ ```
109
+ Player (CharacterBody2D, layer 2, group "player")
110
+ CollisionShape2D (circle, radius 8)
111
+ WeaponManager (Node2D)
112
+ HurtboxComponent (Area2D)
113
+ CollisionShape2D (circle, radius 10)
114
+ InteractionArea (Area2D)
115
+ CollisionShape2D (circle, radius 30)
116
+ Camera2D
117
+ ```
118
+
119
+ State machine: `IDLE, MOVE, ATTACK, DODGE, HURT, DEAD, INTERACT`.
120
+
121
+ ```gdscript
122
+ var input := Input.get_vector("move_left", "move_right", "move_up", "move_down")
123
+ if input.length() > 0.1:
124
+ facing = input.normalized()
125
+ velocity = facing * stats.get_speed()
126
+ state = State.MOVE
127
+ else:
128
+ velocity = velocity.move_toward(Vector2.ZERO, stats.get_speed() * 10.0 * delta)
129
+ state = State.IDLE
130
+ move_and_slide()
131
+ ```
132
+
133
+ - Attack: manual aims at mouse direction; optional auto_attack targets the
134
+ nearest enemy within 250px. Delegate to
135
+ `weapon_manager.attack(direction)` gated by `can_attack()`.
136
+ - Dodge roll: costs 20 energy (`stats.use_energy` returns false if broke),
137
+ 0.25s duration, invincible for the duration, fading trail rects.
138
+ - Hurt: ignore if invincible/dead/dodging. `stats.take_damage`, 0.5s i-frames,
139
+ knockback velocity, `Juice.shake(5)`, red flash, float text, emit
140
+ `player_health_changed`.
141
+
142
+ ## Stats: the ModifiedValue pipeline
143
+
144
+ `final = (base + additive_sum) * (1.0 + multiplicative_sum)`. Modifiers are
145
+ tagged with a source string so a whole buff can be removed in one call:
146
+
147
+ ```gdscript
148
+ stats.add_modifier("attack", 5, "fire_buff")
149
+ stats.remove_modifier("attack", "fire_buff")
150
+ ```
151
+
152
+ Stats resource: base_max_health 100, base_attack 10, base_defense 5,
153
+ base_speed 120, base_crit_chance 0.05, base_crit_multiplier 1.5. Key methods:
154
+ `take_damage()` returns `{damage, killed}`, `calculate_damage(is_crit)`,
155
+ `roll_crit()`, `add_xp()` returns true on level-up, `use_energy()`.
156
+
157
+ MUST call `stats.initialize()` in `_ready()` - forgetting it leaves the
158
+ pipeline null and everything crashes on first hit.
159
+
160
+ Level-up: +10 max HP, +2 attack, +1 defense, +3 speed, full heal.
161
+ XP needed = `50 + level * 30`.
162
+
163
+ ## Combat components (reusable trio)
164
+
165
+ - HitboxComponent (Area2D): the damage dealer. `damage`, `knockback_force`,
166
+ `hit_cooldown` (per-target cooldown dictionary), `try_hit(target) -> bool`,
167
+ `activate()/deactivate()` (deactivate clears cooldowns). Emits
168
+ `hit_landed(target, damage, knockback)`.
169
+ - HurtboxComponent (Area2D): the receiver. `invincibility_duration` 0.3s,
170
+ emits `damage_received(amount, source, knockback)` via
171
+ `take_hit(damage, source, knockback)`.
172
+ - KnockbackComponent (Node on any CharacterBody2D): decaying velocity,
173
+ `resistance` 0-1, `decay_rate` 8. `apply_knockback(force)` then add
174
+ `get_knockback_velocity()` to movement.
175
+
176
+ Attach these to player, enemies, chests - anything hittable. This trio is
177
+ what keeps combat code out of entity scripts.
178
+
179
+ ## Weapon system (data-driven)
180
+
181
+ WeaponData resource carries everything: type string, base_damage,
182
+ attack_speed (attacks/sec), knockback, range, piercing, projectile
183
+ speed/count/fan_angle, area_radius, orbit_count/speed, color. WeaponManager
184
+ (child of player) equips, switches (1-4 keys / scroll), and delegates attacks;
185
+ a `WEAPON_SCRIPTS` const maps type string -> preloaded script.
186
+
187
+ Four archetypes:
188
+
189
+ - Sword: 120-degree arc swing, alternating direction, ease-out for weight,
190
+ forward lunge, physics cone query, trail.
191
+ - Bow: 0.15s draw, then a fan of projectiles (count + fan_angle from data).
192
+ - Staff: homing bolts (homing_strength 3.0) + optional `trigger_nova()` AoE.
193
+ - Orb: passive - orbits the player, contact damage with per-enemy cooldown,
194
+ always active regardless of selected weapon.
195
+
196
+ One generic projectile script serves bow, staff, AND enemies: straight or
197
+ homing, piercing (tracks hit bodies to prevent double-hit), knockback, trail,
198
+ lifetime despawn. Configure per-shot via properties + `collision_mask` and a
199
+ `source_node` so it never hits its shooter.
200
+
201
+ ## LevelBase and level authoring
202
+
203
+ All levels extend LevelBase, which does the boring wiring once:
204
+
205
+ ```gdscript
206
+ func _ready() -> void:
207
+ _spawn_player() # instantiate player.tscn
208
+ _setup_ui() # HUD, PauseMenu, DialogueBox, Inventory, GameOver, PerkSelectionUI
209
+ _setup_connections()
210
+ ```
211
+
212
+ A concrete level sets `level_name`, calls `super._ready()`, then adds its
213
+ spawner / NPCs / AreaTransitions. Town = safe hub with NPCs. Forest = combat
214
+ area with wave spawner. Dungeon = boss arena with a kill gate.
215
+
216
+ ## Build order
217
+
218
+ 1. project.godot: 6 autoloads in order, input map, layer names, 1920x1080
219
+ canvas_items/expand.
220
+ 2. EventBus with the full signal catalog (empty handlers are fine).
221
+ 3. Stats + ModifiedValue, then the combat component trio.
222
+ 4. Player: movement -> dodge -> WeaponManager with sword only.
223
+ 5. One chase enemy + Juice feedback + HUD health bar. Playable slice check.
224
+ 6. GameManager transitions + LevelBase + a second area with AreaTransition.
225
+ 7. Content systems from `2d-rpg-content.md`: enemies, NPCs, quests,
226
+ inventory, perks, effects, save/load.
227
+
228
+ ## Traps
229
+
230
+ - Direct module references. Never `get_node("/root/QuestManager")` from a
231
+ weapon script - emit an EventBus signal. Modules only know EventBus and
232
+ their own data types; anything else rots into circular dependencies.
233
+ - Skipping `stats.initialize()`. Null pipeline, crash on first damage.
234
+ - Huge `_ready()` chains needing other nodes. Await
235
+ `get_tree().process_frame` or connect to `EventBus.scene_ready` instead.
236
+ - UI without `process_mode = ALWAYS`. Dialogue, inventory, level-up, and
237
+ pause all pause the tree; the UI must keep processing.
238
+ - Wrong hitbox/hurtbox layers. Hitbox layer 4/5, hurtbox masks the OPPOSING
239
+ side. Getting this backwards silently produces no hits.
240
+ - Renaming InteractionArea. NPC scripts access `$InteractionArea` by exact
241
+ name; a rename kills interaction with no error at parse time.