// ==UserScript==
// @name Diamond Hunt Fixed
// @namespace FileFace
// @description Improve Diamond Hunt Online
// @version 0.9.0
// @author Zorbing
// @grant none
// @run-at document-start
// @include http://www.diamondhunt.co/game.php
// ==/UserScript==
(function ()
{
'use strict';
const settings = {
reorderFarming: {
title: 'Set seed orders coherent (requires reload)'
, defaultValue: true
}
, useFastLevelCalculation: {
title: 'Use fast level calculation'
, defaultValue: true
}
, hideUnnecessaryPrice: {
title: 'Hide unnecessary prices'
, defaultValue: true
}
, unifyMachineryDialog: {
title: 'Unify the machinery dialog (for sand collector)'
, defaultValue: true
}
, fixSeedPotion: {
title: 'Fix requirements of seed potion'
, defaultValue: true
}
};
function getSetting(key)
{
if (!settings.hasOwnProperty(key))
{
return;
}
const name = 'setting.' + key;
return localStorage.hasOwnProperty(name) ? JSON.parse(localStorage.getItem(name)) : settings[key].defaultValue;
}
function setSetting(key, value)
{
if (!settings.hasOwnProperty(key))
{
return;
}
localStorage.setItem('setting.' + key, JSON.stringify(value));
}
function initSettings()
{
const table = document.getElementById('settings-tab').querySelector('table');
if (!table)
{
return;
}
const headerRow = table.insertRow(-1);
headerRow.innerHTML = `<th style="background-color:black;color:orange">Userscript "DHO Fixed"</th>`;
for (let key in settings)
{
let value = getSetting(key);
const row = table.insertRow(-1);
row.innerHTML = `<td id="fake-link-top">
${settings[key].title}: <span style="color:cyan;" id="userscript-${key}">${value ? 'on' : 'off'}</span>
</td>`;
const indicator = document.getElementById('userscript-' + key);;
row.addEventListener('click', () =>
{
value = !value;
setSetting(key, value);
indicator.textContent = value ? 'on' : 'off';
});
}
const settingLink = document.querySelector('.top-menu td[onclick^="openTab"]');
settingLink.addEventListener('click', function ()
{
const activeTab = document.querySelector('#tab-tr td[style^="background: linear-gradient(rgb"]');
if (activeTab)
{
activeTab.style.background = 'linear-gradient(black, grey)';
}
});
}
function fixKeyItems()
{
// remove unnecessary br element
const oilPump = document.getElementById('key-item-handheldOilPump-box');
let br = oilPump && oilPump.nextElementSibling;
if (!br)
{
br = document.createElement('br');
}
// add br element after img in oil pipe element
const oilPipe = document.getElementById('key-item-bindedOilPipe-box');
let img = oilPipe && oilPipe.children[0];
img = img && img.children[0];
img.parentNode.insertBefore(br, img.nextSibling);
}
const seedOrder = ['bloodLeafSeeds', 'dottedGreenLeafSeeds', 'redMushroomSeeds', 'potatoSeeds', 'greenLeafSeeds', 'strawberrySeeds', 'redMushroomTreeSeeds', 'blewitMushroomSeeds', 'wheatSeeds', 'starDustSeeds', 'blewitMushroomTreeSeeds', 'snapeGrassSeeds', 'limeLeafSeeds', 'appleTreeSeeds', 'iceBerrySeeds', 'goldLeafSeeds', 'starDustTreeSeeds', 'stripedLeafSeeds', 'essenceSeeds', 'crystalLeafSeeds', 'megaDottedGreenLeafSeeds', 'megaRedMushroomSeeds', 'megaGreenLeafSeeds', 'essenceTreeSeeds', 'megaBlewitMushroomSeeds', 'megaLimeLeafSeeds', 'stripedCrystalLeafSeeds'];
const seedTitle = {
potatoSeeds: 'Potato Seeds'
, strawberrySeeds: 'Strawberry Seeds'
, wheatSeeds: 'Wheat Seeds'
, dottedGreenLeafSeeds: 'Dotted Green Leaf Seeds'
, greenLeafSeeds: 'Green Leaf Seeds'
, limeLeafSeeds: 'Lime Leaf Seeds'
, goldLeafSeeds: 'Gold Leaf Seeds'
, stripedLeafSeeds: 'Striped Leaf Seeds'
, crystalLeafSeeds: 'Crystal Leaf Seeds'
, redMushroomSeeds: 'Red Mushroom Seeds'
, blewitMushroomSeeds: 'Blewit Mushroom Seeds'
, appleTreeSeeds: 'Apple Tree Seeds'
, snapeGrassSeeds: 'Snape Grass Seeds'
, redMushroomTreeSeeds: 'Red Mushroom Tree Seeds'
, blewitMushroomTreeSeeds: 'Blewit Mushroom Tree Seeds'
, starDustSeeds: 'Star Dust Seeds'
};
function fixFarming()
{
const inputs = document.querySelectorAll('#dialog-planter input[type="image"]');
for (let i = inputs.length-1; i >= 0; i--)
{
const input = inputs[i];
const key = input.id.replace('planter-input-img-', '');
input.title = seedTitle[key];
}
if (!getSetting('reorderFarming'))
{
return;
}
let planterEl = inputs[0];
let boxEl = document.querySelector('#farming-tab .inventory-item-box-farming');
for (let i = seedOrder.length-1; i >= 0; i--)
{
const key = seedOrder[i];
const input = document.getElementById('planter-input-img-' + key);
if (input)
{
planterEl.parentNode.insertBefore(input, planterEl);
planterEl.parentNode.insertBefore(document.createTextNode(' '), planterEl);
planterEl = input;
}
const box = document.getElementById('item-' + key + '-box');
if (box)
{
boxEl.parentNode.insertBefore(box, boxEl);
boxEl.parentNode.insertBefore(document.createTextNode(' '), boxEl);
boxEl = box;
}
}
}
function fixServerMsg()
{
const serverMsgEl = document.querySelector('#server-inner-msg');
if (!serverMsgEl)
{
return;
}
const serverMsg = serverMsgEl.textContent;
const close = document.querySelector('#server-top-msg > *:last-child');
if (localStorage.getItem('closedServerMsg') == serverMsg)
{
close.click();
return;
}
close.addEventListener('click', function ()
{
localStorage.setItem('closedServerMsg', serverMsg);
});
}
const bgColor = 'hsla(0, 100%, 90%, 1)';
const imgSrc2Key = {
'bronzebar': 'bronzeBar'
, 'ironbar': 'ironBar'
, 'silverbar': 'silverBar'
, 'goldbar': 'goldBar'
, 'stonefurnace': 'stoneFurnace'
, 'bronzefurnace': 'bronzeFurnace'
, 'ironfurnace': 'ironFurnace'
, 'silverfurnace': 'silverFurnace'
, 'goldfurnace': 'goldFurnace'
, 'pic_coin': 'coins'
, 'stardust': 'starDust'
, 'treasureKey': 'treasureChestKey'
, 'dottedgreenleaf': 'dottedGreenLeaf'
, 'redmushroom': 'redMushroom'
, 'greenleaf': 'greenLeaf'
, 'limeleaf': 'limeLeaf'
, 'blewitmushroom': 'blewitMushroom'
, 'goldleaf': 'goldLeaf'
, 'pureWater': 'pureWaterPotion'
, 'snapegrass': 'snapeGrass'
, 'crystalleaf': 'crystalLeaf'
, 'starDustConverter': 'starGemPotion'
, 'superStargemPotion': 'superStarGemPotion'
, 'superoilpotion': 'superOilPotion'
};
const furnaceLevels = ['', 'stone', 'bronze', 'iron', 'silver', 'gold', 'ancient', 'promethium'];
function checkRequirement(row, currentLevel)
{
const isRed = row.style.backgroundColor == 'rgb(255, 128, 128)';
const level = row.cells[2];
level.style.backgroundColor = isRed ? bgColor : '';
const levelTooLow = parseInt(level.textContent, 10) > currentLevel;
level.style.color = levelTooLow ? 'red' : '';
const reqEl = row.cells[3];
reqEl.style.backgroundColor = isRed ? bgColor : '';
const children = reqEl.children;
// check for each requirement if it is fulfilled
for (let i = 0; i < children.length; i++)
{
const el = children[i];
if (el.tagName != 'IMG')
{
continue;
}
let key = el.src.replace(/^.+images\/.*?([^\/]+)\..+$/, '$1');
key = imgSrc2Key[key] || key;
const valueEl = el.nextSibling;
// wrap the amount with a span element
const valueSpan = document.createElement('span');
valueEl.parentNode.insertBefore(valueSpan, valueEl);
valueSpan.appendChild(valueEl);
const amount = parseInt(valueEl.textContent
.replace(/M/i, '000000')
.replace(/B/i, '000000000')
.replace(/\D/g, ''), 10)
;
const has = parseInt(window[key] || '0', 10);
let fulfilled = has >= amount;
if (key == 'watering-can')
{
fulfilled = window.getLevel(window.merchantingXp) >= amount;
}
else if (key == 'gem')
{
fulfilled = window.sapphire >= amount || window.emerald >= amount || window.ruby >= amount || window.diamond >= amount;
}
else if (key == 'wooden_slave')
{
fulfilled = parseInt(window.miners, 10) >= amount;
}
else if (/furnace/i.test(key))
{
const furnaceLevel = furnaceLevels.indexOf(key.replace(/furnace/i, ''));
fulfilled = fulfilled || parseInt(window.bindedFurnaceLevel, 10) >= furnaceLevel;
}
valueSpan.style.color = fulfilled ? '' : 'red';
}
}
function fixRequirements()
{
// create an observer instance
const observer = new MutationObserver(function(mutations)
{
mutations.forEach(function(mutation)
{
if (mutation.attributeName == 'style')
{
checkRequirement(mutation.target, window.getLevel(window.craftingXp));
}
});
});
// configuration of the observer:
const config = { attributes: true, childList: false, characterData: false };
const craftTable = document.querySelector('#enchanted-hammer-boxes + table');
const craftingRows = craftTable.rows;
const craftingLevel = window.getLevel(window.craftingXp);
for (let i = 2; i < craftingRows.length; i++)
{
const row = craftingRows[i];
// pass in the target node, as well as the observer options
observer.observe(row, config);
checkRequirement(row, craftingLevel);
}
const brewingTable = document.querySelector('#brewing-tab table');
const brewingRows = brewingTable.rows;
const brewingLevel = window.getLevel(window.brewingXp);
for (let i = 2; i < brewingRows.length; i++)
{
const row = brewingRows[i];
// pass in the target node, as well as the observer options
observer.observe(row, config);
checkRequirement(row, brewingLevel);
}
}
function fixMarket()
{
// create an observer instance
const observer = new MutationObserver(function(mutations)
{
mutations.forEach(function(mutation)
{
console.log(mutation.type, mutation);
// fix icons
var dragonFurnace = mutation.target.querySelector('input[alt="dragonFurnace"]');
if (dragonFurnace)
{
dragonFurnace.src = dragonFurnace.src.replace(/\.png$/, '.gif');
}
// hide duplicate orb
var orbs = mutation.target.querySelectorAll('input[alt="upgradeEnchantedRake"]');
if (orbs.length > 1)
{
orbs[1].style.display = 'none';
}
});
});
// configuration of the observer:
const config = { attributes: false, childList: true, characterData: false };
const table = document.getElementById('selling-tradable-table');
observer.observe(table, config);
// fix loading icons
const loadingImgs = document.querySelectorAll('[src="images/loading_statique.png"]');
for (var i = 0; i < loadingImgs.length; i++)
{
loadingImgs[i].src = 'images/loading.gif';
}
}
const maxLevel = 100;
const maxLevelVirtual = 1000;
let levelXp = new Array(maxLevelVirtual+1);
function calcLevelXp(level)
{
return level > 0 ? Math.round(Math.pow((level-1), 3 + ((level-1) / 200))) : 0;
}
function getLevelXp(level)
{
return levelXp[level-1] || calcLevelXp(level);
}
const getDynamicLevel = (function ()
{
const size = Math.pow(2, Math.ceil(Math.log2(maxLevel)));
let xpTree = new Array(size);
let levelTree = new Array(size);
const sizeVirtual = Math.pow(2, Math.ceil(Math.log2(maxLevelVirtual)));
let xpTreeVirtual = new Array(sizeVirtual);
let levelTreeVirtual = new Array(sizeVirtual);
createNode(xpTree, levelTree, 1, maxLevel, 0);
createNode(xpTreeVirtual, levelTreeVirtual, 1, maxLevelVirtual, 0);
function createNode(xpArray, levelArray, start, end, i)
{
const current = start + Math.pow(2, Math.floor(Math.log2(end - start + 1))) - 1;
xpArray[i] = getLevelXp(current);
levelArray[i] = current;
if (current - start > 0)
{
createNode(xpArray, levelArray, start, current-1, 2*i + 1);
}
if (end - current > 0)
{
createNode(xpArray, levelArray, current+1, end, 2*i + 2);
}
}
function getDynamicLevel(playerXP, useVirtual = false)
{
const isVirtual = virtualLevelsOn !== 0 && useVirtual === true;
const xpArray = isVirtual ? xpTreeVirtual : xpTree;
const levelArray = isVirtual ? levelTreeVirtual : levelTree;
let i = 0;
let level = 0;
while (xpArray[i] != null)
{
if (playerXP == xpArray[i])
{
return levelArray[i];
}
else if (playerXP < xpArray[i])
{
i = 2*i+1;
}
else if (playerXP > xpArray[i])
{
level = levelArray[i];
i = 2*i+2;
}
}
return level;
}
return getDynamicLevel;
})();
function getLevel(playerXP)
{
return getDynamicLevel(playerXP, false);
}
function getVirtualLevel(playerXP)
{
return getDynamicLevel(playerXP, true);
}
function getGlobalLevel()
{
return getDynamicGlobalLevel(false);
}
function getDynamicGlobalLevel(useVirtual = false)
{
return Math.floor(getDynamicLevel(miningXp, useVirtual))
+ Math.floor(getDynamicLevel(craftingXp, useVirtual))
+ Math.floor(getDynamicLevel(brewingXp, useVirtual))
+ Math.floor(getDynamicLevel(merchantingXp, useVirtual))
+ Math.floor(getDynamicLevel(exploringXp, useVirtual))
+ Math.floor(getDynamicLevel(cookingXp, useVirtual))
+ Math.floor(getDynamicLevel(magicXp, useVirtual));
}
function improveLevelCalculation()
{
if (!getSetting('useFastLevelCalculation'))
{
return;
}
for (var i = 1; i < maxLevelVirtual; i++)
{
levelXp[i-1] = calcLevelXp(i);
}
window.getLevel = getLevel;
window.getVirtualLevel = getVirtualLevel;
window.getGlobalLevel = getGlobalXp;
}
function fixInventory()
{
if (!getSetting('hideUnnecessaryPrice'))
{
return;
}
const tab = document.getElementById('gatherings-tab');
const coinImgs = tab.querySelectorAll('span[id^="item-"][id$="-box"] img[src="images/pic_coin.png"]');
for (let i = 0; i < coinImgs.length; i++)
{
const coinImg = coinImgs[i];
const price = coinImg.nextSibling;
if (price.nodeType == Node.TEXT_NODE && !/\d/.test(price.textContent))
{
const parent = coinImg.parentNode;
parent.removeChild(coinImg);
parent.removeChild(price);
}
}
}
const oilConsumption = {
'drill': 1
, 'crusher': 15
, 'giantDrill': 30
, 'roadHeader': 50
, 'bucketWheelExcavator': 150
, 'giantBWE': 500
, 'sandCollector': 5
};
function getOilValueFromMachine(machinery)
{
return (oilConsumption[machinery] || 0) * window['binded' + machinery[0].toUpperCase() + machinery.substr(1)];
}
function openOilDialogue(varname)
{
const gearOnPath = 'images/spinning-gear.gif';
const gearOffPath = 'images/spinning-gear-off.gif';
const oilArea = document.getElementById('oilUsage-area');
const oilValue = document.getElementById('oilUsage-value');
const repairArea = document.getElementById('machinery-repair-area');
let machine = varname.replace(/key-item-binded([^-]+)-box/, '$1');
machine = machine[0].toLowerCase() + machine.substr(1);
// PROGRESS BAR
var hasRepair = window.bindedPromethiumWrench > 0;
if (machine == 'sandCollector')
{
// hide repair part (ensure, it is hidden)
repairArea.setAttribute('style', 'padding: 0; width: 0px; height: 0px; overflow: hidden; border: 0;');
}
else
{
// show repair part if available
repairArea.setAttribute('style', 'display: ' + (hasRepair ? 'block' : 'none') + ';');
const progressBar = document.getElementById('progress-bar-repair-opened');
const percent = window[machine + 'Repair'];
const bgColor = percent < 20 ? 'yellow' : (percent >= 50 ? 'lime' : 'yellow');
progressBar.style.backgroundColor = bgColor;
progressBar.style.width = percent + '%';
}
// END PROGRESS BAR
oilValue.innerHTML = window.getOilValueFromMachine(machine);
document.getElementById('machineryChosenPopup').value = machine;
const isOn = window[machine + 'AreOn'] == 1;
document.getElementById('myonoffswitch').checked = isOn;
document.getElementById('myonoffswitch-gear').src = isOn ? gearOnPath : gearOffPath;
oilArea.style.display = isOn ? '' : 'none';
window.$('#machinery-dialog').dialog(
{
width: 400
});
}
function fixMachinery()
{
if (!getSetting('unifyMachineryDialog'))
{
return;
}
window.getOilValueFromMachine = getOilValueFromMachine;
window.openOilDialogue = openOilDialogue;
}
const potionRequirements = {
'starDustPotion': {
level: 1
, dottedGreenLeaf: 1
, redMushroom: 25
}
, 'seedPotion': {
level: 5
, dottedGreenLeaf: 5
, redMushroom: 100
, greenLeaf: 1
}
, 'smeltingPotion': {
level: 10
, dottedGreenLeaf: 10
, bronzeBar: 1
, ironBar: 1
, silverBar: 1
, goldBar: 1
}
, 'oilPotion': {
level: 15
, limeLeaf: 5
, redMushroom: 50
, blewitMushroom: 25
}
, 'miningPotion': {
level: 20
, limeLeaf: 5
, redMushroom: 100
, dottedGreenLeaf: 20
}
, 'superStarDustPotion': {
level: 25
, goldLeaf: 3
, redMushroom: 100
, dottedGreenLeaf: 5
}
, 'coinPotion': {
level: 30
, goldLeaf: 1
, greenLeaf: 15
, snapeGrass: 50
}
, 'explorersPotion': {
level: 30
, pureWaterPotion: 1
, greenMushroom: 10
, strangeLeaf: 3
}
, 'compost': {
level: 35
, redMushroom: 650
, blewitMushroom: 500
, snapeGrass: 350
}
, 'starGemPotion': {
level: 40
, goldLeaf: 3
, limeLeaf: 10
, snapeGrass: 50
}
, 'fishingPotion': {
level: 45
, pureWaterPotion: 1
, shrimp: 10
, greenMushroom: 10
, strangeLeaf: 1
}
, 'essencePotion': {
level: 45
, goldLeaf: 5
, limeLeaf: 5
, snapeGrass: 100
}
, 'fastFurnacePotion': {
level: 45
, limeLeaf: 5
, redMushroom: 500
}
, 'superCompostPotion': {
level: 50
, crystalLeaf: 1
, redMushroom: 650
, blewitMushroom: 500
, snapeGrass: 350
}
, 'superOilPotion': {
level: 55
, goldLeaf: 2
, greenLeaf: 10
, dottedGreenLeaf: 25
, snapeGrass: 80
}
, 'goldenStriperPotion': {
level: 60
, goldLeaf: 9
, blewitMushroom: 750
}
, 'magicCoolDownPotion': {
level: 60
, goldLeaf: 2
, blewitMushroom: 500
}
, 'artifactPotion': {
level: 60
, goldLeaf: 4
, redMushroom: 500
, stripedLeaf: 2
}
, 'superStarGemPotion': {
level: 60
, stripedLeaf: 3
, limeLeaf: 20
, snapeGrass: 200
, starGemPotion: 1
}
, 'chestPotion': {
level: 65
, stripedLeaf: 3
, dottedGreenLeaf: 100
, blewitMushroom: 500
}
, 'superEssencePotion': {
level: 65
, stripedCrystalLeaf: 2
, greenLeaf: 100
, snapeGrass: 900
}
, 'megaStarDustPotion': {
level: 70
, crystalLeaf: 3
, dottedGreenLeaf: 80
, redMushroom: 1000
}
, 'superChestPotion': {
level: 75
, stripedCrystalLeaf: 3
, greenLeaf: 300
, blewitMushroom: 3000
, chestPotion: 10
}
, 'whaleFishingPotion': {
level: 80
, pureWaterPotion: 5
, cactusWater: 1
, whaleTooth: 1
}
, 'megaStarGemPotion': {
level: 80
, crystalLeaf: 5
, limeLeaf: 40
, snapeGrass: 400
, superStarGemPotion: 1
}
, 'megaOilPotion': {
level: 85
, stripedCrystalLeaf: 3
, redMushroom: 5000
, superOilPotion: 1
}
, 'invisiblePotion': {
level: 100
, stripedCrystalLeaf: 30
, runite: 25
, runiteBar: 25
, ghostRemains: 1
, dragonstone: 5
}
, 'engineeringPotion': {
level: 40
, stripedLeaf: 1
, swampWater: 2
}
};
function canBrewItem(command)
{
var requirements = potionRequirements[command];
if (!requirements)
{
return true;
}
for (var key in requirements)
{
if (key == 'level')
{
if (getLevel(brewingXp) < requirements.level)
{
return false;
}
}
else if (window[key] < requirements[key])
{
return false;
}
}
return true;
}
function fixBrewing()
{
if (!getSetting('fixSeedPotion'))
{
return;
}
window.canBrewItem = canBrewItem;
}
/**
* init
*/
document.addEventListener('DOMContentLoaded', function ()
{
initSettings();
fixKeyItems();
fixFarming();
fixServerMsg();
fixRequirements();
fixMarket();
improveLevelCalculation();
fixInventory();
fixMachinery();
fixBrewing();
});
})();