Greasy Fork

Greasy Fork is available in English.

MouseHunt HUD Backgroundifier

Change the background of (almost) everything on mousehuntgame.com (But why? What possessed you to seek this out?)

当前为 2021-10-25 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         MouseHunt HUD Backgroundifier
// @author       LethalVision
// @version      0.3
// @description  Change the background of (almost) everything on mousehuntgame.com (But why? What possessed you to seek this out?)
// @include	http://mousehuntgame.com/*
// @include	https://mousehuntgame.com/*
// @include	http://www.mousehuntgame.com/*
// @include	https://www.mousehuntgame.com/*
// @grant        none
// @namespace    http://greasyfork.icu/en/users/683695-lethalvision
// ==/UserScript==

const TAG = "HUD_BCKGRNDFR"

var preferences = {
    hudUrl: "",
    backUrl: "",
    leftUrl: "",
    rightUrl: "",
    statOpacity: 1,
    hudOpacity: 1,
    statShadow: false
};

function init() {
    var loadedPref = window.localStorage.getItem(TAG);
    if (loadedPref){
        try{
            loadedPref = JSON.parse(loadedPref);
            preferences.hudUrl = loadedPref.hudUrl;
            preferences.backUrl = loadedPref.backUrl;
            preferences.leftUrl = loadedPref.leftUrl;
            preferences.rightUrl = loadedPref.rightUrl;
            preferences.statOpacity = loadedPref.statOpacity;
            preferences.hudOpacity = loadedPref.hudOpacity;
            preferences.statShadow = loadedPref.statShadow;
            console.log("Backgroundifier preferences loaded");
        } catch (err) {
            console.log('Preference parse error: ' + err);
        }
    }
    addListener();
    addButton();
    setTimeout(function(){
        updateAll();
    }, 500);
}

// stuff preferences into the localStorage
function savePreferences() {
    var jsonString = JSON.stringify(preferences);
    window.localStorage.setItem(TAG, jsonString);
}

function addListener() {
    const originalOpen = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = function() {
        this.addEventListener("load", function() {
            if ( this.responseURL === "https://www.mousehuntgame.com/managers/ajax/pages/page.php" ||
               this.responseURL === "https://www.mousehuntgame.com/managers/ajax/pages/preferences.php") {
                addButton();
                updateAll();

            }
        });
        originalOpen.apply(this, arguments);
    };
}

// === SMOKE AND MIRRORS HERE ===
// add button to bring up the settings
function addButton() {
    if (document.getElementById("hudBtn")) {
        // if button already exists
        return;
    }
    const div = document.createElement("div");
    div.className = "hudBtn-container";
    div.style.position = "absolute";
    div.style.bottom = "5px";
    div.style.right = "7px"

    const hudBtn = document.createElement("button");
    hudBtn.id = "hudBtn";
    hudBtn.textContent = "!";
    hudBtn.style.width = "20px"
    hudBtn.style.height = "20px"
    hudBtn.style.opacity = "0.5"
    hudBtn.onclick = function(){renderBox();}

    div.appendChild(hudBtn);
    const hudContainer = document.getElementsByClassName("headsUpDisplayView");
    if (!hudContainer || hudContainer.length != 1) {
        // hudContainer can't be found or the length is unexpected
        return;
    }
    hudContainer[0].insertAdjacentElement("afterend",div);
}

// render the almighty Tsitu's Floating Box
function renderBox(){return new Promise((resolve, reject) => {
    // clear all open boxes
    document
     .querySelectorAll("#hud-options")
     .forEach(el=> el.remove())

    const div = document.createElement("div");
    div.id = "hud-options";
    div.style.backgroundColor = "#F5F5F5";
    div.style.position = "fixed";
    div.style.zIndex = "9999";

    div.style.left = "35vw";
    div.style.top = "55vh";

    div.style.border = "solid 3px #696969";
    div.style.borderRadius = "20px";
    div.style.padding = "10px";
    div.style.textAlign = "left";
    div.style.minWidth = "207px";

    const buttonDiv = document.createElement("div");
    buttonDiv.style.float= "right";
    buttonDiv.style.textAlign = "right";
    const closeButton = document.createElement("button", {
        id: "close-button"
    });
    closeButton.textContent = "x";
    closeButton.onclick = function () {
    document.body.removeChild(div);
    };
    closeButton.style.marginRight = "5px"

    const titleDiv = document.createElement("div")
    titleDiv.id = "hud-optionsheader";
    titleDiv.textContent = "HUD Backgroundifier";
    titleDiv.style.width = "75%";
    titleDiv.style.float= "left";
    titleDiv.style.textAlign = "left";
    titleDiv.style.fontSize = "12px"
    titleDiv.style.fontWeight = "bold";
    titleDiv.style.marginLeft = "5px";

    const urlDiv = document.createElement("div")
    urlDiv.className = "clear"
    urlDiv.textContent = "Image URLs";
    urlDiv.style.fontWeight = "bold";
    urlDiv.style.textAlign = "left";
    urlDiv.style.marginTop = "5px";
    urlDiv.style.marginLeft = "5px";

    var urlTable = document.createElement('table');
    urlTable.style.textAlign = "left";
    urlTable.style.borderSpacing = "1em 0";
    urlTable.style.paddingTop = "5px"

    var topRow = urlTable.insertRow();
    topRow.style.height = "24px";
    var topDesc = topRow.insertCell(0);
    topDesc.appendChild(document.createTextNode("HUD background:"));
    // set width once and the rest should follow
    topDesc.style.width = "35%"
    var urlInput = document.createElement('input');
    urlInput.id = "urlInput";
    urlInput.style.width = "95%";
    urlInput.value = preferences.hudUrl;
    urlInput.onchange = function(){
        checkAndLoadImage("hud", urlInput.value);
    }
    topRow.insertCell(1).appendChild(urlInput);

    var backRow = urlTable.insertRow();
    backRow.style.height = "24px";
    var backDesc = backRow.insertCell(0);
    backDesc.appendChild(document.createTextNode("Camp background:"));
    var backInput = document.createElement('input');
    backInput.id = "backInput";
    backInput.style.width = "95%";
    backInput.value = preferences.backUrl;
    backInput.onchange = function(){
        checkAndLoadImage("back", backInput.value);
    }
    backRow.insertCell(1).appendChild(backInput);

    var leftRow = urlTable.insertRow();
    leftRow.style.height = "24px";
    var leftDesc = leftRow.insertCell(0);
    leftDesc.appendChild(document.createTextNode("Left screen background:"));
    var leftInput = document.createElement('input');
    leftInput.id = "leftInput";
    leftInput.style.width = "95%";
    leftInput.value = preferences.leftUrl;
    leftInput.onchange = function(){
        checkAndLoadImage("left", leftInput.value);
    }
    leftRow.insertCell(1).appendChild(leftInput);

    var rightRow = urlTable.insertRow();
    rightRow.style.height = "24px";
    var rightDesc = rightRow.insertCell(0);
    rightDesc.appendChild(document.createTextNode("Right screen background:"));
    var rightInput = document.createElement('input');
    rightInput.id = "rightInput";
    rightInput.style.width = "95%";
    rightInput.value = preferences.rightUrl;
    rightInput.onchange = function(){
        checkAndLoadImage("right", rightInput.value);
    }
    rightRow.insertCell(1).appendChild(rightInput);

    const opDiv = document.createElement("div")
    opDiv.textContent = "Transparency Settings";
    opDiv.style.fontWeight = "bold";
    opDiv.style.textAlign = "left";
    opDiv.style.marginTop = "5px";
    opDiv.style.marginLeft = "5px";

    var opTable = document.createElement('table');
    opTable.style.textAlign = "left";
    opTable.style.borderSpacing = "1em 0";
    opTable.style.paddingTop = "5px"

    var statOpRow = opTable.insertRow();
    statOpRow.style.height = "24px";
    var statDesc = statOpRow.insertCell(0);
    statDesc.appendChild(document.createTextNode("Hunter Stats:"));
    // set width once and the rest should follow
    statDesc.style.width = "20%"
    var statSlider = document.createElement('input');
    statSlider.id = "statSlider";
    statSlider.type = "range"
    statSlider.style.width = "95%";
    statSlider.style.verticalAlign = "middle";
    // this is where I should use some fancy function to handle the conversion for each slider instead of just copy/pasting it twice
    // but it's 3AM and I'm in physical pain
    statSlider.value = preferences.statOpacity*100;
    statSlider.onchange = function(){
        preferences.statOpacity = statSlider.value/100.0;
        updateOpacity()
    }
    statOpRow.insertCell(1).appendChild(statSlider);

    var hudOpRow = opTable.insertRow();
    hudOpRow.style.height = "24px";
    var hudDesc = hudOpRow.insertCell(0);
    hudDesc.appendChild(document.createTextNode("Location HUD:"));
    // set width once and the rest should follow
    hudDesc.style.width = "20%"
    var hudSlider = document.createElement('input');
    hudSlider.id = "hudSlider";
    hudSlider.type = "range"
    hudSlider.style.width = "95%";
    hudSlider.style.verticalAlign = "middle";
    hudSlider.value = preferences.hudOpacity*100;
    hudSlider.onchange = function(){
        preferences.hudOpacity = hudSlider.value/100.0;
        updateOpacity()
    }
    hudOpRow.insertCell(1).appendChild(hudSlider);

    const miscDiv = document.createElement("div")
    miscDiv.textContent = "Misc Settings";
    miscDiv.style.fontWeight = "bold";
    miscDiv.style.textAlign = "Left";
    miscDiv.style.marginTop = "5px";
    miscDiv.style.marginLeft = "5px";

    var shadowLabel = document.createElement("label");
    shadowLabel.textContent = "Toggle shadow for hunter stats";
    shadowLabel.style.textAlign = "left";
    shadowLabel.style.marginLeft = "10px";
    var shadowCheckbox = document.createElement('input');
    shadowCheckbox.id = "shadowCheckbox";
    shadowCheckbox.style.height = "24px";
    shadowCheckbox.style.verticalAlign = "middle";
    shadowCheckbox.type = "checkbox"
    shadowCheckbox.checked = preferences.statShadow;
    shadowCheckbox.onchange = function(){
        preferences.statShadow = shadowCheckbox.checked;
        updateShadow();
    }
    shadowLabel.appendChild(shadowCheckbox);

    buttonDiv.appendChild(closeButton);
    div.appendChild(titleDiv);
    div.appendChild(buttonDiv)
    div.appendChild(urlDiv);
    div.appendChild(urlTable);
    div.appendChild(opDiv);
    div.appendChild(opTable);
    div.appendChild(miscDiv);
    div.appendChild(shadowLabel);
    document.body.appendChild(div);
    // why does this exist
    dragElement(div);
    resolve();
})}

// === Tsitu's drag magic functions ===
// no seriously this should be a library or something
function dragElement(elmnt) {
  var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
  if (document.getElementById(elmnt.id + "header")) {
    // if present, the header is where you move the DIV from:
    document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
  } else {
    // otherwise, move the DIV from anywhere inside the DIV:
    elmnt.onmousedown = dragMouseDown;
  }

  function dragMouseDown(e) {
    e = e || window.event;
    e.preventDefault();
    // get the mouse cursor position at startup:
    pos3 = e.clientX;
    pos4 = e.clientY;
    document.onmouseup = closeDragElement;
    // call a function whenever the cursor moves:
    document.onmousemove = elementDrag;
  }

  function elementDrag(e) {
    e = e || window.event;
    e.preventDefault();
    // calculate the new cursor position:
    pos1 = pos3 - e.clientX;
    pos2 = pos4 - e.clientY;
    pos3 = e.clientX;
    pos4 = e.clientY;
    // set the element's new position:
    elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
    elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
  }

  function closeDragElement() {
    // stop moving when mouse button is released:
    document.onmouseup = null;
    document.onmousemove = null;
  }
}

// === Main logic ===

async function checkAndLoadImage(portion, url) {
    var imgUrl;
    if (url){
        // check if url is a valid image
        let imgPromise = new Promise(function(resolve) {
            try{
                var img = new Image();
                img.onload = function(){
                    resolve(this.width != 0 && this.height != 0)
                };
                img.src = url;
            } catch (error) {
                console.error(error.stack);
                resolve(false);
            }
        });
        var validImage = await imgPromise;
        imgUrl = validImage ? url : "";
    } else {
        imgUrl = "";
    }
    switch(portion) {
        case "hud":
            preferences.hudUrl = imgUrl;
            break;
        case "back":
            preferences.backUrl = imgUrl;
            break;
        case "left":
            preferences.leftUrl = imgUrl;
            break;
        case "right":
            preferences.rightUrl = imgUrl;
            break;
        default:
            console.log("checkAndLoadImage(): invalid portion");
    }
    savePreferences();
    updateImg(portion);
}

// Update HUD background
function updateImg(portion) {
    var target;
    var bgString;
    var url;
    // set the variables
    // YEAH HARDCODING
    switch(portion) {
        case "hud":
            target = document.getElementsByClassName("mousehuntHud-marbleDrawer");
            bgString = `url(https://www.mousehuntgame.com/images/ui/hud/mousehuntHudPedestal.gif?asset_cache_version=2) -37px 0 no-repeat,
        url(https://www.mousehuntgame.com/images/ui/hud/mousehuntHudPedestal.gif?asset_cache_version=2) 723px 0 no-repeat,
        url(${preferences.hudUrl}) bottom center / 100%`;
            url = preferences.hudUrl;
            break;
        case "back":
            target = document.getElementById("mousehuntContainer");
            bgString = `url(${preferences.backUrl}) repeat-y center / 100%`;
            // special handling for journal back - it should only be applied on the camp page.
            if (window.location.href.includes("camp.php")) {
                url = preferences.backUrl;
            } else {
                url = "";
            }
            break;
        case "left":
            target = document.getElementsByClassName("pageFrameView-column left");
            bgString = `url(${preferences.leftUrl})`;
            url = preferences.leftUrl;
            break;
        case "right":
            target = document.getElementsByClassName("pageFrameView-column right");
            bgString = `url(${preferences.rightUrl})`;
            url = preferences.rightUrl;
            break;
        default:
            updateImg("hud");
            updateImg("back");
            updateImg("left");
            updateImg("right");
            return;
    }
    // actually replace stuff
    replaceBackground(target, url, bgString);
}

function replaceBackground(element, url, bgString) {
    // streamline getElementByClass/getElementById
    var replaceElem;
    if (element.length == 1) {
        replaceElem = element[0];
    } else{
        replaceElem = element;
    }
    // only update if a url is specified
    if (url){
        replaceElem.style.background = bgString;
    } else {
        // this should reset the background
        replaceElem.style.background = "";
    }
}

// update transparency
function updateOpacity() {
    savePreferences();
    const statsElem = document.getElementsByClassName("headsUpDisplayView-stats")[0];
    const hudElem = document.getElementsByClassName("hudLocationContent")[0];

    statsElem.style.opacity = preferences.statOpacity;
    hudElem.style.opacity = preferences.hudOpacity;
}

// update stat shading
function updateShadow() {
    savePreferences();
    const statsElem = document.getElementsByClassName("headsUpDisplayView-stats")[0];
    if (preferences.statShadow) {
        // set background to black with 0.3 opacity
        statsElem.style.backgroundColor = "rgba(0, 0, 0, 0.30)";
    } else {
        statsElem.style.backgroundColor = "transparent";
    }
}

function updateAll() {
    updateImg();
    updateOpacity();
    updateShadow();
}
// start the script
init();