Melvor CB only completion log

Completion log for combat only restricted accounts

目前为 2020-08-20 提交的版本。查看 最新版本

// ==UserScript==
// @name         Melvor CB only completion log
// @version      1.3.2
// @description  Completion log for combat only restricted accounts
// @author       8992
// @match        https://*.melvoridle.com/*
// @grant        none
// @namespace    http://tampermonkey.net/
// @noframes
// ==/UserScript==
var skills = [0, 1, 2, 3, 4, 5, 10, 13, 14, 15, 19];
setTimeout(() => {
  for (let i = 0; i < skillLevel.length; i++) {
    if(skills.includes(i) && skillLevel[i] > 1) {
      console.log("Combat only completion log aborted loading due to account type");
      return;
    }
  }
  window.combatPets = [12,13,14,15,16,17,18,19,20];
  window.combatItems = [
    { id: CONSTANTS.item.Attack_Skillcape, name: items[CONSTANTS.item.Attack_Skillcape].name, sources: ["Shop"] },
    { id: CONSTANTS.item.Strength_Skillcape, name: items[CONSTANTS.item.Strength_Skillcape].name, sources: ["Shop"] },
    { id: CONSTANTS.item.Defence_Skillcape, name: items[CONSTANTS.item.Defence_Skillcape].name, sources: ["Shop"] },
    { id: CONSTANTS.item.Hitpoints_Skillcape, name: items[CONSTANTS.item.Hitpoints_Skillcape].name, sources: ["Shop"] },
    { id: CONSTANTS.item.Ranged_Skillcape, name: items[CONSTANTS.item.Ranged_Skillcape].name, sources: ["Shop"] },
    { id: CONSTANTS.item.Magic_Skillcape, name: items[CONSTANTS.item.Magic_Skillcape].name, sources: ["Shop"] },
    { id: CONSTANTS.item.Prayer_Skillcape, name: items[CONSTANTS.item.Prayer_Skillcape].name, sources: ["Shop"] },
    { id: CONSTANTS.item.Slayer_Skillcape, name: items[CONSTANTS.item.Slayer_Skillcape].name, sources: ["Shop"] },
    { id: CONSTANTS.item.Red_Party_Hat, name: items[CONSTANTS.item.Red_Party_Hat].name, sources: ["Shop"] },
    { id: CONSTANTS.item.Amulet_of_Calculated_Promotion, name: items[CONSTANTS.item.Amulet_of_Calculated_Promotion].name, sources: ["Leech"] },
    { id: CONSTANTS.item.Fire_Cape, name: items[CONSTANTS.item.Fire_Cape].name, sources: ["Malcs, the Guardian of Melvor"] },
    { id: CONSTANTS.item.Bowstring, name: items[CONSTANTS.item.Bowstring].name, sources: ["Shop"] },
    { id: CONSTANTS.item.Eight, name: items[CONSTANTS.item.Eight].name, sources: ["Easter egg"] },
    { id: CONSTANTS.item.Lemon, name: items[CONSTANTS.item.Lemon].name, sources: ["Easter egg"] },
    { id: CONSTANTS.item.Signet_Ring_Half_B, name: items[CONSTANTS.item.Signet_Ring_Half_B].name, sources: ["Any monster"] },
  ];
  for (let i = 0; i < slayerItems.length; i++) combatItems.push({ id: slayerItems[i], name: items[slayerItems[i]].name, sources: ["Shop"] });
  for (let i = 0; i < gloveID.length; i++) combatItems.push({ id: gloveID[i], name: items[gloveID[i]].name, sources: ["Shop"] });
  for (let k = 0; k < MONSTERS.length; k++) { //monster loot
    if (typeof MONSTERS[k].bones == "number") {
      let found = combatItems.findIndex((x) => x.id == MONSTERS[k].bones);
      found >= 0
        ? combatItems[found].sources.push(MONSTERS[k].name)
        : combatItems.push({
            id: MONSTERS[k].bones,
            name: items[MONSTERS[k].bones].name,
            sources: [MONSTERS[k].name],
          });
    }
    if (MONSTERS[k].lootTable !== undefined) {
      for (let j = 0; j < MONSTERS[k].lootTable.length; j++) {
        let found = combatItems.findIndex((x) => x.id == MONSTERS[k].lootTable[j][0]);
        found >= 0
          ? combatItems[found].sources.push(MONSTERS[k].name)
          : combatItems.push({
              id: MONSTERS[k].lootTable[j][0],
              name: items[MONSTERS[k].lootTable[j][0]].name,
              sources: [MONSTERS[k].name],
            });
      }
    }
  }
  for (let k = 0; k < combatItems.length; k++) {  //upgrades 1
    if (items[combatItems[k].id].trimmedItemID) {
      potentialUpgrade = [];
      for (let j = 0; j < items[items[combatItems[k].id].trimmedItemID].itemsRequired.length; j++) {
        let found = combatItems.findIndex((x) => x.id == items[items[combatItems[k].id].trimmedItemID].itemsRequired[j][0]);
        found >= 0 ? potentialUpgrade.push(true) : potentialUpgrade.push(false);
      }
      if (!potentialUpgrade.includes(false)) {
        let found = combatItems.findIndex((x) => x.id == items[combatItems[k].id].trimmedItemID);
        if (found >= 0) {
          for (let n = 0; n < combatItems[k].sources.length; n++) {
            if (combatItems[found].sources.findIndex((x) => x == combatItems[k].sources[n]) == -1)
              combatItems[found].sources.push(combatItems[k].sources[n]);
          }
        } else {
          combatItems.push({
            id: items[combatItems[k].id].trimmedItemID,
            name: items[items[combatItems[k].id].trimmedItemID].name,
            sources: [],
          });
          for (let m = 0; m < combatItems[k].sources.length; m++) {
            combatItems[combatItems.length - 1].sources.push(combatItems[k].sources[m]);
          }
        }
      }
    }
  }
  for (let k = 0; k < combatItems.length; k++) {  //chest loot
    if (items[combatItems[k].id].dropTable !== undefined) {
      for (let j = 0; j < items[combatItems[k].id].dropTable.length; j++) {
        let found = combatItems.findIndex((x) => x.id == items[combatItems[k].id].dropTable[j][0]);
        if (found >= 0) {
          for (let i = 0; i < combatItems[k].sources.length; i++) {
            if (combatItems[found].sources.findIndex((x) => x == combatItems[k].sources[i]) == -1)
              combatItems[found].sources.push(combatItems[k].sources[i]);
          }
        } else {
          combatItems.push({
            id: items[combatItems[k].id].dropTable[j][0],
            name: items[items[combatItems[k].id].dropTable[j][0]].name,
            sources: [],
          });
          for (let m = 0; m < combatItems[k].sources.length; m++) {
            combatItems[combatItems.length - 1].sources.push(combatItems[k].sources[m]);
          }
        }
      }
    }
  }
  for (let k = 0; k < combatItems.length; k++) {  //upgrades 2
    if (items[combatItems[k].id].trimmedItemID) {
      potentialUpgrade = [];
      for (let j = 0; j < items[items[combatItems[k].id].trimmedItemID].itemsRequired.length; j++) {
        let found = combatItems.findIndex((x) => x.id == items[items[combatItems[k].id].trimmedItemID].itemsRequired[j][0]);
        found >= 0 ? potentialUpgrade.push(true) : potentialUpgrade.push(false);
      }
      if (!potentialUpgrade.includes(false)) {
        let found = combatItems.findIndex((x) => x.id == items[combatItems[k].id].trimmedItemID);
        if (found >= 0) {
          for (let n = 0; n < combatItems[k].sources.length; n++) {
            if (combatItems[found].sources.findIndex((x) => x == combatItems[k].sources[n]) == -1)
              combatItems[found].sources.push(combatItems[k].sources[n]);
          }
        } else {
          combatItems.push({
            id: items[combatItems[k].id].trimmedItemID,
            name: items[items[combatItems[k].id].trimmedItemID].name,
            sources: [],
          });
          for (let m = 0; m < combatItems[k].sources.length; m++) {
            combatItems[combatItems.length - 1].sources.push(combatItems[k].sources[m]);
          }
        }
      }
    }
  }
  combatItems.sort(function(a, b){return a.id - b.id}); //sorts smallest to largest id

  window.updateCompletionLog = function() {
    let skills = 8 * 99;
    let skillsTotal =
      skillLevel[CONSTANTS.skill.Attack] +
      skillLevel[CONSTANTS.skill.Strength] +
      skillLevel[CONSTANTS.skill.Defence] +
      skillLevel[CONSTANTS.skill.Hitpoints] +
      skillLevel[CONSTANTS.skill.Ranged] +
      skillLevel[CONSTANTS.skill.Magic] +
      skillLevel[CONSTANTS.skill.Prayer] +
      skillLevel[CONSTANTS.skill.Slayer];
    let itemsTotal = combatItems.length;
    let itemsFound = 0;
    let monstersKilled = 0;
    let pets = 0;
    let petsPercentage = 0;
    //skill level
    let skillsPercentage = (skillsTotal / skills) * 100;
    //items
    for (let i = 0; i < combatItems.length; i++) {
      if (itemStats[combatItems[i].id].timesFound > 0) itemsFound++;
    }
    let itemsPercentage = (itemsFound / itemsTotal) * 100;
    //monsters
    for (let i = 0; i < monsterStats.length; i++) {
      if (monsterStats[i].killedByPlayer > 0) monstersKilled++;
    }
    let monstersPercentage = (monstersKilled / MONSTERS.length) * 100;
    //pets
    for (let i = 0; i < petUnlocked.length; i++) {
      if (petUnlocked[i] && combatPets.includes(i)) pets++;
    }
    petsPercentage = pets / combatPets.length * 100;
    let totalPercentage = (itemsPercentage + skillsPercentage + monstersPercentage + petsPercentage) / 4;
    //update percentages
    $('#completion-skills').text(Math.floor(skillsPercentage) + '%');
    $('#completion-items').text(Math.floor(itemsPercentage) + '%');
    $('#completion-monsters').text(Math.floor(monstersPercentage) + '%');
    $('#completion-pets').text(Math.floor(petsPercentage) + '%');
    $('#completion-total').text(Math.floor(totalPercentage) + '%');
  }

  window.openItemLog = function () {
    let timesFound = (timesSold = gpFromSale = deathCount = damageTaken = damageDealt = missedAttacks = timesEaten = healedFor = totalAttacks = amountUsedInCombat = timeWaited = timesDied = timesGrown = harvestAmount = enemiesKilled = timesOpened = "");
    let totalFound = 0;
    $("#itemlog-container").html("");
    for (let i = 0; i < combatItems.length; i++) {
      let itemTooltip;
      if (itemStats[combatItems[i].id].timesFound > 0) {
        totalFound++;
        timesFound = timesSold = gpFromSale = deathCount = damageTaken = damageDealt = missedAttacks = timesEaten = healedFor = totalAttacks = amountUsedInCombat = timeWaited = timesDied = timesGrown = harvestAmount = enemiesKilled = timesOpened = "";
        if (itemStats[combatItems[i].id].timesFound > 0) timesFound = "<br>Times Found: <small class='text-warning'>" + formatNumber(itemStats[combatItems[i].id].timesFound) + "</small>";
        if (itemStats[combatItems[i].id].timesSold > 0) timesSold = "<br>Quantity Sold: <small class='text-warning'>" + formatNumber(itemStats[combatItems[i].id].timesSold) + "</small>";
        if (itemStats[combatItems[i].id].gpFromSale > 0) gpFromSale = "<br>GP Gained from sales: <small class='text-warning'>" + formatNumber(itemStats[combatItems[i].id].gpFromSale) + "</small>";
        if (itemStats[combatItems[i].id].deathCount > 0) deathCount = "<br>Times lost due to death: <small class='text-warning'>" + formatNumber(itemStats[combatItems[i].id].deathCount) + "</small>";
        if (itemStats[combatItems[i].id].damageTaken > 0) damageTaken = "<br>Damage Taken whilst Equipped: <small class='text-warning'>" + formatNumber(itemStats[combatItems[i].id].damageTaken) + "</small>";
        if (itemStats[combatItems[i].id].damageDealt > 0) damageDealt = "<br>Damage Dealt: <small class='text-warning'>" + formatNumber(itemStats[combatItems[i].id].damageDealt) + "</small>";
        if (itemStats[combatItems[i].id].missedAttacks > 0) missedAttacks = "<br>Attacks Missed: <small class='text-warning'>" + formatNumber(itemStats[combatItems[i].id].missedAttacks) + "</small>";
        if (itemStats[combatItems[i].id].timesEaten > 0) timesEaten = "<br>Times Eaten: <small class='text-warning'>" + formatNumber(itemStats[combatItems[i].id].timesEaten) + "</small>";
        if (itemStats[combatItems[i].id].healedFor > 0) healedFor = "<br>Healed for: <small class='text-warning'>" + formatNumber(itemStats[combatItems[i].id].healedFor) + "</small>";
        if (itemStats[combatItems[i].id].totalAttacks > 0) totalAttacks = "<br>Total Attacks: <small class='text-warning'>" + formatNumber(itemStats[combatItems[i].id].totalAttacks) + "</small>";
        if (itemStats[combatItems[i].id].amountUsedInCombat > 0) amountUsedInCombat = "<br>Amount used in combat: <small class='text-warning'>" + formatNumber(itemStats[combatItems[i].id].amountUsedInCombat) + "</small>";
        if (itemStats[combatItems[i].id].timeWaited > 0) timeWaited = "<br>Time spent waiting to grow: <small class='text-warning'>" + formatNumber(itemStats[combatItems[i].id].timeWaited) + "</small>";
        if (itemStats[combatItems[i].id].timesDied > 0) timesDied = "<br>Crop deaths: <small class='text-warning'>" + formatNumber(itemStats[combatItems[i].id].timesDied) + "</small>";
        if (itemStats[combatItems[i].id].timesGrown > 0) timesGrown = "<br>Successful grows: <small class='text-warning'>" + formatNumber(itemStats[combatItems[i].id].timesGrown) + "</small>";
        if (itemStats[combatItems[i].id].harvestAmount > 0) harvestAmount = "<br>Amount harvested: <small class='text-warning'>" + formatNumber(itemStats[combatItems[i].id].harvestAmount) + "</small>";
        if (itemStats[combatItems[i].id].enemiesKilled > 0) enemiesKilled = "<br>Enemies killed: <small class='text-warning'>" + formatNumber(itemStats[combatItems[i].id].enemiesKilled) + "</small>";
        if (itemStats[combatItems[i].id].timesOpened > 0) timesOpened = "<br>Opened: <small class='text-warning'>" + formatNumber(itemStats[combatItems[i].id].timesOpened) + "</small>";
        $("#itemlog-container").append('<img class="skill-icon-sm" id="item-log-img-' + combatItems[i].id + '" src="' + items[combatItems[i].id].media + '">');
        itemTooltip = "<div class='text-center'>" + items[combatItems[i].id].name + "<small class='text-info'> " + timesFound + timesSold + gpFromSale + totalAttacks + missedAttacks + damageDealt + damageTaken + enemiesKilled + amountUsedInCombat + timesEaten + healedFor + timesGrown + timesDied + timeWaited + harvestAmount + timesOpened + "</small></div>";
      } else {
        $("#itemlog-container").append('<img class="skill-icon-sm" id="item-log-img-' + combatItems[i].id + '" src="assets/media/main/question.svg">');
        itemTooltip = "<div class='text-center'>" + items[combatItems[i].id].name + "</div>";
      }
      tippy("#item-log-img-" + combatItems[i].id, {
        content: itemTooltip,
        placement: "bottom",
        allowHTML: true,
        interactive: false,
        animation: false,
      });
    }
    //updateTooltips();
    $("#modal-item-log").modal("show");
    document.getElementById("modal-item-log").getElementsByClassName("block-title")[0].textContent = "Item Log (" + totalFound + "/" + combatItems.length + ")";
  }

  window.openPetLog = function() {
    $("#petlog-container").html("");
    for (let i = 0; i < PETS.length; i++) {
      if (combatPets.includes(i)) {
        let tooltop;
        if (petUnlocked[i]) {
          $("#petlog-container").append('<img class="skill-icon-md" id="pet-log-img-' + i + '" src="' + PETS[i].media + '">');
          tooltip = '<div class="text-center"><span class="text-warning">' + PETS[i].name + '</span><br><span class="text-info">' + PETS[i].description + "</span></div>";
        } else {
          $("#petlog-container").append('<img class="skill-icon-md" id="pet-log-img-' + i + '" src="assets/media/main/question.svg">');
          tooltip = "<div class=\"text-center\">???<br><small class='text-danger'>Hint: " + PETS[i].acquiredBy + "</small></div>";
        }
        tippy("#pet-log-img-" + i, {
          content: tooltip,
          placement: "bottom",
          allowHTML: true,
          interactive: false,
          animation: false,
        });
      }
      $("#modal-pet-log").modal("show");
    }
  }
  for (let i = 0; i < skillLevel.length; i++) {
    if (skills.includes(i)) $('#nav-skill-tooltip-' + i).remove();
  }
  $('li.nav-main-item:contains("Alt. Magic")').remove();
  $('#farming-glower').remove();
  $('.nav-main-heading').remove(":contains('Skills')");
  $("#completion-mastery").parent().remove();
  $('.nav-main-item').remove(":contains('Mastery')");
  let m = [0, 1, 2, 3, 4, 5, 10, 11, 13, 14, 15, 19];
  for (let i = 0; i < m.length; i++) {
    $('a[href="javascript: updateMilestoneTab(' + m[i] + ');"]').parent().remove();
  }

  window.downloadList = function () {
    let itemsRemaining = String("ID" + "\t" + "Name" + "\t" + "Sources" + "\n");
    for (let i = 0; i < combatItems.length; i++) {
      if (itemStats[combatItems[i].id].timesFound < 1) {
        itemsRemaining += String(combatItems[i].id + "\t" + combatItems[i].name + "\t" + combatItems[i].sources + "\n");
      }
    }
    let file = new Blob([itemsRemaining], {
      type: "text/plain",
    });
    if (window.navigator.msSaveOrOpenBlob) window.navigator.msSaveOrOpenBlob(file, "Melvor_items_remaining.txt");
    else {
      var a = document.createElement("a"),
        url = URL.createObjectURL(file);
      a.href = url;
      a.download = "Melvor_items_remaining.txt";
      document.body.appendChild(a);
      a.click();
      setTimeout(function () {
        document.body.removeChild(a);
        window.URL.revokeObjectURL(url);
      }, 0);
    }
  }
  var button1 = document.createElement("button");
  button1.className = "btn btn-sm btn-warning m-1";
  button1.onclick = () => downloadList();
  button1.textContent = "Download list of remaining items";
  document
    .getElementById("modal-item-log")
    .getElementsByClassName("block-header bg-primary-dark")[0]
    .insertBefore(button1, document.getElementById("modal-item-log").getElementsByClassName("block-options")[0]);
  window.downloadKC = function () {
    let KCstring = String("ID" + "\t" + "Name" + "\t" + "KC" + "\n");
    for (let i = 0; i < monsterStats.length; i++) {
      KCstring += String(i + "\t" + MONSTERS[i].name + "\t" + monsterStats[i].killedByPlayer + "\n");
    }
    var file = new Blob([KCstring], {
      type: "text/plain",
    });
    if (window.navigator.msSaveOrOpenBlob) window.navigator.msSaveOrOpenBlob(file, "melvorKC.txt");
    else {
      var a = document.createElement("a"),
        url = URL.createObjectURL(file);
      a.href = url;
      a.download = "melvorKC.txt";
      document.body.appendChild(a);
      a.click();
      setTimeout(function () {
        document.body.removeChild(a);
        window.URL.revokeObjectURL(url);
      }, 0);
    }
  }
  var button2 = document.createElement("button");
  button2.className = "btn btn-sm btn-warning m-1";
  button2.onclick = () => downloadKC();
  button2.textContent = "Download Monster Killcounts";
  document
    .getElementById("modal-monster-log")
    .getElementsByClassName("block-header bg-primary-dark")[0]
    .insertBefore(button2, document.getElementById("modal-monster-log").getElementsByClassName("block-options")[0]);
  updateCompletionLog();
  console.log("Combat only completion log loaded");
}, 8000);

QingJ © 2025

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