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

View file

@ -2,464 +2,125 @@
## Purpose
This document consolidates outstanding work for the Unity Tower Defense project into a single sequenced plan. It supersedes the roadmap section of the existing context summary while preserving all engineering decisions, design rules, and architectural patterns documented there. The context summary remains the authoritative source for completed-work details and design rationale.
The **forward-looking plan**: what's done, what's next, and the sequencing. Current-state architecture and the full list of implemented systems live in [`Project_Context.md`](Project_Context.md) — read that first for "how things work today." This document focuses on direction and remaining work.
The roadmap is organized in three phases:
- **Phase 1** — Functional gameplay completion. Everything required to have a playable, end-to-end tower defense match.
- **Phase 2** — Visual prototype. Proves out the painted-miniature aesthetic on a single tower and a single enemy, using sourced reference content (Space Marine + Hormagaunt) as placeholders.
- **Phase 3** — Path to commercial production. Notes on the IP swap-out, art lead hiring, and what changes when production art begins.
Last substantial update: 2026-06-23 (reorganized around the roguelike pivot).
---
## Phase 1 — Functional Gameplay Completion
## The game
This phase carries forward all pending systems from the existing context document. The order below is the recommended sequencing; some items can run in parallel where noted.
A **co-op tower-defense / roguelike hybrid** (up to 9 players, Steam). Wintermaul-style maze defense — build towers to snake enemies through your zone (shared lives, per-player gold) — fused with a roguelike draft.
### 1.1 Character pipeline mini-session (NEXT)
### Roguelike core loop
Already identified as the immediate next task in the existing roadmap. Establishes the rigging and animation pipeline that everything downstream depends on.
All players start with the **same three towers****Basic Arrow** (ground+air, single-target), **Siege Cannon** (ground-only, splash), **Wall** (no damage, near-free, maze-shaping). Players grow a personal **deck/"build"** through a **3-option draft** at match start and after every wave. The draft is free; players can also spend **gold to buy extra rolls**, creating the central tension: spend gold on towers (your maze) vs. spend on rolls (your build).
- Mixamo character + animation download walkthrough
- Unity Humanoid rig setup
- Animator Controller with idle / walk / build states
- Replace Builder cylinder with rigged animated character
- Connect Claude to Blender via MCP (first-time setup, walkthrough needed)
**Five draft choice archetypes:**
1. **New tower** — add a tower to your buildable arsenal.
2. **Tower upgrade***systemic first* ("all towers of damage-type/projectile-type X gain Y", "unlock Lv.2 across the deck"); per-tower trees only later if needed.
3. **Enemy debuff** — temporary (weaker / slower / downgrade a tier); cost scales with duration.
4. **Builder ability** — active, targeted, in-wave, cooldown-based (e.g. Call Lightning, Haste, Stasis Trap).
5. **Relic quest** — opt-in secondary objective granting a powerful passive Relic.
This pipeline becomes the foundation for both the prototype enemy and any humanoid towers in Phase 2.
### 1.2 HUD
Can run in parallel with later items in this phase. Several existing systems have stubs awaiting HUD consumers.
- Canvas + components: minimap, portrait, context panel, 4×3 tower/upgrade grid
- Tower buttons calling `TowerPlacementController.BeginPlacement` (replaces `TowerPlacementTestTrigger`)
- Rejection message display subscribing to `TowerPlacementController.OnRejectionMessageReady`
- Build progress bar above active construction (consumes `BuildJob` / `BuildSiteVisual` state)
- Cancel-shelved-tower button or context-menu gesture (deferred from Path D2)
- Settings menu eventually owning `EdgePanEnabled`, scroll sensitivity, etc.
### 1.3 Match state and player slot mapping
Several systems currently hold stubbed mappings that must be resolved before multiplayer is meaningful.
- `MatchState` `NetworkBehaviour` — global match data: current wave, lives, race-pick timer
- `PlayerMatchState` `NetworkBehaviour` — per-player: race selection, etc.
- Authoritative client-id → `PlayerSlot` mapping. Replaces the five stubbed mappings in `TowerPlacementManager`, `TowerPlacementController`, `CameraController`, `PlayerBuilderSpawner`, and `Builder`.
### 1.4 Combat system
The most architecturally significant pending system. This blocks the Phase 2 tower animation work (towers can't have target-acquired/firing states to animate until something generates those states).
- `TowerCombat` component on tower prefabs. Component-per-behavior rather than flat fields on `TowerDefinition` — see existing lessons.
- Targeting logic: range check, target acquisition, target prioritization (closest, lowest-HP, etc.)
- Projectile prefabs and hitscan handling
- Damage application against enemy HP
**Architectural note for Phase 2 setup:** when designing `TowerCombat`, expose the following events for visual consumers (these will drive tower animation in Phase 2):
- `OnTargetAcquired` — first enemy enters range
- `OnTargetLost` — no enemies remaining in range
- `OnFire` — weapon discharges (per `FireRate` cycle)
- `CurrentTarget` reference for procedural rotation
### 1.5 Enemy system
- Enemy `NetworkBehaviour` (HP, movement, type, debuffs)
- Spawning system driven by waves / match state
- Enemy prefab pipeline for Phase 2 prototype
### 1.6 Pathfinding
- A* on the runtime walkability grid (consumes `LevelLoader.IsWalkable`)
- 4-connected, no diagonals (matches existing maze validation)
- Re-pathing on tower placement/removal events. Fire on: `TowerInstance` spawn/despawn, construction-start, construction-finish, shelved-tower despawn.
### 1.7 Lobby & Connection (COMPLETE — 2026-05-17)
Replaced the bare "Start Host" button with a proper main menu → lobby → match flow.
Lobby is its own scene; players gather, pick races, ready up, and the host starts the match.
**v1 shipped (Direct IP, Option A host-leaves-closes-lobby):**
- `MainMenu` scene — Host / Join (with IP+port field) / Quit / **Quick Start** (dev shortcut)
- `Lobby` scene — player list, per-player **Select Race** button opening the race-selection overlay, ready toggle, host-only Start button, Leave button
- `LobbyService` `NetworkBehaviour` scene singleton — Start Match RPC, Return to Lobby RPC
- `NetworkBootstrap` static — wraps `UnityTransport` host/join/disconnect. Designed for the Steam swap-out below: same call sites, different transport.
- `SessionFlow` DontDestroyOnLoad singleton — routes disconnected peers back to MainMenu on host loss
- `PlayerMatchState` extended with `IsReady` NetworkVariable and `SubmitRaceRpc` / `SubmitReadyRpc` for client → server submissions
- `PlayerBuilderSpawner` refactored to spawn on `NetworkSceneManager.OnLoadEventCompleted` for the Match scene, not on initial player spawn. Pulls race-specific `BuilderPrefab` from `RaceRegistry` when available, falls back to the inspector default. Re-spawns cleanly across Match → Lobby → Match cycles.
- Match-end overlay extended: **Retry** (back to lobby) AND **Return to Main Menu** (this player only)
- Host leaves → all clients return to main menu via `SessionFlow.OnClientDisconnectCallback` (Option A). Same applies if the host clicks "Return to Main Menu" after a match.
- **Race data + selection UI** delivered as part of 1.7 (originally scoped for 1.8): `RaceId` enum expanded to 16 slots, `RaceDefinition` ScriptableObject (Id, DisplayName, Icon, BuilderName, BuilderDescription, LoreText, BuilderPrefab, Towers stub), `RaceRegistry` (DontDestroyOnLoad singleton in MainMenu — single source of truth across all scenes), `RaceSelectionOverlay` (4×4 grid + detail panel, taken-race greying with picker badge, Esc/X close, server-side exclusivity enforced via `SubmitRaceRpc`).
- **Quick Start dev button** in MainMenu — bypasses lobby: hosts → waits for `PlayerMatchState.Local` → sets Race1 + ready → loads Match scene directly. Coroutine in `MainMenuController.QuickStartCoroutine`.
### 1.7-Future Steam Lobby Migration (Option C — DEFERRED)
When the Steam SDK is integrated (post-1.7, before 1.8 or in parallel), the Direct IP backend is replaced with a Steam-backed lobby provider. **The lobby UI and gameplay code do not change.** The migration touches only `NetworkBootstrap` and adds a `LobbyProvider` abstraction behind it.
**What changes:**
- Add `Facepunch.Steamworks` (recommended) or `Steamworks.NET` to the project
- Use Steam app ID **480 (Spacewar)** during development; switch to the actual app ID once Steam page is provisioned
- Replace `UnityTransport` with `SteamNetworkingSocketsTransport` (community-maintained NGO transport)
- Refactor `NetworkBootstrap` from static helpers into an `IConnectionProvider` interface with two implementations:
- `DirectIpConnectionProvider` (existing behavior, kept for LAN testing and DRM-free distribution)
- `SteamConnectionProvider` (Steam lobby create/join, friend invite via Steam overlay, Steam P2P sockets)
- Add lobby browser UI to `MainMenu` scene (currently just Host/Join buttons)
- Friend-invite flow: handled by Steam overlay (Shift+Tab → invite friend); join request lands in the existing Lobby scene
- Host-leaves behavior upgrades from Option A → Option C: Steam lobbies persist independently of the game host, so a new host can be elected from remaining members rather than tearing the lobby down. **This is the deferred behavioral upgrade flagged for migration time.**
**Notes for the migration:**
- Lobby code already factored to read player state from `PlayerMatchState` (carries across scene loads) and lobby-wide state from `LobbyService` — no UI rewrite needed
- The `IConnectionProvider` abstraction is the single seam between gameplay and transport; everything else stays put
- Both providers should coexist in the codebase so DRM-free builds (itch.io, direct distribution) can still ship without Steam
- Steam Direct fee ($100 USD) is required to publish on Steam but NOT for development — Spacewar app ID 480 is free to use
### 1.7.5 Terrain architecture
Decision deferred per existing context document; Builder code is already terrain-agnostic. Recommend deciding after the character pipeline mini-session and before Phase 2 begins (the visual prototype will look very different on Unity Terrain vs mesh-based terrain).
Options previously discussed: Unity Terrain, mesh-based (Blender), ProBuilder, per-tile heights via volumes.
### 1.8 Race system (Path E) — PARTIALLY COMPLETE
Data model and lobby selection UI shipped as part of 1.7 (2026-05-17). Remaining work is gameplay-side integration of the race payload during a match.
**Already done (delivered with 1.7):**
- `RaceDefinition` ScriptableObject with Identity / Builder / Lore / Gameplay-payload sections
- `RaceRegistry` DontDestroyOnLoad singleton (placed in MainMenu, persists into Lobby + Match)
- `RaceId` enum (None + Race1..Race16) — 16-slot grid reserved
- Lobby race-selection overlay (4×4 grid + detail panel + exclusivity enforcement)
- `PlayerMatchState.RaceSelection` NetworkVariable + `SubmitRaceRpc`
- `PlayerBuilderSpawner` reads race-specific `BuilderPrefab` when available
- Two placeholder RaceDefinition assets configured with the default builder (proves the data path works without race-specific content)
**Still pending:**
- Replace lobby race-pick with in-match race-pick overlay (timer-based auto-lock, `MatchState.RacePickTimer`) — OR retain lobby pick and remove the in-match flow concept. **Open decision** (see 1.10 reconciliation question).
- Multi-builder race support — revisit `PlayerBuilderSpawner` to spawn N builders for races that need them
- `TowerRegistry` filtering by active match's race rosters (currently shows all registered towers regardless of race)
- Auto-discovery of `RaceDefinition` assets (today's flow: drag each asset into `RaceRegistry.Definitions` manually)
- Replace `TowerPlacementManager.towerDefinitions[]` inspector array with race-driven discovery
- Race-specific builder prefabs (currently every race uses the same default builder)
- Real race content (display names, lore, icons, distinct builder visuals) — placeholder races exist but are interchangeable
### 1.9 Camera polish
Flagged for revisit; not blocking anything.
- Cursor-anchored zoom near map edges (Q3c flagged as revisitable)
- Center-on-builder hotkey (e.g., Space)
- Initial camera position taking race or match phase into account
### 1.10 Tower Customization & Meta-Progression (DEFERRED — DESIGN CAPTURED; IN-MATCH PAINT v1 + EFFECTS IMPLEMENTED)
Long-term cross-match progression loop. Recorded here so Phase 1.8 race-system design and Phase 2 visual prototype work can anticipate the customization data model when they're scheduled. Not blocking Phase 1 exit criteria — a single match is fully playable without it.
**Implemented — in-match paint v1 + paint-driven effects (2026-06-03 / 2026-06-09)**
A first-pass, in-match paint mechanic is built, verified in-engine, and now drives both tower visuals **and** projectile behavior.
Paint UI + recolor (2026-06-03):
- **Build / Paint tabs** in the command grid (shown when the builder is selected). Build tab is the existing tower menu.
- **Paint tab:** Red / Green / Blue swatches plus a **Reset** (clear) brush, selectable by click or **Q / W / E / R** hotkeys. The active brush swaps the cursor to a tinted paint circle.
- **Click a tower you own → recolors it**; Reset reverts it to its owner color.
- **Server-authoritative & networked:** `PaintColor` enum + `paintColor` `NetworkVariable` on `TowerInstance`, set via `RequestPaintServerRpc` (own-tower-only validation), replicated to all clients. Tint applied through the existing `MaterialPropertyBlock` path (`TowerInstance.ApplyTint`, which falls back to all child `MeshRenderer`s when none are explicitly listed).
- **New code:** `TowerPaintController` (client-local, mirrors `TowerPlacementController`), `PaintColors` palette in Core, Paint tab + swatches in `HUDController`.
Paint-driven combat effects (2026-06-09):
- `TowerCombat` resolves an effective **`CombatProfile`** per shot from the tower's `TowerDefinition` overridden by its `Paint` color, threaded through both the projectile and hitscan paths (unpainted towers fire as authored).
- **Red = Splash** (radius 2 tiles), **Green = Poison DoT** (½ base damage/sec for 3s), **Blue = Cold slow** (50% speed for 2s). Reuses the existing `EnemyStatus.ApplyEffect` / splash systems. Magnitudes are named constants in `TowerCombat` (promote to a ScriptableObject if designer tuning without recompile is needed).
- **Projectiles tint to the paint color**, replicated via a `PaintColor` `NetworkVariable` on `Projectile` (same pre-spawn → `OnNetworkSpawn` pattern as `TowerInstance`).
Still pending for the full meta-progression:
- Persistence / player profile, end-of-match reward rolls, decals, stat-modifier stack, layering / set bonuses, and the customization menu — all remain deferred as described below.
- The current paint→effect mapping is **override** (paint replaces authored effects) and a fixed 3-color set; the eventual customization system will generalize this to a layered modifier stack drawn from a reward pool.
**Core concept**
- Every player starts each match with the same **base tower set** — a small fixed roster (universal or per-race; see open question below).
- **End of match awards a customization reward**, drawn from a Warhammer-themed pool. Win and loss draw from **different pools** — winning unlocks higher-tier / rarer rewards, losing still progresses at a slower rate so no match is truly wasted.
- Reward types:
- **Paint color** (e.g. Macragge Blue, Mephiston Red, Caliban Green) — applied to tower visuals, can carry gameplay effects (see below)
- **Sticker decal** — chapter badges, regimental icons, faction sigils
- Other Warhammer-aligned customizations: transfers, weathering, base styles, freehand-style elements
- Customizations are **persistent across matches** via a player profile / save system.
- Applied via a **customization menu** (does not exist yet) reachable from the main menu, showing owned customizations and per-tower application slots.
**Gameplay enhancements via customization**
Cosmetics double as upgrades. The pattern mirrors the real-world Warhammer hobby loop (collect → paint → customize) translated into mechanical progression:
- **Stat modifiers** — extended range, increased damage, faster fire rate, larger splash radius
- **Damage-type changes** — applying a particular paint scheme grants Fire / Cold / Poison damage to an otherwise basic tower
- **Special effects** — chain hits, slow effects, DoT — driven by specific decal or paint combinations
- **Layering / set bonuses** — applying multiple customizations from the same "faction" might unlock additional effects (e.g. full Salamanders paint kit + chapter decal grants a flamer-style damage profile)
**Required systems (none exist yet)**
- **Player profile / persistence** — local save for now, account-bound later. Tracks owned customizations + per-tower application state.
- **`CustomizationDefinition` ScriptableObject** — stat-delta fields, visual asset references (decal texture, color values), rarity tier, reward-pool tags.
- **Tower stat modifier stack** — extend `TowerDefinition` (currently flat fields) to accept a layered modifier stack from applied customizations. Affects targeting, damage, range, fire rate at runtime.
- **End-of-match reward roll** — server-authoritative draw from win/loss pool, replicated to the relevant player. Anti-cheat: server owns the roll, not the client.
- **Customization menu UI** — main-menu-accessible. Browse owned, browse locked, apply / remove per tower in the base set.
- **Networked applied-customization state during a match** — towers must visually reflect each owner's applied customizations on every peer, AND stat modifiers must be authoritative on the server.
**Open question — interaction with the Phase 1.8 race system**
Phase 1.8 currently assumes **race-driven tower rosters** (each race has its own distinct set of towers). This new direction suggests a flatter, customization-driven model. The two systems need reconciliation before either ships:
- **Option A:** Race remains the primary tower-set distinction. Customizations layer on top of race-specific towers. Each race owns its own customization pool.
- **Option B:** Race becomes one customization category among many. Tower set is universal across players; "race" identity emerges from the player's chosen paint scheme / decal kit.
- **Option C:** Hybrid — small universal base set + larger race-locked roster, both customizable. Customizations affect both.
Decision deferred until both 1.8 and 1.10 are actively scheduled. The choice has significant implications for content scope: Option A means N races × M customizations each; Option B means one tower set × (M customizations × N "factions"). Option B is dramatically less art work per tower.
**Why this is deferred**
- Not required for Phase 1 exit criteria (a single match plays fine without cross-match progression).
- Phase 2 visual prototype doesn't depend on this — the painted-miniature aesthetic provides the visual scaffolding customization will eventually exploit, but the prototype tower's paint scheme can be hard-coded for the demo.
- The data model interaction with Phase 1.8 needs to be resolved first (see open question above).
**When to schedule**
Earliest reasonable slot: after Phase 1 exit criteria are met and Phase 1.8 race-system design has the customization-interaction question resolved. Could run in parallel with Phase 2 (no overlap with visual prototype scope) or after Phase 2 if visual direction needs to prove out first.
### Phase 1 exit criteria
A complete match is playable end-to-end: race pick → builder spawn → tower placement and construction → wave spawning → enemies path through the maze → towers shoot enemies → enemies die or leak → match concludes. Visuals are placeholder. All systems in this section are functional.
### Locked design decisions
- Draft is **free** at match start + after each wave; a gold **shop buys extra rolls**, available any time *(provisional — may change)*.
- **Per-player** decks/progression (each player drafts independently).
- Tower **upgrades are systemic-first**.
- **Draft pacing:** the prep phase before each wave is the draft window; unpicked drafts **auto-resolve at prep end** so no slow/AFK player stalls the group.
- Draft options are **authored ScriptableObjects** drawn by **weighted random**.
---
## Phase 2 — Visual Prototype
## Status at a glance
Begins only after Phase 1 exit criteria are met. This phase exists to prove out the painted-miniature visual direction on minimal content (one tower, one enemy), so the direction can be communicated to a future art lead with concrete, in-engine examples.
**Done & merged:** functional match loop end-to-end (placement, construction, waves, pathfinding, combat, match-end), HUD, lobby + race selection, economy, enemies + A* pathfinding, **flying enemies + air-targeting**, **per-player tower deck** (roguelike keystone #1).
### Prototype scope and constraints
**Done, pending commit/merge:** **draft system Slice 1** (the draft spine + "new tower" choice), verified working in-engine on branch `feature/draft-system`.
- **One tower** — Space Marine in Ultramarines colors, standing-ready pose, with idle / aim / fire animation states
- **One enemy** — Tyranid Hormagaunt with walk / death animations, animated on 2s for the Spider-Verse-style stepped-frame effect
- **Sourced reference content.** The Space Marine and Hormagaunt are placeholders pulled from existing third-party models. They are private prototype assets only — see Phase 3 for the swap-out plan.
**Paused:** in-match Paint system (overlaps with systemic upgrades — reconcile before building further).
### IP guardrails for the prototype
These hold throughout Phase 2 and until the Phase 3 swap-out is complete.
- Repo `mafoster134/UnityTowerDefense` remains private on GitHub. No public builds, no itch.io demos, no public streams or videos showing GW-derived assets.
- Internal multiplayer testing with friends over private connections is acceptable; anything resembling public distribution is not.
- Don't redistribute GW source files. Kitbash from photos/concept art into your own meshes and textures rather than embedding GW-shipped assets directly. Cleaner swap-out later.
- Maintain a plain-text **asset manifest** in the repo listing every asset using GW IP that needs replacement before commercial release.
### 2.1 Shared visual infrastructure (one-time investment)
Builds the technical scaffolding all Phase 2 assets (and all future production assets) consume.
#### 2.1.1 Painted-miniature URP shader
Custom Shader Graph variant of URP Lit, saved as `MiniatureStandard`.
- Standard PBR inputs: albedo, normal, metallic, roughness, AO
- **Fresnel rim term** added to the lighting output. Drives a subtle lighter color along glancing angles. Fakes the drybrush highlights miniature painters apply to raised edges. Critical for the "photographed painted miniature" read.
- **Crushed shadow curve** — adjustment that deepens the shadow-to-midtone transition. Mimics how miniatures look under photo-studio key lighting.
- Optional: subtle screen-space painted-noise overlay at very low intensity for tactile texture.
This shader is reused by every painted-miniature asset going forward.
#### 2.1.2 Lighting and post-processing setup
Project-wide, applied via the existing `DefaultVolumeProfile` system.
- **Strong directional key light** at ~45° elevation, slightly warm
- **Soft fill light** from opposite side, cool-tinted
- **Subtle bounce light** from below to lift bases (GW studio-shot reference)
- **AO intensity** raised slightly past realistic
- **Tilt-shift DOF** in the volume profile — slight blur at top and bottom of frame to sell diorama scale
- **Color grading** toward saturated, warm-shadowed
- Slight **vignette**
Applied to URP-Medium first; ported to URP-Low / High / Ultra when those quality tiers are configured (existing pending work).
#### 2.1.3 On-2s animation system
A `MonoBehaviour` (working name `SteppedAnimator`) attached to objects whose animation should appear at ~12fps despite the game running at 60fps. Selectively applied to skeletal animation; effects, projectiles, and UI remain smooth.
Implementation approach:
- `LateUpdate` samples the current `Animator` pose
- Quantizes time to 1/12-second steps
- Holds previous-frame pose on intermediate frames
- Configurable target framerate (default 12fps; can be tuned per-asset)
Design rule: stepped animation applies to **skeletal body animation and weapon-target tracking rotation only**. Muzzle flashes, projectiles, and UI run at full framerate. The contrast between stepped and smooth is what sells the Spider-Verse effect — global stepping looks broken.
#### 2.1.4 `TowerVisualController` component
New component on tower prefabs. Bridges the gameplay-side `TowerCombat` events (built in Phase 1.4) to the animation system.
- Subscribes to `TowerCombat.OnTargetAcquired`, `OnTargetLost`, `OnFire`
- Sets Animator parameters: `HasTarget` (bool), `Fire` (trigger)
- Drives procedural torso/turret rotation toward `TowerCombat.CurrentTarget` via `LateUpdate` LookAt on a designated pivot bone
- Pure local visualization. No `NetworkBehaviour`, no networked state. Each client renders animation state from its own read of the networked combat state.
This component, like `MiniatureStandard` and `SteppedAnimator`, is one-time scaffolding that every future tower consumes.
### 2.2 Prototype tower — Space Marine (Ultramarine)
#### 2.2.1 Reference and source acquisition
- Pull 812 reference images of Ultramarine Tactical / Intercessor Marines in standing-ready poses. PureRef board.
- Acquire base model from MyMiniFactory, Sketchfab, or CGTrader. Prefer "miniature-scale" models with proportions already correct for tabletop aesthetic over high-detail "video game" models.
#### 2.2.2 Mesh prep
- Decimate / retopo to 5k15k tris
- Re-UV (most source models have UVs optimized for 3D printing, not texturing)
- Reasonable texel density for 2K texture target
#### 2.2.3 Texturing
Substance Painter (or alternative). Build the painted-Ultramarine look in layers:
1. **Base coat** — Macragge Blue equivalent. Slightly desaturated steely middle value.
2. **Recess shading** — darker blue-violet wash driven by curvature map. Makes armor plates read as separate panels.
3. **Edge highlighting** — Calgar Blue / Fenrisian Grey territory. Visibly broken and slightly streaky, not perfect lines. *Single most "miniature-painted" visual cue.*
4. **Final extreme highlights** — near-white blue, applied only to the absolute sharpest edges, very sparingly.
5. **Gold trim** on aquila, helmet rim, weapon details. NMM-painted gradients photograph better at top-down distance than real metallic.
6. **Black undersuit and weapon casing** — flat very dark navy with subtle blue rim highlights. Avoid pure black.
7. **Battle damage** — small chips on edges showing silver underneath the blue. Used very sparingly.
8. **Base** — broken urban rubble or red Mars-like sand. Skull or two. Optional static grass tuft.
**Critical:** paint deliberate brushstroke variation into the albedo. Slight value/hue shifts across flat surfaces. Airbrushed-gradient textures will read as CGI; broken-application textures read as painted miniature.
Consider community-made "Warhammer / miniature / tabletop" smart materials in the Substance Share library as a starting point; customize from there.
#### 2.2.4 Animation states
Three states minimum, retargeted from Mixamo "rifle" animation set onto the Humanoid rig (leveraging the Phase 1.1 character pipeline work):
- **Idle** — relaxed stance, bolter held at low ready, subtle breathing/sway loop
- **Aiming** — bolter raised, tracking target. Procedural torso pivot rotates toward `CurrentTarget` via `TowerVisualController` LateUpdate LookAt; clip provides upper-body pose.
- **Firing** — short burst animation: muzzle flash effect, recoil pulse, optional casing eject
Animator Controller transitions:
- Idle → Aiming: `HasTarget == true`
- Aiming → Idle: `HasTarget == false` (with ~1 second blend back to relaxed pose)
- Aiming → Firing: `Fire` trigger (returns to Aiming on completion)
Apply `SteppedAnimator` to the body Animator and the torso pivot rotation. Muzzle flash and projectiles remain smooth.
#### 2.2.5 Integration
- Create `TowerDefinition` asset. DisplayName "Space Marine" (will become original-faction equivalent in Phase 3). FootprintSize 2×2. GoldCost per economy tuning. BuildTime 4 seconds (matches existing test value). Combat fields per `TowerCombat` design from Phase 1.4.
- Plug into `TowerPlacementManager.towerDefinitions[]` for testing (eventually replaced by race-driven discovery from Phase 1.8)
- Verify the existing `BuildSiteVisual` ghost system handles the new prefab correctly (green/white/red tinting for build stages should work as-is)
#### 2.2.6 Time estimate
Roughly 2543 hours total. Bulk of time in texturing (812h) and animation retargeting / state machine (610h). Shader and lighting are one-time investments amortized across all future towers.
### 2.3 Prototype enemy — Tyranid Hormagaunt
#### 2.3.1 Reference and source acquisition
- Reference images of Hormagaunts in scuttling poses. Note the four-legged-with-scythe-arms body plan.
- Source model from same channels as the tower. Hormagaunts have a distinct silhouette that's forgiving for proportions but demands clean topology around the joints for the on-2s animation to read well.
#### 2.3.2 Mesh prep and rigging
- Decimate / retopo as for the tower
- Custom rig (Mixamo's Humanoid rig won't fit the four-legged plan). Mixamo's "Quadruped" auto-rigger is a possibility, or hand-rig in Blender.
- Skinning and weight painting
#### 2.3.3 Texturing
Same painted-miniature pipeline as the tower, tuned for organic Tyranid biology:
- Chitin plates with hard-edge gradients (purple-to-bone is the canonical Hyve Fleet Leviathan scheme)
- Recess shading deeper than on the tower — Tyranid sculpts have very pronounced cavities
- Subsurface treatment on flesh areas (mouth, claws, exposed muscle)
- Bone highlights drybrushed onto chitin edges
- Glossy claws and teeth
#### 2.3.4 Animations
Pulled from Mixamo "creature" set or hand-authored:
- Walk / scuttle cycle — fast, low to the ground
- Death — stagger, collapse
Apply `SteppedAnimator` aggressively here. The scuttling gait at 12fps is the *signature* visual moment of the prototype — this is where the Spider-Verse effect is most visible and most rewarding. Generic Mixamo creature animation often looks floaty at 60fps; stepped to 12fps, it reads as deliberately stylized.
#### 2.3.5 Integration
- Hook into the Phase 1.5 enemy system. HP, speed, damage stats per enemy type design.
- Walks the maze via Phase 1.6 pathfinding.
- Takes damage from the Space Marine tower's projectiles via Phase 1.4 combat system.
#### 2.3.6 Time estimate
Roughly 1729 hours. Quadruped rigging is the wildcard — could compress significantly with auto-rigging tools or expand if hand-rigged from scratch.
### 2.4 Demo scene
Final integration step. A small purpose-built scene demonstrating the visual direction in motion.
- Single Space Marine tower placed and animating
- Wave of Hormagaunts spawning and pathing toward an exit
- Tower acquires targets, aims, fires; Hormagaunts die in stepped-animation glory
- Camera positioned to show the tabletop-diorama framing
- Tilt-shift DOF, painted-miniature lighting and post all active
This scene becomes the artifact you show to candidate art leads in Phase 3.
### Phase 2 exit criteria
The demo scene runs in-editor showing the painted-miniature aesthetic working end-to-end with real gameplay (towers shooting enemies, enemies dying). The visual direction is clearly communicated. The shared infrastructure (`MiniatureStandard` shader, lighting setup, `SteppedAnimator`, `TowerVisualController`) is in place and reusable.
**Next:** draft Slice 2 (systemic upgrades).
---
## Phase 3 — Path to Commercial Production
## Part A — Roguelike build-out (current focus)
Notes only. This phase is not actionable until Phase 2 is complete and the decision to pursue commercial release is made.
### A1. Per-player tower deck — ✅ DONE (merged)
Towers are unlocked per player, not globally available. See [`Project_Context.md`](Project_Context.md).
### 3.1 IP swap-out
### A2. Draft spine + "new tower" (Slice 1) — ✅ DONE (branch `feature/draft-system`)
Server generates 3 weighted options per player each prep phase; players pick via a non-modal HUD overlay; unpicked auto-resolve at prep end; gold "Buy Roll" purchases extra rolls. Only choice type is **New Tower** (grants into `PlayerTowerDeck`). *Commit/merge pending.*
The prototype Space Marine and Hormagaunt must be replaced before any public release. Two paths:
### A3. Draft Slice 2 — systemic tower upgrades — ⏭ NEXT
- Add an upgrade `DraftOption` subclass applying **systemic** modifiers: "all towers of damage-type X gain Y", "all projectile-type X …", "unlock Lv.2 across deck".
- **Reconcile with `PlayerBuffManager`.** The existing gold-bought buff stack (global Damage/AttackSpeed multipliers) is the natural underlying apply mechanism — generalize it to type-filtered modifiers and make the draft (not the standalone buff menu) the entry point. Decide the fate of the old buff menu here.
- **Original-faction replacement.** Develop original factions in the painted-miniature aesthetic. The "heavy armored warrior order" archetype and "horde swarm" archetype are not owned by anyone; the specific GW execution is. Production art lead's first major task.
- **GW license.** Possible but selective. GW has licensed indie tabletop-adjacent games; the bar is meaningful. Worth investigating if the prototype demo is strong enough to take to GW directly.
### A4. Builder active abilities (draft choice #4)
New in-wave, targeted, cooldown ability system (Call Lightning, Haste, Stasis Trap). New `DraftOption` subclass grants an ability to the builder; needs input/targeting + cooldown UI. Some builders may start with an ability unlocked.
The data model already supports clean swap-out: `TowerDefinition` is asset-referenced, so replacing the prefab and texture references is the only gameplay-side change. Code is unaffected.
### A5. Relic quests (draft choice #5)
Secondary-objective tracking ("place 50 towers in 5 min", "leak 0 for 3 waves") that, on completion, grants a powerful passive **Relic** (e.g. corpses leave slowing ice, electric hits stun). Needs objective tracking + relic passive/event hooks.
### 3.2 Art lead hiring
### A6. Enemy debuffs (draft choice #3)
Temporary debuffs purchasable in the draft (weaker / slower / **downgrade a tier**). "Downgrade" implies an **ordered enemy progression** the data doesn't model yet — add that first.
The Phase 2 demo scene is the primary recruitment artifact. Look for:
### A7. Tower content beyond the starting three
The "new tower" draft is only meaningful once the pool has towers **beyond** the starting set. Author additional tower types (definitions, prefabs, draft options). *(Until then, the new-tower draft has nothing valid to offer because all towers are starting towers.)*
- Tabletop miniature painting experience or demonstrable understanding of the aesthetic
- 3D character/prop authoring at game-asset quality
- Comfort with stylized PBR pipelines
- Familiarity with Unity URP and Shader Graph (or willingness to learn)
### A8. Cross-match persistence / meta-progression
Player profile saving owned content; **win/loss reward pools** drawn server-side at match end; the customization menu. **Requires a session-stable tower/option ID** (catalog indices reset each match — see Context "technical debt").
### 3.3 Production scope expansion
- Multiple races (Phase 1.8 architecture supports this; content fills it)
- Full tower roster per race (likely 610 towers each, with upgrade paths)
- Full enemy roster (armored, fast, flying, boss types)
- Map variety
- Audio direction matching the visual direction (orchestral / industrial / hobbyist's-table ambient?)
### 3.4 Production guardrails carried from Phase 2
The asset manifest tracking GW-derived content must hit zero entries before any public build, public repo flip, or marketing material.
### Open decisions (resolve as the relevant slice is scheduled)
- **Paint reconciliation:** keep paint as a separate axis, fold it into the systemic-upgrade visuals, or retire it. (Currently paused.)
- **Race vs Builder naming:** the code says "Race"; the design says "Builder." Rename, nest, or keep — decide before it calcifies.
- **Gold-roll availability:** currently any time; may tighten to prep-only.
---
## Cross-phase principles preserved from existing context
## Part B — Functional gameplay remainder (not roguelike-specific)
- **Debug to root cause.** No defensive workarounds, no per-frame state-correcting hacks. Find the actual cause and fix it correctly.
- **Re-state design intent before coding.** Confirmed valuable across multiple sessions; continues into Phase 2 visual work where the same restate-before-build approach prevents asset rework.
- **Server-authoritative gameplay; local-only UI/visual state.** Selection, animation state, ghost visuals all stay client-side. Only gameplay-meaningful state is networked.
- **Existing engine and rendering decisions stand.** Unity 6.4 → next LTS migration plan; URP; IL2CPP; .NET Standard 2.1; Linear color space; new Input System; Force Text serialization.
- **Tower Upgrade / Sell actions** — HUD buttons exist but are disabled. Sell first (refund + despawn), then per-tower upgrade if the systemic model leaves room for it.
- **Enemy resistances / weaknesses**`EnemyHealth.TakeDamage` has the stub slot; info panel has the placeholder.
- **Terrain architecture decision** — Unity Terrain vs mesh vs ProBuilder. Builder code is terrain-agnostic; decide before heavy art.
- **Camera polish** — cursor-anchored zoom near map edges, center-on-builder hotkey, race/phase-aware initial position.
---
## Part C — Near-term art & visual TODOs
These are concrete, scheduled-soon visual fixes (placeholders are otherwise point-isolated and swap cleanly):
- **Enemy idle animation support — NEW.** Add idle animation states to **all** enemy prefabs (enemies currently lack an idle; needed for held/spawned and between-waypoint states, and as the foundation for the stepped-animation direction below).
- **Tower footprint visuals fill the full 2×2 — NEW.** Tower meshes (the new cones / placeholder shapes) sit centered and read smaller than the tile area they occupy. Update the visuals so a placed tower clearly fills its entire 2×2 footprint (matters for readability of maze packing and for the Wall especially).
---
## Part D — Visual prototype: painted-miniature aesthetic (deferred phase)
Begins after the roguelike core is solid. Proves out the "photographed painted tabletop miniature" + Spider-Verse stepped-animation look on minimal content, as a concrete artifact for a future art lead. **Placeholder hero content (Space Marine + Hormagaunt-style) is GW-adjacent and private-only — see Part E.**
**Shared infrastructure (one-time, reused by all future assets):**
- **`MiniatureStandard` URP Shader Graph** — PBR + a **Fresnel rim** term (fakes drybrush edge highlights) and a **crushed-shadow** curve (studio-lit miniature look); optional low-intensity painted-noise overlay.
- **Lighting/post** via the volume profile — warm key (~45°), cool fill, low bounce, slightly raised AO, **tilt-shift DOF** (diorama scale), saturated warm-shadow grade, slight vignette.
- **`SteppedAnimator`** — samples the Animator pose and quantizes to ~12fps for **skeletal body + weapon-tracking only**; effects/projectiles/UI stay smooth (the contrast is what sells it). Builds on the enemy idle-animation work in Part C.
- **`TowerVisualController`** — local-only bridge from `TowerCombat` events (`OnTargetAcquired`/`OnTargetLost`/`OnFire`, `CurrentTarget`) to Animator params + procedural turret rotation.
**Prototype content:** one hero tower (idle/aim/fire) and one enemy (walk/death, stepped), then a **demo scene** showing towers shooting enemies in the painted-miniature look. Exit criteria: the demo runs in-editor with the aesthetic working end-to-end and the shared infra reusable.
---
## Part E — Path to commercial production (notes only)
- **IP swap-out (required before any public release):** replace GW-adjacent placeholder content with original factions (the "armored warrior order" and "horde swarm" archetypes aren't owned; the specific GW execution is) — or pursue a GW license if the demo warrants. The data model already supports clean swap-out (asset-referenced definitions; code unaffected). The **asset manifest of IP-derived content must hit zero** before any public build, repo flip, or marketing.
- **Steam lobby migration (deferred):** replace Direct-IP with a Steam-backed provider behind an `IConnectionProvider` abstraction — **`NetworkBootstrap` is the single seam**; lobby UI and gameplay don't change. Adds friend-invite via overlay, lobby browser, Steam P2P transport; upgrades host-leave handling (Option A → lobby persists / new host). Use Spacewar app ID 480 in dev. Keep Direct-IP for LAN / DRM-free builds.
- **Production scope:** more towers/enemies/maps, audio direction matching the visual direction, art-lead hire (the Part D demo is the recruitment artifact).
---
## Cross-phase principles
- **Debug to root cause** — no defensive workarounds or per-frame correction hacks.
- **Restate design intent before coding** — prevents rework; especially valuable for the roguelike systems and any art pipeline work.
- **Server-authoritative gameplay; local-only UI/visual state.**
- **Existing engine/rendering decisions stand:** Unity 6.4, URP, IL2CPP, .NET Standard 2.1, Linear color, new Input System, Force Text serialization, NGO 2.x.