Greasy Fork

Greasy Fork is available in English.

MouseHunt Custom Themes

Change your hunter's journal to use custom themes (only works locally)

当前为 2020-09-04 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         MouseHunt Custom Themes
// @author       LethalVision
// @namespace    http://greasyfork.icu/en/users/683695-lethalvision
// @version      1.0
// @description  Change your hunter's journal to use custom themes (only works locally)
// @include	http://mousehuntgame.com/*
// @include	https://mousehuntgame.com/*
// @include	http://www.mousehuntgame.com/*
// @include	https://www.mousehuntgame.com/*
// ==/UserScript==

const TAG = "CUST_THEME"
var topUrl = "";
var midUrl = "";
var botUrl = "";
// true = tile mid image, false = stretch
const tileMid = true;

const defaultThemes = {
    "None":{description:"None", links:[]},
    "VR":{description:"Valour Rift by wayew",
         links:["https://cdn.discordapp.com/attachments/487964004162207745/751107541764800672/non_UU_theme.png",
               "https://cdn.discordapp.com/attachments/487964004162207745/748804207171207238/middle_non_UU.png",
               "https://cdn.discordapp.com/attachments/487964004162207745/748804197306073149/bottom_non_UU.png"]},
    "VR_A":{description:"Valour Rift (animated) by wayew & Wellker",
         links:["https://cdn.discordapp.com/attachments/487964004162207745/748810922642112583/lightning_non_UU_gif_cut.gif",
               "https://cdn.discordapp.com/attachments/487964004162207745/748804207171207238/middle_non_UU.png",
               "https://cdn.discordapp.com/attachments/487964004162207745/748804197306073149/bottom_non_UU.png"]},
    "UU":{description:"Ultimate Umbra by wayew",
          links:["https://cdn.discordapp.com/attachments/487964004162207745/748528376750407750/top.png",
                 "https://cdn.discordapp.com/attachments/487964004162207745/748569290789355560/middle.png",
                 "https://cdn.discordapp.com/attachments/487964004162207745/748569283591798864/bottom.png"]},
    "UU_A":{description:"Ultimate Umbra (animated) by wayew & Wellker",
            links:["https://cdn.discordapp.com/attachments/487964004162207745/748572650237853736/UU_theme_top_gif.gif",
                   "https://cdn.discordapp.com/attachments/487964004162207745/748569290789355560/middle.png",
                   "https://cdn.discordapp.com/attachments/487964004162207745/748569283591798864/bottom.png"]},
    "CT_A":{description:"Crystal Theme (animated) by Wellker",
            links:["https://cdn.discordapp.com/attachments/487964004162207745/749338680295948428/Crystal_Theme_Top.gif",
                   "https://cdn.discordapp.com/attachments/487964004162207745/749332686694252564/crystal_theme_mid.png",
                   "https://cdn.discordapp.com/attachments/487964004162207745/749332702188142693/Crystal_theme_bot.png"]},
    "Custom":{description:"Custom", links:[]}
};

const imgSizes = {
    top:{width:0, height:0, loaded:false},
    mid:{width:0, height:0, loaded:false},
    bot:{width:0, height:0, loaded:false}
};

var preferences = {
    selection: "None",
    topUrl: "",
    midUrl: "",
    botUrl: ""
};

function init() {
    var loadedPref = window.localStorage.getItem(TAG);
    if (loadedPref){
        try{
            loadedPref = JSON.parse(loadedPref);
            console.log('Loaded preference: ' + loadedPref.selection);
            preferences.selection = loadedPref.selection;
            preferences.topUrl = loadedPref.topUrl;
            preferences.midUrl = loadedPref.midUrl;
            preferences.botUrl = loadedPref.botUrl;
        } catch (err) {
            console.log('Preference parse error: ' + err);
        }
    }
    addListener();
    loadUrls(preferences.selection);
}

function loadUrls(selection) {
    if (selection == "Custom"){
        topUrl = preferences.topUrl;
        midUrl = preferences.midUrl;
        botUrl = preferences.botUrl;
        loadImageSize("top", topUrl);
        loadImageSize("mid", midUrl);
        loadImageSize("bot", botUrl);
    } else if (defaultThemes.hasOwnProperty(selection) && defaultThemes[selection].links.length == 3){
        topUrl = defaultThemes[selection].links[0];
        midUrl = defaultThemes[selection].links[1];
        botUrl = defaultThemes[selection].links[2];
        loadImageSize("top", topUrl);
        loadImageSize("mid", midUrl);
        loadImageSize("bot", botUrl);
    } else {
        topUrl = "";
        midUrl = "";
        botUrl = "";
        // no need to load theme
    }
}

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") {
                updateTheme();
            } else if (this.responseURL === "https://www.mousehuntgame.com/managers/ajax/users/quest_theme.php") {
                updateSelector();
                // add interface on first load
                addInterface();
            }
        });
        originalOpen.apply(this, arguments);
    };
}

function loadImageSize(portion, url){
    if (url == null || url.length == 0){
        return;
    }
    var img = new Image();
    img.onload = function(){
        setSize(portion, this.width, this.height);
    };
    img.src = url;
}

function setSize(portion, width, height){
    console.log(`${portion}: ${width}, ${height}`);
    switch(portion){
        case "top":
            imgSizes.top.width = width;
            imgSizes.top.height = height;
            imgSizes.top.loaded = true;
            break;
        case "mid":
            imgSizes.mid.width = width;
            imgSizes.mid.height = height;
            imgSizes.mid.loaded = true;
            break;
        case "bot":
            imgSizes.bot.width = width;
            imgSizes.bot.height = height;
            imgSizes.bot.loaded = true;
            break;
        default:
            console.log(`setSize unrecognized portion: ${portion}`);
            return;
    }
    if (imgSizes.top.loaded && imgSizes.mid.loaded && imgSizes.bot.loaded) {
        // all images loaded successfully, apply to theme
        updateTheme();
    }
}

function updateSelector(){
    var setThemeLink = document.getElementsByClassName('campPage-tabs-journal-theme')[0];
    var oldOnClick = setThemeLink.onclick;
    setThemeLink.onclick = function() {
        console.log('onClick');
        oldOnClick();
        addInterface();
        return false;
    };
}

function addInterface(){
    const mainDiv = document.createElement('div');

    // setup title
    var titleDiv = document.createElement('div');
    titleDiv.innerHTML = "<b>Custom Themes</b>";
    titleDiv.style.height = "24px";
    titleDiv.style.fontSize = "large";

    var descDiv = document.createElement('div');
    descDiv.innerHTML = "Apply custom themes to your Hunter's Journal. Note that these changes are local - only you can see this!";
    descDiv.style.height = "24px";

    mainDiv.appendChild(titleDiv);
    mainDiv.appendChild(descDiv);

    // setup selector
    var themeDiv = document.createElement('div');
    themeDiv.style.height = "24px";
    var themeSelect = document.createElement('select');
    themeSelect.id = "selectTheme";
    themeSelect.style.width = "50%"
    // iterate through defaultThemes to add options to select
    for (var key in defaultThemes) {
        if (defaultThemes.hasOwnProperty(key)) {
            themeSelect.options[themeSelect.options.length] = new Option(defaultThemes[key].description, key);
        }
    }
    // set current option to selected theme
    themeSelect.value = preferences.selection;
    themeSelect.onchange = function() {
        var customDiv = document.getElementById('customDiv')
        if (document.getElementById('selectTheme').value == "Custom") {
            customDiv.style.display = "block";
        } else {
            customDiv.style.display = "none";
        }
    }
    themeDiv.appendChild(themeSelect);
    mainDiv.appendChild(themeDiv);

    // setup input UI for Custom themes
    var customDiv = document.createElement('div');
    customDiv.id = "customDiv";
    customDiv.style.marginTop = "10px";
    customDiv.style.marginBottom = "10px";

    var detailDiv = document.createElement('div');
    detailDiv.style.height = "24px";
    detailDiv.innerHTML = "Set images for your custom theme here: images must be provided as URLs, <i>local images will not work.</i>";
    customDiv.appendChild(detailDiv);

    var warningDiv = document.createElement('div');
    warningDiv.style.height = "24px";
    warningDiv.innerHTML = "<b>Please check that the URLs link to images before loading them!</b>".fontcolor("red");
    customDiv.appendChild(warningDiv);

    var customTable = document.createElement('table');
    customTable.style.width = "75%";
    customDiv.appendChild(customTable);

    var topRow = customTable.insertRow();
    topRow.style.height = "24px";
    var topDesc = topRow.insertCell(0);
    topDesc.appendChild(document.createTextNode("Top image Url"));
    // set width once and the rest should follow
    topDesc.style.width = "25%"
    var topUrlInput = document.createElement('input');
    topUrlInput.id = "topInput";
    topUrlInput.style.width = "100%";
    topUrlInput.value = preferences.topUrl;
    topRow.insertCell(1).appendChild(topUrlInput);

    var midRow = customTable.insertRow();
    midRow.style.height = "24px";
    midRow.insertCell(0).appendChild(document.createTextNode("Middle image Url"));
    var midUrlInput = document.createElement('input');
    midUrlInput.id = "midInput";
    midUrlInput.style.width = "100%";
    midUrlInput.value = preferences.midUrl;
    midRow.insertCell(1).appendChild(midUrlInput);

    var botRow = customTable.insertRow();
    botRow.style.height = "24px";
    botRow.insertCell(0).appendChild(document.createTextNode("Bottom image URL"));
    var botUrlInput = document.createElement('input');
    botUrlInput.id = "botInput";
    botUrlInput.style.width = "100%";
    botUrlInput.value = preferences.botUrl;
    botRow.insertCell(1).appendChild(botUrlInput);

    mainDiv.appendChild(customDiv);

    // setup buttons
    var buttonDiv = document.createElement("div");
    buttonDiv.style.marginTop = "5px";

    var loadButton = document.createElement("button");
    loadButton.textContent = "Load Theme";
    loadButton.onclick = savePreferences;
    buttonDiv.appendChild(loadButton);

    var clearButton = document.createElement("button");
    clearButton.textContent = "Clear Preferences";
    clearButton.style.marginLeft = "5px";
    clearButton.onclick = clearPreferences;
    buttonDiv.appendChild(clearButton);

    mainDiv.appendChild(buttonDiv);

    // add the whole UI to theme dialog
    var parent = document.getElementsByClassName('viewQuestThemeSelector-container')[0];
    parent.appendChild(mainDiv);

    // trigger onchange on themeselect to set the display attribute correctly on first load
    themeSelect.onchange();
}

function savePreferences() {
    var selectorElem = document.getElementById('selectTheme');
    var selectValue = selectorElem.value;
    // store preference
    preferences.selection = selectValue;
    if (selectValue == "Custom") {
        preferences.topUrl = document.getElementById('topInput').value;
        preferences.midUrl = document.getElementById('midInput').value;
        preferences.botUrl = document.getElementById('botInput').value;
    }
    var jsonString = JSON.stringify(preferences);
    window.localStorage.setItem(TAG, jsonString);
    window.location.reload(false);
}

function clearPreferences() {
    localStorage.removeItem(TAG);
    window.location.reload(false);
}

function updateJournal(journalElem, url, imgSize) {
    // calculate proper height
    var elemWidth = journalElem.clientWidth;
    var elemHeight = journalElem.clientHeight;

    var newHeight = parseInt(imgSize.height * ((elemWidth*1.0)/ imgSize.width));

    journalElem.style.height = `${newHeight}px`;
    journalElem.style.backgroundImage = `url('${url}')`;
    // use automatic height
    journalElem.style.backgroundSize = "100% auto";
}

function updateTheme() {
    if (imgSizes.top.width == 0 || imgSizes.top.height == 0 ||
        imgSizes.mid.width == 0 || imgSizes.mid.height == 0 ||
        imgSizes.bot.width == 0 || imgSizes.bot.height == 0){
        // skip update if image load failed for any of the images
        return;
    }
    var journalLinks = document.getElementsByClassName("campPage-tabs-journal-link-container");
    if (journalLinks.length == 0 && !window.location.href.includes("journal.php")) {
        // proceed if "Set Journal Theme" is found or on "journal.php", skip update otherwise
        // i.e. don't update theme on other people's profiles
        return;
    }

    var themeTop = document.getElementById('journalContainer').children[0];
    var themeMid = document.getElementById('journalContainer').children[1];
    var themeBot = document.getElementById('journalContainer').children[2];

    updateJournal(themeTop, topUrl, imgSizes.top);
    updateJournal(themeBot, botUrl, imgSizes.bot);
    // manually update mid as it needs to be handled differently
    themeMid.style.backgroundImage = `url('${midUrl}')`;
    if (tileMid){
        themeMid.style.backgroundSize = "100% auto"
    } else {
        themeMid.style.backgroundSize = "100% 100%";
    }
}

// init script on load
window.onload = init