您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Displays rough extended combat info when actively fighting an enemy.
// ==UserScript== // @name TimeToKill // @namespace http://tampermonkey.net // @match https://melvoridle.com // @match https://melvoridle.com/* // @match https://www.melvoridle.com/* // @match https://test.melvoridle.com/* // @grant none // @version 1.1.1 // @author Gardens#3738 // @description Displays rough extended combat info when actively fighting an enemy. // ==/UserScript== // (() => { function effHp() { // return equippedFood.map(({ itemID, qty }) => (getFoodHealValue(itemID) || 0) * qty).reduce((a, b) => a + b) let foodID = equippedFood[currentCombatFood].itemID let foodQty = equippedFood[currentCombatFood].qty; if (foodQty == 0) return maxHitpoints; return equippedFood[currentCombatFood].qty * getFoodHealValue(foodID) + maxHitpoints; } window.effHp = effHp function enemyMaxHit() { if (damageReduction > 0) return Math.floor(combatData.enemy.maximumStrengthRoll * (1 - damageReduction / 100)); else return combatData.enemy.maximumStrengthRoll; } function enemyAccuracy() { let enemyAcc; let playerDefenceRoll; if (combatData.enemy.attackType === CONSTANTS.attackType.Melee) playerDefenceRoll = maximumDefenceRoll; else if (combatData.enemy.attackType === CONSTANTS.attackType.Ranged) playerDefenceRoll = maximumRangedDefenceRoll; else if (combatData.enemy.attackType === CONSTANTS.attackType.Magic) playerDefenceRoll = maximumMagicDefenceRoll; if (combatData.enemy.maximumAttackRoll < playerDefenceRoll) enemyAcc = ((0.5 * combatData.enemy.maximumAttackRoll) / playerDefenceRoll) * 100; else enemyAcc = (1 - (0.5 * playerDefenceRoll) / combatData.enemy.maximumAttackRoll) * 100; if (combatData.enemy.attackType === CONSTANTS.attackType.Melee && prayerBonusProtectFromMelee > 0) enemyAcc = 100 - protectFromValue; else if (combatData.enemy.attackType === CONSTANTS.attackType.Ranged && prayerBonusProtectFromRanged > 0) enemyAcc = 100 - protectFromValue; else if (combatData.enemy.attackType === CONSTANTS.attackType.Magic && prayerBonusProtectFromMagic > 0) enemyAcc = 100 - protectFromValue; return enemyAcc; } window.extended = true function chunkKills() { let respawnTimer = 3; let playerHp = extended ? effHp() : maxHitpoints; let playerAcc = (playerAccuracy / 100); let playerAttackTime = (playerAttackSpeed / 1000); let playerHitDamage = (baseMaxHit + 1) / 2; let regen = 1 + Math.floor(maxHitpoints / 10 / numberMultiplier) / (hitpointRegenInterval / 1000); let enemyHp = combatData.enemy.maxHitpoints; let enemyAcc = (enemyAccuracy() / 100); let enemyAttackTime = (combatData.enemy.attackSpeed / 1000); let enemyHitDamage = (enemyMaxHit() + 1) / 2; let playerAttackDamage = playerHitDamage * playerAcc; let playerHitsPerSec = playerAcc / playerAttackTime; let playerHitsToKill = Math.ceil(enemyHp / playerHitDamage); let playerAttacksToKill = playerHitsToKill / playerAcc; let playerAttacksToKill1 = Math.ceil(enemyHp / playerAttackDamage); let playerRawDps = playerHitDamage * playerHitsPerSec; let playerTimeToKill = playerAttacksToKill * playerAttackTime; let enemyAttackDamage = enemyHitDamage * enemyAcc; // - regen * enemyAttackTime; let enemyHitsPerSec = enemyAcc / enemyAttackTime; let enemyHitsToKill = Math.ceil(playerHp / enemyHitDamage); let enemyAttacksToKill = enemyHitsToKill / enemyHitsPerSec; let enemyAttacksToKill1 = Math.ceil(playerHp / enemyAttackDamage); let enemyRawDps = enemyHitDamage * enemyHitsPerSec; let enemyTimeToKill = enemyAttacksToKill * enemyAttackTime; // if (playerTimeToKill < enemyTimeToKill) { // console.log("winning fight") // } else { // console.log("losing fight") // } let combatDuration = playerTimeToKill + respawnTimer; let hpRegainedPerCombat = regen * combatDuration; let damageDealtPerSecond = enemyHp / combatDuration; let enemyAttacksPerCombat = playerTimeToKill / enemyAttackTime; let damageTakenPerCombat = enemyAttacksPerCombat * enemyAttackDamage - hpRegainedPerCombat; // - hpRegainedPerCombat; // console.log("player hp:", maxHitpoints, playerTimeToKill, "vs enemy ", enemyTimeToKill); // console.log("fightingDuration", fightingDuration); // simulate one combat vs one second of fighting let enemiesTillDeath = playerHp / damageTakenPerCombat; enemiesTillDeath = (enemiesTillDeath < 0) ? Infinity : enemiesTillDeath; let s = Math.round(enemiesTillDeath * combatDuration) let h = Math.floor(s / 3600) let m = Math.floor((s - h * 3600) / 60) s = s - 3600 * h - 60 * m // let timeString = ` h: ${h} m: ${m} s: ${s}`; let timeString = (enemiesTillDeath == Infinity) ? "Forever" : `${h}:${m}:${s}`; return { timeString, enemyHitDamage, enemyAcc, combatDuration, enemiesTillDeath, damageDealtPerSecond, damageTakenPerCombat, playerHitDamage, playerAttackDamage, playerHitsToKill, playerAttacksToKill, playerAttacksToKill1, playerTimeToKill, enemyHitsPerSec, enemyHitDamage, enemyAttackDamage, enemyHitsToKill, enemyAttacksToKill, enemyAttacksToKill1, } } window.chunkKills = chunkKills function dataRow(text, id) { let element = `<div class="col-8"> <h5 class="font-w400 font-size-sm text-combat-smoke m-1">${text}</h5> </div>` let number = `<div class="col-4"> <h5 id="${id}" class="font-w600 font-size-sm text-combat-smoke text-right m-1"></h5> </div>` return element + number } function injectChunkData() { if (document.getElementById("ttk") === null) { console.log("Injecting TTK data") let root = $("#combat-player-chance-to-hit").parent(); // let effHpElement = `<div class="col-8"> // <h5 class="font-w400 font-size-sm text-combat-smoke m-1">Effective HP:</h5> // </div>` // let effHpNumber = `<div class="col-4"> // <h5 id="effHp" class="font-w600 font-size-sm text-combat-smoke text-right m-1"></h5> // </div>` let effHpRow = dataRow("Effective HP:", "effHp"); let ttkElement = `<div class="col-8"> <h5 class="font-w400 font-size-sm text-combat-smoke m-1">Time to kill:</h5> </div>` let ttkNumber = `<div class="col-4"> <h5 id="ttk" class="font-w600 font-size-sm text-combat-smoke text-right m-1"></h5> </div>` let etdElement = `<div class="col-8"> <h5 class="font-w400 font-size-sm text-combat-smoke m-1">Enemies till dead:</h5> </div>` let etdNumber = `<div class="col-4"> <h5 id="etd" class="font-w600 font-size-sm text-combat-smoke text-right m-1"></h5> </div>` let ttdElement = `<div class="col-8"> <h5 class="font-w400 font-size-sm text-combat-smoke m-1">Time till dead:</h5> </div>` let ttdNumber = `<div class="col-4"> <h5 id="ttd" class="font-w600 font-size-sm text-combat-smoke text-right m-1"></h5> </div>` let ddpsElement = `<div class="col-8"> <h5 class="font-w400 font-size-sm text-combat-smoke m-1">Net DPS:</h5> </div>` let ddpsNumber = `<div class="col-4"> <h5 id="ddps" class="font-w600 font-size-sm text-combat-smoke text-right m-1"></h5> </div>` root.after(effHpRow, ttkElement, ttkNumber, etdElement, etdNumber, ttdElement, ttdNumber, ddpsElement, ddpsNumber); } } let refUpdateCombatInfoIcons = updateCombatInfoIcons; updateCombatInfoIcons = function() { refUpdateCombatInfoIcons() setTimeout(() => { let combatInfo = chunkKills() let enemiesTillDeath = Math.floor(combatInfo.enemiesTillDeath) let playerTimeToKill = Math.round(combatInfo.playerTimeToKill) let damageDealtPerSecond = Math.round(combatInfo.damageDealtPerSecond * 10) / 10 enemiesTillDeath = (enemiesTillDeath === Infinity) ? "inf" : enemiesTillDeath; injectChunkData(); $("#effHp").text(effHp()); $("#ttk").text(playerTimeToKill); $("#etd").text(enemiesTillDeath); $("#ddps").text(damageDealtPerSecond); $("#ttd").text(combatInfo.timeString); // let name = $("#combat-enemy-name").text() // $("#combat-enemy-name").text(name + " (" + playerTimeToKill + "s, " + enemiesTillDeath + "x)") }, 10) } // })()