您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Collection of various snippets
- // ==UserScript==
- // @name Melvor Snippets
- // @namespace http://tampermonkey.net/
- // @version 0.0.18
- // @description Collection of various snippets
- // @grant none
- // @author GMiclotte
- // @include https://melvoridle.com/*
- // @include https://*.melvoridle.com/*
- // @exclude https://melvoridle.com/index.php
- // @exclude https://*.melvoridle.com/index.php
- // @exclude https://wiki.melvoridle.com/*
- // @exclude https://*.wiki.melvoridle.com/*
- // @inject-into page
- // @noframes
- // @grant none
- // ==/UserScript==
- ((main) => {
- const script = document.createElement('script');
- script.textContent = `try { (${main})(); } catch (e) { console.log(e); }`;
- document.body.appendChild(script).parentNode.removeChild(script);
- })(() => {
- function startSnippets() {
- window.snippet = {
- name: '',
- log: (...args) => console.log('Snippets:', ...args),
- start: () => snippet.log(`Loading ${snippet.name}.`),
- end: () => snippet.log(`Loaded ${snippet.name}.`),
- };
- // header end
- /////////////////////////////////////
- //AgilityObstacleBuildsRemaining.js//
- /////////////////////////////////////
- snippet.name = 'AgilityObstacleBuildsRemaining.js';
- snippet.start();
- // show agility obstacles that have been built less than 10 times
- window.listObstaclesWithFewerThanTenBuilds = () => {
- agilityObstacleBuildCount.map((_, i) => i)
- .filter(i => agilityObstacleBuildCount[i] < 10)
- .map(i => agilityObstacles[i])
- .map(x => [x.category + 1, x.name]);
- }
- snippet.end();
- ///////////////////
- //BankedHealth.js//
- ///////////////////
- snippet.name = 'BankedHealth.js';
- snippet.start();
- // return total healing in bank
- window.bankedHealth = () => {
- return items.filter(x => x.healsFor)
- .map(x => player.getFoodHealing(x) * combatManager.bank.getQty(x.id))
- .reduce((a, b) => a + b, 0);
- }
- snippet.end();
- //////////////////
- //DefensePure.js//
- //////////////////
- snippet.name = 'DefensePure.js';
- snippet.start();
- // Various Defense Pure Calculations
- window.defensePure = {};
- defensePure.defLvlToHPLvl = def => {
- const hpXP = exp.level_to_xp(10) + 1;
- const minDefXP = exp.level_to_xp(def) + 1;
- const maxDefXP = exp.level_to_xp(def + 1);
- const minHpXP = hpXP + minDefXP / 3;
- const maxHpXP = hpXP + maxDefXP / 3;
- const minHp = exp.xp_to_level(minHpXP) - 1;
- const maxHp = exp.xp_to_level(maxHpXP) - 1;
- return {min: minHp, max: maxHp};
- }
- defensePure.defLvlToCbLvl = def => {
- const hp = defensePure.defLvlToHPLvl(def);
- const att = 1, str = 1, ran = 1, mag = 1, pray = 1;
- const minBase = (def + hp.min + Math.floor(pray / 2)) / 4;
- const maxBase = (def + hp.max + Math.floor(pray / 2)) / 4;
- const melee = (att + str) * 1.3 / 8;
- const ranged = Math.floor(1.5 * ran) * 1.3 / 8;
- const magic = Math.floor(1.5 * mag) * 1.3 / 8;
- const best = Math.max(melee, ranged, magic);
- return {min: minBase + best, max: maxBase + best};
- }
- defensePure.lastHitOnly = (skillID, maxLevel = 1) => {
- if (skillXP[skillID] >= exp.level_to_xp(maxLevel + 1) - 1) {
- combatManager.stopCombat();
- return;
- }
- // swap weapon based on hp left
- let itemID;
- if (combatManager.enemy.hitpoints > 1) {
- if (skillID === Skills.Magic) {
- itemID = Items.Normal_Shortbow;
- } else {
- // melee or ranged
- itemID = Items.Staff_of_Air;
- }
- } else {
- if (skillID === Skills.Ranged) {
- itemID = Items.Iron_Throwing_Knife;
- } else if (skillID === Skills.Magic) {
- itemID = Items.Staff_of_Air;
- } else {
- // melee
- itemID = -1;
- }
- }
- if (player.equipment.slots.Weapon.item.id !== itemID) {
- if (itemID === -1) {
- player.unequipItem(0, 'Weapon');
- } else {
- player.equipItem(itemID, 0);
- }
- }
- // loop
- setTimeout(() => defensePure.lastHitOnly(skillID, maxLevel), 1000);
- }
- snippet.end();
- /////////////////////////
- //GetLocalisationKey.js//
- /////////////////////////
- snippet.name = 'GetLocalisationKey.js';
- snippet.start();
- // Get Localisation Key for a given string
- window.getLocalisationKey = (text) => {
- const list = []
- for (const key in loadedLangJson) {
- for (const identifier in loadedLangJson[key]) {
- if (loadedLangJson[key][identifier] === text) {
- list.push({key: key, identifier: identifier});
- }
- }
- }
- return list;
- }
- snippet.end();
- //////////////////////
- //ListRaidUnlocks.js//
- //////////////////////
- snippet.name = 'ListRaidUnlocks.js';
- snippet.start();
- // list unlocked raid items
- window.listCrateItems = (unlocked = true) =>
- RaidManager.crateItemWeights.filter(x =>
- unlocked === game.golbinRaid.ownedCrateItems.has(x.itemID)
- ).forEach(x =>
- snippet.log(items[x.itemID].name)
- );
- // to list the ones you have unlocked:
- // listCrateItems()
- // to list the ones you haven't unlocked:
- // listCrateItems(false)
- snippet.end();
- ////////////////
- //LootDrops.js//
- ////////////////
- snippet.name = 'LootDrops.js';
- snippet.start();
- // Loot Drops
- window.lootDrops = () => {
- const loot = combatManager.loot;
- // only loot when the loot table is full
- if (loot.drops.length < loot.maxLoot) {
- return;
- }
- // when the bank is full, update the bank cache
- const bankFull = bank.length === getMaxBankSpace();
- if (bankFull) {
- for (let i = 0; i < bank.length; i++) {
- bankCache[bank[i].id] = i;
- }
- }
- loot.drops = loot.drops.filter(drop => {
- const itemID = drop.item.id;
- if (bankFull) {
- // reject all items that aren't in the bank cache
- if (bankCache[itemID] === undefined) {
- return false;
- }
- }
- if (addItemToBank(itemID, drop.qty))
- game.stats.Combat.add(CombatStats.ItemsLooted, drop.qty);
- return false;
- });
- }
- // hook to player.rewardGPForKill, this runs on player death and is a relatively small method
- eval(player.rewardGPForKill.toString().replaceAll(
- 'this',
- 'player',
- ).replace(
- 'rewardGPForKill(){',
- 'window.rewardGPForKill = () => {window.lootDrops();',
- ));
- window.hookLootDrops = () => {
- if (player) {
- player.rewardGPForKill = window.rewardGPForKill;
- } else {
- setTimeout(window.hookLootDrops, 50);
- }
- }
- // window.hookLootDrops();
- snippet.end();
- //////////////////
- //MasteryBars.js//
- //////////////////
- snippet.name = 'MasteryBars.js';
- snippet.start();
- // Add Mastery Bars
- setInterval(() => {
- for (const id in SKILLS) {
- if (SKILLS[id].hasMastery) {
- if ($(`#skill-nav-mastery-${id} .progress-bar`)[0]) {
- $(`#skill-nav-mastery-${id} .progress-bar`)[0].style.width =
- (MASTERY[id].pool / getMasteryPoolTotalXP(id)) * 100 + '%';
- if (MASTERY[id].pool < getMasteryPoolTotalXP(id)) {
- $(`#skill-nav-mastery-${id}`)[0].style.setProperty('background', 'rgb(76,80,84)', 'important');
- $(`#skill-nav-mastery-${id} .progress-bar`)[0].className = 'progress-bar bg-warning';
- } else {
- $(`#skill-nav-mastery-${id}`)[0].style.setProperty('background', 'rgb(48,199,141)', 'success');
- $(`#skill-nav-mastery-${id} .progress-bar`)[0].className = 'progress-bar bg-success';
- }
- const tip = $(`#skill-nav-mastery-${id}`)[0]._tippy;
- tip.setContent((Math.min(1, MASTERY[id].pool / getMasteryPoolTotalXP(id)) * 100).toFixed(2) + '%');
- } else {
- const skillItem = $(`#skill-nav-name-${id}`)[0].parentNode;
- skillItem.style.flexWrap = 'wrap';
- skillItem.style.setProperty('padding-top', '.25rem', 'important');
- const progress = document.createElement('div');
- const progressBar = document.createElement('div');
- progress.id = `skill-nav-mastery-${id}`;
- progress.className = 'progress active pointer-enabled';
- progress.style.height = '6px';
- progress.style.width = '100%';
- progress.style.margin = '.25rem 0rem';
- if (MASTERY[id].pool < getMasteryPoolTotalXP(id)) {
- progress.style.setProperty('background', 'rgb(76,80,84)', 'important');
- progressBar.className = 'progress-bar bg-warning';
- } else {
- progress.style.setProperty('background', 'rgb(48,199,141)', 'success');
- progressBar.className = 'progress-bar bg-success';
- }
- progressBar.style.width = (MASTERY[id].pool / getMasteryPoolTotalXP(id)) * 100 + '%';
- progress.appendChild(progressBar);
- skillItem.appendChild(progress);
- tippy($(`#skill-nav-mastery-${id}`)[0], {
- placement: 'right',
- content: ((MASTERY[id].pool / getMasteryPoolTotalXP(id)) * 100).toFixed(2) + '%',
- });
- }
- }
- }
- }, 5000);
- snippet.end();
- ///////////////////
- //MasteryBuyer.js//
- ///////////////////
- snippet.name = 'MasteryBuyer.js';
- snippet.start();
- // methods to buy base mastery levels
- window.masteryBuyer = {
- poolXpPerItem: 500000,
- };
- masteryBuyer.availXp = (skillID, minPercent = 95) => {
- let minPool = MASTERY[skillID].xp.length * masteryBuyer.poolXpPerItem * minPercent / 100;
- return MASTERY[skillID].pool - minPool;
- }
- masteryBuyer.currentBase = (skillID) => {
- return Math.min(...MASTERY[skillID].xp.map((_, masteryID) => getMasteryLevel(skillID, masteryID)));
- }
- masteryBuyer.maxAffordableBase = (skillID, minPercent = 95) => {
- let xp = masteryBuyer.availXp(skillID, minPercent);
- // make bins with mastery levels
- let bins = [];
- for (let i = 0; i < 100; i++) {
- bins[i] = [];
- }
- MASTERY[skillID].xp.forEach((_, masteryID) => {
- let level = getMasteryLevel(skillID, masteryID);
- bins[level].push(masteryID);
- });
- // level one at a time
- let maxBase = 0;
- bins.forEach((x, i) => {
- if (i >= 99) {
- return;
- }
- if (x.length === 0) {
- return;
- }
- let xpRequired = (exp.level_to_xp(i + 1) - exp.level_to_xp(i)) * x.length;
- xp -= xpRequired;
- if (xp >= 0) {
- maxBase = i + 1;
- x.forEach(y => bins[i + 1].push(y));
- }
- });
- maxBase = maxBase > 99 ? 99 : maxBase;
- return maxBase;
- }
- masteryBuyer.increaseBase = (skillID, minPercent = 95, levelCap = 99) => {
- // buy until goal
- let goal = masteryBuyer.maxAffordableBase(skillID, minPercent);
- if (goal === 0) {
- goal = masteryBuyer.currentBase(skillID);
- }
- if (goal > levelCap) {
- goal = levelCap;
- }
- MASTERY[skillID].xp.forEach((_, masteryID) => {
- let level = getMasteryLevel(skillID, masteryID);
- if (level >= goal) {
- return;
- }
- masteryPoolLevelUp = goal - level;
- levelUpMasteryWithPool(skillID, masteryID);
- });
- // spend remainder on goal + 1
- const xpRequired = exp.level_to_xp(goal + 1) - exp.level_to_xp(goal);
- let count = Math.floor(masteryBuyer.availXp(skillID, minPercent) / xpRequired);
- masteryPoolLevelUp = 1;
- MASTERY[skillID].xp.forEach((_, masteryID) => {
- if (count === 0) {
- return;
- }
- let level = getMasteryLevel(skillID, masteryID);
- if (level > goal || level >= levelCap) {
- return;
- }
- count--;
- levelUpMasteryWithPool(skillID, masteryID);
- });
- // update total mastery
- updateTotalMastery(skillID);
- }
- masteryBuyer.overview = (minPercent = 95) => {
- Object.getOwnPropertyNames(SKILLS).forEach(skillID => {
- const skill = SKILLS[skillID];
- if (!skill.hasMastery) {
- return;
- }
- const maxBase = masteryBuyer.maxAffordableBase(skillID, minPercent);
- if (maxBase === 0) {
- return;
- }
- const currentBase = masteryBuyer.currentBase(skillID);
- snippet.log(`${skill.name}: ${currentBase} -> ${maxBase}`);
- });
- }
- masteryBuyer.remaining = (skillID, target = 99) => {
- let xp = 0;
- let xpTarget = exp.level_to_xp(target);
- MASTERY[skillID].xp.forEach(masteryXp => {
- xp += Math.max(0, xpTarget - masteryXp);
- });
- xp = Math.round(xp)
- snippet.log(formatNumber(xp))
- return xp
- }
- snippet.end();
- ///////////////////////
- //PrintSynergyList.js//
- ///////////////////////
- snippet.name = 'PrintSynergyList.js';
- snippet.start();
- // functions to print synergies per category (cb vs non-cb)
- window.printSynergy = (x, y) => snippet.log('- [ ]',
- x.summoningID,
- parseInt(y),
- items[x.itemID].name,
- items[summoningItems[y].itemID].name,
- SUMMONING.Synergies[x.summoningID][y].description,
- SUMMONING.Synergies[x.summoningID][y].modifiers
- );
- window.printCombatSynergyList = () => {
- // get combat synergies
- summoningItems.filter(x => items[x.itemID].summoningMaxHit).map(x => {
- for (y in SUMMONING.Synergies[x.summoningID]) {
- printSynergy(x, y);
- }
- });
- }
- window.printNonCombatSynergyList = () => {
- // get non-combat synergies
- summoningItems.filter(x => !items[x.itemID].summoningMaxHit).map(x => {
- for (y in SUMMONING.Synergies[x.summoningID]) {
- printSynergy(x, y);
- }
- });
- }
- snippet.end();
- /////////////////////
- //QuickEquipCape.js//
- /////////////////////
- snippet.name = 'QuickEquipCape.js';
- snippet.start();
- // Quick Equip Max/Comp Cape
- window.quickEquipSkillcape = (skill) => {
- const capes = [
- Items.Cape_of_Completion,
- Items.Max_Skillcape,
- skillcapeItems[skill],
- ];
- for (let i = 0; i < capes.length; i++) {
- const capeId = capes[i];
- if (player.equipment.checkForItemID(capeId)) {
- notifyPlayer(skill, `${items[capeId].name} is already equipped.`, "info");
- return;
- }
- const bankId = getBankId(capeId);
- if (bankId === -1) {
- continue;
- }
- if (!player.equipItem(capeId, player.selectedEquipmentSet)) {
- continue;
- }
- notifyPlayer(skill, `${items[capeId].name} Equipped.`, "success");
- if (skill === 0) {
- updateWCRates();
- }
- return;
- }
- notifyPlayer(skill, "There's no " + setToUppercase(Skills[skill]) + " Skillcape in your bank *shrug*", "danger");
- }
- snippet.end();
- ////////////////////
- //ReclaimTokens.js//
- ////////////////////
- snippet.name = 'ReclaimTokens.js';
- snippet.start();
- // reclaim tokens
- window.reclaimMasteryTokens = () => {
- skillXP.forEach((_, s) => {
- if (MASTERY[s] === undefined) {
- return;
- }
- const id = Items['Mastery_Token_' + Skills[s]];
- const p = Math.floor((MASTERY[s].pool - getMasteryPoolTotalXP(s) ) / Math.floor(getMasteryPoolTotalXP(s)*0.001));
- const m = game.stats.Items.statsMap.get(id).stats.get(ItemStats.TimesFound);
- const o = getBankQty(id);
- const a = Math.min(p, m - o);
- const b = getBankId(id);
- if (a > 0 && b >= 0) {
- bank[b].qty += a;
- MASTERY[s].pool -= a * Math.floor(getMasteryPoolTotalXP(s)*0.001);
- snippet.log('reclaimed', a, Skills[s], 'tokens');
- }
- });
- }
- snippet.end();
- /////////////////////
- //RemoveElements.js//
- /////////////////////
- snippet.name = 'RemoveElements.js';
- snippet.start();
- // remove various elements
- // combat
- document.getElementById('offline-combat-alert').remove();
- // summoning marks
- // green
- document.getElementById('summoning-category-0').children[0].children[0].children[2].remove();
- // orange and red
- document.getElementById('summoning-category-0').children[0].children[0].children[1].remove();
- // summoning tablets
- document.getElementById('summoning-category-1').children[0].children[0].children[0].remove()
- // alt. magic
- document.getElementById('magic-container').children[0].children[1].remove();
- // cloud saving
- document.getElementById('header-cloud-save-time').remove();
- document.getElementById('header-cloud-save-btn-connected').remove();
- snippet.end();
- /////////////////////////
- //RerollJuniorFarmer.js//
- /////////////////////////
- snippet.name = 'RerollJuniorFarmer.js';
- snippet.start();
- // automate rerolling and attacking of Junior Farmer
- window.rerollJuniorFarmer = () => {
- // rewardGPForKill loots drops and rerolls slayer task
- eval(player.rewardGPForKill.toString().replaceAll(
- 'this',
- 'player',
- ).replace(
- 'rewardGPForKill(){',
- 'window.rewardGPForKill = () => {' +
- 'window.lootDrops();' +
- 'window.rerollSlayerTaskFast([Monsters.JuniorFarmer], 0, false);',
- ));
- player.rewardGPForKill = window.rewardGPForKill;
- // process death restarts fight
- let checkDeath = combatManager.checkDeath.toString().slice(0,-1); // remove closing curly brace
- checkDeath += 'if (playerDied) {' +
- 'combatManager.selectMonster(Monsters.JuniorFarmer, getMonsterArea(Monsters.JuniorFarmer));' +
- 'snippet.log("player death: new fight initiated");' +
- '}';
- checkDeath += '}'; // add closing curly brace
- eval(checkDeath.replaceAll(
- 'this',
- 'combatManager',
- ).replace(
- 'checkDeath(){',
- 'window.checkDeath = () => {',
- ));
- combatManager.checkDeath = window.checkDeath;
- }
- // window.rerollJuniorFarmer();
- snippet.end();
- ///////////////////
- //RerollSlayer.js//
- ///////////////////
- snippet.name = 'RerollSlayer.js';
- snippet.start();
- //reroll slayer task until desired task is met
- window.rerollSlayerTask = (monsterIDs, tier, extend = true, loop = true) => {
- if (window.stopRerolling) {
- return;
- }
- const task = combatManager.slayerTask;
- const taskID = task.monster.id;
- const taskName = MONSTERS[taskID].name;
- if (!combatManager.slayerTask.taskTimer.active) {
- // only do something if slayer task timer is not running
- if (!combatManager.slayerTask.active || !monsterIDs.includes(taskID)) {
- // roll task if we don't have one, or if it has the wrong monster
- snippet.log(`rerolling ${taskName} for tier ${tier} task ${monsterIDs.map(monsterID => MONSTERS[monsterID].name).join(', ')}`);
- combatManager.slayerTask.selectTask(tier, true, true, false);
- } else if (extend && !task.extended) {
- // extend task if it is the right monster
- snippet.log(`extending ${taskName}`);
- combatManager.slayerTask.extendTask();
- }
- }
- if (loop) {
- setTimeout(() => rerollSlayerTask(monsterIDs, tier, extend), 1000);
- }
- }
- // simulate rerolling of slayer task until desired task is met
- window.rerollSlayerTaskFast = (monsterIDs, tier, extend = true, verbose = false) => {
- const task = combatManager.slayerTask;
- if (task.taskTimer.active) {
- return;
- }
- // only do something if slayer task timer is not running
- if (task.active && monsterIDs.includes(task.monster.id)) {
- if (extend && !task.extended) {
- // extend task if it is the right monster
- if (verbose) {
- snippet.log(`extending ${MONSTERS[task.monster.id].name}`);
- }
- task.extendTask();
- }
- return;
- }
- // roll task if we don't have one, or if it has the wrong monster
- const monsterSelection = task.getMonsterSelection(tier).map(x => x.id);
- const monsterSelectionMap = {};
- monsterSelection.forEach(x => monsterSelectionMap[x] = true);
- monsterIDs = monsterIDs.filter(x => monsterSelectionMap[x]);
- if (monsterIDs.length === 0) {
- snippet.log(`no valid monsterIDs provided for tier ${tier}`);
- return;
- }
- // simulate rerolls until one of the target monsters is rolled
- let rerolls = 1;
- const prob = monsterIDs.length / monsterSelection.length;
- while (Math.random() > prob) {
- rerolls++;
- }
- let scAmount = 0;
- if (tier > 0) {
- scAmount = SlayerTask.data[tier].cost * rerolls;
- if (scAmount > player._slayercoins) {
- snippet.log(`insufficient slayer coins, needed ${scAmount}, have ${player._slayercoins}`);
- return;
- }
- task.player.removeSlayerCoins(scAmount, true);
- }
- // randomly pick one of the valid monsters
- const monsterID = monsterIDs[rollInteger(0, monsterIDs.length - 1)];
- // mimic task.selectTask
- task.monster = MONSTERS[monsterID];
- task.tier = tier;
- task.active = true;
- task.extended = false;
- task.killsLeft = task.getTaskLength(tier);
- task.renderRequired = true;
- task.renderNewButton = true;
- if (verbose) {
- snippet.log(`simulated ${rerolls} rerolls for tier ${tier} task ${MONSTERS[monsterID].name} costing ${scAmount}SC`);
- }
- }
- snippet.end();
- /////////////////
- //ShardsUsed.js//
- /////////////////
- snippet.name = 'ShardsUsed.js';
- snippet.start();
- // compute total shards used
- window.shardsUsed = () => {
- // compute amount of gp spent on summoning shards that have been used (for summoning or agility obstacles)
- items.map((x, i) => [x, i])
- .filter(x => x[0].type === 'Shard' && x[0].category === 'Summoning')
- .map(x => x[1])
- .map(x => (itemStats[x].stats[0] - getBankQty(x) - itemStats[x].stats[1]) * items[x].buysFor)
- .reduce((a, b) => a + b, 0);
- }
- snippet.end();
- ///////////////////
- //SpawnAhrenia.js//
- ///////////////////
- snippet.name = 'SpawnAhrenia.js';
- snippet.start();
- // spawn Ahrenia
- window.spawnAhrenia = (phaseToSpawn = 1) => {
- // run
- combatManager.runCombat();
- // set respawn to 0
- if (!petUnlocked[0]) {
- unlockPet(0);
- }
- PETS[0].modifiers.decreasedMonsterRespawnTimer = 0;
- player.computeAllStats();
- PETS[0].modifiers.decreasedMonsterRespawnTimer = 3000 - TICK_INTERVAL - player.modifiers.decreasedMonsterRespawnTimer + player.modifiers.increasedMonsterRespawnTimer;
- player.computeAllStats();
- // unlock itm
- dungeonCompleteCount[Dungeons.Fire_God_Dungeon] = Math.max(
- dungeonCompleteCount[Dungeons.Fire_God_Dungeon],
- 1,
- );
- skillLevel[Skills.Slayer] = Math.max(
- skillLevel[Skills.Slayer],
- 90,
- );
- // skip to desired phase
- combatManager.selectDungeon(15);
- combatManager.dungeonProgress = 19 + phaseToSpawn;
- combatManager.loadNextEnemy();
- }
- snippet.end();
- ////////////////////
- //UnlimitedPool.js//
- ////////////////////
- snippet.name = 'UnlimitedPool.js';
- snippet.start();
- // don't cap pool xp
- eval(addMasteryXPToPool.toString()
- .replace('MASTERY[skill].pool>getMasteryPoolTotalXP(skill)', 'false')
- .replace(/^function (\w+)/, "window.$1 = function")
- );
- // don't cap token claiming
- eval(claimToken.toString()
- .replace('qty>=tokensToFillPool', 'false')
- .replace(/^function (\w+)/, "window.$1 = function")
- );
- snippet.end();
- /////////////
- //Unsell.js//
- /////////////
- snippet.name = 'Unsell.js';
- snippet.start();
- // unsell sold items
- window.unsell = (id, count = Infinity) => {
- if (count < 0) {
- return;
- }
- const timesSold = game.stats.Items.get(id, ItemStats.TimesSold);
- const gpFromSales = game.stats.Items.get(id, ItemStats.GpFromSale);
- if (timesSold === 0) {
- snippet.log("zero times sold");
- return;
- }
- // check if transaction is affordable
- const times = Math.min(count, timesSold);
- const cost = Math.ceil(gpFromSales / timesSold * times);
- if (gp < cost) {
- snippet.log("can't afford: " + times + " costs " + cost + " have " + gp);
- return;
- }
- // add item
- if (times > 0) {
- addItemToBank(id, times);
- }
- game.stats.Items.add(id, ItemStats.TimesFound, -times);
- game.stats.Items.add(id, ItemStats.TimesSold, -times);
- // remove cost
- gp = Math.floor(gp - cost);
- game.stats.Items.add(id, ItemStats.GpFromSale, -cost);
- updateGP();
- // fix statistics
- game.stats.General.add(GeneralStats.TotalItemsSold, -times);
- updateBank();
- // log transaction
- snippet.log("bought " + times + " for " + cost);
- }
- snippet.end();
- // footer start
- }
- function loadScript() {
- if (typeof isLoaded !== typeof undefined && isLoaded) {
- // Only load script after game has opened
- clearInterval(scriptLoader);
- startSnippets();
- }
- }
- const scriptLoader = setInterval(loadScript, 200);
- });