// Workshop System (Crafting, 3-Tier Plant Upgrades, and Passive Perks) window.WorkshopSystem = class WorkshopSystem { constructor(economy) { this.economy = economy; // Default Materials this.materials = { bioHumus: 10, scrapMetal: 5, sunEssence: 20, crystals: 0 }; // Plant Upgrade Levels (1, 2, 3) this.plantLevels = { peashooter: 1, sunflower: 1, wallnut: 1, potatomine: 1, repeater: 1, snowpea: 1, chomper: 1 }; // Passive Perks (0, 1, 2, 3) this.perks = { magnetism: 0, startSun: 0, fastCool: 0, hardyRoots: 0, luckyDrop: 0 }; // Flying loot items on canvas this.floatingLoot = []; // Upgrade Definitions this.plantDefs = { peashooter: { name: 'Горохострел', icon: '🌱', tiers: { 1: { title: 'Базовый', desc: 'Урон 20, интервал 1.4с' }, 2: { title: 'Скорострел', desc: 'Урон 25, атака +20%, крит 15% (x2 урон)', cost: { coins: 150, bioHumus: 8 } }, 3: { title: 'Плазменный стрелок', desc: 'Пробивает 1-го зомби насквозь и ранит следующего', cost: { coins: 400, bioHumus: 20, crystals: 1 } } } }, sunflower: { name: 'Подсолнух', icon: '🌻', tiers: { 1: { title: 'Базовый', desc: 'Дает 25 ☀️ каждые 12с' }, 2: { title: 'Крупный подсолнух', desc: 'Дает 35 ☀️ каждые 10с', cost: { coins: 120, sunEssence: 15 } }, 3: { title: 'Благодатный свет', desc: 'При генерации лечит +30 HP соседним растениям', cost: { coins: 350, sunEssence: 35, crystals: 1 } } } }, wallnut: { name: 'Стеноорех', icon: '🌰', tiers: { 1: { title: 'Базовый', desc: '400 HP' }, 2: { title: 'Каменный монолит', desc: '700 HP + 15% снижения входящего урона', cost: { coins: 150, scrapMetal: 10 } }, 3: { title: 'Шипованный бастион', desc: '1000 HP + возврат 30% урона кусающим зомби', cost: { coins: 400, scrapMetal: 25, crystals: 1 } } } }, potatomine: { name: 'Картофельная мина', icon: '🥔', tiers: { 1: { title: 'Базовый', desc: 'Взведение 15с, взрыв в клетке' }, 2: { title: 'Быстрый фитиль', desc: 'Взведение всего за 6 секунд!', cost: { coins: 120, bioHumus: 8, scrapMetal: 5 } }, 3: { title: 'Атомный Spudow', desc: 'Взрыв 3x3 + горящая лужа лавы на 5с', cost: { coins: 350, bioHumus: 18, scrapMetal: 15, crystals: 1 } } } }, repeater: { name: 'Повторитель', icon: '🌿', tiers: { 1: { title: 'Базовый', desc: '2 горошины за выстрел' }, 2: { title: 'Тройной залп', desc: '2 горошины + 20% шанс выпустить 3-ю', cost: { coins: 250, bioHumus: 15, sunEssence: 10 } }, 3: { title: 'Огненный повторитель', desc: 'Горошины пылают и наносят сплэш-урон', cost: { coins: 600, bioHumus: 30, sunEssence: 25, crystals: 2 } } } }, snowpea: { name: 'Ледяной горох', icon: '❄️', tiers: { 1: { title: 'Базовый', desc: 'Замедление 4с, урон 20' }, 2: { title: 'Вечная мерзлота', desc: 'Холод 6с + замедляет соседей сзади', cost: { coins: 250, bioHumus: 15, crystals: 1 } }, 3: { title: 'Ледяная глыба', desc: 'Шанс 15% полностью обратить зомби в лед на 2с', cost: { coins: 600, bioHumus: 30, crystals: 3 } } } }, chomper: { name: 'Зубастик', icon: '🌺', tiers: { 1: { title: 'Базовый', desc: 'Заглатывает зомби, жевание 30с' }, 2: { title: 'Острые клыки', desc: 'Скорость жевания ускорена до 14с', cost: { coins: 200, bioHumus: 15, scrapMetal: 10 } }, 3: { title: 'Двойной укус', desc: 'Способен проглотить сразу двух зомби подряд!', cost: { coins: 500, bioHumus: 30, scrapMetal: 20, crystals: 1 } } } } }; this.perkDefs = { magnetism: { name: 'Магнитный газон', icon: '🧲', desc: 'Автоматически притягивает монеты, солнце и материалы', tiers: { 1: { title: 'Ур. 1', desc: 'Радиус сбора +40px', cost: { coins: 150, scrapMetal: 5 } }, 2: { title: 'Ур. 2', desc: 'Радиус сбора +90px', cost: { coins: 300, scrapMetal: 12 } }, 3: { title: 'Ур. 3', desc: 'Полный автосбор со всего экрана!', cost: { coins: 600, scrapMetal: 25, crystals: 1 } } } }, startSun: { name: 'Стартовый капитал', icon: '☀️', desc: 'Дополнительное солнце в начале каждого раунда', tiers: { 1: { title: 'Ур. 1', desc: '+50 начального солнца', cost: { coins: 150, sunEssence: 15 } }, 2: { title: 'Ур. 2', desc: '+100 начального солнца', cost: { coins: 350, sunEssence: 30 } }, 3: { title: 'Ур. 3', desc: '+150 начального солнца', cost: { coins: 700, sunEssence: 60, crystals: 1 } } } }, fastCool: { name: 'Ускоренный полив', icon: '⏳', desc: 'Сокращает время перезарядки всех пакетов семян', tiers: { 1: { title: 'Ур. 1', desc: 'Перезарядка -10%', cost: { coins: 200, bioHumus: 10 } }, 2: { title: 'Ур. 2', desc: 'Перезарядка -20%', cost: { coins: 450, bioHumus: 25 } }, 3: { title: 'Ур. 3', desc: 'Перезарядка -30%', cost: { coins: 900, bioHumus: 50, crystals: 2 } } } }, hardyRoots: { name: 'Упорные корни', icon: '🛡️', desc: 'Увеличивает максимальное здоровье всех растений на газоне', tiers: { 1: { title: 'Ур. 1', desc: '+20% к запасу здоровья', cost: { coins: 180, scrapMetal: 10, bioHumus: 10 } }, 2: { title: 'Ур. 2', desc: '+35% к запасу здоровья', cost: { coins: 400, scrapMetal: 20, bioHumus: 20 } }, 3: { title: 'Ур. 3', desc: '+50% к запасу здоровья', cost: { coins: 800, scrapMetal: 40, bioHumus: 40, crystals: 1 } } } }, luckyDrop: { name: 'Золотая рука', icon: '🍀', desc: 'Повышает шанс выпадения золотых монет и редких материалов', tiers: { 1: { title: 'Ур. 1', desc: 'Шанс дропа +30%', cost: { coins: 200, crystals: 1 } }, 2: { title: 'Ур. 2', desc: 'Шанс дропа +60%', cost: { coins: 500, crystals: 2 } }, 3: { title: 'Ур. 3', desc: 'Шанс дропа +100%', cost: { coins: 1000, crystals: 4 } } } } }; this.loadFromAuth(); } loadFromAuth() { const defaultMaterials = { bioHumus: 10, scrapMetal: 5, sunEssence: 20, crystals: 0 }; const defaultPlantLevels = { peashooter: 1, sunflower: 1, wallnut: 1, potatomine: 1, repeater: 1, snowpea: 1, chomper: 1 }; const defaultPerks = { magnetism: 0, startSun: 0, fastCool: 0, hardyRoots: 0, luckyDrop: 0 }; if (window.PvZAuth) { const data = window.PvZAuth.getUserData(); this.materials = { ...defaultMaterials, ...(data.materials || {}) }; this.plantLevels = { ...defaultPlantLevels, ...(data.plantLevels || {}) }; this.perks = { ...defaultPerks, ...(data.perks || {}) }; } else { this.materials = { ...defaultMaterials }; this.plantLevels = { ...defaultPlantLevels }; this.perks = { ...defaultPerks }; } } saveToAuth() { if (window.PvZAuth && !window.PvZAuth.isGuest()) { window.PvZAuth.saveUserData({ materials: this.materials, plantLevels: this.plantLevels, perks: this.perks, coins: this.economy ? this.economy.totalCoins : undefined }); } } getPlantLevel(plantType) { return this.plantLevels[plantType] || 1; } getPerkLevel(perkId) { return this.perks[perkId] || 0; } canAffordCost(cost) { if (!cost) return false; const coins = this.economy ? this.economy.totalCoins : 0; if (cost.coins && coins < cost.coins) return false; if (cost.bioHumus && this.materials.bioHumus < cost.bioHumus) return false; if (cost.scrapMetal && this.materials.scrapMetal < cost.scrapMetal) return false; if (cost.sunEssence && this.materials.sunEssence < cost.sunEssence) return false; if (cost.crystals && this.materials.crystals < cost.crystals) return false; return true; } payCost(cost) { if (!this.canAffordCost(cost)) return false; if (cost.coins && this.economy) this.economy.addCoins(-cost.coins); if (cost.bioHumus) this.materials.bioHumus -= cost.bioHumus; if (cost.scrapMetal) this.materials.scrapMetal -= cost.scrapMetal; if (cost.sunEssence) this.materials.sunEssence -= cost.sunEssence; if (cost.crystals) this.materials.crystals -= cost.crystals; this.saveToAuth(); return true; } upgradePlant(plantId) { const current = this.getPlantLevel(plantId); if (current >= 3) return false; const nextTier = current + 1; const def = this.plantDefs[plantId]; if (!def || !def.tiers[nextTier]) return false; const cost = def.tiers[nextTier].cost; if (this.payCost(cost)) { this.plantLevels[plantId] = nextTier; this.saveToAuth(); if (nextTier === 3 && this.economy && this.economy.engine && this.economy.engine.achievements) { this.economy.engine.achievements.trigger('tier3_unlocked'); } if (window.PvZAudio) window.PvZAudio.playWin(); return true; } return false; } upgradePerk(perkId) { const current = this.getPerkLevel(perkId); if (current >= 3) return false; const nextTier = current + 1; const def = this.perkDefs[perkId]; if (!def || !def.tiers[nextTier]) return false; const cost = def.tiers[nextTier].cost; if (this.payCost(cost)) { this.perks[perkId] = nextTier; this.saveToAuth(); if (window.PvZAudio) window.PvZAudio.playWin(); return true; } return false; } addMaterial(type, amount = 1) { if (this.materials[type] !== undefined) { this.materials[type] += amount; this.saveToAuth(); } } // Spawn visual drop on field spawnLoot(x, y, type) { this.floatingLoot.push({ x, y, startY: y, targetY: Math.min(y + 25, 550), type, animTime: 0, vy: -120, collected: false, alpha: 1.0 }); } update(dt, gameState) { // Check loot collection and animation const mousePos = gameState.hoverCell ? gameState.grid.getCellBounds(gameState.hoverCell.col, gameState.hoverCell.row) : null; const magLevel = this.getPerkLevel('magnetism'); const magnetRadius = magLevel === 3 ? 9999 : (magLevel === 2 ? 140 : (magLevel === 1 ? 80 : 35)); for (let i = this.floatingLoot.length - 1; i >= 0; i--) { const loot = this.floatingLoot[i]; loot.animTime += dt; if (!loot.collected) { if (loot.vy < 0) { loot.y += loot.vy * dt; loot.vy += 300 * dt; } // Magnetism collection if (gameState.hoverCell) { const bounds = gameState.grid.getCellBounds(gameState.hoverCell.col, gameState.hoverCell.row); const dist = Math.hypot(bounds.centerX - loot.x, bounds.centerY - loot.y); if (dist <= magnetRadius) { this.collectLoot(loot); } } } else { loot.y -= 100 * dt; loot.alpha -= 2.0 * dt; if (loot.alpha <= 0) { this.floatingLoot.splice(i, 1); } } } } collectLoot(loot) { if (loot.collected) return; loot.collected = true; this.addMaterial(loot.type, 1); if (window.PvZAudio) window.PvZAudio.playCoin(); } draw(ctx) { for (const loot of this.floatingLoot) { ctx.save(); ctx.globalAlpha = Math.max(0, loot.alpha); ctx.translate(loot.x, loot.y); // Bounce bobbing const bob = Math.sin(loot.animTime * 6) * 3; ctx.translate(0, bob); // Glow circle ctx.beginPath(); ctx.arc(0, 0, 16, 0, Math.PI * 2); ctx.fillStyle = loot.type === 'crystals' ? 'rgba(0, 229, 255, 0.4)' : (loot.type === 'sunEssence' ? 'rgba(255, 235, 59, 0.4)' : (loot.type === 'scrapMetal' ? 'rgba(158, 158, 158, 0.4)' : 'rgba(139, 195, 74, 0.4)')); ctx.fill(); // Icon ctx.font = '16px sans-serif'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; const icon = loot.type === 'crystals' ? '💎' : (loot.type === 'sunEssence' ? '☀️' : (loot.type === 'scrapMetal' ? '⚙️' : '🧪')); ctx.fillText(icon, 0, 1); ctx.restore(); } } };