@jarrodmedrano/claude-skills 1.0.2 → 1.0.4
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/skills/bevy/SKILL.md +406 -0
- package/.claude/skills/bevy/references/bevy_specific_tips.md +385 -0
- package/.claude/skills/bevy/references/common_pitfalls.md +217 -0
- package/.claude/skills/bevy/references/ecs_patterns.md +277 -0
- package/.claude/skills/bevy/references/project_structure.md +116 -0
- package/.claude/skills/bevy/references/ui_development.md +147 -0
- package/.claude/skills/domain-driven-design/SKILL.md +459 -0
- package/.claude/skills/domain-driven-design/references/ddd_foundations_and_patterns.md +664 -0
- package/.claude/skills/domain-driven-design/references/rich_hickey_principles.md +406 -0
- package/.claude/skills/domain-driven-design/references/visualization_examples.md +790 -0
- package/.claude/skills/domain-driven-design/references/wlaschin_patterns.md +639 -0
- package/.claude/skills/game-design-theory/SKILL.md +102 -0
- package/.claude/skills/game-design-theory/design-principles.md +308 -0
- package/.claude/skills/game-design-theory/gameplay-elements.md +213 -0
- package/.claude/skills/game-design-theory/player-psychology.md +175 -0
- package/.claude/skills/game-design-theory/playtesting.md +321 -0
- package/.claude/skills/game-design-theory/storytelling.md +219 -0
- package/.claude/skills/game-feel/SKILL.md +305 -0
- package/.claude/skills/game-feel/references/adsr-tuning.md +271 -0
- package/.claude/skills/game-feel/references/classic-profiles.md +279 -0
- package/.claude/skills/game-feel/references/perception-thresholds.md +160 -0
- package/.claude/skills/game-feel/references/polish-effects.md +246 -0
- package/.claude/skills/game-feel/references/simulation-recipes.md +306 -0
- package/.claude/skills/game-feel/references/six-metrics.md +239 -0
- package/.claude/skills/godot/SKILL.md +728 -0
- package/.claude/skills/godot/assets/templates/attribute_template.gd +109 -0
- package/.claude/skills/godot/assets/templates/component_template.gd +76 -0
- package/.claude/skills/godot/assets/templates/interaction_template.gd +108 -0
- package/.claude/skills/godot/assets/templates/item_resource.tres +11 -0
- package/.claude/skills/godot/assets/templates/spell_resource.tres +20 -0
- package/.claude/skills/godot/references/architecture-patterns.md +608 -0
- package/.claude/skills/godot/references/common-pitfalls.md +518 -0
- package/.claude/skills/godot/references/file-formats.md +491 -0
- package/.claude/skills/godot/references/godot4-physics-api.md +302 -0
- package/.claude/skills/godot/scripts/validate_tres.py +145 -0
- package/.claude/skills/godot/scripts/validate_tscn.py +170 -0
- package/.claude/skills/level-design/SKILL.md +249 -0
- package/.claude/skills/level-design/anticipatory-play.md +223 -0
- package/.claude/skills/level-design/hiding-linearity.md +181 -0
- package/.claude/skills/level-design/indie-practices.md +286 -0
- package/.claude/skills/level-design/open-world-planning.md +294 -0
- package/.claude/skills/level-design/play-personas.md +240 -0
- package/.claude/skills/level-design/procedural-handmade.md +271 -0
- package/.claude/skills/level-design/themed-environments.md +264 -0
- package/.claude/skills/react-three-fiber/SKILL.md +2055 -0
- package/.claude/skills/react-three-fiber/scripts/build-scene.ts +171 -0
- package/package.json +3 -1
- package/scripts/install.js +16 -1
- package/templates/github-actions/README.md +36 -0
- /package/.claude/{commands/design-review → agents}/design-review-agent.md +0 -0
- /package/.claude/{commands/code-review → agents}/pragmatic-code-review-subagent.md +0 -0
- /package/{.claude/commands/code-review → templates/github-actions}/claude-code-review-custom.yml +0 -0
- /package/{.claude/commands/code-review → templates/github-actions}/claude-code-review.yml +0 -0
- /package/{.claude/commands/security-review → templates/github-actions}/security.yml +0 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
extends Node
|
|
2
|
+
class_name AttributeTemplate
|
|
3
|
+
|
|
4
|
+
## Base attribute system for managing numeric values with min/max constraints.
|
|
5
|
+
##
|
|
6
|
+
## Usage:
|
|
7
|
+
## 1. Attach to character/object as child node
|
|
8
|
+
## 2. Set value_max and value_start in Inspector
|
|
9
|
+
## 3. Connect to signals in parent script
|
|
10
|
+
## 4. Call add()/subtract() to modify value
|
|
11
|
+
##
|
|
12
|
+
## Example:
|
|
13
|
+
## var health = $HealthAttribute
|
|
14
|
+
## health.attribute_changed.connect(_on_health_changed)
|
|
15
|
+
## health.subtract(10.0) # Take 10 damage
|
|
16
|
+
|
|
17
|
+
# Signals
|
|
18
|
+
signal attribute_changed(attribute_name: String, value_current: float, value_max: float, value_increased: bool)
|
|
19
|
+
signal attribute_reached_zero(attribute_name: String)
|
|
20
|
+
signal attribute_reached_max(attribute_name: String)
|
|
21
|
+
|
|
22
|
+
# Configuration
|
|
23
|
+
@export_group("Attribute Settings")
|
|
24
|
+
@export var attribute_name: String = "Attribute"
|
|
25
|
+
@export var value_max: float = 100.0
|
|
26
|
+
@export var value_start: float = 100.0
|
|
27
|
+
|
|
28
|
+
@export_group("Regeneration")
|
|
29
|
+
@export var auto_regenerate: bool = false
|
|
30
|
+
@export var regen_rate: float = 1.0 # Per second
|
|
31
|
+
@export var regen_delay: float = 3.0 # Delay after damage
|
|
32
|
+
|
|
33
|
+
# Current value with automatic clamping and signal emission
|
|
34
|
+
var value_current: float:
|
|
35
|
+
set(value):
|
|
36
|
+
var old_value = value_current
|
|
37
|
+
value_current = clamp(value, 0, value_max)
|
|
38
|
+
var increased = value_current > old_value
|
|
39
|
+
|
|
40
|
+
attribute_changed.emit(attribute_name, value_current, value_max, increased)
|
|
41
|
+
|
|
42
|
+
if value_current <= 0:
|
|
43
|
+
attribute_reached_zero.emit(attribute_name)
|
|
44
|
+
elif value_current >= value_max and old_value < value_max:
|
|
45
|
+
attribute_reached_max.emit(attribute_name)
|
|
46
|
+
|
|
47
|
+
# Internal state for regeneration
|
|
48
|
+
var _regen_timer: float = 0.0
|
|
49
|
+
|
|
50
|
+
## Initialize the attribute
|
|
51
|
+
func _ready() -> void:
|
|
52
|
+
value_current = value_start
|
|
53
|
+
print("[", attribute_name, "] Initialized: ", value_current, "/", value_max)
|
|
54
|
+
|
|
55
|
+
## Handle regeneration
|
|
56
|
+
func _process(delta: float) -> void:
|
|
57
|
+
if not auto_regenerate:
|
|
58
|
+
return
|
|
59
|
+
|
|
60
|
+
if value_current >= value_max:
|
|
61
|
+
_regen_timer = 0.0
|
|
62
|
+
return
|
|
63
|
+
|
|
64
|
+
_regen_timer += delta
|
|
65
|
+
if _regen_timer >= regen_delay:
|
|
66
|
+
add(regen_rate * delta)
|
|
67
|
+
|
|
68
|
+
## Add to the attribute value
|
|
69
|
+
func add(amount: float) -> void:
|
|
70
|
+
if amount <= 0:
|
|
71
|
+
return
|
|
72
|
+
value_current += amount
|
|
73
|
+
|
|
74
|
+
## Subtract from the attribute value
|
|
75
|
+
func subtract(amount: float) -> void:
|
|
76
|
+
if amount <= 0:
|
|
77
|
+
return
|
|
78
|
+
value_current -= amount
|
|
79
|
+
_regen_timer = 0.0 # Reset regen timer on damage
|
|
80
|
+
|
|
81
|
+
## Set to a specific value
|
|
82
|
+
func set_value(new_value: float) -> void:
|
|
83
|
+
value_current = new_value
|
|
84
|
+
|
|
85
|
+
## Set to maximum
|
|
86
|
+
func set_to_max() -> void:
|
|
87
|
+
value_current = value_max
|
|
88
|
+
|
|
89
|
+
## Set to zero
|
|
90
|
+
func set_to_zero() -> void:
|
|
91
|
+
value_current = 0.0
|
|
92
|
+
|
|
93
|
+
## Get current percentage (0.0 to 1.0)
|
|
94
|
+
func get_percentage() -> float:
|
|
95
|
+
if value_max <= 0:
|
|
96
|
+
return 0.0
|
|
97
|
+
return value_current / value_max
|
|
98
|
+
|
|
99
|
+
## Check if attribute is depleted
|
|
100
|
+
func is_depleted() -> bool:
|
|
101
|
+
return value_current <= 0
|
|
102
|
+
|
|
103
|
+
## Check if attribute is full
|
|
104
|
+
func is_full() -> bool:
|
|
105
|
+
return value_current >= value_max
|
|
106
|
+
|
|
107
|
+
## Get remaining value
|
|
108
|
+
func get_remaining() -> float:
|
|
109
|
+
return value_max - value_current
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
extends Node
|
|
2
|
+
class_name ComponentTemplate
|
|
3
|
+
|
|
4
|
+
## A reusable component template following Godot best practices.
|
|
5
|
+
##
|
|
6
|
+
## Usage:
|
|
7
|
+
## 1. Attach as child node to the object that needs this functionality
|
|
8
|
+
## 2. Export variables appear in Inspector for easy configuration
|
|
9
|
+
## 3. Use signals for loose coupling with parent/other systems
|
|
10
|
+
|
|
11
|
+
# Signals for event-driven communication
|
|
12
|
+
signal component_activated
|
|
13
|
+
signal component_deactivated
|
|
14
|
+
signal component_updated(data: Dictionary)
|
|
15
|
+
|
|
16
|
+
# Export variables for Inspector configuration
|
|
17
|
+
@export_group("Component Settings")
|
|
18
|
+
@export var is_enabled: bool = true
|
|
19
|
+
@export var auto_start: bool = true
|
|
20
|
+
|
|
21
|
+
@export_group("Behavior")
|
|
22
|
+
@export var update_interval: float = 1.0
|
|
23
|
+
|
|
24
|
+
# Internal state
|
|
25
|
+
var _timer: float = 0.0
|
|
26
|
+
var _is_active: bool = false
|
|
27
|
+
|
|
28
|
+
## Called when the node enters the scene tree
|
|
29
|
+
func _ready() -> void:
|
|
30
|
+
if auto_start:
|
|
31
|
+
activate()
|
|
32
|
+
|
|
33
|
+
## Called every frame
|
|
34
|
+
func _process(delta: float) -> void:
|
|
35
|
+
if not _is_active or not is_enabled:
|
|
36
|
+
return
|
|
37
|
+
|
|
38
|
+
_timer += delta
|
|
39
|
+
if _timer >= update_interval:
|
|
40
|
+
_update()
|
|
41
|
+
_timer = 0.0
|
|
42
|
+
|
|
43
|
+
## Activate the component
|
|
44
|
+
func activate() -> void:
|
|
45
|
+
if _is_active:
|
|
46
|
+
return
|
|
47
|
+
|
|
48
|
+
_is_active = true
|
|
49
|
+
component_activated.emit()
|
|
50
|
+
print("[", name, "] Component activated")
|
|
51
|
+
|
|
52
|
+
## Deactivate the component
|
|
53
|
+
func deactivate() -> void:
|
|
54
|
+
if not _is_active:
|
|
55
|
+
return
|
|
56
|
+
|
|
57
|
+
_is_active = false
|
|
58
|
+
component_deactivated.emit()
|
|
59
|
+
print("[", name, "] Component deactivated")
|
|
60
|
+
|
|
61
|
+
## Internal update logic - override in subclasses
|
|
62
|
+
func _update() -> void:
|
|
63
|
+
var data = {
|
|
64
|
+
"timestamp": Time.get_ticks_msec(),
|
|
65
|
+
"component": name
|
|
66
|
+
}
|
|
67
|
+
component_updated.emit(data)
|
|
68
|
+
|
|
69
|
+
## Public interface for parent to call
|
|
70
|
+
func do_something() -> void:
|
|
71
|
+
if not is_enabled:
|
|
72
|
+
push_warning("Component not enabled")
|
|
73
|
+
return
|
|
74
|
+
|
|
75
|
+
# Implementation here
|
|
76
|
+
pass
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
extends Node
|
|
2
|
+
class_name InteractionTemplate
|
|
3
|
+
|
|
4
|
+
## Base class for interaction components following the component pattern.
|
|
5
|
+
##
|
|
6
|
+
## Usage:
|
|
7
|
+
## 1. Create subclass extending InteractionTemplate
|
|
8
|
+
## 2. Override _perform_interaction() with custom logic
|
|
9
|
+
## 3. Attach as child to BaseInteractable object
|
|
10
|
+
## 4. Set interaction_text and other exports in Inspector
|
|
11
|
+
##
|
|
12
|
+
## Example subclass:
|
|
13
|
+
## extends InteractionTemplate
|
|
14
|
+
## class_name DoorInteraction
|
|
15
|
+
##
|
|
16
|
+
## @export var door_id: String
|
|
17
|
+
## @export var requires_key: bool = false
|
|
18
|
+
##
|
|
19
|
+
## func _perform_interaction(player) -> void:
|
|
20
|
+
## if requires_key and not player.has_key(door_id):
|
|
21
|
+
## return
|
|
22
|
+
## get_parent().open()
|
|
23
|
+
|
|
24
|
+
# Signals
|
|
25
|
+
signal was_interacted_with(player: Node)
|
|
26
|
+
signal interaction_enabled
|
|
27
|
+
signal interaction_disabled
|
|
28
|
+
|
|
29
|
+
# Configuration
|
|
30
|
+
@export_group("Interaction Settings")
|
|
31
|
+
@export var interaction_text: String = "Interact"
|
|
32
|
+
@export var is_enabled: bool = true
|
|
33
|
+
@export var single_use: bool = false
|
|
34
|
+
|
|
35
|
+
@export_group("Requirements")
|
|
36
|
+
@export var required_item_id: String = ""
|
|
37
|
+
@export var minimum_level: int = 0
|
|
38
|
+
|
|
39
|
+
# Internal state
|
|
40
|
+
var _has_been_used: bool = false
|
|
41
|
+
|
|
42
|
+
## Attempt to interact with this component
|
|
43
|
+
## Returns true if interaction was successful
|
|
44
|
+
func interact(player: Node) -> bool:
|
|
45
|
+
if not can_interact(player):
|
|
46
|
+
return false
|
|
47
|
+
|
|
48
|
+
_perform_interaction(player)
|
|
49
|
+
was_interacted_with.emit(player)
|
|
50
|
+
|
|
51
|
+
if single_use:
|
|
52
|
+
_has_been_used = true
|
|
53
|
+
disable()
|
|
54
|
+
|
|
55
|
+
return true
|
|
56
|
+
|
|
57
|
+
## Check if interaction is possible
|
|
58
|
+
func can_interact(player: Node) -> bool:
|
|
59
|
+
if not is_enabled:
|
|
60
|
+
return false
|
|
61
|
+
|
|
62
|
+
if single_use and _has_been_used:
|
|
63
|
+
return false
|
|
64
|
+
|
|
65
|
+
if required_item_id and not _player_has_item(player, required_item_id):
|
|
66
|
+
return false
|
|
67
|
+
|
|
68
|
+
if minimum_level > 0 and not _player_meets_level(player, minimum_level):
|
|
69
|
+
return false
|
|
70
|
+
|
|
71
|
+
return true
|
|
72
|
+
|
|
73
|
+
## Get the text to display for this interaction
|
|
74
|
+
func get_interaction_text() -> String:
|
|
75
|
+
return interaction_text
|
|
76
|
+
|
|
77
|
+
## Enable this interaction
|
|
78
|
+
func enable() -> void:
|
|
79
|
+
is_enabled = true
|
|
80
|
+
interaction_enabled.emit()
|
|
81
|
+
|
|
82
|
+
## Disable this interaction
|
|
83
|
+
func disable() -> void:
|
|
84
|
+
is_enabled = false
|
|
85
|
+
interaction_disabled.emit()
|
|
86
|
+
|
|
87
|
+
## Reset for reuse (if not single_use)
|
|
88
|
+
func reset() -> void:
|
|
89
|
+
if not single_use:
|
|
90
|
+
_has_been_used = false
|
|
91
|
+
enable()
|
|
92
|
+
|
|
93
|
+
## OVERRIDE THIS: Perform the actual interaction logic
|
|
94
|
+
func _perform_interaction(player: Node) -> void:
|
|
95
|
+
print("[", get_parent().name, "] Interacted by ", player.name)
|
|
96
|
+
# Override in subclasses with specific interaction logic
|
|
97
|
+
|
|
98
|
+
## Helper: Check if player has required item
|
|
99
|
+
func _player_has_item(player: Node, item_id: String) -> bool:
|
|
100
|
+
if not player.has_method("has_item"):
|
|
101
|
+
return false
|
|
102
|
+
return player.has_item(item_id)
|
|
103
|
+
|
|
104
|
+
## Helper: Check if player meets level requirement
|
|
105
|
+
func _player_meets_level(player: Node, level: int) -> bool:
|
|
106
|
+
if not player.has_method("get_level"):
|
|
107
|
+
return false
|
|
108
|
+
return player.get_level() >= level
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
[gd_resource type="Resource" script_class="ItemResource" load_steps=2 format=3 uid="uid://template_item"]
|
|
2
|
+
|
|
3
|
+
[ext_resource type="Script" path="res://src/items/item_resource.gd" id="1_item"]
|
|
4
|
+
|
|
5
|
+
[resource]
|
|
6
|
+
script = ExtResource("1_item")
|
|
7
|
+
item_id = "example_item"
|
|
8
|
+
item_name = "Example Item"
|
|
9
|
+
description = "A template item resource"
|
|
10
|
+
stackable = true
|
|
11
|
+
max_stack = 99
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[gd_resource type="Resource" script_class="SpellResource" load_steps=3 format=3 uid="uid://template_spell"]
|
|
2
|
+
|
|
3
|
+
[ext_resource type="Script" path="res://src/spells/spell_resource.gd" id="1_spell"]
|
|
4
|
+
[ext_resource type="Script" path="res://src/spells/spell_effect.gd" id="2_effect"]
|
|
5
|
+
|
|
6
|
+
[sub_resource type="Resource" id="Effect_damage"]
|
|
7
|
+
script = ExtResource("2_effect")
|
|
8
|
+
effect_type = 0
|
|
9
|
+
magnitude_min = 10.0
|
|
10
|
+
magnitude_max = 20.0
|
|
11
|
+
duration = 0.0
|
|
12
|
+
|
|
13
|
+
[resource]
|
|
14
|
+
script = ExtResource("1_spell")
|
|
15
|
+
spell_name = "Magic Missile"
|
|
16
|
+
spell_id = "magic_missile"
|
|
17
|
+
mana_cost = 15.0
|
|
18
|
+
spell_color = Color(0.5, 0.5, 1, 1)
|
|
19
|
+
projectile_speed = 20.0
|
|
20
|
+
effects = Array[ExtResource("2_effect")]([SubResource("Effect_damage")])
|