claude-code-arcane 2.9.8 → 2.9.9
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/CHANGELOG.md +14 -0
- package/agents/business/business-ops-lead.md +1 -14
- package/agents/game/gameplay-programmer.md +3 -4
- package/agents/game/technical-artist.md +3 -4
- package/dist/cli.js +41 -6
- package/docs/USER-GUIDE.md +1 -1
- package/docs/coordination-rules.md +1 -1
- package/docs/directory-structure.md +93 -122
- package/package.json +1 -1
- package/profiles/backend-go.yaml +1 -0
- package/rules/gamedev/engine-code.md +1 -1
- package/rules/gamedev/shader-code.md +1 -2
- package/rules/gamedev/vn-code.md +3 -2
- package/rules/implementation-workflow.md +1 -1
- package/rules/{ai-code.md → llm-code.md} +5 -5
- package/skills/agent-designer/README.md +2 -1
- package/skills/agent-designer/agent_evaluator.py +0 -5
- package/skills/ai-sdk-setup/SKILL.md +4 -4
- package/skills/architecture-decision/SKILL.md +3 -4
- package/skills/architecture-review/SKILL.md +1 -1
- package/skills/asset-audit/SKILL.md +0 -1
- package/skills/balance-check/SKILL.md +1 -1
- package/skills/brainstorm/SKILL.md +3 -3
- package/skills/brainstorm/references/next-steps-pipeline.md +8 -9
- package/skills/consistency-check/SKILL.md +2 -2
- package/skills/design-system/SKILL.md +1 -1
- package/skills/design-system/references/post-design-validation.md +2 -3
- package/skills/frontend-dev/SKILL.md +27 -28
- package/skills/frontend-dev/references/asset-prompt-guide.md +1 -1
- package/skills/frontend-dev/references/motion-recipes.md +1 -1
- package/skills/help/SKILL.md +1 -2
- package/skills/hotfix/SKILL.md +2 -2
- package/skills/milestone-review/SKILL.md +1 -1
- package/skills/patch-notes/SKILL.md +1 -1
- package/skills/playtest-report/SKILL.md +2 -3
- package/skills/playwright-pro/CLAUDE.md +2 -2
- package/skills/playwright-pro/SKILL.md +13 -9
- package/skills/playwright-pro/agents/migration-planner.md +2 -2
- package/skills/playwright-pro/agents/test-architect.md +1 -2
- package/skills/playwright-pro/agents/test-debugger.md +1 -1
- package/skills/playwright-pro/hooks/detect-playwright.sh +1 -1
- package/skills/playwright-pro/skills/browserstack/SKILL.md +5 -5
- package/skills/playwright-pro/skills/migrate/SKILL.md +1 -1
- package/skills/playwright-pro/skills/report/SKILL.md +2 -2
- package/skills/playwright-pro/skills/testrail/SKILL.md +5 -5
- package/skills/playwright-pro/templates/README.md +2 -2
- package/skills/prototype/SKILL.md +1 -1
- package/skills/quick-design/SKILL.md +1 -1
- package/skills/release-checklist/SKILL.md +0 -1
- package/skills/security-audit/SKILL.md +1 -1
- package/skills/self-improving-agent/CLAUDE.md +12 -12
- package/skills/self-improving-agent/SKILL.md +16 -12
- package/skills/self-improving-agent/agents/memory-analyst.md +1 -1
- package/skills/self-improving-agent/hooks/error-capture.sh +2 -2
- package/skills/self-improving-agent/reference/memory-architecture.md +2 -2
- package/skills/self-improving-agent/reference/promotion-rules.md +3 -3
- package/skills/self-improving-agent/reference/rules-directory-patterns.md +1 -1
- package/skills/self-improving-agent/settings.json +5 -5
- package/skills/self-improving-agent/skills/extract/SKILL.md +7 -7
- package/skills/self-improving-agent/skills/promote/SKILL.md +5 -5
- package/skills/self-improving-agent/skills/remember/SKILL.md +9 -9
- package/skills/self-improving-agent/skills/review/SKILL.md +7 -7
- package/skills/self-improving-agent/skills/status/SKILL.md +8 -8
- package/skills/senior-ml-engineer/references/llm_integration_guide.md +14 -31
- package/skills/senior-prompt-engineer/SKILL.md +10 -10
- package/skills/senior-prompt-engineer/references/prompt_engineering_patterns.md +1 -1
- package/skills/senior-prompt-engineer/scripts/agent_orchestrator.py +43 -40
- package/skills/senior-prompt-engineer/scripts/prompt_optimizer.py +23 -66
- package/skills/shader-dev/reference/fluid-simulation.md +4 -4
- package/skills/shader-dev/reference/simulation-physics.md +6 -6
- package/skills/shader-dev/reference/voxel-rendering.md +1 -1
- package/skills/shader-dev/techniques/ambient-occlusion.md +1 -1
- package/skills/shader-dev/techniques/analytic-ray-tracing.md +2 -2
- package/skills/shader-dev/techniques/domain-warping.md +2 -2
- package/skills/shader-dev/techniques/fluid-simulation.md +45 -45
- package/skills/shader-dev/techniques/multipass-buffer.md +24 -24
- package/skills/shader-dev/techniques/normal-estimation.md +1 -1
- package/skills/shader-dev/techniques/particle-system.md +16 -16
- package/skills/shader-dev/techniques/polar-uv-manipulation.md +1 -1
- package/skills/shader-dev/techniques/post-processing.md +7 -7
- package/skills/shader-dev/techniques/sdf-3d.md +1 -1
- package/skills/shader-dev/techniques/simulation-physics.md +24 -24
- package/skills/shader-dev/techniques/sound-synthesis.md +2 -2
- package/skills/shader-dev/techniques/voronoi-cellular-noise.md +1 -1
- package/skills/shader-dev/techniques/voxel-rendering.md +60 -60
- package/skills/smoke-check/SKILL.md +1 -1
- package/skills/sprint-plan/SKILL.md +1 -2
- package/skills/start/SKILL.md +7 -7
- package/skills/story-done/SKILL.md +1 -1
- package/skills/test-helpers/SKILL.md +7 -2
- package/skills/test-setup/SKILL.md +1 -1
- package/skills/ue-actor-component-architecture/SKILL.md +0 -1
- package/skills/ue-ai-navigation/SKILL.md +0 -1
- package/skills/ue-animation-system/SKILL.md +0 -1
- package/skills/ue-async-threading/SKILL.md +0 -1
- package/skills/ue-audio-system/SKILL.md +0 -1
- package/skills/ue-blueprints/SKILL.md +0 -1
- package/skills/ue-character-movement/SKILL.md +0 -1
- package/skills/ue-cpp-foundations/SKILL.md +0 -1
- package/skills/ue-data-assets-tables/SKILL.md +0 -1
- package/skills/ue-editor-tools/SKILL.md +0 -1
- package/skills/ue-game-features/SKILL.md +0 -1
- package/skills/ue-gameplay-abilities/SKILL.md +0 -1
- package/skills/ue-gameplay-framework/SKILL.md +0 -1
- package/skills/ue-input-system/SKILL.md +0 -1
- package/skills/ue-mass-entity/SKILL.md +0 -1
- package/skills/ue-materials-rendering/SKILL.md +0 -1
- package/skills/ue-module-build-system/SKILL.md +0 -1
- package/skills/ue-naming-conventions/SKILL.md +0 -1
- package/skills/ue-networking-replication/SKILL.md +0 -1
- package/skills/ue-niagara-effects/SKILL.md +0 -1
- package/skills/ue-packaging/SKILL.md +0 -1
- package/skills/ue-physics-collision/SKILL.md +0 -1
- package/skills/ue-procedural-generation/SKILL.md +0 -1
- package/skills/ue-project-context/SKILL.md +0 -1
- package/skills/ue-sequencer-cinematics/SKILL.md +0 -1
- package/skills/ue-serialization-savegames/SKILL.md +0 -1
- package/skills/ue-state-trees/SKILL.md +0 -1
- package/skills/ue-testing-debugging/SKILL.md +0 -1
- package/skills/ue-ui-umg-slate/SKILL.md +0 -1
- package/skills/ue-world-level-streaming/SKILL.md +0 -1
- package/skills/ux-review/SKILL.md +1 -1
- package/docs/RELEASE-SETUP.md +0 -99
- package/docs/presentations/arcane-overview-12.pptx +0 -0
- package/docs/presentations/arcane-overview.pptx +0 -0
- package/docs/presentations/build_arcane_deck.py +0 -310
- package/docs/presentations/build_arcane_deck_12.py +0 -399
- package/docs/trusted-publishing-setup.md +0 -163
|
@@ -26,31 +26,31 @@ precision highp float;
|
|
|
26
26
|
uniform float iTime;
|
|
27
27
|
uniform vec2 iResolution;
|
|
28
28
|
|
|
29
|
-
//
|
|
29
|
+
// WebGL2 must declare the output variable.
|
|
30
30
|
out vec4 fragColor;
|
|
31
31
|
|
|
32
32
|
// ... other functions ...
|
|
33
33
|
|
|
34
34
|
void main() {
|
|
35
|
-
//
|
|
35
|
+
// Use gl_FragCoord.xy instead of fragCoord
|
|
36
36
|
vec2 fragCoord = gl_FragCoord.xy;
|
|
37
37
|
|
|
38
38
|
vec3 col = vec3(0.0);
|
|
39
39
|
|
|
40
40
|
// ... rendering logic ...
|
|
41
41
|
|
|
42
|
-
//
|
|
42
|
+
// Write to fragColor, not gl_FragColor!
|
|
43
43
|
fragColor = vec4(col, 1.0);
|
|
44
44
|
}`;
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
**
|
|
47
|
+
**Common GLSL compile errors:**
|
|
48
48
|
- `in/out storage qualifier supported in GLSL ES 3.00 only` → Check that you are using `getContext("webgl2")` and `#version 300 es`
|
|
49
49
|
- `#version directive must occur on the first line` → Check that the shader string starts with #version, with no characters before it
|
|
50
50
|
- **IMPORTANT: GLSL reserved words**: `cast`, `class`, `template`, `namespace`, `union`, `enum`, `typedef`, `sizeof`, `input`, `output`, `filter`, `image`, `sampler`, `fixed`, `volatile`, `public`, `static`, `extern`, `external`, `interface`, `long`, `short`, `double`, `half`, `unsigned`, `superp`, `inline`, `noinline`, etc. are all GLSL reserved words and **must never be used as variable or function names**! Common pitfall: naming a function `cast` for ray casting → compile failure. **Use compound names like `castRay`, `castShadow`, `shootRay` instead**.
|
|
51
|
-
- **
|
|
52
|
-
- **
|
|
53
|
-
- **
|
|
51
|
+
- **GLSL strict typing**: float/int cannot be mixed. `if (x > 0)` for int, `if (y < 0.0)` for float. Comparing ivec3 members to float requires explicit conversion: `float(c.y) < height`. When getVoxel returns int, compare with `> 0` not `> 0.0`. Function parameter types must match exactly.
|
|
52
|
+
- **Vector dimension mismatch (vec2 vs vec3)**: `p.xz` returns `vec2` and **must never** be added to `vec3` or passed to functions expecting `vec3` parameters (e.g., `fbm(vec3)`, `noise(vec3)`)! Common error: `fbm(p.xz * 0.08 + vec3(...))` — `vec2 + vec3` compile failure. **Fix**: either use a `vec2` version of noise/fbm, or construct a full vec3: `fbm(vec3(p.xz * 0.08, p.y * 0.05))`. Similarly, `vec2` only has `.x`/`.y`, cannot access `.z`/`.w`.
|
|
53
|
+
- **length() / floating-point precision**: `length(ivec2)` must first convert to `vec2`: `length(vec2(d))`. Exact floating-point equality comparison almost never works; use range comparison: `floor(p.y) == floor(height)`
|
|
54
54
|
|
|
55
55
|
# Voxel Rendering Skill
|
|
56
56
|
|
|
@@ -120,7 +120,7 @@ mapPos += mask * rayStep;
|
|
|
120
120
|
### Step 4: Voxel Occupancy Function
|
|
121
121
|
```glsl
|
|
122
122
|
// Basic version: solid block (most common; use this when user asks for "voxel cube")
|
|
123
|
-
//
|
|
123
|
+
// getVoxel receives ivec3, but all internal calculations must use float!
|
|
124
124
|
bool getVoxel(ivec3 c) {
|
|
125
125
|
vec3 p = vec3(c) + vec3(0.5); // ivec3 → vec3 conversion (required!)
|
|
126
126
|
float d = sdBox(p, vec3(6.0)); // Solid 12x12x12 cube
|
|
@@ -135,8 +135,8 @@ bool getVoxelCarved(ivec3 c) {
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
// Advanced version: height map terrain with material IDs
|
|
138
|
-
//
|
|
139
|
-
//
|
|
138
|
+
// all comparisons must use float! c.y is int and must be converted to float for comparison
|
|
139
|
+
// must use range comparison, not exact equality (floating-point precision issues)
|
|
140
140
|
int getVoxelMaterial(ivec3 c) {
|
|
141
141
|
vec3 p = vec3(c); // ivec3 → vec3 conversion (required!)
|
|
142
142
|
float groundHeight = getTerrainHeight(p.xz); // p.xz is vec2, passes float parameters
|
|
@@ -148,7 +148,7 @@ int getVoxelMaterial(ivec3 c) {
|
|
|
148
148
|
// Pure float version (simpler, recommended):
|
|
149
149
|
int getVoxelMaterial(vec3 c) {
|
|
150
150
|
float groundHeight = getTerrainHeight(c.xz);
|
|
151
|
-
//
|
|
151
|
+
// Use range comparison, never exact equality!
|
|
152
152
|
if (c.y >= groundHeight && c.y < groundHeight + 1.0) return 1; // Grass top layer
|
|
153
153
|
if (c.y >= groundHeight - 3.0 && c.y < groundHeight) return 2; // Dirt layer
|
|
154
154
|
if (c.y < groundHeight - 3.0) return 3; // Stone layer
|
|
@@ -156,30 +156,30 @@ int getVoxelMaterial(vec3 c) {
|
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
// Advanced version: mountain terrain (height-based coloring: grass green → rock gray → snow white)
|
|
159
|
-
//
|
|
160
|
-
//
|
|
159
|
+
// Key 1: color thresholds must be based on heightRatio (normalized height 0~1), not absolute height!
|
|
160
|
+
// Key 2: maxH must match the actual maximum return value of getMountainHeight!
|
|
161
161
|
// If getMountainHeight returns at most 15.0, maxH must be 15.0, not arbitrarily 20.0
|
|
162
|
-
//
|
|
163
|
-
//
|
|
164
|
-
float maxH = 15.0; //
|
|
162
|
+
// Key 3: threshold spacing must be large enough (at least 0.2), otherwise color bands are too narrow to see
|
|
163
|
+
// Key 4: grass area typically covers the largest terrain area (low elevation); set grass threshold high (0.4) to ensure green is clearly visible
|
|
164
|
+
float maxH = 15.0; // Must equal the actual max value of getMountainHeight!
|
|
165
165
|
int getMountainVoxel(vec3 c) {
|
|
166
166
|
float height = getMountainHeight(c.xz); // Returns 0 ~ maxH
|
|
167
167
|
if (c.y > height) return 0; // Air
|
|
168
168
|
float heightRatio = c.y / maxH; // Normalize to 0~1
|
|
169
|
-
//
|
|
169
|
+
// Thresholds from low to high: grass < 0.4, rock 0.4~0.7, snow > 0.7
|
|
170
170
|
if (heightRatio < 0.4) return 1; // Grass (green) — largest area
|
|
171
171
|
if (heightRatio < 0.7) return 2; // Rock (gray)
|
|
172
172
|
return 3; // Snow cap (white)
|
|
173
173
|
}
|
|
174
|
-
//
|
|
174
|
+
// Corresponding material colors must have sufficient saturation and clear contrast:
|
|
175
175
|
// mat==1: vec3(0.25, 0.55, 0.15) Grass green (saturated green, must not be grayish!)
|
|
176
176
|
// mat==2: vec3(0.5, 0.45, 0.4) Rock gray-brown
|
|
177
177
|
// mat==3: vec3(0.92, 0.93, 0.96) Snow white
|
|
178
|
-
//
|
|
179
|
-
//
|
|
178
|
+
// Lighting must not be too bright or it washes out colors! Sun intensity ≤ 2.0, sky light ≤ 1.0
|
|
179
|
+
// Gamma correction pow(col, vec3(0.4545)) brightens dark colors and reduces saturation;
|
|
180
180
|
// if colors look grayish-white, make grass green more saturated: vec3(0.2, 0.5, 0.1)
|
|
181
181
|
|
|
182
|
-
//
|
|
182
|
+
// Rotating objects: to rotate a voxel object, apply inverse rotation to the sample point in getVoxel!
|
|
183
183
|
// Do not rotate the camera to simulate object rotation (that only changes the viewpoint)
|
|
184
184
|
bool getVoxelRotating(ivec3 c) {
|
|
185
185
|
vec3 p = vec3(c) + vec3(0.5);
|
|
@@ -240,7 +240,7 @@ ao = pow(ao, 1.0 / 3.0); // Gamma correction to control AO intensity
|
|
|
240
240
|
|
|
241
241
|
### Step 8: DDA Shadow Ray
|
|
242
242
|
```glsl
|
|
243
|
-
//
|
|
243
|
+
// Shadow steps must be capped at 16; total main ray + shadow ray steps should not exceed 80
|
|
244
244
|
#define MAX_SHADOW_STEPS 16
|
|
245
245
|
|
|
246
246
|
float castShadow(vec3 ro, vec3 rd) {
|
|
@@ -268,7 +268,7 @@ float diffuse = max(dot(normal, sundir), 0.0) * shadow;
|
|
|
268
268
|
// === Voxel Rendering - Complete ShaderToy Template ===
|
|
269
269
|
// Includes: DDA traversal, face shading, neighbor AO, hard shadows
|
|
270
270
|
|
|
271
|
-
//
|
|
271
|
+
// Performance critical: SwiftShader software renderer (headless browser evaluation environment) cannot handle too many loop iterations
|
|
272
272
|
// Default 64+16=80 steps, suitable for most scenes. Simple scenes (single cube) can increase to 96+24
|
|
273
273
|
// Multi-building/character/Minecraft scenes must keep 64+16 or lower!
|
|
274
274
|
#define MAX_RAY_STEPS 64
|
|
@@ -289,7 +289,7 @@ vec2 rotate2d(vec2 v, float a) {
|
|
|
289
289
|
}
|
|
290
290
|
|
|
291
291
|
// ---- Voxel Scene Definition ----
|
|
292
|
-
//
|
|
292
|
+
// Default solid cube. Use sdBox for "voxel cube"; add SDF boolean ops for carved/sculpted shapes
|
|
293
293
|
int getVoxel(vec3 c) {
|
|
294
294
|
vec3 p = c + 0.5;
|
|
295
295
|
float d = sdBox(p, vec3(6.0)); // Solid 12x12x12 block
|
|
@@ -366,14 +366,14 @@ HitInfo castRay(vec3 ro, vec3 rd, int maxSteps) {
|
|
|
366
366
|
}
|
|
367
367
|
|
|
368
368
|
// ---- Shadow Ray ----
|
|
369
|
-
//
|
|
369
|
+
// Shadow steps at 16 (combined with main ray 64 = 80, within SwiftShader safe range)
|
|
370
370
|
float castShadow(vec3 ro, vec3 rd) {
|
|
371
371
|
vec3 pos = floor(ro);
|
|
372
372
|
vec3 ri = 1.0 / rd;
|
|
373
373
|
vec3 rs = sign(rd);
|
|
374
374
|
vec3 dis = (pos - ro + 0.5 + rs * 0.5) * ri;
|
|
375
375
|
for (int i = 0; i < MAX_SHADOW_STEPS; i++) {
|
|
376
|
-
//
|
|
376
|
+
// getVoxel returns int; comparison must use int constant (0), not float (0.0)
|
|
377
377
|
if (getVoxel(pos) > 0) return 0.0;
|
|
378
378
|
vec3 mm = step(dis.xyz, dis.yzx) * step(dis.xyz, dis.zxy);
|
|
379
379
|
dis += mm * rs * ri;
|
|
@@ -383,7 +383,7 @@ float castShadow(vec3 ro, vec3 rd) {
|
|
|
383
383
|
}
|
|
384
384
|
|
|
385
385
|
// ---- Material Colors ----
|
|
386
|
-
//
|
|
386
|
+
// Texture coloring key: "low saturation" does not mean "near white/gray"!
|
|
387
387
|
// Low saturation = colorful but not vivid, must retain clear hue differences (e.g., brick red 0.55,0.35,0.3 not gray-white 0.8,0.8,0.8)
|
|
388
388
|
// Brick/stone textures: use UV periodic patterns (mortar lines = dark lines), never use solid colors!
|
|
389
389
|
vec3 getMaterialColor(int mat, vec2 uv) {
|
|
@@ -396,7 +396,7 @@ vec3 getMaterialColor(int mat, vec2 uv) {
|
|
|
396
396
|
}
|
|
397
397
|
|
|
398
398
|
// ---- Brick/Stone Texture Coloring (use this to replace getMaterialColor when user requests "brick texture") ----
|
|
399
|
-
//
|
|
399
|
+
// brick texture = UV periodic pattern (staggered rows + mortar dark lines), not solid color!
|
|
400
400
|
vec3 getBrickColor(vec2 uv, vec3 baseColor, vec3 mortarColor) {
|
|
401
401
|
vec2 brickUV = uv * vec2(4.0, 8.0);
|
|
402
402
|
float row = floor(brickUV.y);
|
|
@@ -447,14 +447,14 @@ void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
|
|
447
447
|
float sky = 0.5 + 0.5 * hit.normal.y;
|
|
448
448
|
|
|
449
449
|
vec3 lighting = vec3(0.0);
|
|
450
|
-
//
|
|
450
|
+
// Mountain/terrain scenes: sun light ≤ 2.0, sky light ≤ 1.0; too bright washes out material color differences
|
|
451
451
|
lighting += 2.0 * diff * vec3(1.0, 0.95, 0.8) * shadow;
|
|
452
452
|
lighting += 1.0 * sky * skyColor;
|
|
453
453
|
lighting *= ao;
|
|
454
454
|
|
|
455
455
|
col = matCol * lighting;
|
|
456
456
|
|
|
457
|
-
//
|
|
457
|
+
// Fog: coefficient should not be too large, otherwise nearby objects get swallowed into pure sky color
|
|
458
458
|
// 0.0002 suits GRID_SIZE=16 scenes; use smaller coefficients for larger scenes
|
|
459
459
|
float fog = 1.0 - exp(-0.0002 * hit.t * hit.t);
|
|
460
460
|
col = mix(col, skyColor, clamp(fog, 0.0, 0.7)); // Clamp prevents objects from disappearing entirely
|
|
@@ -564,7 +564,7 @@ Water surface ripple reflections, underwater refraction, sand and seaweed for a
|
|
|
564
564
|
float waterY = 0.0;
|
|
565
565
|
|
|
566
566
|
// Underwater voxel scene definition (sand + seaweed)
|
|
567
|
-
//
|
|
567
|
+
// All coordinate operations must use correct vector dimensions!
|
|
568
568
|
// c.xz returns vec2, only has .x/.y components, cannot use .z!
|
|
569
569
|
int getVoxel(vec3 c) {
|
|
570
570
|
float sandHeight = -3.0 + 0.5 * sin(c.x * 0.3) * cos(c.z * 0.4);
|
|
@@ -572,7 +572,7 @@ int getVoxel(vec3 c) {
|
|
|
572
572
|
if (c.y < sandHeight + 1.0) return 2; // Sand surface
|
|
573
573
|
// Seaweed: only grows underwater, above sand
|
|
574
574
|
float grassHash = fract(sin(dot(floor(c.xz), vec2(12.9898, 78.233))) * 43758.5453);
|
|
575
|
-
//
|
|
575
|
+
// floor(c.xz) is vec2; the second argument to dot() must also be vec2
|
|
576
576
|
if (grassHash > 0.85 && c.y >= sandHeight + 1.0 && c.y < sandHeight + 1.0 + 3.0 * grassHash) {
|
|
577
577
|
return 3; // Seaweed
|
|
578
578
|
}
|
|
@@ -586,7 +586,7 @@ bool hitWater = tWater > 0.0 && (tWater < hit.t || !hit.hit);
|
|
|
586
586
|
if (hitWater) {
|
|
587
587
|
vec3 waterPos = ro + rd * tWater;
|
|
588
588
|
vec3 waterNormal = vec3(0.0, 1.0, 0.0);
|
|
589
|
-
//
|
|
589
|
+
// waterPos.xz is vec2; access with .x/.y (not .x/.z)
|
|
590
590
|
vec2 waveXZ = waterPos.xz; // vec2: waveXZ.x = worldX, waveXZ.y = worldZ
|
|
591
591
|
waterNormal.x += 0.05 * sin(waveXZ.x * 3.0 + iTime);
|
|
592
592
|
waterNormal.z += 0.05 * cos(waveXZ.y * 2.0 + iTime * 0.7);
|
|
@@ -619,7 +619,7 @@ if (hitWater) {
|
|
|
619
619
|
### Variant 7: Rotating Voxel Objects
|
|
620
620
|
Rotate voxel objects as a whole. Core: apply inverse rotation to sample points in getVoxel.
|
|
621
621
|
```glsl
|
|
622
|
-
//
|
|
622
|
+
// Correct way to rotate objects: apply inverse rotation to sample coordinates in getVoxel
|
|
623
623
|
// Wrong approach: only rotate the camera (that just changes the viewpoint, not the object)
|
|
624
624
|
int getVoxel(vec3 c) {
|
|
625
625
|
vec3 p = c + 0.5;
|
|
@@ -638,7 +638,7 @@ int getVoxel(vec3 c) {
|
|
|
638
638
|
### Variant 8: Indoor/Cave/Enclosed Scenes (Point Lights + High Ambient Lighting)
|
|
639
639
|
Indoor, cave, underground, sci-fi base, and other enclosed or semi-enclosed scenes require point lights and high ambient lighting.
|
|
640
640
|
```glsl
|
|
641
|
-
//
|
|
641
|
+
// Key points for enclosed/semi-enclosed scenes (caves, interiors, sci-fi bases, mazes, etc.):
|
|
642
642
|
// 1. Camera must be placed inside the cavity (a position where getVoxel returns 0)
|
|
643
643
|
// 2. Must use point lights, not just directional light (directional light blocked by walls/ceiling = total darkness!)
|
|
644
644
|
// 3. Ambient light must be high enough (at least 0.2-0.3) to prevent scene from being too dark to see details
|
|
@@ -647,13 +647,13 @@ Indoor, cave, underground, sci-fi base, and other enclosed or semi-enclosed scen
|
|
|
647
647
|
// 6. Emissive elements (holographic screens, indicator lights, magic circles) use emissive materials: add emissive color directly to lighting
|
|
648
648
|
|
|
649
649
|
// Cave scene: cavity = area where getVoxel returns 0
|
|
650
|
-
//
|
|
650
|
+
// Cave/terrain noise functions must respect vector dimensions!
|
|
651
651
|
// p.xz is vec2; if noise/fbm function takes vec3, construct a full vec3:
|
|
652
652
|
// Correct: fbm(vec3(p.xz, p.y * 0.5)) or use vec2 version of noise
|
|
653
653
|
// Wrong: fbm(p.xz + vec3(...)) ← vec2 + vec3 compile failure!
|
|
654
654
|
int getVoxel(vec3 c) {
|
|
655
655
|
float cave = sdSphere(c + 0.5, 12.0);
|
|
656
|
-
//
|
|
656
|
+
// For noise-carved detail, use c's components directly (all float)
|
|
657
657
|
cave += 2.0 * sin(c.x * 0.3) * sin(c.y * 0.4) * sin(c.z * 0.35);
|
|
658
658
|
if (cave > 0.0) return 1; // Rock wall
|
|
659
659
|
return 0; // Cavity (camera goes here)
|
|
@@ -670,7 +670,7 @@ float diff = max(dot(hit.normal, lightDir), 0.0);
|
|
|
670
670
|
float shadow = castShadow(hit.pos + hit.normal * 0.01, lightDir);
|
|
671
671
|
|
|
672
672
|
vec3 lighting = vec3(0.0);
|
|
673
|
-
//
|
|
673
|
+
// High ambient light to prevent total darkness (required for enclosed scenes! at least 0.2)
|
|
674
674
|
lighting += vec3(0.25, 0.22, 0.2); // Warm ambient light
|
|
675
675
|
lighting += 3.0 * diff * attenuation * vec3(1.0, 0.8, 0.5) * shadow; // Point light
|
|
676
676
|
|
|
@@ -683,7 +683,7 @@ lighting += calcPointLight(hit.pos, hit.normal, torch1, vec3(1.0, 0.6, 0.2)) * f
|
|
|
683
683
|
lighting += calcPointLight(hit.pos, hit.normal, torch2, vec3(0.2, 1.0, 0.5)) * flicker2;
|
|
684
684
|
|
|
685
685
|
// Emissive materials (holographic displays, fluorescent moss, indicator lights, magic circles, etc.)
|
|
686
|
-
//
|
|
686
|
+
// Emissive colors are added directly to lighting, unaffected by shadows
|
|
687
687
|
if (hit.mat == 2) {
|
|
688
688
|
lighting += vec3(0.1, 0.4, 0.15); // Fluorescent moss (faint green)
|
|
689
689
|
}
|
|
@@ -698,12 +698,12 @@ col = matCol * lighting;
|
|
|
698
698
|
### Variant 9: Voxel Character Animation
|
|
699
699
|
Simple voxel character animation using time-driven offsets and rotations.
|
|
700
700
|
```glsl
|
|
701
|
-
//
|
|
701
|
+
// Voxel character animation core approach:
|
|
702
702
|
// 1. Split the character into multiple body parts (head, torso, left arm, right arm, left leg, right leg)
|
|
703
703
|
// 2. Each part is an sdBox with independent offset/rotation parameters
|
|
704
704
|
// 3. iTime drives limb swinging (sin/cos periodic motion)
|
|
705
705
|
// 4. Combine all parts using SDF min()
|
|
706
|
-
//
|
|
706
|
+
// SwiftShader performance critical: character function is called at every DDA step!
|
|
707
707
|
// Must add AABB bounding box check in getVoxel: first check if c is near the character,
|
|
708
708
|
// skip sdBox calculations for that character if not nearby. Otherwise frame timeout → black screen
|
|
709
709
|
// Reduce MAX_RAY_STEPS to 64, MAX_SHADOW_STEPS to 16
|
|
@@ -737,12 +737,12 @@ int getCharacter(vec3 p, vec3 charPos, float animPhase) {
|
|
|
737
737
|
}
|
|
738
738
|
|
|
739
739
|
// Combine scene + characters in getVoxel
|
|
740
|
-
//
|
|
740
|
+
// Must add AABB bounding box early exit! Character sdBox calculations are expensive
|
|
741
741
|
int getVoxel(vec3 c) {
|
|
742
742
|
// Scene (floor, walls, etc.)
|
|
743
743
|
int scene = getSceneVoxel(c);
|
|
744
744
|
if (scene > 0) return scene;
|
|
745
|
-
//
|
|
745
|
+
// AABB check: only call getCharacter near the character
|
|
746
746
|
// Character 1: warrior (at position (5,0,0)), bounding box ±5 cells
|
|
747
747
|
if (abs(c.x - 5.0) < 5.0 && c.y >= 0.0 && c.y < 10.0 && abs(c.z) < 5.0) {
|
|
748
748
|
int char1 = getCharacter(c, vec3(5, 0, 0), 0.0);
|
|
@@ -760,7 +760,7 @@ int getVoxel(vec3 c) {
|
|
|
760
760
|
### Variant 10: Waterfall / Flowing Water Particle Effects
|
|
761
761
|
Dynamic waterfall, splash particles, water mist effects. Core: time-offset noise simulates water flow, hashed particles simulate splashes, exponential decay simulates mist.
|
|
762
762
|
```glsl
|
|
763
|
-
//
|
|
763
|
+
// Key points for waterfall/flowing water/particle effects:
|
|
764
764
|
// 1. Waterfall stream: noise + iTime vertical offset simulates water column flowing down
|
|
765
765
|
// 2. Splash particles: hash-distributed voxels at the bottom, positions change with iTime to simulate splashing
|
|
766
766
|
// 3. Water mist: semi-transparent accumulation (reduced alpha) or density field at the bottom simulates mist diffusion
|
|
@@ -782,14 +782,14 @@ int getVoxel(vec3 c) {
|
|
|
782
782
|
// Bottom pool floor
|
|
783
783
|
if (c.y < -2.0 && abs(c.x) < 8.0 && c.z > -6.0 && c.z < 3.0) return 2; // Pool bottom
|
|
784
784
|
|
|
785
|
-
//
|
|
785
|
+
// Waterfall stream: narrow band x ∈ [-2, 2], falling from y=13 to y=0
|
|
786
786
|
// Use iTime offset on y-coordinate noise to simulate downward water flow
|
|
787
787
|
if (abs(c.x) < 2.0 && c.y >= 0.0 && c.y < 13.0 && c.z > -1.0 && c.z < 1.0) {
|
|
788
788
|
float flowNoise = hash21(vec2(floor(c.x), floor(c.y - iTime * 8.0)));
|
|
789
789
|
if (flowNoise > 0.25) return 3; // Water (gaps simulate translucent water curtain)
|
|
790
790
|
}
|
|
791
791
|
|
|
792
|
-
//
|
|
792
|
+
// Splash particles: bottom y ∈ [-1, 3], x ∈ [-4, 4]
|
|
793
793
|
// Use hash + iTime to generate randomly bouncing voxel particles
|
|
794
794
|
if (c.y >= -1.0 && c.y < 3.0 && abs(c.x) < 4.0 && c.z > -3.0 && c.z < 2.0) {
|
|
795
795
|
float t = iTime * 3.0;
|
|
@@ -798,7 +798,7 @@ int getVoxel(vec3 c) {
|
|
|
798
798
|
if (abs(c.y - yOffset) < 0.6 && particleHash > 0.7) return 4; // Splash particle
|
|
799
799
|
}
|
|
800
800
|
|
|
801
|
-
//
|
|
801
|
+
// Water mist: bottom y ∈ [-1, 2], wider range than splashes
|
|
802
802
|
// Density decreases with height and distance from waterfall center
|
|
803
803
|
if (c.y >= -1.0 && c.y < 2.0 && abs(c.x) < 6.0 && c.z > -5.0 && c.z < 3.0) {
|
|
804
804
|
float distFromCenter = length(vec2(c.x, c.z));
|
|
@@ -823,7 +823,7 @@ vec3 getMaterialColor(int mat, vec2 uv) {
|
|
|
823
823
|
return vec3(0.5);
|
|
824
824
|
}
|
|
825
825
|
|
|
826
|
-
//
|
|
826
|
+
// Water mist material needs special lighting: high emissive + translucent feel
|
|
827
827
|
// During shading:
|
|
828
828
|
if (hit.mat == 5) {
|
|
829
829
|
lighting += vec3(0.4, 0.5, 0.6); // Water mist emissive (unaffected by shadows)
|
|
@@ -835,19 +835,19 @@ if (hit.mat == 5) {
|
|
|
835
835
|
|
|
836
836
|
### Variant 11: Multi-Building / Town / Minecraft-Style Scenes (Multi-Structure Town Composition)
|
|
837
837
|
Towns, villages, Minecraft-style worlds, and other scenes requiring multiple discrete structures (houses, trees, lampposts, etc.) placed on the ground.
|
|
838
|
-
**
|
|
838
|
+
**"Minecraft-like voxel scene" = multi-building scene; must follow the performance constraints of this template!**
|
|
839
839
|
```glsl
|
|
840
|
-
//
|
|
840
|
+
// Key points for multi-building scenes:
|
|
841
841
|
// 1. Define the ground first (height map or flat plane), ensure ground getVoxel returns correct material
|
|
842
842
|
// 2. Each building uses an independent helper function, receiving local coordinates, returning material ID
|
|
843
843
|
// 3. In getVoxel, check each building sequentially (using offset coordinates), return on first hit
|
|
844
844
|
// 4. Camera must be outside the scene facing the center, far enough to see the full view
|
|
845
|
-
// 5.
|
|
846
|
-
// 6.
|
|
847
|
-
// 7.
|
|
845
|
+
// 5. Building coordinate ranges must be within DDA traversal range (MAX_RAY_STEPS * cell ≈ reachable distance)
|
|
846
|
+
// 6. Scene range should not be too large! Concentrate all buildings within -20~20 range, camera 30-50 cells away
|
|
847
|
+
// 7. SwiftShader performance critical: getVoxel must have AABB bounding box early exit!
|
|
848
848
|
// Above ground (c.y > 0), check AABB range first; return 0 immediately if outside building area
|
|
849
849
|
// Otherwise every DDA step checks all buildings → frame timeout → black screen / only sky renders
|
|
850
|
-
// 8.
|
|
850
|
+
// 8. MAX_RAY_STEPS reduced to 64, MAX_SHADOW_STEPS to 16 (complex getVoxel requires lower step counts)
|
|
851
851
|
|
|
852
852
|
// Single house: width w, depth d, height h, with triangular roof
|
|
853
853
|
int makeHouse(vec3 p, float w, float d, float h, int wallMat, int roofMat) {
|
|
@@ -902,13 +902,13 @@ int getVoxel(vec3 c) {
|
|
|
902
902
|
// 2. Road (along z direction, x range -2~2)
|
|
903
903
|
if (c.y < 1.0 && abs(c.x) < 2.0) return 2; // Road surface
|
|
904
904
|
|
|
905
|
-
//
|
|
905
|
+
// AABB bounding box early exit (required for SwiftShader!)
|
|
906
906
|
// All buildings are within x:-15~15, y:0~12, z:-5~15
|
|
907
907
|
// Return 0 immediately outside this range, avoiding per-building checks
|
|
908
908
|
if (c.x < -15.0 || c.x > 15.0 || c.y > 12.0 || c.z < -5.0 || c.z > 15.0) return 0;
|
|
909
909
|
|
|
910
910
|
// 3. Place buildings (each with offset coordinates)
|
|
911
|
-
//
|
|
911
|
+
// House width/height must be ≥ 5 cells, otherwise they look like dots from far away! Use bright material colors
|
|
912
912
|
int m;
|
|
913
913
|
|
|
914
914
|
// House A: position (5, 0, 3), width 6, depth 5, height 5
|
|
@@ -930,7 +930,7 @@ int getVoxel(vec3 c) {
|
|
|
930
930
|
return 0;
|
|
931
931
|
}
|
|
932
932
|
|
|
933
|
-
//
|
|
933
|
+
// Camera setup: must be far enough to overlook the entire town
|
|
934
934
|
// Recommended: ro = vec3(0, 15, -35), looking at scene center vec3(0, 3, 5)
|
|
935
935
|
vec3 ro = vec3(0.0, 15.0, -35.0);
|
|
936
936
|
vec3 lookAt = vec3(0.0, 3.0, 5.0);
|
|
@@ -939,12 +939,12 @@ vec3 right = normalize(cross(forward, vec3(0, 1, 0)));
|
|
|
939
939
|
vec3 up = cross(right, forward);
|
|
940
940
|
vec3 rd = normalize(forward * 0.8 + right * screenPos.x + up * screenPos.y);
|
|
941
941
|
|
|
942
|
-
//
|
|
942
|
+
// Sunset/side-lit scene key: when light comes from the side or at low angle, building fronts may be completely backlit turning into black silhouettes!
|
|
943
943
|
// Must satisfy all: (1) ambient light ≥ 0.3 (prevent backlit faces from going black); (2) house walls use bright materials (e.g., light yellow 0.85,0.75,0.55)
|
|
944
944
|
// (3) house dimensions must not be too small (width/height ≥ 5 cells), otherwise they look like dots from far away
|
|
945
945
|
vec3 sunDir = normalize(vec3(-0.8, 0.3, 0.5)); // Sunset low angle
|
|
946
946
|
vec3 sunColor = vec3(1.0, 0.6, 0.3); // Warm orange
|
|
947
|
-
vec3 ambientColor = vec3(0.35, 0.3, 0.4); //
|
|
947
|
+
vec3 ambientColor = vec3(0.35, 0.3, 0.4); // High ambient light (≥0.3) to prevent silhouettes
|
|
948
948
|
// lighting = ambientColor + diff * sunColor * shadow;
|
|
949
949
|
```
|
|
950
950
|
|
|
@@ -957,7 +957,7 @@ vec3 ambientColor = vec3(0.35, 0.3, 0.4); // IMPORTANT: High ambient light (≥
|
|
|
957
957
|
- Material queries, AO, normals, etc. are only computed after hit
|
|
958
958
|
- Replace procedural voxel queries with `texelFetch` texture sampling
|
|
959
959
|
- Multi-frame accumulation + reprojection for low-noise results
|
|
960
|
-
- **
|
|
960
|
+
- **MAX_RAY_STEPS defaults to 64, MAX_SHADOW_STEPS defaults to 16 (total 80)**. Only simple scenes (single cube/sphere) can increase to 96+24. Multi-building/Minecraft/character scenes with complex getVoxel must keep 64+16 or lower, otherwise SwiftShader frame timeout → only sky background renders
|
|
961
961
|
|
|
962
962
|
**Composition Tips:**
|
|
963
963
|
- **Procedural noise terrain**: use FBM/Perlin noise height maps inside `getVoxel()`
|
|
@@ -22,7 +22,7 @@ Output: `production/qa/smoke-[date].md`
|
|
|
22
22
|
|
|
23
23
|
1. Verify `tests/` exists (else stop → `/test-setup`)
|
|
24
24
|
2. Check CI workflow for test refs
|
|
25
|
-
3.
|
|
25
|
+
3. Detect the engine from `ProjectSettings/ProjectVersion.txt` (Unity) or the `.uproject` (Unreal)
|
|
26
26
|
4. Load smoke test list from `production/qa/smoke-tests.md` or `tests/smoke/`
|
|
27
27
|
5. Load QA plan from `production/qa/qa-plan-*.md` (most recent)
|
|
28
28
|
|
|
@@ -44,6 +44,5 @@ Glob for `production/qa/qa-plan-sprint-[N].md`. Found → note in output. Not fo
|
|
|
44
44
|
|
|
45
45
|
- `/qa-plan sprint` — required before implementation
|
|
46
46
|
- `/story-readiness [story-file]` — validate before starting
|
|
47
|
-
- `/
|
|
48
|
-
- `/sprint-status` — check progress mid-sprint
|
|
47
|
+
- `/sprint-report` — check progress mid-sprint
|
|
49
48
|
- `/scope-check [epic]` — verify no scope creep
|
package/skills/start/SKILL.md
CHANGED
|
@@ -35,13 +35,13 @@ AskUserQuestion multi-tab:
|
|
|
35
35
|
|
|
36
36
|
| Tipo | Rol | División | Skills clave |
|
|
37
37
|
|------|-----|----------|-------------|
|
|
38
|
-
| Juego | Dev | Game Dev | `/brainstorm`, `/
|
|
39
|
-
| Web app | Dev | Software Eng | `/scaffold
|
|
40
|
-
| API | Dev | Software Eng | `/scaffold-go`, `/scaffold-
|
|
41
|
-
| Móvil | Dev | Software Eng | `/scaffold-
|
|
38
|
+
| Juego | Dev | Game Dev | `/brainstorm`, `/scaffold-unity` (Unity) o `/ue-project-context` (Unreal), `/design-system` |
|
|
39
|
+
| Web app | Dev | Software Eng | `/nextjs-scaffold`, `/architecture-decision` |
|
|
40
|
+
| API | Dev | Software Eng | `/scaffold-go`, `/scaffold-fastify-ts` |
|
|
41
|
+
| Móvil | Dev | Software Eng | `/scaffold-react-native` |
|
|
42
42
|
| Juego | Designer | Game Dev | `/brainstorm`, `/quick-design`, `/doc-gdd` |
|
|
43
43
|
| Web | Designer | Product | `/ux-design`, `/design-handoff` |
|
|
44
|
-
| Any | PM | PMO | `/sprint-
|
|
44
|
+
| Any | PM | PMO | `/sprint-plan`, `/clickup`, `/jira-tickets` |
|
|
45
45
|
|
|
46
46
|
## Paso 5: Set session state
|
|
47
47
|
|
|
@@ -53,8 +53,8 @@ AskUserQuestion: primary recommendation (Recommended), secondary option, "Ver to
|
|
|
53
53
|
|
|
54
54
|
## Routing Cheatsheet
|
|
55
55
|
|
|
56
|
-
- Game from scratch: `/start` → `/brainstorm` → `/
|
|
57
|
-
- Web app: `/start` → `/scaffold
|
|
56
|
+
- Game from scratch: `/start` → `/brainstorm` → `/scaffold-unity` (Unity) o `/ue-project-context` (Unreal) → `/art-bible` → `/design-system`
|
|
57
|
+
- Web app: `/start` → `/nextjs-scaffold` → `/architecture-decision` → `/api-design`
|
|
58
58
|
- Sprint en curso: `/start` → `/clickup status` → `/standup-report`
|
|
59
59
|
|
|
60
60
|
## Reglas
|
|
@@ -59,7 +59,7 @@ Ask approval → edit story: `Status: Complete` + `## Completion Notes` (date, c
|
|
|
59
59
|
|
|
60
60
|
## Phase 8: Surface Next Story
|
|
61
61
|
|
|
62
|
-
Read sprint plan → find READY/NOT STARTED stories (not blocked, Must/Should Have). Present up to 3 options. If all Must Have complete → sprint close-out sequence: `/smoke-check sprint` → `/
|
|
62
|
+
Read sprint plan → find READY/NOT STARTED stories (not blocked, Must/Should Have). Present up to 3 options. If all Must Have complete → sprint close-out sequence: `/smoke-check sprint` → `/gate-check`.
|
|
63
63
|
|
|
64
64
|
## Protocol
|
|
65
65
|
|
|
@@ -21,8 +21,8 @@ Output: `tests/helpers/` with engine-specific helpers. Run after `/test-setup`,
|
|
|
21
21
|
|
|
22
22
|
## Detection
|
|
23
23
|
|
|
24
|
-
-
|
|
25
|
-
- No engine →
|
|
24
|
+
- Detect the engine from the project: `ProjectSettings/ProjectVersion.txt` (Unity) or a `*.uproject` file (Unreal); language and test framework from the project files
|
|
25
|
+
- No engine detected → ask the user which engine the project uses
|
|
26
26
|
- Scan `tests/**/*_test.*` (up to 5 files): extract setup, assertion, factory, mock patterns
|
|
27
27
|
- Read `design/gdd/systems-index.md`, in-scope GDDs, `docs/architecture/tr-registry.yaml`
|
|
28
28
|
|
|
@@ -48,3 +48,8 @@ Present summary of files to create → ask approval → write. **Never overwrite
|
|
|
48
48
|
- Helpers reflect GDD bounds and constants, not invented values
|
|
49
49
|
- Generated code is a starting point — adapt to actual class structure
|
|
50
50
|
- Ask before writing to `tests/`
|
|
51
|
+
|
|
52
|
+
## Next Steps
|
|
53
|
+
|
|
54
|
+
- `/regression-suite` — map the new helpers onto critical paths that still lack regression tests
|
|
55
|
+
- `/smoke-check` — run the suite before QA hand-off
|
|
@@ -12,7 +12,7 @@ Scaffold automated testing infrastructure. Run once during Technical Setup phase
|
|
|
12
12
|
|
|
13
13
|
## Phase 1: Detect Engine & State
|
|
14
14
|
|
|
15
|
-
1.
|
|
15
|
+
1. Detect the engine from the project: `ProjectSettings/ProjectVersion.txt` (Unity) or a `*.uproject` file (Unreal). None found → ask the user which engine the project uses
|
|
16
16
|
2. Check existing: `tests/`, `tests/unit/`, `tests/integration/`, `.github/workflows/`, engine-specific dirs
|
|
17
17
|
3. Report findings. If everything exists and no `force` arg → "Already in place. Re-run with `force` to regenerate"
|
|
18
18
|
4. `force` skips early-exit but never overwrites existing files
|
|
@@ -498,7 +498,6 @@ Validate before considering the work done:
|
|
|
498
498
|
- [ ] Ownership and attachment are explicit, with no dangling component references
|
|
499
499
|
- [ ] Initialization happens in the correct lifecycle stage, not all in `BeginPlay`
|
|
500
500
|
- [ ] Conventions in `docs/unreal/project-context.md` were read and followed
|
|
501
|
-
- [ ] The Common Mistakes section of this skill was reviewed against the change
|
|
502
501
|
|
|
503
502
|
**PASS** — every item holds. **CONCERNS** — the work stands but at least one item is unresolved and worth flagging to the user. **FAIL** — an item is violated in a way that breaks correctness, replication or the frame budget; fix it before handing the work over.
|
|
504
503
|
|
|
@@ -515,7 +515,6 @@ Validate before considering the work done:
|
|
|
515
515
|
- [ ] Perception configuration matches the intended detection ranges and teams
|
|
516
516
|
- [ ] NavMesh generation settings cover the agent sizes actually used
|
|
517
517
|
- [ ] Conventions in `docs/unreal/project-context.md` were read and followed
|
|
518
|
-
- [ ] The Common Mistakes section of this skill was reviewed against the change
|
|
519
518
|
|
|
520
519
|
**PASS** — every item holds. **CONCERNS** — the work stands but at least one item is unresolved and worth flagging to the user. **FAIL** — an item is violated in a way that breaks correctness, replication or the frame budget; fix it before handing the work over.
|
|
521
520
|
|
|
@@ -510,7 +510,6 @@ Validate before considering the work done:
|
|
|
510
510
|
- [ ] Montage sections and notifies are named consistently and documented
|
|
511
511
|
- [ ] No gameplay decisions are made inside the animation graph
|
|
512
512
|
- [ ] Conventions in `docs/unreal/project-context.md` were read and followed
|
|
513
|
-
- [ ] The Common Mistakes section of this skill was reviewed against the change
|
|
514
513
|
|
|
515
514
|
**PASS** — every item holds. **CONCERNS** — the work stands but at least one item is unresolved and worth flagging to the user. **FAIL** — an item is violated in a way that breaks correctness, replication or the frame budget; fix it before handing the work over.
|
|
516
515
|
|
|
@@ -422,7 +422,6 @@ Validate before considering the work done:
|
|
|
422
422
|
- [ ] Every async completion path handles the owner being destroyed mid-flight
|
|
423
423
|
- [ ] Shared state is protected, or ownership is transferred instead of shared
|
|
424
424
|
- [ ] Conventions in `docs/unreal/project-context.md` were read and followed
|
|
425
|
-
- [ ] The Common Mistakes section of this skill was reviewed against the change
|
|
426
425
|
|
|
427
426
|
**PASS** — every item holds. **CONCERNS** — the work stands but at least one item is unresolved and worth flagging to the user. **FAIL** — an item is violated in a way that breaks correctness, replication or the frame budget; fix it before handing the work over.
|
|
428
427
|
|
|
@@ -515,7 +515,6 @@ Validate before considering the work done:
|
|
|
515
515
|
- [ ] Attenuation settings are shared through assets rather than tuned per instance
|
|
516
516
|
- [ ] Sounds are not started every frame or on every overlap event
|
|
517
517
|
- [ ] Conventions in `docs/unreal/project-context.md` were read and followed
|
|
518
|
-
- [ ] The Common Mistakes section of this skill was reviewed against the change
|
|
519
518
|
|
|
520
519
|
**PASS** — every item holds. **CONCERNS** — the work stands but at least one item is unresolved and worth flagging to the user. **FAIL** — an item is violated in a way that breaks correctness, replication or the frame budget; fix it before handing the work over.
|
|
521
520
|
|
|
@@ -122,7 +122,6 @@ Validate before considering the work done:
|
|
|
122
122
|
- [ ] Reusable logic lives in a Blueprint Class, not the Level Blueprint
|
|
123
123
|
- [ ] Construction Script does editor-time setup only, with no gameplay side effects
|
|
124
124
|
- [ ] Conventions in `docs/unreal/project-context.md` were read and followed
|
|
125
|
-
- [ ] The Common Mistakes section of this skill was reviewed against the change
|
|
126
125
|
|
|
127
126
|
**PASS** — every item holds. **CONCERNS** — the work stands but at least one item is unresolved and worth flagging to the user. **FAIL** — an item is violated in a way that breaks correctness, load times or the frame budget; fix it before handing the work over.
|
|
128
127
|
|
|
@@ -464,7 +464,6 @@ Validate before considering the work done:
|
|
|
464
464
|
- [ ] Network prediction data was extended correctly for any new movement state
|
|
465
465
|
- [ ] Root motion sources are used for authored displacement
|
|
466
466
|
- [ ] Conventions in `docs/unreal/project-context.md` were read and followed
|
|
467
|
-
- [ ] The Common Mistakes section of this skill was reviewed against the change
|
|
468
467
|
|
|
469
468
|
**PASS** — every item holds. **CONCERNS** — the work stands but at least one item is unresolved and worth flagging to the user. **FAIL** — an item is violated in a way that breaks correctness, replication or the frame budget; fix it before handing the work over.
|
|
470
469
|
|
|
@@ -522,7 +522,6 @@ Validate before considering the work done:
|
|
|
522
522
|
- [ ] Containers are `TArray`/`TMap`/`TSet`, strings use the right `FName`/`FText`/`FString` role
|
|
523
523
|
- [ ] No `new`/`delete` on UObjects — `NewObject<>`/`CreateDefaultSubobject<>` only
|
|
524
524
|
- [ ] Conventions in `docs/unreal/project-context.md` were read and followed
|
|
525
|
-
- [ ] The Common Mistakes section of this skill was reviewed against the change
|
|
526
525
|
|
|
527
526
|
**PASS** — every item holds. **CONCERNS** — the work stands but at least one item is unresolved and worth flagging to the user. **FAIL** — an item is violated in a way that breaks correctness, replication or the frame budget; fix it before handing the work over.
|
|
528
527
|
|
|
@@ -516,7 +516,6 @@ Validate before considering the work done:
|
|
|
516
516
|
- [ ] Primary Asset types are registered so scanning and cooking behave correctly
|
|
517
517
|
- [ ] No synchronous load of large assets on the game thread during gameplay
|
|
518
518
|
- [ ] Conventions in `docs/unreal/project-context.md` were read and followed
|
|
519
|
-
- [ ] The Common Mistakes section of this skill was reviewed against the change
|
|
520
519
|
|
|
521
520
|
**PASS** — every item holds. **CONCERNS** — the work stands but at least one item is unresolved and worth flagging to the user. **FAIL** — an item is violated in a way that breaks correctness, replication or the frame budget; fix it before handing the work over.
|
|
522
521
|
|
|
@@ -512,7 +512,6 @@ Validate before considering the work done:
|
|
|
512
512
|
- [ ] The tool fails safely on unexpected asset state instead of corrupting data
|
|
513
513
|
- [ ] Bulk operations are undoable or clearly warn before running
|
|
514
514
|
- [ ] Conventions in `docs/unreal/project-context.md` were read and followed
|
|
515
|
-
- [ ] The Common Mistakes section of this skill was reviewed against the change
|
|
516
515
|
|
|
517
516
|
**PASS** — every item holds. **CONCERNS** — the work stands but at least one item is unresolved and worth flagging to the user. **FAIL** — an item is violated in a way that breaks correctness, replication or the frame budget; fix it before handing the work over.
|
|
518
517
|
|
|
@@ -466,7 +466,6 @@ Validate before considering the work done:
|
|
|
466
466
|
- [ ] Actions register and unregister symmetrically on activate/deactivate
|
|
467
467
|
- [ ] The feature can be disabled without breaking a packaged build
|
|
468
468
|
- [ ] Conventions in `docs/unreal/project-context.md` were read and followed
|
|
469
|
-
- [ ] The Common Mistakes section of this skill was reviewed against the change
|
|
470
469
|
|
|
471
470
|
**PASS** — every item holds. **CONCERNS** — the work stands but at least one item is unresolved and worth flagging to the user. **FAIL** — an item is violated in a way that breaks correctness, replication or the frame budget; fix it before handing the work over.
|
|
472
471
|
|
|
@@ -506,7 +506,6 @@ Validate before considering the work done:
|
|
|
506
506
|
- [ ] State is identified by Gameplay Tags rather than booleans
|
|
507
507
|
- [ ] Ability activation policy and prediction were chosen deliberately
|
|
508
508
|
- [ ] Conventions in `docs/unreal/project-context.md` were read and followed
|
|
509
|
-
- [ ] The Common Mistakes section of this skill was reviewed against the change
|
|
510
509
|
|
|
511
510
|
**PASS** — every item holds. **CONCERNS** — the work stands but at least one item is unresolved and worth flagging to the user. **FAIL** — an item is violated in a way that breaks correctness, replication or the frame budget; fix it before handing the work over.
|
|
512
511
|
|
|
@@ -455,7 +455,6 @@ Validate before considering the work done:
|
|
|
455
455
|
- [ ] Nothing authoritative lives on the Pawn, which can be destroyed and respawned
|
|
456
456
|
- [ ] Server and client paths were both considered for every piece of state
|
|
457
457
|
- [ ] Conventions in `docs/unreal/project-context.md` were read and followed
|
|
458
|
-
- [ ] The Common Mistakes section of this skill was reviewed against the change
|
|
459
458
|
|
|
460
459
|
**PASS** — every item holds. **CONCERNS** — the work stands but at least one item is unresolved and worth flagging to the user. **FAIL** — an item is violated in a way that breaks correctness, replication or the frame budget; fix it before handing the work over.
|
|
461
460
|
|