Follow-up pass on the 2.0 refactor, closing the gap between "waves are drawn
at random" and "difficulty still lives in the enemy assets".
- Enemy health is no longer authored per enemy type. New EnemyScalingConfig
scales a per-zone HP *budget* by encounter number; per-enemy health is that
budget divided by the wave's enemy count. Scaling the total rather than the
per-enemy value keeps enemy count a texture knob (few tanks vs many swarmers)
instead of a second, uncontrolled difficulty axis. EnemyDefinition.MaxHp
becomes HpMultiplier, a deviation around 1.0. Speed stays archetype-only and
unscaled -- escalating it compounds with health and invalidates tower balance
mid-run.
- GoldConfig entries no longer reference a WaveDefinition. Payout is a property
of run position, not of which wave got drawn: WaveGoldEntry ->
EncounterGoldEntry, Waves -> Encounters, keyed by global encounter number.
Its inspector labels elements "Encounter N" and projects cumulative earnings.
- The wave's voted buffs now show as icon badges in the top bar, read from the
same RunState slot the spawn path uses so the display can't drift from what
the enemies actually carry. Hover names the buff; unillustrated cards fall
back to a lettered badge rather than vanishing.
- Clearing a phase's boss destroys every built tower, unrefunded. Queued build
jobs still refund -- those towers were never delivered. Runs with the field
empty, so the walkability churn doesn't hit the re-path scheduler.
- Fixed an RPC codegen break: [ClientRpc] requires a ClientRpc suffix, unlike
the newer [Rpc(SendTo...)] style this file doesn't use.
- Setup checklist reordered into dependency order; it previously asked for a
RunDefinition two sections before creating one.
Also carries the editor-side asset reorganisation into Definitions/RunDefinitions
and the sprite move into Enemy/Player draft icon folders.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Restructures the game around the cyclical run loop from Game Design Doc V2:
5 waves = a cycle, 3 cycles = a phase, each phase ends in a boss.
- New TD.Gameplay.Waves: WaveGroup / PhaseDefinition / RunDefinition author the
run as draggable weighted pools; RunState owns phase/cycle position, the drawn
wave slots, and the per-slot enemy buff sets. WaveManager's flat wave array is
gone -- it now only runs the encounter RunState points at.
- New TD.Gameplay.EnemyUpgrades: the post-wave enemy-buff vote, with public
live-replicated ballots so the HUD can show who voted for what.
- Inter-wave flow is now strictly sequential: draft -> vote -> build, each stage
ending early once every player has acted.
- Enemy abilities inverted from per-instance random rolls to deterministic,
stacking per-wave-slot sets. Six cards ship: Split (reworked), Flight, Blink,
No Bounty, Gold Theft, Double Up.
- Tower upgrades are a two-step tree: a draft pick unlocks a node, gold converts
an already-placed tower in place.
- Boss encounters flag their enemies and drive a boss HP bar.
- Player cap reduced to 3 via MatchRules.MaxPlayers.
- GoldConfig is now keyed by global encounter number rather than wave index.
Compiles clean; NOT yet verified in-engine. Editor wiring still required --
see Docs/2.0_Setup_Checklist.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Owner-validated sell RPC refunds SellRefundPercent of invested gold (Wall refunds 100% while un-upgraded), despawns the tower, and broadcasts a coin-burst VFX + rustle SFX. Refunds do not count as per-wave income. Investment/upgrade tracking added as the seam for the future upgrade system.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Builder.DisplayName: stub property ("Builder (P{n})") for portrait label; swaps
to real player name when MatchState lands in Phase 1.3
- HUDController: subscribe SelectionState.OnSelectionChanged in OnEnable/OnDisable;
HandleSelectionChanged drives portrait label + grays out command grid when nothing
is selected; Start() seeds initial state in case builder auto-selected before Start
- BuildSiteVisual: ComputeProgressNormalized() public API ([0,1], safe on any client);
OnNetworkSpawn spawns a non-networked BuildProgressBar child
- BuildProgressBar: new world-space uGUI Canvas bar; green while Constructing, yellow
while Paused, hidden while Queued; billboards to Camera.main each LateUpdate;
auto-destroyed when parent BuildSiteVisual despawns
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>