TimeToKill

Displays rough extended combat info when actively fighting an enemy.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

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

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

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

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

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

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

// })()