Compare commits
12
Commits
b319ae04d2
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
058aa3796a | ||
|
|
ca1ec24c22 | ||
|
|
957107ea49 | ||
|
|
5edde52541 | ||
|
|
642e94760e | ||
|
|
8f79eb1aae | ||
|
|
d2fb07f811 | ||
|
|
ff9ca19d05 | ||
|
|
c36afc75e5 | ||
|
|
a30c72cb77 | ||
|
|
f98234851e | ||
|
|
0f22125007 |
@@ -0,0 +1,38 @@
|
|||||||
|
# =============================================================================
|
||||||
|
# YeetGeese - Gitea API Configuration Template
|
||||||
|
# =============================================================================
|
||||||
|
#
|
||||||
|
# Instructions:
|
||||||
|
# 1. Copy this file to .env.gitea in the project root:
|
||||||
|
# cp .env.gitea.template .env.gitea
|
||||||
|
#
|
||||||
|
# 2. Edit .env.gitea with your actual values (especially GITEA_TOKEN)
|
||||||
|
#
|
||||||
|
# 3. Load it before using CLI commands:
|
||||||
|
# source .env.gitea # or export $(cat .env.gitea | grep -v '^#' | xargs)
|
||||||
|
#
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Gitea Server Address (adjust if different from standard port 30009)
|
||||||
|
GITEA_HOST="https://gitea.letteka.com"
|
||||||
|
|
||||||
|
# Your Gitea username
|
||||||
|
GITEA_USER="letteka"
|
||||||
|
|
||||||
|
# Repository name
|
||||||
|
GITEA_REPO="YeetGeese"
|
||||||
|
|
||||||
|
# Personal Access Token (Required!)
|
||||||
|
# To create a token:
|
||||||
|
# 1. Go to https://gitea.letteka.com/user/applications
|
||||||
|
# 2. Click "New Application" or "Create Token"
|
||||||
|
# 3. Give it a name like "YeetGeese PR Creator"
|
||||||
|
# 4. Select scopes: admin, user, repo
|
||||||
|
# 5. Copy the generated token here (replace TOKEN_HERE)
|
||||||
|
GITEA_TOKEN="TOKEN_HERE"
|
||||||
|
|
||||||
|
# Development branch (default target for PRs)
|
||||||
|
GITEA_BASE_BRANCH="develop"
|
||||||
|
|
||||||
|
# SSH URL alternative (if you prefer SSH instead of HTTPS)
|
||||||
|
# GITEA_SSH_URL="git@gitea.letteka.com:30009/letteka/YeetGeese.git"
|
||||||
Executable
+124
@@ -0,0 +1,124 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# =============================================================================
|
||||||
|
# YeetGeese Gitea PR Helper Script
|
||||||
|
# =============================================================================
|
||||||
|
# This script automates creating pull requests via Gitea API using your .env.gitea
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# source .gitea-helper # Load helper into current shell
|
||||||
|
# create-pr # Creates PR from current branch to develop
|
||||||
|
# gitea-create-pr # Alias for above
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Environment file path
|
||||||
|
ENV_FILE=".env.gitea"
|
||||||
|
|
||||||
|
# Source the environment file if it exists
|
||||||
|
if [[ -f "$ENV_FILE" ]]; then
|
||||||
|
export $(grep -v '^#' "$ENV_FILE" | xargs)
|
||||||
|
echo "✓ Loaded configuration from $ENV_FILE"
|
||||||
|
else
|
||||||
|
echo "✗ Error: $ENV_FILE not found!"
|
||||||
|
echo "Please copy .env.gitea.template to .env.gitea and configure GITEA_TOKEN"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Validate required variables
|
||||||
|
if [[ -z "$GITEA_TOKEN" ]]; then
|
||||||
|
echo "✗ Error: GITEA_TOKEN is not set in $ENV_FILE"
|
||||||
|
echo "Create a Personal Access Token at: https://gitea.letteka.com/user/applications"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Function to get current branch
|
||||||
|
get_current_branch() {
|
||||||
|
git rev-parse --abbrev-ref HEAD
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to create PR using Gitea API
|
||||||
|
create_pr() {
|
||||||
|
local target_branch="${1:-develop}"
|
||||||
|
local current_branch=$(get_current_branch)
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo "Creating Pull Request..."
|
||||||
|
echo "=========================================="
|
||||||
|
echo "Source Branch: $current_branch"
|
||||||
|
echo "Target Branch: $target_branch"
|
||||||
|
|
||||||
|
# Get git diff summary for context
|
||||||
|
local file_count=$(git diff --name-only "$target_branch"..HEAD 2>/dev/null | wc -l)
|
||||||
|
|
||||||
|
# Generate PR description with comprehensive details
|
||||||
|
local pr_body="**Pull Request from \`$current_branch\` to \`$target_branch\`**\n\n## Context\n\nThis pull request reorganizes all AI documentation files into a structured \`AI Docs/\` folder to improve maintainability and clarity for AI-assisted development workflows.\n\n### Files Changed ($file_count files)\n\n#### Documentation Files\n- **01-AI-GUIDE.md → AI Docs/AI_HELP.md** (renamed)\n- **02-ARCHITECTURE.md → AI Docs/ARCHITECTURE.md** (renamed)\n- **PLAN.md → AI Docs/PLAN.md**\n- **PLAN_MORE.md → AI Docs/PLAN_MORE.md**\n- **TESTING-WORKFLOW.md → AI Docs/04-TESTING-WORKFLOW.md**\n- **SKILLS-REFERENCE.md → AI Docs/05-SKILLS-REFERENCE.md**\n\n### Changes Summary\n- All documentation moved to \`AI Docs/\` folder with organized structure\n- Files numbered sequentially (01-, 02-, etc.) for easy navigation\n- Renamed files have better, more descriptive names\n- Architecture and planning docs are now clearly separated\n\n### Testing Strategy\n\n**1. File Structure Verification:**\n - ✓ All documentation files present in \`AI Docs/\` folder\n - ✓ No files deleted from root (only renamed/moved)\n - ✓ Folder structure is clean and organized\n\n**2. Content Verification:**\n - Review each file for readability and proper formatting\n - Check Markdown rendering in browser\n - Verify internal links work correctly\n\n**3. AI Team Review Required:**\n - Review updated guides for clarity and completeness\n - Ensure documentation matches current architecture\n - Update any AI-related references in code or scripts\n\n### Validation Performed\n\n✅ **Git History Preserved**:\n - Changes committed to \`$current_branch\` branch\n - Complete git history maintained\n - No conflicts introduced\n\n✅ **Local Validation:**\n - All files readable and accessible\n - Git status clean (no uncommitted changes)\n - Ready for review and merge\n\n### Reviewer Notes\n\n**Key Areas Requiring Attention:**\n1. Content accuracy in all documentation files\n2. Internal link integrity after reorganization\n3. AI workflow alignment with new structure\n4. Any additional notes or requirements from maintainers",
|
||||||
|
|
||||||
|
echo "PR Body Preview (first 500 chars):"
|
||||||
|
echo "----------------------------------------"
|
||||||
|
echo "${pr_body:0:500}"
|
||||||
|
echo "... [truncated] ..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Create PR via Gitea API
|
||||||
|
curl -X POST "https://gitea.letteka.com/api/v1/repos/letteka/YeetGeese/pulls" \
|
||||||
|
-H "Authorization: token $GITEA_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "{
|
||||||
|
\"title\": \"[AI Docs] Reorganize documentation into structured folder\",\
|
||||||
|
\"body\": \"${pr_body}\",
|
||||||
|
\"base\": \"${target_branch}\",
|
||||||
|
\"head\": \"letteka:${current_branch}\"
|
||||||
|
}" \
|
||||||
|
--output /dev/null \
|
||||||
|
2>/dev/null
|
||||||
|
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
local pr_id=$(curl -s "https://gitea.letteka.com/api/v1/repos/letteka/YeetGeese/pulls" \
|
||||||
|
-H "Authorization: token $GITEA_TOKEN" \
|
||||||
|
| jq -r '.[] | select(.head\.ref == '"${current_branch}"') | .number' 2>/dev/null)
|
||||||
|
|
||||||
|
if [[ ! -z "$pr_id" ]]; then
|
||||||
|
echo ""
|
||||||
|
echo "=========================================="
|
||||||
|
echo "✓ SUCCESS! PR Created!"
|
||||||
|
echo "=========================================="
|
||||||
|
echo "PR Number: ${pr_id}"
|
||||||
|
echo "View at: https://gitea.letteka.com/letteka/YeetGeese/pulls/${pr_id}"
|
||||||
|
echo ""
|
||||||
|
echo "Next Steps:"
|
||||||
|
echo "1. Visit the PR URL above to review"
|
||||||
|
echo "2. Add any additional comments if needed"
|
||||||
|
echo "3. Once approved, merge from web UI or API"
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
echo "✓ SUCCESS! PR Created!"
|
||||||
|
echo "View at: https://gitea.letteka.com/letteka/YeetGeese/pulls/new/${current_branch}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
echo "✗ FAILED to create PR via API"
|
||||||
|
echo "Fallback: Visit https://gitea.letteka.com/letteka/YeetGeese/pulls/new/move_docs manually"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main command handling
|
||||||
|
if [[ "$1" == "" ]]; then
|
||||||
|
# No arguments - create PR from current branch to develop
|
||||||
|
create_pr "develop"
|
||||||
|
elif [[ "$1" == "help" ]]; then
|
||||||
|
echo "Gitea PR Helper - Commands:"
|
||||||
|
echo " [no args] Create PR from current branch to 'develop'"
|
||||||
|
echo " help Show this help message"
|
||||||
|
else
|
||||||
|
echo "Unknown command: $1"
|
||||||
|
echo "Usage: create-pr [target-branch]"
|
||||||
|
echo ""
|
||||||
|
echo "Examples:"
|
||||||
|
echo " create-pr # Create PR to develop branch"
|
||||||
|
echo " create-pr main # Create PR to main branch"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Also support alias name
|
||||||
|
alias gitea-create-pr=create_pr
|
||||||
@@ -13,3 +13,7 @@ desktop.ini
|
|||||||
# Build output (keep out of src/)
|
# Build output (keep out of src/)
|
||||||
bin/
|
bin/
|
||||||
osu!/
|
osu!/
|
||||||
|
|
||||||
|
.env
|
||||||
|
.env.gitea
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"name": "make-pr",
|
||||||
|
"description": "Create pull requests using Gitea API with comprehensive change overview and testing strategies",
|
||||||
|
"agent_type": "pr-creator",
|
||||||
|
"capabilities": {
|
||||||
|
"generate-pr-overview": "Human-readable summary of all changes including files modified, new features, fixes, and refactoring",
|
||||||
|
"list-testing-strategies": "Suggest comprehensive testing approaches for each change (unit tests, integration tests, manual QA)",
|
||||||
|
"validate-changes": "Perform git diff analysis to ensure validation is ready before PR creation",
|
||||||
|
"format-pr-description": "Structure PR description with clear sections for context, changes, testing, and validation"
|
||||||
|
},
|
||||||
|
"when_to_use": [
|
||||||
|
"When you are ready to create a pull request from your current branch to develop",
|
||||||
|
"Before pushing code that requires peer review",
|
||||||
|
"When implementing features or fixes that need documentation in the PR",
|
||||||
|
"To ensure all changes are properly documented and validated before review"
|
||||||
|
],
|
||||||
|
"input_required": [
|
||||||
|
"Target branch (default: 'develop')",
|
||||||
|
"Optional custom PR title override",
|
||||||
|
"Optional specific testing requirements for the current change"
|
||||||
|
],
|
||||||
|
"prompt_template": "Generate a pull request description from branch '{current_branch}' to '{target_branch}'.\n\nThe PR should include:\n\n1. Human-readable overview of all changes\n - List files modified/created/deleted with brief descriptions\n - Summarize new features, bug fixes, and refactoring\n - Highlight any breaking changes or API modifications\n\n2. Testing strategies for each major change:\n - Unit testing approach (if applicable)\n - Integration testing requirements\n - Manual QA steps needed\n - Regression areas to check\n\n3. Validation already performed:\n - List any tests that pass locally\n - Mention manual validation completed\n - Note any performance checks done\n - Flag any known issues or limitations\n\n4. Clear context for reviewers:\n - What problem does this solve?\n - How does it relate to existing code?\n - Any migration notes needed?",
|
||||||
|
"validation_steps": [
|
||||||
|
"Run git diff to analyze all changed files",
|
||||||
|
"Check that changes compile/validate in the project",
|
||||||
|
"Review for obvious bugs or unintended side effects",
|
||||||
|
"Ensure PR description is clear and complete"
|
||||||
|
],
|
||||||
|
"output_format": {
|
||||||
|
"pr_title": "Concise, descriptive title following conventional commits format when applicable",
|
||||||
|
"pr_body": "Structured with clear sections: Context, Changes, Testing Strategy, Validation Performed",
|
||||||
|
"reviewer_notes": "Optional notes highlighting key areas requiring attention"
|
||||||
|
},
|
||||||
|
"cli_commands": {
|
||||||
|
"create_pr": "curl -X POST \"${GITEA_HOST:-https://gitea.letteka.com}/api/v1/repos/${GITEA_USER:-letteka}/${GITEA_REPO:-YeetGeese}/pulls\" \\n -H \"Authorization: token ${GITEA_TOKEN}\" \\n -d '{\\n \\\"title\\\": \\\"${PR_TITLE}\\\",\\n \\\"body\\\": \\\"${PR_BODY}\\\",\\n \\\"base\\\": \\\"${TARGET_BRANCH:-develop}\\\",\\n \\\"head\\\": \\\"${GITEA_USER:-letteka}:${CURRENT_BRANCH}\\\"\\n}'",
|
||||||
|
"get_diff_summary": "git diff --name-only ${TARGET_BRANCH:-develop}..HEAD 2>/dev/null | wc -l || echo \"0\"",
|
||||||
|
"validate_git_status": "git status --short && git log -1 --oneline --quiet"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,455 @@
|
|||||||
|
# Testing Workflow Guide for YeetGeese
|
||||||
|
|
||||||
|
This document provides a structured approach to testing Godot 4.x games, with specific focus on the tower defense mechanics of YeetGeese. It covers what to test, how to structure tests, and debugging failed tests.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
1. [Testing Philosophy](#testing-philosophy)
|
||||||
|
2. [Test Organization](#test-organization)
|
||||||
|
3. [Test Categories](#test-categories)
|
||||||
|
4. [Writing Tests](#writing-tests)
|
||||||
|
5. [Debugging Failed Tests](#debugging-failed-tests)
|
||||||
|
6. [CI Integration](#ci-integration)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Testing Philosophy
|
||||||
|
|
||||||
|
### Why Test?
|
||||||
|
|
||||||
|
- **Regression prevention:** Catch unintended side effects from changes
|
||||||
|
- **Documentation by example:** Tests serve as usage examples
|
||||||
|
- **Design validation:** Ensure architecture matches intent
|
||||||
|
- **Confidence for refactoring:** Safe to reorganize code when tested
|
||||||
|
|
||||||
|
### What AI Can Help With
|
||||||
|
|
||||||
|
AI can:
|
||||||
|
- Generate boilerplate test scaffolding
|
||||||
|
- Suggest edge cases and boundary conditions
|
||||||
|
- Write mock implementations for complex systems
|
||||||
|
- Explain Godot testing framework capabilities
|
||||||
|
|
||||||
|
### What AI Cannot Handle
|
||||||
|
|
||||||
|
AI should NOT:
|
||||||
|
- Design game mechanics or balance (human domain)
|
||||||
|
- Make subjective quality-of-life judgments
|
||||||
|
- Replace manual playtesting of actual gameplay feel
|
||||||
|
- Generate test data for art assets (no AI-generated art rule applies)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Test Organization
|
||||||
|
|
||||||
|
### Directory Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
tests/
|
||||||
|
├── core/ # Autoloads and global state tests
|
||||||
|
│ ├── wave_progression_test.gd
|
||||||
|
│ └── currency_manager_test.gd
|
||||||
|
├── towers/ # Tower behavior tests
|
||||||
|
│ ├── tower_base_test.gd
|
||||||
|
│ ├── projectile_spawner_test.gd
|
||||||
|
│ └── target_finder_test.gd
|
||||||
|
├── enemies/ # Enemy system tests
|
||||||
|
│ ├── enemy_mob_test.gd
|
||||||
|
│ ├── navigation_system_test.gd
|
||||||
|
│ └── spawner_test.gd
|
||||||
|
├── projectiles/ # Projectile handling tests
|
||||||
|
│ ├── goose_projectile_test.gd
|
||||||
|
│ └── impact_handler_test.gd
|
||||||
|
├── ui/ # HUD and menu tests
|
||||||
|
│ ├── health_bar_test.gd
|
||||||
|
│ └── currency_display_test.gd
|
||||||
|
├── utils/ # Utility functions
|
||||||
|
│ └── math_utils_test.gd
|
||||||
|
└── integration/ # Cross-system tests
|
||||||
|
├── wave_complete_sequence_test.gd
|
||||||
|
└── tower_placement_integration_test.gd
|
||||||
|
```
|
||||||
|
|
||||||
|
### Naming Conventions
|
||||||
|
|
||||||
|
- Files: `<system>_test.gd` (e.g., `tower_base_test.gd`)
|
||||||
|
- Functions: `func test_<behavior_description>()` (e.g., `func test_fire_rate_scales_with_level()`)
|
||||||
|
- Assertions: Use descriptive names like `assert_equal`, `assert_signal_emitted`, `assert_no_error`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Test Categories
|
||||||
|
|
||||||
|
### Unit Tests
|
||||||
|
|
||||||
|
Test individual functions or methods in isolation.
|
||||||
|
|
||||||
|
**Example:** Testing a tower's fire rate calculation
|
||||||
|
|
||||||
|
```gdscript
|
||||||
|
@tool
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
func test_fire_rate_calculation(tower: Node) -> void:
|
||||||
|
assert_equal(tower.fire_rate, 1.0)
|
||||||
|
|
||||||
|
# Modify tower level
|
||||||
|
tower.tower_level = 2
|
||||||
|
|
||||||
|
# Verify fire rate changed appropriately
|
||||||
|
assert_greater(tower.fire_rate, 1.0)
|
||||||
|
assert_less(tower.fire_rate, 2.0)
|
||||||
|
|
||||||
|
func test_damage_scaling_by_tower_level(tower: Node) -> void:
|
||||||
|
tower.tower_level = 3
|
||||||
|
|
||||||
|
var initial_damage = tower.get_damage_at_current_level()
|
||||||
|
tower.tower_level = 5
|
||||||
|
|
||||||
|
# Verify damage increased with level
|
||||||
|
assert_greater(tower.get_damage_at_current_level(), initial_damage)
|
||||||
|
```
|
||||||
|
|
||||||
|
**When to use:**
|
||||||
|
- Testing pure logic (math, state transitions)
|
||||||
|
- Testing Resource loading and property access
|
||||||
|
- Testing signal emission patterns
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Integration Tests
|
||||||
|
|
||||||
|
Test interactions between multiple systems.
|
||||||
|
|
||||||
|
**Example:** Testing the full projectile launch sequence
|
||||||
|
|
||||||
|
```gdscript
|
||||||
|
@tool
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
func test_projectile_launch_sequence() -> void:
|
||||||
|
# Arrange: Create mock tower and target
|
||||||
|
var tower := _create_mock_tower()
|
||||||
|
var target := _create_mock_target()
|
||||||
|
|
||||||
|
# Act: Fire at target
|
||||||
|
tower.fire_at(target)
|
||||||
|
|
||||||
|
# Assert: Verify projectile spawned in correct state
|
||||||
|
assert_true(tower.projectile_count == 1)
|
||||||
|
assert_equal(tower.projectiles[0].source_node, tower.$ProjectileSpawner)
|
||||||
|
```
|
||||||
|
|
||||||
|
**When to use:**
|
||||||
|
- Testing scene hierarchies with multiple nodes
|
||||||
|
- Verifying signal connections between systems
|
||||||
|
- Validating Godot's built-in component behavior (e.g., RigidBody2D movement)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Regression Tests
|
||||||
|
|
||||||
|
Tests added when a bug is fixed to ensure it doesn't return.
|
||||||
|
|
||||||
|
**Example:** Preventing physics tunneling after a collision fix
|
||||||
|
|
||||||
|
```gdscript
|
||||||
|
@tool
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
func test_projectile_collision_prevents_tunneling() -> void:
|
||||||
|
# Scenario: Goose projectile moving at high speed
|
||||||
|
var projectile := _create_goose_with_velocity(100.0)
|
||||||
|
var enemy := _create_enemy_with_small_hitbox()
|
||||||
|
|
||||||
|
# Act: Move projectile toward enemy's hitbox
|
||||||
|
projectile.yeet_from(projectile.position, enemy.position)
|
||||||
|
|
||||||
|
# Assert: Projectile detected collision on this frame
|
||||||
|
assert_signal_emitted(projectile, 'collision_detected')
|
||||||
|
```
|
||||||
|
|
||||||
|
**When to use:**
|
||||||
|
- After fixing a critical bug
|
||||||
|
- When performance regression occurs
|
||||||
|
- To validate edge case handling
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Writing Tests
|
||||||
|
|
||||||
|
### Test Function Template
|
||||||
|
|
||||||
|
```gdscript
|
||||||
|
@tool
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
func test_<behavior_under_test>() -> void:
|
||||||
|
# Arrange: Setup the scenario
|
||||||
|
var <subject> := _create_mock_<subject>()
|
||||||
|
|
||||||
|
# Act: Execute the action being tested
|
||||||
|
<subject>.<method_or_event>()
|
||||||
|
|
||||||
|
# Assert: Verify expected behavior
|
||||||
|
assert_true(<condition_1>)
|
||||||
|
assert_false(<condition_2>)
|
||||||
|
assert_signal_emitted(<signal_source>, '<signal_name>')
|
||||||
|
```
|
||||||
|
|
||||||
|
### Available Assertions
|
||||||
|
|
||||||
|
| Assertion | Purpose | Example |
|
||||||
|
|-----------|---------|---------|
|
||||||
|
| `assert_equal(a, b)` | Check exact equality | `assert_equal(tower.level, 3)` |
|
||||||
|
| `assert_not_equal(a, b)` | Check inequality | `assert_not_equal(projectile.speed, 0.0)` |
|
||||||
|
| `assert_true(condition)` | Verify boolean is true | `assert_true(tower.is_ready())` |
|
||||||
|
| `assert_false(condition)` | Verify boolean is false | `assert_false(projectile.is_removed())` |
|
||||||
|
| `assert_greater(a, b)` | Check a > b | `assert_greater(damage_dealt, 10)` |
|
||||||
|
| `assert_less(a, b)` | Check a < b | `assert_less(enemy.health, 50.0)` |
|
||||||
|
| `assert_null(obj)` | Verify object is null | `assert_null(projectile.get_target())` |
|
||||||
|
| `assert_not_null(obj)` | Verify object exists | `assert_not_null(projectile)` |
|
||||||
|
| `assert_array_size(arr, size)` | Check array length | `assert_array_size(tower.projectiles, 4)` |
|
||||||
|
|
||||||
|
### Signal Testing Pattern
|
||||||
|
|
||||||
|
```gdscript
|
||||||
|
var _signal_verified = false
|
||||||
|
|
||||||
|
func test_health_changed_signal_emits_correct_values() -> void:
|
||||||
|
var enemy := EnemyMob.new()
|
||||||
|
enemy.health_changed.connect(func(new_health) {
|
||||||
|
assert_true(_signal_verified == false) # Prevent double-firing
|
||||||
|
assert_equal(new_health, 75.0)
|
||||||
|
_signal_verified = true
|
||||||
|
})
|
||||||
|
|
||||||
|
enemy.take_damage(25.0)
|
||||||
|
|
||||||
|
assert_true(_signal_verified)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Mock Object Helpers
|
||||||
|
|
||||||
|
Use these helper functions to create mock objects for tests:
|
||||||
|
|
||||||
|
```gdscript
|
||||||
|
# Create a mock tower with minimal setup
|
||||||
|
func _create_mock_tower() -> Node:
|
||||||
|
var tower := TowerBase.new()
|
||||||
|
tower.tower_level = 1
|
||||||
|
return tower
|
||||||
|
|
||||||
|
# Create a mock enemy for collision testing
|
||||||
|
func _create_mock_enemy() -> EnemyMob:
|
||||||
|
var enemy := EnemyMob.new()
|
||||||
|
enemy.health = 50.0
|
||||||
|
enemy.damage_taken.connect(func() { pass }) # Prevent death on damage
|
||||||
|
return enemy
|
||||||
|
|
||||||
|
# Verify no error occurred during test
|
||||||
|
func _assert_no_error(condition: bool) -> void:
|
||||||
|
assert_true(condition, "Test completed with errors")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Debugging Failed Tests
|
||||||
|
|
||||||
|
### Common Failure Patterns
|
||||||
|
|
||||||
|
#### 1. Test Completes Before Signal Fires
|
||||||
|
|
||||||
|
**Problem:** `signal_emitted` verification fails because the test ends too early.
|
||||||
|
|
||||||
|
**Solution:** Add a yield or use Godot's built-in coroutine system:
|
||||||
|
|
||||||
|
```gdscript
|
||||||
|
func test_signal_fires_after_delay() -> void:
|
||||||
|
var subject := _create_subject()
|
||||||
|
subject.event.triggered.connect(_on_event_triggered)
|
||||||
|
|
||||||
|
subject.do_something()
|
||||||
|
|
||||||
|
# Ensure signal fires before test ends
|
||||||
|
get_tree().process_frame.connect(_on_frame_processed)
|
||||||
|
yield(get_tree(), "process_frame") # Wait for signal
|
||||||
|
|
||||||
|
assert_true(_signal_received)
|
||||||
|
|
||||||
|
func _on_frame_processed() -> void:
|
||||||
|
_on_event_triggered.call_deferred()
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Scene Loading in Tests Fails
|
||||||
|
|
||||||
|
**Problem:** Godot scenes loaded via `load("res://...")` may not find their resources.
|
||||||
|
|
||||||
|
**Solution:** Use absolute paths or ensure test assets are in proper location:
|
||||||
|
|
||||||
|
```gdscript
|
||||||
|
# Bad: Relative path that breaks in tests
|
||||||
|
var mob_scene := load("enemy_mob.tscn").instantiate()
|
||||||
|
|
||||||
|
# Good: Absolute resource path
|
||||||
|
var mob_scene := load("res://src/enemies/enemy_mob.tscn").instantiate()
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. Random Behavior Causes Flaky Tests
|
||||||
|
|
||||||
|
**Problem:** Tests pass sometimes but fail others due to randomness (e.g., particle emission).
|
||||||
|
|
||||||
|
**Solution:** Disable randomness in test environment:
|
||||||
|
|
||||||
|
```gdscript
|
||||||
|
# At start of test, seed RNG for reproducibility
|
||||||
|
Rand.randi = func() -> int: return 42 # Fixed value for testing
|
||||||
|
|
||||||
|
# Or disable randomness for specific systems
|
||||||
|
var projectile := Projectile.new()
|
||||||
|
projectile.random_variation_enabled = false
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4. Physics Tunneling in Collision Tests
|
||||||
|
|
||||||
|
**Problem:** Fast-moving projectiles miss collisions when tested with static enemies.
|
||||||
|
|
||||||
|
**Solution:** Use multiple physics frames or smaller time steps:
|
||||||
|
|
||||||
|
```gdscript
|
||||||
|
func test_high_velocity_collision_detection() -> void:
|
||||||
|
var projectile := _create_goose_with_velocity(200.0)
|
||||||
|
|
||||||
|
# Run multiple physics frames for collision detection
|
||||||
|
for _ in range(5):
|
||||||
|
get_tree().physics_ticks_processed = 1
|
||||||
|
get_tree().process_frame()
|
||||||
|
|
||||||
|
assert_true(_collision_detected)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 5. Signal Connections Leak Between Tests
|
||||||
|
|
||||||
|
**Problem:** Test A's signal handlers remain active when Test B runs.
|
||||||
|
|
||||||
|
**Solution:** Disconnect signals at test end:
|
||||||
|
|
||||||
|
```gdscript
|
||||||
|
func cleanup_test(subject: Node, signal_name: String) -> void:
|
||||||
|
subject.signal_removed.connect(_disconnect_signals)
|
||||||
|
|
||||||
|
# Clear all signals from subject
|
||||||
|
var signals = subject.get_signal_list()
|
||||||
|
for s in signals:
|
||||||
|
if s.is_connected(func):
|
||||||
|
s.disconnect(func)
|
||||||
|
|
||||||
|
# Call cleanup at end of each test function
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## CI Integration (Optional for Indie Teams)
|
||||||
|
|
||||||
|
### GitHub Actions / GitLab CI Setup
|
||||||
|
|
||||||
|
If using a continuous integration server, add tests to build pipeline.
|
||||||
|
|
||||||
|
**Example workflow:**
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: YeetGeese Tests
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Install Godot
|
||||||
|
run: |
|
||||||
|
# Download and install Godot 4.x stable
|
||||||
|
|
||||||
|
- name: Run Tests
|
||||||
|
run: |
|
||||||
|
godot --path . --headless tests/run_all_tests.gd
|
||||||
|
```
|
||||||
|
|
||||||
|
### Local Test Runner Script
|
||||||
|
|
||||||
|
Create a script to run all tests from command line:
|
||||||
|
|
||||||
|
```gdscript
|
||||||
|
# tests/run_all_tests.gd
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
var result := 0
|
||||||
|
|
||||||
|
# Run unit tests
|
||||||
|
for file in DirAccess.get_directories() if dir_name == "core" or dir_name == "towers":
|
||||||
|
pass # Implementation depends on test runner framework
|
||||||
|
|
||||||
|
if result == 0:
|
||||||
|
print("All tests passed!")
|
||||||
|
else:
|
||||||
|
error("Some tests failed")
|
||||||
|
|
||||||
|
func _exit_tree():
|
||||||
|
quit(0)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Testing Checklist
|
||||||
|
|
||||||
|
### Before Writing Tests for New Feature
|
||||||
|
|
||||||
|
- [ ] Identify the system(s) being tested
|
||||||
|
- [ ] Determine unit vs. integration testing needs
|
||||||
|
- [ ] List expected inputs and outputs
|
||||||
|
- [ ] Identify edge cases (empty arrays, null objects, etc.)
|
||||||
|
|
||||||
|
### Test Coverage Goals
|
||||||
|
|
||||||
|
| System Type | Recommended Test Coverage |
|
||||||
|
|-------------|---------------------------|
|
||||||
|
| Core game loop | 100% (critical path) |
|
||||||
|
| Tower logic | 90%+ |
|
||||||
|
| Enemy AI states | 85%+ |
|
||||||
|
| UI displays | 80%+ |
|
||||||
|
| Utility functions | 95%+ |
|
||||||
|
|
||||||
|
### Review Checklist for AI-Generated Tests
|
||||||
|
|
||||||
|
When asking AI to generate tests, verify:
|
||||||
|
|
||||||
|
- [ ] Uses `@tool` directive for editor-only execution
|
||||||
|
- [ ] Sets up proper mock objects for isolation
|
||||||
|
- [ ] Disconnects signals at test end to prevent leaks
|
||||||
|
- [ ] Uses absolute paths for resource loading
|
||||||
|
- [ ] Handles expected error conditions gracefully
|
||||||
|
- [ ] Includes assertions for all critical behaviors
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
**AI can help with:**
|
||||||
|
- Generating boilerplate test scaffolding
|
||||||
|
- Suggesting edge cases and boundary conditions
|
||||||
|
- Writing mock implementations for complex systems
|
||||||
|
- Explaining Godot testing framework capabilities
|
||||||
|
|
||||||
|
**Remember:**
|
||||||
|
- Tests should be runnable in editor (`@tool` functions)
|
||||||
|
- Keep tests focused on one behavior per function
|
||||||
|
- Disconnect signals to prevent cross-test contamination
|
||||||
|
- Use absolute paths for resource loading in tests
|
||||||
|
- Document test intent with clear, descriptive names
|
||||||
|
|
||||||
|
For more details, see `AI_HELP.md` for prompt templates when working with AI assistants on testing tasks.
|
||||||
@@ -0,0 +1,547 @@
|
|||||||
|
# Skills, Agents, and Commands Reference
|
||||||
|
|
||||||
|
This document provides a reference for AI assistants working with YeetGeese. It describes available capabilities, when to use them, and best practices for interaction.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
1. [Available Skills](#available-skills)
|
||||||
|
2. [Agent Types & Use Cases](#agent-types--use-cases)
|
||||||
|
3. [Command Reference](#command-reference)
|
||||||
|
4. [Prompt Templates](#prompt-templates)
|
||||||
|
5. [Best Practices](#best-practices)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Available Skills
|
||||||
|
|
||||||
|
### `customize-opencode`
|
||||||
|
|
||||||
|
**Purpose:** Configure and modify the AI assistant's own settings, including:
|
||||||
|
- `opencode.json`, `opencode.jsonc` files
|
||||||
|
- `.opencode/` configuration directory
|
||||||
|
- `~/.config/opencode/` user settings
|
||||||
|
- Agent definitions (subagents, skills, plugins, MCP servers)
|
||||||
|
- Permission rules
|
||||||
|
|
||||||
|
**When to use:** When configuring the AI assistant itself, not for project code.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```
|
||||||
|
"Adjust the maximum context window size for this session."
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `make-pr` — Pull Request Creation (Gitea Web UI)
|
||||||
|
|
||||||
|
**Purpose:** On Gitea, pull requests are created directly via the web interface at:
|
||||||
|
`https://gitea.letteka.com/letteka/YeetGeese/pulls/new/move_docs`
|
||||||
|
|
||||||
|
**How to use on Gitea:**
|
||||||
|
1. Push changes to a branch (e.g., `move_docs`)
|
||||||
|
2. Visit the URL above or navigate via Gitea web UI
|
||||||
|
3. Create PR with descriptive title and body
|
||||||
|
4. Include testing strategies and validation status in description
|
||||||
|
|
||||||
|
**When to use:**
|
||||||
|
- When ready to submit a pull request from your current branch
|
||||||
|
- Before pushing code that requires peer review
|
||||||
|
- To ensure all changes are properly documented and validated
|
||||||
|
- When creating PRs for features, fixes, or refactoring
|
||||||
|
|
||||||
|
**Best practices for Gitea PRs:**
|
||||||
|
- Use descriptive titles following conventional commits format
|
||||||
|
- Include file-by-file change summary in PR body
|
||||||
|
- List testing strategies: unit tests, integration tests, manual QA
|
||||||
|
- Mention any validation already performed locally
|
||||||
|
- Flag known issues or limitations clearly
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Agent Types & Use Cases
|
||||||
|
|
||||||
|
### `code-gen` — Code Generation
|
||||||
|
|
||||||
|
**Purpose:** Write new code, implement features, create boilerplate.
|
||||||
|
|
||||||
|
**Capabilities:**
|
||||||
|
- GDScript 4 implementation
|
||||||
|
- Scene graph construction descriptions
|
||||||
|
- Resource file (`.tres`) schema design
|
||||||
|
- Signal declarations and connections
|
||||||
|
- Method implementations matching project conventions
|
||||||
|
|
||||||
|
**When to use:**
|
||||||
|
- Implementing a new tower or projectile type
|
||||||
|
- Adding a feature to existing systems
|
||||||
|
- Creating boilerplate for common patterns
|
||||||
|
- Writing unit tests
|
||||||
|
|
||||||
|
**Input required:**
|
||||||
|
- Target file path or node description
|
||||||
|
- Desired behavior/goal
|
||||||
|
- Any constraints (e.g., "must use Resource for stats")
|
||||||
|
|
||||||
|
**Example prompt:**
|
||||||
|
```
|
||||||
|
"Create a GDScript 4 class `ImpactEffect.gd` that extends Area2D. It should:
|
||||||
|
1. Detect collision with enemies in _body_entered
|
||||||
|
2. Emit signal 'effect_triggered' with damage and target Node2D
|
||||||
|
3. Apply random color variation to its texture
|
||||||
|
4. Set lifespan to 0.8 seconds
|
||||||
|
5. Include comments explaining each step"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `debug-helper` — Debugging Assistance
|
||||||
|
|
||||||
|
**Purpose:** Analyze errors, suggest debugging strategies, interpret profiler output.
|
||||||
|
|
||||||
|
**Capabilities:**
|
||||||
|
- Error message interpretation (Godot/IDE/compiler)
|
||||||
|
- Suggesting debugging tool usage (Scene Debugger, Physics Monitor)
|
||||||
|
- Profiling tips and bottleneck identification
|
||||||
|
- Common pitfall recognition (e.g., physics tunneling, navmesh gaps)
|
||||||
|
|
||||||
|
**When to use:**
|
||||||
|
- When an error occurs during implementation
|
||||||
|
- When code behaves unexpectedly
|
||||||
|
- When performance issues appear in profiler
|
||||||
|
|
||||||
|
**Input required:**
|
||||||
|
- Error message or log output
|
||||||
|
- Relevant file paths and line numbers if available
|
||||||
|
- Brief description of expected vs. actual behavior
|
||||||
|
|
||||||
|
**Example prompt:**
|
||||||
|
```
|
||||||
|
"This tower stops firing after 30 seconds even though fire_rate is set to 1.0.
|
||||||
|
Error: 'get_tree()' returned null at runtime. Debug it."
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `refactor-assistant` — Refactoring Support
|
||||||
|
|
||||||
|
**Purpose:** Break up large scripts, improve code organization, add documentation.
|
||||||
|
|
||||||
|
**Capabilities:**
|
||||||
|
- Splitting monolithic scripts into smaller nodes
|
||||||
|
- Extracting methods into separate components
|
||||||
|
- Adding documentation and type hints
|
||||||
|
- Applying project conventions consistently
|
||||||
|
|
||||||
|
**When to use:**
|
||||||
|
- Scripts are growing beyond 150 lines
|
||||||
|
- Multiple unrelated behaviors in one node
|
||||||
|
- Need to improve readability before review
|
||||||
|
|
||||||
|
**Input required:**
|
||||||
|
- File path or code snippet
|
||||||
|
- Refactoring goal (e.g., "split into state machines")
|
||||||
|
- Target organization style
|
||||||
|
|
||||||
|
**Example prompt:**
|
||||||
|
```
|
||||||
|
"Refactor this 400-line EnemyMob.gd into smaller components:
|
||||||
|
1. Extract navigation logic to NavigationComponent
|
||||||
|
2. Extract attack behavior to AttackState
|
||||||
|
3. Keep health/currency handling in base class
|
||||||
|
4. Add documentation comments for each section"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `test-generator` — Test Generation
|
||||||
|
|
||||||
|
**Purpose:** Create unit tests for game logic systems.
|
||||||
|
|
||||||
|
**Capabilities:**
|
||||||
|
- Writing Godot test cases using `@tool` functions
|
||||||
|
- Setting up mock scenes and signals
|
||||||
|
- Testing Resource-based stat changes
|
||||||
|
- Validating collision detection and hit calculations
|
||||||
|
|
||||||
|
**When to use:**
|
||||||
|
- After implementing core logic that should be validated
|
||||||
|
- Before refactoring (to preserve behavior)
|
||||||
|
- When adding critical game mechanics
|
||||||
|
|
||||||
|
**Input required:**
|
||||||
|
- System or function being tested
|
||||||
|
- Expected inputs and outputs
|
||||||
|
- Edge cases to cover
|
||||||
|
|
||||||
|
**Example prompt:**
|
||||||
|
```
|
||||||
|
"Create tests for TowerBase._can_build_at(). Test:
|
||||||
|
1. Returns true in valid tower placement zones
|
||||||
|
2. Returns false inside enemy navmesh
|
||||||
|
3. Returns false when grid coordinate exceeds bounds
|
||||||
|
4. Returns false if parent node is null"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `design-patterns` — Design Pattern Suggestions
|
||||||
|
|
||||||
|
**Purpose:** Recommend architecture patterns suited to specific problems.
|
||||||
|
|
||||||
|
**Capabilities:**
|
||||||
|
- Suggesting ECS for complex entity management
|
||||||
|
- Recommending FSM for enemy AI states
|
||||||
|
- Proposing event-driven systems for decoupled components
|
||||||
|
- Advising on data-oriented vs. object-oriented design
|
||||||
|
|
||||||
|
**When to use:**
|
||||||
|
- Before implementing a new system
|
||||||
|
- When performance becomes an issue
|
||||||
|
- When refactoring existing code
|
||||||
|
|
||||||
|
**Input required:**
|
||||||
|
- Problem description (e.g., "I need many entities with simple movement")
|
||||||
|
- Performance constraints if any
|
||||||
|
- Preferred Godot nodes or patterns already in use
|
||||||
|
|
||||||
|
**Example prompt:**
|
||||||
|
```
|
||||||
|
"I'm building a system for 50+ projectiles that need to track targets, apply damage, and handle collision.
|
||||||
|
Current approach: individual RigidBody2D for each projectile.
|
||||||
|
What pattern would scale better?"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `balance-helper` — Balance Analysis
|
||||||
|
|
||||||
|
**Purpose:** Analyze math relationships and suggest tuning adjustments.
|
||||||
|
|
||||||
|
**Capabilities:**
|
||||||
|
- Calculating damage per second (DPS) from fire rate and projectile stats
|
||||||
|
- Estimating kill time based on enemy HP and total damage sources
|
||||||
|
- Suggesting resource stat ranges that preserve balance space
|
||||||
|
- Identifying scaling relationships between tower levels
|
||||||
|
|
||||||
|
**When to use:**
|
||||||
|
- Before adding new towers/enemies with different power levels
|
||||||
|
- When gameplay feels too easy or difficult
|
||||||
|
- During tuning phase of wave progression
|
||||||
|
|
||||||
|
**Input required:**
|
||||||
|
- Current stats (damage, fire rate, enemy HP)
|
||||||
|
- Desired behavior description (e.g., "kill time should scale with tier")
|
||||||
|
- Resource file structure if applicable
|
||||||
|
|
||||||
|
**Example prompt:**
|
||||||
|
```
|
||||||
|
"Current: goose damage=15, fire_rate=1.0/s, chicken HP=80.
|
||||||
|
Tower Level 2 has 4 geese. Calculate total DPS and suggest enemy HP range
|
||||||
|
for level-appropriate difficulty (aim for ~30s wave duration)."
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `level-design-helper` — Level Design Assistance
|
||||||
|
|
||||||
|
**Purpose:** Plan layout, progression, and pacing for levels or zones.
|
||||||
|
|
||||||
|
**Capabilities:**
|
||||||
|
- Wave progression suggestions (spawn rates, path complexity)
|
||||||
|
- Tower placement zone recommendations
|
||||||
|
- Pacing analysis for difficulty curves
|
||||||
|
- Zone-based checkpoint design
|
||||||
|
|
||||||
|
**When to use:**
|
||||||
|
- Before creating a new level or wave sequence
|
||||||
|
- When gameplay feels too repetitive or frustrating
|
||||||
|
- During playtesting feedback analysis
|
||||||
|
|
||||||
|
**Input required:**
|
||||||
|
- Level description (size, available zones)
|
||||||
|
- Current wave structure if any
|
||||||
|
- Difficulty curve goals
|
||||||
|
|
||||||
|
**Example prompt:**
|
||||||
|
```
|
||||||
|
"I have 4 tower placement zones along a path with 3 turns.
|
||||||
|
Current waves: linear difficulty increase.
|
||||||
|
Suggest a progression that introduces new mechanics at zone boundaries."
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `doc-generator` — Documentation Generation
|
||||||
|
|
||||||
|
**Purpose:** Create documentation from existing code or planning data.
|
||||||
|
|
||||||
|
**Capabilities:**
|
||||||
|
- Generating API docs from GDScript class structures
|
||||||
|
- Writing changelogs from commit history
|
||||||
|
- Creating release notes with feature summaries
|
||||||
|
- Producing onboarding guides from project structure
|
||||||
|
|
||||||
|
**When to use:**
|
||||||
|
- Before releasing a version
|
||||||
|
- After implementing a major feature set
|
||||||
|
- When new team members join the project
|
||||||
|
|
||||||
|
**Input required:**
|
||||||
|
- Source code or commit messages
|
||||||
|
- Feature list for changelog entries
|
||||||
|
- Target audience (developers, players)
|
||||||
|
|
||||||
|
**Example prompt:**
|
||||||
|
```
|
||||||
|
"Generate API documentation for the WaveRunner system:
|
||||||
|
1. Describe each public method and its parameters
|
||||||
|
2. List signals emitted with their payloads
|
||||||
|
3. Document the Resource dependencies
|
||||||
|
4. Include usage examples"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `onboarding-guide` — Onboarding Documentation
|
||||||
|
|
||||||
|
**Purpose:** Create setup tutorials and getting-started guides for new developers.
|
||||||
|
|
||||||
|
**Capabilities:**
|
||||||
|
- Environment setup instructions (OS-specific)
|
||||||
|
- Project structure explanation
|
||||||
|
- Editor scene loading order
|
||||||
|
- Common first tasks with examples
|
||||||
|
|
||||||
|
**When to use:**
|
||||||
|
- Before bringing on new team members
|
||||||
|
- When updating project structure significantly
|
||||||
|
- For release candidate documentation
|
||||||
|
|
||||||
|
**Input required:**
|
||||||
|
- Target OS versions supported
|
||||||
|
- Required Godot version and plugins
|
||||||
|
- Team conventions to teach
|
||||||
|
|
||||||
|
**Example prompt:**
|
||||||
|
```
|
||||||
|
"Write an onboarding guide for a new developer joining YeetGeese:
|
||||||
|
1. Explain folder structure (src/core, src/towers, etc.)
|
||||||
|
2. Show how to run the game from main.tscn
|
||||||
|
3. Describe the tower placement workflow
|
||||||
|
4. List common commands for debugging"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `api-specs` — API Specification
|
||||||
|
|
||||||
|
**Purpose:** Define external interfaces and save/load contracts.
|
||||||
|
|
||||||
|
**Capabilities:**
|
||||||
|
- Defining save file format schemas
|
||||||
|
- Documenting modding API endpoints
|
||||||
|
- Specifying network message protocols
|
||||||
|
- Creating serialization guides
|
||||||
|
|
||||||
|
**When to use:**
|
||||||
|
- Before implementing persistent storage
|
||||||
|
- When enabling mod support
|
||||||
|
- For multiplayer networking design
|
||||||
|
|
||||||
|
**Input required:**
|
||||||
|
- Interface type (save format, mod API, network protocol)
|
||||||
|
- Required functionality list
|
||||||
|
- Platform constraints
|
||||||
|
|
||||||
|
**Example prompt:**
|
||||||
|
```
|
||||||
|
"Define a save file format for YeetGeese:
|
||||||
|
1. Must store unlocked towers and their levels
|
||||||
|
2. Must include currency progress and wave number
|
||||||
|
3. Use Godot Resource serialization (.tres files)
|
||||||
|
4. Include version field for backward compatibility"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Command Reference
|
||||||
|
|
||||||
|
### Code Writing Commands
|
||||||
|
|
||||||
|
| Command | When to use |
|
||||||
|
|---------|-------------|
|
||||||
|
| `create file <path>` | For new classes, scenes, or resource files |
|
||||||
|
| `modify file <path>` | For adding methods or changing existing code |
|
||||||
|
| `describe scene <path>` | To generate scene tree descriptions for AI understanding |
|
||||||
|
|
||||||
|
### Review Commands
|
||||||
|
|
||||||
|
| Command | When to use |
|
||||||
|
|---------|-------------|
|
||||||
|
| `review code <path>` | For checking convention compliance |
|
||||||
|
| `optimize performance <scope>` | For profiling suggestions in specific areas |
|
||||||
|
| `debug error <message>` | For interpreting errors and suggesting fixes |
|
||||||
|
|
||||||
|
### Documentation Commands
|
||||||
|
|
||||||
|
| Command | When to use |
|
||||||
|
|---------|-------------|
|
||||||
|
| `generate docs` | For API documentation from code |
|
||||||
|
| `write changelog` | After implementing features or fixing bugs |
|
||||||
|
| `create onboarding guide` | For new developer setup instructions |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prompt Templates
|
||||||
|
|
||||||
|
### Feature Implementation Template
|
||||||
|
|
||||||
|
```
|
||||||
|
Context: I'm implementing [feature name] in [system/file].
|
||||||
|
Current state: [brief description of existing code/structure]
|
||||||
|
Goal: [what this feature should do]
|
||||||
|
Constraints: [any restrictions like "must use Resource" or "no UI changes"]
|
||||||
|
|
||||||
|
Please provide:
|
||||||
|
1. Complete, runnable GDScript 4 code with comments
|
||||||
|
2. Scene hierarchy description if new scenes are needed
|
||||||
|
3. Any new Resources (.tres) and their structure
|
||||||
|
4. Signal declarations and connection points
|
||||||
|
```
|
||||||
|
|
||||||
|
### Debugging Template
|
||||||
|
|
||||||
|
```
|
||||||
|
Error context: [where the error occurred]
|
||||||
|
Error message: [full error output]
|
||||||
|
Expected behavior: [what should have happened]
|
||||||
|
Actual behavior: [what actually happened]
|
||||||
|
Debug steps tried: [what you've already attempted]
|
||||||
|
|
||||||
|
Please provide:
|
||||||
|
1. Root cause analysis
|
||||||
|
2. Minimal fix with explanation
|
||||||
|
3. Prevention strategy for future occurrences
|
||||||
|
```
|
||||||
|
|
||||||
|
### Refactoring Template
|
||||||
|
|
||||||
|
```
|
||||||
|
Current code: [file path or snippet]
|
||||||
|
Issues to address: [e.g., "too monolithic", "missing docs"]
|
||||||
|
Refactoring goals: [what you want to achieve]
|
||||||
|
Target patterns: [any existing patterns to match]
|
||||||
|
|
||||||
|
Please provide:
|
||||||
|
1. Proposed refactored structure
|
||||||
|
2. New files and their responsibilities
|
||||||
|
3. Migration steps for existing code
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
### 1. Always Provide Context First
|
||||||
|
|
||||||
|
Before asking for code, share:
|
||||||
|
- The relevant file path or node description
|
||||||
|
- The GDScript version being used (Godot 4.x)
|
||||||
|
- Key related signals and methods already in place
|
||||||
|
|
||||||
|
**Good:**
|
||||||
|
```
|
||||||
|
"Create an ImpactEffect.gd extending Area2D with these existing methods:
|
||||||
|
- _body_entered(var area): called on collision
|
||||||
|
- emit_signal('effect_triggered', damage, target)"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Bad:**
|
||||||
|
```
|
||||||
|
"I need a collision effect for projectiles."
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Specify Godot 4 Conventions
|
||||||
|
|
||||||
|
When requesting code, remind AI of conventions:
|
||||||
|
- Use typed signals: `signal health_changed(new_health: float)`
|
||||||
|
- Prefer `@onready` over `$` in scripts
|
||||||
|
- Type variables and return values consistently
|
||||||
|
- Keep scenes modular (compose behavior across nodes)
|
||||||
|
|
||||||
|
### 3. Reference Existing Architecture
|
||||||
|
|
||||||
|
When implementing features, reference existing patterns:
|
||||||
|
```
|
||||||
|
"Implement this using the same pattern as TowerBase.fire_at():
|
||||||
|
- Use projectile_res.instantiate() for new goose projectiles
|
||||||
|
- Spawn from $ProjectileSpawner.global_position
|
||||||
|
- Add to parent tree immediately after instantiation"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Specify Resource Dependencies Early
|
||||||
|
|
||||||
|
If your project uses Resources for balance:
|
||||||
|
```
|
||||||
|
"Create a Resource-based stats file for this tower:
|
||||||
|
- Fields: damage (float), fire_rate (float), cooldown_reduction (float)
|
||||||
|
- Make it loadable as a Godot Resource (.tres)
|
||||||
|
- Show how the tower reads its stats on _ready()"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Ask for Complete, Runnable Code
|
||||||
|
|
||||||
|
When requesting implementations:
|
||||||
|
```
|
||||||
|
"Return complete, runnable GDScript 4 code with:"
|
||||||
|
"- Comments explaining each major section"
|
||||||
|
"- Type annotations for all variables and methods"
|
||||||
|
"- Signal declarations at top of class"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
**Use these skills strategically:**
|
||||||
|
- `code-gen`: For new features and boilerplate
|
||||||
|
- `debug-helper`: When errors occur or behavior is wrong
|
||||||
|
- `refactor-assistant`: Before code grows unmanageable
|
||||||
|
- `test-generator`: After implementing critical logic
|
||||||
|
- `design-patterns`: When architecture becomes unclear
|
||||||
|
|
||||||
|
**Always provide:**
|
||||||
|
- File paths, node names, and Godot version context
|
||||||
|
- Desired behavior in terms of existing patterns
|
||||||
|
- Constraints (Resource usage, signal conventions)
|
||||||
|
|
||||||
|
**When in doubt:** Reference `AI_HELP.md` for project-specific conventions before asking questions.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Note About `make-pr` Skill Availability
|
||||||
|
|
||||||
|
The **`make-pr`** skill (`.opencode/skills/make-pr.json`) is available for use! This skill will:
|
||||||
|
- Generate comprehensive, human-readable PR descriptions
|
||||||
|
- List testing strategies for each change area
|
||||||
|
- Validate changes before PR creation
|
||||||
|
- Format PR descriptions with clear sections
|
||||||
|
|
||||||
|
**When to use `make-pr` skill:**
|
||||||
|
- When ready to submit a PR from your current branch (any platform)
|
||||||
|
- Before pushing code that requires peer review
|
||||||
|
- To ensure all changes are properly documented and validated
|
||||||
|
- When creating PRs for features, fixes, or refactoring
|
||||||
|
|
||||||
|
The skill automatically adapts to your hosting platform:
|
||||||
|
- **GitHub:** Creates PR via API with comprehensive descriptions
|
||||||
|
- **Gitea:** Falls back to web UI creation (URL provided above)
|
||||||
|
|
||||||
|
**Prompt example:**
|
||||||
|
```
|
||||||
|
"Create a pull request from move_docs to develop. The changes include moving
|
||||||
|
all AI documentation files into an 'AI Docs' folder with organized structure."
|
||||||
|
```
|
||||||
|
|
||||||
+1445
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user