Idle Pixel Audio Alerts

Audio Alerts for DHP

当前为 2023-12-18 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Idle Pixel Audio Alerts
// @namespace    http://tampermonkey.net/
// @version      1.0.1
// @description  Audio Alerts for DHP
// @author       Felipe Dounford
// @require      https://greasyfork.org/scripts/461221-hack-timer-js-by-turuslan/code/Hack%20Timerjs%20By%20Turuslan.js?version=1159560
// @require      https://greasyfork.org/scripts/441206-idlepixel/code/IdlePixel+.js
// @match        *://idle-pixel.com/login/play*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=greasyfork.org
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

	//Change ding url to set default sound
	let ding = 'https://raw.githubusercontent.com/Dounford-Felipe/Audio-Alerts/main/ding.wav'
	//Change defaultText to set default TTS Text
	let defaultText = 'Ready'
	let alerts = [];
	window.muteAllAlerts = false;
	window.alertVolume = 1;
	window.alertVoices = [];
	window.alertVoice = '';

    class AlertsPlugin extends IdlePixelPlusPlugin {
        constructor() {
            super("alerts", {
                about: {
                    name: GM_info.script.name + " (ver: " + GM_info.script.version + ")",
                    version: GM_info.script.version,
                    author: GM_info.script.author,
                    description: GM_info.script.description
                }
            });
        }
 
        onLogin() {
			IdlePixelPlus.plugins.alerts.addUI()
			IdlePixelPlus.plugins.alerts.loadAlerts()
			speechSynthesis.onvoiceschanged = function () {
				IdlePixelPlus.plugins.alerts.getVoices()
			}
			const alertLoopInterval = setInterval(function(){
				IdlePixelPlus.plugins.alerts.newValue()
				IdlePixelPlus.plugins.alerts.alertLoop()
			}, 1000);
        }
    
		//Gets the tts voices, populate the select with them and set the current voice
		getVoices() {
			alertVoices = speechSynthesis.getVoices();
			const voiceSelect = document.getElementById('ttsVoices');
			alertVoices.forEach((voice, index) => {
				const option = document.createElement('option');
				option.value = index;
				option.textContent = voice.name;
				voiceSelect.appendChild(option);
			});
			// Set the current voice based on the value stored in localStorage or use the first voice
			alertVoice = localStorage.getItem('audioAlertsVoice') ? alertVoices[localStorage.getItem('audioAlertsVoice')] : alertVoices[0]
			document.getElementById('ttsVoices').value = localStorage.getItem('audioAlertsVoice') ? localStorage.getItem('audioAlertsVoice') : 0
		}

		//Adds the table and Style
		addUI() {
			let alertTable = `<table border="1" cellpadding="1" cellspacing="1" style="text-align: center;color: white;font-weight: bold;text-shadow: 1px 1px black;">
				<thead>
					<tr>
						<th style="width: 30%;">Variable</th>
						<th style="width: 10%;" colspan="2">Trigger</th>
						<th style="width: 10%;">Current Value</th>
						<th style="width: 10%;">Sound Type</th>
						<th style="width: 20%;">Option</th>
						<th style="width: 10%;">Enabled</th>
						<th></th>
					</tr>
				</thead>
				<tbody id="alertsBody">
				</tbody>
				<tfoot>
					<tr id="alertsFooter">
						<td colspan="3">
							<select id="ttsVoices" onchange="alertVoice = alertVoices[this.value]" style="width:100%"></select>
						</td>
						<td colspan="2">
							<input type="checkbox" onclick="muteAllAlerts = !muteAllAlerts" style="margin-right: 10px;"> Mute ALL
						</td>
						<td>
							<input type="range" min="1" max="100" value="100" id="alertVolume" onchange="alertVolume = this.value"> Volume
						</td>
						<td>
							<button onclick="IdlePixelPlus.plugins.alerts.saveAlerts()">Save</button>
						</td>
						<td>
							<button onclick="IdlePixelPlus.plugins.alerts.addAlert()">ADD</button>
						</td>
					</tr>
				</tfoot>
			</table>`
			IdlePixelPlus.addPanel("audioAlerts", "Audio Alerts", alertTable);
			
			let alertButton = `<div onclick="IdlePixelPlus.setPanel('audioAlerts')" class="hover hover-menu-bar-item left-menu-item">
				<table class="game-menu-bar-left-table-btn left-menu-item-other" style="width: 100%;">
					<tbody>
						<tr>
							<td style="width: 30px;"><img id="menu-bar-idlepixelplus-icon" src="https://dhm.idle-pixel.com/images/soundOn.png" class="w20" title="alerts"></td>
							<td>AUDIO ALERTS</td>
						</tr>
					</tbody>
				</table>
			</div>`
			$('#menu-bar-buttons').append(alertButton)
		}

		//Adds new alert row and a new key to alerts array
		addAlert = function() {
			let alertRows = document.getElementById('alertsBody').getElementsByTagName("tr")
			let totalAlerts = alertRows.length
			let alertRow = document.createElement('tr')
			alertRow.id = `alert${totalAlerts+1}`
			alertRow.innerHTML = `<td>
						<input placeholder="Variable Name" id="variableName${totalAlerts+1}" style="width:100%">
					</td>
					<td>
						<select id="variableType${totalAlerts+1}">
							<option value="lt">&lt;</option>
							<option value="le">&le;</option>
							<option value="gt">&gt;</option>
							<option value="ge">&ge;</option>
							<option value="eq">&equals;</option>
							<option value="ne">&ne;</option>
						</select>
					</td>
					<td>
						<input placeholder="Value to Trigger" type="number" id="wantedValue${totalAlerts+1}">
					</td>
					<td><span id="variableValue"></span></td>
					<td>
						<select id="audioType${totalAlerts+1}">
							<option value="audio" selected="">Audio File</option>
							<option value="tts">Text To Speech</option>
							<option value="eval">Eval (Advanced Users Only!)</option>
						</select>
					</td>
					<td>
						<input placeholder="Text to Speech or sound URL" id="soundOption${totalAlerts+1}">
					</td>
					<td>
						<input type="checkbox" id="enabled${totalAlerts+1}">
					</td>
					<td style="padding-right: 6px;">
						<button onclick="IdlePixelPlus.plugins.alerts.removeAlert(this.parentNode.parentNode)">Delete</button>
					</td>`
			document.getElementById('alertsBody').append(alertRow)
			alerts[totalAlerts] = {type:'lt',variableName:'',wantedValue:'',soundType:'audio',sound:ding,enabled:false,triggered:false}
		}

		//Remove alert row and the array key, also changes the id of the remaining rows
		removeAlert = function(row) {
			let id = row.id.slice(5)
			alerts.splice(id-1,1)
			row.remove()
			let alertRows = document.getElementById('alertsBody').getElementsByTagName("tr")
			// Update remaining row IDs
			for (let i = 0; i < alertRows.length; i++) {alertRows[i].id = `alert${i+1}`}
			// Add a new alert if there are no rows remaining
			if (alertRows.length == 0) {IdlePixelPlus.plugins.alerts.addAlert()}
		}

		//Save the alerts, also sets the alerts, volume and current voice on localStorage
		saveAlerts = function() {
			let alertRows = document.getElementById('alertsBody').getElementsByTagName("tr")
			for (let i = 0; i < alertRows.length; i++) {
				alerts[i].type = alertRows[i].getElementsByTagName('select')[0].value
				alerts[i].variableName = 'var_' + alertRows[i].getElementsByTagName('input')[0].value
				alerts[i].wantedValue = alertRows[i].getElementsByTagName('input')[1].value
				alerts[i].soundType = alertRows[i].getElementsByTagName('select')[1].value
				alerts[i].sound = alertRows[i].getElementsByTagName('input')[2].value == '' ? ding : alertRows[i].getElementsByTagName('input')[2].value
				alerts[i].enabled = alertRows[i].getElementsByTagName("input")[3].checked
				alerts[i].triggered = false
			}
			let key = `audioAlerts`;
			localStorage.setItem(key, JSON.stringify(alerts));
			localStorage.setItem('audioAlertsVolume', alertVolume);
			let voiceIndex = document.getElementById('ttsVoices').value
			localStorage.setItem('audioAlertsVoice', voiceIndex);
		}

		//Loads both volume and alerts from the localStorage
		loadAlerts() {
			let key = `audioAlerts`;
			let audioAlerts = localStorage.getItem(key);
			if (audioAlerts) {
				audioAlerts = JSON.parse(audioAlerts);
				let alertRows = document.getElementById('alertsBody').getElementsByTagName("tr")
				for (let i = 0; i < audioAlerts.length; i++) {
					IdlePixelPlus.plugins.alerts.addAlert()
					alertRows[i].getElementsByTagName('select')[0].value = audioAlerts[i].type
					alertRows[i].getElementsByTagName('input')[0].value = audioAlerts[i].variableName.slice(4)
					alertRows[i].getElementsByTagName('input')[1].value = audioAlerts[i].wantedValue
					alertRows[i].getElementsByTagName('select')[1].value = audioAlerts[i].soundType
					alertRows[i].getElementsByTagName('input')[3].checked = audioAlerts[i].enabled
					alertRows[i].getElementsByTagName('input')[2].value = audioAlerts[i].sound == ding ? '' : audioAlerts[i].sound;
				}
				alerts = audioAlerts;
			} else {IdlePixelPlus.plugins.alerts.addAlert()}
			alertVolume = localStorage.getItem('audioAlertsVolume') ? localStorage.getItem('audioAlertsVolume') : 100;
			document.getElementById('alertVolume').value = alertVolume
		}

		//Displays the current value of the alert variables
		newValue() {
			let alertRows = document.getElementById('alertsBody').getElementsByTagName("tr")
			for (let i = 0; i < alertRows.length; i++) {
				alertRows[i].getElementsByTagName('span')[0].innerText = window[alerts[i].variableName] == undefined ? '' : window[alerts[i].variableName]
			}
		}

		//This is were the alert happen
		alertLoop() {
			for (let i = 0; i < alerts.length; i++) {
				if (alerts[i].enabled) {
					let type = alerts[i].type
					let triggered = 0
					switch(type) {
						case "lt": {
							triggered =  window[alerts[i].variableName] < alerts[i].wantedValue ? 1 : 0
							break;
						}
						case "le": {
							triggered =  window[alerts[i].variableName] <= alerts[i].wantedValue ? 1 : 0
							break;
						}
						case "gt": {
							triggered =  window[alerts[i].variableName] > alerts[i].wantedValue ? 1 : 0
							break;
						}
						case "ge": {
							triggered =  window[alerts[i].variableName] >= alerts[i].wantedValue ? 1 : 0
							break;
						}
						case "eq": {
							triggered =  window[alerts[i].variableName] == alerts[i].wantedValue ? 1 : 0
							break;
						}
						case "ne": {
							triggered =  window[alerts[i].variableName] != alerts[i].wantedValue && typeof window[alerts[i].variableName] != 'undefined' ? 1 : 0
							break;
						}
					}
					if (triggered == 1 && alerts[i].triggered == false) {
						alerts[i].triggered = true
						if (muteAllAlerts != true) {
							if(alerts[i].soundType == "audio") {
								let sound = new Audio(alerts[i].sound)
								sound = isNaN(sound.duration) ? new Audio(ding) : sound
								sound.volume = alertVolume / 100
								sound.play()
							} else if (alerts[i].soundType == "tts") {
								const message = new SpeechSynthesisUtterance();
								message.text = alerts[i].sound == ding ? defaultText : alerts[i].sound
								message.voice = alertVoice
								message.volume = alertVolume / 100
								window.speechSynthesis.speak(message);
							} else if (alerts[i].soundType == "eval") {// Remove from here
								let command = alerts[i].sound == 'https://raw.githubusercontent.com/Dounford-Felipe/Audio-Alerts/main/ding.wav' ? `console.log('You need to set ' + alerts[i].variableName + ' command')` : alerts[i].sound
								eval(command) // To here if you don't want eval
							}
						}
					} 
					if (triggered == 0) {
						alerts[i].triggered = false
					}
				}
			}
		}
	
	}
 
    const plugin = new AlertsPlugin();
    IdlePixelPlus.registerPlugin(plugin);
 
})();