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.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +27 -5
- package/.codex-plugin/plugin.json +28 -6
- package/.cursor-plugin/plugin.json +27 -5
- package/.factory-plugin/plugin.json +27 -5
- package/.opencode/plugins/summer.js +1 -1
- package/CHANGELOG.md +120 -0
- package/README.md +22 -7
- package/assets/audit/scene_audit.gd +4136 -0
- package/assets/seeing/seeing_probe.gd +1873 -0
- package/dist/cli/commands/setup.js +6 -19
- package/dist/cli/commands/skills.js +57 -32
- package/dist/core/api-client.d.ts +9 -1
- package/dist/core/api-client.js +21 -4
- package/dist/core/capabilities/agent-playbook.js +46 -0
- package/dist/core/capabilities/audit/accept.d.ts +55 -0
- package/dist/core/capabilities/audit/accept.js +147 -0
- package/dist/core/capabilities/audit/args.d.ts +95 -0
- package/dist/core/capabilities/audit/args.js +89 -0
- package/dist/core/capabilities/audit/audit.d.ts +56 -0
- package/dist/core/capabilities/audit/audit.js +287 -0
- package/dist/core/capabilities/audit/frame.d.ts +14 -0
- package/dist/core/capabilities/audit/frame.js +35 -0
- package/dist/core/capabilities/audit/gaps.d.ts +96 -0
- package/dist/core/capabilities/audit/gaps.js +257 -0
- package/dist/core/capabilities/audit/judge.d.ts +162 -0
- package/dist/core/capabilities/audit/judge.js +1134 -0
- package/dist/core/capabilities/audit/math.d.ts +110 -0
- package/dist/core/capabilities/audit/math.js +263 -0
- package/dist/core/capabilities/audit/summary.d.ts +74 -0
- package/dist/core/capabilities/audit/summary.js +212 -0
- package/dist/core/capabilities/board.d.ts +31 -0
- package/dist/core/capabilities/board.js +43 -0
- package/dist/core/capabilities/camera-view.d.ts +4 -2
- package/dist/core/capabilities/camera-view.js +6 -3
- package/dist/core/capabilities/connect-signal.d.ts +85 -0
- package/dist/core/capabilities/connect-signal.js +285 -0
- package/dist/core/capabilities/engine-fallbacks.d.ts +5 -0
- package/dist/core/capabilities/engine-fallbacks.js +5 -0
- package/dist/core/capabilities/engine-ops.d.ts +5 -1
- package/dist/core/capabilities/engine-ops.js +0 -3
- package/dist/core/capabilities/engine-receipt.d.ts +12 -0
- package/dist/core/capabilities/engine-receipt.js +26 -0
- package/dist/core/capabilities/file-read.d.ts +64 -0
- package/dist/core/capabilities/file-read.js +325 -0
- package/dist/core/capabilities/game-task-plan.js +4 -2
- package/dist/core/capabilities/grep.d.ts +60 -0
- package/dist/core/capabilities/grep.js +190 -0
- package/dist/core/capabilities/inspect-node.d.ts +56 -0
- package/dist/core/capabilities/inspect-node.js +225 -0
- package/dist/core/capabilities/inspect-resource.d.ts +61 -0
- package/dist/core/capabilities/inspect-resource.js +376 -0
- package/dist/core/capabilities/math3d.d.ts +28 -0
- package/dist/core/capabilities/math3d.js +88 -0
- package/dist/core/capabilities/motion-generation.d.ts +62 -0
- package/dist/core/capabilities/motion-generation.js +138 -0
- package/dist/core/capabilities/placement-batch.d.ts +102 -0
- package/dist/core/capabilities/placement-batch.js +483 -0
- package/dist/core/capabilities/placement-math.d.ts +70 -0
- package/dist/core/capabilities/placement-math.js +209 -0
- package/dist/core/capabilities/placement-script.d.ts +42 -0
- package/dist/core/capabilities/placement-script.js +1096 -0
- package/dist/core/capabilities/placement.d.ts +485 -0
- package/dist/core/capabilities/placement.js +1731 -0
- package/dist/core/capabilities/project-context.d.ts +33 -2
- package/dist/core/capabilities/project-context.js +87 -4
- package/dist/core/capabilities/replace-node.d.ts +91 -0
- package/dist/core/capabilities/replace-node.js +423 -0
- package/dist/core/capabilities/runtime-control.d.ts +20 -4
- package/dist/core/capabilities/runtime-control.js +67 -2
- package/dist/core/capabilities/scene-batch.d.ts +63 -0
- package/dist/core/capabilities/scene-batch.js +394 -0
- package/dist/core/capabilities/scene-readback.d.ts +36 -0
- package/dist/core/capabilities/scene-readback.js +54 -0
- package/dist/core/capabilities/seeing/args.d.ts +348 -0
- package/dist/core/capabilities/seeing/args.js +178 -0
- package/dist/core/capabilities/seeing/candidates.d.ts +127 -0
- package/dist/core/capabilities/seeing/candidates.js +282 -0
- package/dist/core/capabilities/seeing/math.d.ts +134 -0
- package/dist/core/capabilities/seeing/math.js +269 -0
- package/dist/core/capabilities/seeing/probe.d.ts +62 -0
- package/dist/core/capabilities/seeing/probe.js +188 -0
- package/dist/core/capabilities/seeing/scoring.d.ts +235 -0
- package/dist/core/capabilities/seeing/scoring.js +639 -0
- package/dist/core/capabilities/seeing/seeing.d.ts +233 -0
- package/dist/core/capabilities/seeing/seeing.js +1341 -0
- package/dist/core/capabilities/seeing/shot-store.d.ts +52 -0
- package/dist/core/capabilities/seeing/shot-store.js +204 -0
- package/dist/core/capabilities/surface-snap-mesh.d.ts +88 -0
- package/dist/core/capabilities/surface-snap-mesh.js +425 -0
- package/dist/core/capabilities/surface-snap.d.ts +77 -0
- package/dist/core/capabilities/surface-snap.js +461 -0
- package/dist/core/capabilities/tool-dispatch.js +231 -72
- package/dist/core/capabilities/tscn.d.ts +85 -0
- package/dist/core/capabilities/tscn.js +391 -0
- package/dist/core/capabilities/world-snapshot.d.ts +58 -0
- package/dist/core/capabilities/world-snapshot.js +150 -0
- package/dist/core/capability-skew.d.ts +5 -5
- package/dist/core/capability-skew.js +14 -6
- package/dist/core/headless/worker-engine-client.d.ts +1 -1
- package/dist/core/headless/worker-engine-client.js +2 -2
- package/dist/core/library-read.d.ts +37 -5
- package/dist/core/library-read.js +264 -33
- package/dist/core/library-search.d.ts +2 -2
- package/dist/core/skills-registry.d.ts +9 -1
- package/dist/core/skills-registry.js +25 -2
- package/dist/installer/agent-config.d.ts +9 -4
- package/dist/installer/agent-config.js +194 -392
- package/dist/installer/agent-table.d.ts +119 -0
- package/dist/installer/agent-table.js +619 -0
- package/dist/installer/setup.js +4 -2
- package/dist/installer/skill-locations.d.ts +8 -17
- package/dist/installer/skill-locations.js +22 -101
- package/dist/installer/version-check.d.ts +5 -1
- package/dist/installer/version-check.js +38 -28
- package/dist/mcp/server.js +9 -3
- package/dist/mcp/tools/asset-tools.js +21 -3
- package/dist/mcp/tools/audit-tools.d.ts +23 -0
- package/dist/mcp/tools/audit-tools.js +60 -0
- package/dist/mcp/tools/debug-tools.js +3 -1
- package/dist/mcp/tools/file-tools.js +17 -4
- package/dist/mcp/tools/generate-tools.js +74 -66
- package/dist/mcp/tools/library-tools.js +2 -0
- package/dist/mcp/tools/perception-tools.js +6 -19
- package/dist/mcp/tools/placement-tools.d.ts +24 -0
- package/dist/mcp/tools/placement-tools.js +91 -0
- package/dist/mcp/tools/project-tools.js +18 -15
- package/dist/mcp/tools/scene-tools.js +71 -83
- package/dist/mcp/tools/seeing-tools.d.ts +24 -0
- package/dist/mcp/tools/seeing-tools.js +64 -0
- package/dist/mcp/tools/spatial-tools.js +17 -9
- package/dist/mcp/tools/visual-tools.js +59 -7
- package/gemini-extension.json +26 -4
- package/integrations/README.md +48 -19
- package/integrations/amp/README.md +12 -0
- package/integrations/amp/manifest-target.json +3 -0
- package/integrations/antigravity/README.md +12 -0
- package/integrations/antigravity/manifest-target.json +3 -0
- package/integrations/claude-desktop/README.md +12 -0
- package/integrations/claude-desktop/manifest-target.json +3 -0
- package/integrations/cline/README.md +8 -9
- package/integrations/cline-cli/README.md +12 -0
- package/integrations/cline-cli/manifest-target.json +3 -0
- package/integrations/copilot-jetbrains/README.md +12 -0
- package/integrations/copilot-jetbrains/manifest-target.json +3 -0
- package/integrations/crush/README.md +12 -0
- package/integrations/crush/manifest-target.json +3 -0
- package/integrations/github-copilot/README.md +8 -8
- package/integrations/goose/README.md +12 -0
- package/integrations/goose/manifest-target.json +3 -0
- package/integrations/grok-build/README.md +12 -0
- package/integrations/grok-build/manifest-target.json +3 -0
- package/integrations/hermes/README.md +12 -0
- package/integrations/hermes/manifest-target.json +3 -0
- package/integrations/junie/README.md +12 -0
- package/integrations/junie/manifest-target.json +3 -0
- package/integrations/kilo-code/README.md +6 -10
- package/integrations/kimi-code/README.md +12 -0
- package/integrations/kimi-code/manifest-target.json +3 -0
- package/integrations/kiro/README.md +12 -0
- package/integrations/kiro/manifest-target.json +3 -0
- package/integrations/lm-studio/README.md +8 -8
- package/integrations/mistral-vibe/README.md +12 -0
- package/integrations/mistral-vibe/manifest-target.json +3 -0
- package/integrations/opencode/README.md +9 -12
- package/integrations/qoder/README.md +12 -0
- package/integrations/qoder/manifest-target.json +3 -0
- package/integrations/qwen-code/README.md +12 -0
- package/integrations/qwen-code/manifest-target.json +3 -0
- package/integrations/roo-code/README.md +8 -7
- package/integrations/rovo-dev/README.md +12 -0
- package/integrations/rovo-dev/manifest-target.json +3 -0
- package/integrations/trae/README.md +12 -0
- package/integrations/trae/manifest-target.json +3 -0
- package/integrations/visual-studio/README.md +12 -0
- package/integrations/visual-studio/manifest-target.json +3 -0
- package/integrations/vscode-copilot/README.md +9 -9
- package/integrations/warp/README.md +12 -0
- package/integrations/warp/manifest-target.json +3 -0
- package/integrations/windsurf/README.md +8 -9
- package/integrations/zed/README.md +12 -0
- package/integrations/zed/manifest-target.json +3 -0
- package/library/references/mcp-tools-reference/mcp-tools-reference.md +59 -15
- package/library/references/mcp-tools-reference/resource.yaml +1 -1
- package/library/references/summer-folder/resource.yaml +1 -1
- package/library/references/summer-folder/summer-folder.md +1 -1
- package/library/skills/3d-lighting/SKILL.md +1 -1
- package/library/skills/README.md +264 -0
- package/library/skills/adaptive-music/SKILL.md +1 -1
- package/library/skills/agent-playtesting/SKILL.md +1 -1
- package/library/skills/ai-characters-in-games/SKILL.md +220 -0
- package/library/skills/ai-characters-in-games/resource.yaml +30 -0
- package/library/skills/ambient-bed/SKILL.md +1 -1
- package/library/skills/animated-loop/SKILL.md +1 -1
- package/library/skills/animation-tree/SKILL.md +1 -1
- package/library/skills/art-direction/SKILL.md +1 -1
- package/library/skills/asset-strategy/SKILL.md +2 -1
- package/library/skills/asset-strategy/resource.yaml +2 -1
- package/library/skills/audio-direction/SKILL.md +1 -1
- package/library/skills/auto-fire-targeting/SKILL.md +1 -1
- package/library/skills/brainstorm-game/SKILL.md +1 -1
- package/library/skills/brainstorming/SKILL.md +1 -1
- package/library/skills/browse-templates/SKILL.md +3 -3
- package/library/skills/browse-templates/resource.yaml +1 -1
- package/library/skills/camera-rigs/SKILL.md +128 -0
- package/library/skills/camera-rigs/resource.yaml +29 -0
- package/library/skills/celeste-momentum-platforming/SKILL.md +1 -1
- package/library/skills/character-animation-wiring/SKILL.md +1 -1
- package/library/skills/character-model/SKILL.md +1 -1
- package/library/skills/character-movement/SKILL.md +326 -0
- package/library/skills/character-movement/references/default-third-person-controller.gd +201 -0
- package/library/skills/character-movement/references/default-third-person-verification-probe.gd +154 -0
- package/library/skills/character-movement/references/movement-3d.md +136 -0
- package/library/skills/character-movement/references/platformer-feel.md +83 -0
- package/library/skills/character-movement/resource.yaml +40 -0
- package/library/skills/character-portrait/SKILL.md +1 -1
- package/library/skills/cinematic-cutscene/SKILL.md +1 -1
- package/library/skills/combat-basics/SKILL.md +159 -0
- package/library/skills/combat-basics/references/projectiles-and-aoe.md +100 -0
- package/library/skills/combat-basics/resource.yaml +34 -0
- package/library/skills/concept-art/SKILL.md +1 -1
- package/library/skills/create-asset-sheet/SKILL.md +1 -1
- package/library/skills/debug/SKILL.md +1 -1
- package/library/skills/debugging-game-feel/SKILL.md +1 -1
- package/library/skills/design-level/SKILL.md +1 -1
- package/library/skills/design-mechanic/SKILL.md +1 -1
- package/library/skills/design-npc/SKILL.md +1 -1
- package/library/skills/diagnosing-perf-regressions/SKILL.md +1 -1
- package/library/skills/dispatching-parallel-agents/SKILL.md +1 -1
- package/library/skills/driving-the-editor-ui/SKILL.md +1 -1
- package/library/skills/environment-kit/SKILL.md +1 -1
- package/library/skills/export-and-ship/SKILL.md +1 -1
- package/library/skills/fabricating-assets/SKILL.md +1 -1
- package/library/skills/facial-and-lipsync/SKILL.md +1 -1
- package/library/skills/fps-controller/SKILL.md +9 -7
- package/library/skills/fps-controller/resource.yaml +4 -1
- package/library/skills/game-feel/SKILL.md +1 -1
- package/library/skills/gameskill/SKILL.md +1 -1
- package/library/skills/gdscript-patterns/SKILL.md +1 -1
- package/library/skills/generate-motion/SKILL.md +9 -9
- package/library/skills/generate-motion/resource.yaml +2 -1
- package/library/skills/godogen-visual-proof-game-generation/SKILL.md +1 -1
- package/library/skills/headless-scripting/SKILL.md +1 -1
- package/library/skills/in-game-purchases/SKILL.md +254 -0
- package/library/skills/in-game-purchases/resource.yaml +29 -0
- package/library/skills/instantiate-asset-pack/SKILL.md +1 -1
- package/library/skills/investigating-bugs/SKILL.md +1 -1
- package/library/skills/lumera-single-image-scene-reconstruction/SKILL.md +1 -1
- package/library/skills/make-game/SKILL.md +25 -3
- package/library/skills/make-game/references/2d-platformer-polish.md +93 -0
- package/library/skills/make-game/references/2d-platformer.md +117 -0
- package/library/skills/make-game/references/2d-rpg-content.md +234 -0
- package/library/skills/make-game/references/2d-rpg.md +241 -0
- package/library/skills/make-game/references/2d-survivors-progression.md +201 -0
- package/library/skills/make-game/references/2d-survivors.md +237 -0
- package/library/skills/make-game/references/3d-fps-systems.md +216 -0
- package/library/skills/make-game/references/3d-fps.md +177 -0
- package/library/skills/make-game/references/3d-horror-systems.md +186 -0
- package/library/skills/make-game/references/3d-horror.md +201 -0
- package/library/skills/make-game/references/3d-third-person-systems.md +220 -0
- package/library/skills/make-game/references/3d-third-person.md +215 -0
- package/library/skills/make-game/resource.yaml +6 -1
- package/library/skills/multiplayer/SKILL.md +150 -0
- package/library/skills/multiplayer/resource.yaml +33 -0
- package/library/skills/multiplayer-movement/SKILL.md +510 -0
- package/library/skills/multiplayer-movement/files.md +501 -0
- package/library/skills/multiplayer-movement/resource.yaml +30 -0
- package/library/skills/multiplayer-project/SKILL.md +521 -0
- package/library/skills/multiplayer-project/files.md +448 -0
- package/library/skills/multiplayer-project/resource.yaml +36 -0
- package/library/skills/multiplayer-publish/SKILL.md +229 -0
- package/library/skills/multiplayer-publish/export-errors.md +89 -0
- package/library/skills/multiplayer-publish/resource.yaml +28 -0
- package/library/skills/multiplayer-state/SKILL.md +438 -0
- package/library/skills/multiplayer-state/files.md +592 -0
- package/library/skills/multiplayer-state/resource.yaml +35 -0
- package/library/skills/multiplayer-testing/SKILL.md +236 -0
- package/library/skills/multiplayer-testing/resource.yaml +39 -0
- package/library/skills/music-track/SKILL.md +1 -1
- package/library/skills/navigate-summer/SKILL.md +1 -1
- package/library/skills/new-project/SKILL.md +1 -1
- package/library/skills/organic-model/SKILL.md +1 -1
- package/library/skills/pixel-art/SKILL.md +1 -1
- package/library/skills/play/SKILL.md +1 -1
- package/library/skills/playtesting-a-feature/SKILL.md +1 -1
- package/library/skills/procedural-animation/SKILL.md +2 -2
- package/library/skills/procedural-animation/resource.yaml +1 -1
- package/library/skills/prop-model/SKILL.md +1 -1
- package/library/skills/psx-retro-rendering/SKILL.md +1 -1
- package/library/skills/realtime-wet-surfaces/SKILL.md +2 -2
- package/library/skills/remote-deploy/SKILL.md +1 -1
- package/library/skills/retarget/SKILL.md +1 -1
- package/library/skills/running-in-the-cloud/SKILL.md +1 -1
- package/library/skills/save-load/SKILL.md +156 -0
- package/library/skills/save-load/resource.yaml +27 -0
- package/library/skills/scene-composition/SKILL.md +1 -1
- package/library/skills/scene-hierarchy-design/SKILL.md +1 -1
- package/library/skills/scene-scripting/SKILL.md +1 -1
- package/library/skills/scene-to-level/SKILL.md +1 -1
- package/library/skills/skill-create/SKILL.md +1 -1
- package/library/skills/skill-improve/SKILL.md +1 -1
- package/library/skills/skill-test/SKILL.md +1 -1
- package/library/skills/skintokens-auto-rigging/SKILL.md +1 -1
- package/library/skills/skybox-panorama/SKILL.md +1 -1
- package/library/skills/sound-effect/SKILL.md +1 -1
- package/library/skills/spatial-placement/SKILL.md +134 -3
- package/library/skills/spatial-placement/references/kit-placement-tools.md +364 -0
- package/library/skills/spatial-placement/resource.yaml +16 -2
- package/library/skills/sprite-sheet/SKILL.md +1 -1
- package/library/skills/summer-analytics/SKILL.md +147 -0
- package/library/skills/summer-analytics/resource.yaml +28 -0
- package/library/skills/summer-friends/SKILL.md +226 -0
- package/library/skills/summer-friends/resource.yaml +28 -0
- package/library/skills/summer-leaderboards/SKILL.md +231 -0
- package/library/skills/summer-leaderboards/resource.yaml +30 -0
- package/library/skills/summer-match-results/SKILL.md +286 -0
- package/library/skills/summer-match-results/resource.yaml +32 -0
- package/library/skills/summer-matchmaking/SKILL.md +301 -0
- package/library/skills/summer-matchmaking/resource.yaml +32 -0
- package/library/skills/summer-parties/SKILL.md +253 -0
- package/library/skills/summer-parties/resource.yaml +30 -0
- package/library/skills/summer-player-data/SKILL.md +322 -0
- package/library/skills/summer-player-data/resource.yaml +30 -0
- package/library/skills/summer-store/SKILL.md +271 -0
- package/library/skills/summer-store/resource.yaml +29 -0
- package/library/skills/summer-world-chat/SKILL.md +195 -0
- package/library/skills/summer-world-chat/resource.yaml +30 -0
- package/library/skills/summer-world-saves/SKILL.md +284 -0
- package/library/skills/summer-world-saves/resource.yaml +29 -0
- package/library/skills/text-to-motion/SKILL.md +99 -0
- package/library/skills/text-to-motion/prompts-and-controls.md +34 -0
- package/library/skills/text-to-motion/resource.yaml +41 -0
- package/library/skills/text-to-motion/rigging-for-text-motion.md +54 -0
- package/library/skills/tileable-texture/SKILL.md +1 -1
- package/library/skills/trailer-shot/SKILL.md +1 -1
- package/library/skills/tune-performance/SKILL.md +1 -1
- package/library/skills/ui-basics/SKILL.md +10 -1
- package/library/skills/ui-graphics/SKILL.md +1 -1
- package/library/skills/use-widget-asset/SKILL.md +1 -1
- package/library/skills/using-summer/SKILL.md +2 -2
- package/library/skills/using-summer/resource.yaml +2 -2
- package/library/skills/vehicle-model/SKILL.md +1 -1
- package/library/skills/verification-before-completion/SKILL.md +1 -1
- package/library/skills/verifying-scenes/SKILL.md +76 -2
- package/library/skills/verifying-scenes/resource.yaml +13 -2
- package/library/skills/vfx-dissolve/SKILL.md +1 -1
- package/library/skills/vfx-fire/SKILL.md +1 -1
- package/library/skills/vfx-hit-spark/SKILL.md +1 -1
- package/library/skills/vfx-lightning/SKILL.md +1 -1
- package/library/skills/vfx-magic-glow/SKILL.md +1 -1
- package/library/skills/vfx-muzzle-flash/SKILL.md +1 -1
- package/library/skills/vfx-smoke/SKILL.md +1 -1
- package/library/skills/vfx-water-ripple/SKILL.md +1 -1
- package/library/skills/voice-line/SKILL.md +1 -1
- package/library/skills/web-and-touch-input/SKILL.md +38 -0
- package/library/skills/web-and-touch-input/resource.yaml +28 -0
- package/library/skills/web-compatibility-look/SKILL.md +62 -0
- package/library/skills/web-compatibility-look/resource.yaml +30 -0
- package/library/skills/world-building-3d/SKILL.md +8 -1
- package/library/skills/world-building-3d/references/spatial-tools.md +1 -1
- package/library/skills/world-building-3d/resource.yaml +2 -1
- package/library/skills/writing-plans/SKILL.md +1 -1
- package/library/skills/writing-skills/SKILL.md +1 -1
- package/library/templates/3d-lan-multiplayer-starter/resource.yaml +2 -2
- package/library/tools/attach-to-surface/resource.yaml +142 -0
- package/library/tools/batch/resource.yaml +9 -3
- package/library/tools/connect-ports/resource.yaml +120 -0
- package/library/tools/connect-signal/resource.yaml +3 -2
- package/library/tools/debug-views/resource.yaml +94 -0
- package/library/tools/frame-nodes/resource.yaml +104 -0
- package/library/tools/frame-shot/resource.yaml +134 -0
- package/library/tools/generate-motion/resource.yaml +44 -9
- package/library/tools/get-board/resource.yaml +50 -0
- package/library/tools/get-project-context/resource.yaml +13 -2
- package/library/tools/grep/resource.yaml +77 -0
- package/library/tools/inspect-asset/resource.yaml +71 -0
- package/library/tools/inspect-node/resource.yaml +9 -2
- package/library/tools/inspect-resource/resource.yaml +16 -5
- package/library/tools/instantiate-scene/resource.yaml +27 -2
- package/library/tools/measure/resource.yaml +96 -0
- package/library/tools/place-adjacent/resource.yaml +113 -0
- package/library/tools/play/resource.yaml +15 -2
- package/library/tools/raycast/resource.yaml +101 -0
- package/library/tools/read-file/resource.yaml +36 -2
- package/library/tools/read-library/resource.yaml +2 -2
- package/library/tools/repeat-along/resource.yaml +129 -0
- package/library/tools/replace-node/resource.yaml +11 -5
- package/library/tools/scene-audit/resource.yaml +144 -0
- package/library/tools/screenshot/resource.yaml +13 -2
- package/library/tools/search-assets/resource.yaml +18 -0
- package/library/tools/shot-sheet/resource.yaml +110 -0
- package/library/tools/snap-to-surface/resource.yaml +4 -1
- package/library/tools/world-snapshot/resource.yaml +24 -3
- package/library/tools/zoom/resource.yaml +105 -0
- package/package.json +3 -3
- package/registry/generated/aliases.json +17 -3
- package/registry/generated/counts.json +3 -3
- package/registry/generated/gemini-extension.json +26 -4
- package/registry/generated/index.json +2154 -469
- package/registry/generated/marketplace.claude.json +2 -2
- package/registry/generated/plugin.claude.json +27 -5
- package/registry/generated/plugin.codex.json +28 -6
- package/registry/generated/plugin.cursor.json +27 -5
- package/registry/generated/plugin.factory.json +27 -5
- package/registry/generated/skills-index.md +264 -0
- package/registry/generated/skills-registry.json +901 -206
- package/registry/generated/templates-registry.json +2 -2
- package/library/skills/host-authoritative-state/SKILL.md +0 -332
- package/library/skills/host-authoritative-state/resource.yaml +0 -28
- package/library/skills/peer-to-peer-multiplayer/SKILL.md +0 -373
- package/library/skills/peer-to-peer-multiplayer/resource.yaml +0 -28
- package/library/skills/setup-multiplayer/SKILL.md +0 -336
- 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.
|