/** * CENTRAL POPUP SYSTEM * Displays important messages, quests, and dialogs in center of screen * Always appears in front of player for easy reading */ class CentralPopupSystem { constructor(scene) { this.scene = scene; this.enabled = true; // Current popup this.currentPopup = null; this.popupQueue = []; this.isShowing = false; // Settings this.settings = { enabled: true, autoClose: true, autoCloseDelay: 5000, // 5 seconds pauseGameOnPopup: true, soundOnPopup: true }; this.loadSettings(); console.log('✅ Central Popup System initialized'); } /** * Show popup in center of screen */ showPopup(config) { const popup = { title: config.title || 'Notification', message: config.message || '', type: config.type || 'info', // info, quest, warning, success, story icon: config.icon || '📋', buttons: config.buttons || [{ text: 'OK', action: 'close' }], image: config.image || null, autoClose: config.autoClose !== undefined ? config.autoClose : this.settings.autoClose, onClose: config.onClose || null, priority: config.priority || 'normal' // low, normal, high, critical }; // Add to queue this.popupQueue.push(popup); // Show if not already showing if (!this.isShowing) { this.displayNextPopup(); } } /** * Display next popup from queue */ displayNextPopup() { if (this.popupQueue.length === 0) { this.isShowing = false; return; } this.isShowing = true; const popup = this.popupQueue.shift(); // Get UIScene const uiScene = this.scene.scene.get('UIScene'); if (!uiScene) return; // Pause game if needed if (this.settings.pauseGameOnPopup) { this.scene.physics.pause(); } // Create popup container const centerX = uiScene.scale.width / 2; const centerY = uiScene.scale.height / 2; this.currentPopup = uiScene.add.container(centerX, centerY); this.currentPopup.setDepth(10000); // Always on top this.currentPopup.setScrollFactor(0); // Popup size based on type const width = popup.type === 'story' ? 600 : 500; const height = popup.type === 'story' ? 400 : 300; // Background overlay (darken screen) const overlay = uiScene.add.rectangle(0, 0, uiScene.scale.width * 2, uiScene.scale.height * 2, 0x000000, 0.7); overlay.setOrigin(0.5); this.currentPopup.add(overlay); // Main popup background const bg = uiScene.add.graphics(); // Color based on type let bgColor = 0x2a2a3e; let borderColor = 0x4e4e6e; if (popup.type === 'quest') { bgColor = 0x3a2a1e; borderColor = 0xFFD700; } else if (popup.type === 'warning') { bgColor = 0x3e2a2a; borderColor = 0xff4444; } else if (popup.type === 'success') { bgColor = 0x2a3e2a; borderColor = 0x44ff44; } else if (popup.type === 'story') { bgColor = 0x1a1a2e; borderColor = 0x8888ff; } // Draw background with rounded corners bg.fillStyle(bgColor, 0.95); bg.fillRoundedRect(-width / 2, -height / 2, width, height, 16); bg.lineStyle(4, borderColor, 1); bg.strokeRoundedRect(-width / 2, -height / 2, width, height, 16); this.currentPopup.add(bg); // Icon const iconText = uiScene.add.text(-width / 2 + 30, -height / 2 + 30, popup.icon, { fontSize: '48px' }); this.currentPopup.add(iconText); // Title const title = uiScene.add.text(0, -height / 2 + 50, popup.title, { fontSize: '28px', fontFamily: 'Arial', fill: '#ffffff', fontStyle: 'bold', align: 'center' }).setOrigin(0.5); this.currentPopup.add(title); // Separator line const separator = uiScene.add.graphics(); separator.lineStyle(2, borderColor, 0.5); separator.lineBetween(-width / 2 + 20, -height / 2 + 90, width / 2 - 20, -height / 2 + 90); this.currentPopup.add(separator); // Message const message = uiScene.add.text(0, -height / 2 + 150, popup.message, { fontSize: '18px', fontFamily: 'Arial', fill: '#dddddd', align: 'center', wordWrap: { width: width - 80 } }).setOrigin(0.5, 0); this.currentPopup.add(message); // Image (if provided) if (popup.image) { const img = uiScene.add.image(0, -height / 2 + 120, popup.image); img.setScale(0.5); this.currentPopup.add(img); } // Buttons const buttonY = height / 2 - 50; const buttonSpacing = 150; const buttonStartX = -(popup.buttons.length - 1) * buttonSpacing / 2; popup.buttons.forEach((btn, index) => { const btnX = buttonStartX + index * buttonSpacing; // Button background const btnBg = uiScene.add.graphics(); btnBg.fillStyle(0x4a4a6e, 1); btnBg.fillRoundedRect(btnX - 60, buttonY - 20, 120, 40, 8); btnBg.lineStyle(2, borderColor, 1); btnBg.strokeRoundedRect(btnX - 60, buttonY - 20, 120, 40, 8); btnBg.setInteractive( new Phaser.Geom.Rectangle(btnX - 60, buttonY - 20, 120, 40), Phaser.Geom.Rectangle.Contains ); // Hover effect btnBg.on('pointerover', () => { btnBg.clear(); btnBg.fillStyle(0x6a6a8e, 1); btnBg.fillRoundedRect(btnX - 60, buttonY - 20, 120, 40, 8); btnBg.lineStyle(2, borderColor, 1); btnBg.strokeRoundedRect(btnX - 60, buttonY - 20, 120, 40, 8); }); btnBg.on('pointerout', () => { btnBg.clear(); btnBg.fillStyle(0x4a4a6e, 1); btnBg.fillRoundedRect(btnX - 60, buttonY - 20, 120, 40, 8); btnBg.lineStyle(2, borderColor, 1); btnBg.strokeRoundedRect(btnX - 60, buttonY - 20, 120, 40, 8); }); // Click handler btnBg.on('pointerdown', () => { if (btn.action === 'close') { this.closePopup(popup); } else if (btn.callback) { btn.callback(); this.closePopup(popup); } }); this.currentPopup.add(btnBg); // Button text const btnText = uiScene.add.text(btnX, buttonY, btn.text, { fontSize: '18px', fontFamily: 'Arial', fill: '#ffffff', fontStyle: 'bold' }).setOrigin(0.5); this.currentPopup.add(btnText); }); // Auto-close timer if (popup.autoClose && this.settings.autoClose) { uiScene.time.delayedCall(this.settings.autoCloseDelay, () => { this.closePopup(popup); }); } // Play sound if (this.settings.soundOnPopup && this.scene.soundManager) { this.scene.soundManager.beepPickup(); } // Animate in this.currentPopup.setScale(0.8); this.currentPopup.setAlpha(0); uiScene.tweens.add({ targets: this.currentPopup, scale: 1, alpha: 1, duration: 300, ease: 'Back.easeOut' }); console.log(`📋 Popup shown: ${popup.title}`); } /** * Close current popup */ closePopup(popup) { if (!this.currentPopup) return; const uiScene = this.scene.scene.get('UIScene'); if (!uiScene) return; // Animate out uiScene.tweens.add({ targets: this.currentPopup, scale: 0.8, alpha: 0, duration: 200, ease: 'Power2', onComplete: () => { this.currentPopup.destroy(); this.currentPopup = null; // Resume game if (this.settings.pauseGameOnPopup) { this.scene.physics.resume(); } // Call onClose callback if (popup.onClose) { popup.onClose(); } // Show next popup this.displayNextPopup(); } }); } /** * Show quest popup */ showQuest(title, description, objectives) { this.showPopup({ title: title, message: description + '\n\nObjectives:\n' + objectives.map((obj, i) => `${i + 1}. ${obj}`).join('\n'), type: 'quest', icon: '📜', buttons: [ { text: 'Accept', action: 'close' }, { text: 'Decline', action: 'close' } ], autoClose: false }); } /** * Show story popup */ showStory(title, text, image = null) { this.showPopup({ title: title, message: text, type: 'story', icon: '📖', image: image, buttons: [{ text: 'Continue', action: 'close' }], autoClose: false }); } /** * Show notification */ showNotification(message, type = 'info') { const icons = { 'info': 'â„šī¸', 'success': '✅', 'warning': 'âš ī¸', 'error': '❌' }; this.showPopup({ title: type.charAt(0).toUpperCase() + type.slice(1), message: message, type: type, icon: icons[type] || 'â„šī¸', buttons: [{ text: 'OK', action: 'close' }], autoClose: true }); } /** * Save settings */ saveSettings() { localStorage.setItem('novafarma_popup_settings', JSON.stringify(this.settings)); } /** * Load settings */ loadSettings() { const saved = localStorage.getItem('novafarma_popup_settings'); if (saved) { this.settings = { ...this.settings, ...JSON.parse(saved) }; } } /** * Destroy system */ destroy() { if (this.currentPopup) { this.currentPopup.destroy(); } this.popupQueue = []; console.log('📋 Central Popup System destroyed'); } }