您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Advanced Audio Alerts with EASY instructions and Functional Overlay
// ==UserScript== // @name IQRPG Audio Disco // @namespace https://www.iqrpg.com/ // @version 1.4.0 // @description Advanced Audio Alerts with EASY instructions and Functional Overlay // @author Grogu2484 // @match http://iqrpg.com/game.html // @match https://iqrpg.com/game.html // @match http://www.iqrpg.com/game.html // @match https://www.iqrpg.com/game.html // @require http://code.jquery.com/jquery-latest.js // @grant none // @license MIT // ==/UserScript== /************************************************************************************** * * * YOU MAY EDIT ANYTHING BELOW THIS LINE UNTIL NEXT BOX LIKE THIS !!! * * * **************************************************************************************/ // QUICK ACCESS CONTROLS // Quickly enable or disable specific game notification types var NOTIFICATIONS_ENABLED = { auto: true, // Auto timer notifications dungeon: true, // Dungeon completion notifications boss: true, // Boss fight notifications events: true, // Skill events notifications whispers: true, // Whisper notifications land: true, // Land timer notifications mastery: true, // Mastery milestone notifications effects: true, // Effect expiration notifications clan: true, // Clan-related notifications bonusExp: true // Bonus EXP notifications }; // SOUND PROFILE SELECTION // Choose from: "default", "subtle", "game", "natural", "custom" var SOUND_PROFILE = "default"; /* SOUND PROFILE DETAILS: ---------------------- - default: Original game sounds (recommended) - subtle: Quieter, less intrusive notifications - game: Video game-style voice alerts - natural: Nature-themed sound effects - custom: Use your own sound URLs (configure below) */ // CUSTOM SOUND PROFILE CONFIGURATION // ONLY USE IF ------> SOUND_PROFILE is set to "custom" var CUSTOM_SOUND_URLS = { auto: 'https://www.example.com/auto-sound.wav', boss: 'https://www.example.com/boss-sound.wav', bossDefeated: 'https://www.example.com/boss-defeated-sound.wav', event: 'https://www.example.com/event-sound.wav', whisper: 'https://www.example.com/whisper-sound.wav', land: 'https://www.example.com/land-sound.wav', mastery: 'https://www.example.com/mastery-sound.wav', effect: 'https://www.example.com/effect-sound.wav', watchtower: 'https://www.example.com/watchtower-sound.wav', bonusExp: 'https://www.example.com/bonus-exp-sound.wav' }; /* MAIN CONTROLS - QUICK TOGGLE Set to true --->ENABLES sounds, false<--- DISABLES sounds ----------------------------------------------- */ // MASTER TOGGLE - Set to false to disable ALL AUDIO(SOUND) notifications var MASTER_AUDIO_ENABLED = true; // MASTER TOGGLE - Set to false to disable ALL DESKTOP(Image) notifications var MASTER_DESKTOP_ENABLED = true; // VISUAL OVERLAY - Set to false to disable startup overlay var SHOW_STARTUP_OVERLAY = true; // VISUAL OVERLAY DURATION - How long to show the startup overlay (in seconds) var OVERLAY_DURATION = 5; /* VOLUME CONTROL -------------- Set the master volume for all sounds (Valid range: 0.0 to 1.0 (0 = silent, 1 = maximum volume)) */ var MASTER_VOLUME = 0.9; /* INDIVIDUAL NOTIFICATION SETTINGS ------------------------------- EDIT ALL THE SETTINGS BELOW! EACH SECTION CONTROLS A DIFFERENT TYPE OF NOTIFICATION SET AUDIO ALERTS TO LOWERCASE true TO ENABLE SOUNDS, SET TO LOWERCASE false TO DISABLE AUDIO ALERTS SET DESKTOP ALERTS TO LOWERCASE true TO ENABLE DESTOP NOTIFICATIONS, SET TO LOWERCASE false to DISABLE DESKTOP NOTIFICATIONS DEBUG IS THE LAST EDITABLE SECTION. THERE IS A BIG PAGE BREAK SO YOU DO NOT EDIT BELOW THAT LINE OR IT WILL NOT WORK.. */ // AUTO SECTION var autoAudioAlert = true; // Audio alert when autos are low var autoAlertSoundURL = 'https://www.myinstants.com/media/sounds/notification.mp3'; var autoAlertRepeatInSeconds = 10; // How often to repeat (1-60 seconds) var autoAlertNumber = 100; // Alert at this number of autos (1-100) var autoMaxNumberOfAudioAlerts = 0; // Maximum alerts (0 = unlimited) var autoDesktopAlert = false; // Desktop notification when autos are low // DUNGEON SECTION var dungeonAudioAlert = true; // Audio alert when dungeon completes var dungeonDesktopAlert = false; // Desktop notification for dungeon // BOSS SECTION var bossAudioAlert = true; // Audio alert for boss events var bossAlertSoundURL = 'https://www.myinstants.com/media/sounds/alert.mp3'; var bossDefeatedSoundURL = 'https://www.myinstants.com/media/sounds/ff-victory.mp3'; var bossDesktopAlert = false; // Desktop notification for boss events // EVENT SECTION var eventDesktopAlert = true; // Desktop notification for events var eventAlertSoundURL = 'https://www.myinstants.com/media/sounds/alert.mp3'; var eventAlert_Woodcutting = true; // Alert for woodcutting events var eventAlert_Quarrying = true; // Alert for quarrying events var eventAlert_Mining = true; // Alert for mining events var eventAudioAlert = true; // Audio alert when events start var eventAudioAlertFinished = false; // Audio alert when events finish // WHISPER SECTION var whisperAudioAlert = true; // Audio alert for whispers var whisperAlertSoundURL = 'https://www.myinstants.com/media/sounds/ping.mp3'; var whisperAlertOnlyWhenTabIsInactive = false; // Only alert when tab not active var whisperDesktopAlert = false; // Desktop notification for whispers // LAND SECTION var landAudioAlert = true; // Audio alert when land timer completes var landAlertSoundURL = 'https://www.myinstants.com/media/sounds/coins.mp3'; // MASTERY SECTION var masteryAudioAlert = true; // Audio alert for mastery milestones var masteryEveryXLevels = 10; // Alert every X levels (1-100) var masteryAlertSoundURL = 'https://www.myinstants.com/media/sounds/ff-victory.mp3'; // EFFECT SECTION var effectAudioAlert = true; // Audio alert when effects expire var effectAutoLeft = 5; // Alert at this many minutes (1-60) var effectAlertSoundURL = 'https://www.myinstants.com/media/sounds/hammer.mp3'; // CLAN SECTION var watchtowerAudioAlert = true; // Audio alert for watchtower events var watchtowerAlertSoundURL = 'https://www.myinstants.com/media/sounds/alert.mp3'; var watchtowerDesktopAlert = false; // Desktop notification for watchtower // BONUS EXP SECTION var bonusExpAudioAlert = true; // Audio alert for bonus exp var bonusExpAlertSoundURL = 'https://www.myinstants.com/media/sounds/magic.mp3'; // DEBUG SECTION var showDebugInfo = true; // Show debug info in console /************************************************************************************** * * * !! DO NOT EDIT ANYTHING BELOW THIS LINE !! * * * **************************************************************************************/ (function() { 'use strict'; // Additional configuration (managed by code) var NOTIFICATION_DURATION = 7; var LOW_RESOURCE_MODE = false; var enableVisualIndicators = true; var visualAlertColor = "#ff5555"; var visualAlertPulse = true; var visualAlertCorner = "top-right"; var enableErrorLogging = true; var statsTracking = false; // State variables let alerting = false; let alertInterval = null; let currentAutoAlerts = 0; let canSendDesktopAlert = true; let desktopNotificationCooldown = false; let bonusExpActive = false; let soundProfile = {}; let lastWhisperTime = 0; let visualAlertElement = null; let adaptedSelectors = {}; let notificationStats = { total: 0, auto: 0, dungeon: 0, boss: 0, event: 0, whisper: 0, land: 0, mastery: 0, effect: 0, clan: 0, bonusExp: 0 }; // Initialize sound profiles based on selected profile function initSoundProfiles() { // Default profile (updated more reliable sounds) const defaultProfile = { auto: autoAlertSoundURL || 'https://www.myinstants.com/media/sounds/notification.mp3', boss: bossAlertSoundURL || 'https://www.myinstants.com/media/sounds/alert.mp3', bossDefeated: bossDefeatedSoundURL || 'https://www.myinstants.com/media/sounds/ff-victory.mp3', event: eventAlertSoundURL || 'https://www.myinstants.com/media/sounds/alert.mp3', whisper: whisperAlertSoundURL || 'https://www.myinstants.com/media/sounds/ping.mp3', land: landAlertSoundURL || 'https://www.myinstants.com/media/sounds/coins.mp3', mastery: masteryAlertSoundURL || 'https://www.myinstants.com/media/sounds/ff-victory.mp3', effect: effectAlertSoundURL || 'https://www.myinstants.com/media/sounds/hammer.mp3', watchtower: watchtowerAlertSoundURL || 'https://www.myinstants.com/media/sounds/alert.mp3', bonusExp: bonusExpAlertSoundURL || 'https://www.myinstants.com/media/sounds/magic.mp3' }; // Set active profile based on user selection switch (SOUND_PROFILE.toLowerCase()) { case "custom": soundProfile = CUSTOM_SOUND_URLS; break; default: soundProfile = defaultProfile; } // Log sound profile for debugging if (showDebugInfo) { console.log("Active sound profile:", SOUND_PROFILE); console.log("Sound URLs:", soundProfile); } } // Play audio alert with the specified sound URL function playAudioAlert(soundURL, volume = MASTER_VOLUME) { if (!MASTER_AUDIO_ENABLED) return; try { console.log("Attempting to play sound:", soundURL); const audio = new Audio(soundURL); audio.volume = volume; // Handle autoplay policy issues const playPromise = audio.play(); if (playPromise !== undefined) { playPromise.then(() => { console.log("Sound playing successfully"); }).catch(error => { console.error("Sound play failed:", error); showVisualAlert("Browser blocked autoplay - click anywhere to enable", 3000); // Try playing on next user interaction document.addEventListener('click', function playOnClick() { audio.play(); document.removeEventListener('click', playOnClick); }, { once: true }); }); } if (statsTracking) { notificationStats.total++; } } catch (error) { console.error('Error creating audio object:', error); showVisualAlert("Failed to create audio", 2000); } } // Send desktop notification function sendDesktopNotification(title, message, icon = null, duration = NOTIFICATION_DURATION * 1000) { if (!MASTER_DESKTOP_ENABLED || !canSendDesktopAlert || desktopNotificationCooldown) return; if (!("Notification" in window)) { if (showDebugInfo) { console.log('Desktop notifications not supported in this browser'); } return; } if (Notification.permission === "denied") { if (showDebugInfo) { console.log('Desktop notifications permission denied'); } return; } if (Notification.permission !== "granted") { Notification.requestPermission().then(permission => { if (permission === "granted") { sendDesktopNotification(title, message, icon, duration); } }); return; } desktopNotificationCooldown = true; const options = { body: message, icon: icon || 'https://www.iqrpg.com/favicon.ico', silent: true }; const notification = new Notification(title, options); setTimeout(() => { notification.close(); desktopNotificationCooldown = false; }, duration); } // Display visual alert on screen function showVisualAlert(message, duration = 3000) { if (!enableVisualIndicators) return; console.log("Showing visual alert:", message); if (!visualAlertElement) { visualAlertElement = document.createElement('div'); visualAlertElement.id = 'iqrpg-audio-enhancer-alert'; const style = { position: 'fixed', padding: '10px 15px', backgroundColor: visualAlertColor, color: '#fff', fontWeight: 'bold', zIndex: '9999', borderRadius: '5px', boxShadow: '0 2px 10px rgba(0,0,0,0.2)', opacity: '0', transition: 'opacity 0.3s ease-in-out', top: '10px', right: '10px' }; Object.assign(visualAlertElement.style, style); if (visualAlertPulse) { visualAlertElement.style.animation = 'iqrpg-pulse 1s infinite'; const styleSheet = document.createElement('style'); styleSheet.textContent = ` @keyframes iqrpg-pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } `; document.head.appendChild(styleSheet); } document.body.appendChild(visualAlertElement); } visualAlertElement.textContent = message; visualAlertElement.style.opacity = '1'; setTimeout(() => { visualAlertElement.style.opacity = '0'; }, duration); } // Create and show startup overlay function showStartupOverlay() { if (!SHOW_STARTUP_OVERLAY) return; const overlay = document.createElement('div'); overlay.id = 'iqrpg-enhancer-overlay'; Object.assign(overlay.style, { position: 'fixed', top: '0', left: '0', width: '100%', height: '100%', backgroundColor: 'rgba(0, 0, 0, 0.8)', zIndex: '10000', display: 'flex', flexDirection: 'column', justifyContent: 'center', alignItems: 'center', transition: 'opacity 1s ease-in-out', opacity: '0' }); const header = document.createElement('div'); header.textContent = 'IQRPG AUDIO ENHANCER'; Object.assign(header.style, { color: '#fff', fontSize: '28px', fontWeight: 'bold', textAlign: 'center', marginBottom: '20px', fontFamily: 'Arial, sans-serif', textShadow: '0 0 10px #00ccff, 0 0 20px #00ccff' }); const status = document.createElement('div'); status.textContent = 'SUCCESSFULLY LOADED'; Object.assign(status.style, { color: '#00ff00', fontSize: '22px', fontWeight: 'bold', textAlign: 'center', marginBottom: '30px', fontFamily: 'Arial, sans-serif' }); const version = document.createElement('div'); version.textContent = 'Version 1.4.0 (Fixed)'; Object.assign(version.style, { color: '#aaaaaa', fontSize: '16px', textAlign: 'center', marginBottom: '30px', fontFamily: 'Arial, sans-serif' }); const closeButton = document.createElement('button'); closeButton.textContent = 'Close'; Object.assign(closeButton.style, { marginTop: '20px', padding: '8px 20px', backgroundColor: '#444', color: '#fff', border: 'none', borderRadius: '4px', cursor: 'pointer', fontSize: '14px', fontFamily: 'Arial, sans-serif' }); closeButton.addEventListener('click', () => { hideStartupOverlay(); }); overlay.appendChild(header); overlay.appendChild(status); overlay.appendChild(version); overlay.appendChild(closeButton); document.body.appendChild(overlay); setTimeout(() => { overlay.style.opacity = '1'; }, 100); setTimeout(() => { hideStartupOverlay(); }, OVERLAY_DURATION * 1000); } function hideStartupOverlay() { const overlay = document.getElementById('iqrpg-enhancer-overlay'); if (!overlay) return; overlay.style.opacity = '0'; setTimeout(() => { if (overlay.parentNode) { overlay.parentNode.removeChild(overlay); } }, 1000); } // Handle title change (for whispers and other notifications) function handleTitleChange() { const title = document.title; if (showDebugInfo) { console.log("Title changed:", title); } if (NOTIFICATIONS_ENABLED.whispers && title.includes('Whisper')) { handleWhisperNotification(); } if (NOTIFICATIONS_ENABLED.events && title.includes('Event')) { handleEventNotification(); } if (NOTIFICATIONS_ENABLED.bonusExp && title.includes('Bonus EXP')) { handleBonusExpNotification(); } } // Handle whisper notifications function handleWhisperNotification() { if (!whisperAudioAlert) return; console.log("Whisper notification triggered"); if (whisperAlertOnlyWhenTabIsInactive && document.visibilityState === 'visible') { console.log("Tab is active, skipping whisper alert"); return; } const now = Date.now(); if (now - lastWhisperTime < 3000) { console.log("Whisper alert on cooldown"); return; } lastWhisperTime = now; playAudioAlert(soundProfile.whisper); if (statsTracking) { notificationStats.whisper++; } if (whisperDesktopAlert) { sendDesktopNotification('IQRPG Whisper', 'You received a new whisper!'); } if (enableVisualIndicators) { showVisualAlert('New Whisper'); } } // Handle event notifications function handleEventNotification() { if (!eventAudioAlert) return; console.log("Event notification triggered"); const title = document.title; let eventType = 'Event'; if (title.includes('Woodcutting') && eventAlert_Woodcutting) { eventType = 'Woodcutting'; } else if (title.includes('Quarrying') && eventAlert_Quarrying) { eventType = 'Quarrying'; } else if (title.includes('Mining') && eventAlert_Mining) { eventType = 'Mining'; } playAudioAlert(soundProfile.event); if (statsTracking) { notificationStats.event++; } if (eventDesktopAlert) { sendDesktopNotification('IQRPG Event', `A ${eventType} event has started!`); } if (enableVisualIndicators) { showVisualAlert(`${eventType} Event Started`); } } // Handle bonus exp notifications function handleBonusExpNotification() { if (!bonusExpAudioAlert || bonusExpActive) return; console.log("Bonus EXP notification triggered"); bonusExpActive = true; playAudioAlert(soundProfile.bonusExp); if (statsTracking) { notificationStats.bonusExp++; } if (enableVisualIndicators) { showVisualAlert('Bonus EXP Active!'); } setTimeout(() => { bonusExpActive = false; }, 10000); } // Handle autos remaining change function handleAutosRemainingChange(count) { if (!NOTIFICATIONS_ENABLED.auto || !autoAudioAlert) return; const autosRemaining = typeof count === 'string' ? parseInt(count, 10) : count; if (showDebugInfo) { console.log(`Autos remaining: ${autosRemaining}`); } if (isNaN(autosRemaining) || autosRemaining > autoAlertNumber) { currentAutoAlerts = 0; if (alertInterval) { clearInterval(alertInterval); alertInterval = null; alerting = false; } return; } if (alerting) return; if (autoMaxNumberOfAudioAlerts > 0 && currentAutoAlerts >= autoMaxNumberOfAudioAlerts) { return; } alerting = true; console.log(`Auto alert triggered: ${autosRemaining} autos remaining`); playAudioAlert(soundProfile.auto); currentAutoAlerts++; if (statsTracking) { notificationStats.auto++; } if (autoDesktopAlert) { sendDesktopNotification('IQRPG Auto Alert', `Only ${autosRemaining} autos remaining!`); } if (enableVisualIndicators) { showVisualAlert(`${autosRemaining} Autos Left`); } if (autoAlertRepeatInSeconds > 0) { alertInterval = setInterval(() => { if (autoMaxNumberOfAudioAlerts > 0 && currentAutoAlerts >= autoMaxNumberOfAudioAlerts) { clearInterval(alertInterval); alertInterval = null; alerting = false; return; } playAudioAlert(soundProfile.auto); currentAutoAlerts++; if (statsTracking) { notificationStats.auto++; } }, autoAlertRepeatInSeconds * 1000); } else { alerting = false; } } // Setup observers for game elements function setupObservers() { console.log("Setting up observers..."); // Watch for title changes const titleObserver = new MutationObserver(handleTitleChange); const titleElement = document.querySelector('title'); if (titleElement) { titleObserver.observe(titleElement, { subtree: true, characterData: true, childList: true }); } // Watch for game content changes const gameObserver = new MutationObserver((mutations) => { mutations.forEach((mutation) => { // Look for auto counter changes if (mutation.target.id === 'autosRemaining' || mutation.target.className && mutation.target.className.includes('auto')) { const match = mutation.target.textContent.match(/(\d+)/); if (match) { handleAutosRemainingChange(parseInt(match[1], 10)); } } // Look for whisper messages in chat if (mutation.addedNodes.length > 0) { mutation.addedNodes.forEach(node => { if (node.nodeType === Node.ELEMENT_NODE) { const text = node.textContent || ''; if (text.toLowerCase().includes('whisper') || node.className && node.className.includes('whisper')) { handleWhisperNotification(); } } }); } }); }); // Start observing the entire game area gameObserver.observe(document.body, { childList: true, subtree: true, characterData: true, attributes: true }); console.log("Observers setup complete"); } // Add settings button to game UI function addSettingsButton() { try { console.log("Adding settings button..."); const settingsButton = document.createElement('div'); settingsButton.id = 'iqrpg-audio-enhancer-settings'; settingsButton.title = 'Toggle Audio Alerts'; Object.assign(settingsButton.style, { position: 'fixed', bottom: '20px', right: '20px', width: '40px', height: '40px', backgroundColor: '#333', borderRadius: '50%', cursor: 'pointer', zIndex: '9999', display: 'flex', justifyContent: 'center', alignItems: 'center', boxShadow: '0 2px 5px rgba(0,0,0,0.2)', border: '2px solid #555' }); settingsButton.innerHTML = ` <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2"> <polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon> <path d="M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07"></path> </svg> `; settingsButton.addEventListener('click', function() { MASTER_AUDIO_ENABLED = !MASTER_AUDIO_ENABLED; if (!MASTER_AUDIO_ENABLED) { this.innerHTML = ` <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#ff5555" stroke-width="2"> <polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon> <line x1="23" y1="9" x2="17" y2="15"></line> <line x1="17" y1="9" x2="23" y2="15"></line> </svg> `; this.style.borderColor = '#ff5555'; showVisualAlert('Audio Alerts Disabled', 2000); } else { this.innerHTML = ` <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2"> <polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon> <path d="M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07"></path> </svg> `; this.style.borderColor = '#555'; playAudioAlert(soundProfile.auto, 0.5); showVisualAlert('Audio Alerts Enabled', 2000); } console.log('Audio alerts:', MASTER_AUDIO_ENABLED ? 'enabled' : 'disabled'); }); document.body.appendChild(settingsButton); console.log('Settings button added'); } catch (error) { console.error('Error adding settings button:', error); } } // Simple whisper detection function setupSimpleWhisperDetection() { // Check for whispers in title every 500ms setInterval(() => { if (document.title.toLowerCase().includes('whisper')) { handleWhisperNotification(); } }, 500); // Check for common chat containers setInterval(() => { const chatContainers = document.querySelectorAll('[id*="chat"], [class*="chat"], [id*="message"], [class*="message"]'); chatContainers.forEach(container => { const messages = container.querySelectorAll('div, p, li, span'); messages.forEach(message => { const text = message.textContent.toLowerCase(); if (text.includes('whisper') || text.includes('whispers') || message.className && message.className.includes('whisper')) { handleWhisperNotification(); } }); }); }, 1000); } // Initialization function init() { console.log("IQRPG Audio Enhancer starting..."); try { // Initialize sound profiles initSoundProfiles(); // Set up observers setupObservers(); // Add settings button addSettingsButton(); // Show startup overlay showStartupOverlay(); // Set up simple whisper detection setupSimpleWhisperDetection(); // Show success message showVisualAlert('IQRPG Audio Enhancer activated!', 3000); console.log('IQRPG Audio Enhancer initialized!'); console.log('Active sound profile:', SOUND_PROFILE); console.log('Master volume:', MASTER_VOLUME); // Enable audio on first user interaction document.addEventListener('click', function enableAudio() { console.log("User interaction detected - audio enabled"); const silentAudio = new Audio("data:audio/mp3;base64,SUQzBAAAAAABEVRYWFgAAAAtAAADY29tbWVudABCaWdTb3VuZEJhbmsuY29tIC8gTGFTb25vdGhlcXVlLm9yZwBURU5DAAAAHQAAA1N3aXRjaCBQbHVzIMKpIE5DSCBTb2Z0d2FyZQBUSVQyAAAABgAAAzIyMzUAVFNTRQAAAA8AAANMYXZmNTcuODMuMTAwAAAAAAAAAAAAAAD/80DEAAAAA0gAAAAATEFNRTMuMTAwVVVVVVVVVVVVVUxBTUUzLjEwMFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVf/zQsRbAAADSAAAAABVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVf/zQMSkAAADSAAAAABVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV"); silentAudio.play().catch(e => console.log("Silent audio failed:", e)); document.removeEventListener('click', enableAudio); }, { once: true }); } catch (error) { console.error('IQRPG Audio Enhancer initialization error:', error); // Retry after 5 seconds setTimeout(() => { console.log('Retrying initialization...'); init(); }, 5000); } } // Wait for page to load if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { // Delay initialization to ensure game has loaded setTimeout(init, 1000); } })();