Scale difficulty by run position; wipe towers at phase end

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>
This commit is contained in:
Matt F 2026-07-31 00:32:33 -07:00
parent 4892d7253d
commit 16706a1ecf
154 changed files with 2608 additions and 287 deletions

View file

@ -0,0 +1,18 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d075c66b381872a4781b3916296ccdc9, type: 3}
m_Name: EnemyUpgrade_Blink
m_EditorClassIdentifier: Assembly-CSharp::TD.Gameplay.EnemyUpgrades.AbilityEnemyUpgradeOption
DisplayName: Blink
Description: Enemies occasionally teleport a short distance ahead.
Icon: {fileID: 21300000, guid: df5903159b157404d8e92942029f08f7, type: 3}
Ability: {fileID: 11400000, guid: 030f10c9a264e544ea3e0f4fdb4171bd, type: 2}

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: eef28ca7b8844504e9d75ff903a3bb61
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,19 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f5e90fe6b8e439e4f99769a6923c2262, type: 3}
m_Name: EnemyUpgrade_DoubleUp
m_EditorClassIdentifier: Assembly-CSharp::TD.Gameplay.EnemyUpgrades.DoubleUpEnemyUpgradeOption
DisplayName: Double Dip
Description: Enemies from this wave gain no upgrades, but enemies from the next
wave have two upgrades selected automatically
Icon: {fileID: 21300000, guid: e81c6ebff6b98ac44b884d3006611ae6, type: 3}
BuffsToAutoApply: 2

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 46e2a6a59c0a3034f9fa44681d9ba422
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,18 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d075c66b381872a4781b3916296ccdc9, type: 3}
m_Name: EnemyUpgrade_Flight
m_EditorClassIdentifier: Assembly-CSharp::TD.Gameplay.EnemyUpgrades.AbilityEnemyUpgradeOption
DisplayName: Flight
Description: Enemies gain the power of flight
Icon: {fileID: 21300000, guid: 39ac5850677a092479550234de13e868, type: 3}
Ability: {fileID: 11400000, guid: cb2ec6bb70f57d0429b99b7cd4c7db73, type: 2}

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 80fb851b702ff304183cb6e89c4aa245
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,18 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d075c66b381872a4781b3916296ccdc9, type: 3}
m_Name: EnemyUpgrade_NoBounty
m_EditorClassIdentifier: Assembly-CSharp::TD.Gameplay.EnemyUpgrades.AbilityEnemyUpgradeOption
DisplayName: Peniless
Description: Enemies no longer drop gold upon death
Icon: {fileID: 21300000, guid: ea9802d37489c9442ba2ffd4a41c6cb2, type: 3}
Ability: {fileID: 11400000, guid: c64c7121b0456bb4a873acec9e0abf91, type: 2}

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a67aa3644d2ad4847a47040f53fea26f
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,19 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d075c66b381872a4781b3916296ccdc9, type: 3}
m_Name: EnemyUpgrade_Split
m_EditorClassIdentifier: Assembly-CSharp::TD.Gameplay.EnemyUpgrades.AbilityEnemyUpgradeOption
DisplayName: Split on Death
Description: Enemies killed will spawn two more smaller, faster, weaker versions
of themselves. (This only triggers a single time per base enemy)
Icon: {fileID: 21300000, guid: 43490fdb6e2477643a275956ce5f4596, type: 3}
Ability: {fileID: 11400000, guid: 0305468bc8f912d429a8b20bf23f947c, type: 2}

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f6bfb033a15b6d0419587b80a8286bd1
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,18 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d075c66b381872a4781b3916296ccdc9, type: 3}
m_Name: EnemyUpgrade_Theft
m_EditorClassIdentifier: Assembly-CSharp::TD.Gameplay.EnemyUpgrades.AbilityEnemyUpgradeOption
DisplayName: Thief
Description: Enemies that leak steal 15 gold on their way out
Icon: {fileID: 21300000, guid: 315be3feae908714a911f596b8533317, type: 3}
Ability: {fileID: 11400000, guid: a18691a20d75f17479a83b3e171759e7, type: 2}

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 37d761966a349ba4cb4141f913224d5c
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant: