您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Implements some extra information per finished fight in the battle view on pendoria.
// ==UserScript== // @name Pendoria - Chance to die // @description Implements some extra information per finished fight in the battle view on pendoria. // @namespace http://pendoria.net/ // @version 0.0.33 // @author Xortrox // @contributor Tester: euphone // @contributor Tester: fourkade // @contributor Coder: Kidel // @match http://pendoria.net/game // @match https://pendoria.net/game // @match http://www.pendoria.net/game // @match https://www.pendoria.net/game // @grant none // ==/UserScript== (function () { function showChanceToDie(data) { let playerHealth = $('#php-value')[0]; if (!playerHealth) { return console.log('playerHealth element was not found.'); } let fightDiv = $('#fight')[0]; if (!fightDiv) { return console.log('fightDiv element was not found.'); } let playerHPBackground = $('#php-background')[0]; if (!playerHPBackground) { return console.log('playerHPBackground element was not found.'); } function createHistoricallyLowestHealthTrackerIfNotExists() { let historicallyLowestHPTracker = $('#ctdInfoHistoriallyLowestDiv')[0]; if(!historicallyLowestHPTracker) { let infoDiv = document.createElement('div'); infoDiv.id = 'ctdInfoHistoriallyLowestDiv'; playerHPBackground.parentElement.prepend(infoDiv); } return historicallyLowestHPTracker; } function createInfoDivIfNotExists() { let ctdInfoDiv = $('#ctdInfoDiv')[0]; if (!ctdInfoDiv) { let infoDiv = document.createElement('div'); infoDiv.id = 'ctdInfoDiv'; fightDiv.parentElement.appendChild(infoDiv); } return ctdInfoDiv; } let enemyHitChanceFactor = data.monsterChanceToHit / 100.0; let playerMaxHealth = data.playerMaxLife; let enemyAverageDamage = data.damageTaken / data.hitsTaken; let enemyHitsToKill = Math.ceil(playerMaxHealth / enemyAverageDamage); let playerChanceFactorDeath = enemyHitChanceFactor ** enemyHitsToKill; let playerHitChanceFactor = data.playerChanceToHit / 100.0; let playerAverageDamage = data.damageDone / data.timesHit; let enemyMaxHealth = data.monsterMaxLife; let enemyMaxHealthWithChanceFactor = (enemyMaxHealth / playerHitChanceFactor); let playerHitsToKillEnemy = Math.ceil(enemyMaxHealthWithChanceFactor / playerAverageDamage); let playerHitsToKillEnemyNoChanceFactor = Math.ceil(enemyMaxHealth / playerAverageDamage); // console.log('enemyHitsToKill:', enemyHitsToKill); // console.log('playerHitChanceFactor:', playerHitChanceFactor); // console.log('(1 - (1 - playerHitChanceFactor) ** enemyHitsToKill) * 100'); // let playerWinChance = (1 - (1 - playerHitChanceFactor) ** playerHitsToKillEnemyNoChanceFactor) * 100 let enemyChanceFactorDeath = playerHitChanceFactor ** playerHitsToKillEnemy; let likelinessPrediction = ``; // TODO: Make this based on some amount of % within proximity of max healths and damages. if (playerHitsToKillEnemy < enemyHitsToKill) { likelinessPrediction += `It seems <b style="color:lightgreen">unlikely</b> that you will die as the enemy is required to hit you ${enemyHitsToKill} times, but you need to hit it roughly ${playerHitsToKillEnemy} times.<br> <br> `; } else if (playerHitsToKillEnemy >= enemyHitsToKill){ likelinessPrediction += `It seems <b style="color:red">likely</b> that you will die as the enemy needs to hit you ${enemyHitsToKill} times, but you need to hit it roughly ${playerHitsToKillEnemy} times.<br> <br> `; } let ctdInfoDiv = createInfoDivIfNotExists(); let diffHits = enemyHitsToKill - playerHitsToKillEnemy; if (ctdInfoDiv){ ctdInfoDiv.innerHTML = ` <div style="border-bottom: 1px solid white; margin-bottom: 3px;"> Chance to die<button id="ctdClearHistoricalTracker" style="padding-top: 0; padding-bottom: 0; height:21px; border: 1px solid white; background: transparent; border-radius: 0; float:right; line-height: 21px;">Reset lowest health tracker</button> </div> ${likelinessPrediction} You would die after <b style="color:red;">${enemyHitsToKill}</b>~ rounds of battle if the enemy is still alive.<br> You would win after <b style="color:lightgreen;">${playerHitsToKillEnemy}</b>~ rounds of battle.<br> <br> You have a chance of ${(((1 - playerHitChanceFactor) ** diffHits) * 100).toPrecision(3)}%~ to miss enough in order to receive ${enemyHitsToKill} hits from this enemy, which would kill you.<br> ` } /** * Bind click event of ctdClearHistoricalTracker * */ $('#ctdClearHistoricalTracker').click(() => { let pendCtdSettings = window.localStorage.getItem('PendoriaChanceToDie'); if (pendCtdSettings) { pendCtdSettings = JSON.parse(pendCtdSettings); } delete(pendCtdSettings.historiallyLowestHealth); localStorage.setItem('PendoriaChanceToDie', JSON.stringify(pendCtdSettings)); }); playerCurrentHealth = data.playerLife; if (playerCurrentHealth < 0) { playerCurrentHealth = 0; } // console.log('playerCurrentHealth:', playerCurrentHealth); let ctdInfoHistoriallyLowestDiv = createHistoricallyLowestHealthTrackerIfNotExists(); // TODO: Also show how many hits you took and for what average damage the hits were, in the tooltip if(ctdInfoHistoriallyLowestDiv) { let pendCtdSettings = window.localStorage.getItem('PendoriaChanceToDie'); if (!pendCtdSettings) { pendCtdSettings = { historiallyLowestHealth: playerCurrentHealth }; localStorage.setItem('PendoriaChanceToDie', JSON.stringify(pendCtdSettings)); } else { pendCtdSettings = JSON.parse(pendCtdSettings); if (pendCtdSettings.historiallyLowestHealth === undefined) { pendCtdSettings.historiallyLowestHealth = playerCurrentHealth localStorage.setItem('PendoriaChanceToDie', JSON.stringify(pendCtdSettings)); } } if (playerCurrentHealth < pendCtdSettings.historiallyLowestHealth) { pendCtdSettings.historiallyLowestHealth = playerCurrentHealth; localStorage.setItem('PendoriaChanceToDie', JSON.stringify(pendCtdSettings)) } let playerHealthPercentage = (pendCtdSettings.historiallyLowestHealth / playerMaxHealth * 100); /** * Only update qtip if the contents changed. **/ if (ctdInfoHistoriallyLowestDiv.innerText !== commarize(pendCtdSettings.historiallyLowestHealth)) { setTimeout(() => { $('#php-value').qtip({ style: { classes: 'qtip-dark' }, position: { target: $('#ctdInfoHistoriallyLowestDiv'), at: 'bottom left' }, content: { text: pendCtdSettings.historiallyLowestHealth, // title: 'Historically lowest health' } }); }) } ctdInfoHistoriallyLowestDiv.innerText = commarize(pendCtdSettings.historiallyLowestHealth); ctdInfoHistoriallyLowestDiv.style = ` z-index: 9999; position: absolute; background-color: #14723c; height: 25px; line-height: 26px; padding-left: 5px; border-radius: 10px; font-size: 12px; width: ${playerHealthPercentage}%; `; playerHealth.style.zIndex = '9999'; } } $(function () { function load() { if(window.socket) { socket.on('battle data', (data) => { showChanceToDie(data); }); } else { setTimeout(load, 500); } } load(); }); /** * Appends a suffix to the number and shortens it generally. * */ function commarize(number) { if(number < 999999) { return number; } var sizes = [ '', '', 'Mill', 'Bill', 'Trill', 'Quad', 'Quint', 'Sext', 'Sept', 'Oct' ]; if (number == 0) return '0 Byte'; var i = parseInt(Math.floor(Math.log(number) / Math.log(1000))); return (number / Math.pow(1000, i)).toPrecision(4) + ' ' + sizes[i]; } /** * Shows the full precision of a number up to 100 digits. * */ function fullZeroes(number) { return number.toFixed(100).replace(/.?0+$/,"") // 0.0000005 } /** * Takes a number string * */ function fourLastDigits(numberString) { let index = 0; let theValAfterDot = numberString.substr(numberString.indexOf('.') + 1); while(theValAfterDot[index] === '0'){ index++; } return '0.' + theValAfterDot.substr(0, index + 3) } }());
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址