您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Provides some general additions to Elethor
当前为
// ==UserScript== // @name Elethor General Purpose // @description Provides some general additions to Elethor // @namespace https://www.elethor.com/ // @version 1.2.0 // @author Anders Morgan Larsen (Xortrox) // @match https://elethor.com/* // @match https://www.elethor.com/* // @run-at document-start // @grant none // ==/UserScript== (function() { const currentUserData = {}; const moduleName = 'Elethor General Purpose'; const version = '1.2.0' const playerHealthBarElementDefinition = '.progress.is-medium.is-danger'; const playerHealthBarTextElementDefinition = '.is-fight-health'; function getBattleHealthPercentage() { const playerHealth = document.querySelector(playerHealthBarElementDefinition); if (!playerHealth) { return 0; } return playerHealth.value / playerHealth.max * 100; } function highlightKills() { document.querySelectorAll('.has-combat-log>li').forEach((e) => { if (!e || !e.setAttribute || !e.innerText) { return; } if (e.innerText.includes('You killed')) { e.setAttribute('style', 'color:lime'); } else if (e.innerText.includes('The monster did')){ e.setAttribute('style', 'color:red'); } else { e.setAttribute('style', ''); } }); } function initializeUpdateBattleHealthPercentage() { if (window.elethorExtrasInterval) { clearInterval(window.elethorExtrasInterval); } window.elethorExtrasInterval = setInterval(() => { const playerHealthText = document.querySelector(playerHealthBarTextElementDefinition); const healthPercentage = getBattleHealthPercentage(); if (playerHealthText && healthPercentage && !isNaN(healthPercentage)) { let percentageDisplay; if (playerHealthText.children.length === 0) { percentageDisplay = document.createElement('span'); playerHealthText.appendChild(percentageDisplay); } else { percentageDisplay = playerHealthText.children[0]; } if (percentageDisplay) { percentageDisplay.innerText = ` (${healthPercentage.toFixed(3)}%)`; } } highlightKills(); }, 500); console.log(`[${moduleName} v${version}] Battle Percentage initialized.`); } function initializeToastKiller() { document.addEventListener('click', function(e) { if (e.target && e.target.className && e.target.className.includes && e.target.className.includes('toasted') ) { e.target.remove(); } }); console.log(`[${moduleName} v${version}] Toast Killer initialized.`); } function initializeXHRHook() { let rawSend = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.send = function() { if (!this._hooked) { this._hooked = true; this.addEventListener('readystatechange', function() { if (this.readyState === XMLHttpRequest.DONE) { setupHook(this); } }, false); } rawSend.apply(this, arguments); } function setupHook(xhr) { if (window.elethorGeneralPurposeOnXHR) { const e = new Event('EGPXHR'); e.xhr = xhr; window.elethorGeneralPurposeOnXHR.dispatchEvent(e); } } window.elethorGeneralPurposeOnXHR = new EventTarget(); console.log(`[${moduleName} v${version}] XHR Hook initialized.`); } function initializeUserLoadListener() { elethorGeneralPurposeOnXHR.addEventListener('EGPXHR', function (e) { if (e && e.xhr && e.xhr.responseURL && e.xhr.responseURL.endsWith && e.xhr.responseURL.endsWith('/game/user') ) { try { const userData = JSON.parse(e.xhr.responseText); console.log(`[${moduleName} v${version}] User Data hook:`, userData); if (userData) { for (const key of Object.keys(userData)) { currentUserData[key] = userData[key]; } console.log(`[${moduleName} v${version}] User Data loaded:`, currentUserData); } } catch (e) { console.log(`[${moduleName} v${version}] Error parsing userData:`, e); } } }); console.log(`[${moduleName} v${version}] User Load Listener initialized.`); } function initializeInventoryStatsLoadListener() { elethorGeneralPurposeOnXHR.addEventListener('EGPXHR', function (e) { if (e && e.xhr && e.xhr.responseURL && e.xhr.responseURL.endsWith && e.xhr.responseURL.endsWith('/game/inventory/stats') ) { setTimeout(() => { updateEquipmentPercentageSummary(); setTimeout(updateInventoryStatsPercentages, 1000); }); } }); console.log(`[${moduleName} v${version}] Inventory Stats Load Listener initialized.`); } function updateEquipmentPercentageSummary() { document.querySelector('.is-equipment>div>div').setAttribute('style', 'width: 50%') let percentagesTable = document.querySelector('#egpPercentagesSummary') if (!percentagesTable){ percentagesTable = document.querySelector('.is-equipment>div>div:nth-child(2)').cloneNode(true); percentagesTable.setAttribute('style', 'width: 25%'); percentagesTable.id='egpPercentagesSummary'; document.querySelector('.is-equipment>div').appendChild(percentagesTable); for (const child of percentagesTable.children[0].children) { if (child && child.children && child.children[0]) { child.children[0].remove(); } } document.querySelector('#egpPercentagesSummary>table>tr:nth-child(8)').setAttribute('style', 'height:43px'); } } function getStatSummary(equipment) { const summary = { base: {}, energizements: {} }; if (equipment) { for (const key of Object.keys(equipment)) { const item = equipment[key]; /** * Sums base attributes by name * */ if (item && item.attributes) { for (const attributeName of Object.keys(item.attributes)) { const attributeValue = item.attributes[attributeName]; if (!summary.base[attributeName]) { summary.base[attributeName] = 0; } summary.base[attributeName] += attributeValue; } } /** * Sums energizements by stat name * */ if (item && item.upgrade && item.upgrade.energizements) { for (const energizement of item.upgrade.energizements) { if (!summary.energizements[energizement.stat]) { summary.energizements[energizement.stat] = 0; } summary.energizements[energizement.stat] += Number(energizement.boost); } } } } return summary; } function updateInventoryStatsPercentages() { let percentagesTable = document.querySelector('#egpPercentagesSummary') if (percentagesTable && currentUserData && currentUserData.equipment){ const statSummary = getStatSummary(currentUserData.equipment); const baseKeys = Object.keys(statSummary.base); const energizementKeys = Object.keys(statSummary.energizements); let allKeys = baseKeys.concat(energizementKeys); const filterUniques = {}; for (const key of allKeys){ filterUniques[key] = true; } allKeys = Object.keys(filterUniques); allKeys.sort(); allKeys.push('actions'); const tableRows = percentagesTable.children[0].children; for(const row of tableRows) { if (row && row.children && row.children[0] && row.children[0].children[0] ) { const rowText = row.children[0].children[0]; rowText.innerText = ''; } } let rowIndex = 0; for (const key of allKeys) { if (key === 'puncture') { continue; } const row = tableRows[rowIndex]; if (row && row.children && row.children[0] && row.children[0].children[0] ) { const rowText = row.children[0].children[0]; const rowBase = statSummary.base[key] || 0; const rowEnergizement = (statSummary.energizements[key] || 0); const rowEnergizementPercentage = (statSummary.energizements[key] || 0) * 100; if (key.startsWith('+')) { rowText.innerText = `${key} per 10 levels: ${rowEnergizement}`; } else if (key === 'actions') { const actions = currentUserData.user.bonus_actions || 0; rowText.innerText = `Bonus Actions: ${actions}`; } else { rowText.innerText = `${key}: ${rowBase} (${rowEnergizementPercentage.toFixed(0)}%)`; } rowIndex++; } } } } (function run() { initializeUpdateBattleHealthPercentage(); initializeToastKiller(); initializeXHRHook(); initializeUserLoadListener(); initializeInventoryStatsLoadListener(); console.log(`[${moduleName} v${version}] Loaded.`); })(); (async function loadRerollDisableButtonModule() { async function waitForEcho() { return new Promise((resolve, reject) => { const interval = setInterval(() => { if (window.Echo) { clearInterval(interval); resolve(); } }, 100); }); } async function waitForUser() { return new Promise((resolve, reject) => { const interval = setInterval(() => { if (currentUserData.user && currentUserData.user.id !== undefined) { clearInterval(interval); resolve(); } }, 100); }); } await waitForEcho(); await waitForUser(); elethorGeneralPurposeOnXHR.addEventListener('EGPXHR', async function (e) { if (e && e.xhr && e.xhr.responseURL) { if(e.xhr.responseURL.includes('/game/energize')) { const itemID = e.xhr.responseURL.substr(e.xhr.responseURL.lastIndexOf('/')+1); window.lastEnergizeID = Number(itemID); } } }); function initializeDisableEnergizementButtonOnReroll() { const privateRoom = `App.User.${currentUserData.user.id}`; console.log(`[${moduleName} v${version}] Binding to private room ${privateRoom}`); window.Echo.private(privateRoom).listen(".App\\Domain\\Inventory\\Events\\UpdateItem", (data) => { if (data && data.item.id === window.lastEnergizeID){ enableEnergizementButton(); } }); document.addEventListener('click', function(e) { try { if (!e || !e.target || !e.target.parentElement || !e.target.className || !e.target.parentElement.className || !e.target.innerText || !e.target.innerText.includes ) { return; } if ((e.target.innerText.includes('Reroll Energizements') || e.target.innerText.includes('Costs 1 Standard Energizing Shard')) && (e.target.className.includes('button') || e.target.parentElement.className.includes('button')) ) { disableEnergizementButton(); } } catch (e) { console.warn(`[${moduleName} v${version}] Error during document click:`, e); } }); } initializeDisableEnergizementButtonOnReroll(); function disableEnergizementButton() { const button = getEnergizementButton(); if (!button) { return; } button.setAttribute('style', 'pointer-events: none'); button.setAttribute('disabled', 'true'); } function enableEnergizementButton() { const button = getEnergizementButton(); if (!button) { return; } button.removeAttribute('style'); button.removeAttribute('disabled'); } function getEnergizementButton() { let button; document.querySelectorAll('.buttons>.button.is-multiline.is-info>span:first-child').forEach((e) => { if (e && e.innerText && e.innerText === 'Reroll Energizements') { button = e.parentElement; } }); return button; } })(); })();