commit e68f126f32694ab0ca1df0d750f2da25e943a762 Author: Andrew Kettel Date: Thu Aug 27 12:44:09 2026 -0700 Initial checkin diff --git a/.gitea/workflows/export-check.yml b/.gitea/workflows/export-check.yml new file mode 100644 index 0000000..950d67d --- /dev/null +++ b/.gitea/workflows/export-check.yml @@ -0,0 +1,14 @@ +name: Verify Export Config +on: workflow_dispatch +jobs: + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Download export templates (cached) + run: | + mkdir -p .godot/export_templates + wget -qO- https://github.com/godotengine/godot/releases/download/4.3-stable/Godot_v4.3-stable_export_templates.tpz \ + | tar xzf - -C .godot/export_templates --strip-components=1 + - name: Validate project compiles cleanly + run: godot --headless --quit-after-editor-checks 2>&1 | tee editor.log diff --git a/.gitea/workflows/lint.yml b/.gitea/workflows/lint.yml new file mode 100644 index 0000000..dfca95b --- /dev/null +++ b/.gitea/workflows/lint.yml @@ -0,0 +1,11 @@ +name: GDScript Lint +on: [push, pull_request] +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Run gd-lint + run: | + pipx install godot-lint + gd_lint src/ --error-on-warn --ignore=core/,tools/ diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml new file mode 100644 index 0000000..786a034 --- /dev/null +++ b/.gitea/workflows/test.yml @@ -0,0 +1,14 @@ +name: Run Tests +on: [push] +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Godot CLI + run: | + wget -q https://github.com/godotengine/godot/releases/download/4.3-stable/Godot_v4.3-stable_linux.x86_64.zip + unzip -qq *.zip -d /tmp/ && sudo cp "/tmp/Godot v4.3 stable/Godot_v4.3-stable_linux.x86_64" /usr/local/bin/godot && chmod +x /usr/local/bin/godot + - name: Run headless tests + run: | + godot --headless --script res://tests/run_tests.gd --quit-after-tests diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c58b7d --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +# Auto-generated by Godot +.godot/ +*.import +*.gdignore +export_templates/ + +# IDE & OS +.vscode/ +.idea/ +Thumbs.db +desktop.ini + +# Build output (keep out of src/) +bin/ +osu!/ diff --git a/AI_HELP.md b/AI_HELP.md new file mode 100644 index 0000000..9ca1978 --- /dev/null +++ b/AI_HELP.md @@ -0,0 +1,25 @@ + +# How to Ask for Help on YeetGeese + +When prompting an AI about this project, include: +1. **Godot version:** "Godot 4.x" (use GDScript 4 syntax: typed signals, `@onready`, match/enums) +2. **Node context:** e.g., "`TowerBase.gd` extending `Node2D` with a child `ProjectileSpawner` Marker2D" +3. **Goal + constraint:** "Make fire rate scale with tower level without hardcoding values." + +## Coding Conventions We Follow +- Prefer `Resource`-backed stats over exported hardcoded numbers where balance changes are expected. +- Use named signals: `signal damage_dealt(amount: int)`, `signal mob_killed(currency_reward: int)` +- Keep scenes small; compose behavior across nodes rather than one 1000-line script. +- Always type variables and return values in GDScript 4 style. + +## Prompt Templates That Work Well +- "Write a GDScript 4 `find_target()` that picks the enemy furthest along its path from this tower, using `_get_enemies_in_range() -> Array[EnemyMob]`." +- "Refactor this hardcoded fire rate into a `TowerStats.res` Resource and show how the tower reads it on spawn." +- "Implement a placement preview cursor that snaps to a grid and turns red where `_can_build_at()` returns false." + +## What I Expect From You (AI) +- Return complete, runnable GDScript 4 with comments explaining node setup. +- Flag any Godot 3 vs 4 API differences (e.g., `move_and_slide()` behavior, signal typing). +- If a request needs multiple scenes, describe the scene hierarchy before showing code. + +Read `ARCHITECTURE.md` for system boundaries and data flow expectations. diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 0000000..263d089 --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,29 @@ +# YeetGeese Architecture Notes + +## Core Loop +1. `WaveRunner` reads a `WaveTable` Resource → spawns enemies onto a shared `NavigationRegion2D` path. +2. Player drags a tower placement cursor → confirms → instantiates a tower scene at the grid cell. +3. Towers run a continuous `find_target()` → call `fire()` → spawn a goose projectile from `ProjectileSpawner`. +4. Geese travel to the target, deal damage, and grant currency on kill. + +## Key Design Choices +- **Stats as Resources:** Every balanceable value (damage, fire rate, enemy HP) lives in `.tres`/`.tres` files, not hardcoded. This keeps tuning non-invasive. +- **Signals over polling:** Towers emit `target_acquired`, enemies emit `health_changed`, HUD listens via `%HUD`. No frame-polling managers. +- **Placement grid decoupled from navigation:** The buildable area is a `Vector2i` grid checked against `_can_build_at()`. Pathfinding uses Godot's built-in `NavigationServer2D`. + +## Scene Expectations (for AI) +- Tower: `TowerBase.gd` (Node2D) with child `ProjectileSpawner` (Marker2D) and `TargetFinder`. +- Enemy: `EnemyMob.gd` extending `Area2D`, uses `_ready()` to assign a path via `$NavigationPath2D.bake_path_from_parent()`. +- Projectile: `Goose.gd` extending `RigidBody2D` or `CharacterBody2D` with linear velocity toward target. + +## Data Flow Example +```gdscript +# WaveRunner creates an enemy from a resource +var mob_scene = enemy_res.instantiate().tree_entered.connect(_on_mob_spawned) +add_child(mob_scene) + +# Tower acquires and fires +func fire_at(target: Node2D) -> void: + var goose := projectile_res.instantiate() as Goose + add_child(goose) + goose.yeet_from($ProjectileSpawner.global_position, target.global_position) diff --git a/README.md b/README.md new file mode 100644 index 0000000..3011e1f --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +# YeetGeese 🪿🚜 + +A farm-themed tower defense where you yeet geese at oncoming livestock. Built with Godot 4.x. + +## Quick Start +1. Open this folder in **Godot 4.3+** (stable recommended). +2. Run `main.tscn` from the editor's Play button. +3. Place towers along the animal path and watch the geese fly! + +## Folder Layout +- `src/core/` - Autoloads & global state (wave progress, currency) +- `src/towers/` - Base tower node + individual yeeter scenes +- `src/projectiles/` - Goose projectile logic & impact handling +- `src/enemies/` - Animal mob scenes & path navigation data +- `src/waves/` - `WaveTable.res` (balance file) + runner system +- `src/ui/` - HUD, placement gizmo, menus + +## For AI Assistants +Read `AI_HELP.md` before writing code. It contains our GDScript 4 conventions, scene expectations, and prompt templates tailored to this project. + +## License +TBD (placeholder for indie release) diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..e69de29