TimeToKill

Displays rough extended combat info when actively fighting an enemy.

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==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)
}

// })()