Adding the bones of the drafting system by removing the wall and siege towers from the base set and adding them temporarily as choices for the draft. Also adding Project_Context and Project_Roadmap documents to use with Claude

This commit is contained in:
Matt F 2026-06-24 00:15:17 -07:00
parent 1d03689dad
commit 3ceebed8f6
22 changed files with 1060 additions and 431 deletions

97
Project_Context.md Normal file
View file

@ -0,0 +1,97 @@
# Unity Tower Defense — Project Context
## Purpose
A snapshot of **where the project is and how it works** — the authoritative reference for current architecture, implemented systems, conventions, and known debt. It pairs with [`Project_Roadmap.md`](Project_Roadmap.md), which is the forward-looking plan. When the two disagree, this document describes *what exists today*; the roadmap describes *what's planned next*.
Last substantial update: 2026-06-23.
---
## Game overview
A **co-op tower-defense / roguelike hybrid** for up to 9 players.
- **Maze defense (Wintermaul-style):** players build towers to force enemies along a longer path through their own zone. Lives are a **shared pool**; gold is **per-player**.
- **Roguelike layer (now core to the design):** every player starts with the **same three towers** and builds out a personal "deck"/"build" through a **3-option draft** presented at match start and after every wave. Choices span new towers, systemic upgrades, builder abilities, enemy debuffs, and relic quests. See [`Project_Roadmap.md`](Project_Roadmap.md) for the full design.
- **Target platform:** Steam (Windows / Linux / Steam Deck).
- **Visual direction (aspirational):** "painted tabletop miniature" look with Spider-Verse-style stepped (on-2s) enemy animation. Current visuals are **placeholder** (primitive meshes / cones, sourced creature models).
## Engine & tech
Unity **6.4 (6000.4.4f1)**, URP, IL2CPP, .NET Standard 2.1, Linear color space, new Input System, Force Text serialization. Netcode: **Netcode for GameObjects (NGO) 2.x**.
## Repository & collaboration
- Self-hosted **Forgejo**: `https://git.marlboro-bc.duckdns.org/yeahweregames/UnityTowerDefense` (git remote **`origin`**). A legacy GitHub mirror exists as remote **`github`**.
- **Multiple contributors** work in parallel on feature branches merged to `main` via PRs. Expect `main` to move between sessions; rebase/branch off the latest.
- **IP guardrail:** the prototype uses Games-Workshop-adjacent placeholder content (race names, sourced models). The repo stays **private**, no public builds/demos, until that content is replaced. Maintain a plain-text asset manifest of IP-derived assets to swap before any public release.
---
## Architecture & conventions
- **Server-authoritative gameplay; local-only UI/visual state.** Only gameplay-meaningful state is networked. Selection, placement ghosts, animation, and the paint cursor are client-local.
- **Data-driven via ScriptableObjects:** `TowerDefinition`, `EnemyDefinition`, `WaveDefinition`, `RaceDefinition`, `GoldConfig`, `BuffDefinition`/`BuffCategory`, `DraftOption` (+ `NewTowerDraftOption`). Designers tune stats in assets, not code.
- **Per-player state pattern:** `NetworkBehaviour`s on the **Player prefab** with a static `GetForClient(clientId)` / `Local` registry. Current set: `PlayerGoldManager`, `PlayerMatchState`, `PlayerBuffManager`, `PlayerTowerDeck`, `PlayerDraft`.
- **Networked identifiers are catalog indices.** `TowerTypeId` indexes `TowerPlacementManager.towerDefinitions[]`; `DraftOptionId` indexes `DraftPool`. Stable **within a match**, not across sessions — cross-match persistence will need stable IDs (asset GUID or a serialized StableId).
- **Namespaces:** `TD.Core` (enums, palettes, grid math), `TD.Gameplay` (builder, placement, match/wave/pathfinding state, economy, enemies, deck), `TD.Gameplay.Draft` (draft system), `TD.Combat` (TowerCombat/Projectile), `TD.Levels` (in-engine authoring + bake), `TD.UI`, `TD.Net`.
- **Scenes:** `MainMenu``Lobby` → a Match level (`9Player`, `Main`).
### Engineering principles (carried across sessions)
- **Debug to root cause.** No defensive workarounds or per-frame state-correcting hacks — find and fix the actual cause.
- **Restate design intent before coding.** Confirmed valuable repeatedly; prevents rework.
- **Server owns gameplay; clients render.** Authoritative state on the server, visualization derived locally on each peer.
---
## Implemented systems
### Match foundation
- `MatchState` (NetworkBehaviour scene singleton): phase (`Lobby`/`CountDown`/`Playing`/`Victory`/`Defeat`), current wave, shared lives. `PlayerMatchState` (per-player): slot allocation, race selection, ready state. Authoritative client-id → `PlayerSlot` mapping.
### Combat & towers
- `TowerCombat` (server targeting loop; `OnTargetAcquired`/`OnTargetLost`/`OnFire` events for future animation), `Projectile`, hitscan + projectile paths, Single/Splash/Chain target types, damage types, range indicator. **Air-targeting** done: `GroundedOnly` towers skip flying enemies. Range checks are **3D**.
- `TowerPlacementManager` (server-validated placement queue), `Builder` build queue with staged construction/pause/cancel/refund, `BuildSiteVisual` ghosts, owner tinting, RTS selection.
### Enemies & pathfinding
- `EnemyHealth` (replicated HP, damage types, `IsFlying`, held state), `EnemyStatus` (lingering effects: slow/DoT), `EnemyMovement` (A* path following, zone-leak attribution, death/sink sequence).
- `PathfindingService` (A* on the runtime walkability grid, octile heuristic, corner-cut prevention, line-of-sight path smoothing; re-paths on tower placement/removal).
- **Flying enemies:** path on the **baked terrain grid** (`LevelLoader.IsBaseWalkable`) so they soar over towers; compute once, never re-path; spawn elevated by `EnemyDefinition.FlightHeight`.
- Content: ~10 enemy definitions/prefabs (Crystal Golem / Cyclops / Ent variants, Undead Drake = the flying test enemy), 10 wave definitions.
### Lobby, connection & races
- `MainMenu` + `Lobby` scenes; Direct-IP via `NetworkBootstrap` (the single seam for the deferred Steam swap) + `UnityTransport`; `LobbyService`, `SessionFlow`; **Quick Start** dev shortcut.
- Race data + selection UI: `RaceDefinition`, `RaceRegistry`, 16-slot `RaceId`, `RaceSelectionOverlay`. Two placeholder races (both use the default builder). **Note:** "Race" is the code term; the roguelike design calls this concept "Builder" — naming reconciliation is an open decision.
### Economy
- `PlayerGoldManager` (per-player, server-validated spend/award), `GoldConfig` (starting gold, per-wave kill rewards, completion + no-leak bonuses), `WaveManager` orchestration (prep countdown, per-zone spawning, kill-gold attribution, lives pool, Victory/Defeat).
### Roguelike — tower deck & draft (the current focus)
- **`PlayerTowerDeck`** (per-player): the growable set of unlocked `TowerTypeId`s. Starts at the base set (seeded by `WaveManager` from `TowerPlacementManager.startingDeck`); placement is gated server-side (`TowerNotInDeck` rejection); the HUD build grid reads the local deck and rebuilds live on change. **Merged to `main`.**
- **Draft system (Slice 1 — spine + "new tower"):** `DraftOption` (abstract SO) / `NewTowerDraftOption`, `DraftPool` (scene singleton catalog), `PlayerDraft` (per-player offered set + pick/buy-roll RPCs), `DraftService` (server weighted-random generation + offer/auto-resolve). The **prep phase is the draft window** (wave 1's prep = the match-start draft); unpicked drafts auto-resolve at prep end. Gold **"Buy Roll"** purchases an extra roll any time. Non-modal HUD overlay. **On branch `feature/draft-system`, verified working in-engine; pending commit/merge as of session end.**
- Three base towers exist as data: **Basic Arrow** (ground+air single-target), **Siege Cannon** (ground-only splash), **Wall** (2×2, no damage, maze-shaping). *(Coworkers have begun replacing the placeholder cube visuals with cones.)*
### Paint system (PAUSED)
- In-match paint (R/G/B + Reset) recolors owned towers and drives effects (Red=Splash, Green=Poison, Blue=Cold), server-authoritative. **Frozen** pending the roguelike reconciliation decision (it overlaps with systemic damage-type upgrades).
### Level authoring
- In-engine `TD.Levels` authoring volumes (player zones, spawners, leak exits, goals) + `LevelData` + a bake pipeline producing walkability/placement/owner grids.
### HUD & dev tools
- `HUDController` (UI Toolkit): gold/wave/lives/leaks, scoreboard, minimap, selection portrait + context panel, build/paint command grid, build progress, match-end overlay, chat, buff menu, and the new **draft overlay**.
- `DevWaveControls`: **F9 / "Force Next Wave"**, **F8 / "Grant Next Tower"** (dev stand-in for deck growth).
---
## Known placeholders & technical debt
- **Visuals are placeholder** throughout (primitive/cone towers, sourced enemy models). See roadmap art TODOs.
- **Enemies lack idle animation support** — needs adding across all enemy prefabs.
- **Tower footprint visuals don't fill their 2×2 space** — the cone/mesh sits centered and reads smaller than the tile area it occupies; should visually reflect the full footprint.
- **Two redundant tower lists:** `TowerPlacementManager.towerDefinitions[]` (by-index catalog) and `TowerRegistry.definitions[]` (by-name, for instance resolution). Candidate for consolidation.
- **Catalog index 0 is a reserved sentinel** (valid `TowerTypeId`s start at 1) — easy to forget when wiring the catalog in the inspector.
- **Catalog-index identifiers aren't session-stable** — blocks cross-match persistence until a stable ID is added.
- **Paint system frozen**; **Race vs Builder** naming unresolved; the gold **"Buy Roll available any time"** rule is provisional and may change.
- **Stubbed/unbuilt:** tower Upgrade/Sell actions (HUD buttons disabled), enemy resistances/weaknesses, in-match race-pick countdown.