@jarrodmedrano/claude-skills 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/.claude/skills/bevy/SKILL.md +406 -0
  2. package/.claude/skills/bevy/references/bevy_specific_tips.md +385 -0
  3. package/.claude/skills/bevy/references/common_pitfalls.md +217 -0
  4. package/.claude/skills/bevy/references/ecs_patterns.md +277 -0
  5. package/.claude/skills/bevy/references/project_structure.md +116 -0
  6. package/.claude/skills/bevy/references/ui_development.md +147 -0
  7. package/.claude/skills/domain-driven-design/SKILL.md +459 -0
  8. package/.claude/skills/domain-driven-design/references/ddd_foundations_and_patterns.md +664 -0
  9. package/.claude/skills/domain-driven-design/references/rich_hickey_principles.md +406 -0
  10. package/.claude/skills/domain-driven-design/references/visualization_examples.md +790 -0
  11. package/.claude/skills/domain-driven-design/references/wlaschin_patterns.md +639 -0
  12. package/.claude/skills/godot/SKILL.md +728 -0
  13. package/.claude/skills/godot/assets/templates/attribute_template.gd +109 -0
  14. package/.claude/skills/godot/assets/templates/component_template.gd +76 -0
  15. package/.claude/skills/godot/assets/templates/interaction_template.gd +108 -0
  16. package/.claude/skills/godot/assets/templates/item_resource.tres +11 -0
  17. package/.claude/skills/godot/assets/templates/spell_resource.tres +20 -0
  18. package/.claude/skills/godot/references/architecture-patterns.md +608 -0
  19. package/.claude/skills/godot/references/common-pitfalls.md +518 -0
  20. package/.claude/skills/godot/references/file-formats.md +491 -0
  21. package/.claude/skills/godot/references/godot4-physics-api.md +302 -0
  22. package/.claude/skills/godot/scripts/validate_tres.py +145 -0
  23. package/.claude/skills/godot/scripts/validate_tscn.py +170 -0
  24. package/.claude/skills/guitar-fretboard-mastery/SKILL.md +179 -0
  25. package/.claude/skills/guitar-fretboard-mastery/guitar-fretboard-mastery.skill +0 -0
  26. package/.claude/skills/react-three-fiber/SKILL.md +2055 -0
  27. package/.claude/skills/react-three-fiber/scripts/build-scene.ts +171 -0
  28. package/package.json +1 -1
@@ -0,0 +1,518 @@
1
+ # Common Godot Pitfalls and Solutions
2
+
3
+ This document catalogs frequent mistakes, gotchas, and their solutions when working with Godot 4.x projects.
4
+
5
+ ## Initialization and @onready Timing
6
+
7
+ ### The Problem
8
+
9
+ `@onready` variables are initialized when `_ready()` is called, but the order of initialization across the scene tree can cause issues.
10
+
11
+ ### Common Pitfall: Null References from Parent Methods
12
+
13
+ **Problem:**
14
+ ```gdscript
15
+ # In child component
16
+ @onready var player: CharacterBody3D = get_parent()
17
+ @onready var camera: Camera3D = player.get_camera() # ❌ Returns null!
18
+
19
+ func _ready():
20
+ # camera is null here - get_camera() wasn't available during @onready
21
+ ```
22
+
23
+ **Why it fails:**
24
+ - `@onready` runs before `_ready()` in the scene tree
25
+ - If `get_camera()` returns a node that's dynamically set up, it may not exist yet
26
+ - Parent initialization might not be complete
27
+
28
+ **Solution: Use dynamic getters**
29
+ ```gdscript
30
+ # ✅ Better approach
31
+ @onready var player: CharacterBody3D = get_parent()
32
+
33
+ func _get_camera() -> Camera3D:
34
+ if player and player.has_method("get_camera"):
35
+ return player.get_camera()
36
+ return null
37
+
38
+ func perform_action():
39
+ var camera = _get_camera()
40
+ if camera:
41
+ # Use camera
42
+ ```
43
+
44
+ **Solution: Initialize in _ready()**
45
+ ```gdscript
46
+ # ✅ Alternative approach
47
+ var player: CharacterBody3D
48
+ var camera: Camera3D
49
+
50
+ func _ready():
51
+ player = get_parent()
52
+ if player and player.has_method("get_camera"):
53
+ camera = player.get_camera()
54
+ ```
55
+
56
+ ### Common Pitfall: Accessing Child Nodes Too Early
57
+
58
+ **Problem:**
59
+ ```gdscript
60
+ # Parent node
61
+ @onready var child_component = $ChildComponent
62
+
63
+ func _ready():
64
+ child_component.setup() # ❌ Might fail if child's _ready() hasn't run
65
+
66
+ # Child node
67
+ var is_initialized: bool = false
68
+
69
+ func _ready():
70
+ # Complex initialization
71
+ is_initialized = true
72
+
73
+ func setup():
74
+ if not is_initialized:
75
+ push_error("Called setup() before initialization!")
76
+ ```
77
+
78
+ **Solution: Use call_deferred or signals**
79
+ ```gdscript
80
+ # ✅ Parent waits for child to be ready
81
+ func _ready():
82
+ await get_tree().process_frame # Wait one frame
83
+ child_component.setup()
84
+
85
+ # ✅ Or use signals
86
+ func _ready():
87
+ child_component.initialized.connect(_on_child_ready)
88
+
89
+ func _on_child_ready():
90
+ # Child is definitely ready now
91
+ ```
92
+
93
+ ### _ready() Execution Order
94
+
95
+ **Key principle**: `_ready()` is called **bottom-up** in the scene tree (children before parents).
96
+
97
+ ```
98
+ SceneRoot
99
+ ├─ Parent (ready called THIRD)
100
+ ├─ Child1 (ready called FIRST)
101
+ └─ Child2 (ready called SECOND)
102
+ ```
103
+
104
+ **Implications:**
105
+ - Children's `_ready()` complete before parent's `_ready()` starts
106
+ - Parent can safely access child nodes in `_ready()`
107
+ - Children should NOT assume parent is ready during their `_ready()`
108
+
109
+ **Example:**
110
+ ```gdscript
111
+ # Child component
112
+ func _ready():
113
+ var parent = get_parent()
114
+ # ❌ Don't call parent.initialize() - parent's _ready() hasn't run yet
115
+ # ✅ Instead, emit a signal or wait
116
+ ready.emit()
117
+
118
+ # Parent
119
+ func _ready():
120
+ for child in get_children():
121
+ # ✅ Children are fully ready here
122
+ if child.has_method("configure"):
123
+ child.configure(some_data)
124
+ ```
125
+
126
+ ## Node References and get_node()
127
+
128
+ ### Common Pitfall: Hardcoded NodePaths Breaking
129
+
130
+ **Problem:**
131
+ ```gdscript
132
+ @onready var health_bar = $"../UI/HealthBar" # ❌ Fragile - breaks if hierarchy changes
133
+ ```
134
+
135
+ **Solution: Use groups or signals**
136
+ ```gdscript
137
+ # ✅ Add HealthBar to "ui_health" group in editor
138
+ func _ready():
139
+ var health_bar = get_tree().get_first_node_in_group("ui_health")
140
+
141
+ # ✅ Or use signals
142
+ signal health_changed(current: float, max: float)
143
+
144
+ func take_damage(amount: float):
145
+ health -= amount
146
+ health_changed.emit(health, max_health) # UI listens to this
147
+ ```
148
+
149
+ ### Common Pitfall: Using get_node() in @onready with Complex Paths
150
+
151
+ **Problem:**
152
+ ```gdscript
153
+ @onready var camera = get_node("../../CameraPivot/Camera3D") # ❌ Error-prone
154
+ ```
155
+
156
+ **Solution: Find node by type or group**
157
+ ```gdscript
158
+ # ✅ Find by type
159
+ func _get_camera() -> Camera3D:
160
+ var current = get_parent()
161
+ while current:
162
+ if current is Camera3D:
163
+ return current
164
+ for child in current.get_children():
165
+ if child is Camera3D:
166
+ return child
167
+ current = current.get_parent()
168
+ return null
169
+
170
+ # ✅ Or add camera to "camera" group and find it
171
+ func _ready():
172
+ var camera = get_tree().get_first_node_in_group("main_camera")
173
+ ```
174
+
175
+ ## Signal Connection Issues
176
+
177
+ ### Common Pitfall: Connecting Signals in Wrong Order
178
+
179
+ **Problem:**
180
+ ```gdscript
181
+ func _ready():
182
+ $Button.pressed.connect(_on_button_pressed)
183
+ $Button.pressed.emit() # ❌ Connection might not be active yet
184
+ ```
185
+
186
+ **Solution: Wait one frame or use call_deferred**
187
+ ```gdscript
188
+ func _ready():
189
+ $Button.pressed.connect(_on_button_pressed)
190
+ await get_tree().process_frame
191
+ $Button.pressed.emit() # ✅ Connection is active
192
+
193
+ # Or
194
+ func _ready():
195
+ $Button.pressed.connect(_on_button_pressed)
196
+ $Button.pressed.emit.call_deferred() # ✅ Emits after _ready() completes
197
+ ```
198
+
199
+ ### Common Pitfall: Memory Leaks from Signal Connections
200
+
201
+ **Problem:**
202
+ ```gdscript
203
+ func _ready():
204
+ some_node.signal_name.connect(callback)
205
+ # ❌ If this node is freed but some_node remains, connection persists
206
+ ```
207
+
208
+ **Solution: Disconnect in cleanup or use weak references**
209
+ ```gdscript
210
+ var connected_node: Node
211
+
212
+ func _ready():
213
+ connected_node = some_node
214
+ connected_node.signal_name.connect(callback)
215
+
216
+ func _exit_tree():
217
+ if connected_node and connected_node.signal_name.is_connected(callback):
218
+ connected_node.signal_name.disconnect(callback)
219
+
220
+ # Or use one-shot connections
221
+ func _ready():
222
+ some_node.signal_name.connect(callback, CONNECT_ONE_SHOT)
223
+ ```
224
+
225
+ ## Resource Loading and Modification
226
+
227
+ ### Common Pitfall: Modifying Shared Resources
228
+
229
+ **Problem:**
230
+ ```gdscript
231
+ # item_resource.tres is shared across all instances
232
+ @export var item: ItemResource
233
+
234
+ func _ready():
235
+ item.quantity += 1 # ❌ Modifies the .tres file for ALL instances!
236
+ ```
237
+
238
+ **Solution: Duplicate resources when modifying**
239
+ ```gdscript
240
+ @export var item: ItemResource
241
+ var local_item: ItemResource
242
+
243
+ func _ready():
244
+ local_item = item.duplicate() # ✅ Create instance-specific copy
245
+ local_item.quantity += 1 # Only affects this instance
246
+ ```
247
+
248
+ ### Common Pitfall: preload() in .tres Files
249
+
250
+ **Problem:**
251
+ ```tres
252
+ [resource]
253
+ script = preload("res://script.gd") # ❌ WRONG - .tres files don't support preload()
254
+ ```
255
+
256
+ **Solution: Use ExtResource**
257
+ ```tres
258
+ [ext_resource type="Script" path="res://script.gd" id="1"]
259
+
260
+ [resource]
261
+ script = ExtResource("1") # ✅ Correct
262
+ ```
263
+
264
+ ## CharacterBody3D Movement
265
+
266
+ ### Common Pitfall: Velocity Not Persisting
267
+
268
+ **Problem:**
269
+ ```gdscript
270
+ func _physics_process(delta):
271
+ var velocity = Vector3.ZERO # ❌ Resets velocity every frame!
272
+ velocity.x = input.x * speed
273
+ move_and_slide()
274
+ ```
275
+
276
+ **Solution: Use the velocity property**
277
+ ```gdscript
278
+ func _physics_process(delta):
279
+ velocity.x = input.x * speed # ✅ Modifies persistent velocity
280
+ velocity.y -= gravity * delta
281
+ move_and_slide()
282
+ ```
283
+
284
+ ### Common Pitfall: Floor Detection Issues
285
+
286
+ **Problem:**
287
+ ```gdscript
288
+ func _physics_process(delta):
289
+ if is_on_floor():
290
+ velocity.y = 0 # ❌ Causes jittering on slopes
291
+ ```
292
+
293
+ **Solution: Only reset vertical velocity when needed**
294
+ ```gdscript
295
+ func _physics_process(delta):
296
+ # Apply gravity
297
+ if not is_on_floor():
298
+ velocity.y -= gravity * delta
299
+
300
+ # Jump
301
+ if Input.is_action_just_pressed("jump") and is_on_floor():
302
+ velocity.y = jump_force # ✅ Only set when jumping
303
+
304
+ move_and_slide()
305
+ ```
306
+
307
+ ## Transform and Basis Confusion
308
+
309
+ ### Common Pitfall: Wrong Direction Vector
310
+
311
+ **Problem:**
312
+ ```gdscript
313
+ var forward = transform.basis.z # ❌ This is actually backward in Godot!
314
+ ```
315
+
316
+ **Solution: Negate Z for forward**
317
+ ```gdscript
318
+ var forward = -transform.basis.z # ✅ Forward direction
319
+ var right = transform.basis.x # ✅ Right direction
320
+ var up = transform.basis.y # ✅ Up direction
321
+ ```
322
+
323
+ ### Common Pitfall: Mixing Local and Global Transforms
324
+
325
+ **Problem:**
326
+ ```gdscript
327
+ position += Vector3.FORWARD * speed # ❌ Moves in global forward, not local
328
+ ```
329
+
330
+ **Solution: Use basis to transform direction**
331
+ ```gdscript
332
+ position += -transform.basis.z * speed # ✅ Moves in local forward direction
333
+
334
+ # Or use global_transform for global operations
335
+ global_position += Vector3.FORWARD * speed # ✅ Explicitly global
336
+ ```
337
+
338
+ ## Input Handling
339
+
340
+ ### Common Pitfall: Input Processed in _process() and _physics_process()
341
+
342
+ **Problem:**
343
+ ```gdscript
344
+ func _process(delta):
345
+ if Input.is_action_just_pressed("jump"):
346
+ jump() # ❌ Might miss input if physics runs at different rate
347
+
348
+ func _physics_process(delta):
349
+ # Physics code
350
+ ```
351
+
352
+ **Solution: Handle input where it's used**
353
+ ```gdscript
354
+ # For movement: use _physics_process
355
+ func _physics_process(delta):
356
+ if Input.is_action_just_pressed("jump") and is_on_floor():
357
+ velocity.y = jump_force
358
+ move_and_slide()
359
+
360
+ # For UI/non-physics: use _input or _unhandled_input
361
+ func _input(event):
362
+ if event.is_action_pressed("menu"):
363
+ open_menu()
364
+ ```
365
+
366
+ ### Common Pitfall: Mouse Capture Issues
367
+
368
+ **Problem:**
369
+ ```gdscript
370
+ func _ready():
371
+ Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
372
+
373
+ # ❌ Escape key doesn't work - mouse is captured forever
374
+ ```
375
+
376
+ **Solution: Toggle mouse mode with escape**
377
+ ```gdscript
378
+ func _input(event):
379
+ if event.is_action_pressed("ui_cancel"):
380
+ if Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
381
+ Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
382
+ else:
383
+ Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
384
+ ```
385
+
386
+ ## Type Safety and Static Typing
387
+
388
+ ### Common Pitfall: Weak Typing Hiding Errors
389
+
390
+ **Problem:**
391
+ ```gdscript
392
+ var node = get_node("Player")
393
+ node.health = 100 # ❌ No error if Player doesn't have health property
394
+ ```
395
+
396
+ **Solution: Use static typing**
397
+ ```gdscript
398
+ var player: Player = get_node("Player") as Player
399
+ if player:
400
+ player.health = 100 # ✅ Error if Player class doesn't have health
401
+ ```
402
+
403
+ ### Common Pitfall: Null Checks Missing
404
+
405
+ **Problem:**
406
+ ```gdscript
407
+ var target = get_tree().get_first_node_in_group("player")
408
+ var distance = global_position.distance_to(target.global_position) # ❌ Crashes if no player
409
+ ```
410
+
411
+ **Solution: Always check for null**
412
+ ```gdscript
413
+ var target = get_tree().get_first_node_in_group("player")
414
+ if target:
415
+ var distance = global_position.distance_to(target.global_position) # ✅ Safe
416
+ ```
417
+
418
+ ## Scene Instancing
419
+
420
+ ### Common Pitfall: Forgetting to Add Instanced Scene to Tree
421
+
422
+ **Problem:**
423
+ ```gdscript
424
+ var scene = preload("res://enemy.tscn")
425
+ var enemy = scene.instantiate()
426
+ enemy.position = spawn_point # ❌ Enemy exists but isn't in the scene tree!
427
+ ```
428
+
429
+ **Solution: Add to tree**
430
+ ```gdscript
431
+ var scene = preload("res://enemy.tscn")
432
+ var enemy = scene.instantiate()
433
+ add_child(enemy) # ✅ Add to tree
434
+ enemy.global_position = spawn_point # Use global_position after add_child
435
+ ```
436
+
437
+ ### Common Pitfall: Setting Position Before Adding to Tree
438
+
439
+ **Problem:**
440
+ ```gdscript
441
+ var enemy = scene.instantiate()
442
+ enemy.position = Vector3(10, 0, 10) # ❌ Local position, might be wrong after add_child
443
+ add_child(enemy)
444
+ ```
445
+
446
+ **Solution: Set global position after adding**
447
+ ```gdscript
448
+ var enemy = scene.instantiate()
449
+ add_child(enemy)
450
+ enemy.global_position = Vector3(10, 0, 10) # ✅ Global position after in tree
451
+ ```
452
+
453
+ ## Tween Issues
454
+
455
+ ### Common Pitfall: Creating Tweens Without Cleanup
456
+
457
+ **Problem:**
458
+ ```gdscript
459
+ func animate():
460
+ var tween = create_tween()
461
+ tween.tween_property(self, "position", target, 1.0)
462
+ # ❌ If called repeatedly, creates multiple tweens conflicting
463
+ ```
464
+
465
+ **Solution: Kill previous tweens or check is_valid()**
466
+ ```gdscript
467
+ var current_tween: Tween
468
+
469
+ func animate():
470
+ if current_tween and current_tween.is_valid():
471
+ current_tween.kill() # ✅ Stop previous animation
472
+
473
+ current_tween = create_tween()
474
+ current_tween.tween_property(self, "position", target, 1.0)
475
+ ```
476
+
477
+ ### Common Pitfall: Tween Callbacks Not Firing
478
+
479
+ **Problem:**
480
+ ```gdscript
481
+ func swing_weapon():
482
+ var tween = create_tween()
483
+ tween.tween_property(weapon, "rotation", target_rotation, 0.5)
484
+ tween.tween_callback(finish_swing) # ❌ Might not fire if tween is killed
485
+ ```
486
+
487
+ **Solution: Use await or check tween validity**
488
+ ```gdscript
489
+ func swing_weapon():
490
+ var tween = create_tween()
491
+ tween.tween_property(weapon, "rotation", target_rotation, 0.5)
492
+ await tween.finished # ✅ Waits for tween to complete
493
+ finish_swing()
494
+ ```
495
+
496
+ ## Summary: Quick Checklist
497
+
498
+ When encountering issues, check:
499
+
500
+ - [ ] Is `@onready` causing timing issues? → Use dynamic getters or initialize in `_ready()`
501
+ - [ ] Are you accessing parent methods in child's `_ready()`? → Wait a frame or use signals
502
+ - [ ] Is a node reference null? → Check scene tree structure and initialization order
503
+ - [ ] Using `get_node()` with complex paths? → Use groups or find by type
504
+ - [ ] Modifying a shared resource? → Duplicate it first
505
+ - [ ] Movement not working? → Check you're using `velocity` property, not local variable
506
+ - [ ] Direction vector wrong? → Remember `-transform.basis.z` is forward
507
+ - [ ] Tween not working? → Kill previous tweens, use await for callbacks
508
+ - [ ] Input missed? → Process input where it's used (_physics_process for movement)
509
+ - [ ] Null reference error? → Add null checks before accessing properties
510
+ - [ ] Instance not appearing? → Remember to `add_child()` and use `global_position`
511
+
512
+ ## When in Doubt
513
+
514
+ 1. **Print debug info**: `print()` is your friend
515
+ 2. **Check the scene tree**: Use Remote tab in editor while game runs
516
+ 3. **Enable visible collision shapes**: Debug → Visible Collision Shapes
517
+ 4. **Read error messages carefully**: They often point to the exact issue
518
+ 5. **Consult official docs**: https://docs.godotengine.org/