Greasy Fork is available in English.

DH3 HUD

Highly customizable heads up display for DH3

Від 30.09.2020. Дивіться остання версія.

// ==UserScript==
// @name         DH3 HUD
// @namespace    com.anwinity.dh3
// @version      1.0.0
// @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 HELP = `
<html>
  <head>
    <title>DH3 HUD Help</title>
  </head>
  <body>
    <p>DH3 HUD provides a means to display useful information using the built in variables and images in DH3. You can format this message however you'd like by using a sort of hybrid BBCode/HTML style syntax, which is explained below. Unless you want to make something complex, this let's you create useful displays without needing to know any html or javascript.</p>
    <ul>
      <li>Normal text (as opposed to tags, explained below) is rendered as-is for the most part with a couple of exceptions. Any character following a backslash (\\) will be displayed as text and not evaluated as a tag. This is necessary for including [ and ] text, if you want. So, for example, \\[ will allow you to include a [ character without indicating the start of a tag.</li>
      <li>Tags are in the form [tag=value] and some end with [/tag], where tag is the tag name and value is some associated context.</li>
      <li><strong>[color=xxx][/color]</strong> allows you to change the color of text inside the tags. The xxx can be any valid html color (name or #hex).</li>
      <li><strong>[var=xxx]</strong> allows you to inject any of the built in var_ values in DH3. For example, the number of diamonds you have found is stored in a value called var_diamondMined. You can use [var=diamondMined] to inject this value.</li>
      <li><strong>[icon=xxx]</strong> allows you to inject any PNG image from those found on <a href="https://dh3.diamondhunt.co/images/" target="_blank">https://dh3.diamondhunt.co/images/</a>. For GIF, use <strong>[gif=xxx]</strong>. <strong>[png=xxx]</strong> is also an alias of icon.</li>
      <li><strong>[time=xxx]</strong> is similar to [var] but it takes the value of the variable and formats it as a timestamp using the built in DH3 function formatTime. This is useful for certain variables like heroCooldown.</li>
      <li><strong>[style=xxx]</strong> is a more advanced styling feature which allows you to inject CSS into your HUD. This is literally translated to &lt;span style="xxx"&gt;. Don't forget to include <strong>[/style]</strong>.</li>
      <li><strong>[if=xxx]</strong> is for conditionally including sections. This requires javascript. The xxx part must RETURN some value, which is then evaluated as a boolean. If true, the section will be displayed. Otherwise, it will be hidden. Don't forget to include the <strong>[/if]</strong>.</li>
      <li><strong>[eval=xxx]</strong> is for more complex calculations. This requires javascript. The xxx part must RETURN the text value to be displayed.</li>
    </ul>
  </body>
</html>
`;
    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 "--:--:--"; ]
    `.trim();
    let hud = "";
    let hudUndo = null;
    let hudParsed = [];

    function clamp(min, max, x) {
        return x<min ? min : (x>max ? max : x);
    }

    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 init() {
        if(!window.var_username) {
            setTimeout(init, 1000);
            return;
        }

        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;
          }
          .dh3-hud-button {
            display: inline-block;
            text-align: center;
            vertical-align: middle;
            padding: 2px;
            cursor: pointer;
            opacity: 0.75;
          }
          .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;
          }
        `;
        $("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("", "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}
            `);
            win.document.write(HELP);
            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();
        });

        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();

        const originalSetItems = window.setItems;
        window.setItems = function() {
            originalSetItems.apply(this, arguments);
            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 == '\\') {
                        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;
    }

    function update() {
        let html = ""; // hud.replace(/\r?\n/g, "<br />");
        let conditionResult = null;
        let conditionTag = null;
        function transform(text) {
            return text.replaceAll("<", "&lt;").replaceAll(">", "&gt;").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": {
                            html += formatTime(window["var_"+value]);
                            break;
                        }
                        case "style": {
                            html += `<span style="${value}">`;
                            break;
                        }
                        case "/style": {
                            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 "eval": {
                            html += Function("return function() {" + value + "}")()();
                            break;
                        }
                    }
                }
            }
            catch(err) {
                console.log(err);
                html += '<span style="color: red; font-weight: bold;>ERROR</span>';
            }
        });
        $("#dh3-hud-content").html(html);
    }

    $(init);
    
})();