// ==UserScript==
// @name DH3 HUD
// @namespace com.anwinity.dh3
// @version 1.1.1
// @description Highly customizable heads up display for DH3
// @author Anwinity
// @match dh3.diamondhunt.co
// @grant none
// ==/UserScript==
(function() {
'use strict';
const KEY_CONTENT = "dh3-hud.content";
const KEY_SETTINGS = "dh3-hud.settings";
const HELP_URL = "https://anwinity.com/dh3/hudhelp.html";
const DEFAULT_SETTINGS = {
hideInCombat: false,
hideInCombatMap: false
};
const settings = Object.assign({}, DEFAULT_SETTINGS);
const DEFAULT = `
Default/Example HUD
[color=red]Hello! I'm red![/color]
[style=font-size: 12pt]i am smol[/style]
This is how many gems you've found: [icon=bloodDiamond][var=bloodDiamondMined] [icon=diamond][var=diamondMined] [icon=ruby][var=rubyMined] [icon=emerald][var=emeraldMined] [icon=sapphire][var=sapphireMined]
Here's your combat cooldown: [icon=combatSkill][time=heroCooldown]
Oh boy, this one is complex. Let's take a look at your rocket status:
[if=return var_rocketStatus=="1"][gif=rocket][/if][if=return var_rocketStatus=="3"][gif=rocketBack][/if] [eval=if(var_rocketStatus==1) return formatTime((384000-var_rocketKm)/2); else if(var_rocketStatus==3) return formatTime(var_rocketKm/2); else return "--:--:--"; ]
You can also use some of lassebrus's functions, which are included with this script:
[fn=hud.rocketTimer]
`.trim();
let hud = "";
let hudUndo = null;
let hudParsed = [];
function load() {
hud = localStorage.getItem(KEY_CONTENT);
if(typeof hud !== "string") {
hud = DEFAULT;
}
hudParsed = parseHud(hud);
}
function save() {
localStorage.setItem(KEY_CONTENT, hud);
hudParsed = parseHud(hud);
}
function update() {
let html = ""; // hud.replace(/\r?\n/g, "<br />");
function transform(text) {
return text.replace(/</g, "<").replace(/>/g, ">").replace(/\r?\n/g, "<br />");
};
hudParsed.forEach(piece => {
try {
if(piece.type == "text") {
html += transform(piece.text);
}
else if(piece.type == "tag") {
let text = piece.text.substr(1, piece.text.length-2);
let tag;
let value;
let eq = text.indexOf("=");
if(eq >= 0) {
tag = text.substr(0, eq);
value = text.substr(eq+1);
}
else {
tag = text;
value = null;
}
tag = tag.toLowerCase();
switch(tag) {
case "color": {
html += `<span style="color: ${value}">`;
break;
}
case "/color": {
html += "</span>";
break;
}
case "var": {
html += window["var_"+value];
break;
}
case "icon":
case "png": {
html += `<img class="dh3-hud-icon" src="images/${value}.png" />`;
break;
}
case "gif": {
html += `<img class="dh3-hud-icon" src="images/${value}.gif" />`;
break;
}
case "time": {
let time = formatTime(window["var_"+value]);
if(time=="0") {
time = "--:--:--";
}
html += time;
break;
}
case "number": {
let n = formatNumber(window["var_"+value]);
if(!n || n=="undefined") {
n = "0";
}
html += n;
break;
}
case "style": {
html += `<span style="${value}">`;
break;
}
case "/style": {
html += "</span>";
break;
}
case "class": {
html += `<span class="${value}">`;
break;
}
case "/class": {
html += "</span>";
break;
}
case "if": {
let b = Function("return function() {" + value + "}")()();
if(b) {
html += "<span>";
}
else {
html += '<span style="display: none">';
}
break;
}
case "/if": {
html += "</span>";
break;
}
case "button": {
value = value.replace(/"/g, """);
html += `<button type="button" class="dh3-hud-button" onclick="${value}">`;
break;
}
case "/button": {
html += "</button>";
break;
}
case "eval": {
let evalFunction = `return function() { ${value} }`;
let evalResult = Function(evalFunction)()();
html += evalResult;
break;
}
case "fn": {
let evalFunction = `return ${value}`;
let evalResult = Function(evalFunction)();
if(typeof evalResult === "function") {
evalResult = evalResult();
}
html += evalResult;
break;
}
case "html": {
html += value;
break;
}
}
}
}
catch(err) {
console.log(err);
html += '<span style="color: red; font-weight: bold;>ERROR</span>';
}
});
$("#dh3-hud-content").html(html);
}
function initExtraFunctions() {
/* Other scripts can add functions to window.hud for easy access within the hud */
window.hud = {
/* Credits: Lassebrus */
rocketTimer: function() {
// if the rocket isn't in use atm, return a timer with no time
const rocketStatus = window.getItem('rocketStatus');
if (rocketStatus != 1 && rocketStatus != 3) {
return '--:--:--';
}
// what's the destination?
const dest = window.getItem('rocketDestination');
// rocket km is?
const rocketKm = window.getItem('rocketKm');
// the avg. speed is?
let speed = 0,
// and the end destination is x km away
end = 0;
// get the correct values:
switch (dest) {
case 'moon':
speed = 2;
end = 384e3;
break;
case 'mars':
speed = 140;
end = 54e6;
break;
default:
speed = 0;
}
const kmLeft = rocketStatus === 1 ? end - rocketKm : rocketKm;
return window.formatTime(kmLeft / speed);
},
/* Credits: Lassebrus */
marketCollectable: function(slot = 1) {
const slotEl = document.querySelector(`#market-slot-collect-${slot}`);
if (!(slotEl instanceof HTMLSpanElement)) {
return 'Error! Check your BB-code!';
}
return slotEl.innerText;
}
};
}
function init() {
if(!window.var_username) {
setTimeout(init, 1000);
return;
}
initExtraFunctions();
// adds currentTab variable
window.var_currentTab = "home";
const originalNavigate = window.navigate;
window.navigate = function(tab) {
originalNavigate.apply(this, arguments);
if(tab.startsWith("right-")) {
window.var_currentTab = tab.slice(6);
}
else {
window.var_currentTab = tab;
}
};
setTimeout(function(){
const originalSetItems = window.setItems;
window.setItems = function() {
originalSetItems.apply(this, arguments);
update();
}
}, 5000);
const styles = document.createElement("style");
styles.textContent = `
#dh3-hud-container {
font-size: 14pt;
padding: 0.25em;
margin-top: 0.25em;
margin-bottom: 0.125em;
margin-right: 1px;
border: 1px solid rgb(64, 64, 64);
border-radius: 2px;
background-color: rgb(26, 26, 26);
}
#dh3-hud-toolbar {
text-align: right;
border-bottom: 1px solid rgb(64, 64, 64);
padding-bottom: 0.25em;
margin-bottom: 0.25em;
}
div.dh3-hud-button {
display: inline-block;
text-align: center;
vertical-align: middle;
padding: 2px;
cursor: pointer;
opacity: 0.75;
}
div.dh3-hud-button:hover {
background-color: rgb(39, 39, 39);
opacity: 1.0;
}
#dh3-hud-content {
font-family: "Lucida Console", Monaco, monospace;
}
img.dh3-hud-icon {
display: inline-block;
height: 18px;
width: auto;
}
button.dh3-hud-button {
background-color: rgb(26, 26, 26);
color: white;
border: 1px solid rgb(64, 64, 64);
cursor: pointer;
opacity: 0.75;
}
button.dh3-hud-button:hover {
opacity: 1;
}
`;
$("head").append(styles);
let fontAwesome = document.createElement("script");
fontAwesome.src = "https://kit.fontawesome.com/044e12ee28.js"
fontAwesome.crossorigin = "anonymous";
fontAwesome.type = "text/javascript";
$("head").append(fontAwesome);
$("#table-top-main-items").after(`
<div id="dh3-hud-container">
<div id="dh3-hud-toolbar">
<div id="dh3-hud-button-help" class="dh3-hud-button" title="Help"><i class="far fa-question-circle"></i></div>
<div id="dh3-hud-button-save" class="dh3-hud-button" title="Save" style="display: none"><i class="far fa-save"></i></div>
<div id="dh3-hud-button-cancel" class="dh3-hud-button" title="Cancel" style="display: none"><i class="fas fa-undo-alt"></i></div>
<div id="dh3-hud-button-edit" class="dh3-hud-button" title="Edit"><i class="fas fa-pencil-alt"></i></div>
<div id="dh3-hud-button-hide" class="dh3-hud-button" title="Hide"><i class="far fa-minus-square"></i></div>
<div id="dh3-hud-button-show" class="dh3-hud-button" title="Show" style="display: none"><i class="far fa-plus-square"></i></div>
</div>
<div id="dh3-hud-bottom">
<div id="dh3-hud-content"></div>
<textarea id="dh3-hud-editor" rows="10" style="width: 100%; display: none;"></textarea>
</div>
</div>
`);
$("#dh3-hud-button-help").click(function() {
const w = 500;
const h = 700;
const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : window.screenX;
const dualScreenTop = window.screenTop !== undefined ? window.screenTop : window.screenY;
const width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
const height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;
const systemZoom = width / window.screen.availWidth;
const left = (width - w) / 2 / systemZoom + dualScreenLeft
const top = (height - h) / 2 / systemZoom + dualScreenTop
const win = window.open(HELP_URL, "DH3 HUD Help",
`
scrollbars=yes,
menubar=no,
toolbar=no,
location=no,
status=no,
resizable=yes,
width=${w / systemZoom},
height=${h / systemZoom},
top=${top},
left=${left}
`);
if (typeof win.focus === "function") {
win.focus();
}
});
$("#dh3-hud-button-save").click(function() {
hud = $("#dh3-hud-editor").val();
save();
$("#dh3-hud-content").show();
$("#dh3-hud-editor").hide();
$("#dh3-hud-button-edit").show();
$("#dh3-hud-button-save").hide();
$("#dh3-hud-button-cancel").hide();
update();
});
$("#dh3-hud-button-cancel").click(function() {
hud = hudUndo;
$("#dh3-hud-content").show();
$("#dh3-hud-editor").hide();
$("#dh3-hud-button-edit").show();
$("#dh3-hud-button-save").hide();
$("#dh3-hud-button-cancel").hide();
});
$("#dh3-hud-button-edit").click(function() {
hudUndo = hud;
$("#dh3-hud-content").hide();
$("#dh3-hud-editor").show().val(hud);
$("#dh3-hud-button-edit").hide();
$("#dh3-hud-button-save").show();
$("#dh3-hud-button-cancel").show();
$("#dh3-hud-editor").focus();
});
let hideShowAnimating = false;
$("#dh3-hud-button-hide").click(function() {
if(!hideShowAnimating) {
hideShowAnimating = true;
$("#dh3-hud-bottom").hide("slide", {
direction: "up",
complete: function() {
$("#dh3-hud-button-hide").hide();
$("#dh3-hud-button-show").show();
hideShowAnimating = false;
}
});
}
});
$("#dh3-hud-button-show").click(function() {
if(!hideShowAnimating) {
hideShowAnimating = true;
$("#dh3-hud-bottom").show("slide", {
direction: "up",
complete: function() {
$("#dh3-hud-button-hide").show();
$("#dh3-hud-button-show").hide();
hideShowAnimating = false;
}
});
}
});
load();
update();
}
function parseHud(str) {
let result = [];
if(typeof str === "string") {
let buf = "";
let bracket = false;
for(let i = 0; i < str.length+1; i++) {
let c = str.charAt(i);
let next = str.charAt(i+1);
if(bracket) {
if(c == '\\') {
buf += next;
i++;
}
else if(c == ']') {
buf += c;
result.push({type: "tag", text: buf});
buf = "";
bracket = false;
}
else if(!c) {
result.push({type: "tag", text: buf+"]"});
}
else {
buf += c;
}
}
else {
if(c == '\\') {
if(next != '\n') {
buf += next;
}
i++;
}
else if(c == '[') {
result.push({type: "text", text: buf});
buf = c;
bracket = true;
}
else if(!c) {
result.push({type: "text", text: buf});
}
else {
buf += c;
}
}
}
}
return result;
}
$(init);
})();