feat: add 9-level tower evolution system with distinct tier abilities
Extend all 5 towers to 9 upgrade levels, divided into 3 visual and functional evolution tiers: - Tier 1 (L1-3, Yellow): Base stats (damage, range, rate). - Tier 2 (L4-6, Orange): First major ability evolution with pulsing orange aura. - Tier 3 (L7-9, Blue): Final devastating evolution with blue aura. Evolutions per tower: - Arrow Tower: * L4-6 (Orange): Multishot firing 2-3 arrows simultaneously at distinct targets. * L7-9 (Blue): 4-arrow multishot + Poison DoT (up to 28 dmg/s). - Cannon: * L4-6 (Orange): Incendiary shells applying Burn DoT in splash radius. * L7-9 (Blue): Flak shells hitting flying units with full splash + burn damage. - Frost Tower: * L4-6 (Orange): Permafrost - every 3rd pulse completely freezes enemies (speed = 0). * L7-9 (Blue): Shatter - frozen enemies receive +50% damage from all sources. - Tesla Tower: * L4-6 (Orange): Chain lightning applies stun on each hit. * L7-9 (Blue): Lightning Storm - every 4th shot strikes and stuns ALL enemies in range. - Laser Tower: * L4-6 (Orange): Prism refraction splitting the beam onto 2-3 secondary targets. * L7-9 (Blue): Piercing beam penetrating all enemies in a line up to 280px range. Engine & Renderer updates: - Added DoT tick handling (poison/burn) and freeze/stun status effects. - Added visual indicators for frozen enemies (ice spikes) and DoT particles. - Added 3-slot tier-colored pips on tower base plates + pulsating evolution auras. - Updated TowerPanel with 9-star tier display (★★★ yellow, ★★★ orange, ★★★ blue) and dynamic special ability descriptions. Testing & Validation: - Added `scripts/test-evolution.mts` covering all 10 evolved mechanics (all green). - Verified lockstep multiplayer determinism via `scripts/test-mp.mts`. - Verified solo campaign balance preservation via `scripts/sim.mts`. - Full TypeScript typecheck and production build passing.
This commit is contained in:
parent
ef75203db7
commit
4f8400c480
8 changed files with 518 additions and 98 deletions
|
|
@ -53,14 +53,24 @@ export const TOWERS: Record<TowerKind, TowerDef> = {
|
|||
icon: '🏹',
|
||||
desc: 'Günstiger Standardturm mit schnellen Einzelschüssen.',
|
||||
cost: 50,
|
||||
upgradeCost: [60, 110],
|
||||
upgradeCost: [60, 110, 260, 420, 700, 1200, 2000, 3400],
|
||||
levels: [
|
||||
{ damage: 12, range: 110, rate: 1.7 },
|
||||
{ damage: 22, range: 120, rate: 2.0 },
|
||||
{ damage: 38, range: 132, rate: 2.4 },
|
||||
{ damage: 70, range: 140, rate: 2.6 },
|
||||
{ damage: 95, range: 148, rate: 2.8 },
|
||||
{ damage: 125, range: 155, rate: 3.0 },
|
||||
{ damage: 180, range: 165, rate: 3.2 },
|
||||
{ damage: 240, range: 175, rate: 3.4 },
|
||||
{ damage: 320, range: 185, rate: 3.6 },
|
||||
],
|
||||
hitsFlying: true,
|
||||
projectileSpeed: 460,
|
||||
multi: [1, 1, 1, 2, 2, 3, 3, 3, 4],
|
||||
dotDps: [0, 0, 0, 0, 0, 0, 12, 18, 28],
|
||||
dotDuration: [0, 0, 0, 0, 0, 0, 2, 2.5, 3],
|
||||
dotColor: '#7ddc4f',
|
||||
color: '#9a6a33',
|
||||
accent: '#e8c27a',
|
||||
hotkey: '1',
|
||||
|
|
@ -71,15 +81,25 @@ export const TOWERS: Record<TowerKind, TowerDef> = {
|
|||
icon: '🧨',
|
||||
desc: 'Flächenschaden durch Explosion – trifft aber keine Flieger.',
|
||||
cost: 110,
|
||||
upgradeCost: [100, 180],
|
||||
upgradeCost: [100, 180, 380, 600, 950, 1600, 2600, 4200],
|
||||
levels: [
|
||||
{ damage: 28, range: 118, rate: 0.55 },
|
||||
{ damage: 50, range: 128, rate: 0.62 },
|
||||
{ damage: 92, range: 140, rate: 0.7 },
|
||||
{ damage: 150, range: 150, rate: 0.75 },
|
||||
{ damage: 200, range: 158, rate: 0.8 },
|
||||
{ damage: 260, range: 165, rate: 0.85 },
|
||||
{ damage: 380, range: 175, rate: 0.9 },
|
||||
{ damage: 500, range: 185, rate: 0.95 },
|
||||
{ damage: 680, range: 195, rate: 1.0 },
|
||||
],
|
||||
hitsFlying: false,
|
||||
projectileSpeed: 300,
|
||||
splash: [42, 48, 56],
|
||||
splash: [42, 48, 56, 64, 70, 76, 84, 92, 100],
|
||||
dotDps: [0, 0, 0, 10, 14, 20, 26, 34, 45],
|
||||
dotDuration: [0, 0, 0, 2, 2, 2.5, 2.5, 3, 3],
|
||||
dotColor: '#ff9c40',
|
||||
flak: [false, false, false, false, false, false, true, true, true],
|
||||
color: '#57616e',
|
||||
accent: '#ff9c40',
|
||||
hotkey: '2',
|
||||
|
|
@ -90,15 +110,22 @@ export const TOWERS: Record<TowerKind, TowerDef> = {
|
|||
icon: '❄️',
|
||||
desc: 'Frostpuls verlangsamt ALLE Gegner in Reichweite (auch Flieger).',
|
||||
cost: 80,
|
||||
upgradeCost: [70, 130],
|
||||
upgradeCost: [70, 130, 260, 420, 700, 1100, 1800, 3000],
|
||||
levels: [
|
||||
{ damage: 5, range: 95, rate: 0.9 },
|
||||
{ damage: 9, range: 105, rate: 1.0 },
|
||||
{ damage: 15, range: 118, rate: 1.1 },
|
||||
{ damage: 22, range: 128, rate: 1.15 },
|
||||
{ damage: 30, range: 138, rate: 1.2 },
|
||||
{ damage: 40, range: 148, rate: 1.25 },
|
||||
{ damage: 60, range: 158, rate: 1.3 },
|
||||
{ damage: 80, range: 170, rate: 1.35 },
|
||||
{ damage: 105, range: 182, rate: 1.4 },
|
||||
],
|
||||
hitsFlying: true,
|
||||
slowFactor: [0.55, 0.45, 0.35],
|
||||
slowDuration: [1.5, 1.9, 2.3],
|
||||
slowFactor: [0.55, 0.45, 0.35, 0.32, 0.3, 0.28, 0.25, 0.22, 0.2],
|
||||
slowDuration: [1.5, 1.9, 2.3, 2.5, 2.7, 2.9, 3.1, 3.3, 3.5],
|
||||
freezeDuration: [0, 0, 0, 0.7, 0.9, 1.1, 1.3, 1.5, 1.8],
|
||||
color: '#4d8fb5',
|
||||
accent: '#aef0ff',
|
||||
hotkey: '3',
|
||||
|
|
@ -109,15 +136,23 @@ export const TOWERS: Record<TowerKind, TowerDef> = {
|
|||
icon: '⚡',
|
||||
desc: 'Kettenblitz springt auf mehrere Gegner über.',
|
||||
cost: 130,
|
||||
upgradeCost: [120, 200],
|
||||
upgradeCost: [120, 200, 400, 650, 1000, 1700, 2800, 4500],
|
||||
levels: [
|
||||
{ damage: 22, range: 105, rate: 1.0 },
|
||||
{ damage: 38, range: 115, rate: 1.1 },
|
||||
{ damage: 66, range: 128, rate: 1.2 },
|
||||
{ damage: 95, range: 138, rate: 1.3 },
|
||||
{ damage: 125, range: 145, rate: 1.4 },
|
||||
{ damage: 160, range: 152, rate: 1.5 },
|
||||
{ damage: 230, range: 160, rate: 1.6 },
|
||||
{ damage: 300, range: 168, rate: 1.7 },
|
||||
{ damage: 400, range: 175, rate: 1.8 },
|
||||
],
|
||||
hitsFlying: true,
|
||||
chain: [3, 4, 5],
|
||||
chainRange: 100,
|
||||
chain: [3, 4, 5, 6, 6, 7, 7, 8, 9],
|
||||
chainRange: [100, 100, 100, 110, 110, 115, 120, 125, 130],
|
||||
stunDuration: [0, 0, 0, 0.2, 0.25, 0.3, 0.35, 0.4, 0.5],
|
||||
stormEvery: [0, 0, 0, 0, 0, 0, 5, 5, 4],
|
||||
color: '#6a5fb0',
|
||||
accent: '#c8b4ff',
|
||||
hotkey: '4',
|
||||
|
|
@ -128,19 +163,38 @@ export const TOWERS: Record<TowerKind, TowerDef> = {
|
|||
icon: '💫',
|
||||
desc: 'Soforttreffer mit hoher Reichweite und hohem Schaden.',
|
||||
cost: 160,
|
||||
upgradeCost: [150, 260],
|
||||
upgradeCost: [150, 260, 500, 800, 1300, 2100, 3400, 5500],
|
||||
levels: [
|
||||
{ damage: 60, range: 170, rate: 0.5 },
|
||||
{ damage: 105, range: 185, rate: 0.55 },
|
||||
{ damage: 185, range: 205, rate: 0.6 },
|
||||
{ damage: 170, range: 215, rate: 0.6 },
|
||||
{ damage: 230, range: 225, rate: 0.65 },
|
||||
{ damage: 300, range: 235, rate: 0.7 },
|
||||
{ damage: 420, range: 250, rate: 0.75 },
|
||||
{ damage: 560, range: 265, rate: 0.8 },
|
||||
{ damage: 750, range: 280, rate: 0.85 },
|
||||
],
|
||||
hitsFlying: true,
|
||||
prism: [0, 0, 0, 2, 2, 3, 0, 0, 0],
|
||||
pierce: [false, false, false, false, false, false, true, true, true],
|
||||
color: '#b0483f',
|
||||
accent: '#ff8a7a',
|
||||
hotkey: '5',
|
||||
},
|
||||
}
|
||||
|
||||
/** max tower level */
|
||||
export const MAX_TOWER_LEVEL = 9
|
||||
|
||||
/** tier of a tower level: 0 = yellow (1-3), 1 = orange (4-6), 2 = blue (7-9) */
|
||||
export function towerTier(level: number): number {
|
||||
return Math.min(2, Math.floor((level - 1) / 3))
|
||||
}
|
||||
|
||||
/** tier colors for level pips, stars and auras */
|
||||
export const TIER_COLORS = ['#ffd23e', '#ff9c40', '#4da3ff']
|
||||
|
||||
export const ENEMIES: Record<EnemyKind, EnemyDef> = {
|
||||
normal: {
|
||||
kind: 'normal',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue