// StoryScene - Main Menu / Launcher // Loaded as global class (not ES6 module) class StoryScene extends Phaser.Scene { constructor() { super({ key: 'StoryScene' }); } preload() { // Load audio assets this.load.audio('forest_ambient', 'assets/audio/music/forest_ambient.mp3'); } create() { const width = this.cameras.main.width; const height = this.cameras.main.height; // ๐ŸŽจ NOIR GRADIENT BACKGROUND (dark red-black) const graphics = this.add.graphics(); graphics.fillGradientStyle(0x1a0000, 0x1a0000, 0x000000, 0x000000, 1); graphics.fillRect(0, 0, width, height); // ๐ŸŒซ๏ธ NOIR FOG EFFECT this.createNoirFog(width, height); // ๐ŸŽต NOIR BACKGROUND MUSIC this.playNoirMusic(); // MAIN TITLE (horizontal, top center) const titleBg = this.add.rectangle(width / 2, 80, 480, 70, 0x4a3520, 0.9); titleBg.setStrokeStyle(3, 0xd4a574); const title = this.add.text(width / 2, 80, 'MRTVA DOLINA', { fontSize: '42px', fontFamily: 'Georgia, serif', color: '#f4e4c1', fontStyle: 'bold', stroke: '#2d1b00', strokeThickness: 4 }); title.setOrigin(0.5); // Subtle glow this.tweens.add({ targets: title, alpha: 0.9, yoyo: true, repeat: -1, duration: 2000, ease: 'Sine.easeInOut' }); // Subtitle const subtitle = this.add.text(width / 2, 120, '~ 2084 - Survival Farm ~', { fontSize: '14px', fontFamily: 'Georgia, serif', color: '#d4a574', fontStyle: 'italic' }); subtitle.setOrigin(0.5); // Main Menu Buttons (center) this.createMainMenu(width, height); // Accessibility icon (top-right) this.createAccessibilityIcon(width, height); // Language selector with rotating globe (bottom-right) this.createLanguageSelector(width, height); // Version info const version = this.add.text(10, height - 30, 'v0.95 ALPHA', { fontSize: '14px', color: '#6b4423', fontFamily: 'Georgia, serif' }); // ๐ŸŽฅ STREAMER BUILD LABEL (top-right) const streamerLabel = this.add.text( width - 10, 10, 'Early Access Streamer Build', { fontSize: '12px', fontFamily: 'Georgia, serif', color: '#d4a574', backgroundColor: '#2d1b00', padding: { x: 8, y: 4 } } ); streamerLabel.setOrigin(1, 0); // Top-right anchor // Subtle pulse this.tweens.add({ targets: streamerLabel, alpha: 0.7, yoyo: true, repeat: -1, duration: 2000, ease: 'Sine.easeInOut' }); } createNoirFog(width, height) { // Create fog particles with SOFT texture const graphics = this.add.graphics(); // Soft feathered circle (not harsh edges) const gradient = graphics.createRadialGradient(32, 32, 0, 32, 32, 32); gradient.addColorStop(0, 'rgba(200, 200, 200, 1)'); gradient.addColorStop(0.5, 'rgba(150, 150, 150, 0.5)'); gradient.addColorStop(1, 'rgba(100, 100, 100, 0)'); graphics.fillStyle(0xCCCCCC, 1); graphics.fillCircle(32, 32, 28); graphics.generateTexture('fog_particle', 64, 64); graphics.destroy(); // Fog particle emitter - SOFTER, LARGER, SUBTLE const fogEmitter = this.add.particles(0, 0, 'fog_particle', { x: { min: -100, max: width + 100 }, y: { min: -50, max: height + 50 }, speedX: { min: -10, max: 10 }, speedY: { min: -3, max: 3 }, scale: { start: 2.0, end: 4.0 }, // LARGER! alpha: { start: 0, end: 0.05 }, // SUBTLE! lifespan: 15000, frequency: 600, quantity: 1 }); fogEmitter.setDepth(2); // ENHANCED NOIR VIGNETTE (dark edges) const vignette = this.add.rectangle(width / 2, height / 2, width, height, 0x000000, 0); vignette.setDepth(100); this.tweens.add({ targets: vignette, alpha: 0.5, // Stronger vignette duration: 3000, yoyo: true, repeat: -1, ease: 'Sine.easeInOut' }); } playNoirMusic() { // Play forest evening ambience (noir atmosphere) if (this.sound.get('forest_ambient')) { const music = this.sound.add('forest_ambient', { volume: 0.3, loop: true }); music.play(); console.log('๐ŸŽต Noir atmosphere music playing at 30% volume'); } else { console.warn('โš ๏ธ forest_ambient music not loaded - add to preload()'); } } createMainMenu(width, height) { // Get localized button texts const i18n = window.i18n; const buttons = [ { label: i18n ? i18n.t('new_game', 'โ–ถ NEW GAME') : 'โ–ถ NEW GAME', color: '#8fbc8f', action: () => this.startNewGame() }, { label: i18n ? i18n.t('load_game', '๐Ÿ“ LOAD GAME') : '๐Ÿ“ LOAD GAME', color: '#87ceeb', action: () => this.loadGame() }, { label: i18n ? i18n.t('settings', 'โš™๏ธ SETTINGS') : 'โš™๏ธ SETTINGS', color: '#daa520', action: () => this.showSettings() }, { label: i18n ? i18n.t('exit', 'โŒ EXIT') : 'โŒ EXIT', color: '#cd5c5c', action: () => this.exitGame() } ]; const startY = 170; const spacing = 58; buttons.forEach((btn, index) => { const y = startY + (index * spacing); // Wooden button background (Stardew style) const bg = this.add.rectangle(width / 2, y, 280, 48, 0x6b4423, 1); bg.setStrokeStyle(2, 0xd4a574); // Inner shadow effect const innerShadow = this.add.rectangle(width / 2, y + 2, 270, 38, 0x4a3520, 0.5); // Button text - USE NOTO SANS FOR UTF-8 SUPPORT const text = this.add.text(width / 2, y, btn.label, { fontSize: '20px', fontFamily: '"Noto Sans", "Noto Sans SC", Georgia, sans-serif', // ๐ŸŒ UTF-8 SUPPORT! color: btn.color, fontStyle: 'bold', stroke: '#2d1b00', strokeThickness: 3 }); text.setOrigin(0.5); // Make interactive bg.setInteractive({ useHandCursor: true }); bg.on('pointerover', () => { bg.setFillStyle(0x8b5a3c); text.setScale(1.05); bg.setStrokeStyle(4, 0xf4e4c1); }); bg.on('pointerout', () => { bg.setFillStyle(0x6b4423); text.setScale(1.0); bg.setStrokeStyle(3, 0xd4a574); }); bg.on('pointerdown', () => { // Press effect this.tweens.add({ targets: [bg, text, innerShadow], y: y + 3, duration: 100, yoyo: true, onComplete: btn.action }); }); }); } createAccessibilityIcon(width, height) { // Accessibility icon (top-right) - Stardew style const iconBg = this.add.circle(width - 50, 40, 26, 0x6b4423); iconBg.setStrokeStyle(2, 0xd4a574); const icon = this.add.text(width - 50, 40, 'โ™ฟ', { fontSize: '32px', color: '#8fbc8f' }); icon.setOrigin(0.5); icon.setInteractive({ useHandCursor: true }); // Gentle pulse animation this.tweens.add({ targets: [icon, iconBg], scale: 1.08, duration: 1500, yoyo: true, repeat: -1, ease: 'Sine.easeInOut' }); icon.on('pointerover', () => { icon.setScale(1.2); iconBg.setScale(1.2); iconBg.setFillStyle(0x8b5a3c); }); icon.on('pointerout', () => { icon.setScale(1.0); iconBg.setScale(1.0); iconBg.setFillStyle(0x6b4423); }); icon.on('pointerdown', () => { this.showAccessibility(); }); } createLanguageSelector(width, height) { // Initialize localization if (!window.i18n) { window.i18n = new LocalizationSystem(); } // Wooden circle background for globe (Stardew style) const globeBg = this.add.circle(width - 60, height - 60, 30, 0x6b4423); globeBg.setStrokeStyle(2, 0xd4a574); // Rotating globe button const globeBtn = this.add.text(width - 60, height - 60, '๐ŸŒ', { fontSize: '42px' }); globeBtn.setOrigin(0.5); globeBtn.setInteractive({ useHandCursor: true }); // Continuous rotation animation this.tweens.add({ targets: globeBtn, angle: 360, duration: 8000, repeat: -1, ease: 'Linear' }); let langMenuOpen = false; let langMenu = null; globeBtn.on('pointerover', () => { globeBtn.setScale(1.15); globeBg.setScale(1.15); globeBg.setFillStyle(0x8b5a3c); }); globeBtn.on('pointerout', () => { if (!langMenuOpen) { globeBtn.setScale(1.0); globeBg.setScale(1.0); globeBg.setFillStyle(0x6b4423); } }); globeBtn.on('pointerdown', () => { if (langMenuOpen) { // Close menu if (langMenu) langMenu.destroy(); langMenu = null; langMenuOpen = false; globeBtn.setScale(1.0); } else { // Open menu langMenuOpen = true; langMenu = this.createLanguageMenu(width, height, () => { langMenuOpen = false; globeBtn.setScale(1.0); if (langMenu) langMenu.destroy(); langMenu = null; }); } }); } createLanguageMenu(width, height, onClose) { const container = this.add.container(0, 0); const languages = [ { code: 'slo', flag: '๐Ÿ‡ธ๐Ÿ‡ฎ', name: 'Slovenลกฤina' }, { code: 'en', flag: '๐Ÿ‡ฌ๐Ÿ‡ง', name: 'English' }, { code: 'de', flag: '๐Ÿ‡ฉ๐Ÿ‡ช', name: 'Deutsch' }, { code: 'it', flag: '๐Ÿ‡ฎ๐Ÿ‡น', name: 'Italiano' }, { code: 'cn', flag: '๐Ÿ‡จ๐Ÿ‡ณ', name: 'ไธญๆ–‡' } ]; const menuX = width - 200; const menuY = height - 350; const menuW = 180; const menuH = 290; // Wooden panel background (Stardew style) const panel = this.add.rectangle(menuX, menuY, menuW, menuH, 0x6b4423, 0.98); panel.setStrokeStyle(4, 0xd4a574); container.add(panel); // Title const title = this.add.text(menuX, menuY - 120, 'LANGUAGE', { fontSize: '18px', fontFamily: 'Georgia, serif', color: '#f4e4c1', fontStyle: 'bold' }); title.setOrigin(0.5); container.add(title); // Language buttons languages.forEach((lang, index) => { const btnY = menuY - 90 + (index * 56); const isActive = window.i18n.getCurrentLanguage() === lang.code; const btn = this.add.text(menuX, btnY, `${lang.flag} ${lang.name}`, { fontSize: '16px', fontFamily: 'Georgia, serif', color: isActive ? '#8fbc8f' : '#f4e4c1', backgroundColor: isActive ? '#4a3520' : '#6b4423', padding: { x: 12, y: 6 } }); btn.setOrigin(0.5); btn.setInteractive({ useHandCursor: true }); btn.on('pointerover', () => { btn.setScale(1.05); if (!isActive) btn.setBackgroundColor('#8b5a3c'); }); btn.on('pointerout', () => { btn.setScale(1.0); if (!isActive) btn.setBackgroundColor('#6b4423'); }); btn.on('pointerdown', () => { window.i18n.setLanguage(lang.code); // ๐ŸŽค VOICE FALLBACK NOTICE if (lang.code !== 'slo' && lang.code !== 'en') { const notice = [ '๐ŸŽค VOICE NOTICE', '', `Language changed to ${lang.name}`, '', 'Audio remains in English,', 'but all text is 100% localized.', '', 'Full voiceover available in:', '๐Ÿ‡ธ๐Ÿ‡ฎ Slovenลกฤina', '๐Ÿ‡ฌ๐Ÿ‡ง English' ].join('\n'); alert(notice); } onClose(); // Reload scene to apply language this.scene.restart(); }); container.add(btn); }); // ๐ŸŽค VOICE INFO (bottom of menu) const voiceInfo = this.add.text( menuX, menuY + 120, '๐ŸŽค Full Voice:\n๐Ÿ‡ธ๐Ÿ‡ฎ SL ๐Ÿ‡ฌ๐Ÿ‡ง EN', { fontSize: '10px', fontFamily: '"Noto Sans", Georgia, sans-serif', color: '#d4a574', align: 'center', alpha: 0.7 } ); voiceInfo.setOrigin(0.5); container.add(voiceInfo); return container; } startNewGame() { console.log('๐ŸŽฎ Starting New Game...'); console.log('๐ŸŽฅ Launching ULTIMATE Prologue (100% Polished!)...'); this.scene.start('UltimatePrologueScene'); // โœ… ULTIMATE INTRO! } loadGame() { console.log('๐Ÿ“ Loading Game from LocalStorage...'); try { // Load from LocalStorage const saveKey = 'mrtva_dolina_save'; const savedData = localStorage.getItem(saveKey); if (!savedData) { console.log('โŒ No save file found'); alert('No save file found!\n\nStart a NEW GAME first to create a save.'); return; } // Parse save data const saveFile = JSON.parse(savedData); console.log('โœ… Save file loaded:', saveFile); // Display save info const info = [ '๐Ÿ“‚ SAVE FILE LOADED', '', `Age: ${saveFile.player.current_age} years old`, `Age Level: ${saveFile.player.age_level}/9`, `Memories Found: ${saveFile.progress.memories_found}/${saveFile.progress.total_memories}`, `Money: ${saveFile.economy.money} coins`, `Cannabis Seeds: ${saveFile.economy.cannabis_seeds}`, `Playtime: ${Math.floor(saveFile.playtime / 60)} minutes`, '', `Last Saved: ${new Date(saveFile.lastSaved).toLocaleString()}`, '', 'Load this save?' ].join('\n'); if (confirm(info)) { console.log('๐ŸŽฎ Starting game with loaded save...'); // Pass save data to GameScene this.scene.start('GameScene', { loadedSave: saveFile }); } } catch (error) { console.error('โŒ Failed to load save:', error); alert('Error loading save file!\n\nThe save may be corrupted.\nTry starting a new game.'); } } showSettings() { console.log('โš™๏ธ Opening Settings...'); // TODO: Settings menu alert('Settings - Use โš™๏ธ button in-game!'); } showAccessibility() { console.log('โ™ฟ Opening Accessibility Menu...'); // Initialize AccessibilityManager if not exists if (!this.accessibility) { this.accessibility = new AccessibilityManager(this); } // Create live accessibility menu const width = this.cameras.main.width; const height = this.cameras.main.height; const menuBg = this.add.rectangle(width / 2, height / 2, 500, 400, 0x000000, 0.9); menuBg.setDepth(1000); const title = this.add.text(width / 2, height / 2 - 170, 'โ™ฟ ACCESSIBILITY OPTIONS', { fontSize: '24px', fontFamily: '"Noto Sans", Georgia, serif', color: '#f4e4c1', fontStyle: 'bold' }); title.setOrigin(0.5); title.setDepth(1001); const instructions = [ 'Press number keys to toggle:', '', '1. High Contrast Mode', '2. Large Text (2x)', '3. Color Blind Mode', '4. Screen Reader', '5. Reduce Motion', '6. One-Handed (Left)', '7. Font Scale Reset', '', 'Press ESC to close' ]; const instructionsText = this.add.text(width / 2, height / 2 - 50, instructions.join('\n'), { fontSize: '16px', fontFamily: '"Noto Sans", Georgia, serif', color: '#d4a574', align: 'center', lineSpacing: 8 }); instructionsText.setOrigin(0.5); instructionsText.setDepth(1001); // Keyboard listener for options const keyHandler = (event) => { switch (event.key) { case '1': if (this.accessibility.settings.highContrast) { this.accessibility.disableHighContrast(); alert('โœ… High Contrast: OFF'); } else { this.accessibility.enableHighContrast(); alert('โœ… High Contrast: ON'); } break; case '2': this.accessibility.setSubtitleSize('xlarge'); alert('โœ… Large Text: ON (2.0x scale)'); break; case '3': if (this.accessibility.settings.colorBlindMode === 'none') { this.accessibility.setColorBlindMode('protanopia'); alert('โœ… Color Blind Mode: Protanopia'); } else { this.accessibility.setColorBlindMode('none'); alert('โœ… Color Blind Mode: OFF'); } break; case '4': alert('โ„น๏ธ Screen Reader: Coming soon!'); break; case '5': if (this.accessibility.settings.reduceMotion) { this.accessibility.disableReduceMotion(); alert('โœ… Reduce Motion: OFF'); } else { this.accessibility.enableReduceMotion(); alert('โœ… Reduce Motion: ON'); } break; case '6': if (this.accessibility.settings.oneHandedMode) { this.accessibility.disableOneHandedMode(); alert('โœ… One-Handed Mode: OFF'); } else { this.accessibility.enableOneHandedMode('left'); alert('โœ… One-Handed Mode: LEFT HAND'); } break; case '7': this.accessibility.setFontScale(1.0); alert('โœ… Font Scale: Reset to 1.0x'); break; case 'Escape': menuBg.destroy(); title.destroy(); instructionsText.destroy(); document.removeEventListener('keydown', keyHandler); break; } }; document.addEventListener('keydown', keyHandler); } exitGame() { console.log('โŒ Exiting...'); if (window.close) { window.close(); } else { alert('Close the window to exit.'); } } }