diff --git a/assets/slike/dekoracije/tall_grass.png b/assets/slike/dekoracije/tall_grass.png new file mode 100644 index 000000000..7e37fa030 Binary files /dev/null and b/assets/slike/dekoracije/tall_grass.png differ diff --git a/assets/slike/teren/grass_noir.png b/assets/slike/teren/grass_noir.png new file mode 100644 index 000000000..b141d68e1 Binary files /dev/null and b/assets/slike/teren/grass_noir.png differ diff --git a/assets/slike/teren/grass_tile.png b/assets/slike/teren/grass_tile.png index b43c125db..b141d68e1 100644 Binary files a/assets/slike/teren/grass_tile.png and b/assets/slike/teren/grass_tile.png differ diff --git a/index.html b/index.html index f46fb1b8e..c6f3c46f2 100644 --- a/index.html +++ b/index.html @@ -35,17 +35,27 @@ align-items: center; width: 100vw; height: 100vh; - image-rendering: -moz-crisp-edges; - image-rendering: -webkit-crisp-edges; - image-rendering: pixelated; - image-rendering: crisp-edges; + /* SMOOTH FILMSKI RENDERING (no pixelation!) */ + image-rendering: auto; + /* Browser default - SMOOTH */ + background: #000; + /* Black by default (intro) */ + } + + /* GRASS BACKGROUND - only when GameScene active */ + #game-container.game-active { + background-image: url('assets/slike/teren/grass_noir.png'); + background-repeat: repeat; + background-size: 128px 128px; + /* 512px * 0.25 = 128px */ + background-position: 0 0; + image-rendering: auto; + /* SMOOTH LINEAR filtering */ } canvas { - image-rendering: -moz-crisp-edges; - image-rendering: -webkit-crisp-edges; - image-rendering: pixelated; - image-rendering: crisp-edges; + /* SMOOTH FILMSKI RENDERING for Phaser sprites */ + image-rendering: auto; } @@ -281,7 +291,7 @@ - + diff --git a/src/entities/Player.js b/src/entities/Player.js index 71ed83ea8..1b4286719 100644 --- a/src/entities/Player.js +++ b/src/entities/Player.js @@ -108,12 +108,16 @@ class Player { } createSprite() { - // KRVAVA ลฝETEV: Use new protagonist sprite - let texKey = 'player_protagonist'; + // Priority: kai_main (real sprite) > player_style32 > fallback + let texKey = 'kai_main'; - // Fallback to generated sprite if not loaded if (!this.scene.textures.exists(texKey)) { - console.warn('โš ๏ธ player_protagonist sprite not found! Generating fallback...'); + texKey = 'player_style32'; + } + + // Fallback to generated pink square if nothing loaded + if (!this.scene.textures.exists(texKey)) { + console.warn('โš ๏ธ No Kai sprite found! Generating pink fallback...'); TextureGenerator.createPlayerSprite(this.scene, 'player_fallback'); texKey = 'player_fallback'; } @@ -134,7 +138,7 @@ class Player { // Scale based on sprite type if (texKey === 'player_protagonist') { - this.sprite.setScale(0.5); // 256x256 frames scaled to 128x128 display size + this.sprite.setScale(0.25); // 0.25 scale for correct size } else { this.sprite.setScale(0.5); // Fallback sprite } diff --git a/src/game.js b/src/game.js index 4d46549f1..8c4caf240 100644 --- a/src/game.js +++ b/src/game.js @@ -47,19 +47,19 @@ ErrorHandler.init(); // Phaser Game Configuration const config = { - type: Phaser.CANVAS, // Canvas renderer za pixel-perfect ostrino + type: Phaser.WEBGL, // WEBGL renderer (Canvas has issues in Electron!) width: 1024, // Larger viewport for better view height: 768, // 4:3 aspect ratio parent: 'game-container', - backgroundColor: '#000000', // Black background (not gray!) - pixelArt: false, // ๐ŸŽจ SMOOTH 2D (was: true) - antialias: true, // ๐ŸŽจ SMOOTH edges (was: false) - roundPixels: false, // ๐ŸŽจ SMOOTH positioning (was: true) + backgroundColor: '#000000', // Black background + pixelArt: false, // ๐ŸŽจ SMOOTH FILMSKI LOOK (LINEAR filtering) + antialias: true, // ๐ŸŽจ SMOOTH edges (mehki prehodi) + roundPixels: false, // ๐ŸŽจ FLUID positioning (no kockanje) render: { - pixelArt: false, // ๐ŸŽจ SMOOTH 2D - antialias: true, // ๐ŸŽจ SMOOTH edges - roundPixels: false, // ๐ŸŽจ SMOOTH positioning - transparent: false, + pixelArt: false, // ๐ŸŽจ LINEAR filtering (gladko) + antialias: true, // ๐ŸŽจ Smooth transitions + roundPixels: false, // ๐ŸŽจ Sub-pixel precision + transparent: true, // Allow HTML background to show through clearBeforeRender: true, powerPreference: 'high-performance', premultipliedAlpha: true, diff --git a/src/scenes/BootScene.js b/src/scenes/BootScene.js index bea8e3a92..08bf37d1b 100644 --- a/src/scenes/BootScene.js +++ b/src/scenes/BootScene.js @@ -38,7 +38,7 @@ class BootScene extends Phaser.Scene { create() { console.log('โœ… BootScene: Complete!'); - console.log('๐ŸŽจ Pixel Art Mode: pixelArt=true, roundPixels=true (NEAREST filtering)'); + console.log('๐ŸŽจ SMOOTH Rendering Mode: pixelArt=FALSE, roundPixels=FALSE (LINEAR filtering - filmski look)'); window.gameState.currentScene = 'BootScene'; // Global Constants for Sprites diff --git a/src/scenes/GameScene.js b/src/scenes/GameScene.js index 6861f4f9d..e9d063835 100644 --- a/src/scenes/GameScene.js +++ b/src/scenes/GameScene.js @@ -1,2861 +1,251 @@ -// Game Scene - Glavna igralna scena -// NOTE: WaterPhysicsSystem and AssetManifest must be loaded in index.html, not imported here (Electron/Browser Limitation) - class GameScene extends Phaser.Scene { constructor() { super({ key: 'GameScene' }); - this.terrainSystem = null; - this.terrainContainer = null; - this.player = null; - this.npcs = []; // Array za NPCje - this.statusEffectSystem = null; - - this.settings = { - viewDistance: 'HIGH', - particles: 'HIGH', - shadows: true - }; - this.townRestorationSystem = null; } preload() { - // ๐ŸŽจ STYLE 32 ASSET PIPELINE (SMOOTH 512px) - // Loading the new high-res vector assets + // Load Kai sprite (real character, not fallback!) + console.log('๐Ÿ‘ค Loading Kai sprite...'); + this.load.image('kai_main', 'assets/sprites/smooth/kai_main.png'); - // Load Kai (Style 32 - Smooth) - // Load Kai (Style 32 - Smooth) - this.load.image('player_style32', 'assets/slike/liki/kai_main.png'); + // Load Grass Texture (Using tile version) + this.load.image('grass_main', 'assets/slike/teren/grass_tile.png'); - // Load NPC Placeholder (AA Quality - Using Kai temporarily) - this.load.image('npc_placeholder', 'assets/slike/liki/kai_main.png'); - - // Load Backgrounds (Style 32 - Noir) - // Note: 'bg_farm' and 'bg_town' might be missing in strict sort. - // Using intro asset or disable if missing to prevent error. - // this.load.image('bg_farm', 'assets/slike/zgodba/intro_chaos.png'); - - // Load UI/Zombie Assets (Style 32) - // this.load.image('zombie_miner', 'assets/slike/sovrazniki/zombie_miner.png'); - - // ๐ŸŒฟ GROUND ASSETS (Style 32 - 256x256 Tiling) - this.load.image('tileset_grass', 'assets/slike/teren/grass_tile.png'); - this.load.image('tileset_dirt', 'assets/slike/teren/dirt.png'); - - // Farmland might be missing or named differently - if (this.textures.exists('farmland')) { - this.load.image('tileset_farmland', 'assets/slike/teren/farmland.png'); - } - - this.load.image('tileset_water', 'assets/slike/teren/water.png'); - this.load.image('tileset_stone', 'assets/slike/teren/stone.png'); - - console.log('โœจ Style 32 Smooth Assets Loaded'); + console.log('โญ๏ธ Assets loaded'); } - async create() { - console.log('๐ŸŽฎ GameScene: Initialized!'); + create() { + console.log('๐ŸŒŸ GAME START: Clean Slate Mode'); - // ๐Ÿ–ผ๏ธ SETUP BACKGROUND (Direct Farm Image) - // Checks 'farm_background' (from Phase 1) or fallback 'bg_farm' (New Style 32) - const bgKey = this.textures.exists('bg_farm') ? 'bg_farm' : - this.textures.exists('farm_background') ? 'farm_background' : 'intro_chaos'; + // 1. BACKGROUND (Phaser TileSprite) + // No more CSS hacks! + console.log('๐ŸŒพ Creating Phaser grass background...'); - if (this.textures.exists(bgKey)) { - this.add.image(0, 0, bgKey) - .setOrigin(0, 0) - .setDisplaySize(this.sys.canvas.width, this.sys.canvas.height) - .setDepth(-999); // Way back - console.log(`๐Ÿ–ผ๏ธ Farm Background Set: ${bgKey}`); + const centerX = this.scale.width / 2; + const centerY = this.scale.height / 2; + + // PROCEDURAL GENERATION (Guarantee 100% visible grass) + const grassKey = 'procedural_grass'; + if (!this.textures.exists(grassKey)) { + const g = this.make.graphics({ x: 0, y: 0, add: false }); + g.fillStyle(0x1a2e1a, 1); // Dark Base + g.fillRect(0, 0, 128, 128); + // Noise + for (let i = 0; i < 500; i++) { + g.fillStyle(Math.random() > 0.5 ? 0x2a4a2a : 0x3a5a3a, 0.8); + g.fillRect(Math.random() * 128, Math.random() * 128, 2 + Math.random() * 4, 2 + Math.random() * 7); + } + g.generateTexture(grassKey, 128, 128); + console.log('๐ŸŽจ Procedural Grass Generated!'); } - // ๐Ÿ–ผ๏ธ SETUP BACKGROUND - this.currentPhaseBg = null; - // Phase Selector removed in favor of Tiled Map + if (this.textures.exists(grassKey)) { + // HUGE TileSprite centered on screen + this.grassBg = this.add.tileSprite(centerX, centerY, 4000, 4000, grassKey); + this.grassBg.setOrigin(0.5, 0.5); + this.grassBg.setScrollFactor(0); + this.grassBg.setDepth(-99); // Adjusted depth (visible) + console.log('โœ… Grass TileSprite created!'); + } else { + // Fallback rectangle centered + this.grassBg = this.add.rectangle(centerX, centerY, 4000, 4000, 0x2a4a2a); + this.grassBg.setScrollFactor(0); + this.grassBg.setDepth(-1000); + console.warn('โš ๏ธ Texture missing, using green rect fallback'); + } - - // Generate procedural textures - new TextureGenerator(this).generateAll(); - InventoryIcons.create(this); // Override with flat 2D inventory icons - window.gameState.currentScene = 'GameScene'; - window.gameState.gameScene = this; // Reference for global inventory helper - - const width = this.cameras.main.width; - const height = this.cameras.main.height; - - // Setup kamere - TRAVNATO ZELENO OZADJE! - // REMOVED: this.cameras.main.setBackgroundColor('#7cfc00'); - - // ๐ŸŒฟ TEXTURE OVERLAY: Grass Background - // Using 'tileset_grass' (from assets/slike/teren/grass_tile.png) - // Scaled to 0.25 as requested for sharp high-res texture - const mapWidth = this.worldWidth * 32 || 4000; // Default to reasonable size if undefined - const mapHeight = this.worldHeight * 32 || 4000; - - this.grassBg = this.add.tileSprite(0, 0, mapWidth, mapHeight, 'tileset_grass'); - this.grassBg.setOrigin(0, 0); - this.grassBg.setTileScale(0.25, 0.25); - this.grassBg.setDepth(-100); // Strict depth to ensure Kai (Depth 0+) is visible - - console.log('๐ŸŒฟ Grass Background Applied (Scale 0.25)'); - - // Initialize Isometric Utils - this.iso = new IsometricUtils(); - - // Initialize Spatial Grid - this.spatialGrid = new SpatialGrid(10); - - // Initialize Concept Systems (Zombie Roots) - this.zombieSystem = new ZombieWorkerSystem(this); - this.legacySystem = new LegacySystem(this); - this.expansionSystem = new ExpansionSystem(this); - this.blueprintSystem = new BlueprintSystem(this); - - // Farm Stats Tracking for UI - this.farmStats = { - cropsPlanted: 0, - totalHarvested: 0, - goldEarned: 0, - daysFarmed: 0 + // 2. DUMMY SYSTEMS (Da prepreฤimo crashe, ฤe jih kdo iลกฤe) + // Ti sistemi so trenutno prazni, samo da "obstajajo". + this.terrainSystem = { + tiles: [], + getTileAt: () => null, + width: 100, + height: 100 }; + this.farmingSystem = { update: () => { } }; + this.buildSystem = {}; + this.inventorySystem = new InventorySystem(this); + this.scene.launch('UIScene'); // UI must be active for Player interaction - // PARALLAX BACKGROUND - DISABLED FOR HARD RESET - // this.createParallaxBackground(); + // (Cleanup complete) - // Inicializiraj terrain sistem - 100x100 mapa - console.log('๐ŸŒ Initializing terrain...'); + // 3. PLAYER (Kai) try { - // ๐ŸŽฒ SEED-BASED GENERATION - Vsak krat ista mapa! - // Preveri ฤe ลพe imaลก shranjeno spawn toฤko - let spawnPoint = localStorage.getItem('novafarma_spawn_point'); - let terrainSeed = localStorage.getItem('novafarma_terrain_seed'); + // Spawn point (Sredina 100x100 mape -> 50,50) + const spawnX = 50 * 48; + const spawnY = 50 * 48; - if (!terrainSeed) { - // PRVI LOGIN - generiraj nov seed - terrainSeed = Math.random().toString(36).substring(7); - localStorage.setItem('novafarma_terrain_seed', terrainSeed); - console.log('๐Ÿ†• New world seed:', terrainSeed); - } else { - console.log('โ™ป๏ธ Loading existing world with seed:', terrainSeed); + // Predpostavljamo, da je Player class naloลพen globalno iz src/entities/Player.js + // Argumenti: scene, x, y, offsetX, offsetY + this.player = new Player(this, spawnX, spawnY, 0, 0); + + // Scale Fix + if (this.player.sprite) { + this.player.sprite.setScale(0.25); } - // ๐ŸŽจ 2D FLAT TERRAIN SYSTEM (NEW!) - this.worldWidth = 100; - this.worldHeight = 100; - console.log('๐ŸŽจ Initializing Flat 2D Terrain...'); - this.terrainSystem = new Flat2DTerrainSystem(this); + console.log('โœ… Player created at 50,50'); - // ๐Ÿ—๏ธ PHASE 28-29 SYSTEMS INITIALIZATION - try { - // ๐ŸŒ PHASE 28: Initialize BiomeSystem and ChunkManager BEFORE terrain generation! - const w = this.worldWidth || 100; - const h = this.worldHeight || 100; - console.log(`๐ŸŒ Initializing Biome System (${w}x${h} world)...`); - this.biomeSystem = new BiomeSystem(this); - this.biomeSystem.worldWidth = w; - this.biomeSystem.worldHeight = h; - this.biomeSystem.generateBiomeMap(); // Generate biome layout - console.log('โœ… Biome map generated!'); + // DECORATION: Tall Grass & Trees (Starter Camp) + this.addStarterCampDecoration(spawnX, spawnY); - console.log('๐Ÿ’พ Initializing Chunk Manager...'); - this.chunkManager = new ChunkManager(this, 50); // 50x50 chunks - this.chunkManager.biomeSystem = this.biomeSystem; // Connect biomeSystem! - console.log('โœ… Chunk Manager ready!'); - - // ๐ŸŒˆ PHASE 28: TRANSITION SYSTEM - console.log('๐ŸŒˆ Initializing Transition System...'); - this.transitionSystem = new TransitionSystem(this, this.biomeSystem); - console.log('โœ… Transition System ready!'); - - // ๐ŸŒŠ PHASE 28 SESSION 5: RIVER SYSTEM - console.log('๐ŸŒŠ Initializing River System...'); - this.riverSystem = new RiverSystem(w, h, this.biomeSystem); - this.riverSystem.generateRivers(); - console.log('โœ… River System ready!'); - - // ๐Ÿž๏ธ PHASE 28 SESSION 5: LAKE SYSTEM - console.log('๐Ÿž๏ธ Initializing Lake System...'); - this.lakeSystem = new LakeSystem(w, h, this.biomeSystem); - this.lakeSystem.generateLakes(this.riverSystem); - console.log('โœ… Lake System ready!'); - - // ๐Ÿ›๏ธ PHASE 28 SESSION 6: STRUCTURE SYSTEM - console.log('๐Ÿ›๏ธ Initializing Structure System...'); - this.structureSystem = new StructureSystem(w, h, this.biomeSystem, this.riverSystem, this.lakeSystem); - this.structureSystem.generateAll(); - const structStats = this.structureSystem.getStats(); - console.log(`โœ… Structure System ready! (${structStats.structures} structures, ${structStats.landmarks} landmarks, ${structStats.roads.length} roads)`); - - // Connect systems to terrainSystem - this.terrainSystem.biomeSystem = this.biomeSystem; - this.terrainSystem.chunkManager = this.chunkManager; - this.terrainSystem.transitionSystem = this.transitionSystem; - this.terrainSystem.riverSystem = this.riverSystem; - this.terrainSystem.lakeSystem = this.lakeSystem; - this.terrainSystem.structureSystem = this.structureSystem; // ๐Ÿ›๏ธ SESSION 6 - console.log('โœ… BiomeSystem & ChunkManager connected to terrainSystem'); - - // ๐ŸŽฎ PHASE 29: GAMEPLAY SYSTEMS - console.log('๐ŸŽฎ Initializing Phase 29 Systems...'); - - // Structure Interaction - this.structureInteraction = new StructureInteractionSystem(this); - this.structureInteraction.generateChestsForStructures(this.structureSystem); - console.log(`โœ… Structure Interaction ready! (${this.structureInteraction.chests.size} chests)`); - - // NPC Population - this.npcPopulation = new NPCPopulationSystem(this); - this.npcPopulation.populateStructures(this.structureSystem); - const npcStats = this.npcPopulation.getStats(); - console.log(`โœ… NPC Population ready! (${npcStats.totalNPCs} NPCs)`); - - // Biome Enemies - this.biomeEnemies = new BiomeEnemySystem(this); - this.biomeEnemies.generateSpawns(this.biomeSystem); - const enemyStats = this.biomeEnemies.getStats(); - console.log(`โœ… Biome Enemies ready! (${enemyStats.alive} enemies)`); - - // Quest System - // Quest System - DISABLED AUTO-START FOR CLEAN VIEW - this.landmarkQuests = new LandmarkQuestSystem(this); - // this.landmarkQuests.startMainQuest(); // Disable popup - // this.landmarkQuests.startExplorationQuests(); // Disable popup - console.log(`โœ… Quest System initialized (Passive Mode)`); - - // Map Reveal - this.mapReveal = new MapRevealSystem(this); - console.log('โœ… Map Reveal System ready!'); - - console.log('๐ŸŽ‰ Phase 29 Systems: ALL READY!'); - } catch (err) { - console.error('โŒ ERROR initializing Phase 28/29 systems:', err); - console.warn('โš ๏ธ Continuing with partial initialization...'); - } - - // ๐Ÿ—บ๏ธ TRY TO LOAD USER'S TILED MAP FIRST - this.tiledMapLoaded = false; - this.tiledSpawnPoint = null; - - console.log('๐Ÿ” Checking for NovaFarma map...'); - try { - // Ensure key matches PreloadScene - if (this.cache.tilemap.exists('NovaFarma')) { - const map = this.make.tilemap({ key: 'NovaFarma' }); - - // DEBUG LOGGING - console.log('๐Ÿ—บ๏ธ Map object created:', map); - - if (map && map.width > 0) { - console.log('โœ… FOUND VALID USER MAP: NovaFarma.json'); - // Use terrain system if available, else simple render - if (this.terrainSystem && this.terrainSystem.loadFromTiled) { - this.terrainSystem.loadFromTiled(map); - } else { - // ๐Ÿ—๏ธ STANDARD TILED RENDERING (The "Tiled-First" Approach) - console.log('๐Ÿ—บ๏ธ Rendering Tiled Map Layers...'); - - // 0. ๐ŸŒ AUTO-GROUND (User Request) - // Automatically fill background with grass if 'Ground' layer is empty or just as a base. - // Priority: grass_tile (User request), grass_texture, farm_background, intro_chaos - const groundTextures = ['grass_tile', 'grass_texture', 'farm_background', 'intro_chaos']; - const bgTexture = groundTextures.find(tex => this.textures.exists(tex)); - - if (bgTexture) { - // Create a TileSprite that covers the whole map - const bg = this.add.tileSprite( - 0, 0, - map.widthInPixels, map.heightInPixels, - bgTexture - ).setOrigin(0, 0).setDepth(-100); - console.log(`๐ŸŒฑ Auto-Ground applied using texture: ${bgTexture}`); - } - - // 1. Render Tile Layers (Ground, Objects, Collision, Decoration...) - const tileset = map.tilesets[0]; - if (tileset) { - map.layers.forEach(layer => { - if (layer.type === 'tilelayer') { - const createdLayer = map.createLayer(layer.name, tileset, 0, 0); - - // Set Depth based on layer name or order - if (layer.name === 'Objects') createdLayer.setDepth(10); - - if (layer.name === 'Collision') { - createdLayer.setVisible(false); - this.collisionLayer = createdLayer; - this.collisionLayer.setCollisionByExclusion([-1]); - console.log('๐Ÿšง Collision Layer Set!'); - } - - // ๐Ÿ’ง DYNAMIC TILED EFFECTS (Shine) - // Check for custom properties from Tiled - const layerProps = layer.properties || []; - const getProp = (n) => { - if (Array.isArray(layerProps)) { - const p = layerProps.find(x => x.name === n); - return p ? p.value : undefined; - } - return layerProps[n]; - }; - - const shineIntensity = getProp('shine_intensity'); - const isWind = getProp('isWind'); - - // Apply Shine if prop exists OR if name is Water/Voda - if (shineIntensity !== undefined || layer.name === 'Water' || layer.name === 'Voda') { - const intensity = shineIntensity !== undefined ? parseFloat(shineIntensity) : 5; - - // Validate intensity and apply shader safely - if (!isNaN(intensity) && intensity > 0 && createdLayer.postFX) { - try { - console.log(`๐Ÿ’ง Applying Shine to layer '${layer.name}' (Intensity: ${intensity})`); - const shine = createdLayer.postFX.addShine(1, 0.2, intensity); - - // Animate shine speed for 'glimmer' effect - this.tweens.add({ - targets: shine, - speed: 0.5, - duration: 2000, - yoyo: true, - repeat: -1 - }); - } catch (shaderError) { - console.warn(`โš ๏ธ PostFX Shine failed for '${layer.name}':`, shaderError); - console.log('โ†’ Falling back to tile animation only (no shader)'); - } - } - } - - // ๐ŸŒฌ๏ธ WIND (Wobble Effect) - if (isWind) { - console.log(`๐ŸŒฌ๏ธ Applying Wind to '${layer.name}'`); - this.tweens.add({ - targets: createdLayer, - x: createdLayer.x + 3, - skewX: 0.015, - duration: 2000 + Math.random() * 500, - ease: 'Sine.easeInOut', - yoyo: true, - repeat: -1 - }); - } - } - }); - } - - // 2. Parse Object Layers (Audio, Logic, Spawns) - try { - // ๐ŸŽต MUSIC PROP - const mapMusic = map.properties && map.properties.find(p => p.name === 'music')?.value; - - // ๐ŸŒฒ FOREST AMBIENT (Safe Play) - try { - // Verify cache existence first to avoid decode errors propagating - if (this.cache.audio.exists('forest_ambient')) { - this.sound.play('forest_ambient', { loop: true, volume: 0.3 }); - console.log('๐ŸŒฒ Playing Forest Ambient'); - } else { - console.warn('โš ๏ธ Forest Ambient skipped (Not in cache/Load failed)'); - } - } catch (e) { - console.warn('โŒ Audio play CRASH prevented:', e); - } - - if (mapMusic) { - console.log(`๐ŸŽต Map Triggered Music: ${mapMusic}`); - // Use sound manager or direct play (SoundManager preferred but let's check safety) - // Assuming raw Phaser sound for safety if manager not ready - try { - this.sound.stopAll(); // Stop previous - this.sound.play(mapMusic, { loop: true, volume: 0.5 }); - } catch (e) { console.warn("Audio play failed", e); } - } - - const audioLayer = map.getObjectLayer('Audio_Zones'); - if (audioLayer && audioLayer.objects) { - console.log(`๐ŸŽต Found ${audioLayer.objects.length} Audio Zones`); - } - - const logicLayer = map.getObjectLayer('Logic') || map.getObjectLayer('Spawns'); - if (logicLayer && logicLayer.objects) { - console.log(`๐Ÿง  Found ${logicLayer.objects.length} Logic Objects`); - logicLayer.objects.forEach(obj => { - if (obj.name === 'PlayerSpawn') { - this.tiledSpawnPoint = { x: obj.x, y: obj.y }; - console.log('๐Ÿ“ Tiled defined Player Spawn:', this.tiledSpawnPoint); - } - if (obj.type === 'zombie_spawn') { - // Register zombie spawn point - } - }); - } - - // ๐ŸŽญ ACTORS LAYER (NPCs including Gronk) - const actorsLayer = map.getObjectLayer('Actors') || map.getObjectLayer('Objects'); - if (actorsLayer && actorsLayer.objects) { - console.log(`๐ŸŽญ Found ${actorsLayer.objects.length} Actors`); - actorsLayer.objects.forEach(obj => { - // Gronk disabled per user request - }); - } - } catch (err) { - console.warn('โš ๏ธ Error parsing object layers:', err); - } - } - - this.tiledMapLoaded = true; - - // UPDATE SYSTEM DIMENSIONS TO MATCH TILED MAP - this.worldWidth = map.width; - this.worldHeight = map.height; - - // ๐Ÿ•ต๏ธ FIND SPAWN POINT IN MAP (Optional) - const playerLayer = map.getLayer('Player'); - if (playerLayer) { - // Logic to extract spawn point... - console.log('๐Ÿ‘ค Player Layer detected (Logic Placeholder)'); - } - - } else { - console.error('โŒ Map created but invalid width (0) or null!'); - } - } else { - console.warn('โš ๏ธ Map "NovaFarma" not found in cache. Ensure it is loaded in PreloadScene.'); - } - } catch (e) { - console.error('โš ๏ธ CRITICAL ERROR loading NovaFarma map:', e); - } - - if (!this.tiledMapLoaded) { - console.log('๐ŸŒ TERRAIN: Generating map with 18 Biomes (Style 32 Logic)...'); - - // 1. GENERATE PROCEDURAL MAP (18 Biomes) - // We use the TerrainSystem to generate the full world based on BiomeSystem.js (18 definitions) - this.terrainSystem.width = 100; // 100x100 tiles (standard size for performance) - this.terrainSystem.height = 100; - await this.terrainSystem.generate(); - - // 2. WORLD BOUNDS - // TerrainSystem sets its own bounds usually, but we ensure it matches - const tileSize = 32; // Standard tile size - const worldPixelWidth = this.terrainSystem.width * tileSize; - const worldPixelHeight = this.terrainSystem.height * tileSize; - this.physics.world.setBounds(0, 0, worldPixelWidth, worldPixelHeight); - this.cameras.main.setBounds(0, 0, worldPixelWidth, worldPixelHeight); - - console.log(`โœ… World Generated: ${this.terrainSystem.width}x${this.terrainSystem.height} tiles (${18} Biomes Active)`); - - // 3. BACKGROUND (Underlay) - // Add diverse background color or texture if needed - this.cameras.main.setBackgroundColor('#2d2d2d'); - - } else { - console.log('โœ… Flat 2D terrain ready (Tiled)!'); - - - - // Initialize Farming System - this.farmingSystem = new FarmingSystem(this); - this.statusEffectSystem = new StatusEffectSystem(this); - console.log('๐ŸŒพ Farming system initialized!'); - - // Initialize Build System - this.buildSystem = new BuildSystem(this); - console.log('๐Ÿ—๏ธ Build system initialized!'); - - - - // ======================================================== - // ๐Ÿ—๏ธ TESTNI PRIMERI - Postavitev Ograj (ONEMOGOฤŒENO) - // ======================================================== - // Odstrani // pred vrsticami, ฤe ลพeliลก videti testne ograje! - // ALI pritisni B v igri za Build Mode in postavljaj roฤno! - - // PRIMER 1: Ena sama ograja - // this.buildSystem.placeSingleFence(50, 50, 'fence_post', false); - - // PRIMER 2: Vodoravna linija ograj (10 ograj) - // for (let i = 0; i < 10; i++) { - // this.buildSystem.placeSingleFence(45 + i, 52, 'fence_horizontal', false); - // } - - // PRIMER 3: Navpiฤna linija ograj (10 ograj) - // for (let i = 0; i < 10; i++) { - // this.buildSystem.placeSingleFence(43, 48 + i, 'fence_vertical', false); - // } - - // PRIMER 4: Majhen pravokotnik (8x6) - // this.buildSystem.placeFenceRectangle(60, 45, 8, 6, 'fence_post', false); - - // PRIMER 5: Diagonalna linija (Bresenham) - // this.buildSystem.placeFenceLine(30, 30, 40, 40, 'fence_corner', false); - - // PRIMER 6: Veฤji pravokotnik (20x15) - // this.buildSystem.placeFenceRectangle(20, 60, 20, 15, 'fence_horizontal', false); - - // PRIMER 7: Razliฤni tipi ograj v vrsti - // this.buildSystem.placeSingleFence(70, 50, 'fence', false); - // this.buildSystem.placeSingleFence(71, 50, 'fence_post', false); - // this.buildSystem.placeSingleFence(72, 50, 'fence_horizontal', false); - // this.buildSystem.placeSingleFence(73, 50, 'fence_vertical', false); - // this.buildSystem.placeSingleFence(74, 50, 'fence_corner', false); - - // console.log('โœ… Testne ograje postavljene! Preveri mapo.'); - // ======================================================== - - - // Terrain offset - if (this.tiledMapLoaded) { - // For Tiled maps, we usually start at 0,0 or map center is handled by camera - this.terrainOffsetX = 0; - this.terrainOffsetY = 0; - } else { - // For procedural flat maps, we start at 0,0 - this.terrainOffsetX = 0; - this.terrainOffsetY = 0; - } - - - // ๐ŸŽฒ SPAWN POINT LOGIC - if (this.tiledSpawnPoint) { - // ๐Ÿ“ Uporabi spawn toฤko iz Tiled mape (PRIORITETA!) - const spawnX = Math.floor(this.tiledSpawnPoint.x / 48); // Convert back to grid for init logic if needed, or just use coords - const spawnY = Math.floor(this.tiledSpawnPoint.y / 48); - - spawnPoint = `${spawnX},${spawnY}`; - localStorage.setItem('novafarma_spawn_point', spawnPoint); - - console.log(`๐Ÿ“ Using Tiled Spawn Point: (${spawnX}, ${spawnY})`); - this.initializeFarmWorld(spawnX, spawnY); - - // Override player position directly if initializeFarmWorld doesn't do it precisely - // (initializeFarmWorld usually sets grid position, we might want pixel precision later) - } - else if (!spawnPoint) { - // PRVI LOGIN - Random spawn toฤka (Fallback) - const spawnX = Math.floor(Math.random() * 80) + 10; // 10-90 - const spawnY = Math.floor(Math.random() * 80) + 10; // 10-90 - - spawnPoint = `${spawnX},${spawnY}`; - localStorage.setItem('novafarma_spawn_point', spawnPoint); - - console.log(`๐ŸŽฒ First login - Random spawn at (${spawnX}, ${spawnY})`); - console.log(`๐Ÿก Creating 8x8 starter farm at spawn location...`); - - // Ustvari 8x8 farmo na spawn toฤki - this.initializeFarmWorld(spawnX, spawnY); - } else { - // NI PRVI LOGIN - Naloลพi obstojeฤo spawn toฤko - const [spawnX, spawnY] = spawnPoint.split(',').map(Number); - console.log(`โ™ป๏ธ Returning player - spawn at (${spawnX}, ${spawnY})`); - - // Obnovi farmo (ฤe je shranjena) - this.initializeFarmWorld(spawnX, spawnY); - } - - // ๐ŸŽ SADOVNJAK - Sadna Drevesa (ONEMOGOฤŒENO) - // ======================================================== - // Odstrani // ฤe ลพeliลก sadovnjak - /* - console.log('๐ŸŽ Ustvarjam sadovnjak...'); - - const orchardX = 35; // Lokacija sadovnjaka - const orchardY = 60; - const orchardSize = 10; // 10x10 obmoฤje - - // 1. Oฤisti obmoฤje (odstrani obstojeฤe drevese) - for (let x = orchardX; x < orchardX + orchardSize; x++) { - for (let y = orchardY; y < orchardY + orchardSize; y++) { - if (x >= 0 && x < 100 && y >= 0 && y < 100) { - const key = `${x},${y}`; - if (this.terrainSystem.decorationsMap.has(key)) { - this.terrainSystem.removeDecoration(x, y); - } - - // Spremeni teren v travo - if (this.terrainSystem.tiles[y] && this.terrainSystem.tiles[y][x]) { - this.terrainSystem.tiles[y][x].type = 'grass'; - if (this.terrainSystem.tiles[y][x].sprite) { - this.terrainSystem.tiles[y][x].sprite.setTexture('grass'); - this.terrainSystem.tiles[y][x].sprite.clearTint(); - } - } - } - } - } - - // 2. Dodaj SADIKE (tree_sapling) - bodo rasle v sadna drevesa! - const fruitTreeTypes = ['tree_apple', 'tree_orange', 'tree_cherry']; - let treeCount = 0; - const saplingPositions = []; // Shrani pozicije za ograje - - for (let x = orchardX + 1; x < orchardX + orchardSize - 1; x += 2) { - for (let y = orchardY + 1; y < orchardY + orchardSize - 1; y += 2) { - if (x >= 0 && x < 100 && y >= 0 && y < 100) { - // Dodaj SADIKO (bo rasla v sadno drevo) - this.terrainSystem.addDecoration(x, y, 'tree_sapling'); - saplingPositions.push({ x, y, type: fruitTreeTypes[treeCount % fruitTreeTypes.length] }); - treeCount++; - } - } - } - - // 3. Dodaj LESENO OGRAJO okoli vsakega drevesa (3x3 kvadrat) - saplingPositions.forEach(pos => { - // Ograja okoli drevesa (3x3) - const fencePositions = [ - // Zgornja vrstica - { x: pos.x - 1, y: pos.y - 1 }, - { x: pos.x, y: pos.y - 1 }, - { x: pos.x + 1, y: pos.y - 1 }, - // Spodnja vrstica - { x: pos.x - 1, y: pos.y + 1 }, - { x: pos.x, y: pos.y + 1 }, - { x: pos.x + 1, y: pos.y + 1 }, - // Leva stran - { x: pos.x - 1, y: pos.y }, - // Desna stran - { x: pos.x + 1, y: pos.y } - ]; - - fencePositions.forEach(fPos => { - if (fPos.x >= 0 && fPos.x < 100 && fPos.y >= 0 && fPos.y < 100) { - this.buildSystem.placeSingleFence(fPos.x, fPos.y, 'fence_horizontal', false); - } - }); - }); - - // 4. Dodaj ZUNANJO OGRAJO okoli celega sadovnjaka - this.buildSystem.placeFenceRectangle( - orchardX - 1, - orchardY - 1, - orchardSize + 2, - orchardSize + 2, - 'fence_post', - false - ); - - // 5. Dodaj cvetje med ograjami - for (let x = orchardX; x < orchardX + orchardSize; x++) { - for (let y = orchardY; y < orchardY + orchardSize; y++) { - if (x >= 0 && x < 100 && y >= 0 && y < 100) { - const key = `${x},${y}`; - if (!this.terrainSystem.decorationsMap.has(key) && Math.random() > 0.85) { - this.terrainSystem.addDecoration(x, y, 'flowers_new'); - } - } - } - } - - // 6. RAST DREVES - Sadike bodo rasle v sadna drevesa! - // Nastavi timer za rast (vsako drevo raste po 30 sekundah) - saplingPositions.forEach((pos, index) => { - this.time.delayedCall(30000 + (index * 2000), () => { - const key = `${pos.x},${pos.y}`; - - // Odstrani sadiko - if (this.terrainSystem.decorationsMap.has(key)) { - this.terrainSystem.removeDecoration(pos.x, pos.y); - } - - // Dodaj SADNO DREVO - this.terrainSystem.addDecoration(pos.x, pos.y, pos.type); - - // Animacija rasti - if (this.terrainSystem.visibleDecorations.has(key)) { - const sprite = this.terrainSystem.visibleDecorations.get(key); - sprite.setScale(0.01); - this.tweens.add({ - targets: sprite, - scaleX: 0.04, - scaleY: 0.04, - duration: 2000, - ease: 'Bounce.out' - }); - } - - console.log(`๐ŸŒณ Drevo zraslo: ${pos.type} na (${pos.x}, ${pos.y})`); - }); - }); - - console.log(`โœ… Sadovnjak ustvarjen na (${orchardX}, ${orchardY}) - ${treeCount} sadik (bodo rasle v 30s)`); - */ - // ======================================================== - - - // CITY CONTENT: Ruins, Chests, Spawners - console.log('๐Ÿš๏ธ Generating City Content...'); - - // DISABLED - City structures removed for cleaner gameplay - // Main Ruins - // this.terrainSystem.placeStructure(55, 55, 'ruin'); - // this.terrainSystem.placeStructure(65, 65, 'ruin'); - // this.terrainSystem.placeStructure(75, 75, 'ruin'); - // this.terrainSystem.placeStructure(60, 70, 'ruin'); - // this.terrainSystem.placeStructure(70, 60, 'ruin'); - - // Arena (Boss battle area) - // this.terrainSystem.placeStructure(75, 55, 'arena'); - - // Treasure Chests (scattered in ruins) - // this.terrainSystem.placeStructure(56, 56, 'chest'); - // this.terrainSystem.placeStructure(66, 66, 'chest'); - // this.terrainSystem.placeStructure(76, 76, 'chest'); - - // Zombie Spawners (in city) - // this.terrainSystem.placeStructure(58, 68, 'spawner'); - // this.terrainSystem.placeStructure(72, 62, 'spawner'); - - // CESTE (ROADS) - povezava med farmo (20,20) in mestom (65,65) - console.log('๐Ÿ›ฃ๏ธ Building Roads...'); - // Horizontalna cesta od farme - for (let x = 20; x <= 45; x++) { - if (this.terrainSystem.tiles[22] && this.terrainSystem.tiles[22][x]) { - this.terrainSystem.tiles[22][x].type = 'pavement'; - if (this.terrainSystem.tiles[22][x].sprite) { - this.terrainSystem.tiles[22][x].sprite.setTexture('dirt'); - this.terrainSystem.tiles[22][x].sprite.setTint(0x808080); - } - } - } - // Vertikalna cesta do mesta - for (let y = 22; y <= 65; y++) { - if (this.terrainSystem.tiles[y] && this.terrainSystem.tiles[y][45]) { - this.terrainSystem.tiles[y][45].type = 'pavement'; - if (this.terrainSystem.tiles[y][45].sprite) { - this.terrainSystem.tiles[y][45].sprite.setTexture('dirt'); - this.terrainSystem.tiles[y][45].sprite.setTint(0x808080); - } - } - } - // Horizontalna cesta do mesta - for (let x = 45; x <= 65; x++) { - if (this.terrainSystem.tiles[65] && this.terrainSystem.tiles[65][x]) { - this.terrainSystem.tiles[65][x].type = 'pavement'; - if (this.terrainSystem.tiles[65][x].sprite) { - this.terrainSystem.tiles[65][x].sprite.setTexture('dirt'); - this.terrainSystem.tiles[65][x].sprite.setTint(0x808080); - } - } - } - - // SIGNPOSTS - navigacijske table - // SIGNPOSTS - DISABLED (User request: clean world) - // console.log('๐Ÿชง Placing Signposts...'); - // this.terrainSystem.placeStructure(23, 22, 'signpost_city'); - // this.terrainSystem.placeStructure(65, 64, 'signpost_farm'); - // this.terrainSystem.placeStructure(45, 40, 'signpost_both'); - - // DAMAGED CITY WALLS - DISABLED (User request: clean world) - // console.log('๐Ÿš๏ธ Placing Damaged City Walls...'); - // const wallPositions = [ - // [65, 65], [70, 65], [75, 65], - // [65, 79], [70, 79], [75, 79], - // [65, 70], [65, 75], - // [79, 70], [79, 75] - // ]; - // wallPositions.forEach(([wx, wy]) => { - // if (Math.random() < 0.7) { - // this.terrainSystem.placeStructure(wx, wy, 'wall_damaged'); - // } - // }); - - // Initialize Pathfinding (Worker) - console.log('๐Ÿ—บ๏ธ Initializing Pathfinding...'); - try { - this.pathfinding = new PathfindingSystem(this); - this.pathfinding.updateGrid(); - } catch (err) { - console.warn('โš ๏ธ Pathfinding system failed to initialize:', err); - this.pathfinding = null; // Disable pathfinding for now - } - - } - - // Dodaj igralca NA SPAWN TOฤŒKI - console.log('๐Ÿ‘ค Initializing player...'); - const savedSpawn = localStorage.getItem('novafarma_spawn_point'); - - // ๐ŸŒ PHASE 28: Initial spawn positioning - let playerSpawnX, playerSpawnY; - - if (this.tiledSpawnPoint) { - // Use Tiled spawn point (converted to grid) - playerSpawnX = Math.floor(this.tiledSpawnPoint.x / this.terrainSystem.tileSize); - playerSpawnY = Math.floor(this.tiledSpawnPoint.y / this.terrainSystem.tileSize); - console.log(`๐Ÿ‘ค Spawning player at Tiled location: Grid(${playerSpawnX}, ${playerSpawnY}) -> Pixel(${this.tiledSpawnPoint.x}, ${this.tiledSpawnPoint.y})`); - } else if (this.tiledMapLoaded) { - // Default to map center for Tiled maps - playerSpawnX = Math.floor(this.terrainSystem.width / 2); - playerSpawnY = Math.floor(this.terrainSystem.height / 2); - console.log(`๐Ÿ‘ค Spawning player at Tiled MAP CENTER: (${playerSpawnX}, ${playerSpawnY})`); - } else if (savedSpawn) { - [playerSpawnX, playerSpawnY] = savedSpawn.split(',').map(Number); - console.log(`๐Ÿ‘ค Spawning player at saved location: (${playerSpawnX}, ${playerSpawnY})`); - } else { - playerSpawnX = 250; - playerSpawnY = 250; - console.log(`๐Ÿ‘ค Spawning player at default world center: (${playerSpawnX}, ${playerSpawnY})`); - } - - this.player = new Player(this, playerSpawnX, playerSpawnY, this.terrainOffsetX, this.terrainOffsetY); - - // ๐ŸŒฑ Initialize Micro Farm System (PHASE 37!) - this.microFarmSystem = new MicroFarmSystem(this); - if (playerSpawnX !== undefined && playerSpawnY !== undefined) { - this.microFarmSystem.farmCenterX = playerSpawnX; - this.microFarmSystem.farmCenterY = playerSpawnY; - this.microFarmSystem.init(); // Re-initialize with correct center - console.log(`๐ŸŒฑ Micro Farm system centered at (${playerSpawnX}, ${playerSpawnY})!`); - } - - // ๐ŸŒ PHASE 28: Load initial chunks around player (Procedural ONLY) - if (this.chunkManager && !this.tiledMapLoaded) { - console.log('๐Ÿ’พ Loading initial chunks around player...'); - this.chunkManager.updateActiveChunks(playerSpawnX, playerSpawnY); - const stats = this.chunkManager.getStats(); - console.log(`โœ… Loaded ${stats.activeChunks} chunks (${stats.totalTilesLoaded} tiles)`); - } - - // ๐ŸŽฏ SORTABLE OBJECTS GROUP - Za 2.5D Z-Sorting - console.log('๐ŸŽฏ Creating sortableObjects group for Z-sorting...'); - this.sortableObjects = this.add.group(); - - // Dodaj player sprite v sortableObjects - if (this.player && this.player.sprite) { - this.sortableObjects.add(this.player.sprite); - console.log('โœ… Player added to sortableObjects'); - - // ๐ŸŽฅ CAMERA FOLLOW - console.log('๐ŸŽฅ Setting camera to follow player...'); - this.cameras.main.startFollow(this.player.sprite, true, 0.1, 0.1); - this.cameras.main.setZoom(1); // Ensure visible zoom - } - - // ALL NPCs REMOVED - Solo farming mode - console.log('๐ŸŒพ Solo farming mode - no NPCs'); - - // Gronk logic removed from create() fallback - - - // FPS Monitor (Performance) - // FPS Monitor - DISABLED (Using UnifiedStatsPanel instead) - // console.log('๐Ÿ“Š Initializing FPS Monitor...'); - // this.fpsMonitor = new FPSMonitor(this); - - // Unified Stats Panel (Performance + Debug in one) - console.log('๐Ÿ“Š Initializing Unified Stats Panel...'); - this.unifiedStatsPanel = new UnifiedStatsPanel(this); - - // NPC Spawner - DISABLED (NPCs look like player duplicates) - console.log('๐ŸงŸ NPC Spawner - DISABLED'); - this.npcSpawner = null; // new NPCSpawner(this); - // this.npcSpawner.spawnInitialNPCs(); - - // Easter Egg: Broken Scooter - console.log('๐Ÿ›ต Spawning Scooter Easter Egg...'); - this.vehicles = []; - // const scooter = new Scooter(this, 25, 25); - // this.vehicles.push(scooter); - - // ZOMBIE SPAWNERS (City area) - console.log('๐Ÿ‘น Creating Zombie Spawners...'); - this.spawners = []; - - // DISABLED - Too many zombies for testing - // this.spawners.push(new ZombieSpawner(this, 55, 55, 5, 2, 25000)); // NW - // this.spawners.push(new ZombieSpawner(this, 75, 55, 5, 2, 25000)); // NE - // this.spawners.push(new ZombieSpawner(this, 65, 75, 5, 3, 20000)); // South - - // LOOT CHESTS - console.log('๐Ÿ“ฆ Placing Loot Chests...'); - this.chests = []; - - // Farm Starter Chest ONLY (near spawn) - this.chests.push(new LootChest(this, 28, 28, 'farm_starter')); - - // DISABLED - City chests removed for cleaner gameplay - // this.chests.push(new LootChest(this, 60, 60, 'city')); - // this.chests.push(new LootChest(this, 70, 60, 'city')); - // this.chests.push(new LootChest(this, 65, 70, 'elite')); - - // SIGNPOSTS/NAVIGATION - console.log('๐Ÿชง Adding Signposts...'); - this.signposts = []; - - // Path markers (using fence sprites as signposts) - // ONLY if terrainSystem was successfully initialized - if (this.terrainSystem) { - const pathMarkers = [ - { x: 35, y: 35, label: 'โ†’ City' }, - { x: 50, y: 50, label: 'โ† Farm' }, - ]; - - for (const marker of pathMarkers) { - this.terrainSystem.addDecoration(marker.x, marker.y, 'fence'); - this.signposts.push({ gridX: marker.x, gridY: marker.y, label: marker.label }); - } - } else { - console.warn('โš ๏ธ TerrainSystem not initialized - skipping signposts'); - } - - // Kamera sledi igralcu z gladko interpolacijo (lerp 0.1) + // 4. KAMERA (SMOOTH WebGL) this.cameras.main.startFollow(this.player.sprite, true, 0.1, 0.1); + this.cameras.main.setLerp(0.1, 0.1); // Ultra-smooth WebGL lerp + this.cameras.main.setZoom(0.8); // ๐ŸŽฅ INITIAL WIDE ANGLE (0.8) - // Nastavi deadzone (100px border) - this.cameras.main.setDeadzone(100, 100); + // CAMERA CONTROLS (Arrow keys + Mouse drag + ZOOM) + this.cursors = this.input.keyboard.createCursorKeys(); + this.cameraSpeed = 8; + this.isDraggingCamera = false; - // Round pixels za crisp pixel art - this.cameras.main.roundPixels = true; + // ZOOM CONTROL (Mouse Wheel) + this.input.on('wheel', (pointer, gameObjects, deltaX, deltaY, deltaZ) => { + let newZoom = this.cameras.main.zoom; + // Scroll Down -> Zoom OUT (Wider) | Scroll Up -> Zoom IN (Closer) + newZoom += (deltaY > 0) ? -0.1 : 0.1; + // Clamp Zoom (Min: 0.4, Max: 3.0) + newZoom = Phaser.Math.Clamp(newZoom, 0.4, 3.0); - // Zoom out za boljลกi pogled (85% zoom) - this.cameras.main.setZoom(0.85); - - // ๐ŸŒ PHASE 28: Camera bounds for 500x500 world (48px tiles) - const worldSize = 500 * 48; // 24000x24000 pixels - this.cameras.main.setBounds(0, 0, worldSize, worldSize); - this.physics.world.setBounds(0, 0, worldSize, worldSize); - console.log(`๐Ÿ“ท Camera bounds set to ${worldSize}x${worldSize}`); - - // Parallax oblaki - this.createClouds(); - - // Kamera kontrole - this.setupCamera(); - - // ๐ŸŒŠ WATER PHYSICS SYSTEM (Temporarily Disabled - HARD RESET) - // this.waterPhysics = new WaterPhysicsSystem(this); - - // ๐Ÿ’ง WATER RIPPLES SYSTEM (Temporarily Disabled) - // this.waterRipples = new WaterRipplesSystem(this); - - // ๐Ÿ’ก LIGHTING & SHADOW SYSTEM - console.log('๐Ÿ’ก Initializing Lighting & Shadow System... (DISABLED FOR DEBUG)'); - /* - this.lightingSystem = new LightingSystem(this); - - // Create player shadow - if (this.player) { - this.lightingSystem.createShadow(this.player, 12, 30, 15); - this.lightingSystem.createPlayerTorch(this.player); // Auto-torch at night - } - */ - - // ๐ŸŒฌ๏ธ WEATHER ENHANCEMENTS SYSTEM - console.log('๐ŸŒฌ๏ธ Initializing Weather Enhancements System...'); - this.weatherEnhancements = new WeatherEnhancementsSystem(this); - - // ๐ŸŒŠ WATER PHYSICS SYSTEM (NEW!) - console.log('๐ŸŒŠ Initializing Water Physics System...'); - // ๐ŸŒŠ WATER PHYSICS SYSTEM (Temporarily Disabled) - // console.log('๐ŸŒŠ Initializing Water Physics System...'); - // this.waterPhysics = new WaterPhysicsSystem(this); - - - // ๐Ÿ’ง WATER RIPPLES SYSTEM (NEW!) - console.log('๐Ÿ’ง Initializing Water Ripples System...'); - this.waterRipples = new WaterRipplesSystem(this); - - // Add test water zone (example - remove or adjust later) - // this.waterPhysics.addWaterZone(1000, 1000, 500, 500, 60); - console.log('โœ… Water systems ready!'); - - // ๐ŸŒ PHASE 28: BiomeSystem & ChunkManager already initialized in create() before terrain generation! - // No need to initialize again here. - - // ๐ŸŽจ UI POLISH SYSTEM - console.log('๐ŸŽจ UI POLISH System...'); - this.uiPolish = new UIPolishSystem(this); - - this.statsSystem = new StatsSystem(this); - this.inventorySystem = new InventorySystem(this); - - // ๐Ÿ› ๏ธ CRAFTING SYSTEM - this.craftingSystem = new CraftingSystem(this); - this.craftingSystem.loadRecipes().then(() => { - console.log('๐Ÿ› ๏ธ Crafting system ready!'); - - // Create UI after recipes loaded - this.craftingUI = new CraftingUI(this); - - // Add C key to toggle crafting UI - this.input.keyboard.on('keydown-C', () => { - if (this.craftingUI) { - this.craftingUI.toggle(); - } - }); - - // Add M key to transition to Town Square - this.input.keyboard.on('keydown-M', () => { - console.log('๐Ÿ”„ Transitioning to Town Square...'); - this.scene.start('TownSquareScene'); + // Smoothly Tween Zoom + this.tweens.add({ + targets: this.cameras.main, + zoom: newZoom, + duration: 200, + ease: 'Sine.easeOut' }); }); - // ======================================================== - // ๐Ÿ’Ž NEOMEJENI VIRI - Les in Kamen - // ======================================================== - console.log('๐Ÿ’Ž Dodajam neomejene vire...'); - this.inventorySystem.addItem('wood', 999999); - this.inventorySystem.addItem('stone', 999999); - this.inventorySystem.gold = 999999; - console.log('โœ… Neomejeni viri dodani: 999,999 lesa, kamna in zlata!'); - // ======================================================== - - this.lootSystem = new LootSystem(this); - this.interactionSystem = new InteractionSystem(this); - this.farmingSystem = new FarmingSystem(this); - this.statusEffectSystem = new StatusEffectSystem(this); - this.townRestorationSystem = new TownRestorationSystem(this); - this.buildingSystem = new BuildingSystem(this); - // this.pathfinding = new Pathfinding(this); // REMOVED: Using PathfindingSystem (Worker) instead - this.questSystem = new QuestSystem(this); - this.collectionSystem = new CollectionSystem(this); - this.multiplayerSystem = new MultiplayerSystem(this); - this.worldEventSystem = new WorldEventSystem(this); - this.hybridSkillSystem = new HybridSkillSystem(this); - this.oceanSystem = new OceanSystem(this); - - // Central Popup System (for quests, dialogs, etc.) - this.centralPopup = new CentralPopupSystem(this); - - // Tutorial System (shows keyboard shortcuts) - this.tutorialSystem = new TutorialSystem(this); - - // Full Inventory UI (24 slots, I key to open) - this.fullInventoryUI = new FullInventoryUI(this); - - this.legacySystem = new LegacySystem(this); - - // Initialize Sound Manager - console.log('๐ŸŽต Initializing Sound Manager...'); - this.soundManager = new SoundManager(this); - this.soundManager.startMusic(); - this.soundManager.playForestAmbient(); // ๐ŸŒฒ PHASE 9: Start background ambience - - // Initialize Parallax System - console.log('๐ŸŒ„ Initializing Parallax System...'); - this.parallaxSystem = new ParallaxSystem(this); - - // Initialize Particle Effects - console.log('โœจ Initializing Particle Effects...'); - this.particleEffects = new ParticleEffects(this); - this.particleEffects.createFallingLeaves(); - - // โœจ PARTICLE ENHANCEMENTS SYSTEM - console.log('โœจ Initializing Particle Enhancements System...'); - this.particleEnhancements = new ParticleEnhancementsSystem(this); - - // Initialize Accessibility System - console.log('โ™ฟ Initializing Accessibility System...'); - this.accessibilitySystem = new AccessibilitySystem(this); - - // Initialize Visual Sound Cue System (for deaf/hard-of-hearing players) - console.log('๐Ÿ‘๏ธ Initializing Visual Sound Cue System...'); - this.visualSoundCueSystem = new VisualSoundCueSystem(this); - - // Initialize Input Remapping System (for custom controls) - console.log('๐ŸŽฎ Initializing Input Remapping System...'); - this.inputRemapping = new InputRemappingSystem(this); - - // ======================================================== - // ๐ŸŽ† WEEK 1 IMPLEMENTATION - Priority Systems - // ======================================================== - console.log('๐ŸŽ† Initializing Week 1 Priority Systems...'); - - // ๐Ÿ“ฆ Resource Logistics System (Auto-pickup + Storage) - console.log('๐Ÿ“ฆ Resource Logistics System...'); - // this.resourceLogisticsSystem = new ResourceLogisticsSystem(this); // TODO: Import in index.html - - // ๐Ÿ™๏ธ City Management System (Zombie Statistician + Population) - console.log('๐Ÿ™๏ธ City Management System...'); - // this.cityManagementSystem = new CityManagementSystem(this); // TODO: Import in index.html - - // โšก Building Upgrade System (Generator + Electrician) - console.log('โšก Building Upgrade System...'); - // this.buildingUpgradeSystem = new BuildingUpgradeSystem(this); // TODO: Import in index.html - - console.log('โœ… Week 1 Systems Ready!'); - // ======================================================== - - // Initialize Screen Reader System (for blind/visually impaired players) - console.log('๐Ÿ”Š Initializing Screen Reader System...'); - this.screenReader = new ScreenReaderSystem(this); - - // Initialize Dyslexia Support System - console.log('๐Ÿ“– Initializing Dyslexia Support System...'); - this.dyslexiaSupport = new DyslexiaSupportSystem(this); - - // Initialize ADHD/Autism Support System - console.log('๐Ÿง  Initializing ADHD/Autism Support System...'); - this.adhdAutismSupport = new ADHDAutismSupportSystem(this); - - // Initialize Motor Accessibility System - console.log('๐Ÿฆพ Initializing Motor Accessibility System...'); - this.motorAccessibility = new MotorAccessibilitySystem(this); - - // Initialize Visual Enhancement System - console.log('โœจ Initializing Visual Enhancement System...'); - this.visualEnhancements = new VisualEnhancementSystem(this); - - // Initialize Fog of War System - console.log('๐ŸŒซ๏ธ Initializing Fog of War System... (DISABLED FOR DEBUG)'); - // this.fogOfWar = new FogOfWarSystem(this); - - // Initialize UI Graphics System - console.log('๐ŸŽจ Initializing UI Graphics System...'); - this.uiGraphics = new UIGraphicsSystem(this); - - // Initialize Building Visuals System - console.log('๐Ÿญ Initializing Building Visuals System...'); - this.buildingVisuals = new BuildingVisualsSystem(this); - - // Initialize Skill Tree System - console.log('๐ŸŒณ Initializing Skill Tree System...'); - this.skillTree = new SkillTreeSystem(this); - - // Initialize Crafting Tiers System - console.log('โš’๏ธ Initializing Crafting Tiers System...'); - this.craftingTiers = new CraftingTiersSystem(this); - - // Initialize Farm Automation System - console.log('๐Ÿค– Initializing Farm Automation System...'); - this.farmAutomation = new FarmAutomationSystem(this); - - // Initialize Animal Breeding System - console.log('๐Ÿ‘ Initializing Animal Breeding System...'); - this.animalBreeding = new AnimalBreedingSystem(this); - - // Initialize Automation Tier System - console.log('๐Ÿค– Initializing Automation Tier System...'); - this.automationTiers = new AutomationTierSystem(this); - - // Initialize Breeding UI System - console.log('๐ŸŒณ Initializing Breeding UI System...'); - this.breedingUI = new BreedingUISystem(this); - - // Initialize Cooking System - console.log('๐Ÿณ Initializing Cooking System...'); - this.cooking = new CookingSystem(this); - - // Initialize Fishing System - console.log('๐ŸŽฃ Initializing Fishing System...'); - this.fishing = new FishingSystem(this); - - // Initialize Worker Creatures System - console.log('๐ŸฆŒ Initializing Worker Creatures System...'); - this.workerCreatures = new WorkerCreaturesSystem(this); - - // Initialize Mining & Dungeons System - console.log('โ›๏ธ Initializing Mining & Dungeons System...'); - this.miningDungeons = new MiningDungeonsSystem(this); - - // Initialize Boss Battles System - console.log('๐Ÿ‘น Initializing Boss Battles System...'); - this.bossBattles = new BossBattlesSystem(this); - - // Initialize Story & Quest System - console.log('๐Ÿ“– Initializing Story & Quest System...'); - this.storyQuest = new StoryQuestSystem(this); - - // Initialize Multiplayer & Social System - console.log('๐ŸŒ Initializing Multiplayer & Social System...'); - this.multiplayerSocial = new MultiplayerSocialSystem(this); - - // Initialize Technical & Performance System - console.log('โšก Initializing Technical & Performance System...'); - this.technicalPerformance = new TechnicalPerformanceSystem(this); - - // Initialize Platform Support System - console.log('๐ŸŽฎ Initializing Platform Support System...'); - this.platformSupport = new PlatformSupportSystem(this); - - // Initialize Save System Expansion - console.log('๐Ÿ’พ Initializing Save System Expansion...'); - this.saveSystemExpansion = new SaveSystemExpansion(this); - - // ======================================================== - // ๐ŸŽฌ ACT 1 STORY SYSTEMS (NEW - 23.12.2025) - // ======================================================== - console.log('๐ŸŽฌ Initializing Act 1 Story Systems...'); - - // Dialogue System - NPC conversations - console.log('๐Ÿ’ฌ Initializing Dialogue System...'); - this.dialogueSystem = new DialogueSystem(this); - - // Twin Bond System - Kai โ†” Ana psychic connection - console.log('๐Ÿ’ž Initializing Twin Bond System...'); - this.twinBondSystem = new TwinBondSystem(this); - - // Quest System Expanded - Main campaign quests - console.log('๐Ÿ“– Initializing Quest System Expanded...'); - this.questSystemExpanded = new QuestSystemExpanded(this); - - // Quest Tracker UI - Visual quest display - console.log('๐Ÿ“‹ Initializing Quest Tracker UI...'); - this.questTrackerUI = new QuestTrackerUI(this); - - // Load Grok dialogues - if (typeof GrokDialogues !== 'undefined') { - console.log('๐Ÿง˜ Loading Grok dialogues...'); - Object.keys(GrokDialogues).forEach(key => { - this.dialogueSystem.registerDialogue(key, GrokDialogues[key]); - }); - console.log(`โœ… Loaded ${Object.keys(GrokDialogues).length} Grok dialogue trees`); - } - - // Auto-start Quest 1.1 after 2 seconds - this.time.delayedCall(2000, () => { - if (this.questSystemExpanded && !this.questSystemExpanded.isQuestComplete('quest_1_1_wake_up')) { - console.log('๐Ÿ“– Auto-starting Quest 1.1: A New Beginning'); - this.questSystemExpanded.startQuest('quest_1_1_wake_up'); + // Right-click drag to pan camera + this.input.on('pointerdown', (pointer) => { + if (pointer.rightButtonDown()) { + this.cameras.main.stopFollow(); + this.isDraggingCamera = true; + this.dragStartX = pointer.x; + this.dragStartY = pointer.y; } }); - console.log('โœ… Act 1 Story Systems ready!'); - // ======================================================== - - console.log('๐ŸŽ‰๐ŸŽ‰๐ŸŽ‰ ALL 31 SYSTEMS INITIALIZED! ๐ŸŽ‰๐ŸŽ‰๐ŸŽ‰'); // Updated from 27 to 31 - console.log('๐Ÿ’€ MRTVA DOLINA - DEATH VALLEY ๐Ÿ’€'); - - // Show epilepsy warning on first launch - const hasSeenWarning = localStorage.getItem('novafarma_epilepsy_warning'); - if (!hasSeenWarning) { - this.time.delayedCall(2000, () => { - this.accessibilitySystem.showEpilepsyWarning(() => { - localStorage.setItem('novafarma_epilepsy_warning', 'true'); - }); - }); - } - - - // Generate Item Sprites for UI - TextureGenerator.createItemSprites(this); - - // Launch UI Scene - console.log('๐Ÿ–ฅ๏ธ Launching UI Scene...'); - this.scene.launch('UIScene'); - - // Initialize Save System - this.saveSystem = new SaveSystem(this); - - // Auto-load if available (DISABLED in SaveSystem!) - this.saveSystem.loadGame(); // Vrne false - ne naloลพi save-a! - - // Debug Text - REMOVED (Version shown in UnifiedStatsPanel) - // this.add.text(10, 10, 'NovaFarma Alpha v0.6', { font: '16px monospace', fill: '#ffffff' }) - // .setScrollFactor(0).setDepth(10000); - - console.log('โœ… GameScene ready - FAZA 20 (Full Features)!'); - - // ๐ŸŽฎ PHASE 29: KEY BINDINGS - console.log('๐ŸŽฎ Setting up Phase 29 key bindings...'); - - // E key - Interact with structures/chests - this.input.keyboard.on('keydown-E', () => { - if (this.structureInteraction) { - this.structureInteraction.interact(); + this.input.on('pointermove', (pointer) => { + if (this.isDraggingCamera) { + const dx = this.dragStartX - pointer.x; + const dy = this.dragStartY - pointer.y; + this.cameras.main.scrollX += dx; + this.cameras.main.scrollY += dy; + this.dragStartX = pointer.x; + this.dragStartY = pointer.y; } }); - // T key - Talk to NPCs - this.input.keyboard.on('keydown-T', () => { - if (this.npcPopulation) { - this.npcPopulation.talkToNPC(); - } + this.input.on('pointerup', () => { + this.isDraggingCamera = false; }); - // M key - Toggle full map - this.input.keyboard.on('keydown-M', () => { - if (this.mapReveal) { - this.mapReveal.toggleFullMap(); - } - }); + console.log('๐ŸŽฎ Camera controls: Arrow keys + Right-click drag'); - console.log('โœ… Phase 29 key bindings ready! (E: Interact, T: Talk, M: Map)'); - - // Global command: giveSeeds(amount) - daj seeds najbliลพjemu tamed zombiju - window.giveSeeds = (amount = 10) => { - if (!this.zombieWorkerSystem || !this.player) { - console.log('๐Ÿšซ System not ready!'); - return; - } - - const workers = this.zombieWorkerSystem.workers; - if (workers.length === 0) { - console.log('๐Ÿšซ No tamed zombies found!'); - return; - } - - // Find closest worker - const playerPos = this.player.getPosition(); - let closest = null; - let minDist = 999; - - for (const worker of workers) { - const dist = Phaser.Math.Distance.Between(playerPos.x, playerPos.y, worker.gridX, worker.gridY); - if (dist < minDist) { - minDist = dist; - closest = worker; - } - } - - if (closest && closest.workerData) { - closest.workerData.inventory.seeds += amount; - closest.showEmote(`๐Ÿ“ฆ+${amount}`); - console.log(`๐ŸงŸ๐Ÿ“ฆ Gave ${amount} seeds to worker! (Total: ${closest.workerData.inventory.seeds})`); - } - }; - - console.log('๐Ÿ’ก TIP: Use giveSeeds(20) to give 20 seeds to nearest zombie'); - - // Global command: placeGrave() - postavi grob pri playerju - window.placeGrave = () => { - if (!this.graveSystem || !this.player) { - console.log('๐Ÿšซ System not ready!'); - return; - } - - const playerPos = this.player.getPosition(); - const result = this.graveSystem.placeGrave( - Math.floor(playerPos.x), - Math.floor(playerPos.y) - ); - - if (result) { - console.log('๐Ÿชฆ Grave placed successfully!'); - } - }; - - console.log('๐Ÿ’ก TIP: Use placeGrave() to place grave at your location'); - - // Global command: giveAllParts() - daj vse scooter parts - window.giveAllParts = () => { - if (!this.scooterRepairSystem || !this.inventorySystem) { - console.log('๐Ÿšซ System not ready!'); - return; - } - - const parts = this.scooterRepairSystem.requiredParts; - const tools = this.scooterRepairSystem.requiredTools; - - for (const [part, count] of Object.entries(parts)) { - this.inventorySystem.addItem(part, count); - } - - for (const [tool, count] of Object.entries(tools)) { - this.inventorySystem.addItem(tool, count); - } - - console.log('โœ… All scooter parts and tools added!'); - this.scooterRepairSystem.listMissingParts(); - }; - - // Global command: checkScooter() - preveri kaj manjka - window.checkScooter = () => { - if (!this.scooterRepairSystem) { - console.log('๐Ÿšซ System not ready!'); - return; - } - - this.scooterRepairSystem.listMissingParts(); - }; - - console.log('๐Ÿ’ก TIP: Use checkScooter() to see repair requirements'); - console.log('๐Ÿ’ก TIP: Use giveAllParts() to get all scooter parts (testing)'); - - // Global command: unlockZone(id) - window.unlockZone = (id) => { - if (this.expansionSystem) { - this.expansionSystem.unlockZone(id); - } - }; - // Global command: dropBlueprint() - window.dropBlueprint = () => { - if (this.blueprintSystem && this.player) { - const pos = this.player.getPosition(); - this.blueprintSystem.tryDropBlueprint(pos.x, pos.y, 'boss'); // 100% chance - } - }; - - // Global command: placeFurnace() - window.placeFurnace = () => { - if (this.terrainSystem && this.player) { - const pos = this.player.getPosition(); - const x = Math.floor(pos.x); - const y = Math.floor(pos.y); - this.terrainSystem.placeStructure(x, y, 'furnace'); - if (this.inventorySystem) { - this.inventorySystem.addItem('coal', 10); - this.inventorySystem.addItem('ore_iron', 10); - } - console.log(`๐Ÿญ Furnace placed at ${x},${y}`); - } - }; - - // Global command: placeMint() - window.placeMint = () => { - if (this.terrainSystem && this.player) { - const pos = this.player.getPosition(); - const x = Math.floor(pos.x); - const y = Math.floor(pos.y); - this.terrainSystem.placeStructure(x, y, 'mint'); - if (this.inventorySystem) { - this.inventorySystem.addItem('iron_bar', 10); - this.inventorySystem.addItem('coal', 10); - } - console.log(`๐Ÿ’ฐ Mint placed at ${x},${y}`); - } - }; - - // TESTNA DREVESA IN KAMNI - Za testiranje - console.log('๐ŸŒณ Adding test trees and rocks near player...'); - this.terrainSystem.addDecoration(52, 50, 'tree_green'); - this.terrainSystem.addDecoration(48, 50, 'rock'); - this.terrainSystem.addDecoration(50, 52, 'tree_oak'); - this.terrainSystem.addDecoration(50, 48, 'rock_large'); - console.log('โœ… Test decorations added at (50ยฑ2, 50ยฑ2)'); - - // Start Engine - this.Antigravity_Start(); - } catch (err) { - console.error('โŒ CRITICAL INITIALIZATION ERROR:', err); - } - } - - setupCamera() { - const cam = this.cameras.main; - - // ๐ŸŽจ FLAT 2D CAMERA SETUP (NEW!) - const worldSize = 100 * 48; // 100 tiles ร— 48px = 4800px - cam.setBounds(0, 0, worldSize, worldSize); - cam.setZoom(1.0); // Default zoom for 2D - - // Follow player - if (this.player && this.player.sprite) { - cam.startFollow(this.player.sprite, true, 0.1, 0.1); + } catch (e) { + console.error('โŒ CRITICAL: Player creation failed:', e); + // Emergency Kai + const emergencyKai = this.add.sprite(2400, 2400, 'player_style32'); + emergencyKai.setScale(0.25); + this.cameras.main.startFollow(emergencyKai); } - console.log('๐Ÿ“น 2D Camera setup:', worldSize, 'x', worldSize); - - // Zoom kontrole (Mouse Wheel) - this.input.on('wheel', (pointer, gameObjects, deltaX, deltaY, deltaZ) => { - const zoomSpeed = 0.001; - const newZoom = Phaser.Math.Clamp( - cam.zoom - deltaY * zoomSpeed, - 0.3, - 2.0 - ); - cam.setZoom(newZoom); - }); - - // Q/E za zoom - this.zoomKeys = this.input.keyboard.addKeys({ - zoomIn: Phaser.Input.Keyboard.KeyCodes.Q, - zoomOut: Phaser.Input.Keyboard.KeyCodes.E - }); - - // Save/Load Keys - this.input.keyboard.on('keydown-F8', () => this.saveGame()); - this.input.keyboard.on('keydown-F9', () => this.loadGame()); - - // ======================================================== - // ๐ŸŽ† WEEK 1 DEBUG COMMANDS - Test Keyboard Shortcuts - // ======================================================== - - // F10 - Spawn Electrician NPC near player - this.input.keyboard.on('keydown-F10', () => { - if (this.buildingUpgradeSystem && this.player) { - const x = this.player.gridX + 3; - const y = this.player.gridY; - this.buildingUpgradeSystem.spawnElectrician(x * 48, y * 48); - console.log('โšก Electrician spawned at player location!'); - } - }); - - // F11 - Spawn Zombie Statistician NPC near player - this.input.keyboard.on('keydown-F11', () => { - if (this.cityManagementSystem && this.player) { - const x = this.player.gridX - 3; - const y = this.player.gridY; - this.cityManagementSystem.spawnStatistician(x * 48, y * 48); - console.log('๐Ÿ‘” Zombie Statistician spawned at player location!'); - } - }); - - // F12 - Build ALL Week 1 buildings near player - this.input.keyboard.on('keydown-F12', () => { - if (this.player) { - const baseX = this.player.gridX; - const baseY = this.player.gridY; - - // Generator - if (this.buildingUpgradeSystem) { - this.buildingUpgradeSystem.buildGenerator((baseX + 5) * 48, baseY * 48); - console.log('๐Ÿญ Generator built!'); - } - - // City Hall - if (this.cityManagementSystem) { - this.cityManagementSystem.placeCityHall((baseX - 5) * 48, baseY * 48); - console.log('๐Ÿ›๏ธ City Hall built!'); - } - - // Population Board - if (this.cityManagementSystem) { - this.cityManagementSystem.placePopulationBoard((baseX - 5) * 48, (baseY + 3) * 48); - console.log('๐Ÿ“Š Population Board built!'); - } - - // Resource Depot - if (this.resourceLogisticsSystem) { - this.resourceLogisticsSystem.addDepot((baseX) * 48, (baseY - 5) * 48); - console.log('๐Ÿ“ฆ Resource Depot built!'); - } - - console.log('โœ… All Week 1 buildings constructed!'); - } - }); - - // NUMPAD 1 - Add test resources - this.input.keyboard.on('keydown-NUMPAD_ONE', () => { - if (this.resourceLogisticsSystem) { - this.resourceLogisticsSystem.addResource('wood', 100); - this.resourceLogisticsSystem.addResource('food', 50); - this.resourceLogisticsSystem.addResource('stone', 75); - console.log('๐Ÿ’Ž Added test resources: 100 wood, 50 food, 75 stone!'); - } - }); - - // NUMPAD 2 - Drop test resources near player - this.input.keyboard.on('keydown-NUMPAD_TWO', () => { - if (this.resourceLogisticsSystem && this.player) { - const x = this.player.x; - const y = this.player.y; - this.resourceLogisticsSystem.dropResource(x + 50, y, 'wood', 10); - this.resourceLogisticsSystem.dropResource(x - 50, y, 'food', 5); - this.resourceLogisticsSystem.dropResource(x, y + 50, 'stone', 8); - console.log('๐Ÿ“ฆ Dropped test resources around player!'); - } - }); - - // NUMPAD 3 - Hire Electrician (auto) - this.input.keyboard.on('keydown-NUMPAD_THREE', () => { - if (this.buildingUpgradeSystem && this.buildingUpgradeSystem.electrician) { - this.buildingUpgradeSystem.hireElectrician(); - console.log('โšก Electrician hired!'); - } else { - console.warn('โš ๏ธ Spawn Electrician first (F10)!'); - } - }); - - // NUMPAD 4 - Hire Zombie Statistician (auto) - this.input.keyboard.on('keydown-NUMPAD_FOUR', () => { - if (this.cityManagementSystem && this.cityManagementSystem.statistician) { - this.cityManagementSystem.hireStatistician(); - console.log('๐Ÿ‘” Zombie Statistician hired!'); - } else { - console.warn('โš ๏ธ Spawn Zombie Statistician first (F11)!'); - } - }); - - // NUMPAD 5 - Trigger Electrician inspection - this.input.keyboard.on('keydown-NUMPAD_FIVE', () => { - if (this.buildingUpgradeSystem && this.buildingUpgradeSystem.electrician) { - this.buildingUpgradeSystem.electricianInspectGenerator(); - console.log('โšก Electrician inspecting generator!'); - } else { - console.warn('โš ๏ธ Electrician not spawned or not hired!'); - } - }); - - // NUMPAD 6 - Trigger Electrician repair - this.input.keyboard.on('keydown-NUMPAD_SIX', () => { - if (this.buildingUpgradeSystem && this.buildingUpgradeSystem.electrician) { - this.buildingUpgradeSystem.electricianRepairGenerator(); - console.log('โšก Electrician repairing generator!'); - } else { - console.warn('โš ๏ธ Electrician not spawned or not hired!'); - } - }); - - // NUMPAD 7 - Trigger Statistician board update - this.input.keyboard.on('keydown-NUMPAD_SEVEN', () => { - if (this.cityManagementSystem && this.cityManagementSystem.statistician) { - this.cityManagementSystem.statisticianUpdateBoard(); - console.log('๐Ÿ‘” Zombie Statistician updating board!'); - } else { - console.warn('โš ๏ธ Zombie Statistician not spawned or not hired!'); - } - }); - - // NUMPAD 8 - Show all Week 1 stats - this.input.keyboard.on('keydown-NUMPAD_EIGHT', () => { - console.log('๐Ÿ“Š WEEK 1 SYSTEMS STATUS:'); - - if (this.resourceLogisticsSystem) { - const resources = this.resourceLogisticsSystem.getResources(); - console.log('๐Ÿ“ฆ Resources:', resources); - } - - if (this.cityManagementSystem) { - const population = this.cityManagementSystem.getPopulation(); - console.log('๐Ÿ‘ฅ Population:', population); - console.log('๐Ÿ‘” Statistician employed:', this.cityManagementSystem.statisticianEmployed); - } - - if (this.buildingUpgradeSystem) { - console.log('โšก Generator health:', this.buildingUpgradeSystem.generatorHealth + '%'); - console.log('โšก Power status:', this.buildingUpgradeSystem.isPowered ? 'ONLINE' : 'OFFLINE'); - console.log('โšก Electrician employed:', this.buildingUpgradeSystem.electricianEmployed); - } - }); - - console.log('๐ŸŽฎ Week 1 Debug Commands enabled!'); - console.log(' F10 = Spawn Electrician'); - console.log(' F11 = Spawn Zombie Statistician'); - console.log(' F12 = Build all Week 1 buildings'); - console.log(' Numpad 1 = Add resources'); - console.log(' Numpad 2 = Drop resources'); - console.log(' Numpad 3 = Hire Electrician'); - console.log(' Numpad 4 = Hire Statistician'); - console.log(' Numpad 5 = Electrician inspect'); - console.log(' Numpad 6 = Electrician repair'); - console.log(' Numpad 7 = Statistician update board'); - console.log(' Numpad 8 = Show all stats'); - // ======================================================== - - // Spawn Boss (Debug) - this.input.keyboard.on('keydown-K', () => this.spawnBoss()); - - // Build Mode Keys - this.input.keyboard.on('keydown-B', () => { - if (this.buildSystem) this.buildSystem.toggleBuildMode(); - }); - - // ๐Ÿ•ธ๏ธ Grid Toggle (G key) - this.input.keyboard.on('keydown-G', () => { - if (this.terrainSystem && this.terrainSystem.toggleGrid) { - this.terrainSystem.toggleGrid(); - } - }); - - this.input.keyboard.on('keydown-ONE', () => { - if (this.buildSystem && this.buildSystem.buildMode) this.buildSystem.selectBuilding('fence_post'); - else if (this.scene.get('UIScene')) this.scene.get('UIScene').selectSlot(0); - }); - - this.input.keyboard.on('keydown-TWO', () => { - if (this.buildSystem && this.buildSystem.buildMode) this.buildSystem.selectBuilding('fence_horizontal'); - else if (this.scene.get('UIScene')) this.scene.get('UIScene').selectSlot(1); - }); - - this.input.keyboard.on('keydown-THREE', () => { - if (this.buildSystem && this.buildSystem.buildMode) this.buildSystem.selectBuilding('fence_vertical'); - else if (this.scene.get('UIScene')) this.scene.get('UIScene').selectSlot(2); - }); - - this.input.keyboard.on('keydown-FOUR', () => { - if (this.buildSystem && this.buildSystem.buildMode) this.buildSystem.selectBuilding('fence_corner'); - else if (this.scene.get('UIScene')) this.scene.get('UIScene').selectSlot(3); - }); - - this.input.keyboard.on('keydown-FIVE', () => { - if (this.buildSystem && this.buildSystem.buildMode) this.buildSystem.selectBuilding('barn'); - else if (this.scene.get('UIScene')) this.scene.get('UIScene').selectSlot(4); - }); - - // Soft Reset (F4) - this.input.keyboard.on('keydown-F4', () => window.location.reload()); - - // Help / Tutorial (H key) - this.input.keyboard.on('keydown-H', () => { - if (this.tutorialSystem) { - this.tutorialSystem.showHelp(); - } - }); - - // Mute Toggle (M key) - this.input.keyboard.on('keydown-M', () => { - if (this.soundManager) this.soundManager.toggleMute(); - }); - - // ๐ŸŒง๏ธ WEATHER SYSTEM KEYS - this.input.keyboard.on('keydown-R', () => this.setWeather('rain')); - this.input.keyboard.on('keydown-SHIFT-S', () => this.setWeather('snow')); - this.input.keyboard.on('keydown-T', () => this.setWeather('storm')); - this.input.keyboard.on('keydown-F', () => this.setWeather('fog')); - this.input.keyboard.on('keydown-SHIFT-C', () => this.setWeather('clear')); - - // Initialize weather system - this.initializeWeatherSystem(); - - // Initialize Weather UI Panel - this.weatherUI = new WeatherUI(this); - console.log('๐Ÿ“Š Weather UI Panel created (press W to toggle)'); + console.log('๐Ÿš€ CLEAN SLATE INITIALIZATION COMPLETE'); } - // ๐ŸŒฆ๏ธ COMPLETE WEATHER SYSTEM - MASTER SYSTEM INTEGRATION - initializeWeatherSystem() { - console.log('๐ŸŒฆ๏ธ Integrating Master Weather System...'); + addStarterCampDecoration(centerX, centerY) { + console.log('๐ŸŒฒ Adding starter camp decoration (Graphics)...'); - // Get weather from global manager - if (this.game.weatherManager) { - this.weather = this.game.weatherManager.createForScene(this); + // TALL GRASS (10 green circles with SWAYING animation) + for (let i = 0; i < 10; i++) { + const angle = (Math.PI * 2 / 10) * i + Math.random() * 0.5; + const distance = 100 + Math.random() * 150; + const x = centerX + Math.cos(angle) * distance; + const y = centerY + Math.sin(angle) * distance; - // Set biome (grassland as default, change based on player location) - this.weather.setBiomeWeather('grassland'); + const grass = this.add.circle(x, y, 8 + Math.random() * 6, 0x4a8a4a, 0.8); + grass.setDepth(-50); + grass.setStrokeStyle(2, 0x2a5a2a, 1); - console.log('โœ… Master Weather System integrated!'); - console.log('๐Ÿ’ก R = Rain | Shift+S = Snow | T = Storm | Shift+C = Clear'); - - // Apply wind to player hair if exists - this.time.delayedCall(1000, () => { - if (this.player && this.player.sprite) { - // Create hair layer (example - adjust based on your player setup) - // this.playerHair = this.add.sprite(this.player.x, this.player.y - 10, 'kai_dreads'); - // this.weather.windSystem.applyWindToSprite(this.playerHair, 'hair'); - console.log('๐Ÿ’จ Wind system ready for player hair!'); - } - }); - - } else { - console.warn('โš ๏ธ GlobalWeatherManager not found! Using fallback weather.'); - // Fallback to old system - this.currentWeather = 'clear'; - this.weatherIntensity = 1.0; - this.puddles = []; - this.splashes = []; - this.autoWeatherEnabled = false; - this.weatherCycleTimer = null; - } - - console.log('๐ŸŒฆ๏ธ Weather system initialized'); - } - - toggleAutoWeather() { - this.autoWeatherEnabled = !this.autoWeatherEnabled; - - if (this.autoWeatherEnabled) { - console.log('๐Ÿ”„ Auto weather cycle ENABLED'); - this.startWeatherCycle(); - } else { - console.log('โธ๏ธ Auto weather cycle DISABLED'); - if (this.weatherCycleTimer) { - this.weatherCycleTimer.destroy(); - this.weatherCycleTimer = null; - } - } - this.saveWeatherState(); - } - - startWeatherCycle() { - // Weather cycle: Clear โ†’ Rain โ†’ Storm โ†’ Clear โ†’ Snow โ†’ Fog โ†’ Clear - const weatherSequence = ['clear', 'rain', 'storm', 'clear', 'snow', 'fog']; - const weatherDurations = { - clear: 120000, // 2 minutes - rain: 90000, // 1.5 minutes - storm: 60000, // 1 minute - snow: 90000, // 1.5 minutes - fog: 60000 // 1 minute - }; - - let currentIndex = 0; - - const cycleWeather = () => { - const nextWeather = weatherSequence[currentIndex]; - this.setWeather(nextWeather); - - currentIndex = (currentIndex + 1) % weatherSequence.length; - - const duration = weatherDurations[nextWeather] || 120000; - - this.weatherCycleTimer = this.time.delayedCall(duration, () => { - if (this.autoWeatherEnabled) { - cycleWeather(); - } - }); - - console.log(`๐ŸŒฆ๏ธ Auto weather: ${nextWeather} (${duration / 1000}s)`); - }; - - cycleWeather(); - } - - adjustIntensity(delta) { - this.weatherIntensity = Phaser.Math.Clamp(this.weatherIntensity + delta, 0.2, 2.0); - - // Update current weather with new intensity - if (this.currentWeather !== 'clear' && this.currentWeather !== 'fog') { - this.setWeather(this.currentWeather); // Restart with new intensity - } - - console.log(`๐ŸŽš๏ธ Weather intensity: ${(this.weatherIntensity * 100).toFixed(0)}%`); - this.saveWeatherState(); - } - - saveWeatherState() { - const state = { - currentWeather: this.currentWeather, - intensity: this.weatherIntensity, - autoEnabled: this.autoWeatherEnabled - }; - localStorage.setItem('novafarma_weather_state', JSON.stringify(state)); - } - - loadWeatherState() { - const saved = localStorage.getItem('novafarma_weather_state'); - if (saved) { - try { - const state = JSON.parse(saved); - this.currentWeather = state.currentWeather || 'clear'; - this.weatherIntensity = state.intensity || 1.0; - this.autoWeatherEnabled = state.autoEnabled || false; - - console.log('๐Ÿ“‚ Weather state loaded:', state); - - // Restore weather (delayed to avoid initialization issues) - this.time.delayedCall(1000, () => { - if (this.currentWeather !== 'clear') { - this.setWeather(this.currentWeather); - } - if (this.autoWeatherEnabled) { - this.startWeatherCycle(); - } - }); - } catch (e) { - console.warn('โš ๏ธ Failed to load weather state:', e); - } - } - } - - setWeather(type) { - console.log(`๐ŸŒฆ๏ธ Setting weather to: ${type}`); - - // Use MasterWeatherSystem if available - if (this.weather && this.weather.setWeather) { - const intensityMap = { - 'rain': 0.5, - 'snow': 0.6, - 'storm': 0.9, - 'blizzard': 1.0, - 'fog': 0.4, - 'clear': 0 - }; - - const intensity = intensityMap[type] || 0.5; - this.weather.setWeather(type, intensity, 2000); - - // Save state - this.currentWeather = type; - this.saveWeatherState(); - - } else { - // Fallback to old system - this.stopAllWeather(); - this.currentWeather = type; - - switch (type) { - case 'rain': - this.startRain(); - break; - case 'snow': - this.startSnow(); - break; - case 'storm': - this.startStorm(); - break; - case 'fog': - this.startFog(); - break; - case 'clear': - console.log('โ˜€๏ธ Clear weather'); - break; - } - - 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; - } - - // Stop puddle spawning - if (this.puddleTimer) { - this.puddleTimer.destroy(); - this.puddleTimer = null; - } - - // Fade out fog - if (this.fogOverlay) { + // SWAYING ANIMATION (wind effect) this.tweens.add({ - targets: this.fogOverlay, - alpha: 0, - duration: 2000, - onComplete: () => { - if (this.fogOverlay) this.fogOverlay.destroy(); - this.fogOverlay = null; - } + targets: grass, + x: x + (Math.random() - 0.5) * 10, // Sway left/right + scaleY: 0.9 + Math.random() * 0.2, // Slight height variation + duration: 1000 + Math.random() * 1000, + yoyo: true, + repeat: -1, // Infinite loop + ease: 'Sine.easeInOut', + delay: Math.random() * 1000 // Random start time }); } - // Cleanup puddles - this.puddles.forEach(puddle => { - this.tweens.add({ - targets: puddle, - alpha: 0, - duration: 3000, - onComplete: () => puddle.destroy() - }); - }); - this.puddles = []; - } + // TREES (3 dark green triangles around camp) + const treePositions = [ + { x: centerX - 200, y: centerY - 150 }, + { x: centerX + 220, y: centerY - 100 }, + { x: centerX - 180, y: centerY + 180 } + ]; - // โ˜” RAIN SYSTEM - startRain() { - if (!this.rainEmitter) { - this.createRainParticles(); - } + treePositions.forEach(pos => { + // Tree trunk (brown rectangle) + const trunk = this.add.rectangle(pos.x, pos.y + 20, 10, 30, 0x6b4423); + trunk.setDepth(-40); - // 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 + // Tree crown (green triangle) + const crown = this.add.triangle(pos.x, pos.y - 10, 0, 40, -30, -20, 30, -20, 0x2a6a2a); + crown.setDepth(-40); + crown.setStrokeStyle(3, 0x1a4a1a, 1); }); - // 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() - }); - }); - } + console.log('โœ… Starter camp decoration added!'); } update(time, delta) { + // 1. PLAYER UPDATE if (this.player) { - this.player.update(delta); + this.player.update(time, delta); + } - // Apply water physics - if (this.waterPhysics) { - this.waterPhysics.applyWaterPhysics(this.player, delta); + // 2. MANUAL CAMERA CONTROLS (Arrow Keys) + if (this.cursors) { + const speed = this.cameraSpeed || 8; + let moved = false; - // 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); - } - } - } + if (this.cursors.left.isDown) { + this.cameras.main.scrollX -= speed; + moved = true; + } else if (this.cursors.right.isDown) { + this.cameras.main.scrollX += speed; + moved = true; + } + + if (this.cursors.up.isDown) { + this.cameras.main.scrollY -= speed; + moved = true; + } else if (this.cursors.down.isDown) { + this.cameras.main.scrollY += speed; + moved = true; + } + + // If manual movement detected, stop following player + if (moved) { + this.cameras.main.stopFollow(); } } - // ๐ŸŽฏ Z-SORTING: SortableObjects based on Y position - if (this.sortableObjects) { - const children = this.sortableObjects.getChildren(); + // 3. TILESPRITE PARALLAX (Native Phaser) + if (this.grassBg) { + // Keep background visible at scale + this.grassBg.setX(this.cameras.main.scrollX + this.scale.width / 2); + this.grassBg.setY(this.cameras.main.scrollY + this.scale.height / 2); - // 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); - - // ๐ŸŽ† WEEK 1 SYSTEMS UPDATE - if (this.resourceLogisticsSystem) this.resourceLogisticsSystem.update(time, delta); - if (this.cityManagementSystem) this.cityManagementSystem.update(time, delta); - if (this.buildingUpgradeSystem) this.buildingUpgradeSystem.update(time, 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) }); + // Scroll texture + this.grassBg.tilePositionX = this.cameras.main.scrollX; + this.grassBg.tilePositionY = this.cameras.main.scrollY; } } - - 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; - - } - }); - } - } diff --git a/src/scenes/IntroScene.js b/src/scenes/IntroScene.js index 3be673f1a..ccf8e3069 100644 --- a/src/scenes/IntroScene.js +++ b/src/scenes/IntroScene.js @@ -34,18 +34,16 @@ class IntroScene extends Phaser.Scene { this.load.image('intro_ana_barbershop', dreamyPath + 'ana_barbershop_dreads_dreamy.png'); this.load.image('intro_birthday_cake', dreamyPath + 'birthday_cake_rd_dreamy.png'); this.load.image('intro_virus', introPath + 'virus_xnoir_microscope.png'); - this.load.image('intro_chaos', dreamyPath + 'chaos_streets_apocalypse_dreamy.png'); - this.load.image('intro_zombies', dreamyPath + 'zombie_silhouettes_panic_dreamy.png'); - this.load.image('intro_parents_ghosts', dreamyPath + 'parents_transparent_ghosts_dreamy.png'); - this.load.image('intro_ana_taken', introPath + 'ana_taken_military.png'); - this.load.image('intro_kai_alone', introPath + 'kai_alone_basement.png'); - this.load.image('intro_kai_young', introPath + 'kai_young_timelapse.png'); - this.load.image('intro_kai_adult', introPath + 'kai_adult_35_timelapse.png'); - this.load.image('intro_kai_elder', introPath + 'kai_elder_50_timelapse.png'); - this.load.image('intro_ana_memory', introPath + 'ana_memory_flash_purple.png'); - this.load.image('intro_bedroom', introPath + 'kai_bedroom_wakeup.png'); - this.load.image('intro_gronk', introPath + 'gronk_doorway_silhouette.png'); - this.load.image('intro_twins_childhood', introPath + 'kai_ana_twins_childhood.png'); + // REMOVED STORY ASSETS TO PREVENT 404 + // this.load.image('intro_kai_alone', introPath + 'kai_alone_basement.png'); + // Missing assets commented out to clean console errors + // this.load.image('intro_ana_memory', introPath + 'ana_memory_flash_purple.png'); + // this.load.image('intro_bedroom', introPath + 'kai_bedroom_wakeup.png'); // This was not in the instruction, but it's likely a missing asset too. + // this.load.image('intro_gronk_doorway', introPath + 'gronk_doorway_silhouette.png'); + // this.load.image('intro_kai_twins', introPath + 'kai_ana_twins_childhood.png'); + // this.load.image('intro_kai_basement', introPath + 'kai_alone_basement.png'); // This seems to be a duplicate of intro_kai_alone, but with a different key. + + console.log('โœ… IntroScene assets skipped (clean console check)'); // ๐ŸŽต AMBIENT MUSIC this.loadAudioSafe('noir_ambience', 'assets/audio/ambient/noir_ambience.mp3'); diff --git a/src/scenes/PreloadScene.js b/src/scenes/PreloadScene.js index d7d9ebe36..98a4e3b51 100644 --- a/src/scenes/PreloadScene.js +++ b/src/scenes/PreloadScene.js @@ -57,76 +57,29 @@ class PreloadScene extends Phaser.Scene { // Load Manifest Images // Since we are using script tags in index.html, window.AssetManifest is already available! - if (window.AssetManifest) { - const manifest = window.AssetManifest; + // REMOVED MANIFEST CHECK - FORCE LOAD ASSETS + console.log('๐Ÿ“ฆ FORCE LOADING ASSETS (No Manifest Check)...'); - console.log(`๐Ÿ“ฆ Loading Asset Manifest (Phased)...`); + // ๐ŸŽจ TILESET IMAGES + console.log('๐Ÿ” LOADING REFERENCE GRASS: assets/slike/teren/grass_tile.png'); + this.load.image('trava_osnova', 'assets/slike/teren/grass_tile.png'); + this.load.image('tileset_grass', 'assets/slike/teren/grass_tile.png'); // Duplicate for safety - // Iterate over phases (farm, basement_mine, etc.) - if (manifest.phases) { - Object.keys(manifest.phases).forEach(phaseName => { - console.log(`Phase: ${phaseName} - ${manifest.phases[phaseName].length} items`); - manifest.phases[phaseName].forEach(img => { - this.loadImageSafe(img.key, img.path); - }); - }); - } + this.load.image('tileset_dirt', 'assets/slike/teren/dirt.png'); + this.load.image('tileset_water', 'assets/slike/teren/water.png'); + this.load.image('tileset_stone', 'assets/slike/teren/stone.png'); - // Iterate over spritesheets - if (manifest.spritesheets) { - manifest.spritesheets.forEach(sheet => { - this.load.spritesheet(sheet.key, sheet.path, sheet.frameConfig); - }); - } + // Legacy Keys + this.load.image('tileset_Terrain_Grass', 'assets/slike/teren/grass_tile.png'); + this.load.image('tileset_Terrain_Dirt', 'assets/slike/teren/dirt.png'); + this.load.image('tileset_Terrain_Water', 'assets/slike/teren/water.png'); - console.log('โœ… AssetManifest Queue Complete'); + console.log('โœ… All Tilesets Preloaded!'); - // ๐Ÿ—บ๏ธ TILESET IMAGES (For Tiled maps - Faza1_Finalna.tmx) - console.log('๐ŸŽจ Preloading All Tileset Images...'); - - // Terrain - UPDATED FOR STYLE 32 (Flat2DTerrainSystem keys) - console.log('๐Ÿ” ATTEMPTING LOAD: assets/slike/teren/grass_tile.png'); - this.load.image('trava_osnova', 'assets/slike/teren/grass_tile.png'); - // Legacy/Map keys - this.load.image('tileset_grass', 'assets/slike/teren/grass_tile.png'); // Keep for map compatibility - // Intro Assets (Verified paths in assets/slike/zgodba) - // 'ana_memory_flash' not found, using 'intro_twin_photo' as placeholder - this.load.image('intro_ana_memory', 'assets/slike/zgodba/assets_references_intro_twin_photo.png'); - // 'kai_bedroom_wakeup' not found, using 'intro_cellar' placeholder for now - this.load.image('intro_bedroom_wakeup', 'assets/slike/zgodba/assets_references_intro_cellar_ruins.png'); - - this.load.image('tileset_dirt', 'assets/slike/teren/dirt.png'); - this.load.image('tileset_water', 'assets/slike/teren/water.png'); - // this.load.image('tileset_farmland', 'assets/slike/teren/farmland.png'); // DISABLED: Not found in teren - this.load.image('tileset_stone', 'assets/slike/teren/stone.png'); - - // Legacy Keys (Keep for Tiled Map compatibility if needed) - this.load.image('tileset_Terrain_Grass', 'assets/slike/teren/grass_tile.png'); - this.load.image('tileset_Terrain_Dirt', 'assets/slike/teren/dirt.png'); - this.load.image('tileset_Terrain_Water', 'assets/slike/teren/water.png'); - - // Fences (Commented out if not in teren/okolje yet, likely in ZA_PREGLED) - // this.load.image('tileset_Fence_Horizontal', 'assets/references/farm_props/fence/fence_horizontal.png'); - // this.load.image('tileset_Fence_Vertical', 'assets/references/farm_props/fence/fence_vertical.png'); - // this.load.image('tileset_Fence_Corner', 'assets/references/farm_props/fence/fence_corner.png'); - - - // Trees (Commented out legacy paths) - // this.load.image('tileset_Tree_Apple', 'assets/references/trees/apple/apple_tree.png'); - // this.load.image('tileset_Tree_Cherry', 'assets/references/trees/cherry/cherry_tree.png'); - // this.load.image('tileset_Tree_Dead', 'assets/maps/tilesets/Tree_Dead.png'); - - // Buildings - // this.load.image('tileset_House_Gothic', 'assets/references/buildings/kai_house/04_gothic_house.png'); - - console.log('โœ… All Tilesets Preloaded!'); - - // MAP (Tiled JSON) - this.load.tilemapTiledJSON('NovaFarma', 'assets/maps/NovaFarma.json'); - console.log('๐Ÿ—บ๏ธ Preloading NovaFarma.json map...'); - } else { - console.error('โŒ Critical: window.AssetManifest not found! Check index.html imports.'); - } + // MAP (Tiled JSON) + // Found at: assets/maps/NovaFarma.json + this.load.tilemapTiledJSON('NovaFarma', 'assets/maps/NovaFarma.json'); + console.log('๐Ÿ—บ๏ธ Preloading NovaFarma.json map...'); } loadImageSafe(key, path) { @@ -145,7 +98,7 @@ class PreloadScene extends Phaser.Scene { // this.load.audio('background_music', 'assets/audio/bg_noir.mp3'); - // ๐Ÿง›โ€โ™‚๏ธ GRONK SPRITESHEET (Verified) + // ๐Ÿง›โ€โ™‚๏ธ GRONK (Verified Path: assets/slike/liki/gronk_pro_sheet.png) this.load.spritesheet('gronk_pro_sheet', 'assets/slike/liki/gronk_pro_sheet.png', { frameWidth: 128, frameHeight: 128 @@ -597,8 +550,8 @@ class PreloadScene extends Phaser.Scene { // โœ… Starting INTRO SEQUENCE (NEW! Jan 10, 2026) this.time.delayedCall(500, () => { - console.log('๐ŸŽฌ Starting IntroScene (Cinematic Intro)...'); - this.scene.start('IntroScene'); // โ† NEW INTRO SEQUENCE + console.log('๐ŸŽฌ Starting GameScene (DEMO MODE - SKIP INTRO)...'); + this.scene.start('GameScene'); // โ† NEW INTRO SEQUENCE }); } }); @@ -607,15 +560,15 @@ class PreloadScene extends Phaser.Scene { create() { console.log('๐ŸŽต Starting Background Music Loop...'); - try { - if (!this.sound.get('background_music')) { - this.sound.play('background_music', { loop: true, volume: 0.5 }); - } else if (!this.sound.get('background_music').isPlaying) { - this.sound.get('background_music').play(); - } - } catch (e) { - console.warn('๐ŸŽต Audio Playback Failed (Autoplay policy?):', e); - } + // try { + // if (!this.sound.get('background_music')) { + // this.sound.play('background_music', { loop: true, volume: 0.5 }); + // } else if (!this.sound.get('background_music').isPlaying) { + // this.sound.get('background_music').play(); + // } + // } catch (e) { + // console.warn('๐ŸŽต Audio Playback Failed (Autoplay policy?):', e); + // } // The actual scene start logic has been moved to the 'load.on(complete)' callback // to ensure all assets are fully loaded and the loading bar has faded out. diff --git a/src/scenes/UIScene.js b/src/scenes/UIScene.js index 25f8d54d4..d46bc68b5 100644 --- a/src/scenes/UIScene.js +++ b/src/scenes/UIScene.js @@ -2240,7 +2240,7 @@ class UIScene extends Phaser.Scene { // Background - FARM THEME const bg = this.add.graphics(); - bg.fillStyle(0x4a3520, 0.9); // Brown wood + bg.fillStyle(0x4a3520, 0.7); // Brown wood (70% alpha for noir) bg.fillRect(0, 0, panelWidth, panelHeight); bg.lineStyle(3, 0x8B4513, 0.8); // Saddle brown bg.strokeRect(0, 0, panelWidth, panelHeight); @@ -2298,7 +2298,7 @@ class UIScene extends Phaser.Scene { // Background - FARM THEME const bg = this.add.graphics(); - bg.fillStyle(0x2a4a2a, 0.9); // Dark green + bg.fillStyle(0x2a4a2a, 0.7); // Dark green (70% alpha for noir) bg.fillRect(0, 0, panelWidth, panelHeight); bg.lineStyle(3, 0x90EE90, 0.8); // Light green border bg.strokeRect(0, 0, panelWidth, panelHeight); diff --git a/src/systems/AudioLoader.js b/src/systems/AudioLoader.js index 65076ede5..34217f415 100644 --- a/src/systems/AudioLoader.js +++ b/src/systems/AudioLoader.js @@ -115,7 +115,7 @@ export class AudioLoader { // Common sound keys that systems expect const fallbackKeys = [ - 'background_music', + // 'background_music', 'music_chill_lofi', 'mayor_anthem', 'zombie_satisfied', diff --git a/src/systems/CinematicVoiceSystem.js b/src/systems/CinematicVoiceSystem.js index 7c4ddc840..7d86ec976 100644 --- a/src/systems/CinematicVoiceSystem.js +++ b/src/systems/CinematicVoiceSystem.js @@ -125,9 +125,11 @@ export class CinematicVoiceSystem { return new Promise((resolve) => { utterance.onend = () => { // Restore music volume + /* if (this.scene.sound && this.scene.sound.get('background_music')) { this.duckMusic(1.0, 800); // Restore to 100% over 800ms } + */ resolve(); }; }); @@ -251,6 +253,7 @@ export class CinematicVoiceSystem { * Duck/restore background music volume */ duckMusic(targetVolume, duration) { + /* const music = this.scene.sound.get('background_music'); if (!music) return; @@ -260,6 +263,7 @@ export class CinematicVoiceSystem { duration: duration, ease: 'Sine.easeInOut' }); + */ } /** diff --git a/src/systems/DrugEconomySystem.js b/src/systems/DrugEconomySystem.js index d9c6ffe96..7d508a8f2 100644 --- a/src/systems/DrugEconomySystem.js +++ b/src/systems/DrugEconomySystem.js @@ -144,7 +144,7 @@ export class DrugEconomySystem { applyMarijuanaAudio(config) { // Change music to chill variant - const currentMusic = this.scene.sound.get('background_music'); + const currentMusic = null; // this.scene.sound.get('background_music'); if (currentMusic) { // Fade out current this.scene.tweens.add({ @@ -189,7 +189,7 @@ export class DrugEconomySystem { duration: 2000, onComplete: () => { chillMusic.stop(); - this.scene.sound.play('background_music', { loop: true, volume: 0.5 }); + // this.scene.sound.play('background_music', { loop: true, volume: 0.5 }); } }); } diff --git a/src/systems/ElectionSystem.js b/src/systems/ElectionSystem.js index 17d8b3f92..86ed25a18 100644 --- a/src/systems/ElectionSystem.js +++ b/src/systems/ElectionSystem.js @@ -308,9 +308,9 @@ export class ElectionSystem { } // Change music to ordered/military theme - if (this.scene.sound && this.scene.sound.get('background_music')) { - this.scene.sound.get('background_music').stop(); - } + // if (this.scene.sound && this.scene.sound.get('background_music')) { + // this.scene.sound.get('background_music').stop(); + // } this.scene.sound.play('mayor_anthem', { loop: true, volume: 0.5 }); // Unlock new features diff --git a/test_log.txt b/test_log.txt index 60328991d..1d3d78d50 100644 --- a/test_log.txt +++ b/test_log.txt @@ -16,3 +16,85 @@ [2026-01-16T22:32:55.980Z] CLICK: "CANVAS" at (575, 456) [2026-01-16T22:32:56.453Z] CLICK: "CANVAS" at (575, 457) [2026-01-16T22:32:56.994Z] CLICK: "CANVAS" at (576, 458) +[2026-01-17T10:24:35.121Z] CLICK: "CANVAS" at (579, 460) +[2026-01-17T10:36:14.716Z] CLICK: "CANVAS" at (908, 487) +[2026-01-17T10:36:33.704Z] CLICK: "CANVAS" at (748, 393) +[2026-01-17T10:39:00.310Z] CLICK: "CANVAS" at (913, 580) +[2026-01-17T10:39:11.508Z] CLICK: "CANVAS" at (915, 567) +[2026-01-17T10:42:30.481Z] CLICK: "CANVAS" at (900, 486) +[2026-01-17T10:42:38.107Z] CLICK: "CANVAS" at (857, 434) +[2026-01-17T10:43:47.956Z] CLICK: "CANVAS" at (956, 208) +[2026-01-17T10:54:13.790Z] CLICK: "CANVAS" at (804, 508) +[2026-01-17T10:54:16.355Z] CLICK: "CANVAS" at (804, 499) +[2026-01-17T10:57:29.275Z] CLICK: "CANVAS" at (752, 393) +[2026-01-17T11:03:23.237Z] CLICK: "CANVAS" at (672, 273) +[2026-01-17T11:06:00.593Z] CLICK: "CANVAS" at (751, 387) +[2026-01-17T11:06:10.184Z] CLICK: "CANVAS" at (871, 182) +[2026-01-17T11:16:59.532Z] CLICK: "CANVAS" at (781, 354) +[2026-01-17T11:17:00.652Z] CLICK: "CANVAS" at (702, 440) +[2026-01-17T11:17:00.867Z] CLICK: "CANVAS" at (701, 440) +[2026-01-17T11:17:01.883Z] CLICK: "CANVAS" at (750, 467) +[2026-01-17T11:17:02.763Z] CLICK: "CANVAS" at (679, 470) +[2026-01-17T11:17:03.597Z] CLICK: "CANVAS" at (680, 469) +[2026-01-17T11:21:58.998Z] CLICK: "CANVAS" at (605, 332) +[2026-01-17T11:22:11.989Z] CLICK: "CANVAS" at (696, 192) +[2026-01-17T11:27:05.930Z] ERROR: Uncaught SyntaxError: Missing catch or finally after try at file:///Users/davidkotnik/repos/novafarma/src/scenes/GameScene.js:366 +[2026-01-17T11:27:09.191Z] CLICK:
"DIV" at (765, 394) +[2026-01-17T11:27:11.166Z] CLICK: