Melvor TimeRemaining

Shows time remaining for completing a task with your current resources. Takes into account Mastery Levels and other bonuses.

目前为 2020-04-17 提交的版本。查看 最新版本

// ==UserScript==
// @name         Melvor TimeRemaining
// @namespace    http://tampermonkey.net/
// @version      0.2.2
// @description  Shows time remaining for completing a task with your current resources. Takes into account Mastery Levels and other bonuses.
// @author       Breindahl#2660
// @match        https://*.melvoridle.com/*
// @grant        none
// ==/UserScript==

// Loading
console.log('Loading Breindahl TimeRemaining');

// Initialize audio for notification
function ding() {
	new Audio("https://www.myinstants.com/media/sounds/ding-sound-effect.mp3").play();
};

// Initialize message for notification
function notify(msg) {
	One.helpers('notify', {
		type: 'dark',
		from: 'bottom',
		align: 'center',
		message: msg
	});
};


// Create containers
document.getElementById("smith-item-have").outerHTML += "<br><small id =\"timeLeftSmithing\">"+""+"<small>";
document.getElementById("fletch-item-have").outerHTML += "<br><small id =\"timeLeftFletching\">"+"TEST"+"<small>";
document.getElementById("runecraft-item-have").outerHTML += "<br><small id =\"timeLeftRunecrafting\">"+"TEST"+"<small>";

//Funtion to get unformatted number for Qty
function getQtyUnformat(itemID) {
	let qty = 0;
	for (let i = 0; i < bank.length; i++) {
		if (bank[i].id === itemID) {
			qty += bank[i].qty;
		};
	};
	return qty;
};

// Convert seconds to hours/minutes/seconds
function secondsToHms(d) {
	d = Number(d);
	var h = Math.floor(d / 3600);
	var m = Math.floor(d % 3600 / 60);
	var s = Math.floor(d % 3600 % 60);
	var sDisplay = s > 0 ? s + (s == 1 ? " second" : " seconds") : "";
	var mDisplay = m > 0 ? m + (m == 1 ? " minute" : " minutes") + (s == "" ? "" : ", ") : "";
	var hDisplay = h > 0 ? h + (h == 1 ? " hour" : " hours") + ((s == "" && m == "") ? "" : ", ") : "";
	return hDisplay + mDisplay + sDisplay;
};

// Main function
function timeRemaining(item,currentSkill){
    //console.log("Current Skill is "+currentSkill);
    // Reset variable
    console.log("ItemID"+item);
	var itemCraft = [];
    var recordCraft = Infinity;
    var skillReq = [];
	var skillInterval = null;
	var masteryLim = [];
	var skillID = null;
	var chanceToKeep = []
	var skillMastery = null;
	var containerID = "";

	// Set current skill
	if (currentSkill == "Smithing") {
		//Set variables
		skillInterval = smithInterval;
		skillID = smithingItems[selectedSmith].smithingID;
		skillMastery = smithingMastery[skillID].masteryXP;
		containerID = "timeLeftSmithing";
		for (let i of items[item].smithReq) {
			skillReq.push(i);
		};
		//Set masteryLim for smithing
		masteryLim = [372,3102,22811,165505,Infinity]; //this array should contain the thresholds at which a new chanceToKeep comes into effect
		chanceToKeep = [0,0.1,0.2,0.3,0.4];
	};
	if (currentSkill == "Fletching") {
		//Set variables
		skillInterval = fletchInterval;
		//console.log("skillInterval: "+skillInterval);
		skillID = fletchingItems[selectedFletch].fletchingID;
		//console.log("skillID: "+skillID);
		skillMastery = fletchingMastery[skillID].masteryXP;
		//console.log("skillMastery: "+skillMastery);
		containerID = "timeLeftFletching";
		for (let i of items[item].fletchReq) {
			skillReq.push(i);
		};
		//if arrowshafts
		if (item == 276) {
			//console.log("arrow");
			if (selectedFletchLog === undefined) {selectedFletchLog = 0};
			//console.log("selectedFletchLog: "+selectedFletchLog);
			//console.log(skillReq[selectedFletchLog]);
			skillReq = [skillReq[selectedFletchLog]];
			//skillReq = [{id: selectedFletchLog, qty: 1}]
		};
		//console.log(skillReq);

		//Set masteryLim for fletching
		masteryLim = [6,14,23,32,42,54,66,80,96,113,132,152,175,200,228,259,293,331,372,418,468,524,585,653,728,810,902,1002,1113,1236,1371,1520,1685,1867,2067,2289,2534,2804,3102,3430,3794,4194,4637,5126,5665,6260,6917,7643,8444,9328,10305,11382,12572,13886,15336,16937,18705,20657,22811,25190,27817,30716,33917,37452,41354,45662,50419,55670,61468,67870,74938,82741,91356,100868,111370,122965,135766,149900,165505,182734,201757,222759,245947,271549,299816,331024,365481,403524,445527,491902,543104,599635,662051,730963,807048,891052,983800,1086202, Infinity]; //this array should contain the thresholds at which a new chanceToKeep comes into effect
		chanceToKeep = [0.0000,0.0025,0.0050,0.0075,0.0100,0.0125,0.0150,0.0175,0.0200,0.0225,0.0250,0.0275,0.0300,0.0325,0.0350,0.0375,0.0400,0.0425,0.0450,0.0475,0.0500,0.0525,0.0550,0.0575,0.0600,0.0625,0.0650,0.0675,0.0700,0.0725,0.0750,0.0775,0.0800,0.0825,0.0850,0.0875,0.0900,0.0925,0.0950,0.0975,0.1000,0.1025,0.1050,0.1075,0.1100,0.1125,0.1150,0.1175,0.1200,0.1225,0.1250,0.1275,0.1300,0.1325,0.1350,0.1375,0.1400,0.1425,0.1450,0.1475,0.1500,0.1525,0.1550,0.1575,0.1600,0.1625,0.1650,0.1675,0.1700,0.1725,0.1750,0.1775,0.1800,0.1825,0.1850,0.1875,0.1900,0.1925,0.1950,0.1975,0.2000,0.2025,0.2050,0.2075,0.2100,0.2125,0.2150,0.2175,0.2200,0.2225,0.2250,0.2275,0.2300,0.2325,0.2350,0.2375,0.2400,0.2425,0.2450];
	};
	if (currentSkill == "Runecrafting") {
		//Set variables
		skillInterval = runecraftInterval;
		skillID = runecraftingItems[selectedRunecraft].runecraftingID;
		skillMastery = runecraftingMastery[skillID].masteryXP;
		containerID = "timeLeftRunecrafting";
		for (let i of items[item].runecraftReq) {
			skillReq.push(i);
		};
		//Set masteryLim for fletching
		masteryLim = [Infinity]; //this array should contain the thresholds at which a new chanceToKeep comes into effect
		chanceToKeep = [0];
	};

    // Get Item Requirements and Current Requirements
	for (let i = 0; i < skillReq.length; i++) {
		var itemReq;
		//Check for Smithing Cape
		if (equippedItems[CONSTANTS.equipmentSlot.Cape] === CONSTANTS.item.Smithing_Skillcape && skillReq[i].id == 48) {
			itemReq = Math.floor(skillReq[i].qty / 2)
		} else  {
			itemReq = skillReq[i].qty;
		}
		//console.log("Items Required: "+itemReq);
		//Check for quantity
		var itemQty = getQtyUnformat(skillReq[i].id);
		//console.log("Items Quantity: "+itemQty);
		// Calculate max items you can craft for each itemReq
		itemCraft[i] = Math.floor(itemQty/itemReq);
		// Calculate limiting factor and set new record
		if(itemCraft[i] < recordCraft) {
			recordCraft = itemCraft[i];
		};
		//console.log("Record Craft: "+recordCraft);
	};

    //Return the chanceToKeep for any mastery EXP
    function masteryChance(masteryEXP){
        if (masteryEXP >= masteryLim[0]) {
			for (let i = 0; i < masteryLim.length; i++) {
				if (masteryLim[i] <= masteryEXP && masteryEXP < masteryLim[i+1]) {return chanceToKeep[i+1]}
			};
		} else {return chanceToKeep[0]}
    };

    function expectedTime(resources, resourcesPerAction, timePerAction, currentMastery, masteryLim){ //this function finds the required items to get expToLvl more exp, considering expPerItem and resource preservation due to mastery
 		//console.log("resources: "+resources);
		//console.log("resourcesPerAction: "+resourcesPerAction);
		//console.log("timePerAction: "+timePerAction);
		//console.log("currentMastery: "+currentMastery);
		//console.log("masteryLim: "+masteryLim);

		var expectedActions = Math.floor(resources/resourcesPerAction/(1-masteryChance(currentMastery))); //nr of actions if we do not reach new masteryLim
		//console.log("expectedActions "+expectedActions);
		var currentMastery_lim = masteryLim.find(element => element > currentMastery);  //this many actions can be taken until we reach a new mastery threshold
		//console.log("currentMastery_lim "+currentMastery_lim);
        var finalResult;
        var resourcesLeft
        if (expectedActions <= currentMastery_lim-currentMastery){
            finalResult = expectedActions
            resourcesLeft = 0
        } else {
            finalResult = (currentMastery_lim - currentMastery); //finalResult will be updated to keep track of actions
            resourcesLeft = (resources - finalResult*resourcesPerAction*(1-masteryChance(currentMastery))); //remaining resources after we reach new mastery level
        }
        currentMastery = currentMastery_lim; //prepare for loop
		//console.log("Starting Loop");
        while (Math.floor(resourcesLeft/resourcesPerAction) > 0) { //continue iterating through new chanceToKeep levels until we're out of resources
			currentMastery_lim = masteryLim.find(element => element > currentMastery); //nr of actions from next chanceToKeep
			//console.log("New currentMastery_lim "+currentMastery_lim);
            expectedActions = Math.floor(resourcesLeft/resourcesPerAction/(1-masteryChance(currentMastery))); //how many actions we can do with the remaining resources at the new mastery level
			//console.log("Remaining Resources "+expectedActions);
            if (expectedActions <= currentMastery_lim - currentMastery) { //if this is the final mastery level, add the nr of actions to finalResult and stop iterating
                finalResult += expectedActions;
                break
            } else { //if we will reach a new mastery level, set the new remainder and add the items required to reach the new mastery level to final_result
                resourcesLeft -= (currentMastery_lim-currentMastery)*(1-masteryChance(currentMastery));
                finalResult += currentMastery_lim-currentMastery;
            }
            currentMastery = currentMastery_lim;
        }
        return finalResult*timePerAction
    }

    window.timeLeftLast = window.timeLeftGlobal;

    //Calculate time
    var timeLeft = Math.floor(expectedTime(recordCraft,1,skillInterval/1000, skillMastery,masteryLim));
	console.log("timeLeft: "+timeLeft);
    window.timeLeftGlobal = timeLeft;

    //Inject HTML
    elementToChange = document.getElementById(containerID);
	if (timeLeft !== 0) {
		if(elementToChange !== null) {
			elementToChange.innerHTML = secondsToHms(timeLeft) + " remaining";
		};
	} else {
		if(elementToChange !== null) {
			elementToChange.innerHTML = secondsToHms(timeLeft) + "";
		};
	};
};

// ## SMITHING ##
var selectSmithRef = selectSmith;
window.selectSmith = function(smithingID) {
    selectSmithRef(smithingID);
    timeRemaining(smithingItems[selectedSmith].itemID,"Smithing");
	//console.log("ItemID: "+smithingItems[selectedSmith].itemID);
	//console.log("SmithingID: "+smithingItems[selectedSmith].smithingID);
};
var startSmithingRef = startSmithing;
window.startSmithing = function() {
    startSmithingRef(true);
    timeRemaining(smithingItems[selectedSmith].itemID,"Smithing");
    if (window.timeLeftLast > 1 && window.timeLeftGlobal == 0) {
        notify("Task Done");
        console.log('Task Done');
        ding();
    };
    //console.log('timeLeftLast'+window.timeLeftLast);
    //console.log('timeLeftGlobal'+window.timeLeftGlobal);
};

// ## FLETCHING ##
var selectFletchRef = selectFletch;
window.selectFletch = function(fletchingID, log, update = false) {
    selectFletchRef(fletchingID, log, update = false);
	timeRemaining(fletchingItems[selectedFletch].itemID,"Fletching");
	//console.log("ItemID: "+fletchingItems[selectedFletch].itemID);
	//console.log("FletchingID: "+fletchingItems[selectedFletch].fletchingID);
};
var startFletchingRef = startFletching;
window.startFletching = function() {
    startFletchingRef(true);
    timeRemaining(fletchingItems[selectedFletch].itemID,"Fletching");
    if (window.timeLeftLast > 1 && window.timeLeftGlobal == 0) {
        notify("Task Done");
        console.log('task done');
        ding();
    };
    //console.log('timeLeftLast'+window.timeLeftLast);
    //console.log('timeLeftGlobal'+window.timeLeftGlobal);
};

// ## RUNECRAFTING ##
var selectRunecraftRef = selectRunecraft;
window.selectRunecraft = function(runecraftingID, update = false) {
    selectRunecraftRef(runecraftingID, update = false);
    timeRemaining(runecraftingItems[selectedRunecraft].itemID,"Runecrafting");
	//console.log("ItemID: "+runecraftingItems[selectedRunecraft].itemID);
	//console.log("RunecraftingID: "+runecraftingItems[selectedRunecraft].runecraftingID);
};
var startRunecraftingRef = startRunecrafting;
window.startRunecrafting = function() {
    startRunecraftingRef(true);
    timeRemaining(runecraftingItems[selectedRunecraft].itemID,"Runecrafting");
    if (window.timeLeftLast > 1 && window.timeLeftGlobal == 0) {
        notify("Task Done");
        console.log('task done');
        ding();
    };
    //console.log('timeLeftLast'+window.timeLeftLast);
    //console.log('timeLeftGlobal'+window.timeLeftGlobal);
};

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址