// Garden Roguelike System: Seed Drafting, Artifact Relics, and Progressive Stage Escalation window.RoguelikeSystem = class RoguelikeSystem { constructor(gameEngine) { this.engine = gameEngine; this.activeRelics = []; this.currentFloor = 1; this.draftChoices = []; // All available relics in Roguelike mode this.relicPool = [ { id: 'relic_lightning', name: 'Громоотвод', icon: '⚡', desc: 'Каждые 7 секунд молния бьет в передового зомби, нанося 160 урона.', timer: 7 }, { id: 'relic_toxic_soil', name: 'Токсичный перегной', icon: '🧪', desc: 'Вся почва выделяет споры: все зомби замедлены на 15% и получают 6 ед. яда в секунду.' }, { id: 'relic_sun_resonance', name: 'Солнечный резонанс', icon: '☀️', desc: 'Все подсолнухи производят на +15 больше солнца за каждую вспышку.' }, { id: 'relic_iron_bark', name: 'Титановая кора', icon: '🛡️', desc: 'Все высаживаемые Стеноорехи моментально получают щит прочности +350 HP.' }, { id: 'relic_vampire_sap', name: 'Вампирский сок', icon: '💖', desc: 'Каждое уничтожение зомби восстанавливает +40 HP самому раненому растению.' }, { id: 'relic_fertilizer_boost', name: 'Гормон роста', icon: '🌿', desc: 'Все стрелковые растения атакуют на 20% быстрее.' } ]; // Seed draft candidates this.plantPool = [ 'snowpea', 'repeater', 'wallnut', 'potatomine', 'chomper', 'cherrybomb', 'jalapeno', 'fumeshroom' ]; } reset() { this.activeRelics = []; this.currentFloor = 1; this.draftChoices = []; } hasRelic(id) { return this.activeRelics.some(r => r.id === id); } addRelic(relic) { if (!this.hasRelic(relic.id)) { this.activeRelics.push({ ...relic, timer: relic.timer || 0 }); if (this.engine && this.engine.achievements) { this.engine.achievements.trigger('roguelike_relic'); } } } // Generate 3 choices: seeds or relics generateDraftChoices() { const choices = []; const availableRelics = this.relicPool.filter(r => !this.hasRelic(r.id)); // 1-2 Relic choices if (availableRelics.length > 0) { const shuffledRelics = [...availableRelics].sort(() => 0.5 - Math.random()); const r = shuffledRelics[0]; choices.push({ type: 'relic', id: r.id, name: r.name, icon: r.icon, desc: r.desc, raw: r }); } // Seed choices: plants not currently in economy deck const currentCards = this.engine && this.engine.economy ? this.engine.economy.cards.map(c => c.id) : []; const availablePlants = this.plantPool.filter(p => !currentCards.includes(p)); const shuffledPlants = [...availablePlants].sort(() => 0.5 - Math.random()); for (const pId of shuffledPlants.slice(0, 3 - choices.length)) { const def = this.engine.workshop ? this.engine.workshop.plantDefs[pId] : null; choices.push({ type: 'seed', id: pId, name: def ? def.name : pId, icon: def ? def.icon : '🌱', desc: `Добавляет семя ${def ? def.name : pId} в колоду для текущего забега!`, raw: pId }); } // Fill remaining if needed while (choices.length < 3 && this.plantPool.length > 0) { const pId = this.plantPool[choices.length % this.plantPool.length]; choices.push({ type: 'seed', id: pId, name: pId, icon: '🌱', desc: `Дополнительное семя для текущего забега.`, raw: pId }); } this.draftChoices = choices; return choices; } selectChoice(index) { const choice = this.draftChoices[index]; if (!choice) return false; if (choice.type === 'relic') { this.addRelic(choice.raw); } else if (choice.type === 'seed' && this.engine && this.engine.economy) { // Add seed to deck const newCard = this.engine.economy.allCards.find(c => c.id === choice.raw); if (newCard && !this.engine.economy.cards.some(c => c.id === newCard.id)) { this.engine.economy.cards.push({ ...newCard, timer: 0 }); } } this.currentFloor++; return true; } update(dt, gameState) { // 1. Relic: Lightning strike const lightning = this.activeRelics.find(r => r.id === 'relic_lightning'); if (lightning) { lightning.timer = (lightning.timer || 7) - dt; if (lightning.timer <= 0) { lightning.timer = 7; const target = gameState.zombies.find(z => z.health > 0 && !z.toRemove); if (target) { target.takeDamage(160); gameState.combat.createExplosionParticles(target.x, target.y); if (window.PvZAudio) window.PvZAudio.playStrike(); } } } // 2. Relic: Toxic soil poison damage if (this.hasRelic('relic_toxic_soil')) { for (const z of gameState.zombies) { if (z.health > 0 && !z.toRemove) { z.takeDamage(6 * dt); z.speedModifier = Math.min(z.speedModifier, 0.85); } } } } // Draw active relic badges in HUD draw(ctx) { if (this.activeRelics.length === 0) return; ctx.save(); let rx = 580; const ry = 52; for (const relic of this.activeRelics) { ctx.fillStyle = 'rgba(0, 0, 0, 0.55)'; ctx.beginPath(); ctx.roundRect(rx, ry, 26, 26, 4); ctx.fill(); ctx.strokeStyle = '#ffd700'; ctx.lineWidth = 1.5; ctx.stroke(); ctx.font = '14px sans-serif'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText(relic.icon, rx + 13, ry + 13); rx += 30; } ctx.restore(); } };