diff --git a/src/scenes/GameScene.js b/src/scenes/GameScene.js index 21823d117..0d6fc43a4 100644 --- a/src/scenes/GameScene.js +++ b/src/scenes/GameScene.js @@ -1478,981 +1478,982 @@ class GameScene extends Phaser.Scene { } this.saveWeatherState(); + } // ✅ ADDED MISSING CLOSING BRACE + } + + stopAllWeather() { + // Stop all particle emitters + if (this.rainEmitter) this.rainEmitter.stop(); + if (this.snowEmitter) this.snowEmitter.stop(); + if (this.stormEmitter) this.stormEmitter.stop(); + + // Stop lightning + if (this.lightningTimer) { + this.lightningTimer.destroy(); + this.lightningTimer = null; } - stopAllWeather() { - // Stop all particle emitters - if (this.rainEmitter) this.rainEmitter.stop(); - if (this.snowEmitter) this.snowEmitter.stop(); - if (this.stormEmitter) this.stormEmitter.stop(); + // Stop puddle spawning + if (this.puddleTimer) { + this.puddleTimer.destroy(); + this.puddleTimer = null; + } - // Stop lightning - if (this.lightningTimer) { - this.lightningTimer.destroy(); - this.lightningTimer = null; + // Fade out fog + if (this.fogOverlay) { + this.tweens.add({ + targets: this.fogOverlay, + alpha: 0, + duration: 2000, + onComplete: () => { + if (this.fogOverlay) this.fogOverlay.destroy(); + this.fogOverlay = null; + } + }); + } + + // Cleanup puddles + this.puddles.forEach(puddle => { + this.tweens.add({ + targets: puddle, + alpha: 0, + duration: 3000, + onComplete: () => puddle.destroy() + }); + }); + this.puddles = []; + } + + // ☔ RAIN SYSTEM + startRain() { + if (!this.rainEmitter) { + this.createRainParticles(); + } + + // Apply intensity + this.rainEmitter.setQuantity(Math.floor(3 * this.weatherIntensity)); + this.rainEmitter.setFrequency(30 / this.weatherIntensity); + + this.rainEmitter.start(); + console.log('🌧️ Rain started!'); + + // Start puddle spawning + this.puddleTimer = this.time.addEvent({ + delay: 3000 / this.weatherIntensity, + callback: () => this.spawnPuddle(), + loop: true + }); + + // Play rain sound + if (this.soundManager && this.soundManager.playRainSound) { + this.soundManager.playRainSound(); + } + } + + createRainParticles() { + if (!this.textures.exists('raindrop')) { + const graphics = this.make.graphics({ x: 0, y: 0, add: false }); + graphics.fillStyle(0x88ccff, 1); + graphics.fillCircle(1, 2, 1); + graphics.generateTexture('raindrop', 2, 4); + graphics.destroy(); + } + + const cam = this.cameras.main; + this.rainEmitter = this.add.particles(0, 0, 'raindrop', { + x: { min: 0, max: cam.width }, + y: -50, + lifespan: 3000, + speedY: { min: 400, max: 600 }, + scale: { start: 1, end: 0.5 }, + alpha: { start: 0.6, end: 0.2 }, + quantity: 3, + frequency: 30, + blendMode: 'ADD', + + // 🌊 DETECT WHEN RAINDROP HITS GROUND + deathCallback: (particle) => { + // Convert camera-relative position to world position + const worldX = particle.x + cam.scrollX; + const worldY = particle.y + cam.scrollY; + + // Check if hit water tile + this.checkRainImpactOnWater(worldX, worldY); } + }); - // Stop puddle spawning - if (this.puddleTimer) { - this.puddleTimer.destroy(); - this.puddleTimer = null; - } + this.rainEmitter.setScrollFactor(0); + this.rainEmitter.setDepth(999999); + this.rainEmitter.stop(); + } - // Fade out fog - if (this.fogOverlay) { - this.tweens.add({ - targets: this.fogOverlay, - alpha: 0, - duration: 2000, - onComplete: () => { - if (this.fogOverlay) this.fogOverlay.destroy(); - this.fogOverlay = null; - } - }); - } + // ❄️ SNOW SYSTEM + startSnow() { + if (!this.snowEmitter) { + this.createSnowParticles(); + } - // Cleanup puddles - this.puddles.forEach(puddle => { + this.snowEmitter.start(); + console.log('❄️ Snow started!'); + } + + createSnowParticles() { + if (!this.textures.exists('snowflake')) { + const graphics = this.make.graphics({ x: 0, y: 0, add: false }); + graphics.fillStyle(0xffffff, 1); + graphics.fillCircle(2, 2, 2); + graphics.generateTexture('snowflake', 4, 4); + graphics.destroy(); + } + + const cam = this.cameras.main; + this.snowEmitter = this.add.particles(0, 0, 'snowflake', { + x: { min: 0, max: cam.width }, + y: -50, + lifespan: 8000, + speedY: { min: 50, max: 150 }, + speedX: { min: -30, max: 30 }, + scale: { start: 0.5, end: 1.5 }, + alpha: { start: 0.8, end: 0.3 }, + quantity: 2, + frequency: 80, + blendMode: 'ADD' + }); + + this.snowEmitter.setScrollFactor(0); + this.snowEmitter.setDepth(999999); + this.snowEmitter.stop(); + } + + // ⚡ STORM SYSTEM + startStorm() { + if (!this.stormEmitter) { + this.createStormParticles(); + } + + this.stormEmitter.start(); + console.log('⛈️ Storm started!'); + + // Lightning flashes + this.lightningTimer = this.time.addEvent({ + delay: Phaser.Math.Between(3000, 8000), + callback: () => this.triggerLightning(), + loop: true + }); + + // Puddles (faster spawn) + this.puddleTimer = this.time.addEvent({ + delay: 2000, + callback: () => this.spawnPuddle(), + loop: true + }); + } + + createStormParticles() { + if (!this.textures.exists('raindrop')) { + this.createRainParticles(); + } + + const cam = this.cameras.main; + this.stormEmitter = this.add.particles(0, 0, 'raindrop', { + x: { min: 0, max: cam.width }, + y: -50, + lifespan: 2000, + speedY: { min: 600, max: 900 }, + speedX: { min: 50, max: 150 }, + scale: { start: 1.5, end: 0.5 }, + alpha: { start: 0.8, end: 0.3 }, + quantity: 5, + frequency: 20, + blendMode: 'ADD' + }); + + this.stormEmitter.setScrollFactor(0); + this.stormEmitter.setDepth(999999); + this.stormEmitter.stop(); + } + + triggerLightning() { + // White flash overlay + const flash = this.add.rectangle( + this.cameras.main.scrollX, + this.cameras.main.scrollY, + this.cameras.main.width, + this.cameras.main.height, + 0xffffff, + 0.8 + ); + flash.setOrigin(0, 0); + flash.setScrollFactor(0); + flash.setDepth(1000000); + + // Fade out + this.tweens.add({ + targets: flash, + alpha: 0, + duration: 200, + onComplete: () => flash.destroy() + }); + + // Screen shake + this.cameras.main.shake(200, 0.005); + + // Thunder sound (if available) + if (this.soundManager && this.soundManager.playThunderSound) { + this.time.delayedCall(300, () => { + this.soundManager.playThunderSound(); + }); + } + + console.log('⚡ Lightning strike!'); + } + + // 🌫️ FOG SYSTEM + startFog() { + if (!this.fogOverlay) { + this.fogOverlay = this.add.rectangle( + 0, 0, + this.cameras.main.width * 2, + this.cameras.main.height * 2, + 0xcccccc, + 0 + ); + this.fogOverlay.setOrigin(0, 0); + this.fogOverlay.setScrollFactor(0); + this.fogOverlay.setDepth(500000); + } + + this.tweens.add({ + targets: this.fogOverlay, + alpha: 0.4, + duration: 3000 + }); + + console.log('🌫️ Fog started!'); + } + + + // 💧 PUDDLES SYSTEM (Spawn on grass/dirt where rain lands!) + spawnPuddle() { + if (!this.terrainSystem) return; + + const cam = this.cameras.main; + const worldX = cam.scrollX + Phaser.Math.Between(100, cam.width - 100); + const worldY = cam.scrollY + Phaser.Math.Between(100, cam.height - 100); + + // 🎨 FLAT 2D CONVERSION (NEW!) + const tileSize = 48; + const x = Math.floor(worldX / tileSize); + const y = Math.floor(worldY / tileSize); + + // Get tile type + const tile = this.terrainSystem.getTile(x, y); + + // ONLY spawn puddles on grass or dirt! + if (!tile || (tile.type !== 'grass' && tile.type !== 'dirt' && tile.type !== 'farmland')) { + return; // Skip - not valid surface + } + + // Limit max puddles + if (this.puddles.length >= 15) { + const oldest = this.puddles.shift(); + if (oldest && oldest.active) oldest.destroy(); + } + + // Create puddle SPRITE (realistic!) + const puddle = this.add.image(worldX, worldY, 'luza_sprite'); + puddle.setOrigin(0.5, 0.5); + puddle.setScale(1.5); // BIGGER - more visible! + puddle.setDepth(10); // ABOVE terrain + puddle.setScrollFactor(1); + puddle.setAlpha(0); // Start invisible + + // Fade in + this.tweens.add({ + targets: puddle, + alpha: 0.35, + duration: 2000 + }); + + this.puddles.push(puddle); + + // Auto cleanup after 30 seconds + this.time.delayedCall(30000, () => { + if (puddle && puddle.active) { this.tweens.add({ targets: puddle, alpha: 0, duration: 3000, - onComplete: () => puddle.destroy() - }); - }); - this.puddles = []; - } - - // ☔ RAIN SYSTEM - startRain() { - if (!this.rainEmitter) { - this.createRainParticles(); - } - - // Apply intensity - this.rainEmitter.setQuantity(Math.floor(3 * this.weatherIntensity)); - this.rainEmitter.setFrequency(30 / this.weatherIntensity); - - this.rainEmitter.start(); - console.log('🌧️ Rain started!'); - - // Start puddle spawning - this.puddleTimer = this.time.addEvent({ - delay: 3000 / this.weatherIntensity, - callback: () => this.spawnPuddle(), - loop: true - }); - - // Play rain sound - if (this.soundManager && this.soundManager.playRainSound) { - this.soundManager.playRainSound(); - } - } - - createRainParticles() { - if (!this.textures.exists('raindrop')) { - const graphics = this.make.graphics({ x: 0, y: 0, add: false }); - graphics.fillStyle(0x88ccff, 1); - graphics.fillCircle(1, 2, 1); - graphics.generateTexture('raindrop', 2, 4); - graphics.destroy(); - } - - const cam = this.cameras.main; - this.rainEmitter = this.add.particles(0, 0, 'raindrop', { - x: { min: 0, max: cam.width }, - y: -50, - lifespan: 3000, - speedY: { min: 400, max: 600 }, - scale: { start: 1, end: 0.5 }, - alpha: { start: 0.6, end: 0.2 }, - quantity: 3, - frequency: 30, - blendMode: 'ADD', - - // 🌊 DETECT WHEN RAINDROP HITS GROUND - deathCallback: (particle) => { - // Convert camera-relative position to world position - const worldX = particle.x + cam.scrollX; - const worldY = particle.y + cam.scrollY; - - // Check if hit water tile - this.checkRainImpactOnWater(worldX, worldY); - } - }); - - this.rainEmitter.setScrollFactor(0); - this.rainEmitter.setDepth(999999); - this.rainEmitter.stop(); - } - - // ❄️ SNOW SYSTEM - startSnow() { - if (!this.snowEmitter) { - this.createSnowParticles(); - } - - this.snowEmitter.start(); - console.log('❄️ Snow started!'); - } - - createSnowParticles() { - if (!this.textures.exists('snowflake')) { - const graphics = this.make.graphics({ x: 0, y: 0, add: false }); - graphics.fillStyle(0xffffff, 1); - graphics.fillCircle(2, 2, 2); - graphics.generateTexture('snowflake', 4, 4); - graphics.destroy(); - } - - const cam = this.cameras.main; - this.snowEmitter = this.add.particles(0, 0, 'snowflake', { - x: { min: 0, max: cam.width }, - y: -50, - lifespan: 8000, - speedY: { min: 50, max: 150 }, - speedX: { min: -30, max: 30 }, - scale: { start: 0.5, end: 1.5 }, - alpha: { start: 0.8, end: 0.3 }, - quantity: 2, - frequency: 80, - blendMode: 'ADD' - }); - - this.snowEmitter.setScrollFactor(0); - this.snowEmitter.setDepth(999999); - this.snowEmitter.stop(); - } - - // ⚡ STORM SYSTEM - startStorm() { - if (!this.stormEmitter) { - this.createStormParticles(); - } - - this.stormEmitter.start(); - console.log('⛈️ Storm started!'); - - // Lightning flashes - this.lightningTimer = this.time.addEvent({ - delay: Phaser.Math.Between(3000, 8000), - callback: () => this.triggerLightning(), - loop: true - }); - - // Puddles (faster spawn) - this.puddleTimer = this.time.addEvent({ - delay: 2000, - callback: () => this.spawnPuddle(), - loop: true - }); - } - - createStormParticles() { - if (!this.textures.exists('raindrop')) { - this.createRainParticles(); - } - - const cam = this.cameras.main; - this.stormEmitter = this.add.particles(0, 0, 'raindrop', { - x: { min: 0, max: cam.width }, - y: -50, - lifespan: 2000, - speedY: { min: 600, max: 900 }, - speedX: { min: 50, max: 150 }, - scale: { start: 1.5, end: 0.5 }, - alpha: { start: 0.8, end: 0.3 }, - quantity: 5, - frequency: 20, - blendMode: 'ADD' - }); - - this.stormEmitter.setScrollFactor(0); - this.stormEmitter.setDepth(999999); - this.stormEmitter.stop(); - } - - triggerLightning() { - // White flash overlay - const flash = this.add.rectangle( - this.cameras.main.scrollX, - this.cameras.main.scrollY, - this.cameras.main.width, - this.cameras.main.height, - 0xffffff, - 0.8 - ); - flash.setOrigin(0, 0); - flash.setScrollFactor(0); - flash.setDepth(1000000); - - // Fade out - this.tweens.add({ - targets: flash, - alpha: 0, - duration: 200, - onComplete: () => flash.destroy() - }); - - // Screen shake - this.cameras.main.shake(200, 0.005); - - // Thunder sound (if available) - if (this.soundManager && this.soundManager.playThunderSound) { - this.time.delayedCall(300, () => { - this.soundManager.playThunderSound(); - }); - } - - console.log('⚡ Lightning strike!'); - } - - // 🌫️ FOG SYSTEM - startFog() { - if (!this.fogOverlay) { - this.fogOverlay = this.add.rectangle( - 0, 0, - this.cameras.main.width * 2, - this.cameras.main.height * 2, - 0xcccccc, - 0 - ); - this.fogOverlay.setOrigin(0, 0); - this.fogOverlay.setScrollFactor(0); - this.fogOverlay.setDepth(500000); - } - - this.tweens.add({ - targets: this.fogOverlay, - alpha: 0.4, - duration: 3000 - }); - - console.log('🌫️ Fog started!'); - } - - - // 💧 PUDDLES SYSTEM (Spawn on grass/dirt where rain lands!) - spawnPuddle() { - if (!this.terrainSystem) return; - - const cam = this.cameras.main; - const worldX = cam.scrollX + Phaser.Math.Between(100, cam.width - 100); - const worldY = cam.scrollY + Phaser.Math.Between(100, cam.height - 100); - - // 🎨 FLAT 2D CONVERSION (NEW!) - const tileSize = 48; - const x = Math.floor(worldX / tileSize); - const y = Math.floor(worldY / tileSize); - - // Get tile type - const tile = this.terrainSystem.getTile(x, y); - - // ONLY spawn puddles on grass or dirt! - if (!tile || (tile.type !== 'grass' && tile.type !== 'dirt' && tile.type !== 'farmland')) { - return; // Skip - not valid surface - } - - // Limit max puddles - if (this.puddles.length >= 15) { - const oldest = this.puddles.shift(); - if (oldest && oldest.active) oldest.destroy(); - } - - // Create puddle SPRITE (realistic!) - const puddle = this.add.image(worldX, worldY, 'luza_sprite'); - puddle.setOrigin(0.5, 0.5); - puddle.setScale(1.5); // BIGGER - more visible! - puddle.setDepth(10); // ABOVE terrain - puddle.setScrollFactor(1); - puddle.setAlpha(0); // Start invisible - - // Fade in - this.tweens.add({ - targets: puddle, - alpha: 0.35, - duration: 2000 - }); - - this.puddles.push(puddle); - - // Auto cleanup after 30 seconds - this.time.delayedCall(30000, () => { - if (puddle && puddle.active) { - this.tweens.add({ - targets: puddle, - alpha: 0, - duration: 3000, - onComplete: () => { - puddle.destroy(); - const index = this.puddles.indexOf(puddle); - if (index > -1) this.puddles.splice(index, 1); - } - }); - } - }); - - // Random splash effects - this.time.addEvent({ - delay: Phaser.Math.Between(1000, 3000), - callback: () => { - if (puddle && puddle.active && (this.currentWeather === 'rain' || this.currentWeather === 'storm')) { - this.createSplash(puddle.x, puddle.y); - } - }, - loop: true, - repeat: 5 - }); - } - - // 🌊 CHECK IF RAIN HIT WATER TILE - checkRainImpactOnWater(worldX, worldY) { - if (!this.terrainSystem) return; - - // 🎨 FLAT 2D CONVERSION (NEW!) - const tileSize = 48; - const x = Math.floor(worldX / tileSize); - const y = Math.floor(worldY / tileSize); - - // Get tile at position - const tile = this.terrainSystem.getTile(x, y); - - // If water tile, create ripple! - if (tile && tile.type === 'water') { - this.createWaterRipple(worldX, worldY); - } - // If grass/dirt, 3% chance to spawn puddle - else if (tile && (tile.type === 'grass' || tile.type === 'dirt' || tile.type === 'farmland')) { - if (Math.random() < 0.03) { - this.spawnPuddleAtLocation(worldX, worldY); - } - } - } - - // 💧 CREATE WATER RIPPLE EFFECT - createWaterRipple(x, y) { - // Small expanding circle on water surface - const ripple = this.add.circle(x, y, 2, 0xffffff, 0.5); - ripple.setDepth(500); // Above water tiles - ripple.setScrollFactor(1); // World-bound - - this.tweens.add({ - targets: ripple, - radius: 10, - alpha: 0, - duration: 400, - ease: 'Quad.easeOut', - onComplete: () => ripple.destroy() - }); - } - - // 💧 SPAWN PUDDLE AT EXACT LOCATION (from rain impact) - spawnPuddleAtLocation(worldX, worldY) { - // Limit max puddles - if (this.puddles.length >= 15) { - // Remove oldest puddle - const oldest = this.puddles.shift(); - if (oldest && oldest.active) oldest.destroy(); - } - - // Create puddle SPRITE (realistic!) - const puddle = this.add.image(worldX, worldY, 'luza_sprite'); - puddle.setOrigin(0.5, 0.5); - puddle.setScale(1.5); // BIGGER - more visible! - puddle.setDepth(10); // ABOVE terrain - puddle.setScrollFactor(1); - puddle.setAlpha(0); // Start invisible - - // Fade in - this.tweens.add({ - targets: puddle, - alpha: 0.35, - duration: 2000 - }); - - this.puddles.push(puddle); - - // Auto cleanup after 30 seconds - this.time.delayedCall(30000, () => { - if (puddle && puddle.active) { - this.tweens.add({ - targets: puddle, - alpha: 0, - duration: 3000, - onComplete: () => { - puddle.destroy(); - const index = this.puddles.indexOf(puddle); - if (index > -1) this.puddles.splice(index, 1); - } - }); - } - }); - } - - // 💦 SPLASH EFFECT (Ripples) - createSplash(x, y) { - // Concentric circles - for (let i = 0; i < 3; i++) { - this.time.delayedCall(i * 100, () => { - const circle = this.add.circle(x, y, 3, 0xffffff, 0.5); - circle.setDepth(2); - - this.tweens.add({ - targets: circle, - radius: 20 + (i * 5), - alpha: 0, - duration: 600, - onComplete: () => circle.destroy() - }); - }); - } - } - - update(time, delta) { - if (this.player) { - this.player.update(delta); - - // Apply water physics - if (this.waterPhysics) { - this.waterPhysics.applyWaterPhysics(this.player, delta); - - // Create footstep ripples when moving in water - if (this.waterPhysics.playerInWater && this.waterRipples) { - const velocity = Math.abs(this.player.body.velocity.x) + Math.abs(this.player.body.velocity.y); - if (velocity > 10) { // Only if actually moving - // Random chance to create ripple (not every frame) - if (Math.random() < 0.1) { - this.waterRipples.createFootstepRipple(this.player.x, this.player.y); - } - } - } - } - } - - // 🎯 Z-SORTING: SortableObjects based on Y position - if (this.sortableObjects) { - const children = this.sortableObjects.getChildren(); - - // Sortiranje po Y koordinati (nižji Y = nižji depth) - children.sort((a, b) => a.y - b.y); - - // Nastavi depth glede na vrstni red (index) - children.forEach((obj, index) => { - // Use LAYER_OBJECTS base + index for depth - obj.setDepth(200000 + index); - }); - } - - // Weather UI Update - if (this.weatherUI) this.weatherUI.update(); - - // Update Systems - if (this.terrainSystem) this.terrainSystem.update(time, delta); // Water animation! - if (this.statsSystem) this.statsSystem.update(delta); - if (this.craftingSystem) this.craftingSystem.update(delta); // 🛠️ Crafting progress - if (this.lootSystem) this.lootSystem.update(delta); - if (this.interactionSystem) this.interactionSystem.update(delta); - if (this.farmingSystem) this.farmingSystem.update(delta); - if (this.statusEffectSystem) this.statusEffectSystem.update(time, delta); - if (this.buildSystem) this.buildSystem.update(delta); - if (this.questSystem) this.questSystem.update(delta); - if (this.multiplayerSystem) this.multiplayerSystem.update(delta); - - // Update Master Weather System - if (this.weather && this.weather.update) { - this.weather.update(delta); - } - - if (this.weatherSystem) { - this.weatherSystem.update(delta); - - // Update Lighting (shadows, torches) - if (this.lightingSystem) this.lightingSystem.update(delta); - - // Update Weather Enhancements (wind, tree sway) - if (this.weatherEnhancements) { - this.weatherEnhancements.update(delta); - - // Apply wind to rain if active - if (this.weatherSystem.rainEmitter) { - this.weatherEnhancements.applyWindToRain(this.weatherSystem.rainEmitter); - } - } - - // 🌍 PHASE 28: Update chunk loading based on player position (ONLY for procedural maps!) - if (this.chunkManager && this.player && !this.tiledMapLoaded) { - const pos = this.player.getPosition(); - this.chunkManager.updateActiveChunks(pos.x, pos.y); - } - - // Concept Systems Updates - if (this.zombieSystem) this.zombieSystem.update(this.time.now, delta); - - // Night Logic - if (this.weatherSystem.isNight()) { - const isHorde = this.weatherSystem.isHordeNight(); - const spawnInterval = isHorde ? 2000 : 10000; - - // Check for Horde Start Warning - if (isHorde && !this.hordeWarningShown) { - this.showHordeWarning(); - this.hordeWarningShown = true; - } - - if (!this.nightSpawnTimer) this.nightSpawnTimer = 0; - this.nightSpawnTimer += delta; - - if (this.nightSpawnTimer > spawnInterval) { - this.nightSpawnTimer = 0; - this.spawnNightZombie(); - if (isHorde) { - this.spawnNightZombie(); - this.spawnNightZombie(); - } - } - } else { - this.hordeWarningShown = false; - } - } - - // NPC Update - DISABLED (no NPCs) - /* - for (const npc of this.npcs) { - npc.update(delta); - } - */ - - // Vehicles Update - if (this.vehicles) { - for (const vehicle of this.vehicles) { - if (vehicle.update) vehicle.update(delta); - } - } - - // Spawners Update - if (this.spawners) { - for (const spawner of this.spawners) { - if (spawner.update) spawner.update(delta); - } - } - - // Zombie Worker System - if (this.zombieWorkerSystem) this.zombieWorkerSystem.update(delta); - - // Workstation System - if (this.workstationSystem) this.workstationSystem.update(delta); - - // Grave System Update (regeneration) - if (this.graveSystem) { - this.graveSystem.update(delta); - - // Auto-rest check every 5 seconds - if (!this.graveAutoRestTimer) this.graveAutoRestTimer = 0; - this.graveAutoRestTimer += delta; - if (this.graveAutoRestTimer >= 5000) { - this.graveSystem.autoRest(); - this.graveAutoRestTimer = 0; - } - } - - // 🎵 PHASE 8: Pond Proximity Audio Modulation - if (this.player && this.lakeSystem && this.soundManager) { - const playerPos = this.player.getPosition(); - let minPondDist = 1000; - - // Find nearest pond - this.lakeSystem.lakes.forEach(lake => { - if (lake.type === 'pond' || lake.type === 'lake') { - const d = Phaser.Math.Distance.Between(playerPos.x, playerPos.y, lake.x, lake.y); - if (d < minPondDist) minPondDist = d; + onComplete: () => { + puddle.destroy(); + const index = this.puddles.indexOf(puddle); + if (index > -1) this.puddles.splice(index, 1); } }); - - // Map distance to modulation factor (e.g., 0 within 5 tiles, 1 far away) - // Or 1 at pond center, 0 far away? User said "malo spremeni, ko sem blizu" - // Let's go with 1.0 (max change) at dist=0, and 0.0 (no change) beyond 15 tiles - const modFactor = Phaser.Math.Clamp(1 - (minPondDist / 15), 0, 1); - this.soundManager.setAmbientModulation(modFactor); } + }); - if (this.parallaxSystem && this.player) { - const playerPos = this.player.getPosition(); - // 🎨 FLAT 2D (NEW!) - Direct position, no conversion - const tileSize = 48; - const screenX = playerPos.x * tileSize + tileSize / 2; - const screenY = playerPos.y * tileSize + tileSize / 2; - this.parallaxSystem.update(screenX, screenY); + // Random splash effects + this.time.addEvent({ + delay: Phaser.Math.Between(1000, 3000), + callback: () => { + if (puddle && puddle.active && (this.currentWeather === 'rain' || this.currentWeather === 'storm')) { + this.createSplash(puddle.x, puddle.y); + } + }, + loop: true, + repeat: 5 + }); + } + + // 🌊 CHECK IF RAIN HIT WATER TILE + checkRainImpactOnWater(worldX, worldY) { + if (!this.terrainSystem) return; + + // 🎨 FLAT 2D CONVERSION (NEW!) + const tileSize = 48; + const x = Math.floor(worldX / tileSize); + const y = Math.floor(worldY / tileSize); + + // Get tile at position + const tile = this.terrainSystem.getTile(x, y); + + // If water tile, create ripple! + if (tile && tile.type === 'water') { + this.createWaterRipple(worldX, worldY); + } + // If grass/dirt, 3% chance to spawn puddle + else if (tile && (tile.type === 'grass' || tile.type === 'dirt' || tile.type === 'farmland')) { + if (Math.random() < 0.03) { + this.spawnPuddleAtLocation(worldX, worldY); } + } + } + // 💧 CREATE WATER RIPPLE EFFECT + createWaterRipple(x, y) { + // Small expanding circle on water surface + const ripple = this.add.circle(x, y, 2, 0xffffff, 0.5); + ripple.setDepth(500); // Above water tiles + ripple.setScrollFactor(1); // World-bound + this.tweens.add({ + targets: ripple, + radius: 10, + alpha: 0, + duration: 400, + ease: 'Quad.easeOut', + onComplete: () => ripple.destroy() + }); + } - // Clouds - if (this.clouds) { - for (const cloud of this.clouds) { - if (cloud && cloud.sprite) { - cloud.sprite.x += cloud.speed * (delta / 1000); - if (cloud.sprite.x > this.terrainOffsetX + 2000) { - cloud.sprite.x = this.terrainOffsetX - 2000; - cloud.sprite.y = Phaser.Math.Between(0, 1000); - } + // 💧 SPAWN PUDDLE AT EXACT LOCATION (from rain impact) + spawnPuddleAtLocation(worldX, worldY) { + // Limit max puddles + if (this.puddles.length >= 15) { + // Remove oldest puddle + const oldest = this.puddles.shift(); + if (oldest && oldest.active) oldest.destroy(); + } + + // Create puddle SPRITE (realistic!) + const puddle = this.add.image(worldX, worldY, 'luza_sprite'); + puddle.setOrigin(0.5, 0.5); + puddle.setScale(1.5); // BIGGER - more visible! + puddle.setDepth(10); // ABOVE terrain + puddle.setScrollFactor(1); + puddle.setAlpha(0); // Start invisible + + // Fade in + this.tweens.add({ + targets: puddle, + alpha: 0.35, + duration: 2000 + }); + + this.puddles.push(puddle); + + // Auto cleanup after 30 seconds + this.time.delayedCall(30000, () => { + if (puddle && puddle.active) { + this.tweens.add({ + targets: puddle, + alpha: 0, + duration: 3000, + onComplete: () => { + puddle.destroy(); + const index = this.puddles.indexOf(puddle); + if (index > -1) this.puddles.splice(index, 1); } - } + }); } - - if (this.worldEventSystem) this.worldEventSystem.update(delta); - - // FPS Monitor Update - if (this.fpsMonitor) this.fpsMonitor.update(); - - // Performance Monitor Update - if (this.performanceMonitor) this.performanceMonitor.update(delta); - - // NPC Spawner Update - if (this.npcSpawner) this.npcSpawner.update(delta); - - // Visual Sound Cue System Update - if (this.visualSoundCueSystem) this.visualSoundCueSystem.update(); - - // Screen Reader System Update - if (this.screenReader) this.screenReader.update(); - - // Motor Accessibility System Update - if (this.motorAccessibility) this.motorAccessibility.update(); - - // Visual Enhancement System Update - if (this.visualEnhancements) this.visualEnhancements.update(delta); - - // Fog of War System Update - if (this.fogOfWar) this.fogOfWar.update(); - - // Farm Automation System Update - if (this.farmAutomation) this.farmAutomation.update(delta); - - // Animal Breeding System Update - if (this.animalBreeding) this.animalBreeding.update(delta); - - // Automation Tier System Update - if (this.automationTiers) this.automationTiers.update(delta); - - // Cooking System Update - if (this.cooking) this.cooking.update(delta); - - // Fishing System Update - if (this.fishing) this.fishing.update(delta); - - // Worker Creatures System Update - if (this.workerCreatures) this.workerCreatures.update(delta); - - // Boss Battles System Update - if (this.bossBattles) this.bossBattles.update(delta); - - // Multiplayer & Social System Update - if (this.multiplayerSocial) this.multiplayerSocial.update(delta); - - // Technical & Performance System Update - if (this.technicalPerformance) this.technicalPerformance.update(delta); - - // Platform Support System Update - if (this.platformSupport) this.platformSupport.update(delta); - - // Save System Expansion Update - if (this.saveSystemExpansion) this.saveSystemExpansion.update(delta); - - // Update NPCs - for (const npc of this.npcs) { - if (npc.update) npc.update(delta); - } - - // Update Unified Stats Panel - if (this.unifiedStatsPanel) { - this.unifiedStatsPanel.update(delta); - } - - // Update Full Inventory UI - if (this.fullInventoryUI) { - this.fullInventoryUI.update(); - } - - // Run Antigravity Engine Update - this.Antigravity_Update(delta); - } - - spawnNightZombie() { - // DISABLED - No NPCs allowed - return; - - /* - if (!this.player || this.npcs.length > 50) return; - - const playerPos = this.player.getPosition(); - const angle = Math.random() * Math.PI * 2; - const distance = Phaser.Math.Between(15, 25); - - const spawnX = Math.floor(playerPos.x + Math.cos(angle) * distance); - const spawnY = Math.floor(playerPos.y + Math.sin(angle) * distance); - - if (spawnX < 0 || spawnX >= 100 || spawnY < 0 || spawnY >= 100) return; - if (Phaser.Math.Distance.Between(spawnX, spawnY, 20, 20) < 15) return; - - const tile = this.terrainSystem.getTile(spawnX, spawnY); - if (tile && tile.type !== 'water') { - console.log(`🌑 Night Spawn: Zombie at ${spawnX},${spawnY}`); - const zombie = new NPC(this, spawnX, spawnY, this.terrainOffsetX, this.terrainOffsetY, 'zombie'); - zombie.state = 'CHASE'; - this.npcs.push(zombie); - } - */ - } - - showHordeWarning() { - console.log('🩸 BLOOD MOON RISING!'); - if (this.soundManager) this.soundManager.playDeath(); - - const width = this.cameras.main.width; - const height = this.cameras.main.height; - - const text = this.add.text(width / 2, height / 3, 'THE HORDE IS APPROACHING...', { - fontSize: '40px', fontFamily: 'Courier New', fill: '#ff0000', fontStyle: 'bold', stroke: '#000000', strokeThickness: 6 - }).setOrigin(0.5).setScrollFactor(0).setDepth(10000); - - this.tweens.add({ - targets: text, scale: 1.2, duration: 500, yoyo: true, repeat: 5, - onComplete: () => { - this.tweens.add({ - targets: text, alpha: 0, duration: 2000, - onComplete: () => text.destroy() - }); - } - }); - } - - createClouds() { - if (!this.textures.exists('cloud')) TextureGenerator.createCloudSprite(this, 'cloud'); - this.clouds = []; - console.log('☁️ Creating parallax clouds...'); - for (let i = 0; i < 8; i++) { - const x = Phaser.Math.Between(-1000, 3000); - const y = Phaser.Math.Between(-500, 1500); - const cloud = this.add.sprite(x, y, 'cloud'); - cloud.setAlpha(0.4).setScrollFactor(0.2).setDepth(2000).setScale(Phaser.Math.FloatBetween(2, 4)); - this.clouds.push({ sprite: cloud, speed: Phaser.Math.FloatBetween(10, 30) }); - } - } - - spawnBoss() { - // DISABLED - No NPCs allowed - return; - - /* - if (!this.player) return; - console.log('👑 SPANWING ZOMBIE KING!'); - const playerPos = this.player.getPosition(); - const spawnX = Math.floor(playerPos.x + 8); - const spawnY = Math.floor(playerPos.y + 8); - const boss = new Boss(this, spawnX, spawnY); - boss.state = 'CHASE'; - this.npcs.push(boss); - this.showHordeWarning(); - this.events.emit('show-floating-text', { x: this.player.x, y: this.player.y - 100, text: "THE KING HAS ARRIVED!", color: '#AA00FF' }); - */ - } - - saveGame() { - if (this.saveSystem) this.saveSystem.saveGame(); - } - - loadGame() { - if (this.saveSystem) this.saveSystem.loadGame(); - } - - initializeFarmWorld(spawnX = 20, spawnY = 20) { - console.log(`🌾 Initializing 8x8 Farm Area at (${spawnX}, ${spawnY})...`); - - const farmX = spawnX; // Farm center (custom spawn) - const farmY = spawnY; - const farmRadius = 4; // 8x8 = radius 4 (4 tiles in each direction) - - // 1. Clear farm area (odstrani drevesa in kamne) - for (let x = farmX - farmRadius; x <= farmX + farmRadius; x++) { - for (let y = farmY - farmRadius; y <= farmY + farmRadius; y++) { - if (x >= 0 && x < 100 && y >= 0 && y < 100) { - const key = `${x},${y}`; - // Remove trees and rocks in farm area - if (this.terrainSystem.decorationsMap.has(key)) { - this.terrainSystem.removeDecoration(x, y); - } - - // Change terrain to grass - if (this.terrainSystem.tiles[y] && this.terrainSystem.tiles[y][x]) { - this.terrainSystem.tiles[y][x].type = 'grass'; - this.terrainSystem.tiles[y][x].solid = false; - if (this.terrainSystem.tiles[y][x].sprite) { - this.terrainSystem.tiles[y][x].sprite.setTexture('grass'); - this.terrainSystem.tiles[y][x].sprite.clearTint(); - } - } - } - } - } - - // 2. Optional: Add fence around farm (commented out) - // const minX = farmX - farmRadius - 1; - // const maxX = farmX + farmRadius + 1; - // const minY = farmY - farmRadius - 1; - // const maxY = farmY + farmRadius + 1; - - // // Top and bottom horizontal fences - // for (let x = minX; x <= maxX; x++) { - // if (x >= 0 && x < 100) { - // this.terrainSystem.placeStructure(x, minY, 'fence_full'); // Top - // this.terrainSystem.placeStructure(x, maxY, 'fence_full'); // Bottom - // } - // } - - // // Left and right vertical fences - // for (let y = minY; y <= maxY; y++) { - // if (y >= 0 && y < 100) { - // this.terrainSystem.placeStructure(minX, y, 'fence_full'); // Left - // this.terrainSystem.placeStructure(maxX, y, 'fence_full'); // Right - // } - // } - - console.log(`✅ 8x8 Farm Area Initialized at (${spawnX},${spawnY})`); - } - - // ======================================================== - // ANTIGRAVITY ENGINE UPDATE - // ======================================================== - - Antigravity_Start() { - console.log('🚀 Starting Antigravity Engine...'); - - if (window.Antigravity) { - // Camera Setup - if (this.player && this.player.sprite) { - window.Antigravity.Camera.follow(this, this.player.sprite); - } - - // ZOOM SETUP - 0.75 za "Open World" pregled - window.Antigravity.Camera.setZoom(this, 0.75); - } - } - - Antigravity_Update(delta) { - // Globalni update klic - if (window.Antigravity) { - window.Antigravity.Update(this, delta); - } - - // Parallax background update - this.updateParallax(delta); - - - // 🎮 PHASE 29: SYSTEM UPDATES - const playerGridX = this.player ? this.player.gridX : 250; - const playerGridY = this.player ? this.player.gridY : 250; - - // Structure Interaction (check for nearby chests) - if (this.structureInteraction) { - this.structureInteraction.update(playerGridX, playerGridY); - } - - // NPC Population (check for nearby NPCs) - if (this.npcPopulation) { - this.npcPopulation.update(playerGridX, playerGridY); - } - - // Biome Enemies (AI movement, combat) - if (this.biomeEnemies) { - this.biomeEnemies.update(Date.now(), delta, playerGridX, playerGridY); - } - - // Map Reveal (fog of war) - if (this.mapReveal) { - this.mapReveal.update(); - - // Create minimap on first update - if (!this.mapReveal.minimap && this.player) { - this.mapReveal.createMinimap(); - } - } - - // 🎬 ACT 1 STORY SYSTEMS UPDATE - // Twin Bond System (telepathic messages, bond events) - if (this.twinBondSystem) { - this.twinBondSystem.update(delta); - } - - // Quest System Expanded (location objectives) - if (this.questSystemExpanded) { - this.questSystemExpanded.update(delta); - } - } - - createParallaxBackground() { - const width = this.cameras.main.width; - const height = this.cameras.main.height; - - // Parallax container - this.parallaxContainer = this.add.container(0, 0); - this.parallaxContainer.setDepth(-1000); // Always behind everything - - this.clouds = []; - this.birds = []; - - // Create 5 clouds - for (let i = 0; i < 5; i++) { - const cloud = this.add.text( - Math.random() * width * 2, - Math.random() * height * 0.5, - '☁️', - { fontSize: `${30 + Math.random() * 20}px` } - ); - cloud.speed = 0.3 + Math.random() * 0.2; // 0.3-0.5x speed - this.parallaxContainer.add(cloud); - this.clouds.push(cloud); - } - - // Create 3 birds - for (let i = 0; i < 3; i++) { - const bird = this.add.text( - Math.random() * width * 2, - 100 + Math.random() * 200, - '🐦', - { fontSize: '20px' } - ); - bird.speed = 0.5 + Math.random() * 0.3; // 0.5-0.8x speed - this.parallaxContainer.add(bird); - this.birds.push(bird); - } - - console.log('☁️ Parallax background created!'); - } - - updateParallax(delta) { - if (!this.parallaxContainer) return; - - const width = this.cameras.main.width; - - // Update clouds - this.clouds.forEach(cloud => { - cloud.x -= cloud.speed * (delta / 16); - if (cloud.x < -100) { - cloud.x = width + 100; - cloud.y = Math.random() * this.cameras.main.height * 0.5; - } - }); - - // Update birds - this.birds.forEach(bird => { - bird.x -= bird.speed * (delta / 16); - bird.y += Math.sin(Date.now() / 1000 + bird.x) * 0.5; // Flutter effect - if (bird.x < -100) { - bird.x = width + 100; - bird.y = 100 + Math.random() * 200; - } + }); + } + + // 💦 SPLASH EFFECT (Ripples) + createSplash(x, y) { + // Concentric circles + for (let i = 0; i < 3; i++) { + this.time.delayedCall(i * 100, () => { + const circle = this.add.circle(x, y, 3, 0xffffff, 0.5); + circle.setDepth(2); + + this.tweens.add({ + targets: circle, + radius: 20 + (i * 5), + alpha: 0, + duration: 600, + onComplete: () => circle.destroy() + }); }); } } + update(time, delta) { + if (this.player) { + this.player.update(delta); + + // Apply water physics + if (this.waterPhysics) { + this.waterPhysics.applyWaterPhysics(this.player, delta); + + // Create footstep ripples when moving in water + if (this.waterPhysics.playerInWater && this.waterRipples) { + const velocity = Math.abs(this.player.body.velocity.x) + Math.abs(this.player.body.velocity.y); + if (velocity > 10) { // Only if actually moving + // Random chance to create ripple (not every frame) + if (Math.random() < 0.1) { + this.waterRipples.createFootstepRipple(this.player.x, this.player.y); + } + } + } + } + } + + // 🎯 Z-SORTING: SortableObjects based on Y position + if (this.sortableObjects) { + const children = this.sortableObjects.getChildren(); + + // Sortiranje po Y koordinati (nižji Y = nižji depth) + children.sort((a, b) => a.y - b.y); + + // Nastavi depth glede na vrstni red (index) + children.forEach((obj, index) => { + // Use LAYER_OBJECTS base + index for depth + obj.setDepth(200000 + index); + }); + } + + // Weather UI Update + if (this.weatherUI) this.weatherUI.update(); + + // Update Systems + if (this.terrainSystem) this.terrainSystem.update(time, delta); // Water animation! + if (this.statsSystem) this.statsSystem.update(delta); + if (this.craftingSystem) this.craftingSystem.update(delta); // 🛠️ Crafting progress + if (this.lootSystem) this.lootSystem.update(delta); + if (this.interactionSystem) this.interactionSystem.update(delta); + if (this.farmingSystem) this.farmingSystem.update(delta); + if (this.statusEffectSystem) this.statusEffectSystem.update(time, delta); + if (this.buildSystem) this.buildSystem.update(delta); + if (this.questSystem) this.questSystem.update(delta); + if (this.multiplayerSystem) this.multiplayerSystem.update(delta); + + // Update Master Weather System + if (this.weather && this.weather.update) { + this.weather.update(delta); + } + + if (this.weatherSystem) { + this.weatherSystem.update(delta); + + // Update Lighting (shadows, torches) + if (this.lightingSystem) this.lightingSystem.update(delta); + + // Update Weather Enhancements (wind, tree sway) + if (this.weatherEnhancements) { + this.weatherEnhancements.update(delta); + + // Apply wind to rain if active + if (this.weatherSystem.rainEmitter) { + this.weatherEnhancements.applyWindToRain(this.weatherSystem.rainEmitter); + } + } + + // 🌍 PHASE 28: Update chunk loading based on player position (ONLY for procedural maps!) + if (this.chunkManager && this.player && !this.tiledMapLoaded) { + const pos = this.player.getPosition(); + this.chunkManager.updateActiveChunks(pos.x, pos.y); + } + + // Concept Systems Updates + if (this.zombieSystem) this.zombieSystem.update(this.time.now, delta); + + // Night Logic + if (this.weatherSystem.isNight()) { + const isHorde = this.weatherSystem.isHordeNight(); + const spawnInterval = isHorde ? 2000 : 10000; + + // Check for Horde Start Warning + if (isHorde && !this.hordeWarningShown) { + this.showHordeWarning(); + this.hordeWarningShown = true; + } + + if (!this.nightSpawnTimer) this.nightSpawnTimer = 0; + this.nightSpawnTimer += delta; + + if (this.nightSpawnTimer > spawnInterval) { + this.nightSpawnTimer = 0; + this.spawnNightZombie(); + if (isHorde) { + this.spawnNightZombie(); + this.spawnNightZombie(); + } + } + } else { + this.hordeWarningShown = false; + } + } + + // NPC Update - DISABLED (no NPCs) + /* + for (const npc of this.npcs) { + npc.update(delta); + } + */ + + // Vehicles Update + if (this.vehicles) { + for (const vehicle of this.vehicles) { + if (vehicle.update) vehicle.update(delta); + } + } + + // Spawners Update + if (this.spawners) { + for (const spawner of this.spawners) { + if (spawner.update) spawner.update(delta); + } + } + + // Zombie Worker System + if (this.zombieWorkerSystem) this.zombieWorkerSystem.update(delta); + + // Workstation System + if (this.workstationSystem) this.workstationSystem.update(delta); + + // Grave System Update (regeneration) + if (this.graveSystem) { + this.graveSystem.update(delta); + + // Auto-rest check every 5 seconds + if (!this.graveAutoRestTimer) this.graveAutoRestTimer = 0; + this.graveAutoRestTimer += delta; + if (this.graveAutoRestTimer >= 5000) { + this.graveSystem.autoRest(); + this.graveAutoRestTimer = 0; + } + } + + // 🎵 PHASE 8: Pond Proximity Audio Modulation + if (this.player && this.lakeSystem && this.soundManager) { + const playerPos = this.player.getPosition(); + let minPondDist = 1000; + + // Find nearest pond + this.lakeSystem.lakes.forEach(lake => { + if (lake.type === 'pond' || lake.type === 'lake') { + const d = Phaser.Math.Distance.Between(playerPos.x, playerPos.y, lake.x, lake.y); + if (d < minPondDist) minPondDist = d; + } + }); + + // Map distance to modulation factor (e.g., 0 within 5 tiles, 1 far away) + // Or 1 at pond center, 0 far away? User said "malo spremeni, ko sem blizu" + // Let's go with 1.0 (max change) at dist=0, and 0.0 (no change) beyond 15 tiles + const modFactor = Phaser.Math.Clamp(1 - (minPondDist / 15), 0, 1); + this.soundManager.setAmbientModulation(modFactor); + } + + if (this.parallaxSystem && this.player) { + const playerPos = this.player.getPosition(); + // 🎨 FLAT 2D (NEW!) - Direct position, no conversion + const tileSize = 48; + const screenX = playerPos.x * tileSize + tileSize / 2; + const screenY = playerPos.y * tileSize + tileSize / 2; + this.parallaxSystem.update(screenX, screenY); + } + + + + // Clouds + if (this.clouds) { + for (const cloud of this.clouds) { + if (cloud && cloud.sprite) { + cloud.sprite.x += cloud.speed * (delta / 1000); + if (cloud.sprite.x > this.terrainOffsetX + 2000) { + cloud.sprite.x = this.terrainOffsetX - 2000; + cloud.sprite.y = Phaser.Math.Between(0, 1000); + } + } + } + } + + if (this.worldEventSystem) this.worldEventSystem.update(delta); + + // FPS Monitor Update + if (this.fpsMonitor) this.fpsMonitor.update(); + + // Performance Monitor Update + if (this.performanceMonitor) this.performanceMonitor.update(delta); + + // NPC Spawner Update + if (this.npcSpawner) this.npcSpawner.update(delta); + + // Visual Sound Cue System Update + if (this.visualSoundCueSystem) this.visualSoundCueSystem.update(); + + // Screen Reader System Update + if (this.screenReader) this.screenReader.update(); + + // Motor Accessibility System Update + if (this.motorAccessibility) this.motorAccessibility.update(); + + // Visual Enhancement System Update + if (this.visualEnhancements) this.visualEnhancements.update(delta); + + // Fog of War System Update + if (this.fogOfWar) this.fogOfWar.update(); + + // Farm Automation System Update + if (this.farmAutomation) this.farmAutomation.update(delta); + + // Animal Breeding System Update + if (this.animalBreeding) this.animalBreeding.update(delta); + + // Automation Tier System Update + if (this.automationTiers) this.automationTiers.update(delta); + + // Cooking System Update + if (this.cooking) this.cooking.update(delta); + + // Fishing System Update + if (this.fishing) this.fishing.update(delta); + + // Worker Creatures System Update + if (this.workerCreatures) this.workerCreatures.update(delta); + + // Boss Battles System Update + if (this.bossBattles) this.bossBattles.update(delta); + + // Multiplayer & Social System Update + if (this.multiplayerSocial) this.multiplayerSocial.update(delta); + + // Technical & Performance System Update + if (this.technicalPerformance) this.technicalPerformance.update(delta); + + // Platform Support System Update + if (this.platformSupport) this.platformSupport.update(delta); + + // Save System Expansion Update + if (this.saveSystemExpansion) this.saveSystemExpansion.update(delta); + + // Update NPCs + for (const npc of this.npcs) { + if (npc.update) npc.update(delta); + } + + // Update Unified Stats Panel + if (this.unifiedStatsPanel) { + this.unifiedStatsPanel.update(delta); + } + + // Update Full Inventory UI + if (this.fullInventoryUI) { + this.fullInventoryUI.update(); + } + + // Run Antigravity Engine Update + this.Antigravity_Update(delta); + } + + spawnNightZombie() { + // DISABLED - No NPCs allowed + return; + + /* + if (!this.player || this.npcs.length > 50) return; + + const playerPos = this.player.getPosition(); + const angle = Math.random() * Math.PI * 2; + const distance = Phaser.Math.Between(15, 25); + + const spawnX = Math.floor(playerPos.x + Math.cos(angle) * distance); + const spawnY = Math.floor(playerPos.y + Math.sin(angle) * distance); + + if (spawnX < 0 || spawnX >= 100 || spawnY < 0 || spawnY >= 100) return; + if (Phaser.Math.Distance.Between(spawnX, spawnY, 20, 20) < 15) return; + + const tile = this.terrainSystem.getTile(spawnX, spawnY); + if (tile && tile.type !== 'water') { + console.log(`🌑 Night Spawn: Zombie at ${spawnX},${spawnY}`); + const zombie = new NPC(this, spawnX, spawnY, this.terrainOffsetX, this.terrainOffsetY, 'zombie'); + zombie.state = 'CHASE'; + this.npcs.push(zombie); + } + */ + } + + showHordeWarning() { + console.log('🩸 BLOOD MOON RISING!'); + if (this.soundManager) this.soundManager.playDeath(); + + const width = this.cameras.main.width; + const height = this.cameras.main.height; + + const text = this.add.text(width / 2, height / 3, 'THE HORDE IS APPROACHING...', { + fontSize: '40px', fontFamily: 'Courier New', fill: '#ff0000', fontStyle: 'bold', stroke: '#000000', strokeThickness: 6 + }).setOrigin(0.5).setScrollFactor(0).setDepth(10000); + + this.tweens.add({ + targets: text, scale: 1.2, duration: 500, yoyo: true, repeat: 5, + onComplete: () => { + this.tweens.add({ + targets: text, alpha: 0, duration: 2000, + onComplete: () => text.destroy() + }); + } + }); + } + + createClouds() { + if (!this.textures.exists('cloud')) TextureGenerator.createCloudSprite(this, 'cloud'); + this.clouds = []; + console.log('☁️ Creating parallax clouds...'); + for (let i = 0; i < 8; i++) { + const x = Phaser.Math.Between(-1000, 3000); + const y = Phaser.Math.Between(-500, 1500); + const cloud = this.add.sprite(x, y, 'cloud'); + cloud.setAlpha(0.4).setScrollFactor(0.2).setDepth(2000).setScale(Phaser.Math.FloatBetween(2, 4)); + this.clouds.push({ sprite: cloud, speed: Phaser.Math.FloatBetween(10, 30) }); + } + } + + spawnBoss() { + // DISABLED - No NPCs allowed + return; + + /* + if (!this.player) return; + console.log('👑 SPANWING ZOMBIE KING!'); + const playerPos = this.player.getPosition(); + const spawnX = Math.floor(playerPos.x + 8); + const spawnY = Math.floor(playerPos.y + 8); + const boss = new Boss(this, spawnX, spawnY); + boss.state = 'CHASE'; + this.npcs.push(boss); + this.showHordeWarning(); + this.events.emit('show-floating-text', { x: this.player.x, y: this.player.y - 100, text: "THE KING HAS ARRIVED!", color: '#AA00FF' }); + */ + } + + saveGame() { + if (this.saveSystem) this.saveSystem.saveGame(); + } + + loadGame() { + if (this.saveSystem) this.saveSystem.loadGame(); + } + + initializeFarmWorld(spawnX = 20, spawnY = 20) { + console.log(`🌾 Initializing 8x8 Farm Area at (${spawnX}, ${spawnY})...`); + + const farmX = spawnX; // Farm center (custom spawn) + const farmY = spawnY; + const farmRadius = 4; // 8x8 = radius 4 (4 tiles in each direction) + + // 1. Clear farm area (odstrani drevesa in kamne) + for (let x = farmX - farmRadius; x <= farmX + farmRadius; x++) { + for (let y = farmY - farmRadius; y <= farmY + farmRadius; y++) { + if (x >= 0 && x < 100 && y >= 0 && y < 100) { + const key = `${x},${y}`; + // Remove trees and rocks in farm area + if (this.terrainSystem.decorationsMap.has(key)) { + this.terrainSystem.removeDecoration(x, y); + } + + // Change terrain to grass + if (this.terrainSystem.tiles[y] && this.terrainSystem.tiles[y][x]) { + this.terrainSystem.tiles[y][x].type = 'grass'; + this.terrainSystem.tiles[y][x].solid = false; + if (this.terrainSystem.tiles[y][x].sprite) { + this.terrainSystem.tiles[y][x].sprite.setTexture('grass'); + this.terrainSystem.tiles[y][x].sprite.clearTint(); + } + } + } + } + } + + // 2. Optional: Add fence around farm (commented out) + // const minX = farmX - farmRadius - 1; + // const maxX = farmX + farmRadius + 1; + // const minY = farmY - farmRadius - 1; + // const maxY = farmY + farmRadius + 1; + + // // Top and bottom horizontal fences + // for (let x = minX; x <= maxX; x++) { + // if (x >= 0 && x < 100) { + // this.terrainSystem.placeStructure(x, minY, 'fence_full'); // Top + // this.terrainSystem.placeStructure(x, maxY, 'fence_full'); // Bottom + // } + // } + + // // Left and right vertical fences + // for (let y = minY; y <= maxY; y++) { + // if (y >= 0 && y < 100) { + // this.terrainSystem.placeStructure(minX, y, 'fence_full'); // Left + // this.terrainSystem.placeStructure(maxX, y, 'fence_full'); // Right + // } + // } + + console.log(`✅ 8x8 Farm Area Initialized at (${spawnX},${spawnY})`); + } + + // ======================================================== + // ANTIGRAVITY ENGINE UPDATE + // ======================================================== + + Antigravity_Start() { + console.log('🚀 Starting Antigravity Engine...'); + + if (window.Antigravity) { + // Camera Setup + if (this.player && this.player.sprite) { + window.Antigravity.Camera.follow(this, this.player.sprite); + } + + // ZOOM SETUP - 0.75 za "Open World" pregled + window.Antigravity.Camera.setZoom(this, 0.75); + } + } + + Antigravity_Update(delta) { + // Globalni update klic + if (window.Antigravity) { + window.Antigravity.Update(this, delta); + } + + // Parallax background update + this.updateParallax(delta); + + + // 🎮 PHASE 29: SYSTEM UPDATES + const playerGridX = this.player ? this.player.gridX : 250; + const playerGridY = this.player ? this.player.gridY : 250; + + // Structure Interaction (check for nearby chests) + if (this.structureInteraction) { + this.structureInteraction.update(playerGridX, playerGridY); + } + + // NPC Population (check for nearby NPCs) + if (this.npcPopulation) { + this.npcPopulation.update(playerGridX, playerGridY); + } + + // Biome Enemies (AI movement, combat) + if (this.biomeEnemies) { + this.biomeEnemies.update(Date.now(), delta, playerGridX, playerGridY); + } + + // Map Reveal (fog of war) + if (this.mapReveal) { + this.mapReveal.update(); + + // Create minimap on first update + if (!this.mapReveal.minimap && this.player) { + this.mapReveal.createMinimap(); + } + } + + // 🎬 ACT 1 STORY SYSTEMS UPDATE + // Twin Bond System (telepathic messages, bond events) + if (this.twinBondSystem) { + this.twinBondSystem.update(delta); + } + + // Quest System Expanded (location objectives) + if (this.questSystemExpanded) { + this.questSystemExpanded.update(delta); + } + } + + createParallaxBackground() { + const width = this.cameras.main.width; + const height = this.cameras.main.height; + + // Parallax container + this.parallaxContainer = this.add.container(0, 0); + this.parallaxContainer.setDepth(-1000); // Always behind everything + + this.clouds = []; + this.birds = []; + + // Create 5 clouds + for (let i = 0; i < 5; i++) { + const cloud = this.add.text( + Math.random() * width * 2, + Math.random() * height * 0.5, + '☁️', + { fontSize: `${30 + Math.random() * 20}px` } + ); + cloud.speed = 0.3 + Math.random() * 0.2; // 0.3-0.5x speed + this.parallaxContainer.add(cloud); + this.clouds.push(cloud); + } + + // Create 3 birds + for (let i = 0; i < 3; i++) { + const bird = this.add.text( + Math.random() * width * 2, + 100 + Math.random() * 200, + '🐦', + { fontSize: '20px' } + ); + bird.speed = 0.5 + Math.random() * 0.3; // 0.5-0.8x speed + this.parallaxContainer.add(bird); + this.birds.push(bird); + } + + console.log('☁️ Parallax background created!'); + } + + updateParallax(delta) { + if (!this.parallaxContainer) return; + + const width = this.cameras.main.width; + + // Update clouds + this.clouds.forEach(cloud => { + cloud.x -= cloud.speed * (delta / 16); + if (cloud.x < -100) { + cloud.x = width + 100; + cloud.y = Math.random() * this.cameras.main.height * 0.5; + } + }); + + // Update birds + this.birds.forEach(bird => { + bird.x -= bird.speed * (delta / 16); + bird.y += Math.sin(Date.now() / 1000 + bird.x) * 0.5; // Flutter effect + if (bird.x < -100) { + bird.x = width + 100; + bird.y = 100 + Math.random() * 200; + } + }); + } +} +