您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
The cheat script for DH3
当前为
// ==UserScript== // @name DH3 KindaSafe Cheat // @namespace http://tampermonkey.net/ // @version 1.3.0 // @description The cheat script for DH3 // @author Lasse Brustad // @match https://dh3.diamondhunt.co/ // @grant none // ==/UserScript== /* jshint esversion:8 */ (function() { 'use strict'; // config for cheats const cheats = { // auto fight, configs starting at line 45 autoCombat: !true, // auto smelt ores, click the ore under the mining tab to choose // will automatically fill the furnace to it's maximum capacity // configs starting at line 70 autoSmelt: !true, // auto chop trees, it's fully automated with a tiny issue that doesn't matter autoChop: !true, // auto consume stardust potions you have autoDrinkSD: !true, // auto send/collect the Oxygen Tank, you can't get any fish at all with this on autoOxy: !true, // auto send/collect the Row Boat, this is forced off if autoOxy is on autoRowBoat: !true, // auto send/collect the Canoe Boat, this is forced off if autoOxy or autoRowBoat is on autoCanoeBoat: !true }; const combatConfig = { areas: { // area name : energy cost (1e3 = 1000, 1e4 = 10000, 1_000 = 1000) // Fields fields: 50, // Forest forest: 200, // Caves caves: 500, // Lava Dungeon lavaDungeon: 2e3, // Northern Fields northernFields: 5e3, // Cemetery cemetery: 10e3 }, // the area you want to fight automatically from the "areas" list area: 'fields', // don't teleport from named entities fight: [ 'chicken', 'ent', 'skeleton', 'bat', 'boneHead' ], // skip entities instead, like repel potion does, but using teleport (PS: you get XP) skip: [ 'spider' ], // use skip list, or fight list? 'fight' / 'skip' / 'none' listName: 'fight' // 'none' here will disable this cheat } // additional config for autoSmelt const smeltConfig = { // smelt all resources that can be smelted smeltAllAvaliable: !true, ores: { // this is ordered the way the autoSmelt will choose resource titanium: { // minimum amount before smelting, higher than capacity will be reduced to maximum capacity min: 5, // maximum amount to autosmelt each time, 0 = no limit/furnace capacity max: 10 }, promethium: { min: 5, max: 50 }, gold: { min: 20, max: 100 }, silver: { min: 50, max: 250 }, iron: { min: 100, max: 500 }, sand: { min: 50, max: 0 }, copper: { min: 200, max: 1000 } } } // config for legal mods const mods = { // right click the axe to chop down all fully grown trees chopTrees: true, // right click the rake to harvest all the ready farms harvestCrops: true }; /** * Code below here is functional code, but you can enable/disable everything in the configs above * * Remember, cheats is safe to use as it is, but if you mess with the code, * don't blame me if you get banned! Cheats is ofc not allowed, but who cares? */ window.lbstuff = cheats; window.lbstuff.toggleCheat = cheat => { if (typeof cheats[cheat] !== 'boolean') return `"${cheat}" isn't a cheat!`; cheats[cheat] = !cheats[cheat]; window.lbstuff[cheat] = cheats[cheat]; } window.lbmore = { combatArea: () => combatConfig.area, combatStatus: window.setCombatStatus, changeSmeltOre(ore) { window.smeltOre = ore; } } // logging / debugging const debugLevels = [ 'silent', 'normal logging', 'additional logging', 'debugging' ]; let debugLevel = parseInt(localStorage.getItem('lbdata-debug')) || 1; window.setDebugLevel = (lvl = debugLevel) => { if (typeof lvl !== 'number' || (lvl < 0 && lvl > (debugLevels.length - 1))) { console.log(`Didn't change the logging level, it has to be a number between 0 and 3.`); return; } const previous = debugLevel; debugLevel = lvl; if (previous === debugLevel) { console.log(`Current debug level is: ${lvl} ~ ${debugLevels[lvl]}`); } else { console.log(`Debug level is now set to: ${lvl} ~ ${debugLevels[lvl]}`); } } async function wait(ms) { await new Promise(resolve => { setTimeout(resolve, ms); }); } const min = 0; const cheatData = { combat: { fightSoon: false, error: false, useSpells: false, disabled: JSON.parse(localStorage.getItem('lbdata-combatError')) || false }, smelting: { queue: false } }; // auto combat function autoCombat() { const { fightSoon, error, disabled } = cheatData.combat; // damn, didn't expect this function to require that much anti-fail testing if (error || !disabled) return; if (window.getItem('monsterName') != 'none' && window.getItem('combatCountDown') == 0) { inCombat(); return; } if (fightSoon || window.getItem('heroCooldown') !== 0 || window.getItem('teleportCooldown') != 0) return debug(3, `Combat isn't ready yet`); if (!Object.keys(combatConfig.areas).includes(combatConfig.area)) { cheatData.combat.error = true; debug(2, `The script has no area called ${combatConfig.area} registered!`); return; } if (combatConfig.areas[combatConfig.area] > window.getItem('energy')) return debug(2, `You're low on energy! Eat some food to continue fighting!`);; // FIGHT!!! cheatData.combat.fightSoon = true; cheatData.combat.useSpells = true; safeDelay(() => { if (window.getItem('heroCooldown') !== 0) return debug(3, `Combat isn't ready yet`); window.sendBytes(`FIGHT=${combatConfig.area}`); }) } function castSpell(spell) { if (!['heal', 'poison', 'reflect', 'fire', 'teleport', 'freeze', 'ghostScan', 'invisibility'].includes(spell)) return false; // stole the spell safety check from DH3 Fixed #yolo if( document.getElementById("navigation-right-combat-fighting").style.display != "none" && document.getElementById(`combat-spell-${spell}`).style.display != "none" ){ document.getElementById(`combat-spell-${spell}`).click(); return true; } } async function inCombat() { // avoid spamming if (!cheatData.combat.useSpells) return; cheatData.combat.fightSoon = false; cheatData.combat.useSpells = false; // get the entity name const entity = window.getItem('monsterName'); // stop here if it's in castle! if (entity.startsWith('knight')) return; // use all spells except teleport const spells = ['heal', 'poison', 'reflect', 'fire', 'freeze', 'ghostScan', 'invisibility'].reverse(); for (let spell of spells) { await wait(Math.floor(Math.random() * 150) + 100); castSpell(spell); } // if the entity isn't in the list, cast teleport! const noTeleport = combatConfig[combatConfig.listName]; if ( (!noTeleport.includes(entity) && combatConfig.listName === 'fight') || (noTeleport.includes(entity) && combatConfig.listName === 'skip') ) { await wait(Math.floor(Math.random() * 150) + 350); castSpell('teleport'); } } // settings for autoCombat while playing window.setCombatStatus = (state = null) => { if (typeof state === 'boolean') { cheatData.combat.disabled = state; console.log(`Set the state to ${state ? 'active' : 'inactive'}`); } else if (typeof state === 'string' && typeof combatConfig.areas[state] === 'number') { combatConfig.area = state; console.log(`Set the area to ${state}`); } else if (state === null) { console.log(`Current state: Fighting ${combatConfig.area} is ${!cheatData.combat.error ? 'active' : 'inactive'}`); } } unload(e => { localStorage.setItem('lbdata-combatError', JSON.stringify(cheatData.combat.error)); localStorage.setItem('lbdata-combatArea', combatConfig.area); }); // auto smelt ores window.smeltOre = localStorage.getItem('lbdata-smeltOre') || 'copper'; // the ore to smelt if (cheats.autoSmelt) { unload(e => { localStorage.setItem('lbdata-smeltOre', window.smeltOre); }); } // cheatSmelt function smeltMax(resource) { if (window.isSmelting()) return debug(3, `Your furnace is unavaliable!`); const oilCost = window.getOilCost(resource) || 0; const charcoalCost = window.getCharcoalCost(resource) || 0; if (oilCost == 0 && charcoalCost == 0) return debug(2, `Can't smelt "${resource}"`); const data = smeltConfig.ores[resource]; const cost = oilCost || charcoalCost; const _oilOrCharcoal = oilCost === cost ? 'oil' : 'charcoal'; let cap = +window.getItem('furnaceCapacity'), max = Math.min(+window.getItem(resource) || 0, cap, data.max); if (max === 0) return debug(3, `You don't have any ${resource}!`); if (cap - resource < Math.min(cap, data.min)) return debug(3, `You need more ${resource} to autoSmelt it!`); const oilOrCharcoal = window.getItem(_oilOrCharcoal); max = (max * cost) < oilOrCharcoal ? max : (oilOrCharcoal / (max * cost)); if (max < Math.min(cap, data.min)) return debug(3, `You don't have enought ${_oilOrCharcoal} to smelt ${resource}`); window.smelt(resource, max); // will smelt maximum possible of resource } function smeltableResources() { const result = []; const _ores = Object.keys(smeltConfig.ores); for (let ore of _ores) { if (window.getItem(ore) != 0) result.push(ore); } return result; } function smeltAvaliable() { if (window.isSmelting()) return `Your furnace in unavaliable!`; const avaliable = smeltableResources(); if (avaliable.length === 0) return `You don't have any smeltable resources!`; smeltMax(avaliable[0]); } function cheatSmelt() { if (window.isSmelting() || cheatData.smelting.queue) return; if (smeltConfig.smeltAllAvaliable) { cheatData.smelting.queue = true; safeDelay(() => { smeltAvaliable(); cheatData.smelting.queue = !true; }); return; } cheatData.smelting.queue = true; safeDelay(() => { smeltMax(window.smeltOre) cheatData.smelting.queue = !true; }); } const clicksItem = window.clicksItem; function clicksItemMod(modified = true) { if (modified) { window.clicksItem = (item, ...args) => { if (typeof smeltConfig.ores[item] === 'object') { window.smeltOre = item; } clicksItem(item, ...args); }; } else { window.clicksItem = clicksItem; } } // auto chop trees function cheatChop() { const treeData = { click(n) { debug(2, `Auto Chop - Chopping patch ${n}`); document.getElementById(`tree-section-${n}`).click(); setTimeout(() => window.closeDialogue('dialogue-confirm'), 1e3); }, timer(n) { return window[`var_treeTimer${n}`] * 1; }, isActive(n) { return window[`var_tree${n}`] !== 'none'; } }; const tasks = [null, false, false, false, false, false, false]; function chop(num, waitMinSec = 0) { if (tasks[num]) return; tasks[num] = true; safeDelay(() => { tasks[num] = false; if (!treeData.isActive(num)) return; treeData.click(num); }, waitMinSec * 1e3); } function loop() { for (let i = 1; i < tasks.length; i++) { const timeLeft = treeData.timer(i); if (timeLeft < 10) chop(i, timeLeft); } } setInterval(loop, 1e4); } // auto drink stardust potion let willConsumeSDPot = false; function autoSDPot() { const timeLeft = parseInt(window.var_stardustPotionTimer); if (timeLeft <= (5 * 60) && parseInt(window.var_stardustPotion) > 0 && !willConsumeSDPot) { willConsumeSDPot = true; safeDelay(() => { window.sendBytes('DRINK=stardustPotion'); setTimeout(() => { willConsumeSDPot = false; }, 3e3); }); } } // auto boat let willUseBoat = false; function cheatAnyBoat(str = 'oxygenTank') { if (willUseBoat) return; const tLeft = window.getItem(str + "Timer"); if (tLeft > 2) return; let task = () => {}; switch (tLeft) { case 0: willUseBoat = true; task = () => window.sendBytes("SEND_BOAT=" + str); break; case 1: willUseBoat = true; task = () => window.sendBytes("COLLECT_BOAT=" + str); break; } safeDelay(() => { const timeLeft = window.getItem(str + "Timer"); if (timeLeft === tLeft) task(); willUseBoat = false; }); } function initCheats() { // combat if (cheats.autoCombat) { setInterval(autoCombat, 1e3); debug(1, 'Cheat - Initialized Auto Combat'); } // mining/crafting if (cheats.autoSmelt) { setInterval(cheatSmelt, 1e3); clicksItemMod(true); debug(1, 'Cheat - Initialized Auto Smelt'); } // woodcutting if (cheats.autoChop) { cheatChop(); debug(1, 'Cheat - Initialized Auto Chop'); } // brewing if (cheats.autoDrinkSD) { setInterval(autoSDPot, 2e3); debug(1, 'Cheat - Initialized Auto Drink Stardust Potion'); } // fishing if (cheats.autoOxy) { setInterval(cheatAnyBoat, 1e3); debug(1, 'Cheat - Initialized Auto Oxygen Tank'); } else if (cheats.autoRowBoat) { setInterval(() => cheatAnyBoat('rowBoat'), 1e3); debug(1, 'Cheat - Initialized Auto Row Boat'); } else if (cheats.autoCanoeBoat) { setInterval(() => cheatAnyBoat('canoeBoat'), 1e3); debug(1, 'Cheat - Initialized Auto Canoe Boat'); } } // mod 1 - RightClick axe to chop all trees function chopTrees(e) { const trees = getEls('#tree-section-woodcutting > center > div'); e.preventDefault(); trees.each(el => { const timeEl = el.querySelector('.tree-secton-timer'); const time = timeEl !== null ? timeEl.innerText : ''; if (time === 'READY') el.click(); }); debug(2, 'Chopped all trees'); } // mod 2 - RightClick rake to harvest the crops function harvestCrops(e) { const trees = getEls('#plot-section-farming > center > div'); e.preventDefault(); trees.each(el => { const timeEl = el.querySelector('.tree-secton-timer'); const time = timeEl !== null ? timeEl.innerText : ''; if (time === 'READY') el.click(); }); debug(2, 'Harvested all crops'); } function initMods() { if (mods.chopTrees) { // init mod 1 getEls('#item-section-woodcutting-1 [data-tooltip-id=tooltip-axe]') .each(el => el.addEventListener('contextmenu', chopTrees)); debug(1, 'Mod - Initialized Right Click Axe'); } if (mods.harvestCrops) { // init mod 2 getEls('#item-section-farming-1 [data-tooltip-id=tooltip-rake]') .each(el => el.addEventListener('contextmenu', harvestCrops)); debug(1, 'Mod - Initialized Right Click Rake'); } } function init() { if (typeof window.var_username === "string" && window.var_username.length >= 3) { initMods(); debug(1, 'Initialized Mods'); initCheats(); debug(1, 'Initialized Cheats'); } else { setTimeout(init, 2e3); } } setTimeout(init, 2e3); /** * minor functions for this script to work well with clean code */ function getEls(qSel) { let els = document.querySelectorAll(qSel); return { getRaw() { return els; }, getNum(x) { return els[x]; }, each(fn) { els.forEach(fn); }, ids() { let res = []; for (let key of els) res.push(key.id || 'none'); return res; } } } function debug(lvl, ...msg) { if (lvl > debugLevel) { return; } window.lastMessage = msg.join(' - '); switch (lvl) { case 0: // silent return; case 1: // standard logging case 2: // additional logging return console.log('DH3 KindaSafe:', ...msg); case 3: // debugging return console.log('DH3 KindaSafe Debugging:', ...msg); } } function unload(fn) { window.addEventListener('unload', fn); } // A safe cheat delayer function safeDelay(fn, minTime = 0) { setTimeout(fn, Math.floor(Math.random() * 4e3) + 1e3 + minTime); } })();